refactoring

different default system prompts for cli and audio
This commit is contained in:
2026-05-04 21:18:09 +02:00
parent 3d8975cfc1
commit 51b1123cf9
16 changed files with 80 additions and 45 deletions
Generated
+3 -2
View File
@@ -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",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "own_assist"
version = "0.1.0"
version = "0.2.0"
edition = "2024"
[dependencies]
+1 -1
View File
@@ -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
```
+8 -1
View File
@@ -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",
+2 -1
View File
@@ -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"
log = "0.4.29"
+14
View File
@@ -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)
};
}
+3
View File
@@ -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;
+4 -2
View File
@@ -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",
+2 -1
View File
@@ -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 }
+3 -1
View File
@@ -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<impl Into<CalendarComponent>>,
) -> Result<PutResourceResponse, CalendarError> {
println!("uploading components to {}", calendar.href);
event!(Level::INFO, "uploading components to {}", calendar.href);
let mut upload_calendar = Calendar::new();
for todo in components {
+11 -1
View File
@@ -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()
}
}
+11 -13
View File
@@ -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();
+3 -1
View File
@@ -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")));
+2 -1
View File
@@ -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",
+4 -15
View File
@@ -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;
}
@@ -134,16 +136,3 @@ 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)
};
}
+6 -2
View File
@@ -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<CreateModelStatus, OllamaError> {
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