AI Engineering Academy · Pelajaran

Membangun Antarmuka Basis Data Bahasa Alami

Buat sistem yang memungkinkan pengguna mengajukan pertanyaan dalam bahasa Inggris sehari-hari, model menghasilkan SQL melalui pemanggilan fungsi, aplikasi Anda menjalankan kueri dengan aman, dan model menjelaskan hasilnya.

Pelajaran 4 dari 413 langkah

Membangun Antarmuka Basis Data Bahasa Alami adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Bahasa Alami ke SQL: Visinya

Bayangkan Anda menanyakan kepada basis data, "Pelanggan mana yang membelanjakan lebih dari $1.000 bulan lalu?", lalu mendapatkan jawabannya—tanpa menulis satu pun kueri SQL. Antarmuka basis data bahasa alami menggunakan pemanggilan fungsi agar LLM menghasilkan SQL, aplikasi Anda mengeksekusinya dengan aman, dan model menjelaskan hasilnya dalam bahasa Inggris biasa. Pola ini membuat akses data dapat digunakan oleh pengguna nonteknis.

Ikhtisar Arsitektur Sistem

pipeline NL-ke-SQL memiliki empat komponen yang bekerja bersama:

  • Konteks skema: LLM menerima skema basis data Anda sehingga mengetahui tabel dan kolom yang tersedia.
  • Pembuatan SQL: Model menghasilkan kueri SQL sebagai argumen pemanggilan fungsi.
  • Eksekusi aman: Aplikasi Anda memvalidasi dan menjalankan kueri, lalu mengembalikan hasilnya.
  • Penjelasan hasil: Model menerima hasil kueri dan menjelaskannya dalam bahasa alami.

Mendefinisikan Alat Basis Data Kueri

Definisikan fungsi query_database yang menerima pernyataan SQL SELECT. Deskripsi skema dalam definisi fungsi mengajarkan model tabel dan kolom yang tersedia, sehingga model dapat menghasilkan kueri yang akurat tanpa menebak.

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']
        }
    }
}

Eksekusi SQL yang Aman

Jangan pernah mengeksekusi SQL mentah dari model tanpa validasi. Terapkan lapisan keamanan yang: hanya mengizinkan pernyataan SELECT, menolak kata kunci berbahaya, membatasi baris hasil untuk mencegah masalah memori, dan menjalankan kueri dalam transaksi basis data hanya-baca. Pertahanan berlapis sangat penting saat mengeksekusi kode yang dihasilkan LLM.

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]

Menyisipkan Konteks Skema ke dalam Perintah Sistem

Model menghasilkan SQL yang lebih baik jika dapat melihat skema basis data lengkap. Buat perintah sistem yang menyertakan definisi tabel, nama dan tipe kolom, serta contoh nilai untuk kolom kategoris. Dengan begitu, model dapat mengetahui apakah harus menggunakan country = 'US' atau country_code = 'US' tanpa menebak.

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

Memformat Hasil Kueri untuk Model

Hasil mentah basis data (daftar kamus) perlu diformat menjadi teks yang mudah dibaca sebelum dikirim kembali ke model. Ubah kumpulan hasil menjadi representasi ringkas—tabel atau ringkasan JSON—yang dapat dirujuk model saat menjelaskan jawaban. Hindari mengirim ribuan baris; ringkas kumpulan hasil yang besar.

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

Implementasi pipeline Lengkap

Menggabungkan semuanya: fungsi yang memproses pertanyaan pengguna, memanggil model untuk menghasilkan SQL, mengeksekusi kueri dengan aman, dan mengirimkan hasilnya kembali untuk dijelaskan. Model menerima pertanyaan asli serta hasil kueri, lalu menghasilkan jawaban dalam bahasa Inggris biasa.

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

Menangani Pertanyaan Data Multi-Langkah

Pertanyaan kompleks mungkin memerlukan beberapa kueri. "Siapa 5 pelanggan teratas kita berdasarkan pendapatan, dan apa pesanan terbaru mereka?" memerlukan dua kueri: satu untuk menemukan pelanggan teratas, lalu satu lagi untuk mendapatkan pesanan mereka. Izinkan model mengeluarkan beberapa pemanggilan alat berurutan dengan menjalankan loop pengiriman beberapa kali hingga finish_reason='stop'.

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

Mencegah Risiko Injeksi SQL

Bahkan dengan penjaga khusus SELECT, model yang cerdik (atau pengguna jahat) dapat mencoba mengekfiltrasi data melalui subkueri atau trik berbasis komentar. Perlindungan tambahan meliputi: menggunakan pengguna basis data hanya-baca yang hanya memiliki izin SELECT, menjalankan kueri dalam kumpulan koneksi terpisah, dan memvalidasi bahwa nama tabel dalam kueri sesuai dengan daftar putih skema Anda.

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

Menyimpan Kueri Umum dalam Tembolok

Banyak pertanyaan bisnis diajukan berulang kali dengan jawaban yang sama: "Berapa jumlah pelanggan kita?" "Berapa pendapatan bulan lalu?" Simpan hasil ini dalam Redis dengan TTL singkat. Periksa tembolok sebelum mengeksekusi kueri—ini mengurangi beban basis data dan mempercepat respons untuk pertanyaan analitis yang umum.

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

Menjelaskan Kueri kepada Pengguna

Bangun kepercayaan dengan menampilkan kueri SQL yang dihasilkan bersama jawaban dalam bahasa alami. Saat pengguna dapat melihat "Saya menjalankan kueri ini: SELECT COUNT(*) FROM customers WHERE country = ?UK?", mereka dapat memverifikasi bahwa jawabannya benar dan mempelajari pola SQL. Kolom explanation dalam skema alat kita sangat cocok untuk ini.

Pemeriksaan Cepat

Uji pemahaman Anda tentang cara membangun antarmuka basis data bahasa alami.

Rangkuman Pelajaran

Dalam pelajaran ini Anda telah mempelajari: skema alat query_database menyisipkan konteks skema agar model menghasilkan SQL yang akurat, validasi keamanan harus memblokir pernyataan selain SELECT dan kata kunci berbahaya sebelum eksekusi, dan loop pemanggilan model memungkinkan analisis data multi-langkah yang memerlukan kueri berurutan. Selanjutnya kita akan mempelajari Model Context Protocol (MCP), standar terbuka untuk menghubungkan AI ke alat eksternal.

Gratis untuk memulai

Belajar Python dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
30
Pelajaran
120

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Membangun Antarmuka Basis Data Bahasa Alami” gratis?

Ya — teks lengkap “Membangun Antarmuka Basis Data Bahasa Alami” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Membangun Antarmuka Basis Data Bahasa Alami”?

Buat sistem yang memungkinkan pengguna mengajukan pertanyaan dalam bahasa Inggris sehari-hari, model menghasilkan SQL melalui pemanggilan fungsi, aplikasi Anda menjalankan kueri dengan aman, dan mode… Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?

Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Membangun Antarmuka Basis Data Bahasa Alami” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mendefinisikan Skema Fungsi untuk API
  2. Memproses Pemanggilan Alat di Aplikasi Anda
  3. Pemanggilan Fungsi secara Paralel
  4. Membangun Antarmuka Basis Data Bahasa Alami
← Kembali ke AI Engineering Academy