Salta al contingut
Crida de funcions

Crida de funcions

Descriu les teves funcions a la sol·licitud i el model respon amb les crides que vol que es facin. El teu codi les executa i n'envia els resultats: l'API retorna crides d'eina i no executa cap eina per si mateixa.

POST https://api.shannon-ai.com/v1/chat/completions

Els exemples d'aquesta pàgina fan servir /v1/chat/completions. El mateix bucle funciona a /v1/responses i a /v1/messages; quan un format escriu alguna cosa de manera diferent, les seccions de sota mostren els tres.

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)

La primera resposta no contesta la pregunta. Demana una crida:

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}
  }
}

Després d'enviar el resultat, la resposta següent és una resposta normal: message.content conté el text i finish_reason és stop.

El bucle, pas a pas

Pas Qui Què passa
1 Tu Envia messages juntament amb tools, la llista de funcions que el model pot demanar.
2 Model La resposta porta tool_calls i finish_reason: "tool_calls". Cada crida indica una funció i en dona els arguments.
3 Tu Analitza els arguments de cada crida i executa la teva funció.
4 Tu Afegeix a messages el missatge de l'assistent i un missatge tool per crida, i torna a enviar la sol·licitud amb els mateixos tools.
5 Model El model respon amb text i finish_reason: "stop", o demana més crides. En aquest cas, torna al pas 3.

Una sol·licitud és un torn del model. L'API no conserva cap conversa entre sol·licituds i no fixa cap nombre de rondes: el teu codi guarda messages i decideix quan aturar-se.

Definició d'eines

tools és una matriu amb una entrada per funció. Tots els models del catàleg l'accepten; GET /v1/models informa capabilities.tools: true per a cada id.

Camp Tipus Descripció
type string Sempre function.
function.name string El nom que el model fa servir quan demana aquesta funció. Obligatori.
function.description string Què fa la funció, en llenguatge planer.
function.parameters object Els arguments com a JSON Schema amb type: "object" a dalt de tot. Vegeu Paraules clau de l'esquema més avall.

Cada endpoint té la seva manera d'escriure una eina. Envia la que correspon a l'endpoint que crides:

{
  "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 indica si el model pot, o ha de, cridar una eina. Només es llegeix juntament amb tools.

Valor Descripció S'aplica a
"auto" El model decideix si respon amb text o crida una eina. Aquest és el valor per defecte. Tots els models
"required" La resposta crida almenys una eina. Models open-weight hostejats
{"type": "function", "function": {"name": "get_weather"}} La resposta crida aquesta funció. El nom ha de ser el d'una de les funcions de tools. Les crides a altres funcions no apareixen a la resposta. Models open-weight hostejats

Els models Shannon (shannon-*) decideixen a cada sol·licitud, com amb auto.

Amb required o una funció amb nom, llegeix finish_reason abans de llegir tool_calls. Quan el model no produeix cap crida, la resposta és un text amb finish_reason: "stop".

Significat /v1/chat/completions /v1/responses /v1/messages
El model decideix "auto" "auto" {"type": "auto"}
Crida almenys una eina "required" "required" {"type": "any"}
Crida una funció concreta {"type": "function", "function": {"name": "get_weather"}} {"type": "function", "name": "get_weather"} {"type": "tool", "name": "get_weather"}

S'accepten per compatibilitat: tool_choice: "none" i parallel_tool_calls. Per a un torn sense crides d'eina, envia la sol·licitud sense tools.

Crides d'eina a la resposta

Camp Tipus Descripció
finish_reason string tool_calls quan la resposta porta almenys una crida.
message.tool_calls array Una entrada per crida. El camp només hi és quan el model ha demanat una crida.
tool_calls[].id string call_ seguit de 32 caràcters hexadecimals. Torna'l com a tool_call_id amb el resultat.
tool_calls[].type string Sempre function.
tool_calls[].function.name string La funció que cal executar.
tool_calls[].function.arguments string Els arguments com a cadena JSON, "{}" quan no n'hi ha. Analitza-la abans de fer-la servir.
message.content string | null null quan la resposta conté només crides. Els models open-weight hostejats poden retornar text al costat de les crides; els models Shannon retornen null.

La mateixa crida en cada format. A /v1/responses és un element function_call d'output, amb arguments com a cadena JSON. A /v1/messages és un bloc de contingut tool_use amb input com a objecte JSON, l'id comença per toolu_ i stop_reason és 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\"}"
        }
      }
    ]
  }
}

Diverses crides en un torn

Una resposta pot portar diverses crides. Executa-les totes i envia un resultat per crida, cadascun amb el seu tool_call_id, a la sol·licitud següent.

Els models open-weight hostejats retornen cada crida diferent una sola vegada: dues crides amb el mateix nom i els mateixos arguments arriben com una.

Crides d'eina en streaming

Amb stream: true, una crida arriba d'una sola peça: el fragment conté la cadena arguments completa, així que no cal unir fragments. index compta les crides del torn des de 0.

data: un fragment, amb format
{
  "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 Què arriba
/v1/chat/completions Un chat.completion.chunk per crida, amb la crida a delta.tool_calls[0]. L'últim fragment té finish_reason: "tool_calls" i usage.
/v1/responses Per crida: response.output_item.added (un element function_call amb arguments buit), response.function_call_arguments.delta (la cadena sencera), response.function_call_arguments.done, response.output_item.done.
/v1/messages Per crida: content_block_start (un bloc tool_use amb input buit), un content_block_delta on input_json_delta.partial_json és tot el text dels arguments, content_block_stop. Després message_delta porta stop_reason: "tool_use".

A shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro i shannon-coder-1, una sol·licitud en streaming que porta tools lliura el text de la resposta en un sol delta de content al final del torn. Streaming

Enviament dels resultats

La segona sol·licitud repeteix la conversa i hi afegeix dues coses: el torn de l'assistent que ha demanat les crides i un resultat per crida.

{
  "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\"}"
    }
  ]
}
  • Torna el torn de l'assistent tal com l'has rebut, abans dels resultats. Cada resultat s'associa a la seva crida per l'id: tool_call_id a /v1/chat/completions, call_id a /v1/responses, tool_use_id a /v1/messages.
  • Un resultat és text. Serialitza un objecte a una cadena JSON per a content (output a /v1/responses). A /v1/messages, el content d'un bloc tool_result és una cadena o una llista de blocs de text.
  • Al torn de l'assistent, function.arguments continua sent una cadena JSON, tal com va arribar.
  • La conversa pot acabar amb un resultat d'eina. No cal cap missatge nou de l'usuari: el model continua a partir del resultat.
  • Quan la teva funció falla, envia el fracàs com a text del resultat. El model pot llavors informar-ne o demanar una altra crida.

Paraules clau de l'esquema

parameters (input_schema a /v1/messages) és un JSON Schema. La família Shannon 3 (shannon-3, shannon-3-pro, shannon-3.1, shannon-3.1-pro) i els models open-weight hostejats el reben tal com l'envies.

shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro i shannon-coder-1 reben aquest subconjunt, als tres endpoints:

Tractament Paraules clau
Es llegeix tal com s'envia Totes les paraules clau que no es nomenen a les files de sota, per exemple type, properties, required, items, enum, description, minimum, maximum, anyOf i allOf, a tots els nivells de l'esquema.
format Es llegeix per als valors int32, int64, float, double, byte, date, date-time i enum.
oneOf Es llegeix com a anyOf.
No forma part de l'esquema que reben aquests models $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 i exclusiveMaximum quan són nombres; altres valors de format.

Comportament i límits

  • L'API no fixa cap màxim d'eines ni cap màxim de rondes.
  • El cos d'una sol·licitud pot ser de fins a 32 MiB, i la conversa amb els seus resultats ha de cabre a la finestra de context del model.
  • Quan una sol·licitud porta tools, shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite i shannon-2-pro fan servir una temperature per defecte de 0.2. Envia temperature per fixar-ne un altre valor.
  • Cada ronda és una sol·licitud pròpia: descompta del teu saldo i compta per a la protecció contra inundació com qualsevol altra sol·licitud. Límits i saldo

Errors

Una crida d'eina és una resposta normal amb estat 200. Aquests errors afecten la sol·licitud en si:

Estat Tipus Missatge Quan
400 invalid_request_error unknown model: <id> model no és un id de la llista publicada.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … tools no és una matriu, o un altre camp té un tipus JSON incorrecte.
413 invalid_request_error Failed to buffer the request body: … El cos de la sol·licitud és més gran que 32 MiB. L'error porta code: "request_too_large".

El model escriu els arguments. Comprova'ls amb el teu esquema abans d'executar la funció, com faries amb qualsevol entrada externa.

Els errors d'autenticació, de saldo i del servidor són els mateixos que a qualsevol sol·licitud. Gestió d’errors