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

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

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

POST https://api.shannon-ai.com/v1/chat/completions

نمونه‌های این صفحه از /v1/chat/completions استفاده می‌کنند. همین حلقه روی /v1/responses و /v1/messages هم اجرا می‌شود؛ جایی که یک فرمت چیزی را متفاوت می‌نویسد، بخش‌های زیر هر سه را نشان می‌دهند.

import json
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1")

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a city.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name, for example Paris"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            },
            "required": ["city"],
        },
    },
}]

def get_weather(city, unit="celsius"):
    # Your code: ask a weather service here.
    return {"city": city, "temperature": 18, "unit": unit, "conditions": "cloudy"}

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

for _ in range(5):  # the API sets no limit on rounds: set your own
    response = client.chat.completions.create(
        model="Kimi-K3-3BIT-REAP",
        messages=messages,
        tools=tools,
    )
    choice = response.choices[0]
    if choice.finish_reason != "tool_calls":
        answer = choice.message.content
        break

    messages.append(choice.message)  # the assistant turn with its tool_calls
    for call in choice.message.tool_calls:
        args = json.loads(call.function.arguments)  # arguments is a JSON string
        result = get_weather(**args)
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result),
        })

print(answer)

پاسخ اول به پرسش جواب نمی‌دهد. یک فراخوانی می‌خواهد:

200 JSON
{
  "id": "chatcmpl-5b0c1d8e7f6a4b3c9d2e1f0a8b7c6d5e",
  "object": "chat.completion",
  "created": 1791590400,
  "model": "Kimi-K3-3BIT-REAP",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "reasoning_content": "The user asks for the current weather in Paris. I should call get_weather.",
        "tool_calls": [
          {
            "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\":\"Paris\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 312,
    "completion_tokens": 58,
    "total_tokens": 370,
    "prompt_tokens_details": {"cached_tokens": 0},
    "completion_tokens_details": {"reasoning_tokens": 31}
  }
}

پس از اینکه نتیجه را بفرستید، پاسخ بعدی یک جواب معمولی است: message.content متن را دارد و finish_reason برابر stop است.

حلقه، گام به گام

گام چه کسی چه اتفاقی می‌افتد
1 شما messages را همراه tools بفرستید، یعنی فهرست توابعی که مدل می‌تواند بخواهد.
2 مدل پاسخ tool_calls و finish_reason: "tool_calls" دارد. هر فراخوانی نام یک تابع را می‌برد و آرگومان‌هایش را می‌دهد.
3 شما arguments هر فراخوانی را parse کنید و تابع خود را اجرا کنید.
4 شما پیام assistant و به ازای هر فراخوانی یک پیام tool را به messages اضافه کنید، سپس درخواست را با همان tools دوباره بفرستید.
5 مدل مدل با متن و finish_reason: "stop" پاسخ می‌دهد، یا فراخوانی‌های بیشتری می‌خواهد. در آن حالت به گام 3 برگردید.

یک درخواست یک نوبت مدل است. API هیچ گفتگویی را بین درخواست‌ها نگه نمی‌دارد و تعداد دور تعیین نمی‌کند: کد شما messages را نگه می‌دارد و تصمیم می‌گیرد کی متوقف شود.

تعریف ابزارها

tools آرایه‌ای با یک مورد برای هر تابع است. هر مدل کاتالوگ آن را می‌پذیرد؛ GET /v1/models برای هر شناسه capabilities.tools: true گزارش می‌کند.

فیلد نوع توضیحات
type string همیشه function.
function.name string نامی که مدل هنگام درخواست این تابع به کار می‌برد. الزامی.
function.description string تابع چه می‌کند، به زبان ساده.
function.parameters object آرگومان‌ها به‌صورت JSON Schema با type: "object" در بالا. کلیدواژه‌های Schema را در ادامه ببینید.

هر endpoint شکل نوشتن خاص خودش را برای ابزار دارد. شکلی را بفرستید که به endpointی که فراخوانی می‌کنید تعلق دارد:

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city.",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "City name, for example Paris"
        },
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
      },
      "required": ["city"]
    }
  }
}

tool_choice

tool_choice مشخص می‌کند مدل مجاز است یا باید ابزاری را فراخوانی کند. فقط همراه با tools خوانده می‌شود.

مقدار توضیحات اعمال‌شده توسط
"auto" مدل تصمیم می‌گیرد با متن پاسخ دهد یا ابزاری فراخوانی کند. این پیش‌فرض است. همه مدل‌ها
"required" پاسخ دست‌کم یک ابزار را فراخوانی می‌کند. مدل‌های open-weight میزبانی‌شده
{"type": "function", "function": {"name": "get_weather"}} پاسخ این تابع را فراخوانی می‌کند. نام باید یکی از توابع tools باشد. فراخوانی توابع دیگر از پاسخ حذف می‌شود. مدل‌های open-weight میزبانی‌شده

مدل‌های Shannon (shannon-*) در هر درخواست خودشان تصمیم می‌گیرند، مثل auto.

با required یا یک تابع نام‌برده، پیش از خواندن tool_calls مقدار finish_reason را بخوانید. وقتی مدل فراخوانی تولید نکند، پاسخ یک جواب متنی با finish_reason: "stop" است.

معنا /v1/chat/completions /v1/responses /v1/messages
مدل تصمیم می‌گیرد "auto" "auto" {"type": "auto"}
فراخوانی دست‌کم یک ابزار "required" "required" {"type": "any"}
فراخوانی یک تابع مشخص {"type": "function", "function": {"name": "get_weather"}} {"type": "function", "name": "get_weather"} {"type": "tool", "name": "get_weather"}

برای سازگاری پذیرفته می‌شوند: tool_choice: "none" و parallel_tool_calls. برای نوبتی بدون فراخوانی ابزار، درخواست را بدون tools بفرستید.

فراخوانی ابزار در پاسخ

فیلد نوع توضیحات
finish_reason string tool_calls وقتی پاسخ دست‌کم یک فراخوانی دارد.
message.tool_calls array یک مورد برای هر فراخوانی. این فیلد فقط وقتی وجود دارد که مدل فراخوانی خواسته باشد.
tool_calls[].id string call_ و پس از آن 32 نویسه هگزادسیمال. آن را همراه نتیجه به‌صورت tool_call_id پس بفرستید.
tool_calls[].type string همیشه function.
tool_calls[].function.name string تابعی که باید اجرا شود.
tool_calls[].function.arguments string آرگومان‌ها به‌صورت رشته JSON، و وقتی آرگومانی نیست "{}". پیش از استفاده آن را parse کنید.
message.content string | null وقتی پاسخ فقط فراخوانی دارد null. مدل‌های open-weight میزبانی‌شده می‌توانند کنار فراخوانی‌ها متن هم برگردانند؛ مدل‌های Shannon null برمی‌گردانند.

همان فراخوانی در هر فرمت. روی /v1/responses یک آیتم function_call در output است که arguments آن رشته JSON است. روی /v1/messages یک بلوک محتوای tool_use است که input آن شیء JSON است، id آن با toolu_ شروع می‌شود و stop_reason برابر tool_use است.

{
  "finish_reason": "tool_calls",
  "message": {
    "role": "assistant",
    "content": null,
    "tool_calls": [
      {
        "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"city\":\"Paris\"}"
        }
      }
    ]
  }
}

چند فراخوانی در یک نوبت

یک پاسخ می‌تواند چند فراخوانی داشته باشد. همه را اجرا کنید و در درخواست بعدی به ازای هر فراخوانی یک نتیجه بفرستید، هرکدام با tool_call_id خودش.

مدل‌های open-weight میزبانی‌شده هر فراخوانی متمایز را یک بار برمی‌گردانند: دو فراخوانی با نام و آرگومان‌های یکسان به‌صورت یک فراخوانی می‌رسند.

فراخوانی ابزار در stream

با stream: true هر فراخوانی یکجا می‌رسد: chunk رشته کامل arguments را دارد، پس تکه‌ای برای به هم چسباندن نیست. index فراخوانی‌های نوبت را از 0 می‌شمارد.

data: یک chunk، قالب‌بندی‌شده
{
  "id": "chatcmpl-5b0c1d8e7f6a4b3c9d2e1f0a8b7c6d5e",
  "object": "chat.completion.chunk",
  "created": 1791590400,
  "model": "Kimi-K3-3BIT-REAP",
  "choices": [
    {
      "index": 0,
      "delta": {
        "tool_calls": [
          {
            "index": 0,
            "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\":\"Paris\"}"
            }
          }
        ]
      },
      "finish_reason": null
    }
  ]
}
Endpoint چه چیزی می‌رسد
/v1/chat/completions به ازای هر فراخوانی یک chat.completion.chunk، با فراخوانی در delta.tool_calls[0]. آخرین chunk finish_reason: "tool_calls" و usage را دارد.
/v1/responses به ازای هر فراخوانی: response.output_item.added (آیتم function_call با arguments خالی)، response.function_call_arguments.delta (کل رشته)، response.function_call_arguments.done، response.output_item.done.
/v1/messages به ازای هر فراخوانی: content_block_start (بلوک tool_use با input خالی)، یک content_block_delta که input_json_delta.partial_json آن کل متن آرگومان‌هاست، content_block_stop. سپس message_delta مقدار stop_reason: "tool_use" را می‌آورد.

روی shannon-1.6-lite، shannon-1.6-pro، shannon-2-lite، shannon-2-pro و shannon-coder-1، درخواست streamشده‌ای که tools دارد متن پاسخ را در یک delta از content در پایان نوبت تحویل می‌دهد. استریم

پس فرستادن نتایج

درخواست دوم گفتگو را تکرار می‌کند و دو چیز اضافه می‌کند: نوبت assistant که فراخوانی‌ها را خواسته و به ازای هر فراخوانی یک نتیجه.

{
  "messages": [
    {"role": "user", "content": "What is the weather in Paris right now?"},
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
          "type": "function",
          "function": {
            "name": "get_weather",
            "arguments": "{\"city\":\"Paris\"}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
      "content": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"
    }
  ]
}
  • نوبت assistant را همان‌طور که دریافت کرده‌اید، پیش از نتایج، پس بفرستید. هر نتیجه با شناسه به فراخوانی خود وصل می‌شود: tool_call_id روی /v1/chat/completions، call_id روی /v1/responses، tool_use_id روی /v1/messages.
  • نتیجه متن است. شیء را برای content (روی /v1/responses برای output) به رشته JSON سریالایز کنید. روی /v1/messages، content بلوک tool_result یک رشته یا فهرستی از بلوک‌های متنی است.
  • در نوبت assistant، function.arguments همان‌طور که رسیده یک رشته JSON می‌ماند.
  • گفتگو می‌تواند با نتیجه ابزار تمام شود. به پیام جدید کاربر نیازی نیست: مدل از نتیجه ادامه می‌دهد.
  • وقتی تابع شما شکست بخورد، شکست را به‌عنوان متن نتیجه بفرستید. مدل آن‌گاه می‌تواند آن را گزارش کند یا فراخوانی دیگری بخواهد.

کلیدواژه‌های Schema

parameters (روی /v1/messages input_schema) یک JSON Schema است. خانواده Shannon 3 (shannon-3، shannon-3-pro، shannon-3.1، shannon-3.1-pro) و مدل‌های open-weight میزبانی‌شده آن را همان‌طور که می‌فرستید دریافت می‌کنند.

shannon-1.6-lite، shannon-1.6-pro، shannon-2-lite، shannon-2-pro و shannon-coder-1 این زیرمجموعه را روی هر سه endpoint دریافت می‌کنند:

نحوه برخورد کلیدواژه‌ها
همان‌طور که فرستاده شده خوانده می‌شود هر کلیدواژه‌ای که در ردیف‌های زیر نام برده نشده، برای مثال type، properties، required، items، enum، description، minimum، maximum، anyOf و allOf، در هر سطح از schema.
format برای مقادیر int32، int64، float، double، byte، date، date-time و enum خوانده می‌شود.
oneOf مانند anyOf خوانده می‌شود.
جزو schemaای که این مدل‌ها دریافت می‌کنند نیست $schema، $id، $ref، $defs، $comment، definitions، additionalProperties، unevaluatedProperties، patternProperties، propertyNames، examples، default، title، const، not، if، then، else، contains، minContains، maxContains، dependentRequired، dependentSchemas، dependencies، readOnly، writeOnly، deprecated، contentEncoding، contentMediaType، contentSchema، multipleOf، uniqueItems؛ exclusiveMinimum و exclusiveMaximum وقتی عدد باشند؛ دیگر مقادیر format.

رفتار و محدودیت‌ها

  • API حداکثری برای تعداد ابزارها و حداکثری برای تعداد دورها تعیین نمی‌کند.
  • بدنه درخواست می‌تواند تا 32 MiB باشد و گفتگو همراه نتایجش باید در پنجره زمینه مدل جا شود.
  • وقتی درخواست tools دارد، shannon-1.6-lite، shannon-1.6-pro، shannon-2-lite و shannon-2-pro از temperature پیش‌فرض 0.2 استفاده می‌کنند. برای مقدار دیگر، temperature را بفرستید.
  • هر دور یک درخواست مستقل است: از موجودی شما برداشت می‌کند و مثل هر درخواست دیگر در محافظت در برابر هجوم درخواست شمرده می‌شود. محدودیت‌ها و موجودی

خطاها

فراخوانی ابزار یک پاسخ عادی با وضعیت 200 است. این خطاها به خود درخواست مربوط‌اند:

وضعیت نوع پیام زمان
400 invalid_request_error unknown model: <id> model شناسه‌ای از فهرست منتشرشده نیست.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … tools آرایه نیست، یا نوع JSON فیلد دیگری نادرست است.
413 invalid_request_error Failed to buffer the request body: … بدنه درخواست از 32 MiB بزرگ‌تر است. خطا code: "request_too_large" را دارد.

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

خطاهای احراز هویت، موجودی و سرور مثل هر درخواست دیگر هستند. مدیریت خطا