コンテンツへスキップ
関数呼び出し

関数呼び出し

リクエストで関数を記述すると、モデルは実行してほしい呼び出しを返します。お使いのコードがそれを実行して結果を送り返します。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 をパースし、関数を実行します。
4 あなた アシスタントのメッセージと、呼び出しごとにひとつの tool メッセージを messages に追加し、同じ tools でリクエストをもう一度送信します。
5 モデル モデルは finish_reason: "stop" のテキストで答えるか、さらに呼び出しを求めます。後者の場合は、ステップ 3 に戻ります。

ひとつのリクエストは、モデルの一ターンです。API はリクエスト間で会話を保持せず、ラウンド数も定めません。messages を保持し、いつ止めるかを決めるのはお使いのコードです。

ツールの定義

tools は、関数ごとにひとつのエントリを持つ配列です。カタログのすべてのモデルが受け付けます。GET /v1/models は、すべての ID について capabilities.tools: true を報告します。

フィールド 型 説明
type string 常に function。
function.name string モデルがこの関数を要求するときに使う名前。必須です。
function.description string 関数の内容を、わかりやすい言葉で記述します。
function.parameters object 引数を、最上位に type: "object" を持つ JSON Schema で記述します。下記の スキーマのキーワード を参照してください。

エンドポイントごとに、ツールの書き方が異なります。呼び出すエンドポイントに合ったものを送信してください。

{
  "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" 応答は少なくともひとつのツールを呼び出します。 ホスト型オープンウェイトモデル
{"type": "function", "function": {"name": "get_weather"}} 応答はこの関数を呼び出します。名前は tools にある関数のいずれかでなければなりません。他の関数への呼び出しは、応答から除かれます。 ホスト型オープンウェイトモデル

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 文字列 で表したもの。引数がない場合は "{}" です。使用する前にパースしてください。
message.content string | null 応答に呼び出しだけが含まれる場合は null。ホスト型オープンウェイトモデルは呼び出しと並べてテキストを返すことがあります。Shannon モデルは null を返します。

各形式での同じ呼び出し。/v1/responses では output の function_call アイテムで、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 を付けて結果をひとつずつ送信してください。

ホスト型オープンウェイトモデルは、重複しない呼び出しをそれぞれ一度だけ返します。名前も引数も同じ二つの呼び出しは、ひとつにまとめて届きます。

ストリームされるツール呼び出し

stream: true の場合、呼び出しはひとまとまりで届きます。チャンクに完全な arguments 文字列が入っているため、つなぎ合わせる断片はありません。index は、そのターンの呼び出しを 0 から数えます。

data: ひとつのチャンク(整形済み)
{
  "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
    }
  ]
}
エンドポイント 届くもの
/v1/chat/completions 呼び出しごとにひとつの chat.completion.chunk が届き、呼び出しは delta.tool_calls[0] に入ります。最後のチャンクには finish_reason: "tool_calls" と usage があります。
/v1/responses 呼び出しごとに:response.output_item.added(空の arguments を持つ function_call アイテム)、response.function_call_arguments.delta(文字列全体)、response.function_call_arguments.done、response.output_item.done。
/v1/messages 呼び出しごとに:content_block_start(空の input を持つ tool_use ブロック)、引数テキスト全体が input_json_delta.partial_json に入った content_block_delta がひとつ、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 では、tools を含むストリームリクエストは、ターンの最後にひとつの content デルタで回答テキストを届けます。 ストリーミング

結果を送り返す

二回目のリクエストは会話を繰り返し、ふたつを追加します。呼び出しを求めたアシスタントのターンと、呼び出しごとの結果です。

{
  "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\"}"
    }
  ]
}
  • アシスタントのターンは、受け取ったとおりに、結果の前に送り返してください。各結果は ID で呼び出しと対応付けられます:/v1/chat/completions では tool_call_id、/v1/responses では call_id、/v1/messages では tool_use_id です。
  • 結果はテキストです。オブジェクトは JSON 文字列にシリアライズして content(/v1/responses では output)に入れます。/v1/messages では、tool_result ブロックの content は文字列、またはテキストブロックのリストです。
  • アシスタントのターンでは、function.arguments は届いたとおり、JSON 文字列のままにします。
  • 会話はツールの結果で終わっていてもかまいません。新しいユーザーメッセージは不要です。モデルは結果から続けます。
  • 関数が失敗した場合は、失敗の内容を結果のテキストとして送信してください。モデルはそれを報告するか、別の呼び出しを求めることができます。

スキーマのキーワード

parameters(/v1/messages では input_schema)は JSON Schema です。Shannon 3 ファミリー(shannon-3、shannon-3-pro、shannon-3.1、shannon-3.1-pro)とホスト型オープンウェイトモデルは、送信したとおりに受け取ります。

shannon-1.6-lite、shannon-1.6-pro、shannon-2-lite、shannon-2-pro、shannon-coder-1 は、三つのエンドポイントすべてで、次のサブセットを受け取ります。

扱い キーワード
送信したとおりに読み取られる 以下の行で名前が挙がっていないすべてのキーワード(たとえば type、properties、required、items、enum、description、minimum、maximum、anyOf、allOf)が、スキーマのあらゆる階層で対象です。
format 値 int32、int64、float、double、byte、date、date-time、enum が読み取られます。
oneOf anyOf として読み取られます。
これらのモデルが受け取るスキーマに含まれないもの $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 が、公開されている一覧にある ID ではありません。
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" が含まれます。

引数を書くのはモデルです。外部からの入力と同じように、関数を実行する前にスキーマと照合して確認してください。

認証、残高、サーバーのエラーは、すべてのリクエストと同じです。 エラー処理