Files
localRAG/EINSTIEG.md
T
Philipp MockandClaude Opus 5.5 ce9a863a87 Load bge-m3 as safetensors for x86; update README, add EINSTIEG.md
- EMBEDDING_REVISION pins the official safetensors conversion of bge-m3, so the x86
  env (torch 2.2.2) can load it; identical vectors, no index rebuild
- README rewritten for the current state (personas, providers, retrieval, environments)
- EINSTIEG.md: short German guide to running and configuring the chat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 07:26:29 +01:00

7.6 KiB
Raw Blame History

Kafka-Chat: Einstieg

Stand: Oktober 2026. Ausführliche englische Referenz: README.md.

Starten

Conda-Umgebungen

Umgebung Architektur Einsatz
docling arm64 (Apple Silicon), Python 3.12, torch 2.14 Standard. Auch für Docling (prepare_corpus.py).
local_rag x86_64 (Intel-Mac oder Rosetta), Python 3.10, torch 2.2.2 Alternative für x86. Chat und Suche getestet; Indexbau sollte gehen (gleiches Embedding), ungetestet. Docling nicht.
  • Warum bge-m3 auf x86 nur über safetensors lädt: Für macOS x86 gibt es höchstens torch 2.2.2. transformers lädt .bin-Gewichte aber erst ab torch 2.6, und bge-m3 hat im Hauptzweig nur pytorch_model.bin.
  • Die Lösung im Code: local_rag.py lädt deshalb die offizielle safetensors-Konvertierung (EMBEDDING_REVISION). Die Gewichte sind dieselben, die Vektoren in beiden Umgebungen identisch, und dieselben Indizes funktionieren in beiden.
  • Geschwindigkeit unter Rosetta: Spürbar langsamer. Im Test brauchte die Suche gut 5 statt gut 1 Sekunde, der Serverstart war dagegen nicht langsamer.

Voraussetzungen (einmalig)

  • Ollama mit dem Modell: ollama pull gemma4:12b.
  • Für ChatGPT und Realtime eine Datei .env im Projektordner mit OPENAI_API_KEY=sk-.... Sie ist git-ignoriert, am besten mit chmod 600 schützen. Ohne Key sind beide Einträge im Menü ausgegraut.
  • Die beiden Vektorspeicher vectorstore_pypdf_2000/ und vectorstore_primary_pypdf_2000/. Sie sind nicht im Git; Neubau siehe unten.

Server starten

cd /Users/Philipp/Desktop/workspace/diverses/local_rag
conda activate docling        # auf x86: conda activate local_rag
uvicorn server:app --port 8010

Dann im Browser http://localhost:8010 öffnen. Der Start dauert etwa eine Minute: Embedding-Modell, Reranker und Stichwortindex werden geladen. Danach ist auch die erste Frage schnell.

  • Optionen: --reload startet den Server bei Codeänderungen neu, --log-level debug zeigt mehr Details.
  • Ohne --reload braucht jede Änderung an .py-Dateien einen Neustart. Bei templates/chat.html reicht es, die Seite neu zu laden.

Was im Terminal steht, pro Frage

[RAG] User question: '…'
[Zeit] LLM-Aufruf 1: 6.86s (Suche angefordert)
[RAG] Tool search '…': 5 chunk(s)
[Zeit] Suche 1.37s (davon Reranker 1.21s)
[Zeit] LLM-Aufruf 2: 15.31s (Antwort)
[Zeit] Gesamt 23.54s

Danach folgen die gefundenen Chunks mit Quelle, Seite und Score sowie die vollständige Antwort.

Aufbau

Browser (templates/chat.html)
   │  POST /api/chat {message, history, persona, llm_provider}
   ▼
server.py ── wählt Figur (personas.py) und RAG-Instanz (Anbieter × Vektorspeicher)
   ▼
local_rag.py · LocalRAG.query_with_history
   │  Systemprompt + Verlauf + Frage an das LLM, Such-Werkzeug angeboten
   │  ┌─ LLM ruft search_kafka_corpus(query) auf (höchstens 3 Runden)
   │  │    retrieve(): FAISS (bge-m3) + BM25 → Fusion (RRF) → 25 Kandidaten
   │  │                → Reranker (bge-reranker-v2-m3) → beste 5 Chunks
   │  └─ LLM antwortet mit den Auszügen
   ▼
Antwort + gefundene Chunks + Suchanfragen → Browser

Dateien

Datei Inhalt
server.py FastAPI-Server, Modellwahl, eine RAG-Instanz pro Anbieter und Vektorspeicher, Konsolenausgabe
personas.py die drei Figuren: Texte, Bilder, Systemprompts, Werkzeugbeschreibung, Vektorspeicher
local_rag.py Laden der Modelle, Suche (retrieve), Werkzeugschleife (query_with_history), Indexbau
realtime_chat.py Anbindung der OpenAI Realtime API (WebSocket, nur Text) als LangChain-Modell
templates/chat.html Oberfläche, Menüs für Figur und Modell
templates/visuals/ Bilder (*.png Vorlagen, *.jpg Webversionen, *_avatar.jpg)
add_pdfs.py Vektorspeicher aus einem PDF-Ordner bauen
eval_retrieval.py Suchqualität auf einem Goldset messen (Recall@k, MRR, optional LLM-Judge)

Stellschrauben

Verhalten der Figuren: personas.py

Pro Figur ein Eintrag in PERSONAS; eine neue Figur ist ein neuer Eintrag mit eigenem Bild.

Feld wirkt auf
system_prompt Ton, Rolle, Regeln für Suche und Belege
tool_description was das Modell über das Such-Werkzeug erfährt (ohne Feld gilt SEARCH_TOOL_DESCRIPTION)
vectorstore welcher Index durchsucht wird
label, topic, name, role, place, status, greeting, suggestions Texte in der Oberfläche
image, image_position, image_alt, avatar Bilder
  • Die Regeln zur Suche für Zeitgenosse und Autor stehen gemeinsam in _TOOL_RULES.
  • Der Prompt der Forscherin ist SYSTEM_PROMPT in local_rag.py.

Sprachmodelle: server.py und local_rag.py

Einstellung aktuell wo
lokales Modell (Ollama) gemma4:12b, denkt standardmäßig (reasoning nicht gesetzt) OLLAMA_MODEL in server.py, ChatOllama(...) in local_rag.py
ChatGPT gpt-6.1-sol OPENAI_MODEL in server.py
Denkaufwand ChatGPT low, über die Responses API ChatOpenAI(...) in local_rag.py
Realtime gpt-realtime-2.1-mini REALTIME_MODEL in server.py
Voreinstellung im Menü ChatGPT selected in chat.html
  • gpt-6.1-sol: kennt keinen Denkaufwand none. Werkzeuge funktionieren nur über die Responses API, deshalb steht use_responses_api=True.
  • Realtime: öffnet pro Modellaufruf eine eigene WebSocket-Sitzung.

Suche: Konstanten oben in local_rag.py

Konstante aktuell Bedeutung
RETRIEVAL_K 5 Chunks pro Suche an das LLM
RETRIEVAL_MODE hybrid dense (nur Vektoren), hybrid (Vektoren + BM25, RRF), union
CANDIDATES_K 25 Kandidaten vor dem Reranker. 25 war schneller und nicht schlechter als 50.
RERANKER_MODEL BAAI/bge-reranker-v2-m3 None schaltet das Reranking ab. Läuft auf der GPU in fp16.
MAX_TOOL_ROUNDS 3 Suchen pro Nachricht, danach muss das Modell antworten
SEARCH_TOOL_DESCRIPTION Text Werkzeugbeschreibung für die Forscherin

Die Suche dauert etwa 1 bis 1,5 Sekunden pro Aufruf, fast nur der Reranker. Den größten Teil der Antwortzeit brauchen die Modellaufrufe.

Index: Neubau nötig bei Änderung

Konstante aktuell
EMBEDDING_MODEL BAAI/bge-m3 (normalisierte Vektoren)
CHUNK_SIZE / CHUNK_OVERLAP 2000 / 400 Zeichen
PDF_LOADER pypdf; docling war im Goldset-Vergleich nicht besser
CHUNK_HEADERS False

Neubau der beiden Indizes. data_primary/ enthält nur einen Verweis auf data/Kafka_Die_Verwandlung_.pdf.

python add_pdfs.py --data data --index ./vectorstore_pypdf_2000 --loader pypdf --no-headers
python add_pdfs.py --data data_primary --index ./vectorstore_primary_pypdf_2000 --loader pypdf --no-headers

Jeder Index speichert seine Einstellungen in index_info.json. Passt das Embedding-Modell nicht zum Code, verweigert LocalRAG das Laden.

Suchqualität messen

python eval_retrieval.py --goldset eval/goldset_kafka_human.csv --report eval/mein_bericht.txt
  • --judge gpt-6-luna lässt zusätzlich ein LLM prüfen, ob die Antwort in den Top 5 steht; das braucht den Key.
  • Stand auf dem menschlichen Goldset (30 Fragen): R@5 0,73, MRR 0,68.

Gut zu wissen

  • Speicher: Embedding-Modell, Reranker und BM25-Index gibt es pro Prozess nur einmal, auch bei mehreren Anbietern. Ollama braucht zusätzlich etwa 8 bis 10 GB für gemma4:12b.
  • Nicht im Git: Korpus-PDFs (data/), Vektorspeicher, .env und Schlüsseldateien.