Repository navigation
PowerContext 的模型路由成本结构:多模型配置面实测与四个缺口 #2015
Replies: 3 comments
|
主打三个方面:省 token、强隐私、高性能。 |
|
Two points would change the proposed routing baseline. The second attempt is on the same model, but a schema failure is not an identical request. The adapter uses Pydantic AI's validation retry mechanism. With I checked this with Pydantic AI 2.27.1, the dependency lower bound, using a local That makes the useful comparison same-model repair versus escalation, with the same request and time budgets, rather than blind repetition versus escalation. A schema error alone does not establish that the model lacks the required capability. Also, the external benchmark's 21.2% judge share cannot be carried over to this workload just because decision and generation share a model. Call frequency, input/output lengths and caching affect that share. The proposed per-model usage accounting is needed to measure it before choosing a cheaper default. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
结论摘要
pc_model_usage_daily没有模型维度,全仓没有价格模型。#1736 §2 要求审计记录含 provider/model ID ——pc_decision_observations有,但聚合用量表和生成链路没有。一、多模型配置面(实测)
实测方式:设置环境变量后构造
ServerSettings,直接检查落地的InferenceConfig字段(.venv/bin/python,当前 HEAD)。POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODELNone..._INFERENCE_EMBEDDING_MODEL+_PROFILE_ID+_DIMENSION+_NORMALIZATIONNone..._INFERENCE_RERANK_MODELNone→ 回落 generation..._INFERENCE_DECISION_MODELNone→ 回落 generation四个槽位同时配置实测通过,且
rerank_base_url可指向与 generation 完全不同的厂商。机制来自server/settings.py:190的SettingsConfigDict(env_prefix="POWERCONTEXT_SERVER_", env_nested_delimiter="_", env_nested_max_split=1)。模型串为
适配器:模型名,由 pydantic-aiinfer_model解析;带 base_url/headers 时模型串必须含:,否则抛inference-endpoint-provider(composition.py:1674)。配不到的边界
composition.py:1317-1333):profile.generate、atomic_memory.extract、atomic_memory.reconcile、experience.incubate、experience.generate、skill.generate、handoff.generate(7 项)+topic_memory的 7 个 stage(probe/global/planner/evolve/temporary/reduce/reconcile)。想让topic_memory.reduce单独用便宜模型做不到。*_MODEL(或仅设*_HEADERS)才算独立:separate_rerank_model = rerank_model is not None or bool(rerank_headers)(composition.py:1445),decision 同构(:1567);否则直接复用 generation 的 provider/model 对象,timeout / max_requests 也走or generation_*回落(:1599)。cli/config_wizard_models.py:31-32只有GENERATION("背景整理模型")与EMBEDDING("语义检索模型");cli/config.py的_INFERENCE_REPLACEMENT_NAMES同样不含 rerank / decision。这两个槽位目前只能手写.env。二、四个缺口
缺口 1(P0):Judge 默认与生产者同价
composition.py:1558-1567:decision_provider_model = generation_provider_model、decision_model = generation_model,只有separate_decision_model为真才另开连接。因此不显式配置DECISION_MODEL时,判断成本与生产生成成本同档。这正好落在文章量到的那个陷阱上:LangChain 的 Escalation Router 公开测试中,93% 的执行调用由低成本模型完成,但费用结构是高性能模型 68.4% / Judge 21.2% / 低成本模型 10.4%。一个默认继承生成模型的 Judge,只会让这 21.2% 更高。
memory_write_gate.py:73-95的promotion_criteria已经写了"measured fallback, latency, cost, and friction",config.py:154的memory_write_gate_threshold也刻意留空等待校准(注释:stays unset until a calibration probe establishes it)。建议把「Judge 不得默认继承生产模型」也纳入同一条准入条件:要么要求decision_model显式配置,要么回落到最便宜可用档。另外
memory_write_gate.py:81已有local_rules=("candidate_batch_budget", "evidence_projection_budget")。文章的「三层判断」(明确异常直接判 → 一般信号累计判 → 信号模糊才调 Judge)落到这里就是:把本地规则提升为前置门,本地能定案的请求不进 decision 模型。缺口 2(P0):rerank 旁路掉整个 gate
recall_sufficiency.py:503-504:这个 return 位于
candidate_count、family_count、top_score、top_gap、lexical_overlap全部判断之前。后果是:打开 rerank 等于关掉整个 gate,零模型成本的 admission 扩展路径(ACTION_ADMISSION/ACTION_POLICY_FLOOR)被完全旁路,而REASON_THIN_CANDIDATES/REASON_THIN_FAMILIES这些信号明明可以在不调用任何模型的前提下处理。这与 #1736 §6「不替换现有 model-free recall sufficiency gate」是两个不同方向的风险:#1736 防的是「用模型替换确定性 gate」;这里是「一个配置开关静默停用了 gate」。
模块 docstring 解释了为什么
rerank_enabled读配置而非读实例存在(gate 必须在搜索之前决定是否允许扩展),但没有解释为什么开启 rerank 要取代扩展而不是分层。recall_gate_allow_with_rerank目前是唯一的逃生阀,即全开或全关。建议:按 reason 分层,而不是在入口短路 ——
no-content/budget-floorthin-candidates/thin-familiesweak-top-1/weak-lexicalat-max-rounds约束:
SearchPlan的 docstring(recall_sufficiency.py:149-157)明确承诺「never names a family, never setslimit,modeor a rerank candidate bound」,理由是 Atomic Memory 的coarse_limit → candidate_limit = max(coarse_limit*4, 32)会使 30→100 把后端池从 120 涨到 400,RFC 1560 已否决。新的分层策略必须延续这个 same-pool 不变量,不能靠改 limit 实现升级。缺口 3(P1):重试是同模型盲重试
builtin/inference/pydantic_ai.py:161:retries=self._limits.max_requests - 1,而max_requests默认 2(config.py:299)。结构与模型选择完全解耦 —— 第 1 次失败(尤其是 schema / 校验失败)后,第二次仍然打到同一个模型。结构化解码 / 校验失败恰恰是「当前能力不足」最强的现成信号,对应文章里 NVIDIA Stage Router 的
spinning(反复相似操作、无进展)。建议把第 2 次尝试指向更高能力档,而不是重复同一请求。 实现成本极低(只换 model 参数)。配套需要定义「升级后保持多久」:文章提示频繁切换会丢 Prompt Cache;对 PowerContext 而言抖动代价是候选池与 embedding 复用被打破,性质类似。NVIDIA 的
capable hold(升到强模型后跑满若干轮再考虑降级)或 LangChain 的单向升级(升上去就保持到本次 Session 结束)都是可选项,但必须显式选择其中一个,不能留给默认行为。缺口 4(P1):用量归因不到模型,也没有价格
文章里两条数据驱动机制都依赖「按模型归因 + 折价」:
当前仓库做不到:
MODEL_USAGE_DAILY_TABLE(persistence/tables.py:890)主键是(scope_id, usage_date, purpose, operation),operation还有 CHECK 约束只允许generation/embedding—— 归因到 purpose,归因不到 model;InferenceUsage(builtin/inference/models.py:27)只有requests/input_tokens/output_tokens,全仓无价格字段。值得注意的是术语已经存在:
DECISION_OBSERVATIONS_TABLE(persistence/tables.py:1123)已有provider_id/backend_model_id/model_policy_id/requests/input_tokens/output_tokens/latency_ms。也就是说决策链路已经满足 #1736 §2 的审计要求,缺的是把同一组字段扩展到生成链路与聚合用量表。建议:给用量表加
model_policy_id(沿用已有术语,不造新名)与可选cost_micros。注意两点:operation的 CHECK 约束意味着加模型维度会动主键;AGENTS.md,加列走启动钩子ensure_*_schema(挂在open_builtin_contexts),不是 Alembic。验证必须走真实启动路径(create_server_app+TestClient),只调SQLiteProfile.open()会得到假阳性。这一点与 #1971 的评测要求也直接相关 —— 它已经写明 "Measure all actual provider usage, stages, retries, and later queries; missing usage is unknown"。两份工作面对的是同一个数据缺口:
pc_model_usage_daily当前既没有模型维度,也没有把 retry 单独记出来。三、值得借用的一条算术:Router 自己的成本
文章里最有迁移价值的是这个判断方法,而非任何一个架构:
这把「要不要引入决策模型/路由」从偏好问题变成一个可以先算后做的问题。对 PowerContext 的直接含义:在补上缺口 4(模型归因 + 价格)之前,这个算术根本算不出来。因此缺口 4 虽然排 P1,却是 P0 两项的前置条件。
同一个原则的本地形态是「简单情况用便宜方法判断」:
recall_sufficiency.py已经做到零模型成本判断,这一优势应当在缺口 2 修好后保留并扩大,而不是被 rerank 开关抵消。四、评估口径
文章给出了可复用的 A/B 形态,以及一个明确的负例,两者都指向同一个要求:评估的单位是「完整任务」,不是「单次调用」。
$0.94vs 全高性能模型$2.61(约 -64%);PR Merge Rate29.2%vs27.3%,差异未达统计显著。86.00% / $11.45,动态 Escalation80.00% / $3.00,全低成本77.70% / $0.72。相对全高性能模型省约 74% 成本但准确率掉 6 个百分点;相对全低成本模型只提升 2.3 个百分点,却贵约 4.2 倍。对 PowerContext 而言,recall gate / rerank / write gate 这三个开关的评估应输出三列:完整任务成功率、总成本、执行时间,且必须包含「全便宜档」作为基线 —— 上述负例正是缺基线的后果。
需要如实标注的现状:仓库内的
token_reduction是「召回已选对前提下的压缩率」,不是端到端收益;仓库内也没有「任务成功率提升」的对照证据。这一点与 #1971 的评测设计和 #1736 §3 的对照实验要求方向一致,可以合并考虑。五、不建议照搬的部分
ModelUsagePurpose的 9 个枚举值已是更可靠的人工任务分类,不需要再训 / 调一个分类器去逼近它六、顺带发现两项
环境变量名写错会被静默忽略。
ServerSettings使用SettingsConfigDict(extra="ignore")(server/settings.py:190)。实测POWERCONTEXT_SERVER_INFERENCE_TYPO_MODEL无任何提示地被丢弃,rerank_model于是静静回落到 generation。对于一个以「换便宜模型省钱」为目的的配置面,这类静默失败代价不小 —— 拼错RERANK_MODEL不会报错,只是悄悄按 generation 的价格跑。建议至少对POWERCONTEXT_SERVER_INFERENCE_*前缀做未识别名称告警。#1736 §3 建议「继续 feat(memory): add an optional Jev reranker with comparative evaluation #1643」,但 feat(memory): add an optional Jev reranker with comparative evaluation #1643 目前不存在:GraphQL
issueOrPullRequest(number: 1643)返回null,REST 亦为 404。该后续动作当前没有落点,建议重新开一个跟踪项承接 §3 里那组对照实验要求(同一候选池 / 查询集 / 下游模型 / 上下文预算下比较「无重排 / 当前 LLM reranker / Jev / 专用 reranker」)。七、优先级
recall_sufficiency.py:503的入口短路,改按 reason 分层max_requests的重试改为升级重试,并显式定义升级保持策略spinning类信号接上model_policy_id+ 价格(走ensure_*_schema)以上均为设计与证据层面的建议,未对内核行为做任何约定;是否采纳、以何种顺序推进,请维护者判断。欢迎指出事实性错误 —— 所有行号基于当前 HEAD,若已变动以代码为准。
参考资料
仓库内相关讨论与跟踪项
代码证据(当前 HEAD)
src/powercontext/builtin/runtime/config.py—InferenceConfig(:289)、4 个槽位字段、memory_write_gate_threshold(:154)src/powercontext/builtin/runtime/composition.py— 生成档 14 个 prompt key(:1317-1333)、rerank 独立判定(:1445)、decision 继承(:1558-1567)、or generation_*回落(:1599)、模型串校验(:1674)src/powercontext/builtin/runtime/recall_sufficiency.py—rerank_enabled入口短路(:503-504)、SearchPlansame-pool 不变量(:149-157)src/powercontext/builtin/runtime/memory_write_gate.py—local_rules(:81)、promotion_criteria(:90-94)src/powercontext/builtin/inference/models.py—InferenceUsage(:27)src/powercontext/builtin/inference/pydantic_ai.py—retries = max_requests - 1(:161)src/powercontext/builtin/persistence/tables.py—MODEL_USAGE_DAILY_TABLE(:890)、DECISION_OBSERVATIONS_TABLE(:1123)src/powercontext/server/settings.py—SettingsConfigDict(:190)src/powercontext/cli/config_wizard_models.py— 仅 GENERATION / EMBEDDING 两个角色(:31-32)文章引用的外部来源(均为各方自测,未经独立复现)
All reactions