fehlerkorrektzur Hybrid chat
This commit is contained in:
parent
03594424a1
commit
9cc16bb220
|
|
@ -1,12 +1,7 @@
|
||||||
"""
|
"""
|
||||||
app/config.py — zentrale Konfiguration (ENV → Settings)
|
app/config.py — zentrale Konfiguration
|
||||||
|
Version: 0.4.0 (WP-06 Complete)
|
||||||
Version:
|
|
||||||
0.4.0 (WP-06: Added Decision Engine Config)
|
|
||||||
Stand:
|
|
||||||
2025-12-08
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import os
|
import os
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
@ -27,8 +22,9 @@ class Settings:
|
||||||
OLLAMA_URL: str = os.getenv("MINDNET_OLLAMA_URL", "http://127.0.0.1:11434")
|
OLLAMA_URL: str = os.getenv("MINDNET_OLLAMA_URL", "http://127.0.0.1:11434")
|
||||||
LLM_MODEL: str = os.getenv("MINDNET_LLM_MODEL", "phi3:mini")
|
LLM_MODEL: str = os.getenv("MINDNET_LLM_MODEL", "phi3:mini")
|
||||||
PROMPTS_PATH: str = os.getenv("MINDNET_PROMPTS_PATH", "config/prompts.yaml")
|
PROMPTS_PATH: str = os.getenv("MINDNET_PROMPTS_PATH", "config/prompts.yaml")
|
||||||
|
|
||||||
# WP-06 Decision Engine
|
# NEU für WP-06
|
||||||
|
LLM_TIMEOUT: float = float(os.getenv("MINDNET_LLM_TIMEOUT", "120.0"))
|
||||||
DECISION_CONFIG_PATH: str = os.getenv("MINDNET_DECISION_CONFIG", "config/decision_engine.yaml")
|
DECISION_CONFIG_PATH: str = os.getenv("MINDNET_DECISION_CONFIG", "config/decision_engine.yaml")
|
||||||
|
|
||||||
# API
|
# API
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
"""
|
"""
|
||||||
app/services/llm_service.py — LLM Client (Ollama)
|
app/services/llm_service.py — LLM Client (Ollama)
|
||||||
|
Version: 0.2.0 (WP-06 Hybrid Router Support)
|
||||||
Version:
|
|
||||||
0.2.0 (WP-06 Hybrid Router Support)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
@ -26,12 +24,9 @@ class LLMService:
|
||||||
)
|
)
|
||||||
|
|
||||||
def _load_prompts(self) -> dict:
|
def _load_prompts(self) -> dict:
|
||||||
"""Lädt Prompts aus der konfigurierten YAML-Datei."""
|
|
||||||
path = Path(self.settings.PROMPTS_PATH)
|
path = Path(self.settings.PROMPTS_PATH)
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
logger.warning(f"Prompt config not found at {path}, using defaults.")
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(path, "r", encoding="utf-8") as f:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
return yaml.safe_load(f)
|
return yaml.safe_load(f)
|
||||||
|
|
@ -41,16 +36,16 @@ class LLMService:
|
||||||
|
|
||||||
async def generate_raw_response(self, prompt: str) -> str:
|
async def generate_raw_response(self, prompt: str) -> str:
|
||||||
"""
|
"""
|
||||||
Führt einen direkten LLM Call ohne RAG-Template aus.
|
NEU: Führt einen direkten LLM Call ohne RAG-Template aus.
|
||||||
Ideal für Classification/Routing.
|
Wird vom Router für die Antwortgenerierung genutzt.
|
||||||
"""
|
"""
|
||||||
payload = {
|
payload = {
|
||||||
"model": self.settings.LLM_MODEL,
|
"model": self.settings.LLM_MODEL,
|
||||||
"prompt": prompt,
|
"prompt": prompt,
|
||||||
"stream": False,
|
"stream": False,
|
||||||
"options": {
|
"options": {
|
||||||
"temperature": 0.0, # Deterministisch für Routing!
|
"temperature": 0.0,
|
||||||
"num_ctx": 512 # Kleines Fenster reicht für Classification
|
"num_ctx": 512
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,76 +53,24 @@ class LLMService:
|
||||||
response = await self.client.post("/api/generate", json=payload)
|
response = await self.client.post("/api/generate", json=payload)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
logger.error(f"Ollama Error ({response.status_code}): {response.text}")
|
logger.error(f"Ollama Error ({response.status_code}): {response.text}")
|
||||||
return "FACT" # Fallback bei Fehler
|
return "Fehler bei der Generierung."
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
return data.get("response", "").strip()
|
return data.get("response", "").strip()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"LLM Raw Gen Error: {e}")
|
logger.error(f"LLM Raw Gen Error: {e}")
|
||||||
return "FACT"
|
return "Interner LLM Fehler."
|
||||||
|
|
||||||
async def generate_rag_response(self, query: str, context_str: str) -> str:
|
async def generate_rag_response(self, query: str, context_str: str) -> str:
|
||||||
"""
|
"""Legacy Support / Fallback"""
|
||||||
Generiert eine Antwort basierend auf Query und Kontext (RAG).
|
|
||||||
"""
|
|
||||||
# Template hier ist nur Fallback, falls im Router nichts übergeben wird.
|
|
||||||
# Im Normalfall formatiert der Router den context_str bereits vor oder übergibt das Template.
|
|
||||||
# Hier nutzen wir simple substitution, da der Prompt meist schon vom Router aufbereitet ist
|
|
||||||
# oder wir nutzen das Standard-Template aus der YAML.
|
|
||||||
|
|
||||||
# HINWEIS: In der neuen Architektur (chat.py) wird das Template bereits VOR diesem Aufruf
|
|
||||||
# geladen und formatiert, und als 'prompt' übergeben?
|
|
||||||
# Nein, chat.py ruft generate_rag_response(query, context_str) auf.
|
|
||||||
# Wir müssen sicherstellen, dass wir das *richtige* Template nutzen.
|
|
||||||
# Da generate_rag_response aktuell KEINEN 'template_key' Parameter hat,
|
|
||||||
# gehen wir davon aus, dass 'context_str' bereits Instruktionen enthält ODER
|
|
||||||
# dass chat.py den Prompt komplett baut.
|
|
||||||
|
|
||||||
# Um die API sauber zu halten: chat.py übergibt jetzt den FERTIGEN Prompt als context_str?
|
|
||||||
# Nein, chat.py baut den Prompt mit replace().
|
|
||||||
# Wir ändern diese Methode leicht ab, um flexibler zu sein:
|
|
||||||
# Wir erwarten, dass der Aufrufer (chat.py) die volle Kontrolle hat.
|
|
||||||
|
|
||||||
# Damit es 100% zusammenpasst mit dem chat.py unten:
|
|
||||||
# chat.py baut den finalen Prompt selbst zusammen!
|
|
||||||
# Wir nutzen daher generate_raw_response eigentlich auch für RAG,
|
|
||||||
# ODER wir passen generate_rag_response an, dass es "dumm" ist.
|
|
||||||
|
|
||||||
# Legacy Support für generate_rag_response:
|
|
||||||
# Wir bauen den Prompt zusammen, falls noch nicht geschehen.
|
|
||||||
# ABER: chat.py in meiner Version unten macht das Template-Handling.
|
|
||||||
# Daher ist der sauberste Weg: chat.py ruft generate_raw_response auf für die Antwort!
|
|
||||||
|
|
||||||
# FIX für Kompatibilität: Wir leiten rag_response intern auf raw um,
|
|
||||||
# bauen aber vorher den Prompt, falls context_str übergeben wird.
|
|
||||||
|
|
||||||
# Da wir chat.py kontrollieren (siehe unten), ändern wir chat.py so,
|
|
||||||
# dass es generate_raw_response nutzt! Das ist viel sauberer.
|
|
||||||
# Diese Methode bleibt für Backward Compatibility.
|
|
||||||
|
|
||||||
system_prompt = self.prompts.get("system_prompt", "")
|
system_prompt = self.prompts.get("system_prompt", "")
|
||||||
rag_template = self.prompts.get("rag_template", "{context_str}\n\n{query}")
|
rag_template = self.prompts.get("rag_template", "{context_str}\n\n{query}")
|
||||||
final_prompt = rag_template.format(context_str=context_str, query=query)
|
final_prompt = rag_template.format(context_str=context_str, query=query)
|
||||||
|
|
||||||
payload = {
|
# Wir nutzen intern nun auch raw_response, um Code zu sparen
|
||||||
"model": self.settings.LLM_MODEL,
|
full_prompt = f"{system_prompt}\n\n{final_prompt}"
|
||||||
"system": system_prompt,
|
return await self.generate_raw_response(full_prompt)
|
||||||
"prompt": final_prompt,
|
|
||||||
"stream": False,
|
|
||||||
"options": {
|
|
||||||
"temperature": 0.7,
|
|
||||||
"num_ctx": 2048
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = await self.client.post("/api/generate", json=payload)
|
|
||||||
if response.status_code != 200:
|
|
||||||
return f"Error: {response.text}"
|
|
||||||
return response.json().get("response", "")
|
|
||||||
except Exception as e:
|
|
||||||
return f"Error: {str(e)}"
|
|
||||||
|
|
||||||
async def close(self):
|
async def close(self):
|
||||||
await self.client.aclose()
|
await self.client.aclose()
|
||||||
Loading…
Reference in New Issue
Block a user