把开源代码审查工具接上百炼:踩坑记录 + 一次 PR 账单

最近在搞

上周刷 GitHub 看到阿里开源的 open-code-review(CLI 名 ocr)冲上了 Trending 本周 #1,一周涨了 15,028 颗星。Apache-2.0,Go 原生二进制,内置 28 个 LLM provider,其中就包含百炼的 dashscope。装了一台机器想试试,顺手把接百炼的坑和 PR 的账单都记下来。

环境踩坑记录

坑一:非交互式配置没有 flag

网上能找到的教程不少写了 ocr config provider --name xxx --base-url xxx。实际上 ocr config provider 和 ocr config model 是纯交互式 TUI,cobra.NoArgs,没有任何 flag。grep Flags\(\)|StringVar|BoolVar|IntVar 零命中。

非交互式的唯一路径是 ocr config set <key> <value>:

ocr config set provider dashscope
ocr config set model qwen3.8-max
ocr config set providers.dashscope.api_key sk-你的key

交互式的好处是走完会自动跑一次 ocr llm test 验证连通性,非交互式要自己手动跑。

坑二:只 export DASHSCOPE_API_KEY 不够

环境变量只补 key 那一份。ocr 的 resolver(internal/llm/resolver.go:149)要求完整的(URL、token、model)三元组。光 export 环境变量,另外两份还得靠 config 文件。

我一开始也只 export 了,卡在 ocr llm test 上半天。config 文件路径是 ~/.opencodereview/config.json,字段名是 provider、model、providers.dashscope.api_key,写错一个就废。

配置字段名也容易搞混:url 不是 base_url,model 是字符串(生效的模型),models 是数组(仅供 TUI 选择器用)。内置 provider 的 URL 挂在 providers.<name>.url,自定义 provider 在 custom_providers.<name>.url,两个不同的 map。

坑三:Anthropic 兼容端点 + thinking 模式 → 400

社区 issue #1064 有人报了:走百炼的 Anthropic 兼容端点,开着 thinking 模式,ocr 调 tool_choice=required 时收到 400 Bad Request。报错信息是 "The tool_choice parameter does not support being set to required or object in thinking mode"。

这个 issue closed 了但没有维护者评论,我没法断言已经修了。目前最稳的路径是走内置的 OpenAI 兼容端点,别自己改 Anthropic 兼容端点。

坑四:--page-size 100 静默返空

用百炼 CLI 批量查价的时候发现的。bl model list --page-size 20 正常,--page-size 100 返回 items: [] 还不报错。--output 也是,只接受 text 和 json,写错静默回落 text。

写脚本查价要对返回条数做断言,不然得出"这个模型不存在"的错误结论。还有一个坑:bl model list 返回的模型族有 179 个,但 --page-size 超过内部上限就静默返空。

坑五:flash 名字不承诺快

qwen3.8-flash 单价 ¥0.8/2.7(输入/输出,元每百万 token),看着是便宜档。但它默认就在深度思考,实测一次审 64 行代码烧了 12,909 个输出 token、跑了 241 秒、花 ¥0.0353,是 qwen-plus 的 9 倍。

3.8 这一代的 flash,名字里那点"快"已经不作数了。选档要看它会不会思考、思考多少,别只看名字和单价。

坑六:跨地域的 401

百炼的 API Key 是按地域绑定的。北京地域创建的 Key,拿去调新加坡或弗吉尼亚端点,返回 401。各地域端点:

地域 Base URL
北京(旧) https://dashscope.aliyuncs.com/compatible-mode/v1
北京(工作空间) https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1
弗吉尼亚 https://dashscope-us.aliyuncs.com/compatible-mode/v1
新加坡 https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1

如果已经迁移到工作空间专属域名,用 ocr config set providers.dashscope.url 覆盖。注意 Base URL 以 /compatible-mode/v1 结尾,不包含 /chat/completions。

关于 OCR 是什么

补充一点背景。alibaba/open-code-review 是 Go 原生的代码审查工具,Apache-2.0,通过 npm 分发(@alibaba-group/open-code-review),支持 macOS/ Linux/Windows 多平台。它不走静态分析路线,而是把代码变更喂给大模型,让模型通过 tool calling 来"读懂代码再挑刺"。

这意味着模型必须原生支持 function calling。不是"能在文本里描述工具调用",而是真的通过 function calling 协议完成交互。这也是为什么 FAQ 明确说了 deepseek-r1 不能用——它只在 <think> 块里假装调用,实际并没有。

另一个容易被忽略的工程事实:社区有人实测 1,400 个 PR 跑了十多个小时,几行改动的小 PR 也要几分钟。它不是 pre-commit 工具,适合挂在 PR 合并门禁或者离线批量跑。

模型硬要求:必须支持 function calling

OCR 的审查完全靠 tool calling 驱动。模型必须原生支持 function calling,否则不管怎么调 prompt 都跑不通。官方 FAQ 点名 qwen3 可用。

百炼侧可以通过 bl model list --model <模型名> --output json 查看 features 字段是否包含 function-calling,这条命令免登录。

内置的 dashscope provider 预置模型列表前 5 个全是 qwen:qwen3.8-max、qwen3.7-max、qwen3.7-plus、qwen3.6-plus、qwen3.6-flash。另外还有 deepseek-v4-pro、kimi-k2.7-code、glm-5.2 等第三方模型,function-calling 支持情况要逐一确认。

账单怎么算的

同一份 64 行 Python 订单服务代码(埋 4 个真缺陷 + 2 个诱饵),同一个 prompt,7 个 qwen 模型各审一遍。

单价取自 bl model list --model <模型> --output json,免登录就能查。token 是 API 原样返回的 usage,耗时是客户端墙钟。每组只跑一次,没有重复取样。得分 = 抓到数 − 误报数,满分 4。

这个实验的设计要点是只变一个变量:模型。prompt 逐字节相同,输入文件相同,max_tokens 固定。唯一变化的是不同模型的 tokenizer 会导致输入 token 数略有差异(464 到 540 之间),但这不影响结论方向。

值得提前说明的是 reasoning token 不计入 max_tokens 限制。所以设置了 4096 的 max_tokens,旗舰档还是返回了 11,064 个完成 token,其中 9,770 个是思考。这是平台行为,不是 bug。

模型 思考 token 抓到/4 漏报 误报 得分 耗时 审一次 ¥
qwen-turbo 不思考 2/4 2 4 -2.0 7.4 秒 0.0007
qwen3-coder-plus 不思考 3/4 1 1 2.0 10.1 秒 阶梯计费,见控制台
qwen-plus 不思考 2/4 1 1 1.5 39.3 秒 0.0039
qwen3.7-plus 1,182 4/4 0 0 4.0 23.4 秒 见控制台
qwen3.6-flash 4,258 4/4 0 1 3.0 42.6 秒 见控制台
qwen3.8-flash 9,517 4/4 0 0 4.0 241.0 秒 0.0353
qwen3.8-max 9,770 4/4 0 0 4.0 293.1 秒 0.4048

三处"见控制台"不是留白:qwen3-coder 系列官方文档写明"采取阶梯计费",qwen3.7-plus、qwen3.6-flash 在 bl model list 里没返回单价。查不到我就不编。

三条规律

第一条,满分不需要旗舰。qwen3.7-plus 用 23.4 秒拿满分,qwen3.8-max 也满分但花了 293 秒。多出来的 8,588 个思考 token 和 270 秒在这份代码上没换来分数,但多报了三个我没埋的真问题——包括 amount <= 0 拦不住 float('nan') 这个 corner case。

第二条,分水岭是会不会思考。三个不思考的模型全部有漏报(-2.0、2.0、1.5),四个会思考的零漏报。但思考量过了 1,182 就不再换分。

第三条,便宜档的行号不能信。

模型 行号对了几条
qwen-turbo 0 / 9
qwen-plus 0 / 4
qwen3-coder-plus 1 / 5
qwen3.6-flash 2 / 5
qwen3.7-plus 6 / 6(±1)
qwen3.8-flash 全对
qwen3.8-max 全对

turbo 把 SQL 注入报在第 9 行(实际第 18 行),空指针报在第 10 行(实际第 13 行)。描述对,位置错。便宜档输出当线索清单用,拿着描述自己找。

有意思的一个观察:qwen-plus 漏了空指针,qwen3-coder-plus 漏了竞态,两个便宜档漏的正好不重叠。各跑一遍交叉看能补盲区,但误报也会叠加,得人复核。样本只有 7 组,这是观察不是结论。

换算成能感知的单位

模型 审一次 1 块钱能审 审 100 次 每天 10 次 × 22 天
qwen-turbo ¥0.0007 ≈1,345 次 ¥0.07 ¥0.16
qwen-plus ¥0.0039 ≈256 次 ¥0.39 ¥0.86
qwen3.8-flash ¥0.0353 ≈28 次 ¥3.53 ¥7.76
qwen3.8-max ¥0.4048 ≈2 次 ¥40.48 ¥89.05

单价差 40 倍(输入 ¥0.3 vs ¥12),单次总账差 545 倍。算钱用 Decimal,Python 的 round() 是银行家舍入,账单会对不上。

from decimal import Decimal, ROUND_HALF_UP
def cost(in_tok, out_tok, price_in, price_out):
    c = (Decimal(in_tok) * Decimal(price_in) + Decimal(out_tok) * Decimal(price_out)) / Decimal(1000000)
    return c.quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP)

跑起来要几步

装工具(需要 Node.js 和 Git ≥ 2.41):

npm install -g @alibaba-group/open-code-review

领 API Key:控制台密钥管理页。

三行配置 + 验证:

ocr config set provider dashscope
ocr config set model qwen3.7-plus
ocr config set providers.dashscope.api_key sk-你的key
ocr llm test

然后 ocr review 审工作区变更,ocr scan --path 任意目录 扫文件。

免费额度可用于白跑一遍:每模型独立、通常 100 万 Token、90 天有效期、仅华北2(北京)地域、过期不补发、用尽不会自动切换。

想自己查模型目录和单价,装阿里云百炼 CLI(bl),bl model list 这条命令免登录。

适用边界

  • 不适合 pre-commit:社区实测 1,400 个 PR 跑十多个小时,几行改动的小 PR 也要几分钟
  • 不替代静态扫描:规则引擎报确定命中的模式,它报读懂代码后觉得不对的地方
  • 已有 Copilot / CodeRabbit 且用得顺手的,不需要换

每组只跑一次的局限性也得说清,同一模型跑两次得分会变。以上结论限定在这一次实测、这一份代码上。

posted @ 2026-09-21 09:44  新的白白酱  阅读(27)  评论(0)    收藏  举报