Files
SuperBizAgent-java/openspec/changes/archive/2026-07-01-executor-action-memory-relevance/tasks.md
T
zhuyongxin e438df4355 feat(knowledge): Executor 行动记忆 + 归一化质量等级解决 ISS-002 重复检索
- 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
2026-07-01 18:24:41 +08:00

90 lines
4.0 KiB
Markdown
Raw 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.
# Tasks: executor-action-memory-relevance
## T1: RetrievedDocTracker 域级升级
**文件**: `src/main/java/com/superbiz/agent/tool/RetrievedDocTracker.java`
**改动**:
- 数据结构从 `ConcurrentHashMap<sessionId, Set<filePath>>` 升级为 `ConcurrentHashMap<sessionId, Map<domain, Set<filePath>>>`
- 新增 `markRetrieved(sessionId, domain, filePath)`
- 新增 `isDocRetrieved(sessionId, filePath)` — 从内层 Map 的 values 中查找 filePath
- 新增 `isDomainRetrieved(sessionId, domain)` — 检查 domain key 存在
- 新增 `getRetrievedDomains(sessionId)` → `List<String>`
- `isAlreadyRetrieved(sessionId, filePath)` 保留(委托给 isDocRetrieved,向后兼容)
- `clearSession(sessionId)` 清理外层 key
**验收**: FS-3 所有验收标准通过
## T2: LookupResult 新增字段
**文件**: `src/main/java/com/superbiz/agent/dto/LookupResult.java`
**改动**:
- 新增 `String relevanceLevel`
- 新增 `String completenessHint`
- 新增 `List<String> retrievedDomainsThisSession`
**验收**: 编译通过,字段存在且类型正确
## T3: 归一化计算逻辑
**文件**: `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`
**改动**:
- 新增配置类或字段读取 `retrieval.normalization.max-l2-distance`(默认 2.0)、`highly-relevant-threshold`(默认 0.75)、`reference-threshold`(默认 0.5)
- 新增私有方法 `computeRelevance(int l0MatchCount, float l1TopScore)` → 返回包含 `relevanceLevel` + `completenessHint` 的 record/内部类
- L2 距离归一化:`similarity = 1 - min(l1TopScore, maxL2Distance) / maxL2Distance`
- 判定逻辑按 design.md 中的优先级实现
**验收**: FS-1 + FS-2 所有验收标准通过
## T4: LookupKnowledgeTool 集成归一化 + 行动记忆
**文件**: `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`
**改动**:
- `lookupKnowledge()` 方法中,在 Step 4(组装结果)后、Step 5(去重过滤)前,调用 `computeRelevance()` 计算 relevanceLevel 和 completenessHint
- 从 l0Matches 提取 domain(`l0Matches.get(0).getCategory()`),L1 结果尝试从 metadata JSON 解析 category(兜底)
- markRetrieved 调用从 `markRetrieved(sessionId, docKey)` 改为 `markRetrieved(sessionId, domain, docKey)`
- 去重拦截时(文档级),LookupResult 也附带 retrievedDomainsThisSession
- LookupResult.builder() 中设置三个新字段
**验收**: FS-4 所有验收标准通过;日志中可看到 relevanceLevel 和 completenessHint 输出
## T5: Executor Prompt 重写
**文件**: `src/main/resources/prompts/chat-executor-prompt.md`
**改动**:
- 将"所有需要外部信息的地方,都必须调用对应的工具"替换为"需要外部信息时调用工具,但须遵守下方的检索约束"
- 新增"## 检索约束"区块,包含 4 条规则(判断重复、重复了该怎么办、合法出口、利用质量信号)
- 不注入 knowledge map
**验收**: FS-5 所有验收标准通过
## T6: 入库可观测性
**文件**:
- `src/main/resources/db/migration/V010__add_relevance_level_to_tool_invocation.sql`
- `src/main/java/com/superbiz/agent/domain/entity/ToolInvocation.java`
- `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`(saveToolInvocation 方法)
**改动**:
- V010: ALTER TABLE tool_invocation ADD relevance_level VARCHAR(20), ADD dedup_reason VARCHAR(32)
- ToolInvocation 实体新增 `relevanceLevel` 和 `dedupReason` 字段
- saveToolInvocation() 中:
- 设置 `inv.setRelevanceLevel(...)` 和 `inv.setDedupReason(...)`
- retrieval_details JSON 扩展:新增 l1_top_similarity、relevance_level、completeness_hint、retrieved_domains、dedup_reason 字段
- 去重拦截时,dedupReason 设为 "doc_retrieved";域级拦截时设为 "domain_retrieved"
**验收**: FS-6 所有验收标准通过
## T7: BGE-M3 归一化验证测试
**文件**: `src/test/java/com/superbiz/agent/service/FullPipelineSmokeTest.java`
**改动**:
- 已完成:embeddingBgeM3Works() 中新增 L2 范数断言(范数=1.00000002,测试已通过)
**验收**: 测试通过,范数断言 |norm - 1.0| < 0.01