Doğal Dil Veritabanı Arayüzü Oluşturma
Kullanıcıların günlük İngilizceyle soru sorduğu, modelin işlev çağrılarıyla SQL oluşturduğu, uygulamanızın sorguyu güvenli biçimde çalıştırdığı ve modelin sonuçları açıkladığı bir sistem oluşturun.
Doğal Dil Veritabanı Arayüzü Oluşturma, CoddyKit'te ücretsiz bir AI Engineering Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Engineering Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Engineering Academy kursu toplamda 4 dersten oluşur.
Doğal Dilden SQL'e: Vizyon
Veritabanınıza "Geçen ay 1.000 dolardan fazla harcayan müşteriler hangileri?" diye sorduğunuzu ve tek bir SQL sorgusu yazmadan yanıt aldığınızı düşünün. Doğal dil veritabanı arayüzü, LLM'in SQL oluşturmasını sağlamak için işlev çağrımını kullanır; uygulamanız bu sorguyu güvenli bir şekilde yürütür ve model sonuçları düz İngilizceyle açıklar. Bu yaklaşım, teknik bilgisi olmayan kullanıcıların verilere erişimini kolaylaştırır.
Sistem Mimarısine Genel Bakış
NL'den SQL'e işlem hattı birlikte çalışan dört bileşenden oluşur:
- Şema bağlamı: LLM, hangi tabloların ve sütunların mevcut olduğunu bilmesi için veritabanı şemanızı alır.
- SQL oluşturma: Model, bir işlev çağrısı bağımsız değişkeni olarak SQL sorgusu oluşturur.
- Güvenli yürütme: Uygulamanız sorguyu doğrular ve çalıştırır, ardından sonuçları döndürür.
- Sonuçların açıklanması: Model, sorgu sonuçlarını alır ve bunları doğal dille açıklar.
Sorgu Veritabanı Aracını Tanımlama
Bir SQL SELECT ifadesi kabul eden query_database işlevi tanımlayın. İşlev tanımındaki şema açıklaması, modele hangi tabloların ve sütunların kullanılabilir olduğunu öğretir; böylece model tahminde bulunmadan doğru sorgular oluşturur.
query_db_tool = {
'type': 'function',
'function': {
'name': 'query_database',
'description': '''Execute a read-only SQL query on the company database.
Use this to answer questions about customers, orders, and products.
Only SELECT statements are allowed. Never use DROP, DELETE, UPDATE, or INSERT.
Available tables:
- customers (id, name, email, created_at, country)
- orders (id, customer_id, total_amount, status, created_at)
- order_items (id, order_id, product_id, quantity, unit_price)
- products (id, name, category, price, stock_quantity)
''',
'parameters': {
'type': 'object',
'properties': {
'sql': {
'type': 'string',
'description': 'A valid PostgreSQL SELECT statement.'
},
'explanation': {
'type': 'string',
'description': 'One-sentence explanation of what this query does.'
}
},
'required': ['sql', 'explanation']
}
}
}Güvenli SQL Yürütme
Modelden gelen ham SQL'i doğrulama yapmadan asla yürütmeyin. Şunları yapan bir güvenlik katmanı uygulayın: yalnızca SELECT ifadelerine izin verin, tehlikeli anahtar sözcükleri reddedin, bellek sorunlarını önlemek için sonuç satırlarını sınırlayın ve salt okunur bir veritabanı işlemi içinde çalıştırın. LLM tarafından oluşturulan kodu yürütürken savunmayı derinlemesine yapılandırmak kritik öneme sahiptir.
import re
import psycopg2
DANGEROUS_KEYWORDS = ['DROP', 'DELETE', 'UPDATE', 'INSERT', 'TRUNCATE', 'ALTER', 'CREATE', 'EXEC']
def execute_safe_query(sql: str, max_rows: int = 100) -> list:
'''Execute a read-only SQL query with safety guards.'''
sql_upper = sql.upper().strip()
# Only allow SELECT
if not sql_upper.startswith('SELECT'):
raise ValueError('Only SELECT statements are allowed.')
# Block dangerous keywords
for keyword in DANGEROUS_KEYWORDS:
if re.search(r'\b' + keyword + r'\b', sql_upper):
raise ValueError(f'Forbidden keyword: {keyword}')
conn = psycopg2.connect('postgresql://readonly_user:pass@localhost/appdb')
with conn:
with conn.cursor() as cur:
# Enforce read-only transaction
cur.execute('SET TRANSACTION READ ONLY')
cur.execute(sql)
columns = [desc[0] for desc in cur.description]
rows = cur.fetchmany(max_rows)
return [dict(zip(columns, row)) for row in rows]Şema Bağlamını Sistem İstemine Ekleme
Model, veritabanının tam şemasını görebildiğinde daha iyi SQL oluşturur. Tablo tanımlarını, sütun adlarını ve türlerini, ayrıca kategorik sütunlar için örnek değerleri içeren bir sistem istemi oluşturun. Bu sayede model, tahminde bulunmadan country = 'US' veya country_code = 'US' kullanması gerektiğini bilir.
SYSTEM_PROMPT = '''You are a data analyst assistant with access to the company database.
When users ask data questions, use the query_database tool to look up the answer.
Always explain your query in plain English before executing it.
Database schema:
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
email VARCHAR UNIQUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
country VARCHAR(2) -- ISO 2-letter code: 'US', 'UK', 'DE', etc.
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INTEGER REFERENCES customers(id),
total_amount NUMERIC(10,2),
status VARCHAR -- 'pending', 'shipped', 'delivered', 'cancelled'
created_at TIMESTAMPTZ DEFAULT NOW()
);
Only use columns that exist in the schema above.
'''Sorgu Sonuçlarını Model İçin Biçimlendirme
Ham veritabanı sonuçlarının (sözlük listelerinin), modele geri gönderilmeden önce okunabilir metin olarak biçimlendirilmesi gerekir. Sonuç kümesini, modelin yanıtı açıklarken başvurabileceği kısa bir gösterime — tabloya veya JSON özetine — dönüştürün. Binlerce satır göndermekten kaçının; büyük sonuç kümelerini özetleyin.
import json
def format_results(rows: list, max_display: int = 20) -> str:
if not rows:
return 'The query returned no results.'
total = len(rows)
display = rows[:max_display]
# Format as a simple table
if display:
columns = list(display[0].keys())
lines = [' | '.join(columns)]
lines.append('-' * len(lines[0]))
for row in display:
lines.append(' | '.join(str(row[col]) for col in columns))
result = '\n'.join(lines)
if total > max_display:
result += f'\n... ({total - max_display} more rows not shown)'
return resultİşlem Hattının Tam Uygulaması
Her şeyi bir araya getirdiğinizde: bir kullanıcı sorusunu işleyen, SQL oluşturmak için modeli çağıran, sorguyu güvenli biçimde yürüten ve sonuçları açıklama için geri besleyen işlev. Model hem özgün soruyu hem de sorgu sonuçlarını alır, ardından düz İngilizceyle bir yanıt üretir.
from openai import OpenAI
import json
client = OpenAI()
def answer_data_question(user_question: str) -> str:
messages = [
{'role': 'system', 'content': SYSTEM_PROMPT},
{'role': 'user', 'content': user_question}
]
# First call: get SQL from model
resp = client.chat.completions.create(
model='gpt-4o', messages=messages, tools=[query_db_tool]
)
assistant_msg = resp.choices[0].message
messages.append(assistant_msg)
if resp.choices[0].finish_reason == 'tool_calls':
tc = assistant_msg.tool_calls[0]
args = json.loads(tc.function.arguments)
print(f'Executing: {args["explanation"]}')
print(f'SQL: {args["sql"]}')
try:
rows = execute_safe_query(args['sql'])
result_text = format_results(rows)
except ValueError as e:
result_text = f'Query blocked: {str(e)}'
messages.append({'role': 'tool', 'tool_call_id': tc.id, 'content': result_text})
# Second call: narrate results
final = client.chat.completions.create(model='gpt-4o', messages=messages)
return final.choices[0].message.content
return assistant_msg.contentBirden Çok Aşamalı Veri Sorularını Ele Alma
Karmaşık sorular birden çok sorgu gerektirebilir. "Gelire göre en iyi 5 müşterimiz kimler ve en son siparişleri neler?" sorusu iki sorgu gerektirir: ilki en iyi müşterileri bulur, ikincisi onların siparişlerini alır. finish_reason='stop' olana kadar dağıtım döngüsünü birden çok kez çalıştırarak modelin birden çok sıralı araç çağrısı yapmasına izin verin.
def answer_complex_question(user_question: str) -> str:
messages = [
{'role': 'system', 'content': SYSTEM_PROMPT},
{'role': 'user', 'content': user_question}
]
for _ in range(5): # Max 5 query rounds
resp = client.chat.completions.create(
model='gpt-4o', messages=messages, tools=[query_db_tool]
)
msg = resp.choices[0].message
messages.append(msg)
if resp.choices[0].finish_reason == 'stop':
return msg.content # Model is done
# Process tool call and loop
tc = msg.tool_calls[0]
args = json.loads(tc.function.arguments)
try:
rows = execute_safe_query(args['sql'])
result = format_results(rows)
except Exception as e:
result = f'Error: {str(e)}'
messages.append({'role': 'tool', 'tool_call_id': tc.id, 'content': result})
return 'Could not complete the analysis within the step limit.'SQL Enjeksiyonu Risklerini Önleme
Yalnızca SELECT koruması olsa bile, kötü niyetli bir model (veya saldırgan bir kullanıcı) alt sorgular ya da yorum tabanlı hileler aracılığıyla veri dışarı aktarmaya çalışabilir. Ek korumalar şunları içerir: yalnızca SELECT iznine sahip salt okunur bir veritabanı kullanıcısı kullanmak, ayrı bir bağlantı havuzunda çalıştırmak ve sorgudaki tablo adlarının şema izin listenizle eşleştiğini doğrulamak.
ALLOWED_TABLES = {'customers', 'orders', 'order_items', 'products'}
def validate_tables_in_sql(sql: str) -> bool:
'''Check that only whitelisted tables are referenced in the query.'''
import sqlparse
parsed = sqlparse.parse(sql)[0]
table_names = set()
from_seen = False
for token in parsed.flatten():
if token.ttype is sqlparse.tokens.Keyword and token.value.upper() in ('FROM', 'JOIN'):
from_seen = True
elif from_seen and token.ttype is sqlparse.tokens.Name:
table_names.add(token.value.lower())
from_seen = False
unknown = table_names - ALLOWED_TABLES
if unknown:
raise ValueError(f'References unknown tables: {unknown}')
return TrueYaygın Sorguları Önbelleğe Alma
Birçok iş sorusu aynı yanıtla tekrar tekrar sorulur: "Kaç müşterimiz var?" "Geçen ayki gelirimiz ne kadardı?" Bu sonuçları kısa bir TTL ile Redis'te önbelleğe alın. Sorguyu yürütmeden önce önbelleği kontrol edin; bu, veritabanı yükünü azaltır ve yaygın analitik sorulara verilen yanıtları hızlandırır.
import redis
import hashlib
import json
r = redis.Redis.from_url('redis://localhost:6379')
def cached_query(sql: str, ttl_seconds: int = 300) -> list:
cache_key = 'nl_query:' + hashlib.sha256(sql.encode()).hexdigest()
cached = r.get(cache_key)
if cached:
return json.loads(cached)
rows = execute_safe_query(sql)
r.setex(cache_key, ttl_seconds, json.dumps(rows, default=str))
return rowsSorguları Kullanıcılara Açıklama
Oluşturulan SQL sorgusunu doğal dildeki yanıtla birlikte göstererek kullanıcıların güvenini kazanın. Kullanıcılar "Bu sorguyu çalıştırdım: SELECT COUNT(*) FROM customers WHERE country = ?UK?" ifadesini gördüğünde yanıtın doğru olduğunu doğrulayabilir ve SQL kalıplarını öğrenebilir. Araç şemamızdaki explanation alanı bunun için idealdir.
Kısa Kontrol
Doğal dil veritabanı arayüzü oluşturma konusundaki anlayışınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: query_database araç şeması, modelin doğru SQL oluşturması için şema bağlamı ekler, güvenlik doğrulaması, yürütmeden önce SELECT olmayan ifadeleri ve tehlikeli anahtar sözcükleri engellemelidir ve model çağrılarından oluşan bir döngü, sıralı sorgular gerektiren çok aşamalı veri analizini mümkün kılar. Sırada, yapay zekâyı harici araçlara bağlamak için kullanılan açık standart olan Model Context Protocol'ü (MCP) inceleyeceğiz.
Sıkça Sorulan Sorular
“Doğal Dil Veritabanı Arayüzü Oluşturma” dersi ücretsiz mi?
Evet — “Doğal Dil Veritabanı Arayüzü Oluşturma” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Engineering Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Engineering Academy kursu toplamda 4 dersten oluşur.
“Doğal Dil Veritabanı Arayüzü Oluşturma” dersinde ne öğreneceğim?
Kullanıcıların günlük İngilizceyle soru sorduğu, modelin işlev çağrılarıyla SQL oluşturduğu, uygulamanızın sorguyu güvenli biçimde çalıştırdığı ve modelin sonuçları açıkladığı bir sistem oluşturun. AI Engineering Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
AI Engineering Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te AI Engineering Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Doğal Dil Veritabanı Arayüzü Oluşturma” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu AI Engineering Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her AI Engineering Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- API İçin İşlev Şemaları Tanımlama
- Uygulamanızda Araç Çağrılarını İşleme
- Paralel İşlev Çağrıları
- Doğal Dil Veritabanı Arayüzü Oluşturma