Funksjonskall
Beskriv funksjonene dine i forespørselen, så svarer modellen med kallene den vil ha utført. Koden din kjører dem og sender resultatene tilbake: API-et returnerer verktøykall og kjører ikke selv noe verktøy.
POST https://api.shannon-ai.com/v1/chat/completions
Eksemplene på denne siden bruker /v1/chat/completions. Den samme sløyfen kjører på /v1/responses og /v1/messages; der et format staver noe annerledes, viser avsnittene nedenfor alle 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ørste svaret besvarer ikke spørsmålet. Det ber om et kall:
{
"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}
}
} Etter at du har sendt resultatet, er det neste svaret et vanlig svar: message.content har teksten og finish_reason er stop.
Sløyfen, steg for steg
| Steg | Hvem | Hva som skjer |
|---|---|---|
| 1 | Du | Send messages sammen med tools, listen over funksjoner modellen kan be om. |
| 2 | Modell | Svaret har tool_calls og finish_reason: "tool_calls". Hvert kall oppgir en funksjon og gir argumentene. |
| 3 | Du | Parse arguments i hvert kall og kjør funksjonen din. |
| 4 | Du | Legg assistentmeldingen og én tool-melding per kall til i messages, og send så forespørselen på nytt med samme tools. |
| 5 | Modell | Modellen svarer med tekst og finish_reason: "stop", eller ber om flere kall. I så fall går du tilbake til steg 3. |
Én forespørsel er én modellrunde. API-et lagrer ingen samtale mellom forespørsler og setter ikke noe antall runder: koden din holder messages og avgjør når den skal stoppe.
Definere verktøy
tools er en matrise med én oppføring per funksjon. Alle modeller i katalogen godtar den; GET /v1/models rapporterer capabilities.tools: true for hver id.
| Felt | Type | Beskrivelse |
|---|---|---|
type | string | Alltid function. |
function.name | string | Navnet modellen bruker når den ber om denne funksjonen. Påkrevd. |
function.description | string | Hva funksjonen gjør, i klart språk. |
function.parameters | object | Argumentene som et JSON Schema med type: "object" øverst. Se Skjema-nøkkelord nedenfor. |
Hvert endepunkt har sin egen skrivemåte for et verktøy. Send den som hører til endepunktet du kaller:
{
"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 sier om modellen kan eller må kalle et verktøy. Det leses bare sammen med tools.
| Verdi | Beskrivelse | Brukes av |
|---|---|---|
"auto" | Modellen bestemmer om den svarer med tekst eller kaller et verktøy. Dette er standard. | Alle modeller |
"required" | Svaret kaller minst ett verktøy. | Hostede åpne vektmodeller |
{"type": "function", "function": {"name": "get_weather"}} | Svaret kaller denne funksjonen. Navnet må være en av funksjonene i tools. Kall til andre funksjoner utelates fra svaret. | Hostede åpne vektmodeller |
Shannon-modellene (shannon-*) bestemmer i hver forespørsel, som med auto.
Med required eller en navngitt funksjon, les finish_reason før du leser tool_calls. Når modellen ikke produserer noe kall, er svaret et tekstsvar med finish_reason: "stop".
| Betydning | /v1/chat/completions | /v1/responses | /v1/messages |
|---|---|---|---|
| Modellen bestemmer | "auto" | "auto" | {"type": "auto"} |
| Kall minst ett verktøy | "required" | "required" | {"type": "any"} |
| Kall én navngitt funksjon | {"type": "function", "function": {"name": "get_weather"}} | {"type": "function", "name": "get_weather"} | {"type": "tool", "name": "get_weather"} |
Godtatt for kompatibilitet: tool_choice: "none" og parallel_tool_calls. For en runde uten verktøykall sender du forespørselen uten tools.
Verktøykall i svaret
| Felt | Type | Beskrivelse |
|---|---|---|
finish_reason | string | tool_calls når svaret har minst ett kall. |
message.tool_calls | array | Én oppføring per kall. Feltet finnes bare når modellen ba om et kall. |
tool_calls[].id | string | call_ etterfulgt av 32 heksadesimale tegn. Send den tilbake som tool_call_id sammen med resultatet. |
tool_calls[].type | string | Alltid function. |
tool_calls[].function.name | string | Funksjonen som skal kjøres. |
tool_calls[].function.arguments | string | Argumentene som en JSON-streng, "{}" når det ikke finnes noen. Parse den før bruk. |
message.content | string | null | null når svaret bare inneholder kall. De hostede åpne vektmodellene kan returnere tekst ved siden av kallene; Shannon-modellene returnerer null. |
Det samme kallet i hvert format. På /v1/responses er det et function_call-element i output, med arguments som JSON-streng. På /v1/messages er det en tool_use-innholdsblokk der input er et JSON-objekt, id begynner med toolu_, og stop_reason er 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"}
}
]
} Flere kall i én runde
Et svar kan ha flere kall. Kjør hvert av dem og send ett resultat per kall, hvert med sin egen tool_call_id, i neste forespørsel.
De hostede åpne vektmodellene returnerer hvert distinkte kall én gang: to kall med samme navn og samme argumenter kommer som ett.
Strømmede verktøykall
Med stream: true kommer et kall i ett stykke: chunken har hele arguments-strengen, så det er ingen fragmenter å sette sammen. index teller kallene i runden fra 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
}
]
} | Endepunkt | Hva som kommer |
|---|---|
/v1/chat/completions | Én chat.completion.chunk per kall, med kallet i delta.tool_calls[0]. Den siste chunken har finish_reason: "tool_calls" og usage. |
/v1/responses | Per kall: response.output_item.added (et function_call-element med tomme arguments), response.function_call_arguments.delta (hele strengen), response.function_call_arguments.done, response.output_item.done. |
/v1/messages | Per kall: content_block_start (en tool_use-blokk med tom input), én content_block_delta der input_json_delta.partial_json er hele argumentteksten, content_block_stop. message_delta har deretter stop_reason: "tool_use". |
På shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro og shannon-coder-1 leverer en strømmet forespørsel med tools svarteksten i én content-delta på slutten av runden. Strømming
Sende resultater tilbake
Den andre forespørselen gjentar samtalen og legger til to ting: assistentrunden som ba om kallene, og ett resultat per kall.
{
"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\"}"
}
]
}
]
} - Send assistentrunden tilbake slik du mottok den, før resultatene. Hvert resultat knyttes til kallet sitt via id:
tool_call_idpå/v1/chat/completions,call_idpå/v1/responses,tool_use_idpå/v1/messages. - Et resultat er tekst. Serialiser et objekt til en JSON-streng for
content(outputpå/v1/responses). På/v1/messagesercontenti entool_result-blokk en streng eller en liste med tekstblokker. - I assistentrunden forblir
function.argumentsen JSON-streng, nøyaktig slik den kom. - Samtalen kan ende med et verktøyresultat. Ingen ny brukermelding trengs: modellen fortsetter fra resultatet.
- Når funksjonen din feiler, send feilen som resultattekst. Modellen kan da rapportere den eller be om et nytt kall.
Skjema-nøkkelord
parameters (input_schema på /v1/messages) er et JSON Schema. Shannon 3-familien (shannon-3, shannon-3-pro, shannon-3.1, shannon-3.1-pro) og de hostede åpne vektmodellene mottar det slik du sender det.
shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro og shannon-coder-1 mottar denne delmengden, på alle tre endepunktene:
| Behandling | Nøkkelord |
|---|---|
| Leses slik det er sendt | Alle nøkkelord som ikke er nevnt i radene nedenfor, for eksempel type, properties, required, items, enum, description, minimum, maximum, anyOf og allOf, på alle nivåer i skjemaet. |
format | Leses for verdiene int32, int64, float, double, byte, date, date-time og enum. |
oneOf | Leses som anyOf. |
| Ikke en del av skjemaet disse modellene mottar | $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 og exclusiveMaximum når de er tall; andre verdier av format. |
Oppførsel og grenser
- API-et setter ingen øvre grense for antall verktøy og ingen øvre grense for antall runder.
- En forespørselskropp kan være opptil 32 MiB, og samtalen med resultatene må få plass i kontekstvinduet til modellen.
- Når en forespørsel har
tools, brukershannon-1.6-lite,shannon-1.6-pro,shannon-2-liteogshannon-2-proen standardtemperaturepå 0.2. Sendtemperaturefor å sette en annen verdi. - Hver runde er en egen forespørsel: den trekker fra saldoen din og teller med i flood protection som alle andre forespørsler. Grenser og saldo
Feil
Et verktøykall er et vanlig svar med status 200. Disse feilene gjelder selve forespørselen:
| Status | Type | Melding | Når |
|---|---|---|---|
400 | invalid_request_error | unknown model: <id> | model er ikke en id i den publiserte listen. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | tools er ikke en matrise, eller et annet felt har feil JSON-type. |
413 | invalid_request_error | Failed to buffer the request body: … | Forespørselskroppen er større enn 32 MiB. Feilen har code: "request_too_large". |
Modellen skriver argumentene. Sjekk dem mot skjemaet ditt før du kjører funksjonen, slik du ville sjekket all annen ekstern input.
Autentisering, saldo og serverfeil er de samme som for alle forespørsler. Feilhåndtering