feat(thinking): GPT系列模型effort思考等级透传支持 - #1
Open
jsjm1986 wants to merge 6 commits into
Open
Conversation
对全仓 53k 行 Rust + 23k 行前端逐文件精读,再对每条发现逐一读代码复核(含证伪),
只修确认成立的缺陷,每条都配能抓住旧 bug 的回归测试。测试 778 → 792 全绿。
macOS 完整支持(新平台):
- fix(update): ASSET_BIN 改为按 OS×ARCH 选资产。原先只有 cfg(windows)/cfg(not(windows))
二选一、不看架构,macOS 与 arm64 Linux 全部落到 linux-x86_64 → 一键升级会把 Mach-O
换成 Linux ELF 且 sha256 校验通过,重启后服务当场死亡。未覆盖组合改为 compile_error!
- ci: 新增 build-release-macos job(macos-14,矩阵产出 aarch64/x86_64 + sha256)
- feat(admin): restart_service 增加 macOS 分支,spawn detached POSIX shell 助手拉起新二进制
- feat(install): install-binary.sh 按 uname 选资产、sha256 工具自适应、装 launchd LaunchAgent
致命缺陷:
- fix(scheduler): transient_wait_outcome 补齐 custom_api 与 model_blocklist 两道硬门。
与 is_entry_selectable 不对齐时 select 返 None 而等待判定返 Available,
Available => continue 分支不 sleep 也不递增 attempt_count → 请求永不返回且烧满一核。
另加竞态重选上限 64 作纵深防御
- fix(throttle): 令牌桶容量补 .max(ONE_TOKEN_MILLI)。容量隐含要求 rpm*burst>=60,
默认 burst=2 时 rpm<=29 容量就 <1000 永远攒不满一个令牌,而 AIMD 降两档即到 25
→ 默认配置下被上游 429 打两次就整体塌陷
高危缺陷:
- fix(throttle): last_md_nanos 只在真降档时刷新。已达 rpm_min 时仍刷新会让升档静默期
永不满足,RPM 永久卡在 floor
- fix(scheduler): 裸 429 的 health 键改用 family_key。原用 cred:{id} 而读侧全用 family_key,
M365 号的 429 全写进从不被读的影子条目 → 被打爆也永不熔断
- fix(token): 新增 persist_disabled_state,5 条自动禁用路径补落盘。原先只写 kiro_stats.json
而 StatsEntry 不含 disabled 字段 → 重启后死号以 enabled 回池
- fix(stream): partial_invoke_tag_suffix_len 加 64 字节上限。孤立 < 落到缓冲首位时
emit_len=0 → 此后整条响应文本都不下发,缓冲无界增长
- fix(converter): 工具名前缀改按字节预算截断。原按字节判超限、按字符截前缀,
30 个汉字缩短后反而变 99 字节仍超限 → 上游 400
- fix(security): 背景图两端点加图片 MIME 白名单 + 10MiB 流式上限 + nosniff。
匿名端点原样透传上游 Content-Type 可在 /admin 同源 XSS
- ci: 新增 tag 与 Cargo.toml 版本一致性门禁,防 OTA 无限升级循环
其它:
- test: custom_api 测试改用 RFC6761 .invalid TLD,不再依赖真实 DNS
(fake-IP 代理机器上 198.18/15 命中 SSRF 禁止段致测试必失败)
- docs: README 修正 Docker 默认端口 8991→8990,补平台资产对照表
- docs: CLAUDE.md 更正构建命令须带 --no-default-features、src/test.rs 不参与编译、
已知问题 #2 仅修一半、#6 描述方向
- fix(install): systemd unit 补挂 rollback-guard.sh,此前公共安装脚本无 OTA 崩溃回滚
用户实测反馈:「优先级设置了 kiro 的 apikey 更小,还是会优先调度上游的 apikey」。 根因是两处叠加,导致用户设的 priority 在跨池维度上从未被比较过: - 分派顺序写死在 handlers:请求一进来就先 try_custom_api_passthrough, 只有它返回 None(代挂池全部冷却/失败)才落 Kiro 主路径; - select_custom_api 只在 custom_api **子集内**按 priority 排序。 于是 custom_api 隐含享有绝对最高优先级 —— 哪怕 Kiro 号 priority=0、代挂号 priority=99, 也永远先走代挂号,与「priority 越小越优先」的产品直觉直接冲突。 改动: - feat(config): 新增全局 customApiFirst,**默认 false**(= priority 全局统一比较)。 设 true 可恢复历史的「代挂号绝对优先」行为。TIER1 热重载即时生效。 - feat(credentials): 新增凭据级 customApiFirst(Option<bool>),可**逐个上游 apikey** 覆盖全局值;None=跟随全局。Admin 的 AddCredentialRequest 同步支持。 - feat(scheduler): 新增 should_try_custom_api_first() 做一次性跨池仲裁 —— 任一可用代挂号显式 first=true 则先走透传;否则取两池各自最优 priority 比较, 代挂不劣于 Kiro(<=,priority 相同时维持代挂在前以兼容既有部署)才先走透传。 禁用与冷却中的号不参与仲裁(后者此刻本就选不出来,不该影响路径决策)。 - fix(handlers): 分派前先仲裁,Kiro 更优时跳过透传直接走 Kiro。 即便跳过,Kiro 全失败后 provider 的 failover 仍会落回代挂池,兜底能力不减。 仲裁只做路径选择,不改两池各自的选号逻辑,故「两池隔离铁律」 (Kiro 选号永不返回 custom_api、透传结果永不进 health/family 连坐)完全不变。 测试 792 → 799:新增 7 个用例覆盖 kiro 更优 / 代挂更优 / priority 相等 / 全局开关 / 凭据级双向覆盖 / 空池与单池边界 / 冷却号排除。 另经 A/B 端到端实测:默认+kiro优先时日志零透传迹象,其余三种场景均正确走透传。
用户实测反馈:Claude Code 经 KiroStudio 转发 CC 协议时报 「Stream idle timeout - no chunks received」。 根因:/cc/v1/messages 的流式分支**无条件**走 handle_stream_request_buffered, 完全绕过 ccAutoBuffer 开关。buffered 分发会把整轮回答憋到上游流结束才一次性吐, 期间对客户端只发 25s 间隔的 ping、零内容字节。 项目其实早已坐实这个行为有害并因此把 /v1 的默认改成真流式 (见 default_cc_auto_buffer 的注释): - contextUsageEvent 结尾才到 → 整轮看不到进度,模型越慢越像卡死; - CC 的 steering(执行途中插消息引导)依赖观察流式增量, buffered 把整轮变成不可打断的黑盒。 但那次修正只落在 /v1,本端点漏了 —— 于是把 CC 指向 /cc/v1 的用户拿到旧的有害行为, 且把 ccAutoBuffer 设成 false 也关不掉(开关对该路径完全无效)。 现两个端点由同一开关统一语义: ccAutoBuffer=false(默认)→ 两端都真流式(内容边到边转发) ccAutoBuffer=true → 两端都 buffered(换取 message_start 即精确 input_tokens) 另加分发决策的 debug 日志,便于生产排障确认走的是哪条路径。 实测两种取值下 /cc/v1 分别正确走真流式与 buffered。
按需求把 CC 自动切缓冲协议改为默认开启:识别到 Claude Code 的请求走 buffered 分发, 使 message_start 的 input_tokens 直接用上游 contextUsageEvent 的准确值(CC 会校验该字段), CC 直接打 /v1 即可正确工作,无需手动改用 /cc/v1。 顺带修掉一处长期存在的默认值不一致:ccAutoBuffer 的默认值散落三处 —— ① src/model/config.rs default_cc_auto_buffer() 原为 false ② src/anthropic/handlers.rs CC_AUTO_BUFFER static 初值 本就是 true ③ src/admin/types.rs ConfigSnapshotResponse::default 本就是 true ①与②③相反已久。运行时②会被 main 启动播种覆盖故不会立刻出错,但会让单元测试、 以及任何绕过 create_router_with_provider 的代码路径读到错的默认值,排障时极易误判。 本次改①为 true 后三处对齐,并新增两个测试把一致性钉死(改任一处不同步即失败)。 文档同步:default_cc_auto_buffer 与字段头注释都补全了 buffered 的**代价** (此前字段头只写好处):整轮回答憋到上游流结束才一次性吐、期间只发 ping → 模型越慢越像卡死(客户端可能报 Stream idle timeout - no chunks received), 且 CC 的 steering 失效;想要真流式设为 false(热更即时生效)。 注意:本次只改默认值,不影响已显式写了 ccAutoBuffer 的现有部署。
项目已刻意把 AI 助手相关文件排除在公开 repo 外(.claude/ 标注为 「Claude Code agent 配置/记忆(本地私有,不公开)」,PROMPT.md / PROMPT-*.md / docs/PROMPT-* 同样在排除列表)。项目级 CLAUDE.md 属完全同一类(AI 助手导航文件), 371 个历史提交里从未被跟踪,此处补上 ignore 规则使其显式化,避免后续误提交。
- OpenAI chat/completions路径: reasoning_effort → output_config.effort - OpenAI responses API路径(Codex): reasoning.effort → output_config.effort - converter层: GPT系列模型(sol/terra/luna)生成<effort>LEVEL</effort>标签 - 支持任意effort值透传(low/medium/high/xhigh/max等) - none值触发disabled模式并注入<effort>low</effort>抑制推理 - has_thinking_tags扩展支持<effort>标签识别防重复 - 添加debug级别日志记录effort标签注入 - 流式响应新增thinking_chars_total计数用于监控思考完整度 - Claude模型保持原有<thinking_mode>机制不变 经端到端测试验证: - gpt-5.6-sol/luna/terra全系列支持 - Codex responses API路径正常 - max档位比low多15-40%输出tokens(问题难度相关) - 流式/非流式均正常
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
为 GPT 系列模型(sol/terra/luna)实现完整的思考等级参数透传,使客户端可通过
reasoning_effort参数控制推理深度。修改内容
OpenAI 入站层 (
src/openai/convert.rs)reasoning_effort→output_config.effortreasoning.effort→output_config.effortAnthropic 转换层 (
src/anthropic/converter.rs)generate_thinking_prefix():GPT 系列模型生成<effort>LEVEL</effort>标签none值触发 disabled 模式并注入<effort>low</effort>抑制推理has_thinking_tags()扩展支持<effort>标签识别防重复注入<thinking_mode>机制不变流式处理 (
src/anthropic/stream.rs)thinking_chars_total字段追踪思考内容累计字符数请求处理 (
src/anthropic/handlers.rs)override_thinking_from_model_name不再覆盖用户已指定的 output_config测试验证
实测数据
max 档位比 low 多 ~18% 输出,推理更详细完整。