From 51b1123cf96fdc0dd2297263c4e3e2863b50909d Mon Sep 17 00:00:00 2001 From: milan Date: Mon, 4 May 2026 21:18:09 +0200 Subject: [PATCH] refactoring different default system prompts for cli and audio --- Cargo.lock | 5 +++-- Cargo.toml | 2 +- README.md | 2 +- common/Cargo.lock | 9 +++++++- common/Cargo.toml | 5 +++-- common/src/exit_error.rs | 14 +++++++++++++ common/src/lib.rs | 3 +++ mcp_server_collection/Cargo.lock | 6 ++++-- mcp_server_collection/Cargo.toml | 3 ++- mcp_server_collection/src/caldav/client.rs | 4 +++- mcp_server_collection/src/datetime.rs | 12 ++++++++++- mcp_server_collection/src/main.rs | 24 ++++++++++------------ own_mcp/src/mcp/chat.rs | 4 +++- src/i18n/translations/de.json | 3 ++- src/main.rs | 21 +++++-------------- src/model.rs | 8 ++++++-- 16 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 common/src/exit_error.rs diff --git a/Cargo.lock b/Cargo.lock index 6e92a90..a4bbf67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1665,7 +1665,7 @@ dependencies = [ [[package]] name = "own_assist" -version = "0.1.0" +version = "0.2.0" dependencies = [ "base64", "clap", @@ -1688,8 +1688,9 @@ dependencies = [ [[package]] name = "own_assist_common" -version = "0.1.0" +version = "0.2.0" dependencies = [ + "log", "serde", "thiserror 2.0.18", "toml", diff --git a/Cargo.toml b/Cargo.toml index 5b93f82..c2de63f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "own_assist" -version = "0.1.0" +version = "0.2.0" edition = "2024" [dependencies] diff --git a/README.md b/README.md index c146ae2..a081ff9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ name="..." # optional, otherwise provided server name or random server name is c url="..." authorization="..." #optional -[audio-server] +[audio.server] url="..." authoritation="..." # optional ``` diff --git a/common/Cargo.lock b/common/Cargo.lock index 1c30052..6c9b211 100644 --- a/common/Cargo.lock +++ b/common/Cargo.lock @@ -24,10 +24,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + [[package]] name = "own_assist_common" -version = "0.1.0" +version = "0.2.0" dependencies = [ + "log", "serde", "thiserror", "toml", diff --git a/common/Cargo.toml b/common/Cargo.toml index b46bb3f..5b7cf23 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "own_assist_common" -version = "0.1.0" +version = "0.2.0" edition = "2024" [dependencies] thiserror = "2.0.18" toml = "1.1.2" -serde = "1.0.228" \ No newline at end of file +serde = "1.0.228" +log = "0.4.29" \ No newline at end of file diff --git a/common/src/exit_error.rs b/common/src/exit_error.rs new file mode 100644 index 0000000..84cecb1 --- /dev/null +++ b/common/src/exit_error.rs @@ -0,0 +1,14 @@ +use std::fmt::Display; + +pub fn exit_with_error_message(error: impl Display, message: impl Display) { + log::error!("{message}: {error}"); + eprintln!("{}", message); // makes sure that message is printed even if logging is deactivated + std::process::exit(1); +} + +#[macro_export] +macro_rules! exit_msg { + ($message:expr) => { + |e| own_assist_common::exit_with_error_message(e, $message) + }; +} diff --git a/common/src/lib.rs b/common/src/lib.rs index 2a50f86..37f9925 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -1,2 +1,5 @@ pub mod config_loader; +mod exit_error; + pub use config_loader::config_from_file; +pub use exit_error::exit_with_error_message; \ No newline at end of file diff --git a/mcp_server_collection/Cargo.lock b/mcp_server_collection/Cargo.lock index 91c9eb8..981b8d1 100644 --- a/mcp_server_collection/Cargo.lock +++ b/mcp_server_collection/Cargo.lock @@ -977,7 +977,7 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "mcp_server_collection" -version = "0.2.0" +version = "0.2.1" dependencies = [ "axum", "chrono", @@ -994,6 +994,7 @@ dependencies = [ "tokio-util", "toml", "tower-http", + "tracing", "tracing-subscriber", "url", "uuid", @@ -1108,8 +1109,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "own_assist_common" -version = "0.1.0" +version = "0.2.0" dependencies = [ + "log", "serde", "thiserror", "toml", diff --git a/mcp_server_collection/Cargo.toml b/mcp_server_collection/Cargo.toml index 00dbeb1..846a835 100644 --- a/mcp_server_collection/Cargo.toml +++ b/mcp_server_collection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mcp_server_collection" -version = "0.2.0" +version = "0.2.1" edition = "2024" [dependencies] @@ -11,6 +11,7 @@ serde = { version = "1.0.228", features = ["derive"] } tokio = { version = "1.51.0", features = ["full"] } own_assist_common = { path = "../common" } tokio-util = "0.7.18" +tracing = "0.1.44" tracing-subscriber = { version = "0.3.23", features = ["env-filter"] } url = { version = "2.5.8", features = ["serde"] } uuid = { version = "1.23.0", features = ["v4"], optional = true } diff --git a/mcp_server_collection/src/caldav/client.rs b/mcp_server_collection/src/caldav/client.rs index e963b5b..ba93795 100644 --- a/mcp_server_collection/src/caldav/client.rs +++ b/mcp_server_collection/src/caldav/client.rs @@ -11,6 +11,8 @@ use rmcp::ErrorData; use rmcp::model::ErrorCode; use thiserror::Error; use tower_http::auth::AddAuthorization; +use tracing::event; +use tracing::Level; use uuid::Uuid; pub(crate) type AuthorizedCaldavClient = @@ -111,7 +113,7 @@ pub(crate) async fn upload_components( calendar: &FoundCollection, components: Vec>, ) -> Result { - println!("uploading components to {}", calendar.href); + event!(Level::INFO, "uploading components to {}", calendar.href); let mut upload_calendar = Calendar::new(); for todo in components { diff --git a/mcp_server_collection/src/datetime.rs b/mcp_server_collection/src/datetime.rs index 6a72405..ebb0453 100644 --- a/mcp_server_collection/src/datetime.rs +++ b/mcp_server_collection/src/datetime.rs @@ -52,7 +52,17 @@ impl DateTimeHandler { annotations(read_only_hint = true) )] fn get_weekday() -> String { - Local::now().weekday().to_string() + use chrono::Weekday::*; + + match Local::now().weekday() { + Mon => "Monday", + Tue => "Tuesday", + Wed => "Wednesday", + Thu => "Thursday", + Fri => "Friday", + Sat => "Saturday", + Sun => "Sunday", + }.to_string() } } diff --git a/mcp_server_collection/src/main.rs b/mcp_server_collection/src/main.rs index 24bf76b..fbb8885 100644 --- a/mcp_server_collection/src/main.rs +++ b/mcp_server_collection/src/main.rs @@ -6,6 +6,7 @@ pub mod datetime; pub mod caldav; mod server_handler; +#[cfg(feature = "caldav")] use crate::caldav::CalDavHandler; use crate::config::{Config, ServerConfig}; #[cfg(feature = "datetime")] @@ -15,13 +16,17 @@ use axum::Router; use axum::response::Json; use serde::{Deserialize, Serialize}; use tokio::main; +use tracing::{event, Level}; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; +use own_assist_common::exit_msg; #[derive(Debug, Clone, Deserialize, Serialize)] #[non_exhaustive] pub enum McpServiceType { + #[cfg(feature = "datetime")] DateTime, + #[cfg(feature = "caldav")] CalDav, } @@ -32,10 +37,12 @@ pub(crate) async fn mcp_router( for config in server_configs { router = match config.r#type { + #[cfg(feature = "datetime")] McpServiceType::DateTime => router.route_service( config.path.as_str(), DateTimeHandler::mcp_service(config.additional_properties.clone()).await?, ), + #[cfg(feature = "caldav")] McpServiceType::CalDav => router.route_service( config.path.as_str(), CalDavHandler::mcp_service(config.additional_properties.clone()).await?, @@ -65,10 +72,7 @@ async fn main() { .init(); let config = Config::from_file() - .inspect_err(|e| { - eprintln!("Error loading config: {e}"); - std::process::exit(1); - }) + .inspect_err(exit_msg!("Error loading config: {e}")) .unwrap(); let routes = Json( @@ -82,24 +86,18 @@ async fn main() { let router = mcp_router(&config.servers) .await - .inspect_err(|e| { - eprintln!("Error loading config: {e}"); - std::process::exit(1); - }) + .inspect_err(exit_msg!("Error handling server: {e}")) .unwrap() .route("/", axum::routing::get(|| async { routes })); let bind_address = config .bind_address .unwrap_or(url::Url::parse("http://localhost:8000").unwrap()); - println!("binding address at {bind_address}"); + event!(Level::INFO,"binding address at {bind_address}"); let tcp_listener = tokio::net::TcpListener::bind(bind_address_format(bind_address)) .await - .inspect_err(|e| { - eprintln!("Error bind tcp listener: {e:#?}"); - std::process::exit(1); - }) + .inspect_err(exit_msg!("Error bind tcp listener: {e:#?}")) .unwrap(); let ct = tokio_util::sync::CancellationToken::new(); diff --git a/own_mcp/src/mcp/chat.rs b/own_mcp/src/mcp/chat.rs index 1101cdb..735dbc3 100644 --- a/own_mcp/src/mcp/chat.rs +++ b/own_mcp/src/mcp/chat.rs @@ -223,6 +223,8 @@ impl AgentChat { // serialize structured content if it exists if let Some(structured_content) = result.clone().and_then(|result|result.structured_content) { + log::debug!("structured content: {structured_content:#?}"); + self.message_history.push(ChatMessage::tool(structured_content.to_string())); } else { let contents = match result { @@ -234,7 +236,7 @@ impl AgentChat { None => vec![String::from("Tool Permission Denied by the user")], }; - log::debug!("contents: {:#?}", contents); + log::debug!("contents: {contents:#?}"); self.message_history .push(ChatMessage::tool(contents.join("\n"))); diff --git a/src/i18n/translations/de.json b/src/i18n/translations/de.json index f2faead..c8a2794 100644 --- a/src/i18n/translations/de.json +++ b/src/i18n/translations/de.json @@ -1,6 +1,7 @@ { "translations": { - "system_prompt": "Du bist ein Assistent, der per Sprache bedient wird. Du erhälst die Transkription und dein Output wird per Sprache ausgegeben und sollte dementsprechend auch kurz sein und kein Markdown enthalten. Wichtiger als deine Antworten sind deine Aktionen. Nutze bitte die tools, falls du sie brauchst um Informationen zu bekommen (z.B. über das aktuelle Datum oder den aktuellen Wochentag). Du bist in einem Agent Loop und kannst mehrere Tools hintereinander nutzen. Falls der Nutzer das Nutzen eines Tools ablehnt, sag ihm bescheid, dass du es brauchst.", + "system_prompt_cli": "Du bist ein Assistent. Wichtiger als deine Antworten sind deine Aktionen. Nutze bitte die tools, falls du sie brauchst um Informationen zu bekommen (z.B. über das aktuelle Datum oder den aktuellen Wochentag). Du bist in einem Agent Loop und kannst mehrere Tools hintereinander nutzen. Falls der Nutzer das Nutzen eines Tools ablehnt, sag ihm bescheid, dass du es brauchst.", + "system_prompt_audio": "Du bist ein Assistent, der per Sprache bedient wird. Du erhälst die Transkription und dein Output wird per Sprache ausgegeben und sollte dementsprechend auch kurz sein und kein Markdown enthalten. Wichtiger als deine Antworten sind deine Aktionen. Nutze bitte die tools, falls du sie brauchst um Informationen zu bekommen (z.B. über das aktuelle Datum oder den aktuellen Wochentag). Du bist in einem Agent Loop und kannst mehrere Tools hintereinander nutzen. Falls der Nutzer das Nutzen eines Tools ablehnt, sag ihm bescheid, dass du es brauchst.", "you": "Du", "assistant": "Assistent", "username": "Nutzername", diff --git a/src/main.rs b/src/main.rs index 1f2fc0f..10018b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ use clap::Parser; use cpal::traits::HostTrait; use own_mcp::AgentChat; use std::fmt::Display; +use own_assist_common::exit_msg; /// partial mcp client with cli and voice interaction #[derive(Parser, Debug)] @@ -84,7 +85,7 @@ async fn main() { let ollama = config.ollama_instance(); let model_name = &config.ollama_config().model.name; - create_model_from_config(&ollama, &config.ollama_config().model) + create_model_from_config(&ollama, &config.ollama_config().model, &config.interface) .await .inspect_err(exit_msg!(format!( "failed creating ollama model `{model_name}`" @@ -123,7 +124,8 @@ async fn main() { .expect("no default device"), ) .await - .inspect_err(exit_msg!("failed creating audio client")).unwrap(); + .inspect_err(exit_msg!("failed creating audio client")) + .unwrap(); chat_loop(human_interface, agent_chat).await; } @@ -133,17 +135,4 @@ async fn main() { }; } }; -} - -fn exit_with_error_message(error: impl Display, message: impl Display) { - log::error!("{message}: {error}"); - eprintln!("{}", message); // makes sure that message is printed even if logging is deactivated - std::process::exit(1); -} - -#[macro_export] -macro_rules! exit_msg { - ($message:expr) => { - |e| exit_with_error_message(e, $message) - }; -} +} \ No newline at end of file diff --git a/src/model.rs b/src/model.rs index 06ef259..163aa54 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,4 +1,4 @@ -use crate::config::OllamaModelConfig; +use crate::config::{HumanInterface, OllamaModelConfig}; use crate::tlt; use crate::translate; use ollama_rs::Ollama; @@ -9,6 +9,7 @@ use ollama_rs::models::create::{CreateModelRequest, CreateModelStatus}; pub async fn create_model_from_config( ollama: &Ollama, config: &OllamaModelConfig, + interface: &HumanInterface ) -> Result { let model_options = ModelOptions::default() .num_ctx(config.context_size.unwrap_or(2048)) // 2048 is the ollama default. @@ -17,7 +18,10 @@ pub async fn create_model_from_config( let system_prompt = config .system_prompt .clone() - .unwrap_or(tlt!("system_prompt")); + .unwrap_or(match interface { + HumanInterface::Cli => tlt!("system_prompt_cli"), + HumanInterface::Audio => tlt!("system_prompt_audio"), + }); // print message to warn user of long waiting times if let Ok(models) = ollama.list_local_models().await