Dynamic Context Tuning: Intelligentere Kontextauflösung für Chatbots ohne LLM-Overhead


Bicycle

Das Problem mit "Dieses Produkt"

Multi-Turn Konversationen sind für Menschen selbstverständlich, für Chatbots jedoch überraschend kompliziert. Wenn ein Benutzer fragt "Wie lange ist die Garantie auf dieses Produkt?" nachdem ein bestimmter Artikel besprochen wurde, erwartet er, dass der Chatbot weiß, worauf sich "dieses Produkt" bezieht. Dieses linguistische Phänomen nennt sich Anapher, und die korrekte Auflösung ist entscheidend für einen natürlichen Gesprächsfluss.

Die traditionelle Lösung nutzt ein LLM zum Umschreiben der Anfrage: Man sendet den Konversationsverlauf und bittet GPT-4 oder ähnliche Modelle, "dieses Produkt" in den tatsächlichen Produktnamen zu expandieren. Das funktioniert, hat aber Nachteile: 50-200ms Latenz pro Anfrage, nicht-deterministische Ausgaben und zusätzliche API-Kosten.

Dynamic Context Tuning (DCT) löst dieses Problem mit Embeddings statt LLM-Aufrufen.

Was ist Dynamic Context Tuning?

DCT ist ein embedding-basierter Ansatz, der einen Session-bezogenen Entity-Cache mit semantischen Embeddings pflegt. Anstatt ein LLM zu fragen "was meint der Benutzer mit 'dieses Produkt'?", macht DCT folgendes:

  1. Verfolgt Entitäten (Produktnamen, Services, Orte, etc.), die in der Konversation erwähnt werden
  2. Erkennt anaphorische Referenzen durch Pattern-Matching
  3. Nutzt semantische Ähnlichkeit, um den wahrscheinlichsten Referenten zu finden
  4. Berücksichtigt Aktualität, sodass kürzliche Erwähnungen höher gewertet werden

Das Ergebnis: Sub-Millisekunden Kontextauflösung, die deterministisch und frei von API-Kosten ist.

Die DCT Scoring-Formel

Im Kern von DCT steht eine gewichtete Scoring-Formel, die semantische Relevanz mit Konversationsaktualität ausbalanciert:

Score(entity, query) = α × cosine_similarity(e, q) + (1-α) × recency(e)

Wobei:

  • α = 0.7 (70% Gewicht auf semantische Ähnlichkeit)
  • cosine_similarity = berechnet aus Sentence Embeddings
  • recency = 1 / (1 + alter_in_minuten) (exponentieller Abfall)

Ein praktisches Beispiel:

 1Cache enthält:
 21. "Premium Support Paket" (vor 2 Minuten erwähnt)
 32. "Basic Starter Plan" (vor 5 Minuten erwähnt)
 4
 5Benutzer fragt: "Was ist in diesem Paket enthalten?"
 6
 7Für "Premium Support Paket":
 8  - similarity = 0.72
 9  - recency = 1/(1+2) = 0.33
10  - score = 0.7 × 0.72 + 0.3 × 0.33 = 0.603
11
12Für "Basic Starter Plan":
13  - similarity = 0.58
14  - recency = 1/(1+5) = 0.17
15  - score = 0.7 × 0.58 + 0.3 × 0.17 = 0.457
16
17Gewinner: "Premium Support Paket" (0.603 > Schwellenwert 0.5)

Implementierung im Detail

Hier ist eine Kern-Implementierung des Entity-Caches mit Python und SentenceTransformers:

 1from dataclasses import dataclass, field
 2import time
 3import numpy as np
 4from sentence_transformers import SentenceTransformer
 5
 6@dataclass
 7class CachedEntity:
 8    """Entität, die in der Konversation erwähnt wurde."""
 9    name: str
10    embedding: np.ndarray
11    timestamp: float = field(default_factory=time.time)
12    entity_type: str = "product"
13
14    def recency_score(self) -> float:
15        """Aktualitäts-Score mit exponentiellem Abfall."""
16        age_minutes = (time.time() - self.timestamp) / 60.0
17        return 1.0 / (1.0 + age_minutes)
18
19
20class EntityCache:
21    """DCT-basierter Entity-Cache zur Auflösung anaphorischer Referenzen."""
22
23    def __init__(
24        self,
25        max_size: int = 15,
26        model_name: str = "paraphrase-multilingual-MiniLM-L12-v2",
27        similarity_weight: float = 0.7,
28    ):
29        self.max_size = max_size
30        self.similarity_weight = similarity_weight
31        self.recency_weight = 1.0 - similarity_weight
32        self.encoder = SentenceTransformer(model_name)
33        self._entities: list[CachedEntity] = []

Die Referenzauflösungsmethode bewertet alle gecachten Entitäten gegen die Benutzeranfrage:

 1def resolve_reference(self, query: str, threshold: float = 0.5) -> str | None:
 2    """Löst anaphorische Referenz in Anfrage zum tatsächlichen Entitätsnamen auf."""
 3    if not self._contains_reference(query) or not self._entities:
 4        return None
 5
 6    query_embedding = self.encoder.encode(query, convert_to_numpy=True)
 7    best_entity, best_score = None, -1.0
 8
 9    for entity in self._entities:
10        similarity = self._cosine_similarity(query_embedding, entity.embedding)
11        recency = entity.recency_score()
12        score = self.similarity_weight * similarity + self.recency_weight * recency
13
14        if score > best_score:
15            best_score = score
16            best_entity = entity
17
18    if best_entity and best_score >= threshold:
19        return best_entity.name
20    return None

Pattern-Matching erkennt Referenzen - diese Patterns können für die eigene Domäne und Sprachen angepasst werden:

1self._reference_patterns = [
2    r"\b(dieser|diese|dieses|den|dem)\s+(produkt|artikel|service|paket)\b",
3    r"\b(der|die|das)\s+(erste|zweite|dritte|letzte|vorherige)\b",
4    r"\b(this|that|the)\s+(product|item|service|package)\b",
5]

Automatische Entity-Extraktion

DCT kann automatisch Entitäten aus Chatbot-Antworten extrahieren, um den Cache zu befüllen:

 1def extract_and_cache_entities(self, text: str) -> None:
 2    """Extrahiert Entity-Namen aus Text und fügt sie zum Cache hinzu."""
 3    # Domain-spezifische Patterns - für den eigenen Use Case anpassen
 4    patterns = [
 5        r"Produkt:\s*([^\n,]+)",      # "Produkt: Name"
 6        r"Service:\s*([^\n,]+)",      # "Service: Name"
 7        r"\d+\.\s*\*\*([^*]+)\*\*",   # Markdown fett in Listen
 8        r"\"([A-Z][^\"]{4,})\"",      # Zitierte Eigennamen
 9    ]
10
11    for pattern in patterns:
12        matches = re.findall(pattern, text, re.IGNORECASE)
13        for match in matches:
14            entity_name = match.strip()
15            if len(entity_name) >= 5:
16                self.add_entity(name=entity_name, entity_type="product")

Performance-Vergleich

Die Performance-Gewinne sind signifikant:

MetrikDCTLokales LLMCloud LLM API
Latenz~15-60ms50-200ms50-100ms
Genauigkeit~73-85%~90%~95%
API-Kosten0€0€~0,08€/1K Anfragen
VorhersagbarJa*NeinNein

*DCT ist vorhersagbar, aber nicht vollständig deterministisch: Die Recency-Komponente ist zeitabhängig, sodass sich Scores ändern, wenn Entities altern. Anders als bei LLMs gibt es jedoch kein stochastisches Sampling - bei gleichem Cache-Zustand zum gleichen Zeitpunkt sind die Ergebnisse reproduzierbar.

Der Trade-off ist klar: DCT opfert etwas Genauigkeit für massive Latenzverbesserungen und vorhersagbares Verhalten. Für die meisten Chatbot-Anwendungsfälle, bei denen der Entity-Cache gut befüllt ist, reichen 73-85% Genauigkeit aus, und die 150-200ms Latenzersparnis summiert sich über Multi-Turn Konversationen.

Integrations-Architektur

So fügt sich DCT in eine typische RAG-Pipeline ein:

 1Benutzeranfrage: "Wie lange ist die Garantie auf dieses Produkt?"
 2 3[1] DCT Entity Cache Lookup (~15-60ms)
 4    └─ Erkennung: "dieses produkt" Pattern gefunden
 5    └─ Entitäten bewerten, besten Match finden
 6 7Angereichert: "Wie lange ist die Garantie auf Premium Support Paket?"
 8 9[2] RAG Pipeline (Vector Search + LLM)
10    └─ Query mit Embedding-Modell embedden
11    └─ Vektor-Datenbank durchsuchen
12    └─ Antwort mit LLM generieren
1314Antwort an Benutzer
1516[3] Entity-Extraktion & Caching
17    └─ Entity-Namen aus Antwort extrahieren
18    └─ Zum Entity-Cache für zukünftige Auflösung hinzufügen

Wichtige Konfigurationsparameter

Bei der Implementierung von DCT gibt es einige Stellschrauben, die das Verhalten maßgeblich beeinflussen:

Embedding-Modell: Die Wahl des Modells bestimmt Geschwindigkeit, Genauigkeit und Sprachunterstützung. Multilingual-Modelle wie paraphrase-multilingual-MiniLM-L12-v2 sind vielseitiger, während spezialisierte englische Modelle oft genauer sind.

Cache-Größe: Wie viele Entities pro Session gespeichert werden. Zu klein führt zu verpassten Referenzen, zu groß erhöht die Scoring-Zeit und kann irrelevante alte Entities matchen.

Similarity-Schwellenwert: Der Mindestscore, ab dem ein Match akzeptiert wird (typisch 0.4-0.6). Zu niedrig erzeugt False Positives, zu hoch verpasst legitime Referenzen.

Similarity-Gewichtung (α): Das Verhältnis zwischen semantischer Ähnlichkeit und Aktualität. Ein höheres α (z.B. 0.8) bevorzugt semantisch passende Entities, ein niedrigeres (z.B. 0.5) gewichtet kürzlich erwähnte Entities stärker.

Wann sollte DCT eingesetzt werden?

DCT funktioniert am besten wenn:

  • Sie einen begrenzten Satz von Entity-Typen haben (Produkte, Services, Orte)
  • Multi-Turn Konversationen häufig sind
  • Latenz für die Benutzererfahrung kritisch ist
  • Sie vorhersagbares, debugbares Verhalten wollen

LLM-basierte Anreicherung in Betracht ziehen wenn:

  • Anfragen komplexe Schlussfolgerungen jenseits einfacher Referenzauflösung erfordern
  • Sie sehr hohe Genauigkeit benötigen (>90%)
  • Entity-Typen unbegrenzt oder unvorhersehbar sind

Fazit

Dynamic Context Tuning bietet eine leichtgewichtige Alternative zur LLM-basierten Query-Anreicherung. Durch den Einsatz von Embeddings und einer einfachen Scoring-Formel lässt sich deutlich schnellere Kontextauflösung als mit LLM-basierten Ansätzen erreichen, bei gleichzeitig akzeptabler Genauigkeit. Der Großteil der Zeit entfällt auf das Query-Encoding (~15-50ms) - das eigentliche Cache-Scoring über alle Entities dauert weniger als eine Millisekunde. Der Ansatz ist besonders wertvoll für Produktions-Chatbots, bei denen Latenz und Vorhersagbarkeit wichtig sind.

Das zugrundeliegende Research Paper bietet zusätzliche Tiefe zu den theoretischen Grundlagen und Evaluations-Benchmarks.

Zurück Unsere Trainings entdecken

Wir sind für Sie da

Sie interessieren sich für unsere Trainings oder haben einfach eine Frage, die beantwortet werden muss? Sie können uns jederzeit kontaktieren! Wir werden unser Bestes tun, um alle Ihre Fragen zu beantworten.

Hier kontaktieren