- 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
5.4 KiB
5.4 KiB
Functional Spec: executor-action-memory-relevance
FS-1: L2 距离归一化
需求
LookupKnowledgeTool 内部将 L1 的 L2 距离归一化为 [0,1] 区间的 similarity 值,基于 BGE-M3 输出为 L2 归一化单位向量(已实测验证,范数=1.00000002)。
可观察行为
- 归一化公式:
similarity = 1 - min(l2Score, maxL2Distance) / maxL2Distance maxL2Distance默认 2.0,可通过retrieval.normalization.max-l2-distance覆盖- 归一化阈值可通过
retrieval.normalization.highly-relevant-threshold和retrieval.normalization.reference-threshold配置 - 归一化计算在 LookupKnowledgeTool 内部完成,不暴露原始分数给 LLM
验收标准
- L2 score=0 → similarity=1.0
- L2 score=1.0 → similarity=0.5
- L2 score=2.0 → similarity=0.0
- L2 score=3.0(超出上界)→ similarity=0.0(min 函数截断)
- 配置项可通过 yml 覆盖默认值
FS-2: 归一化质量等级判定
需求
基于 L0 匹配数和归一化后的 L1 similarity,输出三等级 relevanceLevel + completenessHint。
可观察行为
- L0 唯一匹配 → PRECISE + "知识库中不存在比上述结果更精准的文档"
- L0 命中 + L1 similarity ≥ 0.75 → HIGHLY_RELEVANT + "当前结果已高度相关,继续检索不太可能找到更精准的文档"
- 仅 L1 similarity ≥ 0.75 → HIGHLY_RELEVANT + 对应 hint
- L0 多匹配 + L1 similarity [0.5, 0.75) → REFERENCE + "当前结果为相关参考,如需更精准信息请明确缺少的具体维度"
- 仅 L1 similarity [0.5, 0.75) → REFERENCE + 对应 hint
- L1 similarity < 0.5 → 不视为有效结果
- 无 L0 且无 L1 → found=false
验收标准
- L0 matchCount=1 → relevanceLevel=PRECISE
- L0 matchCount=2, L1 similarity=0.8 → relevanceLevel=HIGHLY_RELEVANT
- L0 matchCount=0, L1 similarity=0.8 → relevanceLevel=HIGHLY_RELEVANT
- L0 matchCount=3, L1 similarity=0.6 → relevanceLevel=REFERENCE
- L0 matchCount=0, L1 similarity=0.4 → found=false 或 supplement 被过滤
- 每个 relevanceLevel 对应正确的 completenessHint
FS-3: 域级行动记忆
需求
RetrievedDocTracker 升级为域级 + 文档级双层记录,支持查询当前会话已检索的域列表。
可观察行为
markRetrieved(sessionId, domain, filePath)一次记录两层isDocRetrieved(sessionId, filePath)返回文档级去重结果isDomainRetrieved(sessionId, domain)返回域级检查结果getRetrievedDomains(sessionId)返回已检索域列表clearSession(sessionId)清理所有记录- 现有
isAlreadyRetrieved(sessionId, filePath)语义不变(内部委托给 isDocRetrieved)
验收标准
- markRetrieved("s1", "infrastructure", "a.md") 后,isDocRetrieved("s1", "a.md")=true
- markRetrieved("s1", "infrastructure", "a.md") 后,isDomainRetrieved("s1", "infrastructure")=true
- markRetrieved("s1", "infrastructure", "a.md") 后,getRetrievedDomains("s1")=["infrastructure"]
- markRetrieved("s1", "api", "b.md") 后,getRetrievedDomains("s1")=["infrastructure","api"]
- clearSession("s1") 后,所有方法返回空/false
- 线程安全:ConcurrentHashMap + ConcurrentHashMap 内层
FS-4: LookupResult 返回值扩展
需求
LookupResult 新增 relevanceLevel、completenessHint、retrievedDomainsThisSession 三个字段,让 LLM 获得行动记忆和质量信号。
可观察行为
- 每次 lookup_knowledge 返回值包含这三个新字段
- PrimaryResult 和 SupplementResult 不变,不暴露原始分数
- 去重拦截时,返回值仍包含 retrievedDomainsThisSession(让 LLM 知道已检索了哪些域)
验收标准
- 正常检索返回时,LookupResult 包含 relevanceLevel + completenessHint + retrievedDomainsThisSession
- 文档级去重拦截时,LookupResult.message 包含去重提示,retrievedDomainsThisSession 不为 null
- PrimaryResult 和 SupplementResult 无新增分数字段
FS-5: Executor Prompt 检索约束
需求
重写 chat-executor-prompt.md 的检索规则,从"必须调用工具"改为"基于行动记忆和质量信号判断是否需要检索"。
可观察行为
- Prompt 不包含 knowledge map
- Prompt 包含 4 条检索约束(判断重复、重复了该怎么办、合法出口、利用质量信号)
- 原有规则"所有需要外部信息的地方,都必须调用对应的工具"被替换
验收标准
- Executor prompt 不包含 knowledge map 内容
- Executor prompt 包含"禁止换关键词重新检索"约束
- Executor prompt 包含"不查全不会被追责"合法出口
- Executor prompt 包含 relevanceLevel 行为指导
FS-6: 入库可观测性
需求
tool_invocation 表新增 relevance_level 和 dedup_reason 列,retrieval_details JSON 扩展。
可观察行为
- 每次 lookup_knowledge 调用后,tool_invocation 记录包含 relevance_level 和 dedup_reason
- retrieval_details JSON 包含 l1_top_similarity(归一化后值)、relevance_level、completeness_hint、retrieved_domains、dedup_reason
- 历史数据新列为 null,不影响现有查询
验收标准
- V010 迁移脚本成功执行
- 新增 relevance_level 列 VARCHAR(20) nullable
- 新增 dedup_reason 列 VARCHAR(32) nullable
- saveToolInvocation() 写入新字段
- SQL 可查询归一化等级分布:
SELECT relevance_level, COUNT(*) FROM tool_invocation WHERE tool_name='lookup_knowledge' GROUP BY relevance_level