回應與串流傳輸

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\"}"
}