Antworten und Streaming
- Normativ
- Entwurf 1.0
- Aktualisiert
- Als Markdown anzeigen
6.1 Anfrage
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
}
Das Kernprotokoll verwendet eine Responses-artige input- und output-Struktur statt einer einfachen Liste von Nachrichtenzeichenfolgen, damit eine einzige Anfrageform Folgendes tragen kann:
- mehrteilige Nachrichten über mehrere Gesprächsrunden;
- Text, Bilder, Audio und Dateien;
- Tool-Aufrufe und Tool-Ergebnisse;
- strukturierte Ausgabe;
- Zusammenfassungen des Schlussfolgerns;
- multimodale Ausgabe.
LMSP 1.0 definiert nur Textinhalt. Bild-, Audio- und Dateiinhaltstypen sind für spätere Versionen reserviert.
| Feld | Erforderlich | Bedeutung |
|---|---|---|
model |
Ja | ID des zu verwendenden Modells. |
input |
Ja | Array von Eingabeelementen. Ein message-Element hat eine role (system, user oder assistant) und ein content-Array aus Teilen, etwa input_text. Die Nutzung von Tools fügt function_call- und function_call_output-Elemente hinzu (Abschnitt 6.5). |
stream |
Nein | true, um Server-Sent Events zu erhalten. Standardwert ist false. |
max_output_tokens |
Nein | Obergrenze für die Anzahl der generierten Tokens. |
temperature |
Nein | Sampling-Temperatur. |
response_format |
Nein | {"type": "text"} (der Standard) oder {"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}} für strukturierte Ausgabe. Erfordert die Fähigkeit structured_output. |
tools, tool_choice |
Nein | Funktions-Tools, die das Modell aufrufen darf (Abschnitt 6.5). Erfordert die Fähigkeit tools. |
store |
Nein | Bittet den Dienst, die Antwort aufzubewahren, damit sie später abgerufen und als previous_response_id verwendet werden kann. Standardwert ist false. Wird von Diensten ohne die Fähigkeit conversations ignoriert. |
previous_response_id |
Nein | Setzt eine gespeicherte Antwort fort. Erfordert die Fähigkeit conversations. |
extensions |
Nein | Private Erweiterungen (Abschnitt 9.1). |
Eine Anfrage, die eine Fähigkeit benötigt, die das Modell nicht hat, wird mit 400 und unsupported_capability abgelehnt. Eine Anfrage, die nicht in das Kontextfenster passt, wird mit 400 und context_length_exceeded abgelehnt.
Ein Dienst, der Konversationen speichern kann, KANN auch previous_response_id unterstützen. Andernfalls MUSS jede Anfrage den vollständigen Kontext enthalten. Ein Dienst DARF NICHT darauf vertrauen, dass die HTTP-Verbindung den Konversationszustand hält.
6.2 Synchrone Antwort
Ist stream false, gibt der Dienst nach Abschluss der Generierung 200 OK mit einem Antwortobjekt zurück.
{
"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
}
| Feld | Bedeutung |
|---|---|
id |
Antwortkennung, etwa resp_.... |
object |
Immer "response". |
created_at |
Erstellungszeit in Sekunden seit der Unix-Epoche. |
status |
in_progress, completed, incomplete, failed oder cancelled. Eine synchrone Antwort wird in einem Endstatus zurückgegeben. |
model |
ID des Modells, das die Antwort erzeugt hat. |
output |
Array von Ausgabeelementen. |
usage |
Token-Zähler: input_tokens, output_tokens und total_tokens. |
error |
null oder ein Problemobjekt (Abschnitt 9.3), wenn status failed ist. |
incomplete_details |
null oder ein Objekt mit einem reason wie max_output_tokens, wenn status incomplete ist. |
Typen von Ausgabeelementen:
| Elementtyp | Form |
|---|---|
message |
id, role (assistant) und content, ein Array aus output_text-Teilen, die jeweils einen text haben. |
function_call |
id, call_id, name und arguments, eine JSON-codierte Zeichenfolge. |
reasoning |
id und summary, ein Array aus summary_text-Teilen, die jeweils einen text haben. |
Schlägt die Generierung fehl, wird eine synchrone Anfrage mit einem Fehlerstatus und einem Problemdokument (Abschnitt 9.3) beantwortet, nicht mit einem Antwortobjekt. Der Status failed erscheint in Streams, Aufgaben und gespeicherten Antworten.
GET /lmsp/v1/responses/{response_id} gibt eine Antwort zurück, die mit store: true gespeichert wurde. Er ist optional und erfordert die Fähigkeit conversations. Eine unbekannte ID ergibt 404 mit response_not_found.
6.3 Streaming
Zum Streamen setzen Sie stream in der Anfrage:
{
"stream": true
}
Der Dienst antwortet mit 200 OK und Content-Type: text/event-stream und sendet semantische Ereignisse. Jedes Ereignis hat eine id, einen event-Namen und ein JSON-data-Objekt:
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}}
Mindestens diese Ereignisse sind definiert:
| Ereignis | Bedeutung | Datenfelder |
|---|---|---|
response.created |
Die Antwort wurde erstellt. | response_id, status (in_progress) |
response.output_item.added |
Ein neues Ausgabeelement hat begonnen. | response_id, output_index, item |
response.output_text.delta |
An ein Nachrichtenelement wurde Text angehängt. | response_id, item_id, delta |
response.output_item.done |
Ein Ausgabeelement ist vollständig. | response_id, output_index, item |
response.completed |
Die Antwort ist abgeschlossen. Letztes Ereignis. | response_id, status, usage |
response.incomplete |
Die Generierung wurde vorzeitig beendet, zum Beispiel am Token-Limit. Letztes Ereignis. | response_id, status, incomplete_details, usage |
response.failed |
Die Generierung ist fehlgeschlagen. Letztes Ereignis. | response_id, status, error |
response.cancelled |
Die Antwort wurde abgebrochen. Letztes Ereignis. | response_id, status |
error |
Ein Problem, das nicht an eine einzelne Antwort gebunden ist und nach dem der Stream nicht fortgesetzt werden kann. | error, ein Problemobjekt |
Ein Dienst schließt den Stream nach einem letzten Ereignis oder einem error-Ereignis.
Dienste KÖNNEN zusätzliche Ereignisse senden, zum Beispiel für Argumente von Tool-Aufrufen, Bilder, Audio und strukturierte JSON-Deltas. Clients MÜSSEN Ereignistypen ignorieren, die sie nicht kennen.
Schließt der Client die Verbindung einer Streaming-Anfrage, SOLLTE der Dienst die Generierung beenden.
6.4 Ereignis-IDs und Wiederverbindung
Die id eines Ereignisses MUSS eine ganzzahlige Sequenznummer sein, die innerhalb der Antwort streng ansteigt und bei 1 beginnt.
Nach einer abgebrochenen Verbindung setzt ein Client fort, indem er die zuletzt erhaltene ID sendet. Das geschieht mit einem Header:
Last-Event-ID: 2
oder mit einem Abfrageparameter:
GET /lmsp/v1/tasks/{task_id}/events?after=2
Beides geht an den Ereignis-Endpunkt einer Aufgabe (Abschnitt 7.4). Der Dienst spielt nur die Ereignisse erneut ab, deren Sequenznummer größer als 2 ist. Sind beide vorhanden, hat after Vorrang.
Sind die angeforderten Ereignisse älter als die Aufbewahrungsdauer, antwortet der Dienst mit 410 Gone und dem Fehler event_history_expired. Der Client ruft dann stattdessen das Endergebnis mit GET /lmsp/v1/tasks/{task_id} ab.
Eine direkt von POST /lmsp/v1/responses gestreamte Antwort gehört zu dieser HTTP-Verbindung und kann nicht fortgesetzt werden. Ein Client, der fortsetzbare Ausgabe braucht, SOLLTE eine Aufgabe erstellen und ihren Ereignissen folgen.
6.5 Tool-Aufrufe
LMSP 1.0 definiert Funktions-Tools, die der Client ausführt. Der Dienst führt Tools nicht selbst aus. Der Scope tools:execute ist für Erweiterungen reserviert, die das tun (Abschnitt 10.3).
Zuerst listet der Client die Tools auf. Jeder Eintrag hat type mit dem Wert function, einen name, eine description und parameters, ein JSON-Schema-Objekt. tool_choice ist auto (der Standard), none, required oder {"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"
}
Entscheidet das Modell, ein Tool aufzurufen, enthält die Antwort ein function_call-Element. Seine arguments sind eine JSON-codierte Zeichenfolge. In einem Stream trifft das Element vollständig in response.output_item.done ein.
{
"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
}
Der Client führt das Tool aus und sendet dann eine neue Anfrage, die den vollständigen Kontext trägt: die früheren Eingabeelemente, das function_call-Element wie empfangen und ein function_call_output-Element mit derselben call_id. Sein output ist eine Zeichenfolge, meist JSON-codiert.
{
"type": "function_call_output",
"call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM",
"output": "{\"temperature_c\":17,\"condition\":\"light rain\"}"
}