المظهر
اللغة
·5 دقائق للقراءة

استدعاء الدوال باستخدام واجهة API لنموذج LLM: حلقة عمل كاملة

كيفية عمل استدعاء الدوال (استخدام الأدوات) عبر واجهة API متوافقة مع OpenAI: حلقة Python كاملة شغّلناها على GPT-6 Luna وDeepSeek V4.1 Flash وClaude Haiku 5.5، مع فرض الاستدعاء باستخدام tool_choice، وتنسيق Anthropic Messages.

استدعاء الدوال باستخدام واجهة API لنموذج LLM: حلقة عمل كاملة

استدعاء الدوال (ويُسمى أيضًا استدعاء الأدوات أو استخدام الأدوات) هو الطريقة التي تمنح بها النموذج إمكانية الوصول إلى شيفرتك. تصف دوالًا مثل "البحث عن طلب" أو "تسعير الشحن". يقرر النموذج أي دالة يستدعي وبأي معاملات؛ ثم تشغّل شيفرتك الدالة وترسل النتيجة إليه. كل وكيل، بدءًا من روبوت دعم المتجر ووصولًا إلى Claude Code، مبني على هذه الحلقة.

في GetVibe API، يعمل استدعاء الدوال عبر نقطة النهاية القياسية /v1/chat/completions بتنسيق OpenAI، وعبر /v1/messages بتنسيق Anthropic. فيما يلي حلقة كاملة شغّلناها على ثلاثة نماذج من ثلاث جهات مصنّعة مختلفة.

كيف تعمل الحلقة

  1. ترسل الرسائل بالإضافة إلى قائمة من tools. لكل أداة اسم ووصف وJSON Schema لمعاملاتها.
  2. بدلًا من النص، يعيد النموذج tool_calls: الدالة التي ينبغي استدعاؤها والمعاملات التي ينبغي تمريرها إليها. تكون قيمة finish_reason هي tool_calls.
  3. تشغّل شيفرتك الدوال وتضيف رسالة واحدة بالدور tool لكل استدعاء، مع تمرير tool_call_id نفسه.
  4. ترسل السجل مرة أخرى. إما أن يطلب النموذج استدعاءات إضافية أو يجيب المستخدم نصيًا.

لا يشغّل النموذج أي شيء بنفسه. هو يطلب الاستدعاء فقط. أما ما يُشغَّل فعليًا، والصلاحيات التي يُشغَّل بها، فتحدده شيفرتك.

مثال كامل: مساعد دعم متجر

دالتان: حالة الطلب وعرض سعر الشحن. يسأل المستخدم عن الأمرين معًا، ويستدعي النموذج الدالتين في دور واحد.

import json
import os
from openai import OpenAI

client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])
MODEL = "gpt-6-luna"

def get_order_status(order_id: str) -> dict:
    # يوضع هنا البحث في قاعدة بياناتك أو نظام CRM لديك
    return {"order_id": order_id, "status": "out for delivery", "eta": "2026-10-24"}

def get_shipping_quote(zip_code: str) -> dict:
    return {"zip_code": zip_code, "price_usd": 7.5, "days": 2}

TOOLS = [
    {"type": "function", "function": {
        "name": "get_order_status",
        "description": "Look up an order by its ID",
        "parameters": {"type": "object",
                       "properties": {"order_id": {"type": "string", "description": "Order ID, e.g. A-1042"}},
                       "required": ["order_id"]}}},
    {"type": "function", "function": {
        "name": "get_shipping_quote",
        "description": "Courier shipping price and delivery time to a US ZIP code",
        "parameters": {"type": "object",
                       "properties": {"zip_code": {"type": "string"}},
                       "required": ["zip_code"]}}},
]
FUNCTIONS = {"get_order_status": get_order_status, "get_shipping_quote": get_shipping_quote}

messages = [
    {"role": "system", "content": "أنت مساعد لدعم متجر. كن موجزًا."},
    {"role": "user", "content": "أين طلبي A-1042؟ وكم تبلغ تكلفة الشحن إلى 94110؟"},
]

for _ in range(5):  # الحد الأقصى لعدد الجولات
    resp = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
    msg = resp.choices[0].message
    if not msg.tool_calls:
        print(msg.content)
        break
    messages.append(msg.model_dump(exclude_none=True))
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = FUNCTIONS[call.function.name](**args)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

شغّلنا هذه الشيفرة دون أي تغيير على gpt-6-luna وdeepseek-v4.1-flash وclaude-haiku-5.5، مع تغيير MODEL فقط. في الجولة الأولى، استدعت النماذج الثلاثة الدالتين، حيث استُدعيت get_order_status باستخدام A-1042 وget_shipping_quote باستخدام 94110. وفي الجولة الثانية، أجابت النماذج الثلاثة نصيًا بحالة التسليم ووقت الوصول المتوقع وسعر 7.50 ومدة التسليم البالغة يومين.

ما المهم في هذه الشيفرة

  • أضف رسالة استدعاء الأداة من النموذج إلى السجل كاملةً. من دونها، تجيب رسالة tool عن استدعاء لا يستطيع النموذج رؤيته، ولذلك تعيد نماذج كثيرة استدعاء الدالة نفسها ببساطة، فتدور الحلقة في حلقة مفرغة.
  • رسالة tool واحدة لكل استدعاء، مع tool_call_id المطابق. قد يطلب النموذج عدة استدعاءات في الوقت نفسه، كما حدث هنا.
  • تصل المعاملات كسلسلة نصية. تكون قيمة arguments عبارة عن JSON داخل سلسلة نصية. حلّلها وتحقق من صحتها، لأن النموذج قد يخطئ في قيمة ما.
  • ضع حدًا للجولات. من دون حد، قد يحوّل خلل في إحدى الدوال الحلقة إلى حلقة لا نهائية، وإلى فاتورة رموز لا نهائية.

tool_choice: متى يكون الاستدعاء إلزاميًا

افتراضيًا، يقرر النموذج ما إذا كان سيستدعي أداة أو يجيب نصيًا ("auto"). ويغيّر tool_choice هذا السلوك:

  • "none" — لا تستدعِ الأدوات مطلقًا؛
  • "required" — استدعِ أداة واحدة على الأقل؛
  • {"type": "function", "function": {"name": "..."}} — استدعِ هذه الدالة المحددة.

الصيغة الأخيرة مفيدة لاستخراج البيانات. ويصبح مخطط معاملات الدالة هو شكل الإجابة:

curl https://getvibeapi.com/v1/chat/completions \
  -H "Authorization: Bearer $GETVIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4.1-flash",
    "messages": [{"role": "user", "content": "Jane Doe، [email protected]، تريد عرضًا توضيحيًا يوم الخميس"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "save_lead",
        "description": "Save a sales lead to the CRM",
        "parameters": {
          "type": "object",
          "properties": {"name": {"type": "string"}, "email": {"type": "string"}, "request": {"type": "string"}},
          "required": ["name", "email", "request"]
        }
      }
    }],
    "tool_choice": {"type": "function", "function": {"name": "save_lead"}}
  }'

كانت الاستجابة استدعاءً للدالة save_lead مع name بالقيمة "Jane Doe"، وemail بالقيمة "[email protected]"، وrequest بالقيمة "تريد عرضًا توضيحيًا يوم الخميس".

تجدر الإشارة إلى أن بعض نماذج Claude، بما في ذلك Claude Sonnet 5.5 وClaude Opus 5.5، لا تقبل الاختيار القسري للأداة. يحوّل GetVibe مثل هذا الطلب إلى auto مع الأدوات نفسها، فتحصل على إجابة بدلًا من خطأ، لكن النموذج يقرر بعد ذلك بنفسه ما إذا كان سيستدعي الأداة. للحصول على JSON صارم من هذه النماذج، استخدم المخرجات المنظّمة.

تنسيق Anthropic: /v1/messages

باستخدام Anthropic SDK، تبدو الأدوات مختلفة قليلًا: يوضع مخطط المعاملات في input_schema، ويعود الاستدعاء على هيئة كتلة محتوى tool_use.

curl https://getvibeapi.com/v1/messages \
  -H "x-api-key: $GETVIBE_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-haiku-5.5",
    "max_tokens": 512,
    "tools": [{
      "name": "get_order_status",
      "description": "Look up an order by its ID",
      "input_schema": {"type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"]}
    }],
    "messages": [{"role": "user", "content": "أين الطلب A-1042؟"}]
  }'

احتوت الاستجابة على stop_reason بالقيمة tool_use وكتلة tool_use تستدعي get_order_status مع order_id بالقيمة A-1042. ترسل النتيجة مرة أخرى على هيئة كتلة tool_result في رسالة المستخدم التالية، مع tool_use_id نفسه.

أي نموذج تستخدم مع الأدوات

  • الروبوتات ذات الحجم الكبير والأدوات البسيطة — DeepSeek V4.1 Flash ($0.0112 الإدخال · $0.0445 الإخراج لكل مليون رمز) أو Claude Haiku 5.5 ($0.0267 الإدخال · $0.1334 الإخراج لكل مليون رمز).
  • الوكلاء الذين يستخدمون أدوات كثيرة وخططًا طويلة — GPT-6 Luna ($0.0055 الإدخال · $0.0274 الإخراج لكل مليون رمز) أو Claude Sonnet 5.5.

تعيد حلقات الوكلاء إرسال البادئة الطويلة نفسها في كل جولة، لذا فإن التخزين المؤقت للمطالبات مهم جدًا هنا. تتوفر مزيد من التفاصيل حول حقول الطلب في وثائق استدعاء الأدوات.

واجهة API لاستدعاء الدوالاستدعاء الأدوات في نماذج LLMمثال على استدعاء دوال OpenAItool_choiceاستخدام أدوات Anthropicأدوات وكلاء LLM

جرّب GetVibe API مجانًا

GPT وClaude وGemini والمزيد من خلال واجهة API واحدة متوافقة مع OpenAI. ادفع بالدولار الأمريكي عبر البطاقة أو العملات الرقمية.

مقالات ذات صلة

استدعاء الدوال باستخدام واجهة API لنموذج LLM: حلقة عمل كاملة | GetVibe API