1 Commits
Author SHA1 Message Date
lededevandChris233 ef78a091a9 fix(llm): 通过 LM Studio preset 控制思考 (#1009)
* fix (polish): LM Studio默认对Gemma 4 12B开启思考,需要显式关闭它

摘要
通过 LM Studio 的 OpenAI 兼容接口接入 Gemma 4 12B 时,openless 默认「关闭思考」,但模型仍输出长思维链——UI 开关无效。根因是 LM Studio(llama.cpp 系服务)里 Gemma 4 等思考模型的 chat template 默认 enable_thinking=true:不下发参数不会关,必须显式下发关闭参数才生效;而现有 thinking 控制策略只按厂商域名关键字识别(minimax/deepseek/openrouter/dashscope/stepfun),本地服务无厂商域名,落入 None 分支一个 thinking 参数都不发,行为完全由模型侧默认值决定——恰好是「开」。
本 PR 新增 LmStudioThinking 策略:按 LM Studio 默认端口 1234(另登记 provider_id "lmstudio")识别该场景,显式下发 chat_template_kwargs.enable_thinking=false 关闭思考,并附两个 OpenAI 风格字段多重兜底。
修复 / 新增 / 改进
- 新增 ThinkingControl::LmStudioThinking:关闭时(openless 默认态)下发 chat_template_kwargs.enable_thinking=false + reasoning_effort="none" + reasoning.type="disabled" 三件套显式关掉 Gemma 4 12B 的默认思考(LM Studio/llama.cpp 均接受,多重兜底);用户手动开启时只显式发 enable_thinking=true,不附带后两个关闭字段。
- 识别逻辑:base_url 提取的 host 以 :1234 结尾即命中(LM Studio 默认服务端口,带冒号前缀匹配避免误伤 12345/12340 等端口);同时在已知列表登记 provider_id "lmstudio",将来若新增专属 preset 自动生效。
- doc 注释更新:openai_compatible_thinking_control_for_base_url 命中策略说明改为「厂商关键字 + 本地服务按端口」,并写明自定义端口无法自动识别的局限。
- 测试:4 个新回归用例(默认端口关闭时三字段齐全、开启时仅 enable_thinking=true、尾斜杠//v1 后缀/LAN IP 变体均命中、端口 12345 不误命中),另在既有 unknown-provider 用例补断言 chat_template_kwargs 不存在,防新策略误触发。
- 未改动:各厂商(MiniMax/DeepSeek/OpenRouter/DashScope/StepFun)thinking 参数逻辑、chat body 结构、超时预算。
兼容
- 不包含:不新增 "lmstudio" preset;用户修改 LM Studio 端口后无法自动识别(已写入注释),此时需自行确认模型侧思考默认值。
- 对现有用户 / 本地环境 / 构建流程的影响:无。仅对命中 :1234 的请求多带三个 thinking 控制字段,非思考模型忽略即可;其余 provider 行为不变。
- 改动量:单文件 openless-all/app/src-tauri/src/polish.rs,生产代码净增约 24 行(含注释/文档),测试净增 87 行。
测试计划
- 命令:cargo test --manifest-path src-tauri/Cargo.toml --lib(在 openless-all/app 下运行)
- 结果:5/5通过
- 反向验证:移除 :1234 分支后默认端口及变体用例如期失败;把关闭态三字段减为仅 enable_thinking 则三字段断言失败;若匹配放宽到不含冒号前缀,12345 防误伤用例即被打破
- 证据路径:本地终端输出,未落盘到仓库

* fix(llm): control LM Studio thinking through an explicit preset

---------

Co-authored-by: Chris233 <h-chris233@outlook.com>
2026-09-13 19:59:15 +08:00