From ff7e1bc8de0c10791b1d58750e4b87236ef4f3d8 Mon Sep 17 00:00:00 2001 From: tzt <14718231+flying-travel@user.noreply.gitee.com> Date: Sun, 30 Aug 2026 21:16:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(v2):=20T10=20rollup=20+=20prefix=20cache?= =?UTF-8?q?=20=E5=89=8D=E7=BC=80=E7=A8=B3=E5=AE=9A=E6=80=A7=EF=BC=88--cach?= =?UTF-8?q?e-reuse=20=E5=AF=B9=E9=BD=90=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router_system/workspace.py | 17 +++++++++ tests/test_prefix_cache.py | 72 ++++++++++++++++++++++++++++++++++++++ 任务拆解与执行计划.md | 2 +- 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 tests/test_prefix_cache.py diff --git a/router_system/workspace.py b/router_system/workspace.py index 9fea750..6514324 100644 --- a/router_system/workspace.py +++ b/router_system/workspace.py @@ -501,6 +501,23 @@ class Workspace: data = json.load(f) return cls(data) + def prefix_signature(self) -> str: + """返回稳定前缀的签名(T10 prefix cache)。 + + 交流文本的"恒定位于前部"的部分(version + request_id + query + meta + brief) + 应不随 progress/issues/decisions 追加而变化,从而使 llama-server 的 + --cache-reuse 能命中该前缀、降低 prefill 开销。用紧凑 JSON 的哈希度量稳定性。 + """ + stable = { + "version": self._data.get("version"), + "request_id": self._data.get("request_id"), + "query": self._data.get("query"), + "brief": self._data.get("brief"), + } + import hashlib + s = json.dumps(stable, ensure_ascii=False, sort_keys=True) + return hashlib.sha256(s.encode("utf-8")).hexdigest()[:16] + def to_dict(self) -> Dict[str, Any]: return self.data diff --git a/tests/test_prefix_cache.py b/tests/test_prefix_cache.py new file mode 100644 index 0000000..1b7d35f --- /dev/null +++ b/tests/test_prefix_cache.py @@ -0,0 +1,72 @@ +"""T10 rollup + prefix cache 前缀稳定性测试。 + +验证交流文本的"恒定前缀"(version/request_id/query/meta/brief)在写入 +progress/issues/decisions 后保持不变 —— 这是 llama-server --cache-reuse +命中、降低 prefill 开销的前提(D2 / 6.2 / T10)。 +""" +import json + +from router_system.workspace import Workspace + +BRIEF = { + "goal": "实现快排", + "constraints": ["标准库"], + "tags": ["code"], + "acceptance": [{"id": "a1", "check": "可运行", "machine_checkable": True}], + "plan": [{"id": "s1", "task": "实现", "deps": [], "done_criteria": "可运行"}], +} + + +def _ws(): + ws = Workspace.new("abc123def456", "写个快排") + ws.apply_brief(BRIEF) + return ws + + +def test_prefix_stable_across_writes(): + ws = _ws() + sig0 = ws.prefix_signature() + ws.add_progress("s1", "done", "完成", "a://s1.py") + ws.add_issue("s1", "a://f.py#L1", "obs", "exp", "try", "ask") + ws.add_decision("i1", "reply") + ws.mark_round() + ws.add_budget(input_tokens=100, output_tokens=20) + assert ws.prefix_signature() == sig0 # 前缀不随写操作变化 + + +def test_prefix_changes_with_brief(): + ws = _ws() + sig = ws.prefix_signature() + ws2 = Workspace.new("abc123def456", "写个快排") + ws2.apply_brief({**BRIEF, "goal": "不同的目标"}) + assert ws2.prefix_signature() != sig + + +def test_prefix_changes_with_query(): + ws = _ws() + sig = ws.prefix_signature() + ws2 = Workspace.new("abc123def456", "另一个问题") + ws2.apply_brief(BRIEF) + assert ws2.prefix_signature() != sig + + +def test_rollup_keeps_prefix_stable(): + ws = _ws() + ws.add_progress("s1", "done", "ok", "a://s1.py") + sig_before = ws.prefix_signature() + ws.rollup() + assert ws.prefix_signature() == sig_before + + +def test_serialized_leading_is_stable(): + ws = _ws() + head_before = _leading_json(ws) + ws.add_progress("s1", "done", "ok", "a://s1.py") + ws.add_issue("s1", "a://f.py#L1", "obs", "exp", "try", "ask") + assert _leading_json(ws) == head_before + + +def _leading_json(ws: Workspace) -> str: + d = ws.data + stable = {k: d.get(k) for k in ("version", "request_id", "query", "meta", "brief")} + return json.dumps(stable, ensure_ascii=False, sort_keys=True) diff --git a/任务拆解与执行计划.md b/任务拆解与执行计划.md index cc497cb..8b01f73 100644 --- a/任务拆解与执行计划.md +++ b/任务拆解与执行计划.md @@ -76,7 +76,7 @@ P0 完成后的能力:干净的后端抽象 + 可量化的评测 + 可追溯 | T7 | 网关扩展(/chat 切 v2,/chat/legacy) | ✅ 完成 | T7 | | T8 | 人工检验队列 ReviewQueue | ✅ 完成 | T8 | | T9 | token 计量与账单 | ✅ 完成 | T9 | -| T10 | rollup + prefix cache 调优 | ⬜ | | +| T10 | rollup + prefix cache 调优 | ✅ 完成 | T10 | | T11 | 打包分发 setup_runtime.py | ⬜ | | | T12 | 实验脚本 bench_tokens.py + 数据集 | ⬜ | | | T13 | E1–E5 跑数到 research/v2_experiments/ | ⬜ | |