feat(session): 会话存储体系实现 & Chat多Agent路由

- 新增诊断会话(diagnosis_session/agent_step/tool_invocation)三表
- AgentLoggingHook 持久化 agent_step,记录决策链和耗时
- LookupKnowledgeTool 写入 tool_invocation,记录L0/L1检索质量
- TokenTrackingChatModel 捕获真实token用量
- Chat接口支持意图路由:简单问题单Agent,复杂问题多Agent(Planner+Executor)
- Prompt外置到 src/main/resources/prompts/
- 删除旧 diagnosis_record 表及相关文件
- 新增SessionContextHolder(ThreadLocal传递sessionId)
- QuestionComplexity 复杂度判断工具
- 测试覆盖三张新表的Repository
This commit is contained in:
zhuyongxin
2026-06-26 16:22:05 +08:00
parent a74ccea5be
commit 0d9cce75f9
33 changed files with 1941 additions and 470 deletions
@@ -0,0 +1,88 @@
# 会话存储 — 决策记录
## Question Pool
### 术语维度
| # | 问题 | 类型 | 状态 |
|---|------|------|:----:|
| Q1 | AgentLoggingHook 如何获得 Repository 访问能力? | evidence-driven | ✅ 已查证 |
| Q2 | AiOpsService 当前是否使用了 AgentLoggingHook? | evidence-driven | ✅ 已查证 |
### 边界维度
| # | 问题 | 类型 | 状态 |
|---|------|------|:----:|
| Q3 | Hook 中写 DB 是否同步?要不要一步到位做异步? | user-interview | ✅ 已确认 |
| Q4 | AiOpsService 的 Supervisor 步骤是否单独记录? | user-interview | ✅ 已确认 |
### 验收维度
| # | 问题 | 类型 | 状态 |
|---|------|------|:----:|
| Q5 | tool_invocation 的 output_preview 截断多长合适? | 默认 | 500 字符 |
### 技术实现维度
| # | 问题 | 类型 | 状态 |
|---|------|------|:----:|
| Q6 | LookupKnowledgeTool 如何获取当前 sessionId 和 stepId? | **待解决** | ⚠️ 未确认 |
## Evidence-Driven 查证
### E1: AgentLoggingHook 创建方式
**证据**:ChatService 第 180 行 `.hooks(new AgentLoggingHook())` — 直接 new 创建,非 Spring 管理。
**结论**:Hook 不是 Spring Bean,无法注入 Repository。AiOpsService 的 Planner/Executor 也没有加 Hook。
**影响**:需要改造为 @Component + 构造注入,并在 AiOpsService 中补齐。
### E2: 项目异步基础设施
**证据**:全局搜索 `@Async`、`@EnableAsync`、`CompletableFuture`、`TaskExecutor` — 均无匹配。
**结论**:项目没有异步执行基础设施。
**影响**:MVP 阶段 Hook 内同步写 DB,后续再优化。
## User-Interview 确认
### U1: Hook 改造方式
**问题**:AgentLoggingHook 怎样获得 Repository 访问能力?
**选项**:
1. 改造为 Spring Bean(@Component + 构造注入)
2. 保持 POJO,从外部传 Repository
**用户答复**:改为 Hook(Spring Bean)
**确认状态**:✅ 已确认
### U2: AiOpsService 记录粒度
**问题**:Supervisor 内部的步骤记录范围?
**选项**:
1. 只记子 Agent(Planner/Executor)步骤
2. 全量记录(含 Supervisor)
**用户答复**:接受建议,只记子 Agent
**确认状态**:✅ 已确认
## 开放问题
### O1: LookupKnowledgeTool 获取 sessionId
LookupKnowledgeTool 是 `@Component`,通过 Spring AI 的 `@Tool` 注解暴露给 Agent。它不直接参与 Agent Hook 调用链,**无法直接从 RunnableConfig 读取 sessionId**。
可能的方案:
1. **ThreadLocal** — ChatService/AiOpsService 在执行前设置当前 sessionId 到 ThreadLocal,工具中读取。简单,但需注意清理。
2. **从 agent_step 反查** — 工具调用后根据时间戳和 session 关联查找最近的 step。不准确。
3. **RequestContextHolder** — 利用 Spring 的请求上下文。仅限 Web 请求上下文有效。
**建议方案**:ThreadLocal。在 ChatService/AiOpsService 执行入口设置,AgentLoggingHook 和 LookupKnowledgeTool 都从 ThreadLocal 读取。
**用户确认**:✅ 同意 ThreadLocal 方案