# 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`