SSE API

Regenerate Summary

連線資訊

項目
基礎路徑https://vas-poc.vurbo.ai/api/v1/sse
協定HTTP + Server-Sent Events (SSE)
資料格式text/event-stream
認證方式Header X-API-Key: {KEY}

注意:瀏覽器原生 EventSource API 不支援自訂 Header,需使用 fetch API 搭配 ReadableStream,或使用支援 Header 的 SSE 客戶端套件。


端點總覽

拆成預覽 / 存檔兩個端點:

方法端點寫 DB儲存逐字稿計費用途
GET/api/v1/sse/regenerate/summary/{taskId}預覽(試跑、比較不同 prompt 結果)
POST/api/v1/sse/regenerate/summary/{taskId}✅ + bump revision存檔(正式儲存)

已知限制:GET 預覽仍會計費 — LLM 真實消耗 token,不能讓 GET 端點白嫖。重複呼叫 GET 會重複計費,但不會改變後端儲存狀態。


共用:請求參數

GET 走 query string、POST 走 JSON body,欄位名與型別相同:

參數類型必填限制說明
taskId (path)stringUUID錄音 ID
modestringenum "builtin" | "custom"顯式路徑選擇
templatestringbuiltin 必填 / custom 禁帶exists prompt_templates.slug內建模板 slug
promptstringcustom 必填 / builtin 禁帶≤2000 字元客戶完整 prompt(取代 IPEVO 三層)
promptSlugstringcustom 必填 / builtin 禁帶≤64 字元、Unicode、禁控制字元客戶自家識別碼(pass-through)
languagestring-摘要輸出語言代碼(如 zh-TWen-US),未指定時使用 transcription 第一個語言
plainTextboolean預設 false要求純文字輸出(後端會額外做 markdown 後處理)

互斥規則

  • mode=builtin 下不可帶 promptpromptSlug
  • mode=custom 下不可帶 template,但 promptpromptSlug 必填

違反 → 422 validation error(summary_mode_field_mismatch


GET /api/v1/sse/regenerate/summary/{taskId}(預覽)

功能說明

跑一次 LLM 重新生成摘要,僅串流回客戶端,不寫 DB、不更新逐字稿記錄。

適用情境:客戶端想嘗試不同 prompt / 不同 plain_text 設定,比較結果後再決定是否存檔。

請求範例

builtin mode

curl -N "https://vas-poc.vurbo.ai/api/v1/sse/regenerate/summary/550e8400-e29b-41d4-a716-446655440000?mode=builtin&template=meeting&language=zh-TW&plainText=true" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

custom mode

curl -N "https://vas-poc.vurbo.ai/api/v1/sse/regenerate/summary/550e8400-e29b-41d4-a716-446655440000?mode=custom&prompt=%E8%AB%8B%E5%BC%B7%E8%AA%BFKPI&promptSlug=acme-meeting-v2&plainText=true" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

副作用

  • ✅ 會在 usage_logs 新增一筆 type=summary 的計費記錄(LLM 真實消耗 token)
  • 不會更新 recordings.summary_mode / summary_template / summary_prompt_slug 三欄
  • 不會覆寫已儲存的摘要

POST /api/v1/sse/regenerate/summary/{taskId}(存檔)

功能說明

GET 預覽的所有動作 + 寫入 DB 與逐字稿記錄。

請求範例

builtin mode

curl -N -X POST "https://vas-poc.vurbo.ai/api/v1/sse/regenerate/summary/550e8400-e29b-41d4-a716-446655440000" \
  -H "X-API-Key: vas_..." \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "builtin",
    "template": "meeting",
    "language": "zh-TW",
    "plainText": true
  }'

custom mode

curl -N -X POST "https://vas-poc.vurbo.ai/api/v1/sse/regenerate/summary/550e8400-e29b-41d4-a716-446655440000" \
  -H "X-API-Key: vas_..." \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "custom",
    "prompt": "你是皮膚科專科助手。請從逐字稿萃取 Fitzpatrick 分型...",
    "promptSlug": "skin-clinic-acme-v2",
    "language": "zh-TW",
    "plainText": true
  }'

副作用

  • ✅ 在 usage_logs 新增一筆 type=summary 的計費記錄
  • ✅ 依 mode 互斥寫入 recordings 三欄:
    • builtin → summary_mode='builtin'summary_template=<slug>summary_prompt_slug=NULL
    • custom → summary_mode='custom'summary_template=NULLsummary_prompt_slug=<客戶 slug>
  • ✅ 更新逐字稿記錄的 top-level 欄位並 revision += 1
    • summary(純字串)、summary_languagesummary_modesummary_template(effective slug)、summary_plain_text
    • custom mode 強制 summary_prompt_snapshot(客戶 prompt 原樣 snapshot,是唯一重建依據)

事件序列(兩端點相同)

1. connected              → 連線確認
2. summary_regeneration   → 發送摘要片段(重複 N 次,累積式)
3. done                   → 生成完成

connected

{
  "message": "Summary regeneration stream connected (recordingId: 550e8400-..., mode: custom, endpoint: preview)"
}

⚠️ 避免混淆:message 中的 mode業務 modebuiltin / custom,即 request 帶入的 mode);endpoint 才是端點模式preview GET / persist POST)。兩者語義不同,請勿混為一談。

summary_regeneration

{ "text": "本次會議討論了以下議題:\n1. 產品開發進度", "is_final": false }
欄位類型說明
textstring累積的摘要內容(plainText=true 時 is_final=true 的 text 為清洗後純文字)
is_finalboolean是否為最終結果

done

{
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "tokens_used": 123,
  "final_content": "本次會議...(清洗後完整內容)",
  "mode": "custom",
  "template": "skin-clinic-acme-v2",
  "plain_text": true,
  "persisted": true,
  "prompt_snapshot": "你是皮膚科專科助手..."
}
欄位類型說明
task_idstringRecording UUID
tokens_usednumber總 token 用量
final_contentstring完整摘要內容(plainText=true 時為清洗後純文字)
modestring業務 mode:"builtin""custom"
templatestringeffective slug — builtin → 內建模板 slug;custom → 客戶 slug
plain_textboolean是否啟用純文字模式
persistedboolean本次摘要是否已正式儲存(GET 為 false、POST 為 true)
prompt_snapshotstring僅 custom mode 出現,為客戶原樣傳入的 prompt 內容(強制 snapshot,是唯一重建依據)

特有錯誤碼

錯誤碼HTTP說明處理建議
recording_not_found404找不到指定的錄音確認 taskId 正確
sse_template_not_found404找不到摘要模板(builtin mode)確認 template 正確
sse_transcript_not_found404找不到逐字稿錄音可能尚未處理完成
summary_text_empty400逐字稿沒有可摘要內容錄音內容過短或皆為靜音
llm_content_filtered400LLM 服務內容過濾擋下(custom prompt 或逐字稿含敏感詞)v1.5.5 SSE 端尚未整合 fallback chain,建議改用 POST /api/v1/summary REST 端點觸發自動降級;或修改 prompt 後重試

LLM 服務內容過濾 fallback chain — SSE 端的當前狀態(v1.5.5)

WebSocket realtime 摘要與檔案匯入摘要已在 v1.5.5 整合 L1→L2→L3 fallback chain,被擋時會自動降級產出簡化摘要。但本端點(SSE regenerate/summary)尚未整合,仍會直接回 llm_content_filtered

Follow-up PR 將整合 fallback chain 並擴充 done event 加 fallback_level / dropped_segments 欄位。屆時客戶端可從 done.fallback_level 判斷是否走了 fallback。在此之前,若你的整合方需要 LLM 服務過濾的自動降級行為,建議透過 POST /api/v1/summary REST 端點觸發。 | summary_text_too_long | 400 | 逐字稿超過長度上限(100,000 字元) | 縮短錄音或拆分檔案 | | summary_invalid_mode | 422 | mode 不是 builtin / custom | 改為合法 mode | | summary_mode_field_mismatch | 422 | mode 與欄位組合不符(必填缺漏或禁帶被帶入) | 依 mode 規則調整欄位 | | summary_prompt_too_long | 422 | prompt 超過 2000 字元 | 縮短 | | summary_prompt_slug_too_long | 422 | promptSlug 超過 64 字元 | 縮短 | | summary_prompt_slug_invalid | 422 | promptSlug 含控制字元(\n / \r / \t / \0 等) | 移除控制字元 | | sse_summary_regeneration_failed | 500 | 摘要重新生成失敗(已 sanitize 內部錯誤,不會洩漏 LLM raw error)| 稍後重試 |


版本:V1.5.7 最後更新:2026-05-20

Copyright © 2026