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.
TL;DR
Die paramètres de sampling (Temperatur, top-p, top-k) steuern das Niveau an Kreativität und Determinismus der Antworten eines LLM. In RAG sind diese Parameter kritisch: zu viel Kreativität = Halluzinationen, zu viel Determinismus = robotische Antworten. Dieser Leitfaden zeigt, wie Sie diese Parameter nach Ihrem Anwendungsfall kalibrieren.
Comprendre les paramètres de sampling
Qu'est-ce que le sampling ?
Wenn ein LLM Text generiert, sagt es eine Wahrscheinlichkeitsverteilung über alle möglichen tokens für das nächste Wort voraus. Das sampling bestimmt, wie aus diesen Kandidaten ausgewählt wird.
DEVELOPERpython# Vereinfachtes Beispiel einer Wahrscheinlichkeitsverteilung next_token_probs = { "rapidement": 0.35, "vite": 0.25, "promptement": 0.15, "immédiatement": 0.12, "instantanément": 0.08, "...": 0.05 } # Ohne Sampling (greedy): immer "rapidement" # Mit Sampling: kann "vite", "promptement", etc. wählen
Vue d'ensemble des paramètres
| Paramètre | Plage | Effet | Usage RAG typique |
|---|---|---|---|
| Temperature | 0.0 - 2.0 | Contrôle la "chaleur" de la distribution | 0.1 - 0.5 |
| Top-p | 0.0 - 1.0 | Nucleus sampling | 0.9 - 1.0 |
| Top-k | 1 - 100+ | Limite les candidats | 40 - 80 |
| Frequency penalty | -2.0 - 2.0 | Pénalise les répétitions | 0.0 - 0.5 |
| Presence penalty | -2.0 - 2.0 | Encourage la diversité | 0.0 - 0.3 |
La température en détail
Fonctionnement mathématique
La température modifie la distribution softmax des probabilités :
DEVELOPERpythonimport numpy as np def apply_temperature(logits: np.array, temperature: float) -> np.array: """ Wendet die Temperatur auf die Logits an. - temperature < 1 : schärfere Verteilung (deterministisch) - temperature = 1 : ursprüngliche Verteilung - temperature > 1 : flachere Verteilung (zufälliger) """ if temperature == 0: # Greedy: gibt einen One-Hot-Vektor für das Maximum zurück result = np.zeros_like(logits) result[np.argmax(logits)] = 1.0 return result scaled_logits = logits / temperature exp_logits = np.exp(scaled_logits - np.max(scaled_logits)) return exp_logits / np.sum(exp_logits) # Beispiel logits = np.array([2.0, 1.5, 1.0, 0.5, 0.2]) print("Temp 0.1:", apply_temperature(logits, 0.1)) # [0.99, 0.01, 0.00, 0.00, 0.00] - fast deterministisch print("Temp 1.0:", apply_temperature(logits, 1.0)) # [0.42, 0.26, 0.15, 0.09, 0.07] - ursprüngliche Verteilung print("Temp 2.0:", apply_temperature(logits, 2.0)) # [0.29, 0.23, 0.19, 0.16, 0.14] - gleichmäßigere Verteilung
Impact visuel
Température basse (0.1) Température haute (1.5)
│ │
│ ████████████ │ ██████
│ ██ │ █████
│ █ │ ████
│ │ ███
│ │ ██
└──────────────── └────────────────
Token 1 domine Distribution plate
Recommandations par cas d'usage RAG
| Cas d'usage | Température | Justification |
|---|---|---|
| Support client factuel | 0.1 - 0.2 | Précision maximale, pas de créativité |
| FAQ automatisée | 0.2 - 0.3 | Variations légères acceptables |
| Assistant e-commerce | 0.3 - 0.5 | Un peu de personnalité |
| Rédaction assistée | 0.5 - 0.7 | Créativité contrôlée |
| Brainstorming | 0.7 - 1.0 | Idées variées bienvenues |
Top-p (Nucleus Sampling)
Comment ça marche
Top-p sélectionne les tokens dont les probabilités cumulées atteignent p :
DEVELOPERpythondef top_p_sampling(probs: dict, p: float) -> list: """ Gibt die Tokens zurück, deren kumulierte Wahrscheinlichkeit p erreicht. """ # Trier par probabilité décroissante sorted_tokens = sorted(probs.items(), key=lambda x: x[1], reverse=True) cumulative_prob = 0.0 selected_tokens = [] for token, prob in sorted_tokens: cumulative_prob += prob selected_tokens.append((token, prob)) if cumulative_prob >= p: break return selected_tokens # Exemple probs = { "Le": 0.40, "La": 0.25, "Un": 0.15, "Une": 0.10, "Ce": 0.05, "Cette": 0.03, "Mon": 0.02 } print(top_p_sampling(probs, 0.9)) # [("Le", 0.40), ("La", 0.25), ("Un", 0.15), ("Une", 0.10)] # Kumuliert: 0.90 - die anderen werden ausgeschlossen
Top-p vs Température
| Critère | Température | Top-p |
|---|---|---|
| Contrôle | Global sur toute la distribution | Coupe les tokens improbables |
| Risque | Peut sélectionner des tokens très improbables | Garantit des tokens raisonnables |
| Usage | Ajuster la "confiance" | Éviter les aberrations |
Combinaison recommandée pour RAG
DEVELOPERpython# Configuration recommandée pour un chatbot support rag_config = { "temperature": 0.3, # Peu de créativité "top_p": 0.95, # Garde 95% de la masse probabiliste "top_k": 50, # Maximum 50 candidats } # Die niedrige Temperatur macht die Verteilung spitzer # Top-p eliminiert Tokens mit < 5% restlicher kumulativer Masse # Top-k setzt eine harte Grenze für die Anzahl der Kandidaten
Top-k sampling
Principe
Top-k garde uniquement les k tokens les plus probables :
DEVELOPERpythondef top_k_sampling(probs: dict, k: int) -> dict: """ Behält die k wahrscheinlichsten Tokens. """ sorted_tokens = sorted(probs.items(), key=lambda x: x[1], reverse=True) top_k_tokens = dict(sorted_tokens[:k]) # Renormaliser total = sum(top_k_tokens.values()) return {t: p/total for t, p in top_k_tokens.items()} # Exemple probs = {"A": 0.3, "B": 0.25, "C": 0.2, "D": 0.15, "E": 0.1} print(top_k_sampling(probs, 3)) # {"A": 0.40, "B": 0.33, "C": 0.27} # D et E sont exclus, les autres renormalisés
Quand utiliser Top-k
- k petit (10-20) : Réponses très conservatrices
- k moyen (40-60) : Bon équilibre (recommandé pour RAG)
- k grand (100+) : Presque pas de filtrage
Frequency et Presence Penalties
Frequency Penalty
Pénalise les tokens proportionnellement à leur fréquence dans le texte généré :
DEVELOPERpythondef apply_frequency_penalty( logits: dict, generated_tokens: list, penalty: float ) -> dict: """ Reduziert die Wahrscheinlichkeit häufig verwendeter Tokens. """ token_counts = {} for token in generated_tokens: token_counts[token] = token_counts.get(token, 0) + 1 adjusted_logits = {} for token, logit in logits.items(): count = token_counts.get(token, 0) adjusted_logits[token] = logit - (penalty * count) return adjusted_logits
Usage en RAG : Évite les réponses répétitives comme "comme mentionné précédemment..."
Presence Penalty
Pénalise tout token déjà apparu, indépendamment de la fréquence :
DEVELOPERpythondef apply_presence_penalty( logits: dict, generated_tokens: set, penalty: float ) -> dict: """ Réduit la probabilité des tokens déjà utilisés. """ adjusted_logits = {} for token, logit in logits.items(): if token in generated_tokens: adjusted_logits[token] = logit - penalty else: adjusted_logits[token] = logit return adjusted_logits
Usage en RAG : Encourage l'utilisation de synonymes et la variété lexicale.
Configuration optimale par modèle
OpenAI GPT-4
DEVELOPERpythonfrom openai import OpenAI client = OpenAI() # Empfohlene RAG-Konfiguration response = client.chat.completions.create( model="gpt-4", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": f"Context: {context}\n\nQuestion: {query}"} ], temperature=0.3, top_p=0.95, frequency_penalty=0.2, presence_penalty=0.1, max_tokens=500 )
Anthropic Claude
DEVELOPERpythonimport anthropic client = anthropic.Anthropic() # Claude verwendet nur temperature und top_p response = client.messages.create( model="claude-3-opus-20240229", max_tokens=500, temperature=0.3, top_p=0.95, messages=[ {"role": "user", "content": f"Context: {context}\n\nQuestion: {query}"} ] )
Modèles open-source (Llama, Mistral)
DEVELOPERpythonfrom transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2") tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2") # RAG-Konfiguration generation_config = { "temperature": 0.3, "top_p": 0.95, "top_k": 50, "repetition_penalty": 1.1, # Entspricht frequency_penalty "do_sample": True, "max_new_tokens": 500 } outputs = model.generate( input_ids, **generation_config )
Stratégies avancées
1. Sampling adaptatif
Ajuster les paramètres dynamiquement selon le contexte :
DEVELOPERpythonclass AdaptiveSampler: def __init__(self): self.base_temperature = 0.3 def get_config(self, query_type: str, context_quality: float) -> dict: """ Passt die Parameter je nach Kontext an. - query_type: "factual", "creative", "mixed" - context_quality: 0-1, Relevanzscore des Kontexts """ if query_type == "factual": # Fragen zu Fakten: sehr deterministisch temp = 0.1 elif query_type == "creative": # Kreative Fragen: mehr Freiheit temp = 0.7 else: temp = self.base_temperature # Wenn der Kontext schlecht ist, konservativer sein if context_quality < 0.5: temp *= 0.5 # Temperatur reduzieren return { "temperature": temp, "top_p": 0.95 if context_quality > 0.7 else 0.85, "frequency_penalty": 0.2 } # Utilisation sampler = AdaptiveSampler() config = sampler.get_config( query_type="factual", context_quality=0.85 )
2. Température variable par section
Utiliser différentes températures selon la partie de la réponse :
DEVELOPERpythonasync def generate_structured_response(query: str, context: str): """ Génère une réponse avec des paramètres différents par section. """ # Abschnitt 1: Faktenantwort (niedrige Temperatur) factual_part = await llm.generate( prompt=f"Réponds factuellement: {query}\nContext: {context}", temperature=0.1, max_tokens=200 ) # Abschnitt 2: Erklärung (mittlere Temperatur) explanation = await llm.generate( prompt=f"Explique pourquoi: {factual_part}", temperature=0.4, max_tokens=150 ) # Abschnitt 3: Vorschlag (höhere Temperatur) suggestion = await llm.generate( prompt=f"Suggère des alternatives ou compléments", temperature=0.6, max_tokens=100 ) return { "answer": factual_part, "explanation": explanation, "suggestions": suggestion }
3. A/B Testing des paramètres
DEVELOPERpythonimport random from dataclasses import dataclass @dataclass class SamplingVariant: name: str temperature: float top_p: float frequency_penalty: float class SamplingABTester: def __init__(self): self.variants = [ SamplingVariant("conservative", 0.1, 0.9, 0.0), SamplingVariant("balanced", 0.3, 0.95, 0.2), SamplingVariant("creative", 0.5, 1.0, 0.3), ] self.results = {v.name: {"count": 0, "satisfaction": []} for v in self.variants} def get_variant(self) -> SamplingVariant: return random.choice(self.variants) def record_feedback(self, variant_name: str, satisfaction: float): self.results[variant_name]["count"] += 1 self.results[variant_name]["satisfaction"].append(satisfaction) def get_best_variant(self) -> str: avg_scores = { name: sum(data["satisfaction"]) / max(len(data["satisfaction"]), 1) for name, data in self.results.items() } return max(avg_scores, key=avg_scores.get)
Erreurs courantes
1. Température trop haute pour du factuel
DEVELOPERpython# ❌ Schlecht: zu hohe Temperatur für Support response = llm.generate( prompt="Quel est le délai de retour ?", temperature=1.0 # Risiko von Halluzinationen ! ) # ✅ Gut: niedrige Temperatur für Faktenfragen response = llm.generate( prompt="Quel est le délai de retour ?", temperature=0.2 )
2. Ignorer le context quality
DEVELOPERpython# ❌ Schlecht: gleiche Temperatur unabhängig vom Kontext config = {"temperature": 0.5} # ✅ Gut: an die Qualität des Kontexts anpassen context_score = retriever.get_relevance_score(query, documents) config = { "temperature": 0.2 if context_score < 0.6 else 0.4 }
3. Combiner de façon incohérente
DEVELOPERpython# ❌ Inkonsistent: niedrige Temperatur + sehr niedriges top_p config = { "temperature": 0.1, "top_p": 0.5 # unnötige doppelte Einschränkung } # ✅ Konsistent: eine hauptsächliche Einschränkung config = { "temperature": 0.2, "top_p": 0.95 # Nur um Ausreißer zu vermeiden }
Intégration avec Ailog
Ailog permet de configurer les paramètres de sampling directement dans l'interface :
DEVELOPERpythonfrom ailog import AilogClient client = AilogClient(api_key="your-key") # Konfiguration über die Oberfläche oder die API channel_config = { "generation": { "temperature": 0.3, "top_p": 0.95, "frequency_penalty": 0.2, "adaptive_sampling": True # automatische Anpassung } } client.update_channel_config("support-widget", channel_config)
Conclusion
Les paramètres de sampling sont des leviers puissants mais subtils. En RAG :
- Température basse (0.1-0.3) pour les réponses factuelles
- Top-p autour de 0.95 pour filtrer les aberrations
- Frequency penalty léger (0.1-0.3) pour éviter les répétitions
- Adaptation dynamique selon la qualité du contexte
- A/B testing pour trouver la configuration optimale
Ressources complémentaires
- Introduction au RAG - Fondamentaux
- Génération LLM pour RAG - Guide parent
- Prompt Engineering RAG - Optimiser les prompts
- Chain-of-Thought RAG - Raisonnement étape par étape
Besoin d'une configuration optimale sans vous casser la tête ? Essayez Ailog - paramètres pré-optimisés par cas d'usage, ajustement adaptatif inclus.
FAQ
Tags
Verwandte Artikel
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-Agenten: Orchestrierung von Multi-Agenten-Systemen
Konzipieren Sie RAG-basierte Multi-Agenten-Systeme: Orchestrierung, Spezialisierung, Zusammenarbeit und Fehlerbehandlung für komplexe Assistenten.
Konversationelles RAG: Gedächtnis und Kontext über mehrere Sitzungen
Implementieren Sie ein RAG mit konversationellem Gedächtnis: Verwaltung des Kontexts, Verlauf über mehrere Sitzungen und Personalisierung der Antworten.