العودة إلى المدونة

API وSDKدليل

استدعاء الدوال في Python عبر API متوافق مع OpenAI

أرسل الأدوات، واقرأ tool_calls، وأعد النتيجة بدور tool: حلقة استدعاء دوال من خطوتين في Python مع MiniMax-M2.7.

بواسطة CheapTokens Teamنُشر في تم التحديث في 5 دقيقة قراءة

مخطط لحلقة استدعاء أدوات من خطوتين: أرسل الأدوات، واقرأ tool_calls، وأعد النتيجة كرسالة أداة
في هذه الصفحة
  1. كيف يعمل استدعاء الدوال
  2. إعداد العميل
  3. تعريف دالة وإرسال الطلب الأول
  4. ما الذي يجب أن تراه
  5. عدة استدعاءات وحلقات أطول
  6. لماذا يناسب MiniMax-M2.7 حلقات الأدوات
  7. إذا لم يعمل
  8. الخطوات التالية

يتيح استدعاء الدوال (استدعاء الأدوات) للنموذج أن يطلب من شفرتك تشغيل دالة. ترسل قائمة tools مع الطلب، فيجيب النموذج بـ tool_calls بدلًا من نص، وتشغّل الدالة بنفسك، ثم ترسل نتيجتها مرة أخرى في رسالة ذات role: tool. بعد ذلك يكتب النموذج الإجابة النهائية. يوضح هذا الدليل الحلقة كاملة بلغة Python عبر نقطة النهاية المتوافقة مع OpenAI https://api.cheaptokens.dev/v1/chat/completions مع MiniMax-M2.7 (المعرّف MiniMaxAI/MiniMax-M2.7، سياق 180K، وحتى 8,192 رمز إخراج لكل إجابة).

استدعاء الأدوات مُدرج كمدعوم لكل نموذج في الكتالوج (وثائق CheapTokens docs، تم التحقق في 22 أكتوبر 2026). تحتاج إلى مفتاح API؛ وإذا لم تكن قد أرسلت طلبًا بعد، فابدأ بـ طلب API الأول الخاص بك.

كيف يعمل استدعاء الدوال#

النموذج لا يشغّل أي شيء أبدًا. إنه ينتج فقط طلبًا منظمًا: "استدعِ get_weather بـ {\"city\": \"Paris\"}". برنامجك يقوم بالعمل الفعلي ويبلّغ بالنتيجة. وهذا يصنع حلقة من طلبين:

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

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

إعداد العميل#

ثبّت OpenAI SDK (pip install openai) وضع مفتاحك في متغير بيئة بدلًا من الشيفرة المصدرية:

bash
export CHEAPTOKENS_API_KEY="your-key-here"

عنوان URL الأساسي هو https://api.cheaptokens.dev/v1. خذ معرّف النموذج من وثائق CheapTokens: فالمزوّدون المختلفون يسمّون النموذج نفسه بأسماء مختلفة. يستخدم هذا الدليل MiniMaxAI/MiniMax-M2.7.

تعريف دالة وإرسال الطلب الأول#

تُوصف الدالة في مصفوفة tools. لكل عنصر type: function وكائن function يحوي name وdescription وparameters مكتوبة بصيغة JSON Schema. الوصف هو ما يقرأه النموذج ليقرر متى يستدعي الدالة، لذا اكتبه جملة قصيرة ومحددة.

فيما يلي سكربت كامل. دالة الطقس مجرد هيكل ببيانات وهمية، لذا لا يحتاج المثال إلى خدمات إضافية:

python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url='https://api.cheaptokens.dev/v1',
    api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'MiniMaxAI/MiniMax-M2.7'


def get_weather(city: str) -> dict:
    # Stub with fake data: replace with a real lookup
    fake = {'Paris': 14, 'Tokyo': 19}
    return {'city': city, 'temp_c': fake.get(city, 10)}


FUNCTIONS = {'get_weather': get_weather}

tools = [
    {
        'type': 'function',
        'function': {
            'name': 'get_weather',
            'description': 'Get the current temperature in Celsius for a city.',
            'parameters': {
                'type': 'object',
                'properties': {
                    'city': {'type': 'string', 'description': 'City name, for example Paris'},
                },
                'required': ['city'],
            },
        },
    }
]

messages = [{'role': 'user', 'content': 'What is the weather in Paris right now?'}]

# Step 1: the model decides whether to call a function
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message

if not message.tool_calls:
    print(message.content)
    raise SystemExit

# Step 2: run every requested call and send the results back
messages.append(message)
for call in message.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),
    })

final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
print(final.choices[0].message.content)

ثلاثة تفاصيل تحدد ما إذا كانت الحلقة تعمل:

  • call.function.arguments هو سلسلة JSON، وليس قاموسًا. حلّله بـ json.loads.
  • يجب أن تحمل كل رسالة role: tool قيمة tool_call_id الخاصة بالاستدعاء الذي تجيبه، وهي call.id.
  • قيمة content في رسالة الأداة سلسلة. استخدم json.dumps للنتائج المنظمة.

ما الذي يجب أن تراه#

إذا طبعت الحقول بعد الطلب الأول، فستبدو هكذا (يختلف معرّف الاستدعاء في كل تشغيل):

text
finish_reason: tool_calls
call.id: call_abc123
call.function.name: get_weather
call.function.arguments: {"city": "Paris"}

ثم يطبع السكربت الإجابة النهائية، وهي جملة بسيطة على غرار "تبلغ الحرارة حاليًا 14 °C في باريس." تتغير الصياغة من تشغيل لآخر؛ أما الرقم فيأتي من دالتك.

عدة استدعاءات وحلقات أطول#

يمكن للنموذج أن يعيد أكثر من استدعاء في استجابة واحدة، مثلًا عندما تسأل عن الطقس في مدينتين. لهذا يمر المثال على message.tool_calls ويجيب كل استدعاء بمعرّفه الخاص. يصف دليل استدعاء الدوال من OpenAI السلوك نفسه: مع القيمة الافتراضية tool_choice البالغة auto قد يستدعي النموذج صفرًا أو دالة واحدة أو عدة دوال (وثائق OpenAI، تم التحقق في 22 أكتوبر 2026؛ لا تحمل الصفحة تاريخ آخر تحديث وتصف شكل Responses API الأحدث، بينما يستخدم هذا الدليل شكل Chat Completions لنقطة النهاية /v1/chat/completions).

تكرر الوكلاء الخطوتين حتى يتوقف النموذج عن طلب الأدوات. لفّ الطلبات في حلقة واضبط دائمًا حدًا للخطوات:

python
for _ in range(5):  # safety limit against endless loops
    response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    message = response.choices[0].message
    if not message.tool_calls:
        print(message.content)
        break
    messages.append(message)
    for call in message.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)})

إذا أردت أن تظهر الإجابة رمزًا برمز، فاجمع هذا مع البث في Python.

لماذا يناسب MiniMax-M2.7 حلقات الأدوات#

ترسل حلقة الأدوات طلبات كثيرة بسجل متنامٍ. لهذا النمط تقدم CheapTokens نموذج MiniMax-M2.7: سياق 180K، وحتى 8,192 رمز إخراج لكل إجابة، وسعر واحد في أي وقت من اليوم دون ساعات ذروة، ورصيد واحد لكل النماذج. وباحتساب الإدخال والإخراج معًا، فهو أرخص من سعر OpenRouter المرجعي (مقارنة أسعار CheapTokens، تم التحقق في 31 أكتوبر 2026).

الأسعار الحالية لكل 1M رمز: الإدخال $0.05، والإخراج $0.15. على سبيل المثال كحمل عمل (وليس قياسًا)، فإن رحلة الذهاب والإياب ذات الطلبين أعلاه بنحو 2,700 رمز إدخال و350 رمز إخراج إجمالًا تكلّف $0.00019. قائمة الأسعار الكاملة على صفحة الأسعار.

لتجربة نموذج آخر، غيّر المعرّف فقط؛ وقائمة المعرّفات على صفحة النماذج.

إذا لم يعمل#

  • message.tool_calls هو None. أجاب النموذج بنص. اجعل وصف الدالة description أكثر تحديدًا، وتأكد من أن السؤال يحتاج الدالة فعلًا.
  • json.JSONDecodeError على arguments. أنتج النموذج JSON غير صالح. لفّ json.loads في try/except وأعد نص الخطأ كنتيجة الأداة، ليتمكن النموذج من إعادة المحاولة بوسائط مصححة.
  • فشل الطلب الثاني أو تجاهل النموذج النتيجة. تحقق من أن لكل استدعاء رسالة role: tool واحدة بالضبط بقيمة tool_call_id مطابقة، وأن رسالة المساعد التي تحوي tool_calls موجودة في السجل قبلها.
  • KeyError في FUNCTIONS[...]. سمّى النموذج دالة لم تسجلها. أعد سلسلة خطأ قصيرة كنتيجة الأداة بدلًا من الانهيار.
  • الإجابة مقطوعة. تحقق من finish_reason: القيمة length تعني بلوغ حد رموز الإخراج. راجع لماذا تتوقف إجابة الذكاء الاصطناعي في منتصف الجملة.
  • أخطاء 401 أو المصادقة. تحقق من أن المفتاح في CHEAPTOKENS_API_KEY وأن عنوان URL الأساسي ينتهي بـ /v1.

الخطوات التالية#

استبدل الهيكل بدالة حقيقية: استعلام قاعدة بيانات، أو استدعاء بحث، أو آلة حاسبة. أضف مزيدًا من العناصر إلى tools وإلى FUNCTIONS، وأبقِ كل نتيجة دالة قصيرة، لأنها تعود إلى السجل في كل طلب لاحق. للحصول على مفتاح وإجراء أول استدعاء، افتح وثائق CheapTokens.