AI Agents

حرفه‌ای شدن در فراخوانی توابع: ساخت عامل‌هایی که عمل می‌کنند

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

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

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

اجزای حیاتی در اینجا JSON Schema است. برخلاف مستندات API استاندارد که ممکن است مبهم باشند، فراخوانی توابع نیاز به تعاریف سختگیرانه و صریح دارد. مدل باید دقیقاً بداند چه انواع داده‌ای انتظار می‌رود، کدام فیلدها اختیاری هستند و چه مقادیر شمارنده (enum) مجازند. اگر اسکیما شما مبهم باشد، مدل فرضیات خواهد کرد که منجر به خطاهای زمان اجرا می‌شود.

پیاده‌سازی عملی در پایتون

در زیر یک مثال ساده‌شده با استفاده از یک رابط عمومی LLM آورده شده است. توجه کنید که چگونه ابتدا ابزار را تعریف می‌کنیم و سپس مدل را پرامپت می‌کنیم تا آن را انتخاب کند.

import json
from typing import Callable, Dict, Any

# 1. تعریف منطق تابع
def get_weather(city: str) -> str:
    """شبیه‌سازی دریافت داده‌های هواشناسی."""
    # در یک برنامه واقعی، این فراخوانی یک API خارجی خواهد بود
    return f"The weather in {city} is sunny and 72F."

# 2. تعریف اسکیما برای LLM
weather_tool = {
    "name": "get_weather",
    "description": "Get the current weather for a given city.",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "The name of the city."
            }
        },
        "required": ["city"]
    }
}

# 3. خروجی LLM (شبیه‌سازی شده)
# در یک سناریوی واقعی، شما پرامپت و تعاریف ابزار را به API ارسال می‌کنید.
llm_response = """
{
    "tool_name": "get_weather",
    "arguments": {
        "city": "San Francisco"
    }
}
"""

# 4. تجزیه و اجرا
def dispatch_call(response_json: str) -> Any:
    data = json.loads(response_json)
    tool_name = data["tool_name"]
    args = data["arguments"]
    
    # نگاشت نام‌های توابع به متدهای واقعی
    tool_map: Dict[str, Callable] = {
        "get_weather": get_weather
    }
    
    if tool_name in tool_map:
        return tool_map[tool_name](**args)
    else:
        raise ValueError(f"Unknown tool: {tool_name}")

result = dispatch_call(llm_response)
print(result)

مدیریت ابهام و خطاها

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

علاوه بر این، باید خطاهای تجزیه JSON را مدیریت کنید. حتی مدل‌های بسیار پایدار نیز گاهی اوقات JSON نامعتبر تولید می‌کنند، به ویژه هنگام کار با بافت‌های بزرگ. همیشه منطق تجزیه JSON خود را در یک بلوک try-catch قرار دهید. اگر تجزیه شکست خورد، عامل را کرش نکنید. به جای آن، پیام خطا را با یک پرامپت مانند «خروجی قبلی شما JSON نامعتبری بود. لطفاً دوباره تلاش کنید.» به LLM برگردانید. این حلقه خوداصلاح‌سازی به طور قابل توجهی قابلیت اطمینان را بهبود می‌بخشد.

ملاحظات امنیتی

فراخوانی توابع سطح امنیتی قابل توجهی را معرفی می‌کند. LLM آرگومان‌های کدی را تولید می‌کند که بک‌اند شما آن‌ها را اجرا می‌نماید. اگر به اجرای دلخواه اجازه دهید، یک حمله تزریق پرامپت می‌تواند فاجعه‌بار باشد. برای مثال، یک کاربر ممکن است مدل را فریب دهد تا تابعی مانند delete_database یا send_email را با بارهای بدافزاری فراخوانی کند.

برای کاهش این خطر، یک سیستم سفیدلیست پیاده‌سازی کنید. هرگز به LLM اجازه ندهید که بدون اعتبارسنجی سختگیرانه، توابع را به صورت پویا از یک استخر بزرگ انتخاب کند. علاوه بر این، مراحل تأیید انسانی در حلقه (human-in-the-loop) را برای اقدامات پرخطر اضافه کنید. قبل از اجرای تابعی که داده‌ها را تغییر می‌دهد یا پول خرج می‌کند، عامل را متوقف کنید و تأیید صریح کاربر را درخواست کنید.

نتیجه‌گیری

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

Share: