Spaces:
Sleeping
Sleeping
yc1838 commited on
Commit ·
bcecbbe
1
Parent(s): dffb981
update improvement plan
Browse files- .codex/config.toml +15 -0
- IMPROVEMENT_PLAN.md +166 -233
.codex/config.toml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[mcp_servers.codegraph]
|
| 2 |
+
args = [
|
| 3 |
+
"serve",
|
| 4 |
+
"--mcp",
|
| 5 |
+
]
|
| 6 |
+
command = "codegraph"
|
| 7 |
+
|
| 8 |
+
[mcp_servers.codegraph.tools.codegraph_status]
|
| 9 |
+
approval_mode = "approve"
|
| 10 |
+
|
| 11 |
+
[mcp_servers.codegraph.tools.codegraph_context]
|
| 12 |
+
approval_mode = "approve"
|
| 13 |
+
|
| 14 |
+
[mcp_servers.codegraph.tools.codegraph_explore]
|
| 15 |
+
approval_mode = "approve"
|
IMPROVEMENT_PLAN.md
CHANGED
|
@@ -3,7 +3,9 @@
|
|
| 3 |
> 基于 Marina Wyss "Context Engineering for AI Agents" 视频分析、Anthropic 官方博文、2026 年 5 月最新趋势研究,以及对 lilith-agent 现有代码的逐行审计。
|
| 4 |
>
|
| 5 |
> 日期:2026-05-22
|
| 6 |
-
> 更新:2026-05-
|
|
|
|
|
|
|
| 7 |
|
| 8 |
---
|
| 9 |
|
|
@@ -14,13 +16,13 @@
|
|
| 14 |
- **路线 A(GAIA 提分)**:针对 GAIA benchmark 特点(466 题,全对或全错,三级难度),以最小改动换最大分数提升。当前榜首 Claude Sonnet 4.5 在 Princeton HAL 上 74.6%(有脚手架),裸模型只有 44.8%,说明 agent 框架的价值巨大。
|
| 15 |
- **路线 B(追赶最新趋势)**:让 Lilith 成为架构上最先进的 agent,不只看分数,还看多 agent 编排、context 管理等能力。
|
| 16 |
|
| 17 |
-
下面按
|
| 18 |
|
| 19 |
---
|
| 20 |
|
| 21 |
-
## Phase 0(前置条件):Eval Pipeline 稳定化
|
| 22 |
|
| 23 |
-
**在所有改动之前,必须先确保评估基础设施可靠、结果可复现。**
|
| 24 |
|
| 25 |
### 为什么这是 Phase 0
|
| 26 |
|
|
@@ -28,341 +30,272 @@
|
|
| 28 |
|
| 29 |
### 具体任务
|
| 30 |
|
| 31 |
-
1. **
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
3. **Eval 报告自动化**:每次 eval 后自动生成 JSON 报告,包含:
|
| 34 |
- 总正确率、各 level 正确率
|
| 35 |
- 每题的 tool call 数、耗时、是否触发 fail_safe
|
| 36 |
- 与上次 run 的 diff(新增正确 / 新增错误的题目列表)
|
| 37 |
-
4. **回归检测**:维护一个 `golden_set`(约 20 题,覆盖各 level 和各工具组合),Phase 1/2/3 的每次 PR 都必须在 golden_set 上 pass 才能合并。
|
| 38 |
|
| 39 |
### 涉及文件
|
| 40 |
|
| 41 |
-
- `src/lilith_agent/runner.py`:`run_agent_on_questions()` 增加统计输出
|
|
|
|
|
|
|
| 42 |
- 新增:`scripts/eval_report.py`(生成对比报告)
|
| 43 |
- 新增:`tests/golden_set.json`(稳定题目子集)
|
| 44 |
|
| 45 |
---
|
| 46 |
|
| 47 |
-
##
|
| 48 |
|
| 49 |
-
**路线:A
|
| 50 |
|
| 51 |
-
### 问题
|
| 52 |
|
| 53 |
-
|
| 54 |
|
| 55 |
-
|
|
|
|
| 56 |
|
| 57 |
-
|
| 58 |
|
| 59 |
-
|
| 60 |
|
| 61 |
-
|
| 62 |
-
在 model_node 中,每次 agent 产出 AIMessage 后,调用 cheap model 做一次二分类判断:"这条回复是否标志着一个子任务的完成?"返回 yes/no + 一句话摘要。
|
| 63 |
|
| 64 |
-
|
| 65 |
|
| 66 |
-
|
| 67 |
-
```python
|
| 68 |
-
_MILESTONE_DETECT_PROMPT = (
|
| 69 |
-
"Does this agent message indicate completion of a sub-task or discovery of a key fact? "
|
| 70 |
-
"Answer JSON: {\"is_milestone\": true/false, \"summary\": \"one-line summary if true\"}"
|
| 71 |
-
)
|
| 72 |
-
```
|
| 73 |
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
3. **
|
| 81 |
-
4.
|
|
|
|
|
|
|
| 82 |
|
| 83 |
### 涉及文件
|
| 84 |
|
| 85 |
-
- `src/lilith_agent/app.py`:`
|
| 86 |
-
- 新增
|
| 87 |
|
| 88 |
---
|
| 89 |
|
| 90 |
-
##
|
| 91 |
|
| 92 |
-
**路线:A
|
| 93 |
|
| 94 |
### 问题
|
| 95 |
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
Anthropic 自己的研究表明,子 agent 各自在干净的 context window 中做深度探索,最后只返回 1000-2000 token 的浓缩摘要,在复杂研究任务上表现显著优于单 agent。
|
| 99 |
|
| 100 |
### 实现思路
|
| 101 |
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
|
| 105 |
-
- 子 agent 有自己干净的 context window
|
| 106 |
-
- **精简工具集(按任务类型裁剪)**:子 agent 不应该拿到全部工具,工具越多走偏概率越大。按类型分配:
|
| 107 |
-
- `research` 类型:`web_search`, `fetch_url`, `read_file`, `inspect_pdf`
|
| 108 |
-
- `compute` 类型:`run_python`, `read_file`, `write_file`
|
| 109 |
-
- `vision` 类型:`inspect_visual_content`, `read_file`
|
| 110 |
-
- 所有类型都**不包含** `spawn_sub_agent`(防止递归爆炸,depth=1 硬限制)
|
| 111 |
-
- 子 agent 有独立的、更小的 budget(如 cap=10)
|
| 112 |
-
- **摘要长度按任务类型动态调整**:`research` 类型可能需要更多空间来传递多个发现(≤3000 chars),`compute` 类型通常一个数字就够了(≤500 chars)。不用一刀切 2000 chars。
|
| 113 |
-
2. **主 agent 综合结果**:子 agent 的摘要作为 ToolMessage 返回给主 agent,主 agent 基于多个子 agent 的汇报做最终推理。
|
| 114 |
-
3. **并行 vs 串行**:初期实现串行 spawn(简单可靠),后续可考虑并行。
|
| 115 |
|
| 116 |
### 涉及文件
|
| 117 |
|
| 118 |
-
- `src/lilith_agent/
|
| 119 |
-
- 新增:`src/lilith_agent/
|
| 120 |
-
- `src/lilith_agent/config.py`:新增 `sub_agent_budget`、`sub_agent_summary_caps` 等配置
|
| 121 |
-
|
| 122 |
-
### 注意事项
|
| 123 |
|
| 124 |
-
-
|
| 125 |
-
- GAIA 的 Level 1 题不需要子 agent,可以通过 supervisor 或 heuristic 判断何时触发
|
| 126 |
-
- 子 agent 的 system prompt 应该更聚焦:只描述子任务目标,不包含主 agent 的完整指令集
|
| 127 |
|
| 128 |
---
|
| 129 |
|
| 130 |
-
##
|
| 131 |
|
| 132 |
-
**路线:A | 预估 GAIA 提升:+5-
|
| 133 |
|
| 134 |
### 问题
|
| 135 |
|
| 136 |
-
|
| 137 |
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
### 澄清:ERL 不是强化学习
|
| 141 |
-
|
| 142 |
-
尽管名字里有 "Learning",ERL 不涉及 reward signal 或参数更新。流程是:
|
| 143 |
-
1. 跑完一个任务后,让 LLM 回顾轨迹(成功或失败)
|
| 144 |
-
2. 提炼出文字形式的启发式规则(heuristics),例如:
|
| 145 |
-
- "遇到 Wikipedia 表格数据时,用 `run_python` + pandas 解析比直接读文本更准确"
|
| 146 |
-
- "当搜索返回付费墙页面时,立即换搜索词而非重试同一 URL"
|
| 147 |
-
- "多步数学题必须在 Python 中验证,不要心算"
|
| 148 |
-
3. 将规则存入数据库,标注适用的任务类型/关键词
|
| 149 |
-
4. 下次遇到类似任务时,检索相关规则注入 system prompt
|
| 150 |
-
|
| 151 |
-
### 实现思路(分两步:先验证上限,再自动化)
|
| 152 |
-
|
| 153 |
-
**Step 1:Golden Heuristics 验证上限(1-2 天)**
|
| 154 |
-
|
| 155 |
-
在投入自动化反思管线之前,先手动验证 ERL 的潜力上限:
|
| 156 |
|
| 157 |
-
|
| 158 |
-
- 分析 `.last_failures.txt` 中的失败题目轨迹,人工总结失败原因
|
| 159 |
-
- 复盘已有的成功题目,提取可复用的策略
|
| 160 |
-
- 参考 ERL 论文中的 heuristic 示例
|
| 161 |
-
2. 将这些 golden heuristics 硬编码注入 system prompt
|
| 162 |
-
3. 跑一轮完整 GAIA eval,对比 baseline
|
| 163 |
-
4. 如果提升 < 2%,需要重新审视检索精度和规则质量,再决定是否投入 Step 2
|
| 164 |
|
| 165 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
1. **任务后反思**(Post-Task Reflection):在 `runner.py` 的 `run_agent_on_questions` 中,每个任务完成后(无论成功失败),调用 cheap model 分析轨迹,生成 heuristics。
|
| 170 |
-
2. **规则存储**:在 `memory.py` 的 `MemoryStore` 中新增 `heuristics` 表:
|
| 171 |
-
```sql
|
| 172 |
-
CREATE TABLE heuristics (
|
| 173 |
-
id TEXT PRIMARY KEY,
|
| 174 |
-
rule TEXT NOT NULL, -- 启发式规则文本
|
| 175 |
-
source_task_id TEXT, -- 来源任务
|
| 176 |
-
success BOOLEAN, -- 该任务是否成功
|
| 177 |
-
keywords TEXT, -- 适用关键词(用于检索)
|
| 178 |
-
times_applied INTEGER DEFAULT 0, -- 被检索注入的次数
|
| 179 |
-
times_helped INTEGER DEFAULT 0, -- 注入后任务成功的次数
|
| 180 |
-
times_hurt INTEGER DEFAULT 0, -- 注入后任务失败的次数
|
| 181 |
-
confidence REAL DEFAULT 0.5, -- 动态置信度 = helped / (helped + hurt)
|
| 182 |
-
created_at TEXT,
|
| 183 |
-
retired_at TEXT -- 被淘汰的时间(NULL = 活跃)
|
| 184 |
-
);
|
| 185 |
-
```
|
| 186 |
-
3. **规则检索与注入**:在 `model_node()` 的 iteration 0 阶段,除了现有的 `retrieve_relevant_context()` 之外,额外检索匹配的 heuristics 并注入 system prompt。只注入 `confidence >= 0.4` 且 `retired_at IS NULL` 的规则。
|
| 187 |
-
4. **规则淘汰机制(必须在 Step 2 一开始就设计好)**:
|
| 188 |
-
- 每次任务结束后,回溯本次注入了哪些 heuristics,更新 `times_applied`、`times_helped` 或 `times_hurt`
|
| 189 |
-
- 当 `confidence < 0.3` 且 `times_applied >= 5` 时,自动 retire(设置 `retired_at`)
|
| 190 |
-
- 保留 retired 规则不删除(方便分析),但不再注入
|
| 191 |
-
- 定期(每 50 个任务)输出一次规则健康报告:活跃/退役/低置信度分布
|
| 192 |
-
|
| 193 |
-
**为什么淘汰机制要早做**:低质量规则积累起来会污染 system prompt。一条错误的 heuristic(如"Wikipedia 表格总是在第二个 section")可能让 agent 在本来能做对的题上反而出错。
|
| 194 |
|
| 195 |
### 涉及文件
|
| 196 |
|
| 197 |
-
- `src/lilith_agent/
|
| 198 |
-
- `src/lilith_agent/runner.py`:
|
| 199 |
-
- `src/lilith_agent/app.py`:`model_node()` 中的规则注入(带置信度过滤)
|
| 200 |
-
- 新增:`src/lilith_agent/reflection.py`(反思逻辑独立模块)
|
| 201 |
-
- 新增:`scripts/heuristic_health_report.py`(规则健康报告)
|
| 202 |
|
| 203 |
---
|
| 204 |
|
| 205 |
-
##
|
| 206 |
|
| 207 |
-
**路线:A | 预估 GAIA 提升:+
|
| 208 |
|
| 209 |
### 问题
|
| 210 |
|
| 211 |
-
当前
|
| 212 |
|
| 213 |
### 实现思路
|
| 214 |
|
| 215 |
-
在 `src/lilith_agent/app.py`
|
| 216 |
|
| 217 |
-
1.
|
| 218 |
-
2.
|
| 219 |
-
3.
|
| 220 |
-
|
| 221 |
-
|
| 222 |
|
| 223 |
### 涉及文件
|
| 224 |
|
| 225 |
-
- `src/lilith_agent/app.py`:`
|
| 226 |
-
- `src/lilith_agent/config.py`:新增 `supervisor_model_tier` 配置(cheap/strong/extra_strong)
|
| 227 |
|
| 228 |
---
|
| 229 |
|
| 230 |
-
##
|
| 231 |
|
| 232 |
-
**路线:A | 预估 GAIA 提升:+
|
| 233 |
|
| 234 |
### 问题
|
| 235 |
|
| 236 |
-
|
| 237 |
|
| 238 |
-
### 实现思路
|
| 239 |
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
**Noise patterns 外置成配置文件**(不硬编码在函数里):
|
| 243 |
-
|
| 244 |
-
```yaml
|
| 245 |
-
# config/noise_patterns.yaml
|
| 246 |
-
# 不同语言的页面噪音模式差异大,外置方便维护和扩展
|
| 247 |
-
en:
|
| 248 |
-
- cookie
|
| 249 |
-
- privacy policy
|
| 250 |
-
- terms of service
|
| 251 |
-
- subscribe
|
| 252 |
-
- newsletter
|
| 253 |
-
- follow us
|
| 254 |
-
- share on
|
| 255 |
-
- tweet this
|
| 256 |
-
- skip to content
|
| 257 |
-
- advertisement
|
| 258 |
-
- sponsored
|
| 259 |
-
zh:
|
| 260 |
-
- 隐私政策
|
| 261 |
-
- 使用条款
|
| 262 |
-
- 订阅
|
| 263 |
-
- 关注我们
|
| 264 |
-
- 分享到
|
| 265 |
-
- 跳转到主内容
|
| 266 |
-
- 广告
|
| 267 |
-
```
|
| 268 |
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
cleaned = []
|
| 294 |
-
for line in lines:
|
| 295 |
-
stripped = line.strip()
|
| 296 |
-
if not stripped or len(stripped) < 3:
|
| 297 |
-
continue
|
| 298 |
-
lower = stripped.lower()
|
| 299 |
-
if any(p in lower for p in noise_patterns) and len(stripped) < 80:
|
| 300 |
-
continue
|
| 301 |
-
cleaned.append(line)
|
| 302 |
-
return '\n'.join(cleaned)
|
| 303 |
-
```
|
| 304 |
|
| 305 |
### 涉及文件
|
| 306 |
|
| 307 |
-
- `src/lilith_agent/
|
| 308 |
-
-
|
|
|
|
|
|
|
| 309 |
|
| 310 |
---
|
| 311 |
|
| 312 |
-
##
|
| 313 |
|
| 314 |
-
**路线:A | 预估 GAIA 提升:+
|
| 315 |
|
| 316 |
### 问题
|
| 317 |
|
| 318 |
-
|
| 319 |
|
| 320 |
### 实现思路
|
| 321 |
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
|
| 328 |
### 涉及文件
|
| 329 |
|
| 330 |
-
- `src/lilith_agent/app.py`:
|
| 331 |
-
- `src/lilith_agent/
|
| 332 |
-
- `src/lilith_agent/
|
| 333 |
|
| 334 |
---
|
| 335 |
|
| 336 |
## 实施顺序建议
|
| 337 |
|
| 338 |
```
|
| 339 |
-
Phase 0(
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
└── 建立 golden_set 回归测试
|
| 344 |
|
| 345 |
Phase 1(快速见效,1-2 周)
|
| 346 |
-
├── P3:Supervisor
|
| 347 |
-
├── P4:fetch_url 清洗(
|
| 348 |
-
├── P5:
|
| 349 |
-
└── ⚡ 跑完整 GAIA eval,对比
|
| 350 |
-
|
| 351 |
-
Phase 2(
|
| 352 |
-
├──
|
| 353 |
-
|
| 354 |
-
├──
|
| 355 |
-
├── P2 Step 2:自动化反思管线(含淘汰机制)
|
| 356 |
└── ⚡ 跑完整 GAIA eval,对比 Phase 1
|
| 357 |
|
| 358 |
-
Phase 3(架构
|
| 359 |
-
├── P1
|
| 360 |
-
|
|
|
|
| 361 |
```
|
| 362 |
|
| 363 |
-
**关键原则**:每个 Phase 结束时必须跑
|
| 364 |
-
|
| 365 |
-
Phase 0 是所有后续工作的基础。Phase 1 的三项改动都很小、风险低,适合快速验证。Phase 2 的 ERL 先用手动 golden heuristics 验上限再决定是否投入自动化——避免花两周搭管线结果发现提升不大。Phase 3 改动最大但对 Level 3 长链题帮助最显著。
|
| 366 |
|
| 367 |
---
|
| 368 |
|
|
|
|
| 3 |
> 基于 Marina Wyss "Context Engineering for AI Agents" 视频分析、Anthropic 官方博文、2026 年 5 月最新趋势研究,以及对 lilith-agent 现有代码的逐行审计。
|
| 4 |
>
|
| 5 |
> 日期:2026-05-22
|
| 6 |
+
> 更新:2026-05-23(整合深度 Code Review 反馈与工程落地可行性调整)
|
| 7 |
+
|
| 8 |
+
> **Review note:** 以下新增的 `Review note` 只补充 repo 审计后发现的工程落地风险,不删除或改写原计划内容;实现时应把这些 caveat 当作验收条件的一部分。
|
| 9 |
|
| 10 |
---
|
| 11 |
|
|
|
|
| 16 |
- **路线 A(GAIA 提分)**:针对 GAIA benchmark 特点(466 题,全对或全错,三级难度),以最小改动换最大分数提升。当前榜首 Claude Sonnet 4.5 在 Princeton HAL 上 74.6%(有脚手架),裸模型只有 44.8%,说明 agent 框架的价值巨大。
|
| 17 |
- **路线 B(追赶最新趋势)**:让 Lilith 成为架构上最先进的 agent,不只看分数,还看多 agent 编排、context 管理等能力。
|
| 18 |
|
| 19 |
+
下面按最新的执行顺序排列,每项标注属于哪条路线。
|
| 20 |
|
| 21 |
---
|
| 22 |
|
| 23 |
+
## Phase 0(前置条件):Eval Pipeline 稳定化与 Blockers 修复
|
| 24 |
|
| 25 |
+
**在所有改动之前,必须先确保评估基础设施可靠、结果可复现,同时修复目前存在的严重状态泄露和参数解析 Bug。**
|
| 26 |
|
| 27 |
### 为什么这是 Phase 0
|
| 28 |
|
|
|
|
| 30 |
|
| 31 |
### 具体任务
|
| 32 |
|
| 33 |
+
1. **修复 Blockers**:
|
| 34 |
+
- **`--force` 状态泄露**:当前仅删除 JSON 文件,未清理 checkpointer 的 SQLite persistence。旧的 thread state 在 SQLite 中依然存活,会严重污染重跑结果。
|
| 35 |
+
- **CLI `--level` 解析错误**:`dev_run_gaia.py` 传入的是字符串,而数据集匹配需要严格类型,导致 `--level 1,2,3` 匹配出空集。
|
| 36 |
+
> **Review note:** repo 当前在 `gaia_dataset.py` 中已经把 `row.get("Level")` 和 `level` 都转成字符串比较;真正的缺口不是严格类型,而是 `--level 1,2,3` / `--level all` 这类多 level 输入没有被解析成集合过滤。
|
| 37 |
+
- **`scoring API split` 冲突**:`os.getenv("GAIA_DATASET_SPLIT","test")` 的 fallback 逻辑会与本地 validation runs 冲突,也可能影响 leaderboard 提交脚本,需显式隔离。
|
| 38 |
+
- **Checkpoint 职责分离**:当前的 checkpoint 混杂了 leaderboard payload 和 debug 状态。需要剥离 metadata 到 `runs/<run_id>/<task_id>.json` 中。
|
| 39 |
+
> **Review note:** 如果 metadata 或 per-run checkpoint 迁移到 `runs/<run_id>/...`,必须同步更新 `scripts/build_leaderboard_submission.py` 和相关测试;该脚本当前只从单一 checkpoint 目录 glob `*.json` 生成 submission。
|
| 40 |
+
2. **Baseline 锁定与回归**:跑 3 次精简的 stratified golden set (约 20 题,覆盖各 level) 和 1 次 full GAIA eval,记录分数和各 level 的正确率。
|
| 41 |
3. **Eval 报告自动化**:每次 eval 后自动生成 JSON 报告,包含:
|
| 42 |
- 总正确率、各 level 正确率
|
| 43 |
- 每题的 tool call 数、耗时、是否触发 fail_safe
|
| 44 |
- 与上次 run 的 diff(新增正确 / 新增错误的题目列表)
|
|
|
|
| 45 |
|
| 46 |
### 涉及文件
|
| 47 |
|
| 48 |
+
- `src/lilith_agent/runner.py`:`run_agent_on_questions()` 增加统计输出与 env var 修复
|
| 49 |
+
- `src/lilith_agent/app.py`:修复 checkpointer clear 逻辑
|
| 50 |
+
- `scripts/dev_run_gaia.py`:修复 level parse 逻辑
|
| 51 |
- 新增:`scripts/eval_report.py`(生成对比报告)
|
| 52 |
- 新增:`tests/golden_set.json`(稳定题目子集)
|
| 53 |
|
| 54 |
---
|
| 55 |
|
| 56 |
+
## Phase 0.5:Normalizer 鲁棒性审计
|
| 57 |
|
| 58 |
+
**路线:A | 预估 GAIA 提升:免费加分项**
|
| 59 |
|
| 60 |
+
### 问题与思路
|
| 61 |
|
| 62 |
+
GAIA 评分是严格的 exact-match。如果经历了复杂的多步推理,仅仅因为提取��答案多了一个空格、或者大小写不匹配而丢分,是非常不划算的。在进行任何复杂的架构改动前,提升答案 Normalizer 的保真度(fidelity)是最便宜的"免费加分项"。
|
| 63 |
|
| 64 |
+
1. 审计并强化 Supervisor 的 `best_answer` 提取逻辑。
|
| 65 |
+
2. 确保对比与最终提取时,正确处理空白字符、大小写归一化及标点符号过滤。
|
| 66 |
|
| 67 |
+
---
|
| 68 |
|
| 69 |
+
## P3:Supervisor 升级与安全拦截 (Guard)
|
| 70 |
|
| 71 |
+
**路线:A | 预估 GAIA 提升:+1-2%**
|
|
|
|
| 72 |
|
| 73 |
+
### 问题
|
| 74 |
|
| 75 |
+
当前 supervisor 用的是 cheap model,判断质量有限。特别是在 Level 2/3 题上,cheap model 可能无法准确评估 agent 是否已经收集到足够的证据。此外,它可能会错误地抽取出诸如 "unknown", "N/A" 的 placeholder,导致提前放弃任务。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
+
### 实现思路
|
| 78 |
+
|
| 79 |
+
在 `src/lilith_agent/app.py` 的 `build_react_agent()` 中:
|
| 80 |
+
|
| 81 |
+
1. **模型升级**:将 `supervisor_model = get_cheap_model(cfg)` 改为 `supervisor_model = get_extra_strong_model(cfg)` 或新增一个 `get_strong_model(cfg)` 中间档。
|
| 82 |
+
2. **安全拦截 (Placeholder Guard)**:增加护栏(Guard)逻辑,如果 Supervisor 提取出 "unknown/n/a" 等无意义的 placeholder,强制拒绝结束任务,要求 agent 继续探索。
|
| 83 |
+
3. **阈值调整**:由于 strong model 更贵,提高 supervisor 触发阈值:`_SUPERVISOR_MIN_TOOL_CALLS` 从 5 提到 8。
|
| 84 |
+
4. 同时给 supervisor prompt 加入更明确的评判标准,比如:
|
| 85 |
+
- "如果 agent 已经找到了一个具体的数字/名字/日期,且该答案与已收集的证据一致,则 status=finalize"
|
| 86 |
+
- "如果 agent 在最近 3 次 tool call 中没有获得新信息,则 status=finalize"
|
| 87 |
|
| 88 |
### 涉及文件
|
| 89 |
|
| 90 |
+
- `src/lilith_agent/app.py`:`build_react_agent()` 中的 supervisor 初始化与 guard 逻辑
|
| 91 |
+
- `src/lilith_agent/config.py`:新增 `supervisor_model_tier` 配置
|
| 92 |
|
| 93 |
---
|
| 94 |
|
| 95 |
+
## P4:fetch_url 结果二次清洗
|
| 96 |
|
| 97 |
+
**路线:A | 预估 GAIA 提升:+0.5-1%**
|
| 98 |
|
| 99 |
### 问题
|
| 100 |
|
| 101 |
+
`fetch_url` 提取正文后截断到 `max_chars=8000`。但网页输出经常残留导航栏、cookie 提示、重复 header 等噪音。同样 8000 字符,噪音越少有效信息密度越高。当前逻辑可能只处理了 trafilatura fallback,遗漏了 Jina Reader 主路径。
|
|
|
|
|
|
|
| 102 |
|
| 103 |
### 实现思路
|
| 104 |
|
| 105 |
+
在 `src/lilith_agent/tools/web.py` 的 `fetch_url` 函数中,对 Jina Reader 和 trafilatura 提取的结果,在截断之前,加一步���量清洗。
|
| 106 |
+
|
| 107 |
+
**Noise patterns 外置成 JSON 配置文件**(不使用 YAML,避免引入新依赖):
|
| 108 |
+
|
| 109 |
+
```json
|
| 110 |
+
{
|
| 111 |
+
"en": [
|
| 112 |
+
"cookie",
|
| 113 |
+
"privacy policy",
|
| 114 |
+
"terms of service",
|
| 115 |
+
"subscribe",
|
| 116 |
+
"newsletter",
|
| 117 |
+
"follow us",
|
| 118 |
+
"share on",
|
| 119 |
+
"tweet this",
|
| 120 |
+
"skip to content",
|
| 121 |
+
"advertisement",
|
| 122 |
+
"sponsored"
|
| 123 |
+
],
|
| 124 |
+
"zh": [
|
| 125 |
+
"隐私政策",
|
| 126 |
+
"使用条款",
|
| 127 |
+
"订阅",
|
| 128 |
+
"关注我们",
|
| 129 |
+
"分享到",
|
| 130 |
+
"跳转到主内容",
|
| 131 |
+
"广告"
|
| 132 |
+
]
|
| 133 |
+
}
|
| 134 |
+
```
|
| 135 |
|
| 136 |
+
清洗函数从 JSON 配置文件读取 patterns 进行清洗。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
### 涉及文件
|
| 139 |
|
| 140 |
+
- `src/lilith_agent/tools/web.py`:`fetch_url()` / `_fetch_url()`
|
| 141 |
+
- 新增:`src/lilith_agent/config/noise_patterns.json`(噪音模式配置)
|
|
|
|
|
|
|
|
|
|
| 142 |
|
| 143 |
+
> **Review note:** `src/lilith_agent/config.py` 目前是模块文件,`pyproject.toml` 也没有 package-data 配置;如果把 JSON 放到 `src/lilith_agent/config/noise_patterns.json`,打包后可能无法被可靠读取。优先考虑放到明确的 packaged data 路径,或同步补充 setuptools package-data 配置与读取测试。
|
|
|
|
|
|
|
| 144 |
|
| 145 |
---
|
| 146 |
|
| 147 |
+
## P5:动态 Budget 管理
|
| 148 |
|
| 149 |
+
**路线:A | 预估 GAIA 提升:+0.5-1%**
|
| 150 |
|
| 151 |
### 问题
|
| 152 |
|
| 153 |
+
当前 `budget_hard_cap=25` 和 `budget_warn_at=15` 是全局配置(固定值),不区分题目难度。Level 1 题通常 3-5 步就能回答,而 Level 3 可能需要 30+ 步。由于 graph 编译是一次性的,无法在 runtime 随意修改 cfg。
|
| 154 |
|
| 155 |
+
### 实现思路
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
+
放弃修改 cfg,直接在 `AgentState` 中新增 field 来管理。放弃调用模型来猜测难度。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
+
1. **直接使用 Level 标签**:在任务开始时,直接读取 GAIA 数据集自带的 Level 标签。
|
| 160 |
+
2. **状态驱动的 Budget**:在 `AgentState` 内维护 `current_budget_warn` 和 `current_budget_cap`。
|
| 161 |
+
- Level 1:warn=8, cap=12
|
| 162 |
+
- Level 2:warn=15, cap=25
|
| 163 |
+
- Level 3:warn=25, cap=40(配合更积极的压缩)
|
| 164 |
|
| 165 |
+
> **Review note:** 需要一个统一的 state-derived budget helper 同时驱动 `model_node()` 的 warning prompt、`_route_after_model()` 的 hard cap,以及 graph compile 时的 recursion sizing;只在 `AgentState` 加字段会留下 cfg 默认值继续生效的路径。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
### 涉及文件
|
| 168 |
|
| 169 |
+
- `src/lilith_agent/app.py`:`AgentState` 定义,路由逻辑 `_route_after_model()`
|
| 170 |
+
- `src/lilith_agent/runner.py`:传递 level 标签到状态中
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
---
|
| 173 |
|
| 174 |
+
## P0:状态级里程碑感知压缩(State-Level Milestone)
|
| 175 |
|
| 176 |
+
**路线:A + B | 预估 GAIA 提升:+2-4%**
|
| 177 |
|
| 178 |
### 问题
|
| 179 |
|
| 180 |
+
当前 `_compact_old_tool_messages()` 按位置压缩,这是"时间盲"的,会丢失关键发现。如果直接往消息流强行插入 `SystemMessage` 来标记里程碑,会破坏 `AIMessage(tool_calls)` 与 `ToolMessage` 必须相邻的 LLM 厂商协议,极易触发 API 400 报错。
|
| 181 |
|
| 182 |
### 实现思路
|
| 183 |
|
| 184 |
+
在 `src/lilith_agent/app.py` 中改造,**绝不直接向消息流插入标记**,而是维护一个独立的事实账本。
|
| 185 |
|
| 186 |
+
1. **State-Level Ledger**:在 `AgentState` 中新增一个独立的 `facts_ledger` 列表。
|
| 187 |
+
2. **复用压缩器检测以控制成本**:为了节省 extra cheap model 调用,不在每次 AIMessage 产出时检测。将里程碑检测逻辑合并到已有的 compaction summarizer 流程中,或者当 `tool_calls >= 6` 时才触发检测。提炼出的关键事实追加到 `facts_ledger` 中。
|
| 188 |
+
3. **注入上下文**:在生成 prompt 时,将 `facts_ledger` 作为整体系统上下文注入到前端,保证早期的关键发现不会被后续的时间盲压缩丢失。
|
| 189 |
+
> **Review note:** `facts_ledger` 的来源是 tool/web 输出,属于 untrusted evidence,不应被提升成高优先级指令。实现时要用明确的 evidence wrapper、保留来源/provenance,并增加恶意网页内容不能注入系统指令的测试。
|
| 190 |
+
4. **可选:接入 Anthropic Compaction API** 替代自研总结逻辑。
|
| 191 |
|
| 192 |
### 涉及文件
|
| 193 |
|
| 194 |
+
- `src/lilith_agent/app.py`:`AgentState` 定义、`_compact_old_tool_messages()` 改造
|
|
|
|
| 195 |
|
| 196 |
---
|
| 197 |
|
| 198 |
+
## P2:经验反思学习(ERL)
|
| 199 |
|
| 200 |
+
**路线:A | 预估 GAIA 提升:+5-8%**
|
| 201 |
|
| 202 |
### 问题
|
| 203 |
|
| 204 |
+
Lilith 当前的 `ephemeral_memory` 会在任务结束后被完全清空,无法跨任务继承经验,导致无法实现"从失败中学习"。ERL(arxiv 2603.24639)在 GAIA2 上比 baseline 提高了 7.8%,且完全在 prompt-time 运行。
|
| 205 |
|
| 206 |
+
### 实现思路(分两步)
|
| 207 |
|
| 208 |
+
**Step 1:Golden Heuristics 验证上限(1-2 天)**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
|
| 210 |
+
1. 人工挑选 20-30 条高质量 heuristics(分析 `.last_failures.txt` 失败轨迹提取),写入 JSON 格式的种子文件。
|
| 211 |
+
2. 直接注入 system prompt,跑一轮 stratified golden eval,验证 ERL 在当前架构下的理论上限。若提升 < 2%,需重新审视。
|
| 212 |
+
|
| 213 |
+
**Step 2:自动化反思管线与独立持久化**
|
| 214 |
+
|
| 215 |
+
1. **独立持久化 DB**:新增 `src/lilith_agent/heuristics.py`,建立独立的 SQLite 表(不与 ephemeral memory 混用),记录 rule、成功率等统计数据。
|
| 216 |
+
```sql
|
| 217 |
+
CREATE TABLE heuristics (
|
| 218 |
+
id TEXT PRIMARY KEY,
|
| 219 |
+
rule TEXT NOT NULL,
|
| 220 |
+
source_task_id TEXT,
|
| 221 |
+
success BOOLEAN,
|
| 222 |
+
keywords TEXT,
|
| 223 |
+
times_applied INTEGER DEFAULT 0,
|
| 224 |
+
times_helped INTEGER DEFAULT 0,
|
| 225 |
+
times_hurt INTEGER DEFAULT 0,
|
| 226 |
+
confidence REAL DEFAULT 0.5,
|
| 227 |
+
created_at TEXT,
|
| 228 |
+
retired_at TEXT
|
| 229 |
+
);
|
| 230 |
+
```
|
| 231 |
+
2. **任务后反思**:`run_agent_on_questions` 结束后,不管成功失败,调用 cheap model 分析轨迹,生成规则并存入。
|
| 232 |
+
> **Review note:** `run_agent_on_questions()` 当前没有 ground-truth success signal;validation/golden 以外的 leaderboard/test split 任务不能可靠判断 `success`、`times_helped`、`times_hurt`。自动学习应限制在有 expected answer / 显式 scoring 结果的 run,或把 unlabeled run 只作为候选规则来源而不更新置信度。
|
| 233 |
+
3. **规则检索与自动淘汰**:每次任务记录 applied heuristic IDs;当 `confidence < 0.3` 且 `times_applied >= 5` 时,自动 retire。必须在起步阶段就做好淘汰机制,防止低质量规则污染 prompt。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
|
| 235 |
### 涉及文件
|
| 236 |
|
| 237 |
+
- 新增:`src/lilith_agent/heuristics.py`(独立持久化存储)
|
| 238 |
+
- `src/lilith_agent/runner.py`:任务后反思调用与 heuristic 效果追踪
|
| 239 |
+
- `src/lilith_agent/app.py`:`model_node()` 中的规则检索与注入
|
| 240 |
+
- 新增:`scripts/heuristic_health_report.py`(规则健康报告)
|
| 241 |
|
| 242 |
---
|
| 243 |
|
| 244 |
+
## P1:Sub-Agent 架构
|
| 245 |
|
| 246 |
+
**路线:A(Level 3 题)+ B | 预估 GAIA 提升:+2-3%**
|
| 247 |
|
| 248 |
### 问题
|
| 249 |
|
| 250 |
+
单 agent 在几十步的 Level 3 题中极易"lost in the middle"。引入独立 context 的子代理可以缓解。但当前工具注册机制(如 `build_tools`)较为 monolithic,直接引入会导致循环依赖;同时,所有任务共享同一线程 state 会导致严重污染。
|
| 251 |
|
| 252 |
### 实现思路
|
| 253 |
|
| 254 |
+
必须先解决工程底座问题,才能安全引入 `spawn_sub_agent`。
|
| 255 |
+
|
| 256 |
+
1. **前置重构:工具与 Agent 解耦**:重构 `build_react_agent()` 和 `build_tools()` 的绑定关系。工具构建必须支持按需裁剪(如 `build_tools(cfg, allowed_names)`),解决循环依赖。
|
| 257 |
+
2. **Checkpointer 隔离**:子 Agent **绝不能**使用主线程的同一个 SQLite checkpointer。必须为子任务分配独立的 `in-memory checkpointer`,或唯一的 `child thread ID`,或设为无持久化状态,确保上下文纯净。
|
| 258 |
+
3. **硬限制保护**:
|
| 259 |
+
- 最大深度:`depth=1`,防止递归爆炸。
|
| 260 |
+
- 操作限制:子代理禁止调用 `write_file`,除非明确分配。
|
| 261 |
+
- 独立的 budget 和 timeout。
|
| 262 |
+
4. **精简的子工具集与动态摘要**:子 agent 根据任务类型(research, compute, vision)拿到裁剪后的纯净工具集。返回摘要时按任务类型动态限制长度(research ≤ 3000 chars, compute ≤ 500 chars),汇总回主代理。
|
| 263 |
|
| 264 |
### 涉及文件
|
| 265 |
|
| 266 |
+
- `src/lilith_agent/app.py`:解耦并重构工具组装、注册新工具
|
| 267 |
+
- 新增:`src/lilith_agent/tools/sub_agent.py`(包含工具集裁剪逻辑)
|
| 268 |
+
- `src/lilith_agent/config.py`:新增子代理配置
|
| 269 |
|
| 270 |
---
|
| 271 |
|
| 272 |
## 实施顺序建议
|
| 273 |
|
| 274 |
```
|
| 275 |
+
Phase 0 & 0.5(基础设施与提分低垂果实,2-3 天)
|
| 276 |
+
├── 修复所有 Blockers (状态泄露, CLI bug)
|
| 277 |
+
├── 剥离 Checkpoint Metadata,跑 Baseline
|
| 278 |
+
└── 强化 Normalizer 和 best_answer 提取逻辑
|
|
|
|
| 279 |
|
| 280 |
Phase 1(快速见效,1-2 周)
|
| 281 |
+
├── P3:强模型 Supervisor + Placeholder Guard
|
| 282 |
+
├── P4:fetch_url 清洗(覆盖 Jina 主路径,JSON 配置)
|
| 283 |
+
├── P5:基于 Level 的 AgentState Budget 控制
|
| 284 |
+
└── ⚡ 跑完整 GAIA eval,对比 baseline
|
| 285 |
+
|
| 286 |
+
Phase 2(状态记忆与反思,2-4 周)
|
| 287 |
+
├── P0:State-level 里程碑事实提炼(复用 Summarizer 控制成本)
|
| 288 |
+
├── P2 Step 1:建立独立持久化 DB,JSON 注入验证 Golden ERL 上限
|
| 289 |
+
├── P2 Step 2:自动化任务后反思与淘汰管线
|
|
|
|
| 290 |
└── ⚡ 跑完整 GAIA eval,对比 Phase 1
|
| 291 |
|
| 292 |
+
Phase 3(高���架构,3-5 周)
|
| 293 |
+
├── P1 前置:重构 Tool Registry,解耦循环依赖
|
| 294 |
+
├── P1 核心:Checkpointer 隔离与 Sub-agent 实现
|
| 295 |
+
└── ⚡ 跑完整 GAIA eval,验收最终成果
|
| 296 |
```
|
| 297 |
|
| 298 |
+
**关键原则**:每个 Phase 结束时必须跑评估。如果改动导致 golden_set 回归,立即 revert 并分析。
|
|
|
|
|
|
|
| 299 |
|
| 300 |
---
|
| 301 |
|