RAG-Generierung: LLM auswählen und optimieren
Umfassender Leitfaden zur Auswahl und Konfiguration Ihres LLM in einem RAG-System: prompting, temperature, tokens und Optimierung der Antworten.
RAG-Generierung: LLM auswählen und optimieren
Die Generierungsphase ist der Moment, in dem Ihr RAG-System die abgerufenen Dokumente in eine kohärente und nützliche Antwort umwandelt. Die Wahl des LLM und seine Parametrierung bestimmen die endgültige Qualität des Benutzererlebnisses. Dieser Leitfaden begleitet Sie bei der Auswahl, Konfiguration und Optimierung Ihres Generierungsmodells.
Die Rolle des LLM in einem RAG-System
Im Gegensatz zu einem einzeln eingesetzten LLM generiert das LLM in einem RAG-System nicht aus seinem internen Wissen. Es synthetisiert, reformuliert und strukturiert die Informationen aus dem Retrieval.
Was das RAG-LLM tut
- Synthese: Mehrere Dokumente zu einer prägnanten Antwort verdichten
- Umformulierung: Fachsprache an das Niveau des Nutzers anpassen
- Strukturierung: Informationen logisch organisieren
- Kontextualisierung: Die Antwort mit der gestellten Frage verknüpfen
- Insuffizienz-Erkennung: Erkennen, wenn die Dokumente keine Antwort ermöglichen
Was das RAG-LLM NICHT tun sollte
- Informationen erfinden, die nicht in den Dokumenten vorhanden sind (Halluzination)
- Den bereitgestellten Quellen widersprechen
- Fragen außerhalb des Geltungsbereichs beantworten, ohne darauf hinzuweisen
Vergleich der LLMs für RAG
Proprietäre Modelle
| Modell | Stärken | Schwächen | Kosten (1M Tokens) | RAG-Einsatz |
|---|---|---|---|---|
| GPT-4o | Vielseitig, gutes Reasoning | Hoher Preis | ~$2.50 Input / $10 Output | Premium-Produktion |
| GPT-4o-mini | Gutes Preis-Leistungs-Verhältnis | Schwächer bei komplexen Aufgaben | ~$0.15 / $0.60 | Standard-Produktion |
| Claude Sonnet 4.6 | Exzellente Befolgung von Anweisungen | 1M-Kontext manchmal ungenutzt | ~$3 / $15 | Premium-Produktion |
| Claude Haiku 4.5 | Ultraschnell, wirtschaftlich | Weniger nuanciert | ~$1 / $5 | Hohes Volumen |
| Gemini 2.5 Pro | 1M-Token-Kontext | API manchmal instabil | ~$1.25 / $10 | Sehr lange Dokumente |
Richtwerte für API-Preise (Stand: Juli 2026).
Open-Source-Modelle
| Modell | Parameter | Benötigter VRAM | RAG-Leistung | Selbst hostbar |
|---|---|---|---|---|
| Llama 3.1 70B | 70B | 48GB+ | Exzellent | Ja (dedizierter Server) |
| Llama 3.1 8B | 8B | 8GB | Gut | Ja (Consumer-GPU) |
| Mistral 7B | 7B | 6GB | Gut | Ja |
| Mixtral 8x7B | 46.7B (MoE) | 32GB | Sehr gut | Ja |
| Qwen2 72B | 72B | 48GB+ | Exzellent | Ja |
Auswahlkriterien
DEVELOPERpythondef choisir_llm( budget_mensuel: float, volume_requetes: int, exigence_qualite: str, # "standard", "premium" contrainte_hebergement: str, # "cloud", "souverain", "on-premise" langues: list[str] ) -> str: tokens_par_requete = 2000 # estimation moyenne RAG tokens_mensuels = volume_requetes * tokens_par_requete if contrainte_hebergement == "on-premise": if exigence_qualite == "premium": return "Llama 3.1 70B oder Qwen2 72B" return "Llama 3.1 8B oder Mistral 7B" if contrainte_hebergement == "souverain": return "Mistral Large über die Mistral-API (in der EU gehostet)" cout_gpt4o_mini = tokens_mensuels * 0.15 / 1_000_000 cout_claude_haiku = tokens_mensuels * 1.0 / 1_000_000 if budget_mensuel < cout_gpt4o_mini: return "Selbst gehostetes Open-Source-Modell" if exigence_qualite == "premium": if "fr" in langues: return "Claude Sonnet 4.6 (hervorragend auf Französisch)" return "GPT-4o" return "GPT-4o-mini oder Claude Haiku 4.5"
System-Prompt konfigurieren
Der System-Prompt definiert das Verhalten des LLM in Ihrer RAG-Anwendung. Er ist das kritischste Element der Konfiguration.
Struktur eines effektiven RAG-Prompts
DEVELOPERpythonSYSTEM_PROMPT = """Du bist ein KI-Assistent für {nom_entreprise}, spezialisiert auf {domaine}. STRENGE REGELN: 1. Antworte AUSSCHLIESSLICH auf Basis der im Kontext bereitgestellten Dokumente 2. Wenn die Information nicht in den Dokumenten enthalten ist, sage "Diese Information liegt mir nicht vor" 3. Erfinde niemals Informationen 4. Nenne deine Quellen, wenn relevant ANTWORTSTIL: - Ton: {ton} (professionell/freundlich/technisch) - Länge: {longueur} (prägnant/ausführlich) - Format: Verwende Aufzählungslisten bei mehr als 3 Elementen - Sprache: Antworte in der Sprache der Frage GESCHÄFTLICHER KONTEXT: {contexte_specifique} VERFÜGBARE DOKUMENTE: {documents_retrieves} FRAGE DES NUTZERS: {question} """
Prompt-Beispiele nach Anwendungsfall
E-Commerce-Kundenservice
DEVELOPERpythonECOMMERCE_PROMPT = """Du bist der virtuelle Assistent des Shops {nom_boutique}. ZIELE: - Kunden bei Bestellungen, Retouren und Produktfragen unterstützen - Die Kundenzufriedenheit maximieren - Bei Bedarf an den menschlichen Support weiterleiten REGELN: 1. Stütze deine Antworten AUSSCHLIESSLICH auf die bereitgestellten Dokumente 2. Frage bei Fragen zu einer bestimmten Bestellung nach der Bestellnummer 3. Gib niemals persönliche Daten anderer Kunden weiter 4. Wenn eine Anfrage deine Möglichkeiten übersteigt, schlage vor, den Kundenservice zu kontaktieren TON: Freundlich und hilfsbereit, wie ein Verkäufer im Laden DOKUMENTE: {context} FRAGE: {question} """
Technische Wissensdatenbank
DEVELOPERpythonTECH_KB_PROMPT = """Du bist ein technischer Experte für {produit}. ZIELE: - Präzise technische Antworten liefern - Codebeispiele einbinden, wenn relevant - Auf die offizielle Dokumentation verweisen REGELN: 1. Antworte ausschließlich auf Basis der bereitgestellten Dokumentation 2. Gib die betroffene Produktversion an, sofern erwähnt 3. Weise auf bekannte Einschränkungen oder dokumentierte Bugs hin 4. Schlage Alternativen vor, wenn die gewünschte Lösung nicht existiert FORMAT: - Beginne mit einer direkten Antwort - Gehe bei Bedarf ins Detail - Schließe gegebenenfalls mit einem Codebeispiel ab DOKUMENTATION: {context} FRAGE: {question} """
Generierungsparameter
Temperatur
Die Temperatur steuert das Verhältnis zwischen Kreativität und Konsistenz der Antworten.
DEVELOPERpython# Niedrige Temperatur (0.0 - 0.3): Deterministische, faktenbasierte Antworten # Ideal für: Kundensupport, FAQ, technische Dokumentation temperature = 0.1 # Mittlere Temperatur (0.4 - 0.7): Balance zwischen Kreativität und Kohärenz # Ideal für: allgemeinen Chat, Umformulierung temperature = 0.5 # Hohe Temperatur (0.8 - 1.0): Vielfältige, kreative Antworten # Ideal für: Brainstorming, Content-Erstellung # In RAG VERMEIDEN (Halluzinationsrisiko) temperature = 0.9
Top-p (Nucleus Sampling)
Begrenzt die berücksichtigten Tokens auf jene, die eine kumulative Wahrscheinlichkeit repräsentieren.
DEVELOPERpython# top_p = 0.9: Berücksichtigt Tokens bis zu 90% kumulierter Wahrscheinlichkeit # Restriktiver = kohärenter # Größer = vielfältiger from openai import OpenAI client = OpenAI() response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], temperature=0.2, top_p=0.9, # Kombiniert mit niedriger Temperatur für RAG )
Max tokens
Begrenzt die Länge der generierten Antwort.
DEVELOPERpython# Berechnung des Token-Budgets def calculer_max_tokens( context_length: int, model_limit: int = 128000, # GPT-4o reserve_output: int = 2000 ) -> int: """ Stellt sicher, dass genug Platz für die Antwort bleibt """ prompt_tokens = context_length + 500 # + Anweisungen available = model_limit - prompt_tokens return min(available, reserve_output)
Frequency und Presence Penalty
Steuern die Wiederholung in den Antworten.
DEVELOPERpythonresponse = client.chat.completions.create( model="gpt-4o-mini", messages=messages, frequency_penalty=0.3, # Bestraft bereits verwendete Tokens presence_penalty=0.1, # Fördert neue Themen )
Den an das LLM übergebenen Kontext optimieren
Formatierung der abgerufenen Dokumente
DEVELOPERpythondef format_context(documents: list[dict], max_tokens: int = 4000) -> str: """ Formatiert die Dokumente für den LLM-Kontext """ formatted_docs = [] total_tokens = 0 for i, doc in enumerate(documents): # Token-Schätzung (1 Token ≈ 4 Zeichen im Deutschen) doc_tokens = len(doc["text"]) // 4 if total_tokens + doc_tokens > max_tokens: break formatted = f""" --- QUELLE {i+1}: {doc.get("source", "Document")} RELEVANZ-SCORE: {doc.get("score", "N/A")} {doc["text"]} --- """ formatted_docs.append(formatted) total_tokens += doc_tokens return "\n".join(formatted_docs)
Reihenfolge der Dokumente
Die Reihenfolge beeinflusst die Aufmerksamkeit des LLM. Zwei Hauptstrategien:
DEVELOPERpythondef order_documents(documents: list[dict], strategy: str = "best_first") -> list: """ Ordnet die Dokumente gemäß der gewählten Strategie """ if strategy == "best_first": # Das relevanteste zuerst return sorted(documents, key=lambda x: x["score"], reverse=True) elif strategy == "lost_in_middle": # Die besten am Anfang und am Ende (vermeidet den "lost in the middle"-Effekt) sorted_docs = sorted(documents, key=lambda x: x["score"], reverse=True) n = len(sorted_docs) reordered = [] for i in range(n): if i % 2 == 0: reordered.insert(0, sorted_docs[i]) else: reordered.append(sorted_docs[i]) return reordered return documents
Kontextkompression
Bei langen Dokumenten vor dem Senden an das endgültige LLM zusammenfassen:
DEVELOPERpythonasync def compress_context( documents: list[str], query: str, llm_compressor ) -> str: """ Komprimiert die Dokumente unter Beibehaltung der relevanten Informationen """ compression_prompt = f""" Extrahiere die relevanten Informationen zur Beantwortung dieser Frage: Frage: {query} Dokumente: {chr(10).join(documents)} Zusammenfassung der relevanten Informationen: """ compressed = await llm_compressor.generate(compression_prompt) return compressed
Umgang mit Halluzinationen
Halluzinationen sind das Hauptrisiko bei RAG. So können sie minimiert werden.
Halluzinationserkennung
DEVELOPERpythondef detect_hallucination( response: str, context: str, query: str, verifier_llm ) -> dict: """ Prüft, ob die Antwort Halluzinationen enthält """ verification_prompt = f""" Analysiere diese Antwort und prüfe, ob sie dem bereitgestellten Kontext treu bleibt. BEREITGESTELLTER KONTEXT: {context} FRAGE: {query} ZU PRÜFENDE ANTWORT: {response} ANALYSE: 1. Enthält die Antwort Behauptungen, die nicht im Kontext vorhanden sind? 2. Widerspricht die Antwort dem Kontext? 3. Treue-Score (0-100): Antworte in JSON: {{"hallucinations": [...], "contradictions": [...], "score": X}} """ result = verifier_llm.generate(verification_prompt) return json.loads(result)
Anti-Halluzinations-Strategien
DEVELOPERpythonclass RAGGenerator: def __init__(self, llm, verifier_llm=None): self.llm = llm self.verifier = verifier_llm async def generate_with_verification( self, query: str, context: str, max_retries: int = 2 ) -> dict: """ Generiert eine Antwort mit Anti-Halluzinations-Überprüfung """ for attempt in range(max_retries + 1): # Generierung response = await self.llm.generate( self._build_prompt(query, context), temperature=0.1 # Niedrig, um Halluzinationen zu reduzieren ) # Überprüfung, falls Verifier verfügbar if self.verifier: check = detect_hallucination(response, context, query, self.verifier) if check["score"] >= 80: return { "response": response, "confidence": check["score"], "verified": True } # Wiederholung mit strengerer Anweisung context = self._add_anti_hallucination_instruction(context, check) else: return {"response": response, "verified": False} # Fallback: vorsichtige Antwort return { "response": "Ich bin mir nicht sicher, ob ich diese Frage mit den verfügbaren Informationen präzise beantworten kann.", "confidence": 0, "verified": True }
Streaming und Latenz
Für ein flüssiges Benutzererlebnis ist Streaming unverzichtbar.
Streaming-Implementierung
DEVELOPERpythonfrom openai import OpenAI client = OpenAI() async def stream_response(prompt: str): """ Streamt die Antwort Token für Token """ stream = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], stream=True ) for chunk in stream: if chunk.choices[0].delta.content: yield chunk.choices[0].delta.content # Verwendung mit FastAPI from fastapi import FastAPI from fastapi.responses import StreamingResponse app = FastAPI() @app.post("/chat") async def chat(request: ChatRequest): prompt = build_rag_prompt(request.query, request.context) return StreamingResponse( stream_response(prompt), media_type="text/event-stream" )
Latenzoptimierung
DEVELOPERpythonimport asyncio from functools import lru_cache class OptimizedRAG: def __init__(self): self.retriever = Retriever() self.llm = LLM() async def query(self, question: str) -> str: # Retrieval und Prompt-Vorbereitung parallelisieren retrieval_task = asyncio.create_task( self.retriever.search(question) ) # Statische Prompt-Teile vorab berechnen base_prompt = self._get_cached_prompt() # Auf das Retrieval warten documents = await retrieval_task # An das LLM aufbauen und senden full_prompt = base_prompt.format( context=format_context(documents), question=question ) return await self.llm.generate(full_prompt) @lru_cache(maxsize=1) def _get_cached_prompt(self) -> str: return self._load_system_prompt()
Qualitätsmetriken der Generierung
Faithfulness (Treue)
Misst, ob die Antwort dem bereitgestellten Kontext treu ist.
DEVELOPERpythondef calculate_faithfulness( response: str, context: str, evaluator_llm ) -> float: """ Treue-Score zwischen 0 und 1 """ prompt = f""" Bewerte die Treue dieser Antwort in Bezug auf den Kontext. Kontext: {context} Antwort: {response} Prüfe für jede Behauptung in der Antwort, ob sie: - vom Kontext gestützt wird (1 Punkt) - im Kontext nicht erwähnt wird (0 Punkte) - dem Kontext widerspricht (-1 Punkt) Endgültiger Score (0-1): """ result = evaluator_llm.generate(prompt) return float(result)
Answer Relevancy (Relevanz)
Misst, ob die Antwort die Frage tatsächlich beantwortet.
DEVELOPERpythondef calculate_relevancy( question: str, response: str, evaluator_llm ) -> float: """ Relevanz-Score zwischen 0 und 1 """ prompt = f""" Bewerte, ob diese Antwort die gestellte Frage gut beantwortet. Frage: {question} Antwort: {response} Kriterien: - Geht die Antwort direkt auf die Frage ein? (0-0.4) - Ist die Antwort vollständig? (0-0.3) - Ist die Antwort prägnant und klar? (0-0.3) Endgültiger Score (0-1): """ result = evaluator_llm.generate(prompt) return float(result)
Integration mit verschiedenen Anbietern
OpenAI
DEVELOPERpythonfrom openai import OpenAI class OpenAIGenerator: def __init__(self, model: str = "gpt-4o-mini"): self.client = OpenAI() self.model = model async def generate(self, prompt: str, **kwargs) -> str: response = self.client.chat.completions.create( model=self.model, messages=[{"role": "user", "content": prompt}], temperature=kwargs.get("temperature", 0.2), max_tokens=kwargs.get("max_tokens", 2000) ) return response.choices[0].message.content
Anthropic Claude
DEVELOPERpythonfrom anthropic import Anthropic class ClaudeGenerator: def __init__(self, model: str = "claude-sonnet-4-6"): self.client = Anthropic() self.model = model async def generate(self, prompt: str, system: str = None, **kwargs) -> str: messages = [{"role": "user", "content": prompt}] response = self.client.messages.create( model=self.model, max_tokens=kwargs.get("max_tokens", 2000), system=system or "Du bist ein präziser und faktenbasierter RAG-Assistent.", messages=messages ) return response.content[0].text
Lokales Modell mit Ollama
DEVELOPERpythonimport httpx class OllamaGenerator: def __init__(self, model: str = "llama3.1:8b", base_url: str = "http://localhost:11434"): self.model = model self.base_url = base_url async def generate(self, prompt: str, **kwargs) -> str: async with httpx.AsyncClient() as client: response = await client.post( f"{self.base_url}/api/generate", json={ "model": self.model, "prompt": prompt, "stream": False, "options": { "temperature": kwargs.get("temperature", 0.2) } } ) return response.json()["response"]
Nächste Schritte
Nachdem Sie die RAG-Generierung beherrschen, erkunden Sie diese fortgeschrittenen Themen:
- Konversationelles RAG: Speicher und Kontext - Multi-Turn-Gespräche verwalten
- RAG-Agenten: Multi-Agenten-Orchestrierung - Über einfaches RAG hinausgehen
- Ein RAG-System evaluieren - Vollständige Metriken und Methoden
Für einen umfassenden Überblick lesen Sie unsere Einführung in RAG.
Machen Sie es sich einfach mit Ailog
Ein LLM für RAG zu konfigurieren und zu optimieren erfordert viele Iterationen. Mit Ailog profitieren Sie von einer schlüsselfertigen, optimierten Konfiguration:
- Voroptimierte Prompts für jeden Anwendungsfall (Support, E-Commerce, interne KB)
- Integrierter Anti-Halluzinations-Schutz mit automatischer Überprüfung
- Natives Streaming für ein flüssiges Benutzererlebnis
- Multi-LLM: Wechseln Sie zwischen GPT-4, Claude oder souveränen Modellen, ohne Ihren Code zu ändern
Starten Sie kostenlos mit Ailog und deployen Sie einen optimierten RAG-Assistenten in wenigen Minuten.
Tags
Verwandte Artikel
Temperatur und RAG-Sampling: Die Kreativität des LLM steuern
Umfassender Leitfaden zu Sampling-Parametern für RAG-Systeme: Temperatur, top-p, top-k, frequency penalty. Optimieren Sie das Gleichgewicht zwischen Kreativität und Treue.
Prompt Engineering RAG: System-Prompts für bessere Antworten optimieren
Vollständiger Leitfaden zum Prompt Engineering für RAG-Systeme: fortgeschrittene Techniken, optimierte Templates und Best Practices zur Maximierung der Antwortqualität.
Function calling : RAG mit Aktionen
Vollständiger Leitfaden zum Kombinieren von RAG und function calling: Agenten, die recherchieren UND handeln, Integration externer APIs, automatisierte Aktionen und interaktive Workflows.