56 lines
1.7 KiB
Markdown
56 lines
1.7 KiB
Markdown
# RAG L0 和 L1 未真正融合排序
|
||
|
||
**状态**:待规划
|
||
**严重程度**:中
|
||
**发现时间**:2026-07-04
|
||
**范围**:知识检索工具、召回排序、Agent 证据质量
|
||
|
||
---
|
||
|
||
## 现象
|
||
|
||
当前 `lookup_knowledge` 的 L0 和 L1 更像是串行兜底关系,不是真正的多路召回融合:
|
||
|
||
- L0 命中唯一结果时,直接返回 L0。
|
||
- L0 不唯一或不足时,才进入 L1。
|
||
- L1 查询 `topK=3`,但最终主要把第一条结果作为补充证据。
|
||
|
||
这会导致关键词召回和语义召回没有充分互补。
|
||
|
||
---
|
||
|
||
## 当前实现
|
||
|
||
- `LookupKnowledgeTool` 先调用 `KnowledgeIndexService.exactMatch` 做 L0。
|
||
- 再按条件调用 `VectorSearchService.search` 做 L1。
|
||
- L0 和 L1 结果没有统一进入候选池做 fusion ranking。
|
||
- L1 多结果没有充分利用,相关性接近的候选可能被丢弃。
|
||
|
||
---
|
||
|
||
## 影响
|
||
|
||
- L0 命中但质量一般时,会压过更好的 L1 语义结果。
|
||
- L1 找到多个相近片段时,只有 top1 被 Agent 看到,降低召回覆盖率。
|
||
- 难以解释检索排序,因为当前更像规则分支,不是可调的排序模型。
|
||
|
||
---
|
||
|
||
## 建议修复
|
||
|
||
建立统一候选池:
|
||
|
||
1. L0 和 L1 都返回候选列表。
|
||
2. 按 `docId/chunkId` 去重。
|
||
3. 为候选计算综合分:`keywordScore`、`vectorScore`、`domainScore`、`freshness`、`breadcrumbMatch`。
|
||
4. 取 topN 进入上下文打包,而不是只取 L1 top1。
|
||
5. 在 `tool_invocation` 中记录每个候选的分数组成,方便调试。
|
||
|
||
---
|
||
|
||
## 相关文件
|
||
|
||
- `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`
|
||
- `src/main/java/com/superbiz/agent/service/KnowledgeIndexService.java`
|
||
- `src/main/java/com/superbiz/agent/service/VectorSearchService.java`
|