Durante la creazione di un Messaggio, puoi impostare "stream": true per trasmettere incrementalmente la risposta utilizzando server-sent events (SSE).

Streaming con SDK

I nostri SDK Python e TypeScript offrono diversi modi di streaming. L’SDK Python consente stream sia sincroni che asincroni. Consulta la documentazione in ciascun SDK per i dettagli.

Tipi di eventi

Ogni evento server-sent include un tipo di evento nominato e dati JSON associati. Ogni evento utilizzerà un nome evento SSE (es. event: message_stop), e includerà il corrispondente type di evento nei suoi dati.

Ogni stream utilizza il seguente flusso di eventi:

  1. message_start: contiene un oggetto Message con content vuoto.
  2. Una serie di blocchi di contenuto, ciascuno dei quali ha un content_block_start, uno o più eventi content_block_delta, e un evento content_block_stop. Ogni blocco di contenuto avrà un index che corrisponde al suo indice nell’array finale content del Messaggio.
  3. Uno o più eventi message_delta, che indicano modifiche di alto livello all’oggetto Message finale.
  4. Un evento finale message_stop.

Eventi ping

Gli stream di eventi possono includere anche un qualsiasi numero di eventi ping.

Eventi di errore

Occasionalmente potremmo inviare errori nello stream di eventi. Ad esempio, durante periodi di alto utilizzo, potresti ricevere un overloaded_error, che normalmente corrisponderebbe a un HTTP 529 in un contesto non streaming:

Esempio di errore
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}

Altri eventi

In conformità con la nostra politica di versioning, potremmo aggiungere nuovi tipi di eventi, e il tuo codice dovrebbe gestire i tipi di eventi sconosciuti in modo elegante.

Tipi di delta

Ogni evento content_block_delta contiene un delta di un tipo che aggiorna il blocco content a un determinato index.

Delta di testo

Un delta di contenuto text appare così:

Delta di testo
event: content_block_delta
data: {"type": "content_block_delta","index": 0,"delta": {"type": "text_delta", "text": "ello frien"}}

Delta JSON di input

I delta per i blocchi di contenuto tool_use corrispondono agli aggiornamenti per il campo input del blocco. Per supportare la massima granularità, i delta sono stringhe JSON parziali, mentre l’input finale di tool_use è sempre un oggetto.

Puoi accumulare le stringhe delta e analizzare il JSON una volta ricevuto un evento content_block_stop, utilizzando una libreria come Pydantic per fare il parsing JSON parziale, o utilizzando i nostri SDK, che forniscono helper per accedere ai valori incrementali analizzati.

Un delta del blocco di contenuto tool_use appare così:

Delta JSON di input
event: content_block_delta
data: {"type": "content_block_delta","index": 1,"delta": {"type": "input_json_delta","partial_json": "{\"location\": \"San Fra"}}}

Nota: I nostri modelli attuali supportano solo l’emissione di una proprietà chiave e valore completa da input alla volta. Pertanto, quando si utilizzano gli strumenti, potrebbero esserci ritardi tra gli eventi di streaming mentre il modello sta lavorando. Una volta che una chiave e un valore di input sono accumulati, li emettiamo come multipli eventi content_block_delta con json parziale suddiviso in modo che il formato possa supportare automaticamente una granularità più fine nei modelli futuri.

Risposta HTTP Stream grezza

Raccomandiamo vivamente di utilizzare i nostri SDK client quando si utilizza la modalità streaming. Tuttavia, se stai costruendo un’integrazione API diretta, dovrai gestire questi eventi da solo.

Una risposta stream è composta da:

  1. Un evento message_start
  2. Potenzialmente multipli blocchi di contenuto, ciascuno dei quali contiene: a. Un evento content_block_start b. Potenzialmente multipli eventi content_block_delta c. Un evento content_block_stop
  3. Un evento message_delta
  4. Un evento message_stop

Potrebbero esserci eventi ping dispersi in tutta la risposta. Vedi Tipi di eventi per maggiori dettagli sul formato.

Richiesta di streaming base

Richiesta
curl https://api.anthropic.com/v1/messages \
     --header "anthropic-version: 2023-06-01" \
     --header "content-type: application/json" \
     --header "x-api-key: $ANTHROPIC_API_KEY" \
     --data \
'{
  "model": "claude-3-5-sonnet-20241022",
  "messages": [{"role": "user", "content": "Hello"}],
  "max_tokens": 256,
  "stream": true
}'
Risposta
event: message_start
data: {"type": "message_start", "message": {"id": "msg_1nZdL29xx5MUA1yADyHTEsnR8uuvGzszyY", "type": "message", "role": "assistant", "content": [], "model": "claude-3-5-sonnet-20241022", "stop_reason": null, "stop_sequence": null, "usage": {"input_tokens": 25, "output_tokens": 1}}}

event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}}

event: ping
data: {"type": "ping"}

event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "Hello"}}

event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "!"}}

event: content_block_stop
data: {"type": "content_block_stop", "index": 0}

event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence":null}, "usage": {"output_tokens": 15}}

event: message_stop
data: {"type": "message_stop"}

Richiesta di streaming con uso di strumenti

In questa richiesta, chiediamo a Claude di utilizzare uno strumento per dirci il tempo.

Richiesta
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-3-5-sonnet-20241022",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather in a given location",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city and state, e.g. San Francisco, CA"
              }
            },
            "required": ["location"]
          }
        }
      ],
      "tool_choice": {"type": "any"},
      "messages": [
        {
          "role": "user",
          "content": "What is the weather like in San Francisco?"
        }
      ],
      "stream": true
    }'
Risposta
event: message_start
data: {"type":"message_start","message":{"id":"msg_014p7gG3wDgGV9EUtLvnow3U","type":"message","role":"assistant","model":"claude-3-haiku-20240307","stop_sequence":null,"usage":{"input_tokens":472,"output_tokens":2},"content":[],"stop_reason":null}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: ping
data: {"type": "ping"}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Okay"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" let"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'s"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" check"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" weather"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" San"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Francisco"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" CA"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":":"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01T1x1fJ34qAmk2tNTrN7Up6","name":"get_weather","input":{}}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"location\":"}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"San"}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" Francisc"}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"o,"}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" CA\""}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":", "}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"\"unit\": \"fah"}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"renheit\"}"}}

event: content_block_stop
data: {"type":"content_block_stop","index":1}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":89}}

event: message_stop
data: {"type":"message_stop"}