回應與串流傳輸
- 規範性
- 草案 1.0
- 更新於
- 檢視 Markdown
6.1 請求
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
}
核心協定採用 Responses 風格的 input/output 結構,而不是只支援簡單的 messages 字串,以便用同一種請求格式統一承載:
- 多輪訊息;
- 文本、圖片、音訊和檔案;
- 工具呼叫及工具結果;
- 結構化輸出;
- 推理摘要;
- 多模態輸出。
LMSP 1.0 只定義文本內容。圖片、音訊和檔案的內容型別留待後續版本。
| 欄位 | 必需 | 含義 |
|---|---|---|
model |
是 | 要使用的模型 id。 |
input |
是 | 輸入項陣列。message 項包含 role(system、user 或 assistant)和由多個部分組成的 content 陣列,例如 input_text。使用工具時會增加 function_call 和 function_call_output 項(第 6.5 節)。 |
stream |
否 | 為 true 時接收伺服器傳送事件,預設為 false。 |
max_output_tokens |
否 | 生成 token 數的上限。 |
temperature |
否 | 取樣溫度。 |
response_format |
否 | {"type": "text"}(預設),或用於結構化輸出的 {"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}。需要 structured_output 能力。 |
tools、tool_choice |
否 | 模型可以呼叫的函式工具(第 6.5 節)。需要 tools 能力。 |
store |
否 | 請求服務儲存該回應,以便之後查詢,並可用作 previous_response_id。預設為 false。沒有 conversations 能力的服務會忽略它。 |
previous_response_id |
否 | 接著已儲存的某個回應繼續對話。需要 conversations 能力。 |
extensions |
否 | 私有擴充(第 9.1 節)。 |
請求需要模型不具備的能力時,回傳 400 和 unsupported_capability。請求放不進上下文視窗時,回傳 400 和 context_length_exceeded。
能夠儲存工作階段的服務可以額外支援 previous_response_id;否則每次請求都必須攜帶完整上下文。服務不得依賴 HTTP 連線儲存對話狀態。
6.2 同步回應
當 stream 為 false 時,服務在生成結束後回傳 200 OK 和一個回應物件。
{
"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
}
| 欄位 | 含義 |
|---|---|
id |
回應識別碼,例如 resp_...。 |
object |
始終為 "response"。 |
created_at |
建立時間,自 Unix 紀元起的秒數。 |
status |
in_progress、completed、incomplete、failed 或 cancelled。同步回應回傳時已處於最終狀態。 |
model |
生成該回應的模型 id。 |
output |
輸出項陣列。 |
usage |
token 用量:input_tokens、output_tokens 和 total_tokens。 |
error |
null;當 status 為 failed 時是一個 problem 物件(第 9.3 節)。 |
incomplete_details |
null;當 status 為 incomplete 時是帶有 reason(例如 max_output_tokens)的物件。 |
輸出項型別:
| 項型別 | 結構 |
|---|---|
message |
id、role(assistant)和 content,後者是 output_text 部分的陣列,每個部分帶有 text。 |
function_call |
id、call_id、name 和 arguments,後者是 JSON 編碼的字串。 |
reasoning |
id 和 summary,後者是 summary_text 部分的陣列,每個部分帶有 text。 |
如果生成失敗,同步請求回傳錯誤狀態碼和 problem 文件(第 9.3 節),而不是回應物件。failed 狀態只出現在流、任務和已儲存的回應中。
GET /lmsp/v1/responses/{response_id} 回傳以 store: true 儲存的回應。它是可選介面,需要 conversations 能力。未知的 id 回傳 404 和 response_not_found。
6.3 串流回應
要使用串流傳輸,在請求中設定 stream:
{
"stream": true
}
服務回傳 200 OK 和 Content-Type: text/event-stream,並傳送語義化事件。每個事件包含 id、event 名稱和一個 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}}
最少定義以下事件:
| 事件 | 含義 | 資料欄位 |
|---|---|---|
response.created |
回應已建立。 | response_id、status(in_progress) |
response.output_item.added |
開始了一個新的輸出項。 | response_id、output_index、item |
response.output_text.delta |
文本被追加到某個 message 項。 | response_id、item_id、delta |
response.output_item.done |
一個輸出項已完成。 | response_id、output_index、item |
response.completed |
回應已完成。最終事件。 | response_id、status、usage |
response.incomplete |
生成提前停止,例如達到 token 上限。最終事件。 | response_id、status、incomplete_details、usage |
response.failed |
生成失敗。最終事件。 | response_id、status、error |
response.cancelled |
回應已取消。最終事件。 | response_id、status |
error |
與某個具體回應無關的問題,出現後流無法繼續。 | error,一個 problem 物件 |
服務在最終事件或 error 事件之後關閉流。
服務可以傳送額外的事件,例如工具呼叫引數、圖片、音訊和結構化 JSON 增量。客戶端必須忽略不認識的事件型別。
如果客戶端關閉了串流請求的連線,服務應停止生成。
6.4 事件 id 與重連
事件的 id 必須是整數序號,在該回應內嚴格遞增,從 1 開始。
連線斷開後,客戶端透過傳送自己收到的最後一個 id 來恢復。可以使用請求標頭:
Last-Event-ID: 2
或使用查詢引數:
GET /lmsp/v1/tasks/{task_id}/events?after=2
兩者都發往任務的事件介面(第 7.4 節)。服務只補發序號大於 2 的事件。兩者同時出現時,以 after 為準。
如果請求的事件已超出保留期,服務回傳 410 Gone 和錯誤碼 event_history_expired,客戶端改為透過 GET /lmsp/v1/tasks/{task_id} 取得最終結果。
直接從 POST /lmsp/v1/responses 串流回傳的回應屬於該 HTTP 連線,無法恢復。需要可恢復輸出的客戶端應建立任務並跟隨它的事件。
6.5 工具呼叫
LMSP 1.0 定義由客戶端執行的函式工具,服務本身不執行工具。tools:execute 許可權範圍預留給會執行工具的擴充(第 10.3 節)。
首先,客戶端列出工具。每個條目的 type 為 function,並帶有 name、description 和 parameters(一個 JSON Schema 物件)。tool_choice 可以是 auto(預設)、none、required,或 {"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"
}
當模型決定呼叫工具時,回應中會包含一個 function_call 項,其 arguments 是 JSON 編碼的字串。在流中,該項會以完整形式出現在 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
}
客戶端執行工具,然後傳送一個攜帶完整上下文的新請求:之前的輸入項、收到的 function_call 項,以及一個 call_id 相同的 function_call_output 項。其 output 是字串,通常為 JSON 編碼。
{
"type": "function_call_output",
"call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM",
"output": "{\"temperature_c\":17,\"condition\":\"light rain\"}"
}