- Workspace.render_for_architect:超 1200 token 时对 archive 行按与 query+goal 的字符 2-gram Dice 相似度分档——sim<0.25 先丢、sim<0.55 截断为 40% 摘要、 仍超限从低到高继续丢;保留行维持原插入序(前缀稳定),最近 4 行下限不变 (相比旧'从最旧整段丢',高相关事实在预算内留存更久) - 顺带消除两项旧债:压缩态与首次渲染共用同一 parts 结构(格式漂移)、 裁剪循环不再每轮 deepcopy 全文档 - 修复本轮引入的缺陷:会话轮次 tool_calls 为 int 计数时清单提取迭代崩溃 (test_session_multi_turn 抓出,已加类型防御) - 新增 tests/test_pinch_trim.py 4 项;全量 244 passed ×2(基线 230)
61 lines
2.7 KiB
Python
61 lines
2.7 KiB
Python
"""Architect 渲染三档裁剪(T-M3,采纳 llmrouter pinch keep/summarize/drop 设计)。"""
|
||
from router_system.workspace import Workspace
|
||
|
||
_GOAL = "用 Python 实现快速排序并分析时间复杂度"
|
||
|
||
_BRIEF = {
|
||
"goal": _GOAL, "constraints": ["标准库"], "tags": ["code"],
|
||
"acceptance": [{"id": "a1", "check": "可运行", "machine_checkable": True}],
|
||
"plan": [{"id": "s1", "task": "实现", "deps": [], "done_criteria": "过"}],
|
||
}
|
||
|
||
|
||
def _ws_with_archive():
|
||
ws = Workspace.new(request_id="abc123def456", query=_GOAL,
|
||
api_token_cap=8000, rounds_cap=6)
|
||
ws.apply_brief(_BRIEF)
|
||
relevant = ("s1: 完成快速排序实现,基准选取三数取中,递归深度优化,"
|
||
"平均时间复杂度 O(n log n) 分析见附件。" + "快排边界处理细节" * 50)
|
||
lines = [f"sX{i}: 无关行{i},今日食堂菜单有红烧肉、番茄炒蛋与清炒时蔬,"
|
||
f"周末计划去郊外徒步露营并整理旅行照片。" + "生活琐事记录" * 50
|
||
+ f"独特结尾标记{i}号" # 唯一尾串:判断"该行是否还被输出"
|
||
for i in range(7)]
|
||
# 相关行放在中间:不在最新 4 行下限保护区内,检验相关性而非新近度
|
||
ws._data["archive"] = lines[:3] + [relevant] + lines[3:]
|
||
return ws, relevant, lines
|
||
|
||
|
||
def test_trim_keeps_relevant_line_full():
|
||
"""高相关行全文保留,低相关行被丢弃/截断(尾段不再出现在输出)。"""
|
||
ws, relevant, lines = _ws_with_archive()
|
||
out = ws.render_for_architect()
|
||
# 相关行全文(含尾段独特内容)仍在
|
||
assert relevant[-40:] in out
|
||
# 至少一条低相关行的尾段消失(被丢或被截为摘要)
|
||
assert lines[0][-40:] not in out
|
||
|
||
|
||
def test_trim_respects_floor_of_four_lines():
|
||
"""任何情况下至少保留 4 行(与旧实现下限一致)。"""
|
||
ws, _, lines = _ws_with_archive()
|
||
out = ws.render_for_architect()
|
||
archive_shown = out.split("== archive ==")[1].strip().splitlines()
|
||
assert len(archive_shown) >= 4
|
||
|
||
|
||
def test_render_deterministic():
|
||
"""同输入两次渲染逐字节一致(裁剪决策确定性)。"""
|
||
ws1, _, _ = _ws_with_archive()
|
||
ws2, _, _ = _ws_with_archive()
|
||
assert ws1.render_for_architect() == ws2.render_for_architect()
|
||
|
||
|
||
def test_under_budget_untouched():
|
||
"""预算内不触发裁剪:archive 行原样出现、无截断省略号。"""
|
||
ws = Workspace.new(request_id="abc123def456", query="写个快排",
|
||
api_token_cap=8000, rounds_cap=6)
|
||
ws.apply_brief(_BRIEF)
|
||
ws._data["archive"] = ["s1: 完成(产出: a://s1.py)"]
|
||
out = ws.render_for_architect()
|
||
assert "s1: 完成(产出: a://s1.py)" in out
|