☰
Operit 动态思考选项 Provider 能力映射:从供应商规则生成到请求参数写入的完整链路
2026/9/27 10:49:58 网站建设 项目流程
  • AI Agent
  • 人工智能
  • 大模型
  • AI 应用
  • 工具调用
  • 本地部署
  • MCP Clients
  • Agent 记忆

【免费下载链接】Operit

The most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent

项目地址:https://gitcode.com/gh_mirrors/op/Operit
点击查看免费下载

导读

本篇技术指南聚焦 Operit 在“动态思考选项”改造中的核心机制——Provider 能力映射。旧实现把所有模型的思考强度压成 1 到 5 五个固定整数档位,无法表达各供应商真实、异构的思考参数;新实现改为由当前模型配置中的思考规则驱动,规则通过match匹配模型、声明control/parameterLabel/enable/disable/options,最终由请求层把选中动作写入对应协议参数。读完本文,你将掌握规则的数据结构、匹配优先级、内置规则如何随供应商写入模型配置、请求阶段如何解析并应用规则,以及无效选项为何会让请求直接失败。

系列文档入口见 dynamic_thinking_options_20260824/index.md,模型选项模型见 01-model-options.md,设置与 UI 见 02-settings-and-ui.md。


一、设计动机:供应商名不再是运行时全局能力集合

在旧实现中,思考档位是运行时全局状态:所有模型被压成 1~5 五个整数,滑块档位保存在ApiPreferences的全局状态中,Provider 按供应商名查找固定能力集合。这种做法的根本问题是把"供应商"等同于"能力"——同一个供应商的不同模型(如 Gemini 2.5 与其它 Gemini 型号、Anthropic 的 claude-3 旧型号与新型号)在思考参数上截然不同,全局五档契约无法承载这种差异。

新实现的核心原则是:

思考参数由当前模型配置中的规则生成,不再把供应商名视为运行时全局能力集合。

这意味着思考能力完全跟随模型配置走:新建配置或切换供应商时,收集目录会筛出对应供应商的规则并写入模型配置;请求阶段只读取当前模型配置中的规则,不再读取收集目录,也不再把档位保存在全局ApiPreferences中。


二、规则的数据结构:control、parameterLabel、enable、disable、options

每条思考规则是一个 JSON 对象,声明了五个关键字段,请求层依据它们决定如何写入参数。从源码 ModelThinkingConfigDefaultsCollect.kt 中DEFAULT_JSON(第 8~398 行)可以看到规则的完整形态,其解析结构在 ThinkingQualityMapping.kt 的ThinkingConfigurationRule.fromJson(第 180~208 行)中体现。

字段含义取值示例
id规则唯一标识openai-chat-reasoning-effort、gemini-25-thinking-budget
providers规则适用的供应商集合(写入配置后被移除)["OPENAI", "OPENAI_GENERIC"]
match模型匹配特征(见第三节){"modelRegex": ["(?:^|/)(?:o[1-9]|gpt-[5-9]|gpt-oss|codex)"]}
control控件类型levels(多档滑块)、toggle_only(仅开关)、unsupported(不支持)
parameterLabel参数标签,用于展示reasoning_effort、thinkingBudget、thinking.type
enable/disable开启/关闭思考时写入的动作数组(path + value){"path": "thinking.type", "value": "enabled"}
options选项数组,每项含id、label、path、value{"id": "high", "label": "high", "path": "reasoning_effort", "value": "high"}
required(可选)思考是否强制开启Gemini thinkingLevel、xAI Grok 等为true
endpointSuffix(可选)端点后缀匹配(位于 match 内或规则顶层)DeepSeek/responses端点与普通端点区分

control在解析时映射为枚举ThinkingQualityControl { LEVELS, TOGGLE_ONLY, UNSUPPORTED }(ThinkingQualityMapping.kt)。toggle_only规则没有options,只依赖enable/disable动作;levels规则则通过选项 id 找到对应档位值。每个选项同时携带显示文本、线路值(wire value)和请求路径——展示给用户的是label,写进请求的是path+value,二者解耦使得"显示低/中/高"与"线路传 low/high"可以自由组合。

在解析阶段,ThinkingModelMatcher(第 212~263 行)会把match中的各类匹配特征统一收集,规则还支持enable/disable动作数组、disabledValue推导(从 disable 动作中自动提取与parameterLabel同路径的字符串值作为关闭值)。


三、match 匹配特征:前缀、包含项、正则、首段与末段

规则通过match对象对模型名做模式匹配,匹配特征是ThinkingModelMatcher(ThinkingQualityMapping.kt)中定义的八种:

匹配特征说明内置规则示例
modelPrefix模型名以指定前缀开头gemini-2.5匹配 Gemini 2.5 系列
modelContains模型名包含指定子串grok匹配 xAI 全系、glm-5.3/glm-5-3匹配智谱新模型
modelSuffix模型名以指定后缀结尾—
modelRegex正则匹配模型名(?:^|/)(?:o[1-9]|gpt-[5-9]|gpt-oss|codex)匹配 OpenAI 推理模型
firstSegment模型路径(按/切分)首段精确匹配OpenCode 规则中的google、anthropic、openai、xai、zhipu等
lastSegmentPrefix末段以指定前缀开头deepseek-v4、gemini-、claude-、glm-、hunyuan-
lastSegmentContains末段包含指定子串glm
lastSegmentRegex正则匹配末段—

匹配实现(第 222~238 行)会先把模型名小写化、按/切分成段,再对所有特征做 OR 判断;所有特征都为空时视为通配规则(匹配任意模型)。这种"首段 + 末段"的分段匹配特别适合 OpenRouter、SiliconFlow、OpenCode 这类托管多厂商模型的网关:模型名形如google/gemini-2.5-pro、deepseek-ai/deepseek-v4-xxx,首段识别供应商、末段识别具体家族,比整串正则更直观也更稳。

此外规则还支持endpointSuffix端点后缀匹配(第 149~167 行):例如 DeepSeek 分别定义了/responses端点和普通端点两条规则,前者写reasoning.effort,后者写reasoning_effort,因为两条线路的协议字段完全不同。

匹配优先级:规则数组顺序即优先级

规则数组顺序就是匹配优先级:界面明确提示"按从上到下判断,首条命中的启用规则立即生效,后续规则不再评估"。对应实现见ThinkingQualityMappingRegistry.resolve(第 65~77 行)——用parseRules过滤出enabled = true的规则后firstOrNull { it.matches(...) },命中即返回;没有任何规则命中时回退为ThinkingQualityMapping.unsupported()(control = UNSUPPORTED,请求层不会写入任何思考参数)。解析时的endpointMatches会对端点做去 query、去 fragment、去尾部斜杠、小写化的归一化处理。


四、内置规则写入模型配置:forProvider 筛选机制

规则不是硬编码在 Provider 内部的,而是通过收集目录 ModelThinkingConfigDefaultsCollect.kt 提供内置默认集,在新建配置或切换供应商时写入模型配置:

forProvider(providerTypeId)(第 400~420 行)把传入的供应商类型 id 大写化后,遍历DEFAULT_JSON中的全部规则,筛选出providers或providerTypeIds包含该供应商的规则,剥离 providers/providerTypeIds 字段后生成该供应商专属的规则数组返回。请求阶段则只从当前模型配置读取规则,不再读取收集目录——收集目录只负责"播种"默认规则,模型配置才是唯一事实来源(这一点在 02-settings-and-ui.md 中有明确说明)。

设置页对规则的维护方式是弹窗表单:模型配置页新增"思考配置"块,与模型参数同级;外层默认收起,展开后只展示每条配置的模型匹配、请求路径和控件摘要;点击单条预览进入对应配置的紧凑弹窗,写入动作和滑块档位在弹窗内继续折叠。每条规则预览项提供上移/下移操作,调整后的顺序随规则配置自动保存,从而控制首条命中优先级。

模型配置 DataStore 保存thinking_option_id,Web API 使用同名字符串字段,见 WebChatModels.kt 中的@SerialName("thinking_option_id")声明。滑块直接以当前配置规则解析出的选项数量设置 stops 和 labels,切换模型后由当前映射重新计算可用位置。


五、各供应商默认规则:一份规则表看懂全部能力

内置默认集(DEFAULT_JSON)覆盖了当前接入的全部供应商,每条默认规则对应上文第三节的匹配特征,形成一张完整的"供应商 × 模型家族 → 思考参数"能力表:

供应商 / 协议默认规则要点写出的请求参数
OpenAI Chat / 通用推理模型(o1-o9、gpt-5+、gpt-oss、codex)走reasoning_effort五档(low/medium/high/xhigh/max);gpt-3/4、chatgpt-等非推理模型标记为unsupported;OpenAI 兼容协议兜底同样写reasoning_effortreasoning_effort
OpenAI Responses / Codex写reasoning.effort五档,并伴随enable动作:reasoning.summary = "auto"、include = ["reasoning.encrypted_content"];关闭时reasoning.effort = "none"reasoning.effort及伴随字段
Gemini 2.5匹配modelPrefix: ["gemini-2.5"],使用thinkingBudget五档(1024/4096/8192/16384/32768),开启时generationConfig.thinkingConfig.includeThoughts = true,关闭时thinkingBudget = 0generationConfig.thinkingConfig.thinkingBudget
其它 Gemini匹配gemini-3+正则,使用thinkingLevel四档(MINIMAL/LOW/MEDIUM/HIGH),且required = true强制思考generationConfig.thinkingConfig.thinkingLevel
Anthropic 旧型号匹配modelPrefix: ["claude-3"],使用预算thinking.budget_tokens四档(1024/4096/8192/16384)thinking.budget_tokens
Anthropic 新型号使用adaptive thinking与 effort:开启时thinking.type = "adaptive"、thinking.display = "summarized",档位写output_config.effort(low/medium/high)output_config.effort
DeepSeek普通端点写reasoning_effort三档(low/high/max),开启/关闭联动thinking.type = enabled/disabled;/responses端点改用reasoning.effort三档reasoning_effort/reasoning.effort
OpenRouter / Nous默认示例写reasoning.max_tokens五档(1024/8192/16384/32768/65536),关闭时reasoning.enabled = falsereasoning.max_tokens
OpenCode按模型路径首段识别家族:google/*→thinkingLevel+thinkingConfig.includeThoughts;anthropic/minimax首段 +claude-/minimax-末段 → adaptive thinking +output_config.effort;zhipu/zai-org/thudm首段 +glm末段 →reasoning_effort;openai/azure/xai首段 +gpt-/grok-/codex→ Responses 协议reasoning.effort;兜底走 Chat 协议reasoning_effort按家族区分
智谱 GLMglm-5.3/glm-5-3→reasoning_effort三档且required;glm-5.x-6+正则 → high/max 两档;glm-4.5+→ 仅开关thinking.typereasoning_effort/thinking.type
Kimi / MiMo / 豆包均为仅开关(toggle_only):thinking.type = enabled/disabledthinking.type
通义 Qwen3qwen3正则匹配,仅开关enable_thinkingenable_thinking
SiliconFlowdeepseek-ai/deepseek-v4*→reasoning_effort(high/max,required);zai-org/tencent+glm-/hunyuan-→enable_thinking开关;其余 →thinking_budget五档reasoning_effort/enable_thinking/thinking_budget
xAI GrokmodelContains: ["grok"],reasoning_effort四档(low/medium/high/xhigh),requiredreasoning_effort
NVIDIAgpt-oss/nemotron→reasoning_effort三档;其余模板走chat_template_kwargs.enable_thinking开关reasoning_effort/chat_template_kwargs.enable_thinking
本地模板(MNN / llama.cpp)仅开关enable_thinkingenable_thinking

智谱、Kimi、MiMo、豆包、SiliconFlow、NVIDIA 和本地模板能力都通过同一套规则结构表达——没有为任何供应商单独写死分支,差异全部收敛为 JSON 规则数据。


六、请求阶段应用:解析规则 → 写入 JSON 路径

请求阶段的入口是ThinkingConfigurationApplier.apply(ThinkingQualityMapping.kt),它接收providerTypeId、modelName、apiEndpoint、当前模型配置的thinkingConfigurations、enableThinking开关和optionId(选项 id 属于当前模型配置,绝不读取全局偏好),执行三步:

  1. 解析并匹配规则:调用ThinkingQualityMappingRegistry.resolve得到当前模型的ThinkingQualityMapping;若control == UNSUPPORTED直接返回,不写入任何参数。
  2. 应用模式动作:thinkingEnabled = enableThinking || mapping.reasoningRequired,按开关状态执行enabledActions或disabledActions(即规则的enable/disable数组),通过applyAction逐条写入。applyAction(第 339~344 行)支持点分路径写入(putJsonPath自动创建中间 JSON 对象),且默认overwrite = false——如果路径已存在则不覆盖,避免破坏请求中已有的同名参数。
  3. 应用档位动作:仅当思考开启且control == LEVELS时,通过optionFor(optionId)找到选中选项并写入其actions(path + value)。

无效选项 id 直接失败,绝不静默

关键的安全设计:optionFor(optionId)找不到选项时(第 310~311 行)会抛出IllegalArgumentException("$providerTypeId option is not supported: $optionId"),请求直接失败。这样用户选择了一个不存在的档位时,系统宁可报错也不会静默改变其选择——避免"看起来选了 high 实际发的是 low"这类隐蔽的语义漂移。

参数回显为模型参数

modelParameters(第 317~337 行)把规则应用后的请求 JSON 回显为可展示的ModelParameter列表:字符串、整数、浮点、布尔和对象分别映射为对应类型的参数,thinkingConfig在 Gemini 协议下归类为ParameterCategory.GENERATION(第 466~493 行)。这让模型参数页能直接展示当前思考配置产生的实际请求字段。

各 Provider 请求层都会把enableThinking与规则结果一起传给底层实现,例如 GeminiProvider.kt 中的GeminiThinkingConfig(第 51~81 行)依据mapping.optionFor(optionId)的 wire value 类型构造thinkingLevel或thinkingBudget并写入generationConfig.thinkingConfig;ClaudeProvider.kt、DeepseekProvider.kt等在enableThinking开关分支中同样联动规则动作。


七、本地 llama.cpp:enableThinking 进入 chat template

本地推理链路(llama.cpp / MNN)不经过 HTTP 协议,而是把思考开关透传给本地 chat template:规则mnn-llama-template-thinking-toggle声明parameterLabel = "enable_thinking",enable/disable分别写enable_thinking = true/false。请求层把enableThinking传入 llama.cpp chat template 的enable_thinking输入字段,由模板在本地拼装 prompt 时决定是否注入思考段。这样本地模型与云端模型共用同一套规则表达,无需为本地链路单独维护档位逻辑——本地思考只有开关(toggle_only),符合 llama.cpp 模板的实际能力边界。


八、小结与自检清单

Provider 能力映射的完整闭环是:

  1. 播种:新建配置/切换供应商时,ModelThinkingConfigDefaultsCollect.forProvider从内置默认集筛出对应规则写入模型配置;
  2. 维护:设置页弹窗表单展示/编辑规则,顺序即匹配优先级,支持上下移与自动保存;
  3. 匹配:请求阶段ThinkingQualityMappingRegistry.resolve按 provider + 模型名 + 端点后缀首条命中规则;
  4. 应用:ThinkingConfigurationApplier.apply按 enable/disable 动作与选中 option 的 path+value 写入请求 JSON,无效选项 id 直接抛错;
  5. 回显:规则产物转为ModelParameter供模型参数页展示,Android 与 WebChat 共用thinking_option_id字符串字段。

排查思考参数问题时可按此顺序核对:当前模型配置里是否存在该供应商的规则 → 规则顺序是否让错误规则先行命中 →match特征是否覆盖该模型名(注意首段/末段按/切分)→control类型是否符合预期 → 选中 option 的 id 是否存在于 options 列表 → enable/disable 动作的 path 是否与协议文档一致(尤其注意 DeepSeek 的/responses与普通端点、Gemini 的thinkingBudget与thinkingLevel之分)。

关键参考文件:

  • 能力映射规则默认集:ModelThinkingConfigDefaultsCollect.kt
  • 规则解析、匹配与应用核心:ThinkingQualityMapping.kt
  • Gemini 思考配置构造:GeminiProvider.kt
  • WebChat 协议字段:WebChatModels.kt
  • 系列文档:01-model-options.md · 02-settings-and-ui.md
  • AI Agent
  • 人工智能
  • 大模型
  • AI 应用
  • 工具调用
  • 本地部署
  • MCP Clients
  • Agent 记忆

【免费下载链接】Operit

The most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent

项目地址:https://gitcode.com/gh_mirrors/op/Operit
点击查看免费下载

相关推荐

上一篇:7个技巧彻底掌握Plain Craft Launcher 2:重新定义Minecraft游戏管理体验
下一篇:7大创意应用方案:开源中文字体如何彻底改变你的设计工作流

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询