0Pricing
AI Engineering Academy · Ders

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.content

Birden Ç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 True

Yaygı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 rows

Sorguları 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

  1. API İçin İşlev Şemaları Tanımlama
  2. Uygulamanızda Araç Çağrılarını İşleme
  3. Paralel İşlev Çağrıları
  4. Doğal Dil Veritabanı Arayüzü Oluşturma
← AI Engineering Academy Sayfasına Dön