Vai al contenuto
Chiamata di funzioni

Chiamata di funzioni

Descrivi le tue funzioni nella richiesta e il modello risponde con le chiamate che vuole eseguire. Il tuo codice le esegue e rimanda i risultati: l'API restituisce le chiamate ai tool e non esegue alcun tool da sola.

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

Gli esempi in questa pagina usano /v1/chat/completions. Lo stesso ciclo funziona su /v1/responses e /v1/messages; dove un formato scrive qualcosa in modo diverso, le sezioni qui sotto mostrano tutti e 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)

La prima risposta non risponde alla domanda. Richiede una chiamata:

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

Dopo che hai inviato il risultato, la risposta successiva è una normale risposta: message.content contiene il testo e finish_reason è stop.

Il ciclo, passo per passo

Passo Chi Cosa succede
1 Tu Invia messages insieme a tools, l'elenco delle funzioni che il modello può richiedere.
2 Modello La risposta porta tool_calls e finish_reason: "tool_calls". Ogni chiamata indica una funzione e ne fornisce gli argomenti.
3 Tu Analizza gli arguments di ogni chiamata ed esegui la tua funzione.
4 Tu Aggiungi a messages il messaggio dell'assistente e un messaggio tool per ogni chiamata, poi invia di nuovo la richiesta con gli stessi tools.
5 Modello Il modello risponde con testo e finish_reason: "stop", oppure richiede altre chiamate. In tal caso torna al passo 3.

Una richiesta è un turno del modello. L'API non conserva alcuna conversazione tra le richieste e non fissa un numero di giri: il tuo codice tiene messages e decide quando fermarsi.

Definire i tool

tools è un array con una voce per funzione. Lo accetta ogni modello del catalogo; GET /v1/models riporta capabilities.tools: true per ogni id.

Campo Tipo Descrizione
type string Sempre function.
function.name string Il nome che il modello usa quando richiede questa funzione. Obbligatorio.
function.description string Cosa fa la funzione, in linguaggio semplice.
function.parameters object Gli argomenti come JSON Schema con type: "object" in cima. Vedi Parole chiave dello schema più sotto.

Ogni endpoint ha una propria scrittura di un tool. Invia quella che appartiene all'endpoint che chiami:

{
  "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 se il modello può, o deve, chiamare un tool. Viene letto solo insieme a tools.

Valore Descrizione Applicato da
"auto" Il modello decide se rispondere con testo o chiamare un tool. È il valore predefinito. Tutti i modelli
"required" La risposta chiama almeno un tool. Modelli open-weight ospitati
{"type": "function", "function": {"name": "get_weather"}} La risposta chiama questa funzione. Il nome deve essere una delle funzioni in tools. Le chiamate ad altre funzioni vengono escluse dalla risposta. Modelli open-weight ospitati

I modelli Shannon (shannon-*) decidono a ogni richiesta, come con auto.

Con required o una funzione indicata per nome, leggi finish_reason prima di leggere tool_calls. Quando il modello non produce alcuna chiamata, la risposta è un testo con finish_reason: "stop".

Significato /v1/chat/completions /v1/responses /v1/messages
Decide il modello "auto" "auto" {"type": "auto"}
Chiama almeno un tool "required" "required" {"type": "any"}
Chiama una funzione indicata per nome {"type": "function", "function": {"name": "get_weather"}} {"type": "function", "name": "get_weather"} {"type": "tool", "name": "get_weather"}

Accettati per compatibilità: tool_choice: "none" e parallel_tool_calls. Per un turno senza chiamate a tool, invia la richiesta senza tools.

Chiamate ai tool nella risposta

Campo Tipo Descrizione
finish_reason string tool_calls quando la risposta porta almeno una chiamata.
message.tool_calls array Una voce per chiamata. Il campo è presente solo quando il modello ha richiesto una chiamata.
tool_calls[].id string call_ seguito da 32 caratteri esadecimali. Rimandalo come tool_call_id insieme al risultato.
tool_calls[].type string Sempre function.
tool_calls[].function.name string La funzione da eseguire.
tool_calls[].function.arguments string Gli argomenti come stringa JSON, "{}" se non ce ne sono. Analizzala prima dell'uso.
message.content string | null null quando la risposta contiene solo chiamate. I modelli open-weight ospitati possono restituire testo accanto alle chiamate; i modelli Shannon restituiscono null.

La stessa chiamata in ogni formato. Su /v1/responses è un elemento function_call di output, con arguments come stringa JSON. Su /v1/messages è un blocco di contenuto tool_use il cui input è un oggetto JSON, il suo id inizia con toolu_ e 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\"}"
        }
      }
    ]
  }
}

Più chiamate in un turno

Una risposta può portare più chiamate. Eseguile tutte e invia un risultato per chiamata, ciascuno con il proprio tool_call_id, nella richiesta successiva.

I modelli open-weight ospitati restituiscono ogni chiamata distinta una sola volta: due chiamate con lo stesso nome e gli stessi argomenti arrivano come una sola.

Chiamate ai tool in streaming

Con stream: true, una chiamata arriva in un solo pezzo: il chunk contiene l'intera stringa arguments, quindi non ci sono frammenti da unire. index conta le chiamate del turno a partire da 0.

data: un chunk, formattato
{
  "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 Cosa arriva
/v1/chat/completions Un chat.completion.chunk per chiamata, con la chiamata in delta.tool_calls[0]. L'ultimo chunk ha finish_reason: "tool_calls" e usage.
/v1/responses Per chiamata: response.output_item.added (un elemento function_call con arguments vuoto), response.function_call_arguments.delta (l'intera stringa), response.function_call_arguments.done, response.output_item.done.
/v1/messages Per chiamata: content_block_start (un blocco tool_use con input vuoto), un content_block_delta il cui input_json_delta.partial_json è l'intero testo degli argomenti, content_block_stop. message_delta porta poi stop_reason: "tool_use".

Su shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro e shannon-coder-1, una richiesta in streaming che porta tools consegna il testo della risposta in un solo delta di content alla fine del turno. Streaming

Rimandare i risultati

La seconda richiesta ripete la conversazione e aggiunge due cose: il turno dell'assistente che ha richiesto le chiamate e un risultato per chiamata.

{
  "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\"}"
    }
  ]
}
  • Rimanda il turno dell'assistente così come l'hai ricevuto, prima dei risultati. Ogni risultato è associato alla sua chiamata tramite id: tool_call_id su /v1/chat/completions, call_id su /v1/responses, tool_use_id su /v1/messages.
  • Un risultato è testo. Serializza un oggetto in una stringa JSON per content (output su /v1/responses). Su /v1/messages il content di un blocco tool_result è una stringa o un elenco di blocchi di testo.
  • Nel turno dell'assistente, function.arguments resta una stringa JSON, esattamente com'è arrivata.
  • La conversazione può terminare con un risultato di tool. Non serve un nuovo messaggio dell'utente: il modello prosegue dal risultato.
  • Quando la tua funzione fallisce, invia l'errore come testo del risultato. Il modello può poi segnalarlo o richiedere un'altra chiamata.

Parole chiave dello schema

parameters (input_schema su /v1/messages) è uno JSON Schema. La famiglia Shannon 3 (shannon-3, shannon-3-pro, shannon-3.1, shannon-3.1-pro) e i modelli open-weight ospitati lo ricevono come lo invii.

shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro e shannon-coder-1 ricevono questo sottoinsieme, su tutti e tre gli endpoint:

Trattamento Parole chiave
Letto come inviato Ogni parola chiave non indicata nelle righe qui sotto, per esempio type, properties, required, items, enum, description, minimum, maximum, anyOf e allOf, a ogni livello dello schema.
format Letto per i valori int32, int64, float, double, byte, date, date-time e enum.
oneOf Letto come anyOf.
Non fa parte dello schema che questi modelli ricevono $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 e exclusiveMaximum quando sono numeri; altri valori di format.

Comportamento e limiti

  • L'API non fissa un numero massimo di tool né un numero massimo di giri.
  • Il corpo di una richiesta può arrivare a 32 MiB, e la conversazione con i suoi risultati deve rientrare nella finestra di contesto del modello.
  • Quando una richiesta porta tools, shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite e shannon-2-pro usano come default una temperature di 0.2. Invia temperature per impostare un altro valore.
  • Ogni giro è una richiesta a sé: attinge al tuo saldo e conta per la flood protection come qualsiasi altra richiesta. Limiti e saldo

Errori

Una chiamata a un tool è una normale risposta con stato 200. Questi errori riguardano la richiesta stessa:

Stato Tipo Messaggio Quando
400 invalid_request_error unknown model: <id> model non è un id dell'elenco pubblicato.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … tools non è un array, oppure un altro campo ha il tipo JSON sbagliato.
413 invalid_request_error Failed to buffer the request body: … Il corpo della richiesta è più grande di 32 MiB. L'errore porta code: "request_too_large".

Gli argomenti li scrive il modello. Verificali rispetto al tuo schema prima di eseguire la funzione, come faresti con qualsiasi input esterno.

Gli errori di autenticazione, di saldo e del server sono gli stessi di ogni richiesta. Gestione errori