- AI Agent
- 人工智能
- 大模型
- AI 应用
- 工具调用
- 本地部署
- MCP Clients
- Agent 记忆
【免费下载链接】Operit
The most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent
导读
本篇技术指南聚焦 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_effort | reasoning_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 = 0 | generationConfig.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 = false | reasoning.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 | 按家族区分 |
| 智谱 GLM | glm-5.3/glm-5-3→reasoning_effort三档且required;glm-5.x-6+正则 → high/max 两档;glm-4.5+→ 仅开关thinking.type | reasoning_effort/thinking.type |
| Kimi / MiMo / 豆包 | 均为仅开关(toggle_only):thinking.type = enabled/disabled | thinking.type |
| 通义 Qwen3 | qwen3正则匹配,仅开关enable_thinking | enable_thinking |
| SiliconFlow | deepseek-ai/deepseek-v4*→reasoning_effort(high/max,required);zai-org/tencent+glm-/hunyuan-→enable_thinking开关;其余 →thinking_budget五档 | reasoning_effort/enable_thinking/thinking_budget |
| xAI Grok | modelContains: ["grok"],reasoning_effort四档(low/medium/high/xhigh),required | reasoning_effort |
| NVIDIA | gpt-oss/nemotron→reasoning_effort三档;其余模板走chat_template_kwargs.enable_thinking开关 | reasoning_effort/chat_template_kwargs.enable_thinking |
| 本地模板(MNN / llama.cpp) | 仅开关enable_thinking | enable_thinking |
智谱、Kimi、MiMo、豆包、SiliconFlow、NVIDIA 和本地模板能力都通过同一套规则结构表达——没有为任何供应商单独写死分支,差异全部收敛为 JSON 规则数据。
六、请求阶段应用:解析规则 → 写入 JSON 路径
请求阶段的入口是ThinkingConfigurationApplier.apply(ThinkingQualityMapping.kt),它接收providerTypeId、modelName、apiEndpoint、当前模型配置的thinkingConfigurations、enableThinking开关和optionId(选项 id 属于当前模型配置,绝不读取全局偏好),执行三步:
- 解析并匹配规则:调用
ThinkingQualityMappingRegistry.resolve得到当前模型的ThinkingQualityMapping;若control == UNSUPPORTED直接返回,不写入任何参数。 - 应用模式动作:
thinkingEnabled = enableThinking || mapping.reasoningRequired,按开关状态执行enabledActions或disabledActions(即规则的enable/disable数组),通过applyAction逐条写入。applyAction(第 339~344 行)支持点分路径写入(putJsonPath自动创建中间 JSON 对象),且默认overwrite = false——如果路径已存在则不覆盖,避免破坏请求中已有的同名参数。 - 应用档位动作:仅当思考开启且
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 能力映射的完整闭环是:
- 播种:新建配置/切换供应商时,
ModelThinkingConfigDefaultsCollect.forProvider从内置默认集筛出对应规则写入模型配置; - 维护:设置页弹窗表单展示/编辑规则,顺序即匹配优先级,支持上下移与自动保存;
- 匹配:请求阶段
ThinkingQualityMappingRegistry.resolve按 provider + 模型名 + 端点后缀首条命中规则; - 应用:
ThinkingConfigurationApplier.apply按 enable/disable 动作与选中 option 的 path+value 写入请求 JSON,无效选项 id 直接抛错; - 回显:规则产物转为
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
相关推荐
Operit 动态思考选项:基于 Provider 真实能力的思考强度映射、配置持久化与请求序列化实战
Operit 动态思考选项:基于 Provider 真实能力的思考强度映射、配置持久化与请求序列化实战 导读 本篇技术指南围绕 Operit(Android 平
AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Operit 动态思考选项模型:从固定五档整数到 Provider 级字符串选项的架构演进
Operit 动态思考选项模型:从固定五档整数到 Provider 级字符串选项的架构演进 Operit 在思考强度(Thinking Quality)控制上完
AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Spring MVC HandlerMapping 源码剖析:从 HTTP 请求到 HandlerExecutionChain 的完整映射链路
Spring MVC HandlerMapping 源码剖析:从 HTTP 请求到 HandlerExecutionChain 的完整映射链路 本文基于本仓库的
文档教程知识库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考