PMFlow/mdproject/ai-visibility-panel-plan.md

174 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AI Processing Visibility Panel — Implementation Plan
**Goal:** Make AI processing fully observable. Know if AI is running, what it output, why it routed each item.
**Placement:** Above signal source list on SSTC board. Collapsible. Expanded by default in dev mode.
**Scope:** Frontend panel + backend logging endpoints. No new pages.
---
## Backend
### 1. Logging (add to existing AI job)
Every Feishu message processed must write a log record:
- [ ] Create `ai_processing_logs` table:
```
id
feishu_message_id
feishu_item_id (FK)
raw_message -- original Feishu text
ai_raw_output -- full JSON from LLM
project_score -- float 0–1
signal_confidence -- float 0–1
level -- "project" or "signal"
routing_decision -- "auto_create_project" / "auto_enter_signal" / "pending_low_confidence" / "pending_cold_start" / "pending_uncertain_project" / "duplicate_filtered"
routing_reason -- plain text, 1 sentence
reasoning_bullets -- JSON array, 3 items
processing_status -- "success" / "failed" / "processing"
error_message -- null if success
duration_ms -- processing time
created_at
```
- [ ] On duplicate detected (`feishu_message_id` already exists): write log with `routing_decision = "duplicate_filtered"`, do not process further
- [ ] On AI job failure: write log with `processing_status = "failed"` + `error_message`
### 2. API endpoints
- [ ] `GET /api/ai-logs?project_id=&limit=20&offset=0` — paginated log list for a project
- [ ] `GET /api/ai-logs/stats?project_id=&date=today` — daily stats summary
- [ ] `GET /api/ai-logs/{id}` — full detail for one log record
- [ ] `GET /api/ai-logs/latest?project_id=` — most recent log record (for real-time status)
---
## Frontend
### Panel structure
Collapsible section above the signal source table. Toggle button: "AI 处理状态 ▾"
Default state: collapsed in production, expanded in dev (`import.meta.env.DEV`).
Three blocks inside:
---
### Block 1 — Latest processing status (real-time)
Polls `GET /api/ai-logs/latest` every 10 seconds.
```
┌─────────────────────────────────────────────────────┐
│ 最近处理 │
│ │
│ ✅ 已处理 14:23:01 耗时 3.2s │
│ 原始消息:新增个需求,关于做饭食谱...(点击展开) │
│ │
│ project_score: 0.31 → 信号级别 │
│ confidence: 0.62 → 低于阈值,进待处理队列 │
│ 路由:冷启动期 / 低置信度 │
└─────────────────────────────────────────────────────┘
```
Status indicator colors:
- ✅ green — success
- ⏳ yellow — processing (AI job in flight)
- ❌ red — failed, shows error message
- [ ] Build `LatestProcessingStatus` component
- [ ] Poll `/api/ai-logs/latest` every 10s, stop polling if tab not focused
- [ ] Show raw message truncated to 1 line, click to expand full text
- [ ] Show `project_score`, `signal_confidence`, `routing_decision`, `routing_reason`
- [ ] Show `duration_ms` formatted as seconds
---
### Block 2 — Today's stats
Fetches `GET /api/ai-logs/stats` once on mount, refetches when new log arrives.
```
┌─────────────────────────────────────────────────────┐
│ 今日统计 │
│ │
│ 接收 12 │ AI处理成功 10 │ 失败 2 │ 重复过滤 2 │
│ 自动入库 3 │ 待处理 7 │
│ 平均 confidence: 0.71 │ 平均 project_score: 0.28 │
└─────────────────────────────────────────────────────┘
```
- [ ] Build `DailyStats` component
- [ ] Display all 7 counters in a single row of stat chips
- [ ] Highlight failed count in red if > 0
- [ ] Show average scores to 2 decimal places
---
### Block 3 — Processing log list
Fetches `GET /api/ai-logs?project_id=` with pagination. Shows last 20 records.
Each row:
```
时间 状态 路由决策 confidence project_score 操作
14:23:01 ✅ pending_low_conf 0.62 0.31 [详情]
12:06:25 ✅ auto_enter_signal 0.83 0.29 [详情]
12:00:11 ❌ failed — — [详情]
11:39:27 ✅ duplicate_filtered — — [详情]
```
- [ ] Build `ProcessingLogTable` component
- [ ] Columns: time / status icon / routing decision (translated to Chinese label) / confidence / project_score / detail button
- [ ] `routing_decision` label map:
- `auto_create_project` → 🏗 自动创建项目
- `auto_enter_signal` → ✅ 自动入库
- `pending_low_confidence` → ⏸ 低置信度待处理
- `pending_cold_start` → ⏸ 冷启动期待处理
- `pending_uncertain_project` → ⏸ 项目归属不确定
- `duplicate_filtered` → 🔁 重复过滤
- `failed` → ❌ 处理失败
- [ ] Click `[详情]` → opens a right-side drawer showing:
- Raw Feishu message (full text)
- AI raw output (JSON, formatted)
- All scores and reasoning bullets
- Error message if failed
- [ ] Pagination: load more button at bottom (not infinite scroll)
- [ ] Row color: red background if `processing_status = failed`
---
## Routing decision labels (used in both backend logs and frontend display)
| `routing_decision` value | Meaning |
|--------------------------|---------|
| `auto_create_project` | project_score ≥ 0.85, cold start over, project auto-created |
| `auto_enter_signal` | confidence ≥ 0.80, cold start over, signal auto-entered |
| `pending_low_confidence` | confidence < 0.80, queued for review |
| `pending_cold_start` | cold start period active, all items queued regardless of score |
| `pending_uncertain_project` | project_score 0.60–0.84, queued for user to confirm |
| `duplicate_filtered` | feishu_message_id already processed, dropped |
| `failed` | AI job threw an error |
---
## Implementation order
| Task | When |
|------|------|
| `ai_processing_logs` table + write logs in AI job | First, before anything else — need data to display |
| 4 API endpoints | After table exists |
| `DailyStats` component | Quick win, shows immediately if AI is running |
| `LatestProcessingStatus` component | Core visibility, shows scores + routing |
| `ProcessingLogTable` + detail drawer | Last, most complex |
---
## Out of scope
- Alerts / notifications when AI fails (add later)
- Log retention policy / auto-delete (add later)
- Exporting logs (add later)