diff --git a/.claude/skills/llm/scripts/llm.py b/.claude/skills/llm/scripts/llm.py index bd5a3c2..adb747c 100644 --- a/.claude/skills/llm/scripts/llm.py +++ b/.claude/skills/llm/scripts/llm.py @@ -144,8 +144,8 @@ def extract_json(text): # ══ 额度治理层(chat_governed)══ # WHY 上收:此前每个调用方各写一套模型降级链(parse_llm/parse_outline/review_cards 各一份, # 链名/顺序还不一致),既无法全局限预算、也无法跨进程共享"这一窗烧了多少/调了多少次"。 -# 统一到 chat_governed 后:一本共享账本按 5 小时窗计钱计次,MiniMax 超 $10/窗自动切非 MiniMax 链, -# 全窗调用达 4000 次自动睡到下一窗续跑——降级策略只此一处,调用方只管拿结果。 +# 统一到 chat_governed 后:一本共享账本按 5 小时窗计钱计次,MiniMax 超 $24/窗自动切非 MiniMax 链, +# 全窗调用达 6000 次自动睡到下一窗续跑——降级策略只此一处,调用方只管拿结果。 _PRICING_CACHE = None @@ -300,7 +300,7 @@ def chat_governed(prompt, model=DEFAULT_MODEL, system=None, max_tokens=512000, print(f"[llm] 治理链 {m} 失败({type(e).__name__}: {str(e)[:80]}),降级下一个", file=sys.stderr) continue - # 4) 成功记账:只有 MiniMax 计入 $10/窗 预算,其余模型成本计 0(只占调用数) + # 4) 成功记账:只有 MiniMax 计入 $24/窗 预算,其余模型成本计 0(只占调用数) add = cost_usd(m, usage) if m in MINIMAX_MODELS else 0.0 _bump_window(wk, add) # 全新短连接原子累加,写完即释放 return content, usage, m diff --git a/.claude/skills/llm/scripts/test_quota.py b/.claude/skills/llm/scripts/test_quota.py index c41df0b..0aa8025 100644 --- a/.claude/skills/llm/scripts/test_quota.py +++ b/.claude/skills/llm/scripts/test_quota.py @@ -3,7 +3,7 @@ 不碰真 DB、不发真请求、不做任何真实 LLM 调用。直接 `.venv/bin/python test_quota.py` 跑(无需 pytest)。 覆盖:window_key 归窗 / seconds_to_next_window 边界 / cost_usd 计价(含缓存折扣) / -chat_governed 六条路由(首选成功、预算耗尽切链、敏感换模型、不可用换模型、全链失败、达上限睡窗)。""" +chat_governed 六条路由(首选成功、$24 预算耗尽切链、敏感换模型、不可用换模型、全链失败、6000 次达上限睡窗)。""" import pathlib import sys import types @@ -78,6 +78,12 @@ def test_cost_usd(): assert abs(c2 - 0.000804) < 1e-9, f"M3 缓存折扣后成本应=0.000804,实得{c2}" +def test_current_quota_policy(): + """额度策略固定为每 5 小时 $24/6000,防止实现和测试再次漂移。""" + assert llm.WINDOW_BUDGET_USD == 24.0, "当前 MiniMax 每窗预算必须是 $24" + assert llm.WINDOW_CALL_CAP == 6000, "当前每窗总调用上限必须是 6000" + + def test_route_first_success(): """①usd=0/calls=0:链首 M3 成功 → 返回 MiniMax-M3、记账 usd>0、bump 一次到本窗。""" calls = [] @@ -94,13 +100,17 @@ def test_route_first_success(): def test_route_budget_exhausted(): - """②usd=10.5≥预算:链首变 glm-5.2(摘掉 MiniMax)、记账增量=0。""" + """②usd 超过 $24 预算:链首变 glm-5.2(摘掉 MiniMax)、记账增量=0。""" calls = [] def chat(prompt, model=None, **kw): calls.append(model) return "ok", dict(_USAGE) - bumps = _install(datetime(2026, 7, 16, 12, 0), {"2026-07-16T10": (10.5, 0)}, chat) + bumps = _install( + datetime(2026, 7, 16, 12, 0), + {"2026-07-16T10": (llm.WINDOW_BUDGET_USD + 0.5, 0)}, + chat, + ) content, usage, used = llm.chat_governed("p") assert calls[0] == "glm-5.2", f"预算耗尽后链首应为 glm-5.2,实得{calls[0]}" assert used == "glm-5.2", f"应由 glm-5.2 产出,实得{used}" @@ -153,14 +163,14 @@ def test_route_all_fail(): def test_route_call_cap_sleep(): - """⑥calls=4000 达上限 → sleep 桩被调一次、_now 推进到下一窗后 calls 归 0 续跑成功。""" + """⑥calls=6000 达上限 → sleep 桩被调一次、_now 推进到下一窗后 calls 归 0 续跑成功。""" clock = {"t": datetime(2026, 7, 16, 12, 0)} # 起始窗 T10(12:00) sleeps = [] def fake_sleep(secs): sleeps.append(secs) clock["t"] = clock["t"] + timedelta(seconds=secs) # 睡到下一窗边界(15:00) - reads = {"2026-07-16T10": (0.0, 4000), "2026-07-16T15": (0.0, 0)} + reads = {"2026-07-16T10": (0.0, llm.WINDOW_CALL_CAP), "2026-07-16T15": (0.0, 0)} calls = [] def chat(prompt, model=None, **kw): @@ -175,6 +185,7 @@ def test_route_call_cap_sleep(): def main(): tests = [test_window_key, test_seconds_to_next_window, test_cost_usd, + test_current_quota_policy, test_route_first_success, test_route_budget_exhausted, test_route_sensitive_then_next, test_route_runtime_then_next, test_route_all_fail, test_route_call_cap_sleep] diff --git a/docs/2026-07-19-回放评测-细纲首跑设计与计划.md b/docs/2026-07-19-回放评测-细纲首跑设计与计划.md index ca5cda7..b150394 100644 --- a/docs/2026-07-19-回放评测-细纲首跑设计与计划.md +++ b/docs/2026-07-19-回放评测-细纲首跑设计与计划.md @@ -13,7 +13,7 @@ - 已落地并同步到 `agent-example/main`:`fbb262c`(冻结/细纲/评分合同)、`a54a3a4`(审查反馈收紧与回放编排)、`1243d9b`(外部 planner execute 链路测试)。 - 已验证:回放脚本 26 个离线测试、fine-outline 合同 3 个测试全部通过;fake planner 已跑通三臂 execute 链路。测试只使用合成 fixture,不代表参考作品评测结果。 - 已执行真实数据库前置 smoke:深空之影 `work_id=8` 的 `example_reference_work` 表没有不可变授权快照/版权用途字段,结果为 `blocked_authorization`,三臂均未调用模型。 -- 既有 `.claude/skills/llm/scripts/test_quota.py` 仍有历史基线失败:测试期望 `$10/4000` 阀值时切到 `glm-5.2`,当前代码已是 `$24/6000`;本任务未改额度实现,也未把该失败算入回放结论。 +- `.claude/skills/llm/scripts/test_quota.py` 已统一到当前 `$24/6000` 契约:预算场景使用 `$24.5`,调用上限场景使用 `6000`,并增加策略常量断言。 - 当前允许的结论是“冻结、变量控制、候选结构门和安全摘要机制已通”;不能说细纲智能体或知识卡已通过。内容级目标事实泄露审计、真实授权接入、detector/judge 双评和 430/489/550 实样仍待完成。 ---