קריאת פונקציות
תארו את הפונקציות שלכם בבקשה והמודל משיב עם הקריאות שהוא רוצה שיבוצעו. הקוד שלכם מריץ אותן ושולח את התוצאות בחזרה: ה-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) import OpenAI from "openai";
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1" });
const 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"],
},
},
}];
// Your code: ask a weather service here.
function getWeather({ city, unit = "celsius" }) {
return { city, temperature: 18, unit, conditions: "cloudy" };
}
const messages = [{ role: "user", content: "What is the weather in Paris right now?" }];
let answer = null;
// The API sets no limit on rounds: set your own.
for (let round = 0; round < 5; round++) {
const response = await client.chat.completions.create({
model: "Kimi-K3-3BIT-REAP",
messages,
tools,
});
const choice = response.choices[0];
if (choice.finish_reason !== "tool_calls") {
answer = choice.message.content;
break;
}
messages.push(choice.message); // the assistant turn with its tool_calls
for (const call of choice.message.tool_calls) {
const args = JSON.parse(call.function.arguments); // arguments is a JSON string
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(getWeather(args)),
});
}
}
console.log(answer); # 1. Send the conversation with the tools.
curl https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Kimi-K3-3BIT-REAP",
"messages": [
{"role": "user", "content": "What is the weather in Paris right now?"}
],
"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"]
}
}
}]
}'
# 2. Run the function yourself, then send the assistant turn and the result.
# Use the id of the call you received.
curl https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Kimi-K3-3BIT-REAP",
"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\"}"}
],
"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"]
}
}
}]
}' התשובה הראשונה אינה עונה על השאלה. היא מבקשת קריאה:
{
"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 | אתם | הוסיפו ל-messages את הודעת ה-assistant והודעת tool אחת לכל קריאה, ושלחו שוב את הבקשה עם אותו 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" בראשו. ראו מילות מפתח של הסכמה בהמשך. |
לכל 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"]
}
}
} {
"type": "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"]
}
} {
"name": "get_weather",
"description": "Get the current weather for a city.",
"input_schema": {
"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 או עם פונקציה בשם, קראו את finish_reason לפני tool_calls. כשהמודל לא מפיק קריאה, התשובה היא תשובת טקסט עם 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 כשהתשובה מכילה קריאות בלבד. מודלי ה-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\"}"
}
}
]
}
} {
"output": [
{
"id": "fc_3d2c1b0a9f8e4d7c6b5a4f3e2d1c0b9a",
"type": "function_call",
"call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}",
"status": "completed"
}
]
} {
"stop_reason": "tool_use",
"content": [
{
"type": "tool_use",
"id": "toolu_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"input": {"city": "Paris"}
}
]
} כמה קריאות בתור אחד
תשובה יכולה לשאת כמה קריאות. הריצו את כולן ושלחו תוצאה אחת לכל קריאה, כל אחת עם tool_call_id משלה, בבקשה הבאה.
מודלי ה-open-weight המתארחים מחזירים כל קריאה ייחודית פעם אחת: שתי קריאות עם אותו שם ואותם ארגומנטים מגיעות כקריאה אחת.
קריאות לכלים ב-streaming
עם stream: true, קריאה מגיעה בחתיכה אחת: ה-chunk מכיל את מחרוזת arguments השלמה, ולכן אין שברים לחבר. index סופר את הקריאות של התור החל מ-0.
{
"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, בקשה ב-streaming שנושאת 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\"}"
}
]
} {
"input": [
{"role": "user", "content": "What is the weather in Paris right now?"},
{
"type": "function_call",
"call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
},
{
"type": "function_call_output",
"call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"output": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"
}
]
} {
"messages": [
{"role": "user", "content": "What is the weather in Paris right now?"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"input": {"city": "Paris"}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_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. - תוצאה היא טקסט. סדרו אובייקט למחרוזת JSON עבור
content(outputב-/v1/responses). ב-/v1/messagesה-contentשל בלוקtool_resultהוא מחרוזת או רשימה של בלוקי טקסט. - בתור ה-assistant,
function.argumentsנשאר מחרוזת JSON, בדיוק כפי שהגיע. - השיחה יכולה להסתיים בתוצאה של כלי. אין צורך בהודעת משתמש חדשה: המודל ממשיך מהתוצאה.
- כשהפונקציה שלכם נכשלת, שלחו את הכשל כטקסט התוצאה. המודל יכול אז לדווח עליו או לבקש קריאה אחרת.
מילות מפתח של הסכמה
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 מקבלים את תת-הקבוצה הזו, בשלושת ה-endpoints:
| טיפול | מילות מפתח |
|---|---|
| נקרא כפי שנשלח | כל מילת מפתח שאינה נזכרת בשורות שלהלן, למשל 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 אינו מזהה מהרשימה שפורסמה. |
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". |
המודל כותב את הארגומנטים. בדקו אותם מול הסכמה שלכם לפני שאתם מריצים את הפונקציה, כמו שבודקים כל קלט חיצוני.
שגיאות אימות, יתרה ושרת זהות לאלה של כל בקשה. טיפול בשגיאות