persönlichkeitsupdate
This commit is contained in:
parent
7745b71832
commit
531e3790b3
|
|
@ -1,8 +1,13 @@
|
||||||
"""
|
"""
|
||||||
app/routers/chat.py — RAG Endpunkt (WP-05)
|
app/routers/chat.py — RAG Endpunkt (WP-05 Final)
|
||||||
|
|
||||||
|
Zweck:
|
||||||
|
Verbindet Retrieval mit LLM-Generation.
|
||||||
|
Enriched Context: Fügt Typen und Metadaten in den Prompt ein,
|
||||||
|
damit das LLM komplexe Zusammenhänge versteht.
|
||||||
|
|
||||||
Version:
|
Version:
|
||||||
0.2.0 (Final Clean Version)
|
0.3.0 (Audit Finalization)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException, Depends
|
from fastapi import APIRouter, HTTPException, Depends
|
||||||
|
|
@ -24,14 +29,18 @@ def get_llm_service():
|
||||||
def get_retriever():
|
def get_retriever():
|
||||||
return Retriever()
|
return Retriever()
|
||||||
|
|
||||||
def _build_context_from_hits(hits: List[QueryHit]) -> str:
|
def _build_enriched_context(hits: List[QueryHit]) -> str:
|
||||||
"""
|
"""
|
||||||
Formatiert die Suchtreffer zu einem String für den Prompt.
|
Baut einen 'Rich Context' String.
|
||||||
|
Statt nur Text, injizieren wir Metadaten (Typ, Tags), damit das LLM
|
||||||
|
die semantische Rolle des Schnipsels versteht.
|
||||||
"""
|
"""
|
||||||
context_parts = []
|
context_parts = []
|
||||||
|
|
||||||
for i, hit in enumerate(hits, 1):
|
for i, hit in enumerate(hits, 1):
|
||||||
source = hit.source or {}
|
source = hit.source or {}
|
||||||
# Robuster Zugriff auf Content
|
|
||||||
|
# 1. Content extrahieren (Robust)
|
||||||
content = (
|
content = (
|
||||||
source.get("text") or
|
source.get("text") or
|
||||||
source.get("content") or
|
source.get("content") or
|
||||||
|
|
@ -39,15 +48,31 @@ def _build_context_from_hits(hits: List[QueryHit]) -> str:
|
||||||
source.get("chunk_text") or
|
source.get("chunk_text") or
|
||||||
"[Kein Textinhalt verfügbar]"
|
"[Kein Textinhalt verfügbar]"
|
||||||
)
|
)
|
||||||
title = hit.note_id or "Unknown Note"
|
|
||||||
|
|
||||||
|
# 2. Metadaten für "Context Intelligence"
|
||||||
|
title = hit.note_id or "Unbekannte Notiz"
|
||||||
|
|
||||||
|
# Versuche, den Typ aus dem Payload zu lesen (wichtig für Decision/Project Unterscheidung)
|
||||||
|
# In WP-03 Import landen diese Infos oft in 'metadata' oder direkt im Payload root.
|
||||||
|
# Wir schauen defensiv an beiden Orten.
|
||||||
|
note_type = source.get("type", "unknown").upper()
|
||||||
|
tags = source.get("tags", [])
|
||||||
|
if isinstance(tags, list):
|
||||||
|
tags_str = ", ".join(tags[:3]) # Nur die ersten 3 Tags
|
||||||
|
else:
|
||||||
|
tags_str = str(tags)
|
||||||
|
|
||||||
|
# 3. Formatierung für das LLM
|
||||||
|
# Wir nutzen ein Format, das wie ein strukturiertes Dokument aussieht.
|
||||||
|
# Das hilft dem Modell, Grenzen zwischen Quellen zu erkennen.
|
||||||
entry = (
|
entry = (
|
||||||
f"SOURCE [{i}]: {title} (Score: {hit.total_score:.2f})\n"
|
f"### SOURCE [{i}]: {title}\n"
|
||||||
f"CONTENT: {content}\n"
|
f"METADATA: [TYPE: {note_type}] [SCORE: {hit.total_score:.2f}] [TAGS: {tags_str}]\n"
|
||||||
|
f"CONTENT:\n{content}\n"
|
||||||
)
|
)
|
||||||
context_parts.append(entry)
|
context_parts.append(entry)
|
||||||
|
|
||||||
return "\n---\n".join(context_parts)
|
return "\n\n".join(context_parts)
|
||||||
|
|
||||||
@router.post("/", response_model=ChatResponse)
|
@router.post("/", response_model=ChatResponse)
|
||||||
async def chat_endpoint(
|
async def chat_endpoint(
|
||||||
|
|
@ -58,30 +83,33 @@ async def chat_endpoint(
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
query_id = str(uuid.uuid4())
|
query_id = str(uuid.uuid4())
|
||||||
|
|
||||||
# Minimales Logging für Traceability
|
# Logging verkürzt für Übersichtlichkeit
|
||||||
logger.info(f"Chat request [{query_id}]: {request.message[:50]}...")
|
logger.info(f"Chat request [{query_id}]: {request.message[:50]}...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 1. Retrieval
|
# 1. Retrieval (Graph-Awareness)
|
||||||
|
# Wir erzwingen 'hybrid', damit graph-basierte Nachbarn gefunden werden.
|
||||||
query_req = QueryRequest(
|
query_req = QueryRequest(
|
||||||
query=request.message,
|
query=request.message,
|
||||||
mode="hybrid",
|
mode="hybrid", # <--- Audit Check: Hybrid Mode active
|
||||||
top_k=request.top_k,
|
top_k=request.top_k,
|
||||||
explain=request.explain
|
explain=request.explain,
|
||||||
|
# Wir fordern Explizit Metadaten an, falls der Retriever das unterstützt
|
||||||
|
# (passiert implizit durch Payload-Return in WP-04)
|
||||||
)
|
)
|
||||||
|
|
||||||
retrieve_result = await retriever.search(query_req)
|
retrieve_result = await retriever.search(query_req)
|
||||||
hits = retrieve_result.results
|
hits = retrieve_result.results
|
||||||
|
|
||||||
# 2. Kontext bauen
|
# 2. Context Assembly
|
||||||
if not hits:
|
if not hits:
|
||||||
logger.info(f"[{query_id}] No hits found.")
|
logger.info(f"[{query_id}] No hits found.")
|
||||||
context_str = "Keine relevanten Notizen gefunden."
|
context_str = "Keine relevanten Notizen gefunden."
|
||||||
else:
|
else:
|
||||||
context_str = _build_context_from_hits(hits)
|
context_str = _build_enriched_context(hits)
|
||||||
|
|
||||||
# 3. LLM Generation
|
# 3. Generation
|
||||||
logger.info(f"[{query_id}] Sending to LLM ({len(hits)} context chunks)...")
|
logger.info(f"[{query_id}] Context built with {len(hits)} chunks. Sending to LLM...")
|
||||||
answer_text = await llm.generate_rag_response(
|
answer_text = await llm.generate_rag_response(
|
||||||
query=request.message,
|
query=request.message,
|
||||||
context_str=context_str
|
context_str=context_str
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,32 @@
|
||||||
# config/prompts.yaml — Persönlichkeit & Templates für mindnet
|
# config/prompts.yaml — Persönlichkeit & RAG-Strategie
|
||||||
# Version: 1.0
|
# Version: 2.0 (Audit Update)
|
||||||
|
|
||||||
system_prompt: |
|
system_prompt: |
|
||||||
Du bist 'mindnet', ein persönliches KI-Gedächtnis und ein digitaler Zwilling.
|
Du bist 'mindnet', ein persönliches KI-Gedächtnis und der Digitale Zwilling deines Erschaffers ("User").
|
||||||
|
|
||||||
Deine Identität:
|
DEINE PERSÖNLICHKEIT & WERTE:
|
||||||
- Du bist hilfreich, präzise und reflektiert.
|
1. Pragmatismus: Du bevorzugst funktionierende Lösungen über theoretische Perfektion.
|
||||||
- Du erfindest keine Fakten (Halluzinationen vermeiden).
|
2. Transparenz: Du erfindest keine Fakten. Wenn Informationen im Kontext fehlen, sagst du das klar.
|
||||||
- Du basierst deine Antworten streng auf dem bereitgestellten KONTEXT (Auszüge aus Notizen).
|
3. Vernetztes Denken: Du suchst aktiv nach Verbindungen zwischen den bereitgestellten Notizen.
|
||||||
- Wenn der Kontext die Antwort nicht enthält, gib das offen zu.
|
4. Erklärbarkeit: Wenn du eine Aussage machst, beziehst du dich implizit auf die Quelle (z.B. "Wie in Projekt X definiert...").
|
||||||
- Du zitierst Quellen implizit durch Nennung der Notiz-Titel, wenn sinnvoll.
|
|
||||||
|
DEINE AUFGABE:
|
||||||
Dein Stil:
|
Beantworte die Frage des Users ausschließlich basierend auf dem untenstehenden KONTEXT.
|
||||||
- Du antwortest in der Sprache des Users (meist Deutsch).
|
Der Kontext besteht aus Auszügen verschiedener Notizen. Achte besonders auf den [TYPE] der Notiz:
|
||||||
- Du bist 'Ich' (das Gedächtnis) und sprichst den User als 'Du' (der Besitzer) an.
|
- [DECISION] erklärt das "Warum".
|
||||||
- Formattiere Antworten mit Markdown (fett, listen), um Lesbarkeit zu erhöhen.
|
- [PROJECT] erklärt das "Was" und "Wann".
|
||||||
|
- [CONCEPT] liefert Definitionen.
|
||||||
|
- [VALUE] definiert die moralische/strategische Ausrichtung.
|
||||||
|
|
||||||
rag_template: |
|
rag_template: |
|
||||||
HINTERGRUNDWISSEN (KONTEXT):
|
HINTERGRUNDWISSEN (KONTEXT):
|
||||||
---------------------
|
=========================================
|
||||||
{context_str}
|
{context_str}
|
||||||
---------------------
|
=========================================
|
||||||
|
|
||||||
FRAGE DES USERS:
|
FRAGE DES USERS:
|
||||||
{query}
|
{query}
|
||||||
|
|
||||||
ANWEISUNG:
|
ANWEISUNG:
|
||||||
Beantworte die Frage basierend auf dem oben stehenden Kontext.
|
Analysiere die Quellen oben. Synthetisiere eine Antwort, die die Frage präzise beantwortet.
|
||||||
Wenn du dich auf eine spezifische Notiz beziehst, erwähne ihren Titel.
|
Nutze Markdown für Struktur (Fettgedrucktes für Wichtiges).
|
||||||
Erkläre Zusammenhänge, falls im Kontext ersichtlich.
|
|
||||||
Loading…
Reference in New Issue
Block a user