diff --git a/own_mcp/Cargo.lock b/own_mcp/Cargo.lock index bb233e0..5d091db 100644 --- a/own_mcp/Cargo.lock +++ b/own_mcp/Cargo.lock @@ -11,6 +11,28 @@ dependencies = [ "memchr", ] +[[package]] +name = "alsa" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d" +dependencies = [ + "alsa-sys", + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad7569085a265dd3f607ebecce7458eaab2132a84393534c95b18dcbc3f31e04" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -164,6 +186,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -282,6 +313,50 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "coreaudio-rs" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16dd574a72a021b90c7656c474ea31d11a2f0366a8eff574186e761e0b9e3586" +dependencies = [ + "bitflags", + "libc", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "cpal" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8942da362c0f0d895d7cac616263f2f9424edc5687364dfd1d25ef7eba506d7" +dependencies = [ + "alsa", + "coreaudio-rs", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "objc2", + "objc2-audio-toolbox", + "objc2-avf-audio", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -344,6 +419,12 @@ dependencies = [ "syn", ] +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + [[package]] name = "digest" version = "0.10.7" @@ -354,6 +435,16 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags", + "objc2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -658,6 +749,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + [[package]] name = "http" version = "1.4.0" @@ -1080,6 +1177,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mach2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.8.0" @@ -1092,6 +1198,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "mio" version = "1.2.0" @@ -1120,6 +1236,35 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + [[package]] name = "nix" version = "0.31.2" @@ -1132,6 +1277,17 @@ dependencies = [ "libc", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1141,6 +1297,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "oauth2" version = "5.0.0" @@ -1160,6 +1338,95 @@ dependencies = [ "url", ] +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-audio-toolbox" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" +dependencies = [ + "bitflags", + "libc", + "objc2", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-avf-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" +dependencies = [ + "dispatch2", + "objc2", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" +dependencies = [ + "bitflags", + "objc2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", + "block2", + "dispatch2", + "libc", + "objc2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + [[package]] name = "ollama-rs" version = "0.3.4" @@ -1250,7 +1517,10 @@ dependencies = [ name = "own_mcp" version = "0.1.0" dependencies = [ + "bytes", + "cpal", "env_logger", + "hound", "log", "ollama-rs", "rand 0.10.0", @@ -1329,6 +1599,15 @@ dependencies = [ "syn", ] +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -1611,6 +1890,7 @@ dependencies = [ "js-sys", "log", "mime", + "mime_guess", "percent-encoding", "pin-project-lite", "quinn", @@ -1619,6 +1899,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", @@ -2233,6 +2514,36 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + [[package]] name = "tower" version = "0.5.3" @@ -2321,6 +2632,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + [[package]] name = "unicode-ident" version = "1.0.24" @@ -2902,6 +3219,15 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/own_mcp/src/audio/recording.rs b/own_mcp/src/audio/recording.rs index 22dc31f..a828f4a 100644 --- a/own_mcp/src/audio/recording.rs +++ b/own_mcp/src/audio/recording.rs @@ -7,7 +7,6 @@ use std::thread::JoinHandle; use std::time::Duration; use hound::WavSpec; use log::{debug, error, info, trace}; -use thiserror::__private18::AsDisplay; use thiserror::Error; fn generic_sample_to_i16(sample: impl SizedSample + Into, format: SampleFormat) -> i16 { diff --git a/own_mcp/src/mcp/chat.rs b/own_mcp/src/mcp/chat.rs index f68efc3..c8fe9da 100644 --- a/own_mcp/src/mcp/chat.rs +++ b/own_mcp/src/mcp/chat.rs @@ -103,9 +103,8 @@ impl AgentChat { ollama_client: Ollama, model: String, mcp_clients: HashMap, - system_prompt: String, ) -> Result { - let history = vec![ChatMessage::system(system_prompt)]; + let history = vec![]; let mut servers = HashMap::new(); @@ -192,7 +191,13 @@ impl AgentChat { { let all_tools: Vec = self .get_all_tools() - .map(|restricted_tool| restricted_tool.tool_info.clone()) + .filter_map(|restricted_tool|{ + if restricted_tool.permission == ToolPermission::Denied { // filters denied tools to save tokens + None + } else { + Some(restricted_tool.tool_info.clone()) + } + }) .collect(); log::debug!("all tools: {all_tools:#?}"); @@ -347,7 +352,7 @@ mod tests { ).await.unwrap(), )]); - let mut chat = AgentChat::new(ollama, "lfm2.5-thinking:1.2b".to_string(), mcp_clients, String::new()).await.unwrap(); + let mut chat = AgentChat::new(ollama, "lfm2.5-thinking:1.2b".to_string(), mcp_clients).await.unwrap(); let tools: Vec = chat.get_all_tools().cloned().collect(); assert_eq!(tools.len(), 1); diff --git a/src/config.rs b/src/config.rs index a0d7c44..7f03c69 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,12 +13,12 @@ use own_assist_common::config_from_file; #[derive(Debug, Deserialize)] pub struct Config { + permissions: Option>, ollama: OllamaConfig, #[serde(rename = "audio-server")] - audio_server: AudioServerConfig, + audio_server: Option, #[serde(rename = "mcp-servers")] mcp_servers: Vec, - permissions: Option>, } #[derive(Debug, Deserialize)] @@ -40,7 +40,7 @@ impl Config { let mut ollama_headers = HeaderMap::new(); if let Some(authorization_header) = &self.ollama.authorization { - ollama_headers.append("Authorization", HeaderValue::from_str(&authorization_header).unwrap()); + ollama_headers.append("Authorization", HeaderValue::from_str(authorization_header).unwrap()); } let ollama_default_url = Url::parse("http://127.0.0.1:11434").unwrap(); @@ -50,16 +50,19 @@ impl Config { ollama } - pub fn audio_client(&self) -> AudioClient { - let mut audio_client = AudioClient::new(self.audio_server.url.clone()); - if let Some(authorization) = &self.audio_server.authorization { - audio_client = audio_client.with_authorization(authorization.clone()); + pub fn audio_client(&self) -> Option { + if let Some(audio_server) = &self.audio_server { + let mut audio_client = AudioClient::new(audio_server.url.clone()); + if let Some(authorization) = &audio_server.authorization { + audio_client = audio_client.with_authorization(authorization.clone()); + } + Some(audio_client) + } else { + None } - - audio_client } - pub async fn mcp_clients(&self) -> HashMap { + pub async fn mcp_clients(&self) -> Result, rmcp::service::ClientInitializeError> { let mut mcp_clients: HashMap = HashMap::new(); for mcp_server in &self.mcp_servers { @@ -67,7 +70,7 @@ impl Config { mcp_server.url.as_str(), mcp_server.authorization.clone(), Implementation::new("own_assist", env!("CARGO_PKG_VERSION")), - ).await.unwrap(); + ).await?; let server_name = guaranteed_mcp_server_name(mcp_server.name.clone(), &client); let server_data = client; @@ -75,14 +78,14 @@ impl Config { mcp_clients.insert(server_name.clone(), server_data); } - mcp_clients + Ok(mcp_clients) } pub async fn set_tool_permissions(&self, agent_chat: &mut AgentChat) -> Result<(), ChatError> { - if let Some(permissions) = &self.permissions && permissions.len() > 0 { + if let Some(permissions) = &self.permissions && !permissions.is_empty() { for permission_config in permissions { log::info!("set permission for `{}` to {:?}", permission_config.tool_name, permission_config.permission); - agent_chat.set_permission(permission_config.tool_name.clone(), permission_config.permission.clone())?; + agent_chat.set_permission(permission_config.tool_name.clone(), permission_config.permission)?; } } else { @@ -104,6 +107,7 @@ pub struct OllamaConfig { pub struct OllamaModelConfig { pub from_model: String, pub name: String, + pub system_prompt: Option, pub context_size: Option, pub temperature: Option, } diff --git a/src/i18n/mod.rs b/src/i18n/mod.rs new file mode 100644 index 0000000..e3a3dd4 --- /dev/null +++ b/src/i18n/mod.rs @@ -0,0 +1,87 @@ +use rmcp::serde_json; +use serde::Deserialize; +use std::collections::HashMap; +use std::sync::{LazyLock, OnceLock, RwLock}; + +#[derive(Debug, Deserialize)] +struct Language { + translations: HashMap, +} + +static LANGUAGES: OnceLock> = OnceLock::new(); +static LOCALE_SELECTION: LazyLock> = LazyLock::new(|| RwLock::new(Locale::DE)); + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Locale { + DE, +} + +#[macro_export] +macro_rules! include_language { + ($file:expr) => { + serde_json::from_str::(include_str!($file)).unwrap() + }; +} + +fn load_languages() -> &'static HashMap { + LANGUAGES + .get_or_init(|| HashMap::from([(Locale::DE, include_language!("translations/de.json"))])) +} + +/// +/// # Examples +/// +/// ``` +/// let formatted = format_dynamically("{...} is cool!".to_string(), +/// vec!["Rust".to_string()]); +/// assert_eq!(formatted, "Rust is cool!"); +/// ``` +fn format_dynamically(mut template: String, arguments: Vec>) -> String { + let replaced_str = "{...}"; + + for arg in arguments { + template = template.replacen(replaced_str, arg.into().as_str(), 1); + } + + template +} + +pub fn translate(template_name: String, arguments: Vec>) -> String { + let locale: Locale = LOCALE_SELECTION.read().unwrap().clone(); + let languages = load_languages(); + let translation = languages + .get(&locale) + .unwrap() + .translations + .get(&template_name) + .unwrap(); + format_dynamically(translation.clone(), arguments) +} + +#[macro_export] +macro_rules! tlt { + ($template_name:tt) => { + translate($template_name.to_string(), Vec::::new()) + }; + ($template_name:tt, $($args:tt)*) => { + translate($template_name.to_string(), vec![$($args)*]) + }; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dynamic_formatting() { + let formatted = format_dynamically("{...} is cool!".to_string(), vec!["Rust".to_string()]); + assert_eq!(formatted, "Rust is cool!"); + + let formatted = format_dynamically("{...}, {...} and {...} are three consecutive numbers.".to_string(), vec![ + "1".to_string(), + "2".to_string(), + "3".to_string(), + ]); + assert_eq!(formatted, "1, 2 and 3 are three consecutive numbers."); + } +} diff --git a/src/i18n/translations/de.json b/src/i18n/translations/de.json new file mode 100644 index 0000000..6d3e0f8 --- /dev/null +++ b/src/i18n/translations/de.json @@ -0,0 +1,5 @@ +{ + "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." + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 305ae7b..7d5df37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ mod config; mod model; mod human_interface; +mod i18n; + +use crate::i18n::translate; use own_mcp::audio::{AudioClientTrait}; -use own_mcp::mcp::chat::{PermissionAnswer, ToolPermission}; use crate::config::Config; use crate::model::create_model_from_config; use crate::human_interface::HumanInterface; @@ -25,20 +27,18 @@ 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).await.inspect_err(|e|{ log::error!("failed creating ollama model {model_name}: {e}"); std::process::exit(1); }).unwrap(); - let 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.".to_string(); - let mcp_clients = config.mcp_clients().await; + let mcp_clients = config.mcp_clients().await.inspect_err(|e|{ + log::error!("failed creating MCP clients: {e}"); + std::process::exit(1); + }).unwrap(); - let mut agent_chat = own_mcp::AgentChat::new(ollama, model_name.clone(), mcp_clients, system_prompt).await.inspect_err( + let mut agent_chat = own_mcp::AgentChat::new(ollama, model_name.clone(), mcp_clients).await.inspect_err( |e| { log::error!("error creating agent: {}", e); std::process::exit(1); diff --git a/src/model.rs b/src/model.rs index ddfc8ed..f0420d4 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,22 +1,27 @@ +use crate::translate; use crate::config::OllamaModelConfig; use ollama_rs::Ollama; use ollama_rs::error::OllamaError; use ollama_rs::models::ModelOptions; use ollama_rs::models::create::{CreateModelRequest, CreateModelStatus}; +use crate::tlt; pub async fn create_model_from_config( ollama: &Ollama, config: &OllamaModelConfig, ) -> Result { let model_options = ModelOptions::default() - .num_ctx(config.context_size.unwrap_or(2048))// 2048 is the ollama default. + .num_ctx(config.context_size.unwrap_or(2048)) // 2048 is the ollama default. .temperature(config.temperature.unwrap_or(0.8)); // 0.8 is the ollama default + let system_prompt = config.system_prompt.clone().unwrap_or(tlt!("system_prompt")); + ollama .create_model( CreateModelRequest::new(config.name.clone()) .from_model(config.from_model.clone()) - .parameters(model_options), + .parameters(model_options) + .system(system_prompt), ) .await }