added Tokens, openrouter, memory system
This commit is contained in:
@@ -14,6 +14,9 @@ nazarick-core = { path = "../nazarick-core" }
|
||||
# Skills
|
||||
skills = { path = "../skills" }
|
||||
|
||||
# Memory
|
||||
memory = { path = "../memory" }
|
||||
|
||||
# LLM Provider
|
||||
api = { path = "../api" }
|
||||
|
||||
|
||||
@@ -11,8 +11,12 @@ pub enum AuthResult {
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct AgentChatConfig {
|
||||
pub agent_id: String,
|
||||
pub model: String, // referenziert [models.x]
|
||||
pub max_tokens: u32,
|
||||
pub max_loops: u32,
|
||||
pub history_window: usize, // unkomprimierte Nachrichten im Context
|
||||
pub summary_every: usize, // Rolling Summary alle N Nachrichten
|
||||
pub conversation_timeout_mins: u64,
|
||||
pub bot_token: String,
|
||||
pub incoming_webhook_url: String,
|
||||
pub allowed_user_ids: Vec<u64>,
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
// crates/nazarick/src/config.rs
|
||||
|
||||
use std::collections::HashMap;
|
||||
use serde::Deserialize;
|
||||
use crate::chat::types::AgentChatConfig;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct NazarickConfig {
|
||||
pub chat: ChatConfig,
|
||||
pub models: HashMap<String, ModelConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct ModelConfig {
|
||||
pub provider: String,
|
||||
pub url: String,
|
||||
pub model: String,
|
||||
pub api_key: Option<String>,
|
||||
pub max_summary_tokens: Option<usize>,
|
||||
/// "tool_use" | "xml" — default xml wenn nicht gesetzt
|
||||
pub skill_format: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
||||
+75
-11
@@ -1,3 +1,5 @@
|
||||
// crates/nazarick/src/main.rs
|
||||
|
||||
mod chat;
|
||||
mod config;
|
||||
|
||||
@@ -8,13 +10,49 @@ use tokio::sync::Mutex;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tracing::info;
|
||||
|
||||
use api::llm::lmstudio::LmStudioProvider;
|
||||
use nazarick_core::agent::skill_registry::SkillRegistry;
|
||||
use nazarick_core::llm::{LlmProvider, SkillFormat};
|
||||
use api::llm::openai_compat::OpenAiCompatProvider;
|
||||
use nazarick_core::memory::Memory;
|
||||
use nazarick_core::summarizer::Summarizer;
|
||||
use memory::store::MemoryStore;
|
||||
use memory::summarizer::Summarizer as MemorySummarizer;
|
||||
use sebas_tian::Sebas;
|
||||
use lyra::Lyra;
|
||||
use chat::synology::{handle_incoming, AppState};
|
||||
use config::ModelConfig;
|
||||
use skills as _;
|
||||
|
||||
fn build_provider(model_cfg: &ModelConfig) -> Box<dyn LlmProvider> {
|
||||
let skill_format = model_cfg.skill_format
|
||||
.as_deref()
|
||||
.map(SkillFormat::from_str)
|
||||
.unwrap_or(SkillFormat::Xml);
|
||||
|
||||
match model_cfg.provider.as_str() {
|
||||
"openai_compat" => Box::new(OpenAiCompatProvider::new(
|
||||
&model_cfg.url,
|
||||
&model_cfg.model,
|
||||
model_cfg.api_key.clone(),
|
||||
skill_format,
|
||||
)),
|
||||
unknown => panic!("Unbekannter Provider: '{}'", unknown),
|
||||
}
|
||||
}
|
||||
|
||||
async fn build_memory(agent_id: &str) -> anyhow::Result<Arc<dyn Memory>> {
|
||||
let store = MemoryStore::open(agent_id).await?;
|
||||
Ok(Arc::new(store))
|
||||
}
|
||||
|
||||
fn build_summarizer(model_cfg: &ModelConfig) -> Arc<dyn Summarizer> {
|
||||
Arc::new(MemorySummarizer::new(
|
||||
&model_cfg.url,
|
||||
&model_cfg.model,
|
||||
model_cfg.max_summary_tokens.unwrap_or(4000),
|
||||
))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
@@ -50,31 +88,57 @@ async fn main() -> anyhow::Result<()> {
|
||||
.find(|a| a.agent_id == "lyra")
|
||||
.ok_or_else(|| anyhow::anyhow!("lyra nicht in config"))?;
|
||||
|
||||
let sebas = Sebas::new(
|
||||
let sebas_model = cfg.models
|
||||
.get(&sebas_cfg.model)
|
||||
.ok_or_else(|| anyhow::anyhow!("Modell '{}' nicht in [models] config", sebas_cfg.model))?;
|
||||
|
||||
let lyra_model = cfg.models
|
||||
.get(&lyra_cfg.model)
|
||||
.ok_or_else(|| anyhow::anyhow!("Modell '{}' nicht in [models] config", lyra_cfg.model))?;
|
||||
|
||||
let summary_model = cfg.models
|
||||
.get("summary")
|
||||
.ok_or_else(|| anyhow::anyhow!("'summary' nicht in [models] config"))?;
|
||||
|
||||
let sebas_memory = build_memory("sebas_tian").await?;
|
||||
let lyra_memory = build_memory("lyra").await?;
|
||||
let summarizer = build_summarizer(summary_model);
|
||||
|
||||
info!("Memory geladen");
|
||||
|
||||
let mut sebas = Sebas::new(
|
||||
"sebas_tian",
|
||||
"config/shared_core.md",
|
||||
"crates/sebas-tian/config/soul_core.md",
|
||||
Box::new(LmStudioProvider::new(
|
||||
"http://localhost:1234",
|
||||
"qwen/qwen3.5-9b",
|
||||
)),
|
||||
build_provider(sebas_model),
|
||||
registry.clone(),
|
||||
sebas_memory,
|
||||
summarizer.clone(),
|
||||
sebas_cfg.max_tokens,
|
||||
sebas_cfg.max_loops,
|
||||
sebas_cfg.history_window,
|
||||
sebas_cfg.summary_every,
|
||||
sebas_cfg.conversation_timeout_mins,
|
||||
);
|
||||
sebas.init().await?;
|
||||
|
||||
let lyra = Lyra::new(
|
||||
let mut lyra = Lyra::new(
|
||||
"lyra",
|
||||
"config/shared_core.md",
|
||||
"crates/lyra/config/soul_core.md",
|
||||
Box::new(LmStudioProvider::new(
|
||||
"http://localhost:1234",
|
||||
"qwen/qwen3.5-9b",
|
||||
)),
|
||||
build_provider(lyra_model),
|
||||
registry.clone(),
|
||||
lyra_memory,
|
||||
summarizer.clone(),
|
||||
lyra_cfg.max_tokens,
|
||||
lyra_cfg.max_loops,
|
||||
lyra_cfg.history_window,
|
||||
lyra_cfg.summary_every,
|
||||
lyra_cfg.conversation_timeout_mins,
|
||||
);
|
||||
lyra.init().await?;
|
||||
|
||||
info!("Agenten initialisiert");
|
||||
|
||||
let state = Arc::new(AppState {
|
||||
agents: cfg.chat.agents,
|
||||
|
||||
Reference in New Issue
Block a user