در یک شرکت پخش مواد غذایی در مشهد، هر یکشنبه صبح صفی کوچک جلوی میز کارشناس دادهٔ شرکت تشکیل میشود. مدیر فروش میخواهد بداند کدام کد کالا در خراسان نسبت به ماه قبل افت داشته، مدیر مالی دنبال مشتریان با بدهی بالای نود روز است و مدیر انبار میخواهد بداند کدام اقلام در سه مرکز توزیع همزمان زیر نقطهٔ سفارش رفتهاند. جواب هر سه سوال، همین حالا داخل پایگاهدادهٔ شرکت نشسته است. مشکل این است که فاصلهٔ میان سوال و جواب، یک آدم است: کسی که باید بنشیند، جدولها را به یاد بیاورد، جوینها را درست ببندد و کوئری را بنویسد. آن آدم گلوگاه شده و خودش هم میداند.
وسوسهٔ اول این است که سوال را عیناً جلوی مدل بگذاریم و بگوییم «برای این سوال کوئری بنویس». مدل هم چیزی مینویسد که کاملاً شبیه کوئری است: کلیدواژهها سر جایشاناند، جوین دارد، فیلتر دارد. فقط نام یکی از ستونها در پایگاهدادهٔ شما آنطور نیست و رابطهٔ میان دو جدول از مسیر دیگری میگذرد. کوئری اجرا میشود، عددی برمیگرداند، و آن عدد غلط است. این بدترین حالت ممکن است، چون خطای بیصدا از خطای پرصدا گرانتر تمام میشود. کوکبوک رسمی آنتروپیک برای همین مسئله یک مسیر پلهپله دارد و این درس، همان مسیر است.
لیست مطالب
آنچه در این درس یاد میگیرید
- چرا نمایش درست ساختار پایگاهداده، مهمتر از هنر پرامپتنویسی است
- الگوی پرامپت پایه و قاعدهٔ برچسبگذاری خروجی برای استخراج مطمئن کوئری
- اثر واقعی مثالهای نمونه و زنجیرهٔ فکر روی نرخ موفقیت، با عدد
- وقتی پایگاهداده صدها جدول دارد: بازیابی هوشمند شِما بهجای چپاندن همهچیز در پرامپت
- حلقهٔ خودترمیم: برگرداندن پیام خطای پایگاهداده به مدل برای اصلاح کوئری
- چه چیزهایی جز نام ستون باید در زمینه بگذاری و کجا باید جلوی مدل را بگیری

نقطهٔ شروع، شِما است نه پرامپت
مدل، پایگاهدادهٔ شما را نمیشناسد؛ هر چیزی که دربارهٔ ساختار دادهها میداند باید همان لحظه در پرامپت به او داده شود. پس اولین قطعهٔ واقعی این سیستم، تابعی کوچک است که ساختار جدولها را از خودِ پایگاهداده میخواند و به متن تبدیل میکند؛ نه سندی دستی که شش ماه پیش نوشته شده و از آن موقع سه ستون به جدولها اضافه شده است. تفاوت این دو، تفاوت سیستمی است که با تغییر شِما خودش را بهروز میکند با سیستمی که بیسروصدا کهنه میشود.
def get_schema_info(db_path):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
schema_info = []
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()
for (table_name,) in tables:
cursor.execute(f"PRAGMA table_info({table_name})")
columns = cursor.fetchall()
table_info = f"Table: {table_name}\n"
table_info += "\n".join(f" - {col[1]} ({col[2]})" for col in columns)
schema_info.append(table_info)
conn.close()
return "\n\n".join(schema_info)
خروجی این تابع، یک متن ساده و خوانا است: نام جدول، و زیرش فهرست ستونها با نوعشان. همین سادگی عمدی است. هر چه نمایش شِما تمیزتر و یکدستتر باشد، مدل کمتر دچار حدسزدن میشود.
پرامپت پایه و قاعدهٔ برچسب
حالا شِما را داخل یک قالب میگذاریم. دو نکتهٔ این قالب بیش از بقیه اهمیت دارد. اول اینکه شِما و سوال هرکدام داخل برچسب مشخص خودشان قرار میگیرند تا مدل بداند مرز میان «اطلاعات زمینه» و «درخواست» کجاست. دوم اینکه از مدل میخواهیم خروجی را داخل برچسب بگذارد. این دومی ظاهر تشریفاتی دارد اما در عمل تفاوت میان سیستم قابل اتکا و سیستم شکننده است: استخراج کوئری از میان برچسب، یک خط کد ساده است و دیگر لازم نیست با عبارات باقاعده دنبال چیزی بگردی که شبیه کوئری است.
You are an AI assistant that converts natural language queries into SQL.
Given the following SQL database schema:
<schema>
{schema}
</schema>
Convert the following natural language query into SQL:
<query>
{query}
</query>
Provide only the SQL query in your response, enclosed within <sql> tags.
سوال کاربر میتواند فارسی باشد؛ چیزی که باید استاندارد بماند ساختار پرامپت و نام برچسبهاست.
مثال بده، بعد بخواه بلند فکر کند
گام بعدی، افزودن چند سوال بههمراه کوئری درستشان است. این نمونهها فقط آموزش نحو نیستند؛ عرف خانگی سازمان شما را منتقل میکنند — مثلاً اینکه همیشه با نام مستعار جدول کار میکنید یا تاریخ را به شکل خاصی فیلتر میکنید — بیآنکه لازم باشد در قالب توضیحش بدهی.
تا اینجا مقدمه بود. ادامهٔ این درس — تمرینها، فایلهای همراه و بخش اصلی — مخصوص اعضای «حرفهای» است.
از سوال فارسی تا کوئری SQL؛ چطور مدل را به گزارشگیر قابلاعتماد پایگاهداده تبدیل کنیم
این بخش جزو محتوای «عضویت حرفهای» است: دورهها، تمرینهای تعاملی و بستههای اختصاصی.
آشنایی با عضویت حرفهای