refactor: LLM Typen und Traits nach nazarick-core verschoben, BaseAgent extrahiert
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
// nazarick-core/src/agent.rs
|
||||
//
|
||||
// BaseAgent — gemeinsame Logik für alle Agenten.
|
||||
// Sebas, Lyra und zukünftige Agenten sind nur noch dünne Wrapper darum.
|
||||
|
||||
use crate::prompt::PromptBuilder;
|
||||
use crate::types::{AgentId, Result};
|
||||
use crate::llm::{LlmProvider, LlmRequest, Message};
|
||||
|
||||
pub struct BaseAgent {
|
||||
/// Eindeutige ID dieser Agent-Instanz
|
||||
pub id: AgentId,
|
||||
/// Baut den System-Prompt aus soul_core + soul_personality
|
||||
prompt_builder: PromptBuilder,
|
||||
/// Das LLM-Backend (LmStudio, Ollama, Mistral)
|
||||
llm: Box<dyn LlmProvider>,
|
||||
/// Konversationsverlauf — damit der Agent den Kontext behält
|
||||
history: Vec<Message>,
|
||||
}
|
||||
|
||||
impl BaseAgent {
|
||||
/// Erstellt eine neue BaseAgent-Instanz.
|
||||
/// Wird von jedem Agenten in seinem new() aufgerufen.
|
||||
pub fn new(
|
||||
soul_core_path: impl Into<String>,
|
||||
soul_personality_path: impl Into<String>,
|
||||
llm: Box<dyn LlmProvider>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: AgentId::new_v4(),
|
||||
prompt_builder: PromptBuilder::new(soul_core_path, soul_personality_path),
|
||||
llm,
|
||||
history: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sendet eine Nachricht und gibt die Antwort zurück.
|
||||
/// Konversationsverlauf wird automatisch mitgeführt.
|
||||
pub async fn chat(&mut self, user_message: &str) -> Result<String> {
|
||||
let system_prompt = self.prompt_builder.build()?;
|
||||
|
||||
self.history.push(Message::user(user_message));
|
||||
|
||||
let mut messages = vec![Message::system(system_prompt)];
|
||||
messages.extend(self.history.clone());
|
||||
|
||||
let request = LlmRequest {
|
||||
messages,
|
||||
max_tokens: 4096,
|
||||
temperature: 0.7,
|
||||
};
|
||||
|
||||
let response = self.llm.complete(request).await?;
|
||||
|
||||
self.history.push(Message::assistant(&response.content));
|
||||
|
||||
Ok(response.content)
|
||||
}
|
||||
|
||||
/// Löscht den Konversationsverlauf.
|
||||
/// Nützlich wenn ein neues Gespräch beginnen soll.
|
||||
pub fn clear_history(&mut self) {
|
||||
self.history.clear();
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,6 @@ pub mod usage;
|
||||
/// Persönlichkeit basiert auf zwei Dateien:
|
||||
/// - soul_core.md → unveränderlicher Kern (Regeln, Sicherheit)
|
||||
/// - soul_personality.md → entwickelbarer Teil (Ton, Präferenzen)
|
||||
pub mod prompt;
|
||||
pub mod prompt;
|
||||
pub mod llm;
|
||||
pub mod agent;
|
||||
@@ -0,0 +1,10 @@
|
||||
// nazarick-core/src/llm/mod.rs
|
||||
//
|
||||
// LLM-Modul — Typen und Traits für alle LLM-Provider.
|
||||
// Re-exportiert alles damit Nutzer nur `nazarick_core::llm::X` schreiben müssen.
|
||||
|
||||
mod types;
|
||||
mod traits;
|
||||
|
||||
pub use types::{Message, LlmRequest, LlmResponse};
|
||||
pub use traits::LlmProvider;
|
||||
@@ -0,0 +1,19 @@
|
||||
// nazarick-core/src/llm/traits.rs
|
||||
//
|
||||
// LlmProvider Trait — gemeinsame Schnittstelle für alle LLM-Backends.
|
||||
// Neue Provider (Ollama, Mistral) implementieren diesen Trait.
|
||||
|
||||
use crate::types::Result;
|
||||
use crate::llm::types::{LlmRequest, LlmResponse};
|
||||
|
||||
/// Zentraler Trait für alle LLM-Provider.
|
||||
/// Jeder Provider (LmStudio, Ollama, Mistral) implementiert diesen Trait.
|
||||
#[async_trait::async_trait]
|
||||
pub trait LlmProvider: Send + Sync {
|
||||
/// Sendet eine Anfrage an das LLM und gibt die Antwort zurück.
|
||||
async fn complete(&self, request: LlmRequest) -> Result<LlmResponse>;
|
||||
|
||||
/// Gibt den Namen des Providers zurück.
|
||||
/// Wird für Logging und Usage-Tracking verwendet.
|
||||
fn name(&self) -> &str;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// nazarick-core/src/llm/types.rs
|
||||
//
|
||||
// Gemeinsame Datentypen für alle LLM-Provider.
|
||||
// Jeder Provider (LmStudio, Ollama, Mistral) nutzt diese Typen.
|
||||
|
||||
/// Repräsentiert eine einzelne Nachricht in einem Gespräch.
|
||||
/// Entspricht dem Message-Format das alle gängigen LLM APIs verwenden.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Message {
|
||||
/// Rolle des Absenders: "system", "user" oder "assistant"
|
||||
pub role: String,
|
||||
/// Inhalt der Nachricht
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
/// Erstellt eine System-Nachricht (z.B. den Persönlichkeits-Prompt)
|
||||
pub fn system(content: impl Into<String>) -> Self {
|
||||
Self { role: "system".to_string(), content: content.into() }
|
||||
}
|
||||
|
||||
/// Erstellt eine User-Nachricht
|
||||
pub fn user(content: impl Into<String>) -> Self {
|
||||
Self { role: "user".to_string(), content: content.into() }
|
||||
}
|
||||
|
||||
/// Erstellt eine Assistant-Nachricht (vorherige Antworten für Kontext)
|
||||
pub fn assistant(content: impl Into<String>) -> Self {
|
||||
Self { role: "assistant".to_string(), content: content.into() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Konfiguration für einen einzelnen LLM-Aufruf.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LlmRequest {
|
||||
/// Der vollständige Gesprächsverlauf inklusive System-Prompt
|
||||
pub messages: Vec<Message>,
|
||||
/// Maximale Anzahl Token in der Antwort
|
||||
pub max_tokens: u32,
|
||||
/// Kreativität der Antwort (0.0 = deterministisch, 1.0 = sehr kreativ)
|
||||
pub temperature: f32,
|
||||
}
|
||||
|
||||
/// Antwort eines LLM-Aufrufs.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LlmResponse {
|
||||
/// Der generierte Text
|
||||
pub content: String,
|
||||
/// Anzahl der Input-Token (für Usage-Tracking)
|
||||
pub tokens_input: u64,
|
||||
/// Anzahl der Output-Token (für Usage-Tracking)
|
||||
pub tokens_output: u64,
|
||||
}
|
||||
Reference in New Issue
Block a user