Funktionsanrop
Beskriv dina funktioner i begäran så svarar modellen med de anrop den vill ha gjorda. Din kod kör dem och skickar tillbaka resultaten: API:et returnerar verktygsanrop och kör inget verktyg själv.
POST https://api.shannon-ai.com/v1/chat/completions
Exemplen på den här sidan använder /v1/chat/completions. Samma loop körs på /v1/responses och /v1/messages; där ett format stavar något annorlunda visar avsnitten nedan alla tre.
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"]
}
}
}]
}' Det första svaret besvarar inte frågan. Det ber om ett anrop:
{
"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}
}
} När du har skickat resultatet är nästa svar ett vanligt svar: message.content innehåller texten och finish_reason är stop.
Loopen, steg för steg
| Steg | Vem | Vad som händer |
|---|---|---|
| 1 | Du | Skicka messages tillsammans med tools, listan över funktioner som modellen får be om. |
| 2 | Modell | Svaret bär tool_calls och finish_reason: "tool_calls". Varje anrop anger en funktion och dess argument. |
| 3 | Du | Parsa arguments i varje anrop och kör din funktion. |
| 4 | Du | Lägg till assistentmeddelandet och ett tool-meddelande per anrop i messages och skicka sedan begäran igen med samma tools. |
| 5 | Modell | Modellen svarar med text med finish_reason: "stop", eller ber om fler anrop. Gå i så fall tillbaka till steg 3. |
En begäran är en modellomgång. API:et sparar ingen konversation mellan begäranden och sätter inget antal rundor: din kod håller messages och avgör när den ska sluta.
Definiera verktyg
tools är en array med en post per funktion. Varje modell i katalogen accepterar den; GET /v1/models anger capabilities.tools: true för varje id.
| Fält | Typ | Beskrivning |
|---|---|---|
type | string | Alltid function. |
function.name | string | Namnet som modellen använder när den ber om den här funktionen. Obligatoriskt. |
function.description | string | Vad funktionen gör, i vanligt språk. |
function.parameters | object | Argumenten som ett JSON Schema med type: "object" överst. Se Schemanyckelord nedan. |
Varje endpoint har sin egen stavning av ett verktyg. Skicka den som hör till den endpoint du anropar:
{
"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 anger om modellen får, eller måste, anropa ett verktyg. Det läses bara tillsammans med tools.
| Värde | Beskrivning | Tillämpas av |
|---|---|---|
"auto" | Modellen avgör om den ska svara med text eller anropa ett verktyg. Detta är standard. | Alla modeller |
"required" | Svaret anropar minst ett verktyg. | Hostade open-weight-modeller |
{"type": "function", "function": {"name": "get_weather"}} | Svaret anropar den här funktionen. Namnet måste vara en av funktionerna i tools. Anrop till andra funktioner utelämnas ur svaret. | Hostade open-weight-modeller |
Shannon-modellerna (shannon-*) avgör i varje begäran, som med auto.
Med required eller en namngiven funktion: läs finish_reason innan du läser tool_calls. När modellen inte ger något anrop är svaret ett textsvar med finish_reason: "stop".
| Betydelse | /v1/chat/completions | /v1/responses | /v1/messages |
|---|---|---|---|
| Modellen avgör | "auto" | "auto" | {"type": "auto"} |
| Anropa minst ett verktyg | "required" | "required" | {"type": "any"} |
| Anropa en namngiven funktion | {"type": "function", "function": {"name": "get_weather"}} | {"type": "function", "name": "get_weather"} | {"type": "tool", "name": "get_weather"} |
Accepteras för kompatibilitet: tool_choice: "none" och parallel_tool_calls. För en omgång utan verktygsanrop, skicka begäran utan tools.
Verktygsanrop i svaret
| Fält | Typ | Beskrivning |
|---|---|---|
finish_reason | string | tool_calls när svaret bär minst ett anrop. |
message.tool_calls | array | En post per anrop. Fältet finns bara när modellen bad om ett anrop. |
tool_calls[].id | string | call_ följt av 32 hexadecimala tecken. Skicka tillbaka det som tool_call_id tillsammans med resultatet. |
tool_calls[].type | string | Alltid function. |
tool_calls[].function.name | string | Funktionen som ska köras. |
tool_calls[].function.arguments | string | Argumenten som en JSON-sträng, "{}" när det inte finns några. Parsa den före användning. |
message.content | string | null | null när svaret bara innehåller anrop. De hostade open-weight-modellerna kan returnera text vid sidan av anropen; Shannon-modellerna returnerar null. |
Samma anrop i varje format. På /v1/responses är det ett function_call-objekt i output, med arguments som JSON-sträng. På /v1/messages är det ett tool_use-innehållsblock vars input är ett JSON-objekt, vars id börjar med toolu_, och stop_reason är 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"}
}
]
} Flera anrop i en omgång
Ett svar kan bära flera anrop. Kör alla och skicka ett resultat per anrop, vart och ett med sitt eget tool_call_id, i nästa begäran.
De hostade open-weight-modellerna returnerar varje distinkt anrop en gång: två anrop med samma namn och samma argument kommer som ett.
Streamade verktygsanrop
Med stream: true kommer ett anrop i ett stycke: chunken innehåller hela arguments-strängen, så det finns inga fragment att foga ihop. index räknar omgångens anrop från 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 | Vad som kommer |
|---|---|
/v1/chat/completions | En chat.completion.chunk per anrop, med anropet i delta.tool_calls[0]. Sista chunken har finish_reason: "tool_calls" och usage. |
/v1/responses | Per anrop: response.output_item.added (ett function_call-objekt med tomma arguments), response.function_call_arguments.delta (hela strängen), response.function_call_arguments.done, response.output_item.done. |
/v1/messages | Per anrop: content_block_start (ett tool_use-block med tomt input), ett content_block_delta vars input_json_delta.partial_json är hela argumenttexten, content_block_stop. message_delta bär därefter stop_reason: "tool_use". |
På shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro och shannon-coder-1 levererar en streamad begäran som bär tools sin svarstext i ett enda content-delta i slutet av omgången. Streaming
Skicka tillbaka resultat
Den andra begäran upprepar konversationen och lägger till två saker: assistentomgången som bad om anropen och ett resultat per anrop.
{
"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\"}"
}
]
}
]
} - Skicka tillbaka assistentomgången som du fick den, före resultaten. Varje resultat matchas mot sitt anrop via id:
tool_call_idpå/v1/chat/completions,call_idpå/v1/responses,tool_use_idpå/v1/messages. - Ett resultat är text. Serialisera ett objekt till en JSON-sträng för
content(outputpå/v1/responses). På/v1/messagesärcontenti etttool_result-block en sträng eller en lista med textblock. - I assistentomgången förblir
function.argumentsen JSON-sträng, precis som den kom. - Konversationen får sluta med ett verktygsresultat. Inget nytt användarmeddelande behövs: modellen fortsätter från resultatet.
- När din funktion misslyckas, skicka felet som resultattext. Modellen kan då rapportera det eller be om ett annat anrop.
Schemanyckelord
parameters (input_schema på /v1/messages) är ett JSON Schema. Shannon 3-familjen (shannon-3, shannon-3-pro, shannon-3.1, shannon-3.1-pro) och de hostade open-weight-modellerna får det som du skickar det.
shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro och shannon-coder-1 får den här delmängden, på alla tre endpoints:
| Hantering | Nyckelord |
|---|---|
| Läses som skickat | Varje nyckelord som inte nämns i raderna nedan, till exempel type, properties, required, items, enum, description, minimum, maximum, anyOf och allOf, på varje nivå i schemat. |
format | Läses för värdena int32, int64, float, double, byte, date, date-time och enum. |
oneOf | Läses som anyOf. |
| Ingår inte i det schema som de här modellerna får | $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 och exclusiveMaximum när de är tal; andra värden för format. |
Beteende och gränser
- API:et sätter inget maximalt antal verktyg och inget maximalt antal rundor.
- En begäranskropp kan vara upp till 32 MiB, och konversationen med sina resultat måste rymmas i modellens kontextfönster.
- När en begäran bär
toolsanvändershannon-1.6-lite,shannon-1.6-pro,shannon-2-liteochshannon-2-proen standard-temperaturepå 0.2. Skickatemperatureför att ange ett annat värde. - Varje runda är en egen begäran: den drar från din balans och räknas mot flood protection som vilken annan begäran som helst. Gränser och balans
Fel
Ett verktygsanrop är ett vanligt svar med status 200. Dessa fel gäller själva begäran:
| Status | Typ | Meddelande | När |
|---|---|---|---|
400 | invalid_request_error | unknown model: <id> | model är inte ett id i den publicerade listan. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | tools är inte en array, eller ett annat fält har fel JSON-typ. |
413 | invalid_request_error | Failed to buffer the request body: … | Begäranskroppen är större än 32 MiB. Felet bär code: "request_too_large". |
Modellen skriver argumenten. Kontrollera dem mot ditt schema innan du kör funktionen, som du skulle kontrollera all annan extern input.
Autentiserings-, balans- och serverfel är desamma som för varje begäran. Felhantering