Commit caed64cc authored by Kantz's avatar Kantz
Browse files

altlasten entfernt

parent dae35034
from __future__ import annotations
from typing import List
import os
import httpx
from openai import OpenAI
from app.services.embeddings import OpenAILikeEmbeddings
from app.services import vector_store
SYSTEM_PROMPT = """Du bist ein Mathe-Tutor. Antworte auf Deutsch, klar und korrekt.
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 | ...].
"""
CONTEXT_LIMITS = {
"direct": 4,
"indirect": 6,
"subsection": 2,
"section": 1,
}
def _get_embedder() -> OpenAILikeEmbeddings:
base_url = os.getenv("OPENAI_BASE_URL")
api_key = os.getenv("OPENAI_API_KEY")
model = os.getenv("OPENAI_EMBED_MODEL", "text-embedding-3-large")
if not base_url or not api_key:
raise ValueError("Missing OPENAI_BASE_URL or OPENAI_API_KEY")
return OpenAILikeEmbeddings(base_url=base_url, api_key=api_key, model=model, target_dim=1024)
def _format_ref(doc: vector_store.Retrieved) -> str:
meta = doc.metadata
sec = meta.get("section_index")
sub = meta.get("subsection_index")
child = meta.get("child_index")
ref = []
if sec is not None:
ref.append(f"s{sec}")
if sub is not None:
ref.append(f"ss{sub}")
if child is not None:
ref.append(f"c{child}")
ref_id = "/".join(ref) if ref else "unknown"
doc_type = meta.get("type") or doc.doc_type
title = (
meta.get("title")
or meta.get("subsection_title")
or meta.get("section_title")
or meta.get("path")
or "Untitled"
)
return f"[{ref_id} | {doc_type} | {title}]"
def build_context(result: dict) -> str:
blocks: List[str] = []
def add_group(label: str, items: List[vector_store.Retrieved], limit: int) -> None:
if not items:
return
for doc in items[:limit]:
blocks.append(f"{label} {_format_ref(doc)}\n{doc.markdown}")
add_group("DIRECT", result.get("children_direct", []), CONTEXT_LIMITS["direct"])
add_group("INDIRECT", result.get("children_expanded", []), CONTEXT_LIMITS["indirect"])
add_group("SUBSECTION", result.get("subsections", []), CONTEXT_LIMITS["subsection"])
add_group("SECTION", result.get("sections", []), CONTEXT_LIMITS["section"])
if not blocks:
return "KONTEXT: (leer)"
return "KONTEXT:\n" + "\n\n".join(blocks)
def build_messages(messages: list[dict], context: str) -> list[dict]:
return [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "system", "content": context},
] + messages
def retrieve_context(pg_url: str, query_text: str) -> str:
embedder = _get_embedder()
retrieval = vector_store.retrieve(
pg_url=pg_url,
embedder=embedder,
query=query_text,
k=8,
expand_links=True,
)
return build_context(retrieval)
def call_chat_api(messages_payload: list[dict]) -> str:
base_url = os.getenv("OPENAI_BASE_URL")
api_key = os.getenv("OPENAI_API_KEY")
model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
if not base_url or not api_key:
raise ValueError("Missing OPENAI_BASE_URL or OPENAI_API_KEY")
url = f"{base_url.rstrip('/')}/chat/completions"
payload = {
"model": model,
"messages": messages_payload,
}
headers = {"Authorization": f"Bearer {api_key}"}
with httpx.Client(timeout=60.0) as client:
response = client.post(url, headers=headers, json=payload)
response.raise_for_status()
data = response.json()
return data["choices"][0]["message"]["content"]
def stream_chat(messages_payload: list[dict]):
base_url = os.getenv("OPENAI_BASE_URL")
api_key = os.getenv("OPENAI_API_KEY")
model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
if not base_url or not api_key:
raise ValueError("Missing OPENAI_BASE_URL or OPENAI_API_KEY")
client = OpenAI(api_key=api_key, base_url=base_url)
return client.chat.completions.create(
model=model,
messages=messages_payload,
stream=True,
)
from app.services import context_store, decision_tool, math_intent, retrieval_service, tool_logging from app.services import context_store, math_intent, retrieval_service, tool_logging
from app.tools import hint_tool, math_tool from app.tools import hint_tool, math_tool, decision_tool
def _append_tool_log(tool_log: list[dict], name: str, args: dict, response: object) -> None: def _append_tool_log(tool_log: list[dict], name: str, args: dict, response: object) -> None:
......
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