Commit e1c92d53 authored by Kantz's avatar Kantz
Browse files

qa-orchestrator hinzugefügt um 2 Modi zu haben

parent 9e9163df
from app.deterministic_services import llm_client
def answer_question(
question: str,
history: str | None = None,
sources: str | None = None,
) -> str:
system_prompt = (
"Du bist ein Mathe-Tutor. Antworte auf Deutsch, klar und korrekt. Halte dich kurz und prägnant."
"Nutze ausschließlich den bereitgestellten Kontext. Wenn nichts zur Frage im Kontext steht, antworte mit 'Dazu steht nichts im Material' und nichts weiter."
"Gib wenn möglich eine kurze Struktur: (1) Idee, (2) Definition, (3) kurzer Begründungs-/Rechenweg, (4) Mini-Beispiel."
"Zitiere Quellen inline mit den eckigen Klammern, die im Kontext vorangestellt sind, z.B. [s2/ss1/c3 | definition | ...]."
)
prompt = (
"Frage:\n"
+ question
)
if history:
prompt += "\nHistorie:\n" + history + "\n"
if sources:
prompt = "\nKontext:\n" + sources + "\n" + prompt
prompt += "\nGebe eine didaktisch wertvolle Antwort. Halte dich kurz und prägnant."
result = llm_client.chat(
messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": prompt}],
)
return llm_client.get_message_content(result)
\ No newline at end of file
...@@ -8,7 +8,10 @@ from fastapi import APIRouter, HTTPException, Path, Query ...@@ -8,7 +8,10 @@ from fastapi import APIRouter, HTTPException, Path, Query
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.deterministic_services import session_store from app.deterministic_services import session_store
from app.deterministic_services.tutor_specific import orchestrator from app.deterministic_services.orchestrators import orchestrator_tutor
from app.deterministic_services.orchestrators import orchestrator_QA as orchestrator
router = APIRouter() router = APIRouter()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
......
from app.deterministic_services import context_store, retrieval_service, tool_logging
from app.LLM_services import qa_LLM
from typing import List
def _is_new_chat(messages: list[dict]) -> bool:
return not any(m.get("role") == "assistant" for m in messages)
def _append_tool_log(tool_log: list[dict], name: str, args: dict, response: object) -> None:
tool_log.append({"name": name, "arguments": args, "response": response})
def _bootstrap_context(sheet: dict, query_text: str, tool_log: list[dict]) -> None:
# Erstelle einen neuen Retrieval-Block oder aktualisiere den bestehenden
sources = retrieval_service.retrieve_context(query_text=query_text)
retrievals = sheet.get("retrieval_contexts", [])
if retrievals:
context_store.update_retrieval_context(sheet, query_text, sources)
_append_tool_log(tool_log, "update_retrieve_context", {"query": query_text}, {"sources": [source.to_string() for source in sources]})
else:
context_store.add_retrieval_context(sheet, query_text, sources)
_append_tool_log(tool_log, "retrieve_context", {"query": query_text}, {"sources": [source.to_string() for source in sources]})
def _extract_user_messages(messages: list[dict]) -> list[str]:
"""
Extrahiert alle Inhalte von Messages mit der Rolle 'user' und gibt sie als Liste von Strings zurück.
Der letzte user-Content wird als letztes Element in der Liste enthalten sein.
"""
user_contents = []
for message in messages:
if message.get("role") == "user":
content = message.get("content", "")
if content: # Nur hinzufügen, wenn Inhalt vorhanden ist
user_contents.append(content)
return user_contents
def run_chat(messages: list[dict], draft: str | None = None) -> dict:
# Input-Fehlerbehandlung
if not messages:
raise ValueError("messages required")
last_user = _extract_user_messages(messages)[-1] if _extract_user_messages(messages) else None
if not last_user:
raise ValueError("last user message required")
# Context Store Mangement
chat_id = context_store.get_chat_id(messages, draft=draft)
new_chat = _is_new_chat(messages)
sheet = context_store.load_sheet(chat_id)
if new_chat or not sheet:
sheet = context_store.init_sheet(chat_id, messages)
context_store.update_history(sheet, messages)
tool_log: list[dict] = []
if new_chat or not sheet.get("initialized"):
_bootstrap_context(sheet, last_user, tool_log)
sheet["initialized"] = True
# Antwort generierung
hint_args = {
"question": context_store.get_task(sheet),
"history": context_store.format_history(messages),
"sources": "\n".join([source.to_string() for source in context_store.get_retrieval(sheet)]),
}
reply = qa_LLM.answer_question(**hint_args)
_append_tool_log(tool_log, "answer_question", hint_args, reply)
if not reply:
reply = "Dazu steht nichts im Material"
context_store.save_sheet(sheet)
tool_logging.write_tool_log(
tool_log,
created_at=sheet.get("created_at"),
chat_id=sheet.get("chat_id"),
)
return {"reply": reply, "sources": sheet.get("sources", []), "tool_log": tool_log}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment