chatbot2 / rag_pipeline.py
Nguyen5's picture
commit
ed084d7
# rag_pipeline.py – SUPABASE RAG VERSION
from typing import List, Dict, Any, Tuple
from langchain_core.messages import SystemMessage, HumanMessage
MAX_CHARS = 900
def build_sources_metadata(docs: List) -> List[Dict[str, Any]]:
srcs = []
for i, d in enumerate(docs):
meta = d.metadata
src = meta.get("source")
page = meta.get("page")
snippet = d.page_content[:300].replace("\n", " ")
if src == "Prüfungsordnung (PDF)":
pdf_url = meta["pdf_url"]
if isinstance(page, int) and pdf_url:
url = f"{pdf_url}#page={page + 1}"
else:
url = pdf_url
elif src == "Hochschulgesetz NRW":
url = meta["url"]
page = None
else:
url = None
srcs.append(
{
"id": i + 1,
"source": src,
"page": page + 1 if isinstance(page, int) else None,
"url": url,
"snippet": snippet,
}
)
return srcs
def format_context(docs):
if not docs:
return "(Kein relevanter Kontext gefunden.)"
out_lines = []
for i, d in enumerate(docs):
txt = d.page_content[:MAX_CHARS]
src = d.metadata.get("source")
page = d.metadata.get("page")
if src == "Prüfungsordnung (PDF)" and isinstance(page, int):
src_str = f"{src}, Seite {page + 1}"
else:
src_str = src
out_lines.append(f"[KONTEXT {i+1}] ({src_str})\n{txt}")
return "\n\n".join(out_lines)
SYSTEM_PROMPT = """
Du bist ein juristisch präziser Chatbot für Prüfungsrecht.
Du nutzt ausschließlich:
- die Prüfungsordnung (PDF) und
- das Hochschulgesetz NRW (Absätze aus der Datenbank)
Regeln:
1. Keine Halluzinationen – nur Inhalte aus dem gelieferten Kontext.
2. Wenn der Kontext unklar ist, sage ausdrücklich, dass keine sichere
Aussage möglich ist.
3. Antworte immer in gut verständlichem, ganzen Sätzen.
4. Nenne, soweit im Kontext erkennbar:
- Paragraphen oder Überschriften,
- das Dokument (Prüfungsordnung / Hochschulgesetz NRW),
- Seitenzahl (bei der Prüfungsordnung).
"""
def answer(question: str, retriever, chat_model) -> Tuple[str, List[Dict[str, Any]]]:
docs = retriever.invoke(question)
context_str = format_context(docs)
human = f"""
FRAGE:
{question}
NUTZE AUSSCHLIESSLICH DIESEN KONTEXT:
{context_str}
AUFGABE:
Erstelle eine juristisch korrekte Antwort ausschließlich auf Basis
des obigen Kontextes. Wenn der Kontext keine sichere Antwort zulässt,
sage das ausdrücklich und verzichte auf Spekulationen.
"""
msgs = [
SystemMessage(content=SYSTEM_PROMPT),
HumanMessage(content=human),
]
result = chat_model.invoke(msgs)
answer_text = result.content.strip()
sources = build_sources_metadata(docs)
return answer_text, sources