Prompt Engineering

پل زدن بر شکاف: تسلط بر فراخوانی تابع برای عامل‌های هوش مصنوعی آماده تولید

مدل‌های زبانی بزرگ (LLMs) نحوه تعامل ما با نرم‌افزارها را متحول کرده‌اند و پارادایم را از جستجوی کلمات کلیدی ایستا به استدلال پویا و آگاه از زمینه تغییر داده‌اند. با این حال، یک محدودیت اساسی همچنان پابرجاست: مدل‌های زبانی بزرگ اساساً موتورهای پیش‌بینی هستند، نه موتورهای اجرا. آن‌ها در یک محفظه ایزوله از متن وجود دارند و از داده‌های زنده و ابزارهای خارجی که برای انجام اقدامات دنیای واقعی لازم است، جدا هستند. اینجاست که فراخوانی تابع (که به استفاده از ابزار یا فراخوانی اقدام نیز معروف است) به عنوان پل ارتباطی حیاتی بین هوش مصنوعی گفتگومحور و کاربرد عملی ظاهر می‌شود.

برای توسعه‌دهندگان متوسط تا پیشرفته، درک فراخوانی تابع دیگر اختیاری نیست—بلکه برای ساخت عامل‌هایی که می‌توانند بلیط هواپیما رزرو کنند، پایگاه‌های داده را پرس‌وجو کنند یا دستگاه‌های اینترنت اشیاء (IoT) را کنترل کنند، ضروری است. این پست به بررسی مکانیک‌ها، استراتژی‌های پیاده‌سازی و بهترین شیوه‌ها برای یکپارچه‌سازی ابزارهای خارجی با مدل‌های زبانی بزرگ می‌پردازد.

معماری فراخوانی تابع

فراخوانی تابع یک حلقه ساختاریافته بین مدل و برنامه شما ایجاد می‌کند. به جای اینکه مدل زبانی بزرگ پاسخ نهایی را مستقیماً تولید کند، یک درخواست ساختاریافته (معمولاً به فرمت JSON) برای فراخوانی یک تابع خاص که در کد برنامه شما تعریف شده است، تولید می‌کند. سپس بک‌اند شما این تابع را اجرا می‌کند، نتیجه را بازیابی کرده و آن را به مدل زبانی بزرگ باز می‌گرداند تا یک پاسخ به زبان طبیعی فرمول‌بندی کند.

این معماری بر سه مؤلفه متکی است:

  1. تعاریف تابع: یک طرحواره (Schema) که ابزارهای موجود، آرگومان‌های آن‌ها و خروجی‌های مورد انتظار را توصیف می‌کند.
  2. مدل: تابع مناسب را انتخاب کرده و پارامترهای مرتبط را از پرس‌وجوی کاربر استخراج می‌کند.
  3. موتور اجرا: تابع انتخاب شده را اجرا می‌کند و نتیجه را به مدل باز می‌گرداند.

تعریف طرحواره ابزار

قبل از اینکه یک مدل زبانی بزرگ بتواند یک تابع را فراخوانی کند، باید بداند آن تابع چه کاری انجام می‌دهد و به چه داده‌هایی نیاز دارد. APIهای مدرن به شما اجازه می‌دهند تعاریف طرحواره JSON را برای ابزارهای خود ارائه دهید. دقت در اینجا حیاتی است؛ توصیف‌های مبهم منجر به آرگومان‌های توهمی یا فراخوانی‌های ناموفق می‌شود.

فرض کنید در سناریویی ساده، کاربر می‌خواهد وضعیت آب‌وهوا را بررسی کند. شما ابزار را به شرح زیر تعریف می‌کنید:

{
  "name": "get_weather",
  "description": "دریافت وضعیت فعلی آب‌وهوا در یک مکان مشخص.",
  "parameters": {
    "type": "object",
    "properties": {
      "location": {
        "type": "string",
        "description": "شهر و ایالت، مثلاً سن فرانسیسکو، کالیفرنیا"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"]
      }
    },
    "required": ["location"]
  }
}

با تعریف واضح فیلدهای required (الزامی) و ارائه محدودیت‌های enum، فضای خروجی مدل را محدود می‌کنید که احتمال خطا در مرحله پردازش بعدی را به طور قابل توجهی کاهش می‌دهد.

روند پیاده‌سازی

این تعامل یک فراخوانی API واحد نیست، بلکه یک فرآیند چندمرحله‌ای است. در اینجا یک جریان مفهومی با استفاده از نمایش کد شبه‌رایج در SDKهای اصلی مدل‌های زبانی بزرگ آورده شده است:

// 1. پرس‌وجوی اولیه کاربر
messages = [{"role": "user", "content": "وضعیت آب‌وهوا در لندن چگونه است؟"}]

// 2. پاسخ مدل زبانی بزرگ
response = client.chat.completions.create(
  model="gpt-4",
  messages=messages,
  tools=[weather_tool_definition]
)

// بررسی کنید که آیا مدل می‌خواهد یک تابع را فراخوانی کند یا خیر
if response.choices[0].message.tool_calls:
    # 3. اجرای تابع به صورت محلی
    function_name = response.choices[0].message.tool_calls[0].function.name
    function_args = response.choices[0].message.tool_calls[0].function.arguments
    function_response = get_weather(function_args["location"])

    # 4. الحاق نتیجه تابع به پیام‌ها
    messages.append(response.choices[0].message) # الحاق پیام دستیار
    messages.append({
        "role": "tool",
        "tool_call_id": response.choices[0].message.tool_calls[0].id,
        "content": function_response
    })

    # 5. تولید نهایی
    final_response = client.chat.completions.create(
        model="gpt-4",
        messages=messages
    )

در این مثال، به اهمیت نقش tool توجه کنید. این به مدل سیگنال می‌دهد که پیام قبلی توسط مدل زبانی بزرگ تولید نشده است، بلکه داده واقعی از محیط است. این زمینه به مدل امکان می‌دهد تا یک پاسخ طبیعی مانند «در حال حاضر دمای لندن ۱۵ درجه سانتی‌گراد است» را سنتز کند.

بهترین شیوه‌ها برای یکپارچه‌سازی مقاوم

  • توصیحات را مختصر اما واضح نگه دارید: مدل از توصیف ابزار برای تصمیم‌گیری در مورد زمان فراخوانی ابزار استفاده می‌کند. اطمینان حاصل کنید که کلمات کلیدی با قصد‌های احتمالی کاربر مطابقت دارند.
  • خطاها را به آرامی مدیریت کنید: اگر اجرای تابع شما با شکست مواجه شود (مثلاً زمان‌بر شدن اتصال به پایگاه داده)، پیام خطا را در فیلد content بازگردانید. سپس مدل زبانی بزرگ می‌تواند شکست را به کاربر توضیح دهد یا تلاش کند ورودی را اصلاح کند.
  • امنیت: هرگز پرس‌وجوهای سیستم داخلی یا کلیدهای حساس را از طریق آرگومان‌های تابع در دسترس قرار ندهید. ورودی‌ها را قبل از ارسال به APIهای خارجی تصفیه (Sanitize) کنید.
  • روندهای پیچیده: برای وظایف چندمرحله‌ای، اطمینان حاصل کنید که توابع اتمیک (غیرقابل تجزیه) هستند. شکستن منطق پیچیده به ابزارهای کوچکتر و تک‌منظوره، قابلیت اطمینان و عیب‌یابی را افزایش می‌دهد.

نتیجه‌گیری

فراخوانی تابع، مدل‌های زبانی بزرگ را از دریافت‌کنندگان غیرفعال اطلاعات به عامل‌های فعالی تبدیل می‌کند که قادر به تعامل با دنیای دیجیتال هستند. با تسلط بر تعریف طرحواره‌های ابزار و مدیریت حلقه اجرای چندمرحله‌ای، توسعه‌دهندگان می‌توانند پتانسیل واقعی هوش مصنوعی مولد را در محیط‌های تولید آزاد کنند. با تکامل اکوسیستم، انتظار چارچوب‌های پیچیده‌تری را داشته باشید که این الگوها را خودکار می‌کنند، اما درک عمیق از مکانیک‌های زیربنایی همچنان ارزشمندترین دارایی شما در ساخت برنامه‌های قابل اعتماد و هوشمند باقی خواهد ماند.

Share: