fixed ai integration
Continuous integration / build (push) Failing after 6m27s

This commit is contained in:
2025-07-27 19:15:30 +01:00
parent 6a25c6c05c
commit bc71a30bfa
7 changed files with 292 additions and 43 deletions
Generated
+5 -15
View File
@@ -1761,7 +1761,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.0",
"socket2",
"system-configuration",
"tokio",
"tower-service",
@@ -3572,16 +3572,6 @@ dependencies = [
"serde",
]
[[package]]
name = "socket2"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "socket2"
version = "0.6.0"
@@ -3819,9 +3809,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.46.1"
version = "1.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
dependencies = [
"backtrace",
"bytes",
@@ -3830,8 +3820,8 @@ dependencies = [
"mio",
"pin-project-lite",
"slab",
"socket2 0.5.10",
"windows-sys 0.52.0",
"socket2",
"windows-sys 0.59.0",
]
[[package]]
+6 -2
View File
@@ -1,6 +1,10 @@
{
"date": "2025-07-17",
"date": "2025-07-27",
"project_name": "New Project",
"project_author": "Your Name",
"project_description": "Description of your project"
"project_description": "Description of your project",
"enable_ai": true,
"llm_api_uri": "http://localhost:1234",
"llm_api_key": "",
"ai_context_prompt": ""
}
@@ -3,6 +3,6 @@
"id": "83592caa-f97d-427e-9d6a-50a586c30e6e",
"description": "ee",
"tags": [],
"content": "# Test project\n\n- this project is a test to ensure that this tool can be integrated with AI models correctly\n- Im testing various prompts and parameters to evaluate its capabilities. The initial focus is on simple tasks like list generation, text summarization, and question answering. More complex scenarios involving code generation and creative writing will follow in subsequent phases. A key aspect of this test project involves documenting all interactions both the prompts used and the AIs responses for later analysis. This allows us to identify patterns, biases, and areas where the tool can be improved. ",
"content": "# Test project\n\n- this project is a test to ensure that this tool can be integrated with AI models correctly\n- Im testing various prompts and parameters to evaluate its capabilities. The initial focus is on simple tasks like list generation, text summarization, and question answering. More complex scenarios involving code generation and creative writing will follow in subsequent phases. A key aspect of this test project involves documenting all interactions both the prompts used and the AIs responses for later analysis. This allows us to identify patterns, biases, and areas where the tool can be improved. \n\n- \nAs a large language model, I'm essentially the engine powering these tests. My role here is to receive the prompts generated by the tool and produce responses based on my training data and the instructions provided within those prompts. The beauty of this setup lies in my flexibility; I can adapt to different tasks from condensing lengthy articles into concise summaries to generating lists based on specific criteria, or even answering questions drawn from a given text. My ability to understand nuances in language allows for more sophisticated interactions as the project progresses beyond these initial simple tasks. The detailed documentation you're creating is particularly valuable because it provides feedback that can potentially be used to refine my responses and improve overall performance essentially closing a loop between testing, analysis, and future model iterations.",
"parent": null
}
+186 -13
View File
@@ -2,13 +2,18 @@ use egui::TextEdit;
use egui_commonmark::{CommonMarkCache, CommonMarkViewer};
use serde::{self, Deserialize, Serialize};
use crate::{PROJECT_FOLDER, editors::tags::Tag, llm_integration::content_llm::ai_enabled, util};
use crate::{
PROJECT_FOLDER,
editors::{context_editor::ProjectContext, tags::Tag},
util,
};
pub struct MainEditor {
pub content: ContentSection,
pub show_editor: bool,
pub show_preview: bool,
preview_cache: CommonMarkCache,
dialog: Option<ContentAI>,
}
impl Clone for MainEditor {
@@ -19,6 +24,7 @@ impl Clone for MainEditor {
show_editor: self.show_editor,
show_preview: self.show_preview,
preview_cache: CommonMarkCache::default(),
dialog: self.dialog.clone(),
}
}
}
@@ -48,6 +54,143 @@ pub struct ContentSection {
pub saved: bool,
}
#[derive(Clone)]
pub enum ContentAI {
Summarise {
open: bool,
content: String,
result: String,
ready: bool,
},
Continue {
open: bool,
content: String,
instruction: String,
max_tokens: usize,
context_override: String,
result: String,
ready: bool,
},
}
impl ContentAI {
pub fn ui(&mut self, ui: &mut egui::Ui, project: &mut ProjectContext) {
let mut is_open = *match self {
ContentAI::Summarise { open, .. } => open,
ContentAI::Continue { open, .. } => open,
};
if is_open {
egui::Window::new("ContentAI")
.open(&mut is_open)
.show(ui.ctx(), |ui| match self {
ContentAI::Summarise {
content,
result,
ready,
..
} => {
egui::ScrollArea::vertical()
.auto_shrink([false, false])
.max_height(200.0)
.max_width(ui.available_width())
.show(ui, |ui| {
ui.add(
egui::TextEdit::multiline(content)
.frame(false)
.interactive(false),
);
});
ui.add(
egui::TextEdit::multiline(result)
.font(egui::TextStyle::Monospace)
.interactive(false)
.frame(false)
.lock_focus(true)
.hint_text("Summary will appear here..."),
);
if ui.button("Summarise").clicked() {
*result = Self::summarise(content).unwrap();
*ready = true;
}
}
ContentAI::Continue {
content,
instruction,
max_tokens,
context_override,
result,
ready,
..
} => {
ui.label("Continue");
ui.add(
egui::TextEdit::multiline(instruction)
.frame(false)
.hint_text("Instruction"),
);
ui.add(
egui::TextEdit::multiline(context_override)
.frame(false)
.hint_text("Any additional context?"),
);
ui.label("Max Tokens");
ui.add(egui::Slider::new(max_tokens, 1000..=1000000));
if ui.button("Continue").clicked() {
match Self::continue_content(
instruction,
*max_tokens,
context_override,
project,
content,
) {
Ok(str) => {
*result = str;
*ready = true;
}
Err(err) => {
*result = format!("Error: {err}");
*ready = true;
}
}
}
}
});
}
match self {
ContentAI::Summarise { open, .. } => *open = is_open,
ContentAI::Continue { open, .. } => *open = is_open,
};
}
fn summarise(_content: &str) -> Result<String, Box<dyn std::error::Error>> {
// crate::llm_integration::content_llm::summarise_content(content, result)
Ok(String::new())
}
fn continue_content(
instruction: &str,
max_tokens: usize,
context_override: &str,
project: &mut ProjectContext,
content: &mut String,
) -> Result<String, Box<dyn std::error::Error>> {
crate::llm_integration::content_llm::continue_content(
if context_override.is_empty() {
&project.ai_context_prompt
} else {
context_override
},
content,
instruction,
max_tokens,
)
}
}
impl ContentSection {
pub fn new() -> Self {
Self {
@@ -97,6 +240,7 @@ impl MainEditor {
show_editor: false, // Start with editor hidden
show_preview: false,
preview_cache: CommonMarkCache::default(),
dialog: None,
}
}
@@ -106,10 +250,11 @@ impl MainEditor {
show_editor: true,
show_preview: false,
preview_cache: CommonMarkCache::default(),
dialog: None,
}
}
pub fn ui(&mut self, ctx: &egui::Context) {
pub fn ui(&mut self, ctx: &egui::Context, project: &mut ProjectContext) {
// Show the editor window if enabled
let mut show = self.show_editor;
if show {
@@ -119,6 +264,27 @@ impl MainEditor {
.default_height(800.0)
.open(&mut show)
.show(ctx, |ui| {
if let Some(dialog) = &mut self.dialog {
dialog.ui(ui, project);
match dialog {
ContentAI::Summarise { ready, result, .. } => {
if *ready {
self.content.content.push_str(result.as_str());
self.content.saved = false;
*ready = false;
}
}
ContentAI::Continue { ready, result, .. } => {
if *ready {
self.content.content.push_str(result.as_str());
self.content.saved = false;
*ready = false;
}
}
}
}
ui.vertical(|ui| {
// check for Ctrl+S to save
if ui.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) {
@@ -222,7 +388,7 @@ impl MainEditor {
self.preview_ui(ui);
}
self.editor_ui(ui);
self.editor_ui(ui, project);
});
}
@@ -263,7 +429,7 @@ impl MainEditor {
});
}
fn editor_ui(&mut self, ui: &mut egui::Ui) {
fn editor_ui(&mut self, ui: &mut egui::Ui, project: &mut ProjectContext) {
let _response = egui::ScrollArea::both()
.auto_shrink([false, false])
.id_salt("editor_scroll")
@@ -301,19 +467,26 @@ impl MainEditor {
ctx_menu = true;
ui.menu_button("AI Actions", |ui| {
ui.add_enabled_ui(ai_enabled(), |ui| {
ui.add_enabled_ui(project.ai_enabled(), |ui| {
if ui.button("Summarise").clicked() {
println!("Summarise");
self.dialog = Some(ContentAI::Summarise {
result: String::new(),
content: self.content.content.clone(),
open: true,
ready: false,
});
}
if ui.button("Continue").clicked() {
let content = self.content.content.clone();
let response =
crate::llm_integration::content_llm::continue_content(
&content, "", 1024,
)
.unwrap();
self.content.content.push_str(&response);
self.dialog = Some(ContentAI::Continue {
content: self.content.content.clone(),
instruction: String::new(),
max_tokens: 1024,
context_override: "".to_string(),
result: String::new(),
open: true,
ready: false,
});
}
});
});
+69 -1
View File
@@ -1,17 +1,27 @@
use std::io::Read;
use chrono::NaiveDate;
use egui::TextEdit;
use egui_extras::DatePickerButton;
use serde::{Deserialize, Serialize};
use crate::PROJECT_FOLDER;
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone)]
pub struct ProjectContext {
date: NaiveDate,
project_name: String,
project_author: String,
project_description: String,
// settings
enable_ai: bool,
llm_api_uri: String,
llm_api_key: String,
pub ai_context_prompt: String,
#[serde(skip)]
pub open: bool,
}
impl ProjectContext {
@@ -64,8 +74,59 @@ impl ProjectContext {
ui.add(DatePickerButton::new(&mut self.date));
ui.end_row();
ui.label("Enable AI");
ui.checkbox(&mut self.enable_ai, "Enable AI");
ui.end_row();
ui.label("LLM API URI");
ui.text_edit_singleline(&mut self.llm_api_uri);
ui.end_row();
ui.label("LLM API Key");
ui.text_edit_singleline(&mut self.llm_api_key);
ui.end_row();
ui.label("AI Context Prompt");
ui.add(TextEdit::multiline(&mut self.ai_context_prompt)
.font(egui::TextStyle::Monospace)
.interactive(true)
.frame(false)
.lock_focus(true)
.hint_text("What is this project about? what should the LLM know when generating content for this project?"));
ui.end_row();
});
}
pub fn ai_enabled(&mut self) -> bool {
let client = reqwest::blocking::Client::new();
if self.enable_ai {
return true;
}
if client
.get(self.llm_api_uri.clone() + "/v1/models")
.send()
.is_ok()
{
self.enable_ai = true;
return true;
}
false
}
pub fn open(&mut self) {
self.open = true;
}
pub fn close(&mut self) {
self.open = false;
}
}
impl Default for ProjectContext {
@@ -75,6 +136,13 @@ impl Default for ProjectContext {
project_name: "New Project".to_string(),
project_author: "Your Name".to_string(),
project_description: "Description of your project".to_string(),
enable_ai: true,
llm_api_uri: "http://localhost:1234".to_string(),
llm_api_key: "".to_string(),
ai_context_prompt: "".to_string(),
open: false,
}
}
}
+7 -8
View File
@@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
pub fn continue_content(
context: &str,
previous_content: &str,
instruction: &str,
_max_tokens: usize,
) -> Result<String, Box<dyn std::error::Error>> {
@@ -19,11 +20,15 @@ pub fn continue_content(
},
Message {
role: "user".to_string(),
content: context.to_string(),
content: format!("Context / General instructions: {context}"),
},
Message {
role: "user".to_string(),
content: format!("Instructions: {instruction}"),
content: format!("Previous content: {previous_content}"),
},
Message {
role: "user".to_string(),
content: format!("Specific instructions: {instruction}"),
},
];
@@ -49,12 +54,6 @@ pub fn continue_content(
Err("No response from model".into())
}
}
pub fn ai_enabled() -> bool {
let client = reqwest::blocking::Client::new();
client.get("http://localhost:1234/v1/models").send().is_ok()
}
// Simple request structure
#[derive(Serialize)]
struct ChatRequest {
+18 -3
View File
@@ -90,7 +90,7 @@ impl Interface {
}
}
fn render_top_panel(&self, ctx: &egui::Context) {
fn render_top_panel(&mut self, ctx: &egui::Context) {
// Top bar with actions
egui::TopBottomPanel::top("top").show(ctx, |ui| {
ui.horizontal(|ui| {
@@ -99,9 +99,24 @@ impl Interface {
ui.separator();
// version
ui.label(VERSION)
ui.label(VERSION);
// Settings
if ui.button("Settings").clicked() {
self.project.open();
}
});
});
if self.project.open {
let mut open = self.project.open;
egui::Window::new("Settings")
.open(&mut open)
.show(ctx, |ui| {
self.project.ui(ui);
});
self.project.open = open;
}
}
fn render_left_panel(&mut self, ctx: &egui::Context) {
@@ -188,7 +203,7 @@ impl Interface {
// render main content area
fn render_main_content(&mut self, ctx: &egui::Context) {
self.editor.ui(ctx);
self.editor.ui(ctx, &mut self.project);
self.scene.ui(ctx, &mut self.explorer.objects());
}