Insights API (VLM)
對齊
docs/SaaS-API.md第 6.C 節(Analysis Insights)。VLM 洞察相關端點。
端點範圍
| 方法 | 路徑 | 說明 |
|---|---|---|
| GET | /api/v1/analysis/insights | 洞察列表 |
| GET | /api/v1/analysis/insights/{id} | 洞察詳情 |
| GET | /api/v1/analysis/insights/{id}/snapshots | 洞察截圖 |
| GET | /api/v1/analysis/insights/{id}/attributes | 洞察關聯屬性(LEVEL_02) |
| GET | /api/v1/analysis/insights/attributes/stats | 屬性聚合統計(LEVEL_02) |
| GET | /api/v1/analysis/insights/vlm-summaries | VLM 摘要列表 |
| GET | /api/v1/analysis/attributes | 獨立屬性列表(v0.10.0+, LEVEL_02) |
| GET | /api/v1/analysis/attributes/{id} | 單筆屬性詳情(v0.10.0+, LEVEL_02) |
前置條件
- 已完成設備、場景建立與分析啟動
- 認證:
Authorization: Bearer {API_KEY} - 權限:
analytics:read - LEVEL_02 才能使用屬性相關端點
Insight 與 Alert 的關係
告警觸發 (Alert) → 建立 Insight (PENDING)
→ BullMQ → VLM Worker (Vercel AI SDK generateObject())
→ 更新 vlmStructuredResult + vlmSummary (COMPLETED)
→ 前端透過本 API 查詢
每個 Insight 與一個 Alert 1:1 綁定。
1) 洞察列表
GET /api/v1/analysis/insights
Query 參數
| 參數 | 型別 | 必填 | 預設 | 說明 |
|---|---|---|---|---|
page | Number | ❌ | 1 | 頁碼 |
limit | Number | ❌ | 20 | 每頁數量 (1-100) |
q | String | ❌ | - | 全文搜索 (VLM 摘要) |
deviceId | UUID | ❌ | - | 設備 ID 篩選 |
sceneId | UUID | ❌ | - | 場景 ID 篩選 |
severity | Enum | ❌ | - | warning / critical |
vlmStatus | Enum | ❌ | - | pending / completed / failed |
startDate | ISO 8601 | ❌ | - | 觸發時間起始 |
endDate | ISO 8601 | ❌ | - | 觸發時間結束 |
hasVlmSummary | Boolean | ❌ | - | 僅含 VLM 摘要 |
hasAttributes | Boolean | ❌ | - | 僅含屬性資料 |
響應 (200)
{
"success": true,
"statusCode": 200,
"data": [
{
"id": "insight-uuid",
"alertId": "alert-uuid",
"deviceId": "device-uuid",
"deviceName": "入口攝影機",
"sceneId": "scene-uuid",
"sceneName": "主入口排隊區",
"severity": "critical",
"triggeredAt": "2026-02-25T10:30:00Z",
"message": "Queue length exceeded threshold: 15 > 10",
"vlmStatus": "completed",
"vlmSummary": "畫面中可見 15 人在排隊等候...",
"vlmStructuredResult": {
"summary": "畫面中可見 15 人在排隊等候,隊伍較長...",
"personCount": 15,
"riskLevel": "high",
"activities": ["排隊等候"],
"suggestions": ["增派服務人員"],
"environment": "室內大廳"
},
"thumbnailUrl": "https://storage.example.com/thumb/insight-123.jpg",
"snapshotCount": 3,
"attributesSummary": {
"totalPersons": 15,
"genderDistribution": { "female": 8, "male": 7 }
},
"hasAttributes": true,
"hasVlmSummary": true,
"createdAt": "2026-02-25T10:30:01Z"
}
],
"meta": {
"pagination": { "page": 1, "limit": 20, "total": 42, "totalPages": 3 }
}
}
vlmStructuredResult 結構
| 欄位 | 型別 | 說明 |
|---|---|---|
summary | String | 場景分析摘要 (最多 500 字) |
personCount | Number | 畫面中檢測到的人數 |
riskLevel | Enum | low / medium / high / critical |
activities | String[] | 檢測到的活動列表 (最多 5 項) |
suggestions | String[] | 建議採取的行動 (最多 3 項) |
environment | String | 環境描述 (最多 50 字) |
2) 洞察詳情
GET /api/v1/analysis/insights/{id}
響應 (200)
除列表欄位外,額外包含:
| 欄位 | 型別 | 說明 |
|---|---|---|
metricPath | String | 觸發告警的指標路徑 |
operator | Enum | 比較運算符 (GT, LT, GTE, LTE, EQ) |
threshold | Number | 閾值 |
actualValue | Number | 觸發時的實際值 |
computeNodeId | UUID | 處理此分析的計算節點 ID |
snapshotUrls | String[] | 截圖完整 URL 列表 |
vlmRequestedAt | ISO 8601 | VLM 請求時間 |
vlmCompletedAt | ISO 8601 | VLM 完成時間 |
vlmError | String | VLM 錯誤訊息 (status=failed 時) |
vlmTokensUsed | Number | VLM 消耗 token 數 (合計) |
vlmInputTokensUsed | Number | VLM input token 數 |
vlmOutputTokensUsed | Number | VLM output token 數 |
3) 洞察截圖
GET /api/v1/analysis/insights/{id}/snapshots
響應 (200)
{
"success": true,
"data": [
{ "index": 0, "url": "https://storage.example.com/snapshots/insight-123-0.jpg" },
{ "index": 1, "url": "https://storage.example.com/snapshots/insight-123-1.jpg" }
]
}
4) 洞察關聯屬性(LEVEL_02)
GET /api/v1/analysis/insights/{id}/attributes
查詢洞察觸發時間 ±30 秒內的行人屬性偵測記錄,最多返回 50 筆。
響應 (200)
{
"success": true,
"data": [
{
"id": "attr-uuid",
"capturedAt": "2026-02-25T10:29:55Z",
"totalPersons": 15,
"attributes": {
"female": 8, "male": 7,
"ageLess18": 2, "age18To60": 10, "ageOver60": 3,
"front": 5, "side": 6, "back": 4,
"hat": 3, "glasses": 4, "handBag": 2, "shoulderBag": 1, "backpack": 3, "holdObjectsInFront": 1,
"shortSleeve": 6, "longSleeve": 9, "longCoat": 2, "trousers": 8, "shorts": 3, "skirtDress": 4, "boots": 1,
"upperBlack": 4, "upperWhite": 3, "upperRed": 2, "upperPurple": 1, "upperYellow": 2, "upperGray": 3
}
}
]
}
26 個屬性欄位
| 分類 | 欄位 |
|---|---|
| 性別 | female, male |
| 年齡 | ageLess18, age18To60, ageOver60 |
| 方向 | front, side, back |
| 配件 | hat, glasses, handBag, shoulderBag, backpack, holdObjectsInFront |
| 衣著 | shortSleeve, longSleeve, longCoat, trousers, shorts, skirtDress, boots |
| 上衣顏色 | upperBlack, upperWhite, upperRed, upperPurple, upperYellow, upperGray |
5) 屬性聚合統計(LEVEL_02)
GET /api/v1/analysis/insights/attributes/stats
Query 參數
| 參數 | 型別 | 必填 | 說明 |
|---|---|---|---|
startDate | ISO 8601 | ✅ | 統計起始時間 |
endDate | ISO 8601 | ✅ | 統計結束時間 |
deviceId | UUID | ❌ | 設備 ID 篩選 |
sceneId | UUID | ❌ | 場景 ID 篩選 |
groupBy | Enum | ❌ | hour / day,預設 hour |
響應 (200)
{
"success": true,
"data": {
"totalRecords": 1250,
"totalPersons": 18750,
"genderDistribution": { "female": 9800, "male": 8950 },
"ageDistribution": { "ageLess18": 2500, "age18To60": 12500, "ageOver60": 3750 },
"timeline": [
{
"timestamp": "2026-02-25T08:00:00Z",
"personCount": 180,
"attributes": { "female": 95, "male": 85 }
}
]
}
}
6) VLM 摘要列表
GET /api/v1/analysis/insights/vlm-summaries
Query 參數
| 參數 | 型別 | 必填 | 說明 |
|---|---|---|---|
page | Number | ❌ | 頁碼 |
limit | Number | ❌ | 每頁數量 (1-100) |
q | String | ❌ | 全文搜索 VLM 摘要 |
deviceId | UUID | ❌ | 設備 ID 篩選 |
sceneId | UUID | ❌ | 場景 ID 篩選 |
startDate | ISO 8601 | ❌ | 觸發時間起始 |
endDate | ISO 8601 | ❌ | 觸發時間結束 |
響應 (200)
{
"success": true,
"data": [
{
"insightId": "insight-uuid",
"triggeredAt": "2026-02-25T10:30:00Z",
"severity": "critical",
"vlmSummary": "畫面中可見 15 人在排隊等候...",
"thumbnailUrl": "https://storage.example.com/thumb/insight-123.jpg",
"deviceId": "device-uuid",
"deviceName": "入口攝影機",
"sceneId": "scene-uuid",
"sceneName": "主入口排隊區"
}
],
"meta": { "pagination": { "page": 1, "limit": 20, "total": 28, "totalPages": 2 } }
}
7) 獨立屬性列表(v0.10.0+, LEVEL_02)
GET /api/v1/analysis/attributes
直接查詢 scene_analysis_attributes 表,獨立於 Insight。
Query 參數
| 參數 | 型別 | 必填 | 說明 |
|---|---|---|---|
page | Number | ❌ | 頁碼 |
limit | Number | ❌ | 每頁數量 (1-100) |
deviceId | UUID | ❌ | 設備 ID 篩選 |
sceneId | UUID | ❌ | 場景 ID 篩選 |
startDate | ISO 8601 | ❌ | capturedAt 起始時間 |
endDate | ISO 8601 | ❌ | capturedAt 結束時間 |
8) 單筆屬性詳情(v0.10.0+, LEVEL_02)
GET /api/v1/analysis/attributes/{id}
回傳比列表更多的欄位:computeNodeId、userId、updatedAt。
錯誤處理
| HTTP 狀態 | 說明 |
|---|---|
400 | UUID 或日期格式不合法 |
403 | Plan 不足(LEVEL_01 存取 LEVEL_02 功能) |
404 | Insight / Attribute 不存在 |
實務建議
- 以
requestId串接 API、Queue、Compute Node 日誌 - 列表頁優先打
insights/vlm-summaries,詳情頁才打insights/{id}