RAG - Retrieval Augmented Generation¶
Theorie¶
Paper¶
Originalpaper
Lewis, P., Perez, E., Piktus, A., et al. (2020) Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks DOI: 10.48550/arXiv.2005.11401 NeurIPS 2020
Abstract¶
Retrieval-Augmented Generation (RAG) kombiniert vortrainierte parametrische Sprachmodelle mit nicht-parametrischen Wissensspeichern. Anstatt alles Wissen in den Modellgewichten zu speichern, wird externes Wissen zur Inferenzzeit abgerufen und dem LLM als Kontext bereitgestellt.
flowchart LR
subgraph Retrieval
Q[Query] --> E[Embedding]
E --> VS[(Vector Store)]
VS --> C[Context Chunks]
end
subgraph Generation
C --> P[Query + Context]
P --> LLM[LLM]
LLM --> R[Response]
end
Kernkonzepte¶
1. Retriever (Abruf) - Wandelt Query in Embedding-Vektor um - Sucht ähnliche Dokumente im Vektorraum - Gibt Top-K relevanteste Chunks zurück
2. Generator (Generierung) - Erhält Query + abgerufenen Kontext - Generiert Antwort basierend auf Kontext - Kann auf Quellen verweisen
Vorteile¶
| Vorteil | Beschreibung |
|---|---|
| Aktuelles Wissen | Keine Neutrainierung bei Wissensänderung |
| Faktenbasiert | Antworten basieren auf realen Dokumenten |
| Quellenangaben | Transparenz durch Zitierbarkeit |
| Domänenspezifisch | Einfache Anpassung an Fachgebiete |
Nachteile¶
| Nachteil | Beschreibung |
|---|---|
| Retrieval-Qualität | Antwort nur so gut wie gefundene Dokumente |
| Latenz | Zusätzliche Suchzeit |
| Semantic Gap | Kurze Queries matchen schlecht mit langen Dokumenten |
Beispiel¶
Query¶
Retrieval (Top-3 Chunks)¶
[Dokument 1] Impressum - dg agentur
Dominik Günther
dg agentur
Bahnhofstraße 2
90402 Nürnberg
Telefon: +49 911 97554990
[Dokument 2] Datenschutzerklärung
Verantwortlicher: Dominik Günther, Bahnhofstraße 2...
[Dokument 3] Über uns
Die DG Agentur wurde gegründet...
Generation (LLM Response)¶
Der Inhaber der DG Agentur ist Dominik Günther. Die Agentur
befindet sich in der Bahnhofstraße 2, 90402 Nürnberg. [1]
Quellen:
[1] Impressum - dg agentur
Implementierung in LLARS¶
Status: Produktiv
RAG ist vollständig implementiert und im Produktiveinsatz.
Architektur¶
flowchart TB
subgraph Input
Q[User Query]
end
subgraph MultiCollection["Multi-Collection Search"]
Q --> C1[Collection 1<br/>weight: 1.0]
Q --> C2[Collection 2<br/>weight: 0.8]
Q --> C3[Collection N<br/>weight: ...]
C1 --> S1[Semantic Search]
C2 --> S2[Semantic Search]
C3 --> S3[Semantic Search]
S1 --> W1["Score × Weight"]
S2 --> W2["Score × Weight"]
S3 --> W3["Score × Weight"]
end
subgraph Aggregation["Aggregation & Filtering"]
W1 --> AGG[Alle Ergebnisse kombinieren]
W2 --> AGG
W3 --> AGG
AGG --> SORT[Nach Score sortieren]
SORT --> MINR[Min. Relevance Filter]
MINR --> RERANK[Optional: Reranking]
RERANK --> TOPK["Top-K auswählen"]
end
subgraph ContextBuilding["Context Building"]
TOPK --> CTX["[Dokument 1]<br/>[Dokument 2]<br/>..."]
TOPK --> SRC[Sources Metadata]
end
subgraph Generation
CTX --> PROMPT[System + Context + History]
SRC --> PROMPT
PROMPT --> LLM[LLM]
LLM --> RESP["Response mit<br/>Fußnoten [1], [2]"]
end
Nur Semantic Search im Standard-RAG
Die Standard-RAG-Pipeline verwendet ausschließlich semantische Suche (Vektor-Ähnlichkeit). Lexical Search (FTS5/Trigram) ist nur in den Agent-Modi (ACT, ReAct, ReflAct) als Tool verfügbar.
Komponenten¶
1. Embedding Models¶
- Auswahl erfolgt datenbankbasiert über
llm_models(model_type = embedding). - Primär über LiteLLM (z.B.
llamaindex/vdr-2b-multi-v1), Fallback über HuggingFace lokal. - Wenn keine DB-Modelle vorhanden sind, wird
LLARS_EMBEDDING_MODELversucht, ansonstenLLARS_FALLBACK_EMBEDDING_MODEL.
Embedding-Konsistenz
Query-Embedding muss zum Document-Embedding passen (gleiche Dimensionen).
Der Service embedding_model_service.py wählt automatisch das beste verfügbare Modell pro Collection.
2. Vector Store¶
- Technologie: ChromaDB
- Persistenz:
/app/storage/vectorstore/<model_name>/ - Metadaten: document_id, chunk_index, has_image, page_number, start_char, end_char, vector_id
- Distanzmetrik: Cosine Distance (
hnsw:space: cosine) - Score-Konvertierung:
similarity = 1 - cosine_distance
3. Multi-Collection Aggregation¶
Chatbots können mehrere RAG-Collections nutzen. Jede Collection hat:
| Parameter | Beschreibung | Default |
|---|---|---|
weight |
Multiplikator für Chunk-Scores | 1.0 |
priority |
Reihenfolge der Suche (höher = zuerst) | 0 |
Ablauf:
- Pro Collection wird semantisch gesucht.
- Scores werden mit weight multipliziert.
- Ergebnisse werden kombiniert und sortiert.
- candidate_k = max(final_k * 8, 32) und danach auf final_k reduziert.
4. Relevance-Filter¶
- Mindestschwelle:
rag_min_relevance - Falls nichts die Schwelle erfüllt, werden die Top-K Kandidaten genutzt.
5. Reranking (Optional)¶
Das Reranking läuft über services/rag/reranker.py:
- Modi:
lexical(Default),cross-encoder,off - Steuerung:
RAG_RERANK_MODE(Env) - Lexical: Overlap-Score mit
RAG_RERANK_ALPHA(Default 0.15) - Cross-Encoder: Sentence-Transformers, optional über
rag_reranker_model - Fallback: Wenn Cross-Encoder fehlschlägt → lexical
6. Lexical Search (Nur Agent-Modi)¶
- Technologie: SQLite FTS5 (Trigram)
- Index:
app/data/rag/indexes/lexical_index.sqlite(override viaLEXICAL_INDEX_PATH) - Query-Expansion: Stopword-Filtering, Synonyme, Compound-Splitting
- Fallback: SQL LIKE Search
7. Vision-Filter¶
- Bei Non‑Vision Modellen werden Chunks mit Bildern herausgefiltert.
Dateien¶
| Datei | Funktion |
|---|---|
app/services/chatbot/chat_service.py |
RAG Orchestrierung + Prompt Builder |
app/services/chatbot/chat_rag_retrieval.py |
Semantic Search + Aggregation + Filter |
app/services/rag/embedding_model_service.py |
Model-Fallback-Chain |
app/services/rag/reranker.py |
Reranking (Lexical/Cross-Encoder) |
app/services/chatbot/lexical_index.py |
FTS5 Index (Agent-Modi) |
app/rag_pipeline.py |
Legacy RAG Pipeline (System-Dokumentation) |
Konfiguration¶
# Chatbot (db/models/chatbot.py)
rag_enabled: bool = True
rag_retrieval_k: int = 8 # Anzahl Dokumente im Kontext
rag_min_relevance: float = 0.05 # Minimum Score (0-1)
rag_include_sources: bool = True
rag_reranker_model: Optional[str] = None
rag_use_cross_encoder: bool = False
# ChatbotCollection (pro Collection)
weight: float = 1.0 # Score-Multiplikator
priority: int = 0 # Suchreihenfolge
API¶
# Multi-Collection RAG
context, sources = chat_service._get_multi_collection_context(query)
# → context: "[Dokument 1]\n...\n---\n\n[Dokument 2]\n..."
# → sources: [{"footnote_id": 1, "title": "...", "relevance": 0.85, ...}, ...]
# Einzelne Collection durchsuchen
results = chat_service._search_collection(collection, query, k=12)
# → [{"content": "...", "score": 0.85, "document_id": 1, ...}, ...]
Logs¶
[ChatRAGRetrieval] Semantic search: 24 results for chatbot 5
[ChatRAGRetrieval] Top 24 candidates before relevance filter:
[ChatRAGRetrieval] Reranking 12 results