AI Agents · Pelajaran

Cara Kerja Agen NL-to-SQL

Injeksi skema, pembuatan kueri, eksekusi, dan pemformatan hasil.

Pelajaran 1 dari 413 langkah

Cara Kerja Agen NL-to-SQL adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 1 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 Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Apa Itu Agen NL-ke-SQL

Agen Bahasa Alami ke SQL menerjemahkan pertanyaan bahasa sehari-hari menjadi kueri SQL, mengeksekusinya terhadap basis data, lalu mengembalikan jawaban yang mudah dipahami manusia.

Alih-alih menulis SELECT COUNT(*) FROM orders WHERE status='pending', pengguna cukup bertanya: "Berapa banyak pesanan tertunda yang kita miliki?"

Arsitektur Inti

Setiap agen NL-ke-SQL mengikuti alur yang sama:

  1. Penyisipan skema—sisipkan struktur basis data ke dalam prompt
  2. LLM menghasilkan SQL—model menghasilkan kueri
  3. Eksekusi—jalankan kueri terhadap basis data
  4. Memformat hasil—ubah baris menjadi teks yang mudah dibaca
  5. Mengembalikan jawaban—tanggapi pengguna
# High-level pipeline
def nl_to_sql_agent(user_question, db_connection):
    schema = get_schema(db_connection)
    sql = llm_generate_sql(user_question, schema)
    rows = execute_query(db_connection, sql)
    answer = format_results(rows, user_question)
    return answer

Penjelasan tentang Penyisipan Skema

LLM tidak memiliki pengetahuan tentang struktur basis data Anda. Anda harus menyisipkan skema ke dalam setiap prompt agar model mengetahui tabel dan kolom yang tersedia.

Deskripsi skema yang ringkas memberi tahu model: "Tabel orders memiliki kolom: id, user_id, status, total, created_at."

def build_schema_prompt(schema_info):
    lines = []
    for table in schema_info:
        cols = ', '.join(
            f"{c['name']} ({c['type']})"
            for c in table['columns']
        )
        lines.append(f"Table {table['name']}: {cols}")
    return '\n'.join(lines)

# Output:
# Table users: id (INT), email (VARCHAR), created_at (TIMESTAMP)
# Table orders: id (INT), user_id (INT), status (VARCHAR), total (FLOAT)

if __name__ == '__main__':
    demo_schema = [
        {'name': 'users', 'columns': [{'name': 'id', 'type': 'INT'}, {'name': 'email', 'type': 'VARCHAR'}]},
        {'name': 'orders', 'columns': [{'name': 'id', 'type': 'INT'}, {'name': 'user_id', 'type': 'INT'}]},
    ]
    print(build_schema_prompt(demo_schema))

Prompt untuk Pembuatan SQL oleh LLM

Prompt harus memberikan tiga hal kepada LLM: skema, pertanyaan, dan instruksi eksplisit untuk hanya mengembalikan SQL yang valid.

Penjelasan yang tegas tentang SELECT-only dan dialek SQL tujuan (PostgreSQL, MySQL, SQLite) sangat penting untuk keamanan dan ketepatan.

SYSTEM_PROMPT = '''You are a SQL expert. Given a database schema and a question,
generate a valid {dialect} SELECT query. Return ONLY the SQL query, no explanation.
Do not use INSERT, UPDATE, DELETE, or DROP.

Schema:
{schema}
'''

def llm_generate_sql(question, schema, dialect='PostgreSQL'):
    prompt = SYSTEM_PROMPT.format(schema=schema, dialect=dialect)
    response = client.chat.completions.create(
        model='gpt-4o',
        messages=[
            {'role': 'system', 'content': prompt},
            {'role': 'user', 'content': question}
        ]
    )
    return response.choices[0].message.content.strip()

Mengeksekusi SQL yang Dihasilkan

Setelah LLM mengembalikan SQL, jalankan SQL tersebut terhadap basis data yang sebenarnya. Gunakan kueri berparameter jika memungkinkan dan selalu tangkap pengecualian—LLM dapat menghasilkan SQL yang tidak valid.

Membungkus eksekusi dalam try/except memungkinkan Anda mencoba lagi dengan mengirimkan petunjuk kesalahan kembali kepada LLM.

import psycopg2

def execute_query(conn, sql):
    try:
        with conn.cursor() as cur:
            cur.execute(sql)
            columns = [desc[0] for desc in cur.description]
            rows = cur.fetchmany(100)  # limit rows
            return {'columns': columns, 'rows': rows}
    except psycopg2.Error as e:
        return {'error': str(e), 'sql': sql}

Memformat Hasil untuk Pengguna

Baris mentah dari basis data tidak mudah dipahami pengguna. Agen harus mengubahnya menjadi jawaban dalam bahasa alami.

Untuk kumpulan hasil yang kecil, kirimkan baris tersebut kembali kepada LLM untuk ditafsirkan. Untuk kumpulan yang besar, hitung statistik ringkasan terlebih dahulu.

def format_results(result, original_question):
    if 'error' in result:
        return f'Query failed: {result["error"]}'

    rows = result['rows']
    columns = result['columns']

    if not rows:
        return 'No results found.'

    # For simple counts/aggregates — just return the value
    if len(columns) == 1 and len(rows) == 1:
        return f'Result: {rows[0][0]}'

    # For multi-row results — summarize
    summary = f'Found {len(rows)} rows.\n'
    for row in rows[:5]:  # show first 5
        summary += ', '.join(f'{columns[i]}: {row[i]}' for i in range(len(columns))) + '\n'
    return summary

if __name__ == '__main__':
    demo_result = {'rows': [[42]], 'columns': ['count']}
    print(format_results(demo_result, 'How many users signed up?'))
    demo_result2 = {'rows': [], 'columns': ['id']}
    print(format_results(demo_result2, 'Any orders today?'))

Mengapa NL-ke-SQL Sulit: Ambiguitas

Ambiguitas adalah tantangan terbesar. Pertimbangkan pertanyaan: "Tampilkan pelanggan teratas kepada saya."

  • Teratas berdasarkan pendapatan, jumlah pesanan, atau kebaruan?
  • Bulan lalu atau sepanjang waktu?
  • 10 teratas atau 100 teratas?

Manusia memahami konteks, sedangkan LLM membuat asumsi. Agen memerlukan strategi untuk menangani atau memperjelas pertanyaan yang ambigu.

AMBIGUITY_PROMPT = '''If the question is ambiguous, respond with JSON:
{"needs_clarification": true, "question": "your clarifying question"}

If clear, respond with the SQL query directly.

User question: {question}
'''

def generate_or_clarify(question, schema):
    response = llm_call(AMBIGUITY_PROMPT.format(
        question=question, schema=schema
    ))
    if '"needs_clarification"' in response:
        import json
        return json.loads(response)
    return {'sql': response}

Mengapa NL-ke-SQL Sulit: Ukuran Skema

Basis data perusahaan dapat memiliki ratusan tabel dan ribuan kolom. Menyisipkan seluruh skema akan melampaui jendela konteks LLM.

Solusinya meliputi: pencarian skema (sematkan deskripsi tabel, lalu ambil yang relevan), penyaringan tabel (tanyakan terlebih dahulu kepada LLM tabel mana yang diperlukan), dan pemadatan skema (hilangkan kolom indeks dan audit).

# Two-phase approach for large schemas
def get_relevant_tables(question, all_tables):
    prompt = f'''Given these tables: {all_tables}
Which 3-5 tables are most relevant to answer: "{question}"?
Return a JSON list of table names only.'''
    response = llm_call(prompt)
    import json
    return json.loads(response)

def nl_to_sql_large_db(question, conn):
    all_tables = list_all_tables(conn)  # just names
    relevant = get_relevant_tables(question, all_tables)
    schema = get_schema_for_tables(conn, relevant)
    return llm_generate_sql(question, schema)

Mengapa NL-ke-SQL Sulit: Perbedaan Dialek SQL

SQL tidak bersifat universal. LIMIT dalam PostgreSQL/MySQL menjadi TOP dalam SQL Server. Fungsi tanggal berbeda di setiap basis data. LLM harus mengetahui dialek yang harus digunakan.

Selalu sertakan dialek tujuan dalam prompt sistem dan pertimbangkan untuk menambahkan contoh khusus dialek dalam pemberian beberapa contoh.

DIALECT_EXAMPLES = {
    'postgresql': 'Use LIMIT for row limits. Use NOW() for current time.',
    'mysql': 'Use LIMIT for row limits. Use NOW() for current time.',
    'sqlite': 'Use LIMIT. Use datetime("now") for current time.',
    'mssql': 'Use TOP N for row limits. Use GETDATE() for current time.',
    'bigquery': 'Use LIMIT. Use CURRENT_TIMESTAMP() for current time. Use backtick for table names.'
}

def get_dialect_hint(dialect):
    return DIALECT_EXAMPLES.get(dialect.lower(), '')

if __name__ == '__main__':
    for dialect in ['postgresql', 'sqlite', 'mssql']:
        print(f'{dialect}: {get_dialect_hint(dialect)}')

Siklus Pemulihan Kesalahan

SQL yang dihasilkan sering gagal pada percobaan pertama. Agen yang tangguh menerapkan siklus pemulihan kesalahan: kirimkan SQL yang gagal dan pesan kesalahannya kembali kepada LLM, lalu minta LLM memperbaiki kueri tersebut.

Batasi percobaan ulang hingga 2–3 kali untuk menghindari siklus tanpa akhir pada kueri yang tidak dapat diperbaiki.

def nl_to_sql_with_retry(question, schema, conn, max_retries=3):
    sql = llm_generate_sql(question, schema)
    for attempt in range(max_retries):
        result = execute_query(conn, sql)
        if 'error' not in result:
            return format_results(result, question)
        # Ask LLM to fix the error
        fix_prompt = f'The SQL query failed with error: {result["error"]}\n'\
                     f'Original SQL: {sql}\n'\
                     f'Please fix the SQL query.'
        sql = llm_call(fix_prompt)
        print(f'Retry {attempt + 1} with fixed SQL')
    return 'Could not generate a valid query after retries.'

Menggabungkan Semuanya

Agen NL-ke-SQL untuk produksi menggabungkan semua bagian: pengambilan skema, penyusunan prompt, pembuatan SQL, validasi, eksekusi, pemulihan kesalahan, dan pemformatan hasil.

Penambahan cache kueri (pertanyaan yang sama → SQL yang sama) secara signifikan mengurangi latensi dan biaya LLM untuk kueri yang berulang.

import hashlib

query_cache = {}

def cached_nl_to_sql(question, schema_hash, conn):
    cache_key = hashlib.md5((question + schema_hash).encode()).hexdigest()
    if cache_key in query_cache:
        print('Cache hit!')
        sql = query_cache[cache_key]
    else:
        schema = get_schema(conn)
        sql = llm_generate_sql(question, schema)
        query_cache[cache_key] = sql

    result = execute_query(conn, sql)
    return format_results(result, question)

Pemeriksaan Pengetahuan

Apa urutan langkah yang benar dalam alur agen NL-ke-SQL?

Ringkasan: Arsitektur NL-ke-SQL

Agen NL-ke-SQL mengubah pertanyaan dalam bahasa alami menjadi kueri SQL yang dapat dieksekusi melalui alur terstruktur: sisipkan skema → hasilkan SQL → eksekusi → format → kembalikan.

Tantangan utamanya adalah ambiguitas dalam pertanyaan pengguna, ukuran skema yang besar hingga melampaui jendela konteks, serta perbedaan dialek SQL di berbagai basis data. Siklus pemulihan kesalahan menangani SQL yang dihasilkan LLM dan gagal saat eksekusi pertama.

Gratis untuk memulai

Belajar AI Agents 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
60
Pelajaran
239

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Cara Kerja Agen NL-to-SQL” gratis?

Ya — teks lengkap “Cara Kerja Agen NL-to-SQL” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Cara Kerja Agen NL-to-SQL”?

Injeksi skema, pembuatan kueri, eksekusi, dan pemformatan hasil. Kamu berlatih AI Agents 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 Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents 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 1 dari 4.

Berapa lama pelajaran “Cara Kerja Agen NL-to-SQL” 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 Agents ini?

Ya. Setiap pelajaran AI Agents 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. Cara Kerja Agen NL-to-SQL
  2. Memahami dan Menyisipkan Skema
  3. Membuat dan Memvalidasi Kueri SQL
  4. Menangani Pertanyaan Basis Data yang Ambigu
← Kembali ke AI Agents