Repository navigation
Conversation
GPT-6 Astra 自动代码审查审查提交: 由 Codex 定时任务使用 GPT-6 Astra 子 agent 审查,并经主 agent 复核。 [P2] 不要将含可选属性的 Anthropic schema 原样设为 Responses 严格模式位置:src-tauri/src/proxy/providers/transform_responses.rs:65 当 output_config.format.schema 含有未列入 required 的可选属性时,这里直接复制 schema 并默认 strict=true,会生成 OpenAI Responses 不接受的结构化输出配置。Anthropic 明确支持可选属性,而 OpenAI 严格模式要求所有属性都在 required 中。因此合法的 Anthropic 请求会因本次新增的 text.format 被上游拒绝;新增测试仅覆盖全部属性必填的 schema,未覆盖这一协议差异。Anthropic 文档;OpenAI 文档。 证据:离线测试 review_repros::optional_anthropic_property_is_emitted_as_invalid_strict_schema 直接运行从 HEAD 原样提取的映射函数。输入为 properties={name:string,notes:string}、required=[name]、additionalProperties=false,输出仍为 required=[name] 且 strict=true。OpenAI 官方文档明确说明不符合严格模式约束的 schema 会报错。调用方 anthropic_to_responses 在 1896-1898 行直接发送该映射结果;BASE 对应位置未生成 text.format。 建议:转换前检查两套 schema 支持子集的差异,对可选属性实施能保留客户端语义的兼容处理,不要只添加 strict=true;对无法等价转换的 schema 明确处理。增加顶层及嵌套可选属性的回归测试。 [P2] 不要把请求级采样参数拒绝永久缓存为整条路由的能力位置:src-tauri/src/proxy/responses_compat.rs:160 这里把任何匹配 error.param 的 400/422 都缓存为后续请求必须删除该字段,但拒绝可能仅与本次推理模式或参数值有关。例如同一 GPT-5.2 路由先发送 high 推理请求并触发 temperature 回退,再发送关闭 thinking 的请求,第二次本来支持的 temperature 仍会被静默删除,直到进程重启。官方文档说明 GPT-5.2 的 temperature/top_p 支持取决于 reasoning.effort 是否为 none,而非仅取决于模型。OpenAI 参数兼容性文档。 证据:离线测试 review_repros::reasoning_rejection_leaks_into_non_reasoning_request 使用原始缓存模块和原样提取的路由键、reasoning 解析函数:首个请求 output_config.effort=high 的模拟上游返回 400/unsupported_parameter/temperature;第二个请求 thinking.type=disabled、temperature=0.2 的实际发送体变成 {model:claude-sonnet-4-6,thinking:{type:disabled}}。transform.rs:108-154 对 disabled 返回 None,transform_responses.rs:1885-1890 因而不注入 reasoning,使用 GPT-5.2 默认 none。另一个复现 value_validation_error_poisons_later_valid_temperature 确认 invalid_value 错误也被当作能力拒绝,随后合法的 0.2 同样被删除;optional_param_from_error 在 127-128 行仅检查 param,不检查错误原因。 建议:将当前请求的降级重试与跨请求能力缓存分开。只对明确、无条件不支持字段的错误记录路由能力;请求条件导致的拒绝应按最终推理配置等条件隔离,普通参数值校验错误应原样返回。增加同模型 high→disabled 及非法值→合法值的连续请求测试。 [P2] 使用实际出站模型和目标地址隔离兼容缓存位置:src-tauri/src/proxy/forwarder.rs:1184 缓存键在模型映射和 URL 解析之前构建,记录的是客户端别名及 /v1/messages,而不是实际出站模型和上游地址。用户在同一供应商卡片中修改模型映射或上游地址后,provider.id 和客户端别名不变,旧上游的采样字段禁用记录仍会应用到新上游。例如先把 claude-sonnet-4-6 映射到不支持 temperature 的模型,再改映射到支持该参数的模型,后者的 temperature 会在首次请求前就被删除。进程级缓存没有配置更新失效机制,因而这不是一次额外重试,而是持续改变新路由的请求语义。 证据:离线测试 review_repros::upstream_model_change_reuses_old_model_omissions 原样提取这里的键构造代码,并调用完整的 HEAD model_mapper 模块。相同 provider.id、入站 model=claude-sonnet-4-6,先后设置 ANTHROPIC_DEFAULT_SONNET_MODEL=o3 和 gpt-4o,两个键完全相等;首个模拟上游协商删除 temperature 后,第二次实际映射结果为 {model:gpt-4o},丢失传入的 temperature=0.2。实际 forward 在 1297-1305 行才应用模型映射,在 1555 行附近才生成目标 URL。ProviderService::update 在 5535 行保存同一 ID 的新配置,未清理本模块的 OnceLock 缓存。 建议:在最终模型、实际 API 格式及上游目标解析完成后生成能力缓存键,并在供应商相关配置变化时隔离或失效旧记录。增加同一供应商修改模型映射和 base URL 后保留新路由采样参数的回归测试。 验证与范围已完整审查指定 BASE...HEAD 的全部四个文件 diff,以及参数兼容缓存、schema 转换、模型映射、协议/URL 解析、请求覆写、四处重试调用、错误分类和供应商更新的关键上下文与相关测试。确认 3 条 P2 发现:结构化 schema 的严格模式兼容性、请求级拒绝污染跨请求能力缓存、入站路由键导致上游配置变更后复用旧删除记录。离线 29 项测试完成,审查 worktree 保持干净。
未验证或受限范围:
本评论仅针对以上提交的代码审查结果,不构成合并批准。 |
|
已在
|
1 similar comment
|
@farion1231 已同步变基至最新 v4.0.4 主线。修复 Responses 路由在不支持可选参数(如 temperature/top_p)报错时的过滤重试与 output_config 映射,分支无冲突且 CI 全绿,方便时麻烦审阅一下,谢谢! |
|
@farion1231 顺便跟最新 main 合过了,CI 检查全绿。等手头发版节奏放缓了再看看哈! |
Map Anthropic output_config.format to Responses text.format and negotiate unsupported temperature/top_p omissions through bounded, same-route retries. Cache negotiated omissions by provider, endpoint, model, and API format. Signed-off-by: Xingqiu Xu <hilbertanjou83@gmail.com>
Enable strict Responses schemas only when eligible, retry only explicit unsupported-parameter errors, and key negotiated omissions by the final endpoint, model, and reasoning mode. Signed-off-by: Xingqiu Xu <hilbertanjou83@gmail.com>
3f89027 to
3a56b8e
Compare
Summary
output_config.formatto Responsestext.format, including the format name and strict JSON Schema semantics required by the Responses API.400/422responses whoseerror.paramis a safely omittable sampling field (temperatureortop_p), retry on the same provider, endpoint, model, and API format without that field.Tests
cargo test --manifest-path src-tauri/Cargo.toml --lib: 2911 passed, 0 failed, 9 ignoredcargo fmt --all --manifest-path src-tauri/Cargo.toml -- --checkcargo clippy --manifest-path src-tauri/Cargo.toml --lib --tests: completed successfully with one pre-existing, unrelated warning outside this changeFixes #6394