رضا مسئول قیمتگذاری یک فروشگاه لوازم خانگی در اصفهان است. عصر پنجشنبه فهرست تخفیف عید را به دستیار هوش مصنوعی میدهد و مینویسد: «قیمت هر کالا را با ۱۸ درصد تخفیف حساب کن، بعد ۹ درصد مالیات را روی مبلغ نهایی اضافه کن و جمع کل سبد را بگو.» جواب در سه ثانیه میآید؛ مرتب، جدولبندیشده و کاملاً قانعکننده. رضا فردا صبح میفهمد جمع کل، هفتصد هزار تومان کمتر از عدد واقعی بوده است.
نکتهٔ آزاردهنده اینجاست که مدل «نمیدانست» اشتباه میکند. مدل زبانی عدد را حساب نمیکند؛ محتملترین ادامهٔ متن را مینویسد. برای «دو بهعلاوهٔ دو» محتملترین ادامه اتفاقاً درست است، اما برای ضرب هفترقمی در ۱٫۰۹ دیگر نه. راهحل رسمی آنتروپیک هم پیچیده نیست: به مدل ماشینحساب بدهید. کوکبوک آنتروپیک اولین درس ابزارها را دقیقاً با همین مثال شروع میکند، چون ماشینحساب سادهترین ابزاری است که کل مکانیزم «استفاده از ابزار» را لو میدهد.
لیست مطالب
آنچه در این درس یاد میگیرید
- چرا مدل زبانی در حساب کردن ضعیف است و چرا این ضعف با مدل بهتر حل نمیشود.
- ساختار دقیق تعریف یک ابزار: نام، توضیح و شِمای ورودی — و اینکه کدامشان مهمتر از بقیه است.
- چرخهٔ چهارمرحلهای ابزار: درخواست مدل، اجرای شما، بازگرداندن نتیجه، پاسخ نهایی.
- نقش
tool_use_idو اینکه چرا بدون آن همهچیز بههم میریزد. - خطر امنیتی
evalدر نمونهٔ رسمی و جایگزین امن آن. - کد کامل و آمادهٔ کپی یک ابزار ماشینحساب بههمراه حلقهٔ گفتوگو.
- اینکه همین منطق، پایهٔ هر ایجنتی است که بعداً میسازید.
چرا مدل حساب بلد نیست
مدل زبانی روی نویسهها و توکنها کار میکند، نه روی مقدار عددی. وقتی مینویسید ۴۸۷۳۹۱ × ۱٫۰۹، مدل الگویی از ارقام دیده که شبیه این است، و چیزی مینویسد که شکلِ جواب درست را دارد. این با اشتباه انسانی فرق دارد: انسان میداند که دارد حساب میکند و میتواند شک کند؛ مدل حتی نمیداند وارد یک محاسبه شده است. برای همین اضافهکردن جملهٔ «دقت کن» یا «مرحلهبهمرحله حساب کن» فقط احتمال درستی را بالا میبرد، آن را تضمین نمیکند.
راهحل، عوضکردن جنس کار است. کاری که ماشین در آن بینقص است — حساب کردن — به ماشین سپرده میشود، و کاری که مدل در آن خوب است — فهمیدن اینکه چه چیزی باید حساب شود — نزد مدل میماند. این تقسیم کار، تعریفِ «ابزار» است.
یک ابزار از چه ساخته شده است
ابزار در واقع یک قرارداد سهتکه است که شما به مدل میدهید: مدل چه چیزی را میتواند صدا بزند، آن چیز چه کاری میکند، و با چه ورودیای باید صدا زده شود. تعریف رسمی ماشینحساب در کوکبوک آنتروپیک این است:
{
"name": "calculator",
"description": "A simple calculator that performs basic arithmetic operations.",
"input_schema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "The mathematical expression to evaluate (e.g., '2 + 3 * 4')."
}
},
"required": ["expression"]
}
}
مهمترین بخش این قرارداد، برخلاف تصور اولیه، name نیست؛ description است. مدل هیچ راهی برای دیدن کد شما ندارد و تنها چیزی که دربارهٔ توانایی ابزار میداند، همین یک جملهٔ انگلیسی است. اگر توضیح مبهم باشد، مدل یا ابزار را در جای اشتباه صدا میزند یا اصلاً صدایش نمیزند و باز خودش حساب میکند. همان قاعدهای که در درس بهترین تمرینهای پرامپتنویسی کلود دربارهٔ صراحت گفتیم، اینجا با شدت بیشتری صادق است.
تکهٔ سوم، input_schema، یک شِمای جِیسون است که ساختار ورودی را قفل میکند. بهجای اینکه امیدوار باشید مدل عبارت ریاضی را در قالبی که کدتان میفهمد بنویسد، صریحاً میگویید: یک شیء با کلید expression از جنس رشته، و این کلید اجباری است.
پیادهسازی ماشینحساب و تلهٔ امنیتی آن
سمت شما، ابزار فقط یک تابع معمولی است. نسخهٔ رسمی کوکبوک اینطور نوشته شده:
import re
def calculate(expression):
# هر نویسهای جز رقم و عملگر را دور بریز
expression = re.sub(r"[^0-9+\-*/().]", "", expression)
try:
result = eval(expression) # فقط برای نمایش؛ در محیط واقعی امن نیست
return str(result)
except (SyntaxError, ZeroDivisionError, NameError, TypeError, OverflowError):
return "Error: Invalid expression"
دو نکته را از این چند خط برندارید و رد نشوید. اول، خود آنتروپیک زیر همین کد هشدار داده است که eval صرفاً برای سادگیِ آموزش آمده و در محصول واقعی باید سراغ ast.literal_eval یا یک تجزیهگر ریاضی اختصاصی رفت؛ چون eval هر رشتهای را بهعنوان کد پایتون اجرا میکند و ورودیاش از سمت مدل میآید. آن خط re.sub که همهچیز جز ارقام و عملگرها را حذف میکند، یک لایهٔ دفاعی است، اما لایهٔ اول است نه آخر.
دوم، به بلوک except نگاه کنید: تابع در صورت خطا هم چیزی برمیگرداند و بالا نمیآید. این عمدی است. ابزاری که خطا میدهد باید پیام خطای قابلخواندن به مدل برگرداند تا مدل بتواند خودش را اصلاح کند — مثلاً عبارت را بازنویسی کند یا به کاربر بگوید تقسیم بر صفر ممکن نیست.
چرخهٔ گفتوگو؛ قلب ماجرا
بزرگترین سوءتفاهم تازهکارها این است که فکر میکنند مدل ابزار را «اجرا میکند». مدل هیچوقت هیچ کدی اجرا نمیکند. مدل فقط درخواست میدهد؛ اجراکننده شمایید. چرخه چهار مرحله دارد:
- پیام کاربر همراه با فهرست ابزارها به مدل میرود.
- مدل بهجای متن، پاسخی با
stop_reason: "tool_use"برمیگرداند که داخلش یک بلوکtool_useبا نام ابزار، ورودی و یک شناسهٔ یکتا هست. - شما تابع را با آن ورودی اجرا میکنید و نتیجه را میگیرید.
- نتیجه را در قالب بلوک
tool_result— بههمراه همان شناسه — دوباره به مدل میفرستید و مدل جواب نهایی را به زبان آدمیزاد مینویسد.
کد این حلقه در کوکبوک به این شکل است:
def process_tool_call(tool_name, tool_input):
if tool_name == "calculator":
return calculate(tool_input["expression"])
message = client.messages.create(
model=MODEL_NAME, max_tokens=4096,
messages=[{"role": "user", "content": user_message}],
tools=tools,
)
if message.stop_reason == "tool_use":
tool_use = next(b for b in message.content if b.type == "tool_use")
tool_result = process_tool_call(tool_use.name, tool_use.input)
response = client.messages.create(
model=MODEL_NAME, max_tokens=4096,
messages=[
{"role": "user", "content": user_message},
{"role": "assistant", "content": message.content},
{"role": "user", "content": [{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": tool_result,
}]},
],
tools=tools,
)
else:
response = message
دو جزئیات ریز اما حیاتی در این کد پنهان است. یکی اینکه پاسخ قبلی مدل، یعنی message.content، عیناً بهعنوان پیام assistant در تاریخچه گذاشته میشود؛ اگر آن را حذف کنید یا خلاصهاش کنید، مدل نمیداند نتیجهای که فرستادهاید پاسخ کدام درخواست است. دیگری tool_use_id است: وقتی مدل در یک نوبت سه ابزار را همزمان صدا میزند، تنها چیزی که نتیجهها را به درخواستها وصل میکند همین شناسه است.
در چرخهٔ استفاده از ابزار، پاسخ مدل با stop_reason برابر tool_use برمیگردد. در این لحظه دقیقاً چه اتفاقی افتاده است؟
اگر برنامهنویس نیستید
این درس در ظاهر برای توسعهدهندههاست، اما مفهومش برای همه به کار میآید. وقتی در چت هوش مصنوعی گزینهٔ اجرای کد یا جستجوی وب را روشن میکنید، دقیقاً همین چرخه پشت پرده اجرا میشود؛ فقط ابزارها را شرکت سازنده تعریف کرده است. فایدهٔ عملی دانستنش این است: از این به بعد میدانید برای پرسشهای عددی، مالی یا آماری باید ابزار محاسبه را فعال کنید و به متن خام مدل تکیه نکنید — و میدانید که اگر جواب عددی بدون فراخوانی ابزار آمد، باید به آن مشکوک باشید.
در سطح بعد، همین ماشینحساب سادهٔ تکمرحلهای، سلول بنیادی هر ایجنت است. ایجنت چیزی جز همین حلقه نیست که بهجای یک بار، در یک تکرار ادامهدار اجرا شود و بهجای یک ابزار، به ده ابزار دسترسی داشته باشد. اگر میخواهید مسیر را کامل بروید، دورهٔ ایجنتنویسی همین منطق را تا ساخت یک عامل کامل جلو میبرد، و نقشهٔ راه مهندسی پرامپت ترتیب پیشنهادی آنتروپیک برای رسیدن به آنجا را نشان میدهد.
این تمرین ویژهٔ اعضاست
برای دیدن این بخش باید عضو ویژه (VIP) باشی. با شمارهٔ موبایلت وارد شو تا ۱۴ روز دسترسی رایگان فعال شود.
🎁 ورود / ثبتنام و شروع ۱۴ روز رایگانجمعبندی
سه جمله، خلاصهٔ کل درس است. اول، ضعف مدل در محاسبه یک نقص قابلرفع با پرامپت بهتر نیست؛ جنس کار اشتباه است و باید به ابزار سپرده شود. دوم، ابزار یعنی یک قرارداد سهتکه که مدل فقط توضیحش را میبیند، پس آن یک جمله را با وسواس بنویسید. سوم، مدل ابزار را صدا میزند اما اجرا نمیکند؛ حلقهٔ درخواست، اجرا، بازگرداندن نتیجه با شناسه، و پاسخ نهایی، ستون فقرات همهٔ ایجنتهاست. رضای اول این درس، اگر یک بار همین ماشینحساب را به دستیارش وصل کند، دیگر هیچوقت جمع سبد را دستی بازبینی نمیکند.
و چرا این تکنیک کهنه نمیشود؟ چون آنچه یاد گرفتیم به هیچ مدلی گره نخورده است. مدلها هر سال در محاسبه بهتر میشوند و شاید روزی ماشینحساب برای ضربهای ساده لازم نباشد، اما الگوی زیرین سر جایش میماند: هرجا کاری قطعیت میخواهد، آن را از دست مدل بگیرید و به کدی بدهید که همیشه یک جواب میدهد. این الگو فردا برای پایگاه داده، پرداخت و ارسال ایمیل تکرار میشود و شکلش دقیقاً همین چهار مرحله است. یادگیری میانبر ندارد؛ اما ابزار دارد.
منبع این درس، مستندات رسمی آنتروپیک است؛ ما آن را برای فارسیزبانها درس کردهایم.
