Mehrdeutige Datenbankfragen verarbeiten
Rückfragen, Schema-Disambiguierung und logisches Denken bei Joins über mehrere Tabellen.
Mehrdeutige Datenbankfragen verarbeiten ist eine kostenlose AI Agents-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Agents-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.
Das Mehrdeutigkeitsproblem bei NL-to-SQL
Natürliche Sprache ist grundsätzlich mehrdeutig. Wenn jemand fragt: „Zeigen Sie mir aktuelle Bestellungen“, stellt sich für einen Menschen die Frage: für wen? in welchem Zeitraum? wie sortiert?
Ein Agent, der stillschweigend Standardwerte annimmt, liefert Ergebnisse, die der Benutzer nicht erwartet hat. Ein guter Agent erkennt Mehrdeutigkeiten und stellt gezielte Rückfragen.
Arten von Mehrdeutigkeiten
Im Datenbankkontext gibt es vier häufige Kategorien mehrdeutiger Fragen:
- Zeitliche Mehrdeutigkeit: „aktuell“, „neueste“, „alt“, „dieses Jahr“
- Mehrdeutigkeit des Geltungsbereichs: „Top-Kunden“ – anhand welcher Kennzahl?
- Mehrdeutigkeit bei Tabellen: Mehrere Tabellen könnten die Frage beantworten
- Mehrdeutigkeit bei Filtern: „aktive Benutzer“ – was gilt als aktiv?
# Examples of each type
ambiguous_examples = {
'temporal': 'Show me recent orders', # last 7 days? 30 days? 1 year?
'scope': 'Who are the top customers?', # by revenue, order count, or recency?
'table': 'Show me user activity', # from users, sessions, or audit_log?
'filter': 'List all active products' # active = in_stock? not discontinued?
}
if __name__ == '__main__':
print('Types of ambiguous questions:')
for kind, example in ambiguous_examples.items():
print(f' {kind}: "{example}"')
Mehrdeutigkeiten mit dem LLM erkennen
Statt Regeln für Mehrdeutigkeiten fest zu codieren, lassen Sie das LLM Mehrdeutigkeiten erkennen. Geben Sie ihm das Schema und fragen Sie: Ist diese Frage klar genug, um eine eindeutige SQL-Abfrage zu generieren?
import json
AMBIGUITY_CHECK_PROMPT = '''You are a SQL assistant. Given a database schema and a user question,
determine if the question is clear enough to write a single correct SQL query.
Schema:
{schema}
Question: {question}
Respond with JSON:
- If clear: {{"ambiguous": false, "sql": "SELECT ..."}}
- If ambiguous: {{"ambiguous": true, "clarification": "What time range counts as recent?",
"options": ["Last 7 days", "Last 30 days", "Last 90 days"]}}
JSON:'''
def check_and_generate(question, schema):
response = llm_call(AMBIGUITY_CHECK_PROMPT.format(
schema=schema, question=question
))
return json.loads(response)Die Klärungsschleife
Wenn eine Mehrdeutigkeit erkannt wird, starten Sie eine Klärungsschleife: Stellen Sie dem Benutzer eine gezielte Frage, nehmen Sie seine Antwort entgegen und versuchen Sie anschließend erneut, mit dem erweiterten Kontext SQL zu generieren.
Beschränken Sie die Schleife auf 2 Klärungsrunden – zu viele Fragen frustrieren die Benutzer.
def nl_to_sql_with_clarification(user_question, schema, conn, ask_user_fn):
for attempt in range(2): # max 2 clarification rounds
result = check_and_generate(user_question, schema)
if not result.get('ambiguous'):
# Clear question — execute
rows = execute_query(conn, result['sql'])
return format_results(rows, user_question)
# Ambiguous — ask user
clarification = result['clarification']
options = result.get('options', [])
user_reply = ask_user_fn(clarification, options)
# Enrich the question with the answer
user_question = f'{user_question} ({clarification}: {user_reply})'
print(f'Enriched question: {user_question}')
# After 2 rounds, generate with best guess
return check_and_generate(user_question, schema)Zeitliche Auflösung von „aktuell“
Zeitangaben wie „aktuell“, „neueste“, „diese Woche“ und „neu“ kommen äußerst häufig vor. Entwickeln Sie einen speziellen Resolver für Zeitangaben, der mehrdeutige Begriffe auf Standardzeiträume abbildet, dem LLM aber weiterhin ermöglicht, bei geringer Sicherheit nachzufragen.
from datetime import datetime, timedelta
TEMPORAL_DEFAULTS = {
'recent': 7, # days
'latest': 1, # days
'new': 30,
'old': 365,
'this week': 7,
'this month': 30,
'this year': 365
}
def resolve_temporal(question):
lower = question.lower()
for term, days in TEMPORAL_DEFAULTS.items():
if term in lower:
since = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
return question + f" ('{term}' means since {since})"
return question
print(resolve_temporal('Show me recent orders'))
# Show me recent orders ('recent' means since 2024-05-22)Schema-Disambiguierung: Mehrere Tabellen
Wenn mehrere Tabellen eine Frage beantworten könnten, muss der Agent ermitteln, welche davon am geeignetsten ist. Beispielsweise könnte sich „Benutzeraktivität“ in sessions, audit_log oder user_events befinden.
TABLE_SEMANTIC_MAP = {
'user activity': ['sessions', 'user_events', 'audit_log'],
'purchases': ['orders', 'transactions', 'invoices'],
'product catalog': ['products', 'items', 'listings'],
'sign-ups': ['users', 'registrations', 'accounts']
}
def disambiguate_tables(question, schema_dict, ask_user_fn):
lower = question.lower()
for concept, tables in TABLE_SEMANTIC_MAP.items():
if concept in lower:
available = [t for t in tables if t in schema_dict]
if len(available) > 1:
chosen = ask_user_fn(
f"Which table should I query for '{concept}'?",
available
)
return question + f" (use the {chosen} table)"
return question
if __name__ == '__main__':
def ask_user_fn(prompt, options):
print(f'{prompt} -> choosing "{options[0]}" (demo default)')
return options[0]
demo_schema = {'sessions': [], 'transactions': [], 'orders': []}
resolved = disambiguate_tables('Show me user activity', demo_schema, ask_user_fn)
print('Resolved question:', resolved)
Umgang mit der Mehrdeutigkeit bei „Top N“
„Top-Kunden“, „beste Produkte“ und „aktivste Benutzer“ setzen voraus, dass bekannt ist, anhand welcher Kennzahl die Rangfolge bestimmt wird. Zeigen Sie dem Benutzer Optionen für die Kennzahl an, statt stillschweigend eine auszuwählen.
RANKING_AMBIGUITY_PROMPT = '''The question asks for a ranking but the metric is unclear.
Question: {question}
Table columns available: {columns}
List 2-3 reasonable ranking metrics as a JSON array of objects:
[{{"label": "By total revenue", "sql_expr": "SUM(total) DESC"}},
{{"label": "By order count", "sql_expr": "COUNT(*) DESC"}}]
JSON:'''
def resolve_ranking(question, columns, ask_user_fn):
import json
response = llm_call(RANKING_AMBIGUITY_PROMPT.format(
question=question, columns=columns
))
options = json.loads(response)
labels = [o['label'] for o in options]
chosen_label = ask_user_fn('How should I rank the results?', labels)
chosen = next(o for o in options if o['label'] == chosen_label)
return question + f" (rank by: {chosen['sql_expr']})", chosen['sql_expr']Intelligente Standardwerte anbieten
Den Benutzer jedes Mal zu fragen, kann störend sein. Ein intelligenterer Ansatz ist: Wählen Sie einen sinnvollen Standardwert, führen Sie die Abfrage aus und teilen Sie dem Benutzer mit, was Sie angenommen haben. Fügen Sie einen Hinweis hinzu wie: „Ich habe ‚aktuell‘ als die letzten 30 Tage interpretiert. Meinten Sie einen anderen Zeitraum?“
def nl_to_sql_with_assumptions(question, schema, conn):
# Resolve common ambiguities with defaults
enriched = resolve_temporal(question)
result = check_and_generate(enriched, schema)
if result.get('ambiguous'):
# Still ambiguous — pick default option
options = result.get('options', ['the most common interpretation'])
default = options[0]
enriched = enriched + f' ({result["clarification"]}: {default})'
result = check_and_generate(enriched, schema)
rows = execute_query(conn, result['sql'])
answer = format_results(rows, question)
# Append assumption note
if enriched != question:
assumption = enriched[len(question):].strip().strip('()')
answer += f'\n\n[Note: I assumed {assumption}]'
return answerMehrdeutigkeit auf Spaltenebene
Manchmal liegt die Mehrdeutigkeit auf Spaltenebene. „Zeigen Sie mir nach Datum sortierte Bestellungen“ – welches Datum ist gemeint? created_at, updated_at, shipped_at oder delivery_date?
Nehmen Sie Spaltenbeschreibungen in Ihre Schema-Injektion auf, um das LLM zu unterstützen und Mehrdeutigkeiten auf Spaltenebene zu reduzieren.
COLUMN_DESCRIPTIONS = {
('orders', 'created_at'): 'When the order was placed',
('orders', 'updated_at'): 'When the order was last modified',
('orders', 'shipped_at'): 'When the order was shipped to customer',
('orders', 'delivery_date'): 'Expected or actual delivery date'
}
def format_columns_with_descriptions(table, columns):
parts = []
for col in columns:
desc = COLUMN_DESCRIPTIONS.get((table, col['name']), '')
label = f"{col['name']} ({col['type']})"
if desc:
label += f' [{desc}]'
parts.append(label)
return ', '.join(parts)
if __name__ == '__main__':
demo_columns = [
{'name': 'created_at', 'type': 'timestamp'},
{'name': 'shipped_at', 'type': 'timestamp'},
{'name': 'total', 'type': 'float'},
]
print(format_columns_with_descriptions('orders', demo_columns))
Auflösungen von Mehrdeutigkeiten protokollieren
Verfolgen Sie, wie häufig jede Art von Mehrdeutigkeit auftritt und welche Standardwerte oder Klärungen gewählt wurden. Diese Daten helfen Ihnen, Standardwerte zu verbessern und die Anzahl der im Laufe der Zeit gestellten Fragen zu verringern.
import json
from datetime import datetime
ambiguity_log = []
def log_ambiguity(original_question, clarification, resolution, method):
ambiguity_log.append({
'timestamp': datetime.now().isoformat(),
'question': original_question,
'clarification': clarification,
'resolution': resolution,
'method': method # 'asked_user' | 'default' | 'llm_inferred'
})
# Periodically analyze to improve defaults
def analyze_ambiguity_log():
from collections import Counter
types = Counter(entry['clarification'] for entry in ambiguity_log)
print('Most common ambiguities:')
for q, count in types.most_common(5):
print(f' {count}x: {q}')
if __name__ == '__main__':
log_ambiguity('Show recent orders', 'temporal', 'last 30 days', 'default')
log_ambiguity('Show recent orders', 'temporal', 'last 7 days', 'asked_user')
log_ambiguity('Top customers', 'scope', 'by revenue', 'llm_inferred')
analyze_ambiguity_log()
Kontext in mehrstufigen Unterhaltungen
In einer Chatoberfläche liefern vorherige Gesprächsrunden Kontext. Wenn der Benutzer bereits gesagt hat: „Ich sehe mir Daten aus Q4 2024 an“, sollten spätere Fragen nach „aktuellen Bestellungen“ standardmäßig diesen Zeitraum verwenden – nicht fest codiert 30 Tage.
def nl_to_sql_with_context(question, schema, conn, conversation_history):
context_prompt = ''
if conversation_history:
context_prompt = 'Previous conversation context:\n'
for turn in conversation_history[-3:]: # last 3 turns
context_prompt += f"User: {turn['user']}\n"
if 'assumption' in turn:
context_prompt += f"Assumption made: {turn['assumption']}\n"
full_prompt = context_prompt + f'Current question: {question}'
result = check_and_generate(full_prompt, schema)
conversation_history.append({
'user': question,
'sql': result.get('sql', ''),
'assumption': result.get('assumption', '')
})
return resultWissensüberprüfung
Welche Strategie wird empfohlen, wenn ein NL-to-SQL-Agent eine zeitliche Mehrdeutigkeit erkennt, zum Beispiel bei „aktuellen Bestellungen“?
Zusammenfassung: Umgang mit mehrdeutigen Fragen
Mehrdeutigkeiten bei NL-to-SQL treten in vier Formen auf: zeitliche Mehrdeutigkeit, Mehrdeutigkeit des Geltungsbereichs, Mehrdeutigkeit bei Tabellen und Mehrdeutigkeit bei Filtern. Die besten Strategien kombinieren intelligente Standardwerte – etwa „aktuell“ automatisch als die letzten 30 Tage aufzulösen –, LLM-basierte Erkennung von Mehrdeutigkeiten und gezielte Rückfragen, wenn die Frage tatsächlich unklar ist.
Teilen Sie dem Benutzer immer Ihre Annahmen mit. Nutzen Sie den Gesprächsverlauf als Kontext und protokollieren Sie Auflösungen von Mehrdeutigkeiten, um Standardwerte im Laufe der Zeit zu verbessern.
Häufig gestellte Fragen
Ist die Lektion „Mehrdeutige Datenbankfragen verarbeiten“ kostenlos?
Ja — der vollständige Text von „Mehrdeutige Datenbankfragen verarbeiten“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Agents-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Mehrdeutige Datenbankfragen verarbeiten“?
Rückfragen, Schema-Disambiguierung und logisches Denken bei Joins über mehrere Tabellen. Du übst AI Agents mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um AI Agents zu starten?
Keine Vorkenntnisse erforderlich. AI Agents auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Mehrdeutige Datenbankfragen verarbeiten“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser AI Agents-Lektion Code schreiben und ausführen?
Ja. Jede AI Agents-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Funktionsweise von NL-to-SQL-Agenten
- Schemaverständnis und -injektion
- SQL-Queries generieren und validieren
- Mehrdeutige Datenbankfragen verarbeiten