ข้ามไปยังเนื้อหา
การเรียกฟังก์ชัน

การเรียกฟังก์ชัน

อธิบายฟังก์ชันของคุณในคำขอ แล้วโมเดลจะตอบกลับด้วยการเรียกที่ต้องการให้ทำ โค้ดของคุณรันฟังก์ชันและส่งผลลัพธ์กลับมา: API ส่งคืนการเรียก tool แต่ไม่รัน tool เอง

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 คุณ parse arguments ของแต่ละการเรียก แล้วรันฟังก์ชันของคุณ
4 คุณ เพิ่มข้อความของ assistant และข้อความ tool หนึ่งข้อความต่อหนึ่งการเรียกลงใน messages แล้วส่งคำขอใหม่ด้วย tools ชุดเดิม
5 โมเดล โมเดลตอบเป็นข้อความพร้อม finish_reason: "stop" หรือขอเรียกเพิ่ม ในกรณีหลังให้กลับไปที่ขั้นตอน 3

หนึ่งคำขอคือหนึ่งรอบของโมเดล API ไม่เก็บบทสนทนาระหว่างคำขอและไม่กำหนดจำนวนรอบ: โค้ดของคุณเก็บ messages และตัดสินใจว่าจะหยุดเมื่อใด

การกำหนด tool

tools คืออาร์เรย์ที่มีหนึ่งรายการต่อหนึ่งฟังก์ชัน ทุกโมเดลในแคตตาล็อกรองรับ; GET /v1/models รายงาน capabilities.tools: true สำหรับทุก id

ฟิลด์ ประเภท คำอธิบาย
type string เป็น function เสมอ
function.name string ชื่อที่โมเดลใช้เมื่อขอเรียกฟังก์ชันนี้ จำเป็นต้องมี
function.description string ฟังก์ชันนี้ทำอะไร เขียนเป็นภาษาธรรมดา
function.parameters object อาร์กิวเมนต์ในรูป JSON Schema โดยระดับบนสุดเป็น type: "object" ดู คีย์เวิร์ดของ schema ด้านล่าง

แต่ละ endpoint เขียน tool ในแบบของตัวเอง ให้ส่งแบบที่ตรงกับ 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 บอกว่าโมเดลเรียก tool ได้หรือต้องเรียก tool โดยจะอ่านค่านี้เมื่อมี tools เท่านั้น

ค่า คำอธิบาย ใช้โดย
"auto" โมเดลตัดสินใจเองว่าจะตอบเป็นข้อความหรือเรียก tool นี่คือค่าเริ่มต้น ทุกโมเดล
"required" คำตอบจะเรียก tool อย่างน้อยหนึ่งรายการ โมเดล open-weight ที่โฮสต์
{"type": "function", "function": {"name": "get_weather"}} คำตอบจะเรียกฟังก์ชันนี้ ชื่อต้องเป็นหนึ่งในฟังก์ชันใน tools การเรียกฟังก์ชันอื่นจะไม่ปรากฏในคำตอบ โมเดล open-weight ที่โฮสต์

โมเดล Shannon (shannon-*) ตัดสินใจเองในทุกคำขอ เหมือนกับ auto

เมื่อใช้ required หรือฟังก์ชันที่ระบุชื่อ ให้อ่าน finish_reason ก่อนอ่าน tool_calls หากโมเดลไม่เรียกอะไรเลย คำตอบจะเป็นข้อความพร้อม finish_reason: "stop"

ความหมาย /v1/chat/completions /v1/responses /v1/messages
โมเดลตัดสินใจเอง "auto" "auto" {"type": "auto"}
เรียก tool อย่างน้อยหนึ่งรายการ "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 สำหรับรอบที่ไม่ต้องเรียก tool ให้ส่งคำขอโดยไม่มี tools

การเรียก tool ในคำตอบ

ฟิลด์ ประเภท คำอธิบาย
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 string เป็น "{}" เมื่อไม่มีอาร์กิวเมนต์ ให้ parse ก่อนใช้งาน
message.content string | null เป็น null เมื่อคำตอบมีเฉพาะการเรียก โมเดล open-weight ที่โฮสต์อาจส่งข้อความมาพร้อมกับการเรียก ส่วนโมเดล Shannon จะส่ง null

การเรียกเดียวกันในแต่ละรูปแบบ บน /v1/responses เป็นรายการ function_call ใน output โดย arguments เป็น JSON string บน /v1/messages เป็น content block ชนิด 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 ที่โฮสต์ส่งคืนแต่ละการเรียกที่ต่างกันเพียงครั้งเดียว: สองการเรียกที่มีชื่อและอาร์กิวเมนต์เหมือนกันจะมาถึงเป็นรายการเดียว

การเรียก tool แบบสตรีม

เมื่อใช้ 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
    }
  ]
}
เอนด์พอยต์ สิ่งที่ส่งมา
/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 คำขอแบบสตรีมที่มี tools จะส่งข้อความคำตอบใน content delta เดียวเมื่อจบรอบ สตรีมมิง

การส่งผลลัพธ์กลับ

คำขอที่สองส่งบทสนทนาซ้ำและเพิ่มสองอย่าง: รอบของ 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 กลับตามที่ได้รับ ก่อนผลลัพธ์ ผลลัพธ์แต่ละรายการจับคู่กับการเรียกด้วย id: tool_call_id บน /v1/chat/completions, call_id บน /v1/responses, tool_use_id บน /v1/messages
  • ผลลัพธ์เป็นข้อความ แปลงออบเจ็กต์เป็น JSON string สำหรับ content (output บน /v1/responses) บน /v1/messages content ของบล็อก tool_result เป็น string หรือรายการของ text block
  • ในรอบของ assistant function.arguments ยังคงเป็น JSON string ตามที่ได้รับมาทุกประการ
  • บทสนทนาอาจจบด้วยผลลัพธ์ของ tool ไม่ต้องมีข้อความใหม่จากผู้ใช้: โมเดลจะทำงานต่อจากผลลัพธ์
  • เมื่อฟังก์ชันของคุณล้มเหลว ให้ส่งความล้มเหลวนั้นเป็นข้อความผลลัพธ์ โมเดลจะรายงานหรือขอเรียกอีกครั้งได้

คีย์เวิร์ดของ schema

parameters (input_schema บน /v1/messages) คือ 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 ไม่กำหนดจำนวน tool สูงสุดและไม่กำหนดจำนวนรอบสูงสุด
  • เนื้อหาคำขอใหญ่ได้ถึง 32 MiB และบทสนทนาพร้อมผลลัพธ์ต้องพอดีกับ context window ของโมเดล
  • เมื่อคำขอมี tools โมเดล shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite และ shannon-2-pro ใช้ temperature เริ่มต้นเป็น 0.2 ส่ง temperature เพื่อกำหนดค่าอื่น
  • ทุกรอบเป็นคำขอแยกต่างหาก: หักจากยอดคงเหลือของคุณและนับรวมใน flood protection เหมือนคำขออื่น ขีดจำกัดและยอดคงเหลือ

ข้อผิดพลาด

การเรียก tool เป็นคำตอบปกติที่มีสถานะ 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: … เนื้อหาคำขอ (request body) ใหญ่กว่า 32 MiB ข้อผิดพลาดจะมี code: "request_too_large"

โมเดลเป็นผู้เขียนอาร์กิวเมนต์ ให้ตรวจสอบกับ schema ของคุณก่อนรันฟังก์ชัน เหมือนที่ตรวจสอบอินพุตจากภายนอกทุกชนิด

ข้อผิดพลาดด้านการยืนยันตัวตน ยอดคงเหลือ และเซิร์ฟเวอร์ เหมือนกับคำขอทุกประเภท การจัดการข้อผิดพลาด