修复: 子代理上下文预算恒128K不随模型窗口
子代理预算改继承父会话(同模型同窗口单一事实来源), 939-③ 收口; 939-⑪⑫ 核实已由前批落地, 看板销账更新
This commit is contained in:
+2
-2
@@ -703,9 +703,9 @@
|
|||||||
939. [ ] **上下文管理瓶颈清单(2026-10-10 五维只读走查,源码取证)** — 按收益排序,⚠️ `crates/df-ai/**` 被并行写者占用(工具结果外置 WIP)→ 带 ★ 的可先在 src-tauri 侧落,其余待解禁:
|
939. [ ] **上下文管理瓶颈清单(2026-10-10 五维只读走查,源码取证)** — 按收益排序,⚠️ `crates/df-ai/**` 被并行写者占用(工具结果外置 WIP)→ 带 ★ 的可先在 src-tauri 侧落,其余待解禁:
|
||||||
- **HIGH ①** `history_tokens` 与真实请求体量**脱钩**:工具结果经 namespace 引用化入内存(`audit/mod.rs:1183-1190` + `namespace_store.rs:40-55` ALWAYS_LARGE_TOOLS 命中即引用,与体积无关),估算器只数字符(`context_helpers.rs:62-105`)→ 单条上万 token 的大结果只记 ~15 token;**预算/裁剪门(`context/mod.rs:185-205`)/压缩门(`context_lifecycle.rs:103-108`)三重门槛形同虚设**,每轮实际重发展开后的全量历史(223:1 结构浪费根因)。修:push/外置时按原文体量入账,或估算器识别 ref 取真实大小。
|
- **HIGH ①** `history_tokens` 与真实请求体量**脱钩**:工具结果经 namespace 引用化入内存(`audit/mod.rs:1183-1190` + `namespace_store.rs:40-55` ALWAYS_LARGE_TOOLS 命中即引用,与体积无关),估算器只数字符(`context_helpers.rs:62-105`)→ 单条上万 token 的大结果只记 ~15 token;**预算/裁剪门(`context/mod.rs:185-205`)/压缩门(`context_lifecycle.rs:103-108`)三重门槛形同虚设**,每轮实际重发展开后的全量历史(223:1 结构浪费根因)。修:push/外置时按原文体量入账,或估算器识别 ref 取真实大小。
|
||||||
- **HIGH ②** 每轮 O(n) 全量深克隆 + sanitize + namespace 展开 + 摘要 + 估算(`context/mod.rs:198-205` / `agentic/mod.rs:1904-1921`,`1945-1957`,`1981-1984`)→ 会话内 O(n²) 累积(全量重发本体);治本=设计档 P2 分层组装。
|
- **HIGH ②** 每轮 O(n) 全量深克隆 + sanitize + namespace 展开 + 摘要 + 估算(`context/mod.rs:198-205` / `agentic/mod.rs:1904-1921`,`1945-1957`,`1981-1984`)→ 会话内 O(n²) 累积(全量重发本体);治本=设计档 P2 分层组装。
|
||||||
- **★HIGH ③** 预算上限**恒 128K**不随模型窗口(`commands/ai/mod.rs:1239` `ContextManager::new(ContextConfig::default())`;`context_helpers.rs:131/140-142`;子代理同 `sub_agent.rs:117-127`)→ 1M 窗口模型被当 128K 裁(能力降级),小窗口模型预算高于实际窗口。修:`ContextConfig` 字段 pub,可在 src-tauri 侧按 resolved_model 窗口构造(无需改 df-ai)。
|
- **★HIGH ③ ✅ 已修(两批)**:主会话=model_context.rs 按 resolved_model 窗口构造(b37279f,未知窗口保守回退 128K 零回归);子代理=sub_agent_context_config 继承父会话预算(10-11,同模型同窗口单一事实来源,恒 128K 缺口收口)。
|
||||||
- **HIGH ④(压缩)** 压缩**单向不可逆**:被压原文对 LLM 永久不可见(`context/mod.rs:664-699` 标 Compressed + `sanitize.rs:42` is_active 过滤出局),设计 C-r1「压缩不丢/可召回」未落地 → 方向:复用 P1 句柄模式,压缩写 pointer 可回读。
|
- **HIGH ④(压缩)** 压缩**单向不可逆**:被压原文对 LLM 永久不可见(`context/mod.rs:664-699` 标 Compressed + `sanitize.rs:42` is_active 过滤出局),设计 C-r1「压缩不丢/可召回」未落地 → 方向:复用 P1 句柄模式,压缩写 pointer 可回读。
|
||||||
- MED ⑤ `chars_ratio=0.35` 中文低估 2-3 倍、base64 高估(`context_helpers.rs:29-44/73-74`);⑥ 保护区固定 6 条 + 补偿仅 300 字(`:648/:655`);⑦ 分层组装 P2 未落地(窗口外历史无检索召回);⑧ **★** system 可变段(日期+项目/任务清单)内嵌稳定段致**前缀缓存失效**(`prompt.rs:611-635` 缓存拆分开关默认关;清单描述不截断 `:565/:584`);⑨ 滑动裁剪致前缀缓存整体失配(`context/mod.rs:239-246`);⑩ 一次压尽(windows 式分批未做);⑪ **后台压缩无 epoch/内容版本守卫**——`clear()` 保留 per_conv 条目且复位 is_compressing → 窗口内旧摘要可注入已清空的新上下文(`context_lifecycle.rs:206-323`,loop 侧有 F1 epoch,此 task 侧无);⑫ 后台压缩**无 panic 兜底** → is_compressing 永真致压缩永久停摆。
|
- MED ⑤ `chars_ratio=0.35` 中文低估 2-3 倍、base64 高估(`context_helpers.rs:29-44/73-74`);⑥ 保护区固定 6 条 + 补偿仅 300 字(`:648/:655`);⑦ 分层组装 P2 未落地(窗口外历史无检索召回);⑧ **★** system 可变段(日期+项目/任务清单)内嵌稳定段致**前缀缓存失效**(`prompt.rs:611-635` 缓存拆分开关默认关;清单描述不截断 `:565/:584`);⑨ 滑动裁剪致前缀缓存整体失配(`context/mod.rs:239-246`);⑩ 一次压尽(windows 式分批未做);⑪ ✅ 已修(内容版本守卫,context_lifecycle 提交前比对快照);⑫ ✅ 已修(reset_compressing_after_panic)。
|
||||||
- LOW ⑬ 估值双轨(estimated_prompt 准确用于路由 vs history_tokens 失真用于预算)从不互相校准;⑭ sys_tokens 未计工具 schema。
|
- LOW ⑬ 估值双轨(estimated_prompt 准确用于路由 vs history_tokens 失真用于预算)从不互相校准;⑭ sys_tokens 未计工具 schema。
|
||||||
- **已核良好**:裁剪三元组原子性正确(`context/mod.rs:612-642`);909 两处修复(锚点避让/单锁复位)现状有效,未见旧窗口复现。
|
- **已核良好**:裁剪三元组原子性正确(`context/mod.rs:612-642`);909 两处修复(锚点避让/单锁复位)现状有效,未见旧窗口复现。
|
||||||
|
|
||||||
|
|||||||
@@ -113,16 +113,13 @@ pub(crate) const SUB_AGENT_WALL_TIMEOUT_SECS: u64 = 900;
|
|||||||
/// 自达统一出口。
|
/// 自达统一出口。
|
||||||
pub(crate) const SUB_AGENT_TOOL_BATCH_HEADROOM_SECS: u64 = 65;
|
pub(crate) const SUB_AGENT_TOOL_BATCH_HEADROOM_SECS: u64 = 65;
|
||||||
|
|
||||||
/// 子代理上下文窗口预算上限(token)。自动压缩触发阈值与 build_for_request 裁剪预算
|
/// 子代理会话的上下文配置(压缩/裁剪预算来源)。max_tokens **继承父会话预算**——
|
||||||
/// 的数据源,口径同 [`ContextConfig::max_tokens`]。默认 128_000 对齐 ContextConfig::default
|
/// 子代理与父同模型同窗口(939③ 收口:原恒 128K,1M 窗口模型被子代理裁半是同款缺口),
|
||||||
/// ——接入压缩层不改动既有预算(零行为变更);值单点集中于此,后续按需分档只改本常量。
|
/// 父侧已按 model_context 按窗口构造,直接取单一事实来源,子侧不再自持口径。
|
||||||
const SUB_AGENT_CONTEXT_MAX_TOKENS: u32 = 128_000;
|
|
||||||
|
|
||||||
/// 子代理会话的上下文配置(压缩/裁剪预算来源)。仅覆写 max_tokens 为子代理常量,
|
|
||||||
/// 输出预留与安全系数沿用 ContextConfig::default,与主会话同一压缩链路口径一致。
|
/// 输出预留与安全系数沿用 ContextConfig::default,与主会话同一压缩链路口径一致。
|
||||||
fn sub_agent_context_config() -> ContextConfig {
|
fn sub_agent_context_config(parent_max_tokens: u32) -> ContextConfig {
|
||||||
ContextConfig {
|
ContextConfig {
|
||||||
max_tokens: SUB_AGENT_CONTEXT_MAX_TOKENS,
|
max_tokens: parent_max_tokens,
|
||||||
..ContextConfig::default()
|
..ContextConfig::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -755,10 +752,16 @@ async fn run_sub_agent_loop_inner(
|
|||||||
// 先于 conv() 调用(insert 需可变借 session,避免与 conv 借用冲突)
|
// 先于 conv() 调用(insert 需可变借 session,避免与 conv 借用冲突)
|
||||||
session.deleted_convs.insert(child_conv_id.clone());
|
session.deleted_convs.insert(child_conv_id.clone());
|
||||||
session.conv_origins.insert(child_conv_id.clone(), SUB_AGENT_ORIGIN.to_string());
|
session.conv_origins.insert(child_conv_id.clone(), SUB_AGENT_ORIGIN.to_string());
|
||||||
|
// 父预算先取(可变借用 conv 之前):子代理与父同模型,窗口预算单一事实来源在父侧
|
||||||
|
let parent_max_tokens = session
|
||||||
|
.conv(&parent_conv_id)
|
||||||
|
.messages
|
||||||
|
.config()
|
||||||
|
.max_tokens;
|
||||||
let conv = session.conv(&child_conv_id);
|
let conv = session.conv(&child_conv_id);
|
||||||
// 上下文预算单点接入:子会话 ContextManager 用子代理配置(默认值与父会话一致),
|
// 上下文预算单点接入:子会话 ContextManager 继承父预算(939③ 子代理半边),
|
||||||
// 供压缩触发阈值与 build_for_request 裁剪读取;新条目消息为空,直接替换无损。
|
// 供压缩触发阈值与 build_for_request 裁剪读取;新条目消息为空,直接替换无损。
|
||||||
conv.messages = ContextManager::new(sub_agent_context_config());
|
conv.messages = ContextManager::new(sub_agent_context_config(parent_max_tokens));
|
||||||
conv.messages.push(ChatMessage::user(&task_prompt));
|
conv.messages.push(ChatMessage::user(&task_prompt));
|
||||||
conv.stop_flag.store(false, Ordering::SeqCst);
|
conv.stop_flag.store(false, Ordering::SeqCst);
|
||||||
conv.iteration_used = 0;
|
conv.iteration_used = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user