Files
SuperBizAgent-java/mvp/issues/ISS-003-executor-domain-hard-limit.md
T

147 lines
4.9 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.
# ISS-003 Executor 域级检索水位控制(Phase 2)
**状态**:待规划
**严重程度**:低(当前软约束已从 20+ 次收敛到 10 次,文档级去重兜住无效调用)
**发现时间**:2026-07-01
**关联**:ISS-002(Part A 软约束已修,LLM 遵守度不够)
---
## 现象
ISS-002 修复后,lookup_knowledge 调用从 20+ 次降到 10 次,但仍有 8 次冗余调用:
```
id=138 → infrastructure 首次检索 HIGHLY_RELEVANT
id=139 → infrastructure 变体 → doc_retrieved
id=140 → infrastructure 变体 → doc_retrieved
id=141 → api 首次检索 REFERENCE
id=142 → api 变体 → doc_retrieved
id=143 → infrastructure 变体 → doc_retrieved(又跳回)
id=144-146 → infrastructure 变体 × 3 → doc_retrieved
id=147 → api 变体 → doc_retrieved
```
LLM 在两个域之间反复横跳,prompt 第 2 条"禁止换关键词重新检索"被忽略。
---
## 根本原因
Prompt 软约束依赖 LLM 遵守,但 LLM 在自主决策(ReactAgent)模式下倾向于"多确认一步"而不是"相信已有信息"。
---
## 影响
- **可接受**:文档级去重已拦截重复内容,不影响回答质量
- **可优化**:每次冗余调用浪费 400-500ms 服务端检索时间
- **长会话风险**:如果 session 持续追问,冗余调用会线性增长
---
## 方案:质量等级×水位决策矩阵
### 核心思路
将检索决策权从 LLM 思维链移交到代码层,动态判断是否允许下一次 `lookup_knowledge`。
### 决策矩阵
```
水位
低 中 高
PRECISE 可用 可用 可用/停
HIGHLY_ 可用 可用 停
REFERENCE 可定向补 可定向补 停
DEDUPED 停 停 停
```
### 水位指标
| 水位 | 指标 | 说明 |
|------|------|------|
| 低 | lookup_knowledge 调用 ≤ 3 次 | 检索预算充足 |
| 中 | lookup_knowledge 调用 4-8 次 | 适当收紧定向补充 |
| 高 | lookup_knowledge 调用 ≥ 8 次 | 熔断,禁止再查 |
备选水位指标:
- Token 消耗量
- 已检索域数(retrievedDomainsThisSession.size())
### 熔断 prompt 示例
每次工具返回后,代码根据矩阵结果动态拼装约束注入下一步 LLM:
| 场景 | 熔断 prompt |
|------|------------|
| 水位高 + HIGHLY_RELEVANT | "水位已高,请直接给出最终结论,不要再调用 lookup_knowledge" |
| 水位高 + REFERENCE | "水位已高,lookup_knowledge 已被限制,直接基于已有信息回答" |
| 水位低 + REFERENCE | "水位充足,可针对缺少的维度定向补充检索一次" |
| DEDUPED + 任何水位 | "该内容已检索过,禁止重复调用 lookup_knowledge" |
### 架构改动
```
ChatService / ChatExecutorAgent 执行循环
│
├─ step N: LLM 调用工具 → lookup_knowledge 返回
├─ step N+1:
│ ├─ 读取 LookupResult(relevanceLevel + retrievedDomainsThisSession)
│ ├─ 算当前水位(调用计数 / token / 域数)
│ ├─ 查决策矩阵 → 是否允许继续检索
│ └─ 拼装熔断 prompt → 注入 LLM 下一步 SystemMessage
├─ step N+2: LLM 收到约束后的回复
└─ ...
```
### 与现有机制的关系
| 机制 | 层 | ISS-002 | ISS-003 |
|------|-----|---------|---------|
| 静态 Prompt 约束 | Prompt | 已实现 | 保留作为基线 |
| 行动记忆(retrievedDomainsThisSession) | 工具返回值 | 已实现 | 复用 |
| 归一化质量等级(relevanceLevel) | 工具返回值 | 已实现 | 复用 |
| 文档级去重(doc_retrieved) | 工具层 | 已实现 | 保留 |
| **域级水位决策矩阵** | 代码层 | — | **新增** |
| DEDUPED 等级启用 | 工具返回值 | 设计预留 | 启用 |
---
## 修法方向
### 方案 A:决策矩阵(推荐)
上述质量等级×水位矩阵,在 ChatService 执行循环中做决策。
优点:
- 不依赖 LLM 遵守程度
- 保留定向补充的合法通道(比硬拦截更灵活)
- 水位指标可配置,运维友好
缺点:
- 需要改动 ChatService/ExecutorAgent 执行逻辑
- 需要定义水位阈值(需实测校准)
### 方案 B:域级工具层硬限流
在 `LookupKnowledgeTool` 入口直接判断 `isDomainRetrieved(sessionId, domain)`,同域直接返回不检索。
优点:实现简单,100% 可靠
缺点:没有"定向补充"的灵活度,误杀合法跨域查询
### 建议
**方案 A**。利用 ISS-002 已有数据结构和归一化等级,新增决策引擎层,改动量不大且灵活度高。
---
## 相关文件
- `src/main/java/com/superbiz/agent/dto/LookupResult.java`
- `src/main/java/com/superbiz/agent/tool/RetrievedDocTracker.java`
- `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`
- `src/main/resources/prompts/chat-executor-prompt.md`
- 架构设计:`mvp/architecture/action-memory-relevance.md`
- OpenSpec:`openspec/changes/archive/2026-07-01-executor-action-memory-relevance/`