- RetrievedDocTracker 升级为域级+文档级双层记录(Map<sessionId, Map<domain, Set<filePath>>>) - LookupKnowledgeTool 新增 Min-Max 归一化层(BGE-M3 L2 距离→[0,1] similarity) - 三等级 relevanceLevel:PRECISE / HIGHLY_RELEVANT / REFERENCE + completenessHint 兜底信号 - LookupResult 新增 relevanceLevel、completenessHint、retrievedDomainsThisSession - Executor prompt 重写:4 条检索约束 + 合法出口不查全不追责,重复检索才惩罚 - 入库可观测性:V010 迁移 + retrieval_details JSON 扩展 - 归档 executor-action-memory-relevance change
90 lines
4.2 KiB
Markdown
90 lines
4.2 KiB
Markdown
# Proposal: executor-action-memory-relevance
|
||
|
||
## 问题
|
||
|
||
ISS-002:Executor 在单次会话中调用 `lookup_knowledge` 20+ 次,大部分是同域换变体的冗余调用。
|
||
|
||
根因:
|
||
1. **行动记忆缺失**:Executor 不知道自己已经检索过哪些域,反复用不同关键词查同一个域
|
||
2. **质量信号缺失**:检索结果没有归一化质量等级,LLM 无法判断"结果够不够"
|
||
3. **Prompt 约束缺失**:现有 executor prompt 要求"所有需要外部信息的地方都必须调用工具",没有"放弃检索"的合法出口
|
||
|
||
## 建议方案
|
||
|
||
### 1. 行动记忆(通过工具返回值传递)
|
||
|
||
`RetrievedDocTracker` 数据结构升级:`Map<sessionId, Map<domain, Set<filePath>>>`。
|
||
|
||
每次 `lookup_knowledge` 返回值附带 `retrievedDomainsThisSession`,让 Executor 知道自己本次会话已检索过哪些域。
|
||
|
||
**不给 Executor knowledge map**——保持 Agent 边界清晰:Planner 知道全域(规划查哪个域),Executor 只知道自己做了什么(执行检索 + 基于结果推理)。
|
||
|
||
### 2. 归一化质量等级(封装 L0/L1 分数差异)
|
||
|
||
在 `LookupKnowledgeTool` 内部新增归一化层,将 L0 匹配数和 L1 score 统一为三个等级:
|
||
|
||
| 等级 | 含义 | LLM 应做什么 |
|
||
|------|------|-------------|
|
||
| `PRECISE` | 精准命中 | 直接使用,不再检索 |
|
||
| `HIGHLY_RELEVANT` | 高度相关 | 综合推理,大概率不需要继续查 |
|
||
| `REFERENCE` | 相关参考 | 可参考,如需更精准请明确缺什么维度 |
|
||
|
||
归一化逻辑:
|
||
- L0 唯一匹配 → PRECISE
|
||
- L0 命中 + L1 高分 → HIGHLY_RELEVANT
|
||
- L0 多匹配 + L1 中分 → HIGHLY_RELEVANT
|
||
- L0 多匹配 + 无 L1 → REFERENCE
|
||
- 仅 L1 命中 → 按 score 分 HIGHLY_RELEVANT / REFERENCE
|
||
|
||
**L0/L1 原始分数不返回给 LLM**,只在归一化层内部使用。原始分数入库(`tool_invocation.retrieval_details`)保留可观测性。
|
||
|
||
### 3. 兜底信号(completenessHint)
|
||
|
||
每次返回附带 `completenessHint`,给 LLM "天花板"信号:
|
||
|
||
| relevanceLevel | completenessHint |
|
||
|----------------|-----------------|
|
||
| PRECISE | "知识库中不存在比上述结果更精准的文档" |
|
||
| HIGHLY_RELEVANT | "当前结果已高度相关,继续检索不太可能找到更精准的文档" |
|
||
| REFERENCE | "当前结果为相关参考,如需更精准信息请明确缺少的具体维度" |
|
||
|
||
### 4. Executor prompt 重写检索约束
|
||
|
||
- 基于 `retrievedDomainsThisSession` 判断重复(不是"不要重复",而是"重复了该怎么办")
|
||
- 给 LLM 合法出口:"不查全不会被追责,重复检索才会被惩罚"
|
||
- 利用 `relevanceLevel` + `completenessHint` 判断质量
|
||
|
||
### 5. 入库可观测性
|
||
|
||
`tool_invocation` 表新增 `relevance_level` 和 `dedup_reason` 列。
|
||
`retrieval_details` JSON 扩展:加入归一化等级、兜底信号、已检索域、去重原因、L1 top score。
|
||
|
||
## 范围
|
||
|
||
- `LookupKnowledgeTool`:归一化层 + 行动记忆注入 + 域级拦截
|
||
- `RetrievedDocTracker`:数据结构升级(域级记录)
|
||
- `LookupResult`:新增 `relevanceLevel`、`completenessHint`、`retrievedDomainsThisSession`
|
||
- `chat-executor-prompt.md`:检索约束重写
|
||
- `ToolInvocation` 实体 + V010 迁移:新增列
|
||
- `LookupKnowledgeTool.saveToolInvocation()`:扩展入库字段
|
||
|
||
## 非目标
|
||
|
||
- 不给 Executor 注入 knowledge map(保持 Agent 边界)
|
||
- 不修改 Planner prompt 或 Planner 逻辑
|
||
- 不修改 `PrimaryResult`/`SupplementResult` 的字段(不暴露原始分数给 LLM)
|
||
- Phase 2 域级硬限制暂不实施,先观察 prompt 约束效果
|
||
|
||
## 风险
|
||
|
||
1. L1 score 阈值(0.3/0.7)需要根据实际 embedding 分布调优,当前为初始值
|
||
2. 归一化等级可能让 LLM 过早停止检索——需实测观察 REFERENCE 场景下的行为
|
||
3. Prompt 约束仍依赖 LLM 遵守——如果效果不足,需启用 Phase 2 域级硬限制
|
||
|
||
## 来自 devflow 的上下文约束
|
||
|
||
- 前序 change `session-dedup-knowledge-map`:已实现文档级去重(RetrievedDocTracker + filePath)和 Planner knowledge map 注入
|
||
- ISS-001:文档级重复召回已修复
|
||
- glossary:ReactAgent 是自主决策工具调用的 Agent,不受外部流程控制
|
||
- JPA ddl-auto 使用 validate 模式,表结构修改必须通过 Flyway 迁移
|