Commit c75bfc647ef38aca664e24918370f6fc1ec870e1

Authored by yibo
1 parent b095d3a7

perf: evolver token optimization + system prompt size guards

1. Evolver agent.md: Added token budget rules
   - No re-reading unchanged files between iterations
   - Use head/grep instead of cat for large files
   - Concise output only (scores + diff summary, no full SKILL.md)
   - Cap at 5 iterations per session (was 10)
   - Early stop if score change < 2 points for 2 consecutive rounds

2. agent-chat.js: System prompt size guards
   - MAX_PROMPT_FILE_SIZE = 15KB per file (auto-truncate with warning)
   - MAX_TOTAL_PROMPT_SIZE = 100KB total (safety net)
   - Prevents runaway files from inflating context ever again
server/routes/agent-chat.js
... ... @@ -228,8 +228,19 @@ domain: ${domain}
228 228 // Bootstrap 工具
229 229 // ═══════════════════════════════════════
230 230  
  231 +// 💰 Token 防护:单文件注入上限
  232 +const MAX_PROMPT_FILE_SIZE = 15 * 1024; // 15KB per file
  233 +const MAX_TOTAL_PROMPT_SIZE = 100 * 1024; // 100KB total system prompt
  234 +
231 235 function loadFile(agentDir, filename) {
232   - try { return fs.readFileSync(path.join(agentDir, filename), 'utf-8'); }
  236 + try {
  237 + const content = fs.readFileSync(path.join(agentDir, filename), 'utf-8');
  238 + if (content.length > MAX_PROMPT_FILE_SIZE) {
  239 + console.warn(`[TokenGuard] ⚠️ ${filename} 超过 ${MAX_PROMPT_FILE_SIZE/1024}KB (${(content.length/1024).toFixed(1)}KB),已截断`);
  240 + return content.substring(0, MAX_PROMPT_FILE_SIZE) + `\n\n... [⚠️ 文件过大已截断,原始 ${(content.length/1024).toFixed(1)}KB,请用 Read 工具按需读取完整内容]`;
  241 + }
  242 + return content;
  243 + }
233 244 catch { return ''; }
234 245 }
235 246  
... ... @@ -396,7 +407,15 @@ function buildSystemPrompt(agentDir, userMessage) {
396 407 }
397 408 }
398 409  
399   - return parts.join('\n\n---\n\n');
  410 + let result = parts.join('\n\n---\n\n');
  411 +
  412 + // 💰 Token 防护:总 system prompt 上限
  413 + if (result.length > MAX_TOTAL_PROMPT_SIZE) {
  414 + console.warn(`[TokenGuard] ⚠️ System prompt 超过 ${MAX_TOTAL_PROMPT_SIZE/1024}KB (${(result.length/1024).toFixed(1)}KB),已截断`);
  415 + result = result.substring(0, MAX_TOTAL_PROMPT_SIZE) + `\n\n... [⚠️ System prompt 过大已截断]`;
  416 + }
  417 +
  418 + return result;
400 419 }
401 420  
402 421 /**
... ...
system/agents/evolver/agent.md
... ... @@ -85,7 +85,29 @@
85 85 - 不要修改目标分数 — industry_avg 由 Digester 设定
86 86 - 超过 10 轮仍未达标 → 报告瓶颈, 等待 Innovator 决策
87 87  
  88 +## 💰 Token 预算规则(极其重要!)
  89 +
  90 +> 每轮迭代都会累积上下文,5 轮后 input 可达数百万 tokens。必须严格遵守以下规则:
  91 +
  92 +### 文件读取规则
  93 +- **首次读取** test.jsonl / train.jsonl / benchmark.md / knowhow.md 后,**后续迭代绝不重复读取**这些未变化的文件
  94 +- **SKILL.md** 是唯一需要每轮重新读取的文件(因为你在修改它)
  95 +- 读取 scorer.js 只在首次和修改后
  96 +- **禁止使用 `cat` 读取超过 5KB 的文件**,改用 `head -100` 或 `grep` 提取关键信息
  97 +
  98 +### 评分输出规则
  99 +- 每轮评分结果只输出**总分 + 弱维度名称**,不要输出每条 test case 的完整评分细节
  100 +- 评分详情写入 `iteration_N_scores.json` 文件,不要在对话中展开
  101 +
  102 +### 迭代效率规则
  103 +- 每轮修改 SKILL.md 后,只输出**修改了哪些维度的哪些规则**(diff 摘要),不要输出完整的新版 SKILL.md 内容
  104 +- evolving_log.md 只追加 1-2 行摘要,不要写长篇分析
  105 +- 如果连续 2 轮分数变化 < 2 分,立即报告瓶颈并停止,不要继续浪费迭代
  106 +
  107 +### 迭代上限
  108 +- **单次 session 最多执行 5 轮迭代**。如果 5 轮后仍未达标,报告当前最佳分数和瓶颈维度,等待 Innovator 决策是否重启新 session 继续
  109 +
88 110 ## ✅ 始终要做
89   -- 每轮迭代记录 evolving_log.md
  111 +- 每轮迭代记录 evolving_log.md(1-2 行摘要)
90 112 - 当 score ≥ industry_avg 时,报告完成
91 113 - 使用 report_task API 定期向 Innovator 汇报进度
... ...