update
This commit is contained in:
@@ -30,3 +30,4 @@ CLAUDE_CLI = "claude"
|
||||
MODEL_GUIDE = "claude-opus-4-8"
|
||||
MODEL_BAUSTEIN_GEN = "claude-sonnet-4-6"
|
||||
MODEL_BAUSTEIN_REWORK = "claude-sonnet-4-6"
|
||||
MODEL_CHAT = "claude-sonnet-4-6"
|
||||
|
||||
@@ -16,6 +16,7 @@ from config import (
|
||||
MODEL_GUIDE,
|
||||
MODEL_BAUSTEIN_GEN,
|
||||
MODEL_BAUSTEIN_REWORK,
|
||||
MODEL_CHAT,
|
||||
STORAGE_DIR,
|
||||
)
|
||||
from database import (
|
||||
@@ -556,6 +557,48 @@ def _build_topic_suggest_prompt(problem: str, existing_topics: list[str]) -> str
|
||||
return template.replace("{problem}", problem).replace("{existing}", existing)
|
||||
|
||||
|
||||
def _build_guide_chat_prompt(topic: str, format_name: str, section: str, outline: str, messages: list[dict]) -> str:
|
||||
transcript = "\n".join(
|
||||
f"{'Nutzer' if m.get('role') == 'user' else 'Assistent'}: {m.get('content', '')}"
|
||||
for m in messages
|
||||
)
|
||||
outline_block = outline.strip() or "(keine)"
|
||||
section_block = section.strip() or "(kein Abschnitt erkannt)"
|
||||
return f"""Du bist ein hilfreicher Tutor zum Lern-Guide "{topic}" (Format: {format_name}). Ein Leser stellt dir Fragen, während er den Guide liest.
|
||||
|
||||
GLIEDERUNG DES GUIDES:
|
||||
{outline_block}
|
||||
|
||||
AKTUELLER ABSCHNITT, DEN DER LESER GERADE LIEST:
|
||||
{section_block}
|
||||
|
||||
BISHERIGER CHAT-VERLAUF:
|
||||
{transcript}
|
||||
|
||||
Antworte als Assistent auf die letzte Nutzer-Nachricht.
|
||||
|
||||
WICHTIG – Antwortstil:
|
||||
- KURZ und EINFACH: 1–3 Sätze, klare Sprache.
|
||||
- Keine Einleitung, keine Wiederholung der Frage, kein Markdown-Drumherum.
|
||||
- Beantworte nur die Frage; nutze den Abschnitt und die Gliederung als Kontext.
|
||||
|
||||
Gib NUR die Antwort aus, kein Präfix wie "Assistent:"."""
|
||||
|
||||
|
||||
async def chat_with_guide(topic: str, format_name: str, section: str, outline: str, messages: list[dict]) -> str:
|
||||
try:
|
||||
prompt = _build_guide_chat_prompt(topic, format_name, section, outline, messages)
|
||||
returncode, stdout, stderr = await _run_claude(
|
||||
"chat-" + str(uuid.uuid4()), prompt, 120, tools=None, model=MODEL_CHAT
|
||||
)
|
||||
if returncode != 0:
|
||||
return "Entschuldigung, das hat nicht geklappt. Bitte versuche es erneut."
|
||||
reply = stdout.strip()
|
||||
return reply or "Entschuldigung, ich habe keine Antwort erhalten."
|
||||
except Exception:
|
||||
return "Entschuldigung, das hat nicht geklappt. Bitte versuche es erneut."
|
||||
|
||||
|
||||
async def suggest_topics(problem: str, existing_topics: list[str] | None = None) -> list[dict]:
|
||||
try:
|
||||
prompt = _build_topic_suggest_prompt(problem, existing_topics or [])
|
||||
|
||||
@@ -75,3 +75,18 @@ class TopicSuggestRequest(BaseModel):
|
||||
class TopicSuggestion(BaseModel):
|
||||
title: str
|
||||
reason: str
|
||||
|
||||
|
||||
class ChatMessage(BaseModel):
|
||||
role: Literal["user", "assistant"]
|
||||
content: str = Field(min_length=1, max_length=8000)
|
||||
|
||||
|
||||
class GuideChatRequest(BaseModel):
|
||||
section: str = Field(default="", max_length=20000)
|
||||
outline: str = Field(default="", max_length=8000)
|
||||
messages: list[ChatMessage] = Field(min_length=1)
|
||||
|
||||
|
||||
class GuideChatResponse(BaseModel):
|
||||
reply: str
|
||||
|
||||
@@ -11,11 +11,12 @@ from database import (
|
||||
create_baustein as db_create_baustein, list_bausteine, get_baustein, delete_baustein as db_delete_baustein,
|
||||
list_suggestions, get_suggestion, update_suggestion, delete_suggestion,
|
||||
)
|
||||
from generator import generate_guide, rework_guide, cancel_guide, generate_suggestions, generate_baustein_detail, rework_baustein, sort_bausteine, suggest_topics, is_suggestions_generating, is_sorting
|
||||
from generator import generate_guide, rework_guide, cancel_guide, generate_suggestions, generate_baustein_detail, rework_baustein, sort_bausteine, suggest_topics, chat_with_guide, is_suggestions_generating, is_sorting
|
||||
from models import (
|
||||
GuideCreateRequest, GuideReworkRequest, GuideResponse,
|
||||
BausteinCreateRequest, BausteinReworkRequest, BausteinSortRequest, BausteinResponse, SuggestionResponse,
|
||||
TopicSuggestRequest, TopicSuggestion,
|
||||
GuideChatRequest, GuideChatResponse,
|
||||
)
|
||||
from paths import final_paths
|
||||
|
||||
@@ -89,6 +90,18 @@ async def rework(guide_id: str, req: GuideReworkRequest):
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.post("/guides/{guide_id}/chat", response_model=GuideChatResponse)
|
||||
async def guide_chat(guide_id: str, req: GuideChatRequest):
|
||||
guide = await get_guide(guide_id)
|
||||
if guide is None:
|
||||
raise HTTPException(404, "Guide nicht gefunden")
|
||||
reply = await chat_with_guide(
|
||||
guide["topic"], guide["format"], req.section, req.outline,
|
||||
[m.model_dump() for m in req.messages],
|
||||
)
|
||||
return {"reply": reply}
|
||||
|
||||
|
||||
@router.post("/guides/{guide_id}/cancel")
|
||||
async def cancel(guide_id: str):
|
||||
cancelled = await cancel_guide(guide_id)
|
||||
|
||||
Reference in New Issue
Block a user