Réponses et streaming
- Normative
- Brouillon 1.0
- Mis à jour
- Afficher en Markdown
6.1 Requête
POST /lmsp/v1/responses
Authorization: Bearer <token>
Content-Type: application/json
Idempotency-Key: 01J8M5T7Z2K4N6Q8S0V3X5B9DG
LMSP-Version: 1.0
{
"model": "qwen3:14b-q4_k_m",
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Describe a local model service in one sentence."
}
]
}
],
"stream": false,
"max_output_tokens": 512,
"temperature": 0.7,
"response_format": {
"type": "text"
},
"store": true
}
Le protocole principal utilise une structure input et output de style Responses plutôt qu’une simple liste de chaînes de messages, afin qu’une seule forme de requête puisse transporter :
- des messages multi-tours ;
- du texte, des images, du son et des fichiers ;
- des appels d’outils et des résultats d’outils ;
- une sortie structurée ;
- des résumés de raisonnement ;
- une sortie multimodale.
LMSP 1.0 ne définit que le contenu texte. Les types de contenu image, audio et fichier sont réservés à de futures versions.
| Champ | Obligatoire | Signification |
|---|---|---|
model |
Oui | Identifiant du modèle à utiliser. |
input |
Oui | Tableau d’éléments d’entrée. Un élément message a un role (system, user ou assistant) et un tableau content de parties, comme input_text. L’usage d’outils ajoute des éléments function_call et function_call_output (section 6.5). |
stream |
Non | true pour recevoir des événements envoyés par le serveur. Vaut false par défaut. |
max_output_tokens |
Non | Borne supérieure du nombre de tokens générés. |
temperature |
Non | Température d’échantillonnage. |
response_format |
Non | {"type": "text"} (la valeur par défaut), ou {"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}} pour une sortie structurée. Exige la capacité structured_output. |
tools, tool_choice |
Non | Outils de type fonction que le modèle peut appeler (section 6.5). Exige la capacité tools. |
store |
Non | Demande au service de conserver la réponse, afin qu’elle puisse être récupérée plus tard et servir de previous_response_id. Vaut false par défaut. Ignoré par les services sans la capacité conversations. |
previous_response_id |
Non | Poursuit à partir d’une réponse stockée. Exige la capacité conversations. |
extensions |
Non | Extensions privées (section 9.1). |
Une requête qui exige une capacité que le modèle n’a pas est rejetée avec 400 et unsupported_capability. Une requête qui ne tient pas dans la fenêtre de contexte est rejetée avec 400 et context_length_exceeded.
Un service capable de stocker des conversations PEUT aussi prendre en charge previous_response_id. Sinon, chaque requête DOIT porter le contexte complet. Un service NE DOIT PAS compter sur la connexion HTTP pour conserver l’état de la conversation.
6.2 Réponse synchrone
Lorsque stream vaut false, le service renvoie 200 OK avec un objet réponse une fois la génération terminée.
{
"id": "resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF",
"object": "response",
"created_at": 1794200000,
"status": "completed",
"model": "qwen3:14b-q4_k_m",
"output": [
{
"id": "msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE",
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "A local model service is a resident interface layer that discovers, manages and calls models on the user's own device."
}
]
}
],
"usage": {
"input_tokens": 28,
"output_tokens": 31,
"total_tokens": 59
},
"error": null,
"incomplete_details": null
}
| Champ | Signification |
|---|---|
id |
Identifiant de la réponse, tel que resp_.... |
object |
Toujours "response". |
created_at |
Date de création, en secondes depuis l’epoch Unix. |
status |
in_progress, completed, incomplete, failed ou cancelled. Une réponse synchrone est renvoyée à un état final. |
model |
Identifiant du modèle qui a produit la réponse. |
output |
Tableau d’éléments de sortie. |
usage |
Compteurs de tokens : input_tokens, output_tokens et total_tokens. |
error |
null, ou un objet problème (section 9.3) lorsque status vaut failed. |
incomplete_details |
null, ou un objet avec un reason tel que max_output_tokens lorsque status vaut incomplete. |
Types d’éléments de sortie :
| Type d’élément | Forme |
|---|---|
message |
id, role (assistant) et content, un tableau de parties output_text qui ont chacune un text. |
function_call |
id, call_id, name et arguments, une chaîne encodée en JSON. |
reasoning |
id et summary, un tableau de parties summary_text qui ont chacune un text. |
Si la génération échoue, une requête synchrone reçoit un état d’erreur et un document problème (section 9.3), et non un objet réponse. L’état failed apparaît dans les flux, les tâches et les réponses stockées.
GET /lmsp/v1/responses/{response_id} renvoie une réponse qui a été stockée avec store: true. Il est facultatif et exige la capacité conversations. Un identifiant inconnu donne 404 avec response_not_found.
6.3 Streaming
Pour diffuser en streaming, définissez stream dans la requête :
{
"stream": true
}
Le service répond 200 OK avec Content-Type: text/event-stream et envoie des événements sémantiques. Chaque événement a un id, un nom event et un objet JSON data :
id: 1
event: response.created
data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","status":"in_progress"}
id: 2
event: response.output_item.added
data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","output_index":0,"item":{"id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","type":"message","role":"assistant","content":[]}}
id: 3
event: response.output_text.delta
data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","item_id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","delta":"A local model "}
id: 4
event: response.output_text.delta
data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","item_id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","delta":"service is a resident interface layer."}
id: 5
event: response.output_item.done
data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","output_index":0,"item":{"id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","type":"message","role":"assistant","content":[{"type":"output_text","text":"A local model service is a resident interface layer."}]}}
id: 6
event: response.completed
data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","status":"completed","usage":{"input_tokens":28,"output_tokens":12,"total_tokens":40}}
Au moins ces événements sont définis :
| Événement | Signification | Champs de données |
|---|---|---|
response.created |
La réponse a été créée. | response_id, status (in_progress) |
response.output_item.added |
Un nouvel élément de sortie a commencé. | response_id, output_index, item |
response.output_text.delta |
Du texte a été ajouté à un élément message. | response_id, item_id, delta |
response.output_item.done |
Un élément de sortie est complet. | response_id, output_index, item |
response.completed |
La réponse est terminée. Événement final. | response_id, status, usage |
response.incomplete |
La génération s’est arrêtée prématurément, par exemple à la limite de tokens. Événement final. | response_id, status, incomplete_details, usage |
response.failed |
La génération a échoué. Événement final. | response_id, status, error |
response.cancelled |
La réponse a été annulée. Événement final. | response_id, status |
error |
Un problème qui n’est pas lié à une seule réponse, après lequel le flux ne peut pas continuer. | error, un objet problème |
Un service ferme le flux après un événement final ou un événement error.
Les services PEUVENT envoyer des événements supplémentaires, par exemple pour les arguments d’appels d’outils, les images, le son et les deltas JSON structurés. Les clients DOIVENT ignorer les types d’événements qu’ils ne connaissent pas.
Si le client ferme la connexion d’une requête en streaming, le service DEVRAIT cesser de générer.
6.4 Identifiants d’événements et reconnexion
L’id d’un événement DOIT être un numéro de séquence entier, strictement croissant au sein de la réponse, à partir de 1.
Après une coupure de connexion, un client reprend en envoyant le dernier identifiant reçu. Il le fait avec un en-tête :
Last-Event-ID: 2
ou avec un paramètre de requête :
GET /lmsp/v1/tasks/{task_id}/events?after=2
Les deux s’adressent au point de terminaison d’événements d’une tâche (section 7.4). Le service ne rejoue que les événements dont le numéro de séquence est supérieur à 2. Si les deux sont présents, after l’emporte.
Si les événements demandés sont plus anciens que la durée de conservation, le service répond 410 Gone avec l’erreur event_history_expired. Le client récupère alors le résultat final à la place, avec GET /lmsp/v1/tasks/{task_id}.
Une réponse diffusée directement depuis POST /lmsp/v1/responses appartient à cette connexion HTTP et ne peut pas être reprise. Un client qui a besoin d’une sortie reprenable DEVRAIT créer une tâche et suivre ses événements.
6.5 Appels d’outils
LMSP 1.0 définit des outils de type fonction que le client exécute. Le service n’exécute pas lui-même d’outils. La portée tools:execute est réservée aux extensions qui le font (section 10.3).
D’abord, le client liste les outils. Chaque entrée a type défini à function, un name, une description et parameters, un objet JSON Schema. tool_choice vaut auto (la valeur par défaut), none, required, ou {"type": "function", "name": "get_weather"}.
{
"model": "qwen3:14b-q4_k_m",
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is the weather in Hangzhou?"
}
]
}
],
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
],
"tool_choice": "auto"
}
Lorsque le modèle décide d’appeler un outil, la réponse contient un élément function_call. Ses arguments sont une chaîne encodée en JSON. Dans un flux, l’élément arrive complet dans response.output_item.done.
{
"id": "resp_01J8M7B3N6Q9T2V5X8Z1C4D7FH",
"object": "response",
"created_at": 1794200050,
"status": "completed",
"model": "qwen3:14b-q4_k_m",
"output": [
{
"id": "fc_01J8M7B3N8R1S4W7Y0A3E6G9JK",
"type": "function_call",
"call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM",
"name": "get_weather",
"arguments": "{\"city\":\"Hangzhou\"}"
}
],
"usage": {
"input_tokens": 74,
"output_tokens": 18,
"total_tokens": 92
},
"error": null,
"incomplete_details": null
}
Le client exécute l’outil, puis envoie une nouvelle requête qui porte le contexte complet : les éléments d’entrée précédents, l’élément function_call tel qu’il a été reçu, et un élément function_call_output avec le même call_id. Son output est une chaîne, généralement encodée en JSON.
{
"type": "function_call_output",
"call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM",
"output": "{\"temperature_c\":17,\"condition\":\"light rain\"}"
}