161 lines
5.6 KiB
Markdown
161 lines
5.6 KiB
Markdown
# 会话与 Trace 生命周期
|
||
|
||
**更新日期**:2026-07-10
|
||
**状态**:当前可运行架构
|
||
**参考历史文档**:`archive/2026-07-05-legacy/session-management.md`
|
||
|
||
## 1. 定位
|
||
|
||
当前 MVP 把“会话态”和“运行态”拆开:
|
||
|
||
```text
|
||
chat_session(sessionId)
|
||
-> diagnosis_run(runId)
|
||
-> agent_step(runId)
|
||
-> tool_invocation(runId)
|
||
```
|
||
|
||
- `sessionId` 表示多轮会话目录和 Redis 上下文。
|
||
- `runId` 表示一次可回放诊断执行。
|
||
- `DiagnosisTraceService` 聚合一个 run 的主记录、步骤和工具调用,形成可回放 Trace。
|
||
- `diagnosis_session` 只保留为历史兼容和回滚表。
|
||
|
||
## 2. 生命周期总图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start["request: chat / ai_ops"] --> Resolve["resolve sessionId"]
|
||
Resolve --> Session["ensure chat_session metadata"]
|
||
Session --> Run["create diagnosis_run(runId)"]
|
||
Run --> Running["run.status = RUNNING"]
|
||
|
||
Running --> Agent["Agent workflow"]
|
||
Agent --> Context["execution context(sessionId, runId)"]
|
||
Context --> StepHook["AgentLoggingHook"]
|
||
StepHook --> Step["agent_step(session_id, run_id)"]
|
||
Context --> Tool["Evidence tools"]
|
||
Tool --> Invocation["tool_invocation(session_id, run_id)"]
|
||
Invocation --> Gatekeeper["Gatekeeper evidence validation"]
|
||
|
||
Agent --> Final{"workflow result"}
|
||
Final -->|success| Success["run.status = SUCCESS, answer saved"]
|
||
Final -->|failed| Failed["run.status = FAILED"]
|
||
|
||
Success --> Evaluation["diagnosis_run.self_evaluation merge"]
|
||
Failed --> Evaluation
|
||
Evaluation --> Trace["GET /api/diagnosis/{sessionId}/trace?runId=..."]
|
||
Success --> Feedback["POST /api/feedback(sessionId, runId)"]
|
||
Feedback --> Case["useful -> case_library(run_id)"]
|
||
```
|
||
|
||
## 3. ID 规则
|
||
|
||
| ID | 来源 | 含义 |
|
||
|---|---|---|
|
||
| `sessionId` | Chat request `Id`、AIOps payload `sessionId`,缺失时由服务生成 | 多轮会话目录和 Redis 上下文 |
|
||
| `runId` | 每次有效 Chat/AIOps 执行创建 | 一次诊断运行和 Trace 回放边界 |
|
||
|
||
设计含义:
|
||
|
||
- 同一个 `sessionId` 可以贯穿多轮 Chat。
|
||
- 每次有效 Chat/AIOps 执行都会创建新的 `runId`。
|
||
- Trace 和 Feedback 新客户端应传 `runId`;只传 `sessionId` 时兼容解析 latest run。
|
||
- latest run 排序使用 `diagnosis_run.created_at DESC, id DESC`,不使用 `updated_at`。
|
||
|
||
## 4. 运行状态流转
|
||
|
||
```mermaid
|
||
stateDiagram-v2
|
||
[*] --> PENDING
|
||
PENDING --> RUNNING: start diagnosis
|
||
RUNNING --> SUCCESS: workflow completed
|
||
RUNNING --> FAILED: exception / empty state
|
||
SUCCESS --> SUCCESS: feedback submitted
|
||
FAILED --> FAILED: feedback submitted
|
||
```
|
||
|
||
字段边界:
|
||
|
||
| 字段 | 所属表 | 含义 |
|
||
|---|---|---|
|
||
| `status` | `diagnosis_run` | 单次运行执行状态 |
|
||
| `answer` | `diagnosis_run` | 本次运行最终报告或答复 |
|
||
| `self_evaluation` | `diagnosis_run` | 本次运行系统自评估 JSON |
|
||
| `feedback` | `diagnosis_run` | 本次运行用户反馈 |
|
||
|
||
`feedback` 不修改 `status`。一个执行成功但用户标记 `not_useful` 的 run,仍然应该是 `SUCCESS + feedback=not_useful`。
|
||
|
||
## 5. agent_step 写入
|
||
|
||
`AgentLoggingHook` 在模型调用前后写入和回填 `agent_step`。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
autonumber
|
||
participant Agent as Agent
|
||
participant Hook as AgentLoggingHook
|
||
participant DB as agent_step
|
||
|
||
Agent->>Hook: before_model(messages, sessionId, runId)
|
||
Hook->>DB: insert step(session_id, run_id, model_input, step_index)
|
||
Agent->>Hook: after_model(output, sessionId, runId)
|
||
Hook->>DB: update model_output, duration, token_count, has_tool_call
|
||
```
|
||
|
||
新写入必须带 `run_id`,同时保留 `session_id` 便于粗粒度排查。
|
||
|
||
## 6. tool_invocation 写入
|
||
|
||
工具调用记录同样通过执行上下文拿到 `sessionId + runId`:
|
||
|
||
```text
|
||
ToolInvocationRecorder
|
||
-> tool_invocation.session_id
|
||
-> tool_invocation.run_id
|
||
-> retrieval_details / evidence_refs
|
||
```
|
||
|
||
Verifier、Gatekeeper 和 EvaluationService 应按 `run_id` 读取工具调用,避免同一 session 的其他 run 参与评分或证据校验。
|
||
|
||
## 7. Trace API 聚合
|
||
|
||
```text
|
||
GET /api/diagnosis/{sessionId}/trace
|
||
GET /api/diagnosis/{sessionId}/trace?runId=run-...
|
||
```
|
||
|
||
聚合逻辑:
|
||
|
||
```text
|
||
diagnosis_run by sessionId + runId
|
||
+ chat_session metadata when available
|
||
+ agent_step where run_id = runId, ordered by the Trace API
|
||
+ tool_invocation where run_id = runId order by id
|
||
-> DiagnosisTraceResponse
|
||
```
|
||
|
||
当 `runId` 缺失时,Trace API 为兼容旧客户端解析最新 run,并在响应中返回 resolved `runId`。当 `runId` 属于其他 `sessionId` 时,API 必须拒绝,不能泄漏其他会话的 Trace。
|
||
|
||
## 8. Chat 与 AIOps 差异
|
||
|
||
| 维度 | Chat | AIOps |
|
||
|---|---|---|
|
||
| `agent_flow` | `CHAT` | `AI_OPS` |
|
||
| 编排方式 | `SequentialAgent`: Planner -> Executor -> Gatekeeper -> Verifier -> Composer | `SupervisorAgent`: Planner + Executor |
|
||
| 自评估 | `rule_evaluation` + `verifier_evaluation` | `aiops_rule_evaluation` |
|
||
| 答案字段 | Chat 最终答复 | 告警分析报告 |
|
||
| runId 暴露 | `/api/chat` JSON response | `/api/ai_ops` SSE metadata message |
|
||
|
||
## 9. 清理与边界
|
||
|
||
- Redis 会话历史用于多轮上下文,不是长期审计记录。
|
||
- MySQL `diagnosis_run + agent_step + tool_invocation` 是主要可回放来源。
|
||
- `chat_session.expires_at` 只是目录元数据;Redis 消息历史可独立过期。
|
||
- `RetrievedDocTracker` 仍是 session 级运行时去重状态,诊断结束后清理。
|
||
|
||
## 10. 后续增强
|
||
|
||
1. Trace API 增加更结构化的 `self_evaluation` 展示。
|
||
2. `agent_step` 与 `tool_invocation.step_id` 建立更严格关联。
|
||
3. 旧 `diagnosis_session` 只读观察期结束后,再评估数据库层面的约束收紧或归档策略。
|