Usare l'API Risposte in modalità WebSocket

L'API delle Risposte supporta una modalità WebSocket per flussi di lavoro di lunga durata ricchi di strumenti. In modalità WebSocket si mantiene una connessione permanente a /v1/responses e si continua ogni turno inviando solo nuovi elementi di input insieme a un oggetto previous_response_id. Questo approccio riduce il sovraccarico per turno e migliora la latenza end-to-end tra catene lunghe.

La modalità WebSocket funziona con store=false.

Prerequisiti

  • Modello OpenAI Azure distribuito.
  • Metodo di autenticazione:
    • Chiave API o
    • Microsoft Entra ID.
  • Per esempi di Python:
    • Installare il websocket-client pacchetto.
    • Installare azure-identity per l'autenticazione di Microsoft Entra ID.

Quando usare la modalità WebSocket

Usare la modalità WebSocket quando un flusso di lavoro prevede molti round trip dello strumento modello, ad esempio la codifica agentica o i cicli di orchestrazione con chiamate ripetute agli strumenti. Poiché la connessione rimane aperta e ogni turno invia solo input incrementale, la latenza di continuazione è inferiore a quella delle richieste HTTP ripetute.

Per le richieste a singolo colpo o brevi conversazioni, continuate a usare l'API delle risposte HTTP standard.

Come funziona

Si apre una connessione WebSocket a /v1/responses e la si guida con eventi response.create.

  • Il primo response.create avvia un nuovo turno. Il payload riflette il corpo di creazione HTTP, tranne che i campi specifici del trasporto come stream e background non si applicano.
  • Catena di messaggi response.create di follow-up dalla risposta precedente usando previous_response_id e includendo solo i nuovi elementi di input.

Gli eventi del server e l'ordinamento corrispondono al modello di evento di streaming delle risposte esistente.

Avviare un turno

Inviare un evento response.create al socket aperto. Gli esempi seguenti si connettono all'endpoint WebSocket e chiedono al modello una domanda. La modalità WebSocket supporta sia la chiave API che l'autenticazione Microsoft Entra ID: scegliere la scheda corrispondente al metodo di autenticazione.

from websocket import create_connection
import json

ws = create_connection(
    f"wss://{YOUR_RESOURCE_NAME}.openai.azure.com/openai/v1/responses",
    header=[f"Authorization: Bearer {YOUR_AOAI_API_KEY}"],
)

ws.send(json.dumps({
    "type": "response.create",
    "model": "gpt-4.1", # Replace with your model deployment name
    "store": False,
    "input": [
        {
            "type": "message",
            "role": "user",
            "content": [{"type": "input_text", "text": "Find fizz_buzz()"}],
        }
    ],
    "tools": [],
}))

Suggerimento

Facoltativamente, è possibile scaldare lo stato della richiesta inviando response.create con generate: false. Usare questa opzione quando si conoscono già gli strumenti, le istruzioni o i messaggi che si prevede di inviare con un turno imminente. Un riscaldamento non restituisce l'output del modello, ma prepara lo stato della richiesta affinché il successivo turno generato possa iniziare più rapidamente. La richiesta di riscaldamento restituisce un ID risposta da cui è possibile eseguire la concatenazione usando previous_response_id.

Trasmettere la risposta

Leggere eventi dal WebSocket, stampare il testo man mano che arriva e interrompere quando la risposta è terminata.

while True:
    event = json.loads(ws.recv())

    if event["type"] == "response.output_text.delta":
        print(event["delta"], end="", flush=True)

    elif event["type"] == "response.completed":
        response_id = event.get("response", {}).get("id")
        print(f"\nResponse ID: {response_id}")
        break

# Close the socket only when you are done with all turns.
# ws.close()

Continuare con gli input incrementali

Per continuare la stessa catena, inviare un altro response.create sullo stesso socket con:

  • previous_response_id impostato sull'ID risposta precedente.
  • input contenente solo nuovi elementi, ad esempio output degli strumenti e il messaggio utente successivo.
ws.send(json.dumps({
    "type": "response.create",
    "model": "gpt-4.1",
    "store": False,
    "previous_response_id": f"{response_id}",
    "input": [
        {
            "type": "message",
            "role": "user",
            "content": [{"type": "input_text", "text": "Now optimize it."}],
        },
    ],
    "tools": [],
}))

Semantica di continuazione

La modalità WebSocket usa la stessa previous_response_id concatenazione della modalità HTTP, ma aggiunge un percorso di continuazione a bassa latenza nel socket attivo.

Per i flussi di lavoro multi-agente, inserire gli output delle funzioni definite dallo sviluppatore nella risposta attiva in modo che l'agente in attesa possa riprendere mentre altri agenti continuano. Vedere Usare l'orchestrazione multi-agente con l'API Risposte OpenAI Azure.

In una connessione WebSocket attiva, il servizio mantiene uno stato precedente della risposta in una cache in memoria locale della connessione (la risposta più recente). Continuare da tale risposta è veloce perché il servizio riutilizza lo stato locale della connessione. Poiché questo stato viene mantenuto solo in memoria e non viene scritto su disco, la modalità WebSocket è compatibile con store=false.

Se un previous_response_id oggetto non si trova nella cache in memoria, il comportamento dipende dal fatto che le risposte siano archiviate:

  • Con store=true, il servizio potrebbe idratare gli ID risposta meno recenti dallo stato persistente. La continuazione funziona ancora, ma in genere perde il vantaggio di latenza in memoria.
  • Con store=false, non esiste un fallback persistente. Se l'ID non è memorizzato nella cache, la richiesta restituisce previous_response_not_found.

Se un turno ha esito negativo (4xx o 5xx), il servizio rimuove l'oggetto a cui viene fatto previous_response_id riferimento dalla cache locale della connessione. Questa eliminazione impedisce il riutilizzo dello stato della cache obsoleto per quella continuazione fallita.

Compattazione

Se si usa la compattazione del contesto, esistono due modelli di continuazione diversi.

Compattazione lato server

Quando si abilita la compattazione lato server (context_management con compact_threshold), la compattazione avviene durante la generazione normale /responses . In modalità WebSocket si continua allo stesso modo in cui normalmente si esegue: inviare il successivo response.create con gli elementi di input più recenti previous_response_id e solo nuovi.

/responses/compact autonomo

L'endpoint autonomo /responses/compact restituisce una nuova finestra di input compattata, non un ID risposta. Dopo la compattazione, inizia una nuova risposta sulla tua connessione WebSocket omettendo previous_response_id (o impostandolo su null) e utilizzando l'output compattato come input, insieme ai successivi elementi dell'utente o degli strumenti. Passare l'output compattato così com'è; non eliminare la finestra restituita.

# Compact your current window (HTTP call)
compacted = client.responses.compact(
    model="gpt-4.1",
    input=long_input_items_array,
)

# Start a new response on the WebSocket using the compacted window
ws.send(json.dumps({
    "type": "response.create",
    "model": "gpt-4.1",
    "store": False,
    "input": [
        *compacted.output,
        {
            "type": "message",
            "role": "user",
            "content": [{"type": "input_text", "text": "Continue from here."}],
        },
    ],
    "tools": [],
}))

Comportamento e limiti della connessione

  • Una singola connessione WebSocket può ricevere più messaggi response.create, ma li esegue in sequenza (una risposta in elaborazione alla volta).
  • La connessione non supporta il multiplexing. Usare più connessioni se sono necessarie esecuzioni parallele.
  • La durata della connessione è limitata a 60 minuti. Riconnettere quando si raggiunge il limite.

Riconnettersi e ripristinare

Quando una connessione si chiude o raggiunge il limite di 60 minuti, aprire una nuova connessione WebSocket e continuare con uno di questi modelli:

  • Se la risposta precedente è persistente (store=true) e si dispone di un ID di risposta valido, continuare con previous_response_id e nuovi elementi di input.
  • Se non è possibile continuare la catena (ad esempio, store=false o previous_response_not_found), avviare una nuova risposta omettendolo previous_response_id (o impostandolo su null) e inviare il contesto di input completo per il turno successivo.
  • Se il contesto è stato compattato con /responses/compact, usare la finestra compattata restituita come base input per la nuova risposta, quindi aggiungere gli elementi dell'utente o degli strumenti più recenti.

Risoluzione dei problemi

  • previous_response_not_found: l'ID risposta a cui si fa riferimento non si trova nella cache locale della connessione e non esiste uno stato persistente da cui idratarsi. Avvia una nuova catena o abilita store=true se lo scenario lo consente.

    {
      "type": "error",
      "status": 400,
      "error": {
        "code": "previous_response_not_found",
        "message": "Previous response with id 'resp_abc' not found.",
        "param": "previous_response_id"
      }
    }
    
  • websocket_connection_limit_reached: la connessione è aperta per 60 minuti. Aprire una nuova connessione WebSocket e continuare a usare uno dei modelli di riconnessione e ripristino .

    {
      "type": "error",
      "status": 400,
      "error": {
        "type": "invalid_request_error",
        "code": "websocket_connection_limit_reached",
        "message": "Responses websocket connection limit reached (60 minutes). Create a new websocket connection to continue."
      }
    }
    

Passaggio successivo