# 0010: `openai-rs` vs `openai-node` 当前差距复评
日期:`2026-04-09`
## 1. 结论先行
- 如果把 `openai-node` 当成 `100` 分的成熟基线,`openai-rs` 当前综合可以给到 **`86 / 100`**。
- 相比上一轮 [0008.md](./0008.md) 的 **`83 / 100`**,本轮我认为可以上调到 **`86 / 100`**。
- `openai-rs` 现在已经明显跨过了“玩具 SDK / 只能演示”的阶段,处在 **“可以正式使用,但还没到官方 SDK 那种成熟度”** 的区间。
- 它和 `openai-node` 的核心差距,已经不主要是“有没有这个功能”,而是:
- 长尾 API 的强类型完整度
- 回归测试广度与生态兼容验证
- 规格驱动 / codegen 驱动的长期对齐能力
- 面向陌生用户的发布成熟度与稳定预期
一句话判断:
- **从团队内部或熟悉 Rust 的用户视角看,`openai-rs` 已经能用了。**
- **从“能否像 `openai-node` 一样长期对外、让陌生用户直接放心接入生产”看,还差一轮系统性补强。**
## 2. 本轮核对范围
本次评审同时看了两边的:
- 公开资源面与能力覆盖
- 主链路可用性
- 流式 / Realtime / Tool Runner
- Provider / Azure / OpenAI-compatible 兼容
- 测试广度、测试深度、生态验证方式
- README / examples / 文档主题
- 代码质量、类型质量、结构可维护性
- CI / 发布 / breaking change / packaging 工程化
本次结论以本地仓库实际代码与命令结果为准,不直接复用旧结论。
## 3. 本轮实测事实
### 3.1 `openai-rs`
本地已实际跑通:
- `cargo test --all-features`
- `cargo test --no-default-features`
- `cargo fmt --all -- --check`
- `cargo clippy --all-targets --all-features -- -D warnings`
- `cargo check --examples --all-features`
- `bash ./scripts/check-public-api.sh`
- `cargo deny check`
结果:
- 以上命令全部通过。
- `cargo deny check` 有重复依赖告警,但 `advisories / bans / licenses / sources` 全部通过。
- `provider_live` 测试存在且结构化,默认是 `ignored`,说明项目已经具备真实 provider 验证能力,但默认仍以“手动触发、带成本”的方式运行。
### 3.2 `openai-node`
本地已实际跑通:
- `yarn install --frozen-lockfile`
- `./scripts/lint`
结果:
- `lint` 全通过,且不仅是 ESLint。
- 它实际覆盖了 `build`、`tsc`、`Are The Types Wrong?`、`publint`、`JSR dry-run`,工程化成熟度很高。
本地还实际执行了:
- `./scripts/test`
结果:
- 在当前本地环境下,该命令 **失败**。
- 失败形态不是 SDK 断言失败,而是测试过程中 Steady mock server 中途掉线,导致大量用例报:
- `ECONNREFUSED 127.0.0.1:4010`
- 当前本地 `node` 版本为 `v24.12.0`。
- `openai-node/.github/workflows/ci.yml` 明确固定使用 `Node 20`。
因此,本轮对 `openai-node` 的判断:
- **工程链路本身仍按 `100` 分成熟基线看待**
- **本地 `./scripts/test` 的失败记为环境信号,不记为 SDK 质量回退**
## 4. 量化快照
> 这些统计是事实快照,不是直接等于质量评分。
| `src` 文件数 | `236` | `43` | Rust 更轻,但也更依赖手写聚合 |
| `tests` 文件数 | `79` | `28` | Rust 比上一轮明显增加,但仍落后 |
| 测试函数数 | `535` | `149` | Rust 主链路覆盖已成型,广度仍不足 |
| `examples` 文件数 | `49` | `42` | 主题差距已经不大 |
| `ecosystem-tests` 文件数 | `118` | `0` | Node 明显更强 |
| GitHub workflows | `6` | `3` | Rust 已不再是只有单一 CI |
| `src + tests + examples + workflows` 总行数 | `139600` | `26227` | Rust 仍是更轻量实现 |
| 公开 `JsonRequestBuilder<Value>` 暴露点 | 很少作为公开主入口暴露 | `18` | 这是 Rust 端主要 API 质量短板 |
| 公开 `ListRequestBuilder<Value>` 暴露点 | 很少作为公开主入口暴露 | `4` | 长尾资源仍偏原始 |
| codegen / 规格驱动 | 明确使用 OpenAPI + Stainless | ADR 已接受,但尚未落地 | 维护风险差距的关键来源 |
额外事实:
- `openai-node` README 明确声明自己是从 OpenAPI 规格经 Stainless 生成。
- `openai-rs` 已有 [docs/adr/0001_codegen_strategy.md](../docs/adr/0001_codegen_strategy.md),但当前仓库里还没有真正落地的生成层。
- `openai-node` 有 `ecosystem-tests`。
- `openai-rs` 有跨平台 / MSRV / feature matrix 的 Rust CI,这一点比很多早期 Rust SDK 更成熟。
## 5. 相比上一轮的变化
和 [0008.md](./0008.md) 相比,本轮 `openai-rs` 的正向变化是实打实的:
- `examples` 从 `34` 提升到 `42`
- `tests` 从 `16` 提升到 `28`
- workflow 从 `1` 提升到 `3`
- 本地已验证通过:
- `all-features`
- `no-default-features`
- `clippy -D warnings`
- `examples`
- `public-api`
- `cargo deny`
所以这次我不会沿用 `83` 分,而是上调到 `86` 分。
## 6. 评分总表
> 评分口径:`openai-node = 100`。
| 功能覆盖 | `100` | **`95`** | 资源面已经很接近,差距主要不在“有没有”而在“够不够 typed” |
| 主链路可用性 | `100` | **`90`** | Chat / Responses / Files / Audio / Webhook / SSE / WS 都可用 |
| 流式 / Realtime / Tool Runner | `100` | **`89`** | 已有 contract 与 websocket 测试,但 battle-tested 程度仍弱于 Node |
| Provider / Azure / 兼容层 | `100` | **`92`** | 这是 `openai-rs` 的强项之一 |
| 测试广度 | `100` | **`79`** | 有明显进步,但仍没有 Node 那种资源级和生态级密度 |
| 测试深度 | `100` | **`83`** | 有 snapshot / retry / parser / websocket / live,但缺 property/fuzz/spec-driven 验证 |
| 文档 / Examples | `100` | **`91`** | 主题已很接近,运行时专题仍少于 Node |
| 类型质量 / API 人体工学 | `100` | **`80`** | 仍有一批对外 `Value` builder 与 `Value` 字段 |
| 代码质量 | `100` | **`88`** | `unsafe` 禁止、`clippy`、`deny`、`public-api` 都很扎实 |
| 可维护性 | `100` | **`82`** | 主要差在手写聚合较重、尚未 codegen 化、`Value` 聚集较多 |
| 工程化 / 发布成熟度 | `100` | **`84`** | 已经不弱,但仍少 breaking-change / ecosystem / 自动发布这一级别能力 |
### 综合评分
- **`openai-rs` 当前综合:`86 / 100`**
我的判断标准是:
- 这个分数已经足以说明它不是“还不能用”的项目。
- 但它也还没有达到 `openai-node` 那种“功能、测试、规格对齐、发布链路都非常稳定”的状态。
## 7. 分方向评审
### 7.1 功能覆盖:`95 / 100`
`openai-rs` 现在的顶层资源面已经几乎和 `openai-node` 对齐,包括:
- `completions`
- `chat`
- `embeddings`
- `files`
- `images`
- `audio`
- `moderations`
- `models`
- `fine_tuning`
- `graders`
- `vector_stores`
- `webhooks`
- `batches`
- `uploads`
- `responses`
- `realtime`
- `conversations`
- `evals`
- `containers`
- `skills`
- `videos`
- `beta`
这意味着:
- 如果只问“`openai-node` 现在能做的大块事情,`openai-rs` 有没有对应入口”,答案基本已经是“有”。
当前剩余差距主要不是纯功能缺口,而是这些入口里仍有一些是“能打到接口,但公开形态不够好”的状态。
### 7.2 主链路可用性:`90 / 100`
从本轮实测看,`openai-rs` 的主链路已经非常稳:
- `cargo test --all-features` 通过
- `cargo test --no-default-features` 通过
- `cargo check --examples --all-features` 通过
这说明它不只是“接口堆齐了”,而是:
- 默认 feature 组合能工作
- 全 feature 组合能工作
- examples 至少编译层面是通的
我不给更高分的原因是:
- live provider 测试仍默认 `ignored`
- 真正的线上行为长期稳定性,还没有像 `openai-node` 一样被大规模生态使用和持续回归验证
### 7.3 流式 / Realtime / Tool Runner:`89 / 100`
这一项 `openai-rs` 已经不弱:
- SSE
- Responses runtime event
- Assistant stream
- Realtime WebSocket
- Responses WebSocket
- structured output
- tool runner
都已经在工程里有明确实现和测试。
扣分点主要在“边角稳定性”:
- `openai-node` 有针对 partial JSON parser 的 property-based 测试
- `openai-rs` 虽然已经引入 `proptest` 作为 dev-dependency,但当前仓库里并没有真正使用它
- `openai-rs/src/stream/partial_json.rs` 当前只有较小规模的单元测试,不是系统性随机输入验证
这类差距不会立刻让功能不可用,但会影响“极端事件序列下的信心”。
### 7.4 Provider / Azure / 兼容层:`92 / 100`
这是 `openai-rs` 的加分项。
从仓库结构和测试组织看,它对这些场景的重视程度很高:
- OpenAI
- Azure OpenAI
- Zhipu
- MiniMax
- ZenMux
而且不只是 README 写了支持,而是真的有:
- `tests/provider_live/*`
- `.github/workflows/live.yml`
- `tests/azure.rs`
所以如果你的目标是:
- OpenAI 官方接口
- Azure
- 多家 OpenAI-compatible provider
那么 `openai-rs` 的实用价值其实比很多“只会调 OpenAI 一家”的 Rust SDK 更高。
### 7.5 测试广度:`79 / 100`
这是 `openai-rs` 目前最清楚的弱项之一。
虽然 Rust 端测试已经明显比上一轮多,但和 `openai-node` 相比,仍有三个硬差距:
1. 资源级测试拆分密度不够
2. 内部协议层专题不够多
3. 缺少生态级兼容矩阵
直接对比:
- `openai-node/tests`:`79` 个文件
- `openai-rs/tests`:`28` 个文件
- `openai-node` 测试函数:`535`
- `openai-rs` 测试函数:`149`
Rust 端已经有这些专项:
- `retry_timeout`
- `logger`
- `path_query`
- `uploads`
- `parser`
- `azure`
- `websocket`
- `snapshots`
- `provider_live`
但 Node 端仍明显更细,且 `api-resources/*` 基本按资源逐个拆开。
### 7.6 测试深度:`83 / 100`
这一项 `openai-rs` 比“广度”好一些,因为它并不只是写了浅层 smoke test。
它已经有:
- snapshot tests
- websocket contract tests
- retry / timeout tests
- logger tests
- path / query tests
- upload tests
- parser tests
- provider live tests
这说明它在“工程内自证能力”上已经建立起骨架了。
但还欠三块更硬的验证:
- property-based tests
- fuzz / fault injection
- spec-driven mock validation
Node 端的代表信号是:
- `tests/_vendor/partial-json-parser/partial-json-parsing.test.ts` 用 `fast-check`
- `scripts/test` 依赖 Steady mock server 直接对 OpenAPI 规格做验证
Rust 端目前主要还是 `wiremock` 驱动的 focused contract tests,这很实用,但还不是“规格对齐型”回归。
### 7.7 文档 / Examples:`91 / 100`
这项差距已经不大了。
本轮统计:
- `openai-node/examples`:`49`
- `openai-rs/examples`:`42`
Rust 端已经覆盖了绝大多数关键主题:
- chat
- responses
- stream
- realtime
- tool runner
- parsing
- structured outputs
- webhook verification
- Azure
- files
- audio
- pagination
- logging
剩余差距主要在更细的运行时专题:
- browser / express / next 风格的 stream-to-client 示例
- 更接近 Node helper 形态的 tool helper 变体
- 一些 Node 生态特有的 runtime 示例
所以这一项我认为已经是“接近齐了”,不是主要短板。
### 7.8 类型质量 / API 人体工学:`80 / 100`
这是现在 `openai-rs` 和 `openai-node` 最本质的差距之一。
`openai-rs` 不是没有 builder,也不是没有 typed API;它的问题是:
- 核心链路 typed 得不错
- 长尾资源 typed 得不够均匀
本轮直接能看到的公开原始暴露点包括:
- `src/resources/core.rs`
- `completions.create() -> JsonRequestBuilder<Value>`
- `moderations.create() -> JsonRequestBuilder<Value>`
- `src/resources/responses.rs`
- `input_items.list() -> ListRequestBuilder<Value>`
- `realtime.client_secrets.create() -> JsonRequestBuilder<Value>`
- `realtime.calls.*() -> JsonRequestBuilder<Value>`
- `src/resources/uploads.rs`
- `uploads.parts.create() -> JsonRequestBuilder<Value>`
- `src/resources/fine_tuning.rs`
- `alpha.graders.run() -> JsonRequestBuilder<Value>`
- `alpha.graders.validate() -> JsonRequestBuilder<Value>`
- `graders.grader_models() -> JsonRequestBuilder<Value>`
- `src/resources/beta.rs`
- `beta.chatkit.*`
- `beta.realtime.sessions.*`
- `beta.realtime.transcription_sessions.*`
此外,公开结构体里也还存在很多:
- `Option<Value>`
- `Vec<Value>`
- `BTreeMap<String, Value>`
主要集中在:
- `src/resources/longtail.rs`
- `src/resources/mod.rs`
- `src/resources/beta.rs`
这不会让功能不能用,但会直接影响:
- IDE 自动补全
- 编译期约束
- 文档可发现性
- 用户写错参数时的提早失败能力
### 7.9 代码质量:`88 / 100`
如果只看工程纪律,`openai-rs` 其实做得相当好:
- `#![forbid(unsafe_code)]`
- `cargo fmt`
- `clippy -D warnings`
- `cargo deny`
- `public-api` 基线检查
- feature gating
- examples 检查
- docs.rs 风格文档构建
这些都是真正能提高外部信心的信号。
我不给更高分,不是因为代码“脏”,而是因为:
- 仍然有较多 `Value` 暴露
- 手写维护比例偏高
- 规格对齐能力还没有像 Node 那样通过生成链路固化
### 7.10 可维护性:`82 / 100`
这项比代码质量低,因为维护性看的是未来成本。
当前最明显的结构问题有两个:
1. 聚合文件仍较重
2. 尚未进入“generated layer + handwritten facade”模式
典型文件体量:
- `src/resources/longtail.rs`:`1703` 行
- `src/resources/mod.rs`:`988` 行
- `src/resources/chat.rs`:`954` 行
- `src/resources/beta.rs`:`832` 行
- `src/resources/responses.rs`:`708` 行
这些文件大小本身不是错误,但在“纯手写、资源面持续增长”的前提下,会让后续维护越来越依赖作者上下文记忆。
而 `openai-node` 的核心优势是:
- 它把“规格同步”和“大量重复资源形态”交给生成链路
- 手写层更多集中在 runtime / helper / stream / ergonomics
`openai-rs` 已经有这个方向的 ADR,但还没真正落地。
### 7.11 工程化 / 发布成熟度:`84 / 100`
这项是 `openai-rs` 本轮比上一轮提升最大的维度之一。
它现在已经有:
- `ci.yml`
- `live.yml`
- `release.yml`
而且 `ci.yml` 不是简单 smoke:
- Linux / macOS / Windows
- stable / MSRV
- default / no-default-features / all-features
再加上:
- `cargo deny`
- `cargo public-api`
- `cargo publish --dry-run`
- docs.rs 风格构建
这已经是一个相当认真维护的 Rust 库姿态了。
它仍落后于 `openai-node` 的地方主要在:
- breaking-change detection workflow
- release doctor
- ecosystem tests
- 自动发布与外部发布链路成熟度
## 8. 现在距离“真正可以用”还有多远
这里我把“真正可以用”拆成两个标准。
### 标准 A:团队内部 / 熟悉 Rust 的用户 / 有明确需求
结论:
- **已经可以用**
更准确地说:
- 这个标准下,`openai-rs` 大约在 **`90 / 100`** 左右
- 差距大概还剩 **`5` 到 `10` 分**
原因:
- 主功能面齐
- 测试不是空的
- examples 足够多
- 工程检查是全的
- Azure 和多 provider 支持是真正可用的
### 标准 B:公开库 / 陌生用户直接接入生产 / 需要长期稳定预期
结论:
- **还差一轮系统性补强**
更准确地说:
- 这个标准下,`openai-rs` 大约在 **`84` 到 `86 / 100`**
- 和 `openai-node` 的差距大约还剩 **`14` 到 `16` 分**
差距主要不是:
- “没有接口”
- “不能发请求”
- “主链路不通”
而是:
- 测试矩阵还不够厚
- 规格驱动对齐还不够自动化
- 长尾 API typed 程度还不够高
- 长期维护成本还没被 codegen / generated layer 进一步压下去
换句话说:
- **它已经过了“能不能用”这条线**
- **但还没过“官方级成熟度”这条线**
## 9. 主要差距清单
按优先级看,我认为现在的差距主要是这几类。
### P0
1. 公开 `Value` builder 仍然偏多,长尾 API typed 不够完整
2. 缺少 property-based / fuzz / spec-driven 测试
3. 没有真正落地的 codegen / generated layer
4. 缺少 Node 那种生态兼容级测试矩阵
### P1
1. `longtail.rs` / `mod.rs` / `beta.rs` / `responses.rs` 的维护集中度仍偏高
2. live provider 测试虽存在,但默认不参与常规回归
3. examples 已接近齐,但 cookbook 化和专题深度还可以继续加强
### P2
1. 依赖重复告警可以进一步清理
2. 可以继续增加更多 consumer-side 集成样例和微型 workspace fixture
## 10. 优化建议
下面这些建议是按“投入产出比”排的。
### 10.1 第一优先级:先补测试强度,不要先追求继续堆功能
建议立刻做:
1. 把 `proptest` 真正用起来
2. 先补这些主题:
- `src/stream/partial_json.rs`
- SSE line decoder
- websocket event decode
- path/query serializer
- provider error mapping
3. 在 `tests/` 下新增更细的协议级测试文件,而不是继续往现有大文件里塞
4. 引入一层更接近 OpenAPI 规格验证的 contract harness
目标收益:
- “测试深度”可从 `83` 提到 `87+`
- “主链路信心”会明显提高
### 10.2 第二优先级:消灭对外 `Value` builder
建议按下面顺序收敛:
1. `src/resources/core.rs`
- `completions.create`
- `moderations.create`
2. `src/resources/responses.rs`
- `input_items.list`
- `realtime.client_secrets.create`
- `realtime.calls.*`
3. `src/resources/uploads.rs`
- `uploads.parts.create`
4. `src/resources/fine_tuning.rs`
- `alpha.graders.*`
- `graders.grader_models`
5. `src/resources/beta.rs`
- `chatkit`
- `realtime.sessions`
- `realtime.transcription_sessions`
目标收益:
- “类型质量 / API 人体工学”可从 `80` 提到 `86+`
- 新用户的上手阻力会明显下降
### 10.3 第三优先级:把 ADR 里的 codegen strategy 真正落地
现在最值得做的,不是全面重写,而是局部落地:
1. 先引入 generated layer,只托管:
- schema
- 路由
- 基础请求 / 响应结构
2. 手写层只负责:
- Rust builder
- provider compatibility
- stream runtime
- structured output
- tool runner
3. 先从重复度最高的模块切入:
- `beta`
- `responses`
- `fine_tuning`
- `vector_stores`
目标收益:
- “可维护性”可从 `82` 提到 `88+`
- 新接口跟进速度会更稳
- 和 `openai-node` 的长期对齐能力会更强
### 10.4 第四优先级:补一层 Rust 语境下的 ecosystem test
Rust 不需要照搬 Node 的 browser / bun / deno 矩阵,但依然值得有自己的生态回归:
建议增加:
- `cargo nextest`
- 更多 feature-combo 的 consumer fixture
- 最小集成样例,例如:
- `tokio + reqwest`
- `axum webhook`
- `SSE passthrough`
- `websocket client`
如果能做到:
- 每个 fixture 都是独立可编译的小 crate
- 在 CI 里单独跑
那么这会是 Rust 世界里更合理的 “ecosystem tests”。
### 10.5 第五优先级:继续补发布成熟度
现在 `openai-rs` 的 release 基础已经不错了,下一步建议补:
1. breaking change 自动检测
2. schedule smoke live workflow
3. 更明确的 release note / changelog 检查
4. 可选地接入 `cargo-semver-checks`
目标收益:
- “工程化 / 发布成熟度”可从 `84` 提到 `89+`
## 11. 最终判断
我的最终判断是:
- **`openai-rs` 已经是一个可以认真使用的 Rust SDK**
- **它和 `openai-node` 的差距,已经不是功能面的大坑,而是成熟度层面的最后一段路**
如果把 `openai-node` 当成 `100` 分:
- `openai-rs` 当前大约是 **`86 / 100`**
如果只看“能不能做事”:
- 差距已经不大
如果看“能不能像官方 SDK 那样长期稳定、低风险、强预期地对外服务”:
- 还差 **类型完善 + 测试硬化 + codegen 落地 + ecosystem 验证** 这一整轮工程化补强
## 12. 优化后回归(2026-04-08)
> 本节覆盖并更新上文的 `86 / 100` 结论;当前以这里的回归结果为准。
这一轮我已经把上面列出的 P0 / P1 / P2 核心项尽量落到了代码里,并重新做了一次完整回归。
### 12.1 已完成的优化
#### P0:公开 `Value` builder 收敛
- 公开资源接口里的 `JsonRequestBuilder<Value>` / `ListRequestBuilder<Value>` 已从 **`22` 处降到 `0` 处**
- 已补齐或包装为 typed API 的方向包括:
- `completions.create`
- `moderations.create`
- `chat.completions.messages.list`
- `responses.input_items.list`
- `realtime.client_secrets.create`
- `realtime.calls.*`
- `uploads.parts.create`
- `fine_tuning.alpha.graders.run / validate`
- `graders.grader_models`
- `beta.chatkit.*`
- `beta.realtime.sessions.create`
- `beta.realtime.transcription_sessions.create`
#### P0:测试强度补强
- `proptest` 已真正落地,当前仓库里已有 **`7` 处** property-based 断言
- 新增:
- partial JSON property tests
- SSE line decoder property tests
- spec fixture 反序列化 contract tests
- typed endpoint contract tests
- 在补测试过程中,实际修掉了一个协议层 bug:
- **SSE line decoder 在 `\r\n` 跨 chunk 时会误拆分**
#### P0 / P1:codegen / generated layer 初步落地
- 已新增:
- `codegen/endpoints.json`
- `scripts/generate_endpoints.py`
- `src/generated/endpoints.rs`
- 目前 generated layer 先托管了高重复度路由目录,并接入了 CI 的 drift check
- 这还不是完整 schema/type codegen,但已经不再是“只有 ADR、没有落地”
#### P0 / P1:生态回归与工程化
- 已新增 **`5` 个** Rust consumer fixture crate:
- `tokio_responses_client`
- `axum_webhook`(当前用 webhook consumer fixture 形式落地)
- `realtime_client`
- `responses_ws_client`
- `structured_output_client`
- 已新增 `scripts/check-ecosystem.sh`
- CI 已新增或补强:
- generated endpoint catalog check
- ecosystem fixture check
- `cargo nextest`
- semver / breaking-change workflow
- scheduled live smoke workflow
- workflow 数从 **`3`** 个增加到 **`4`** 个
#### 额外修正
- 修复了 `chatkit` 端点错误复用 `assistants=v2` header 的问题,现在改为 `chatkit_beta=v1`
### 12.2 本次回归结果
本地回归结果如下:
| `cargo test --all-features` | 通过 | 包含新增 typed / spec / property tests |
| `cargo test --no-default-features` | 通过 | 最小特性面未回退 |
| `cargo nextest run --all-features` | 通过 | 与 CI 新增守门项一致 |
| `cargo fmt --all -- --check` | 通过 | |
| `cargo clippy --all-targets --all-features -- -D warnings` | 通过 | |
| `cargo check --examples --all-features` | 通过 | |
| `RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --all-features --no-deps` | 通过 | |
| `bash ./scripts/check-public-api.sh` | 通过 | 已同步更新 baseline |
| `python3 ./scripts/generate_endpoints.py --check` | 通过 | generated layer 已纳入 drift check |
| `bash ./scripts/check-ecosystem.sh` | 通过 | 5 个 fixture crate 均可离线编译 |
| `cargo deny check` | 通过 | 仍有 duplicate warnings,但无 advisory / ban / license / source 问题 |
### 12.3 更新后的评分
如果仍然以 `openai-node = 100` 为基线,我会把 `openai-rs` 的评分更新为:
| 功能覆盖 | `93` | **`94`** | 功能面本来就不差,这轮主要补成熟度,不是继续堆新端点 |
| 类型质量 / API 人体工学 | `80` | **`91`** | 对外 raw `Value` builder 已清零,typed surface 明显更稳 |
| 测试深度 | `83` | **`91`** | 新增 property / spec / typed contract / ecosystem fixture |
| 可维护性 | `82` | **`88`** | generated endpoint catalog 已落地,但还不是完整 schema codegen |
| 工程化 / 发布成熟度 | `84` | **`91`** | nextest / semver / scheduled smoke / ecosystem CI 都补上了 |
| 综合评分 | `86` | **`92`** | 已明显进入“对外认真使用”级别 |
### 12.4 现在距离“官方级长期稳定 SDK”还差多少
我的判断更新为:
- **现在已经不是“能不能用”的问题,而是“离官方级长期维护能力还有多少边角要磨”**
- 如果 `openai-node = 100`,那么 `openai-rs` 现在大约是 **`92 / 100`**
- 也就是还差大约 **`8` 分左右**
这 `8` 分主要还卡在:
1. generated layer 现在还是“路由目录 + 基础托管”的第一阶段,还没扩展到 schema / type 级别
2. 一些复杂对象内部仍然保留较多 `Value` 字段,typed surface 已改善,但 typed depth 还可以继续往下挖
3. ecosystem fixture 现在是 compile-check 为主,还没到 node 那种更重的跨运行时 / 更强集成矩阵
4. `cargo deny` 的 duplicate 依赖告警还没完全消掉
### 12.5 结论
优化后的结论是:
- **`openai-rs` 已经达到了可以认真对外使用的程度**
- **与 `openai-node` 的主要差距,已经进一步收缩到“完整 codegen 深度”和“长期生态级验证密度”**
- **如果后面再补一轮 schema/type codegen、继续下沉复杂对象类型、再把 ecosystem fixture 从 compile 扩到 runtime smoke,那么分数可以继续逼近 `95+`**
## 13. 第二轮剩余差距优化回归(2026-04-08)
> 本节覆盖第 `12` 节中的“还差约 8 分”判断;当前以这里的结论为准。
这一轮我专门针对上次剩余的三个差距继续收口:
1. `vector_stores` 仍有一批关键字段停留在 `Value`
2. ecosystem fixture 还只是 compile-check,不算真正 runtime smoke
3. `cargo deny` 虽然不失败,但还保留 duplicate warning 噪音
### 13.1 本轮实际完成的优化
#### A. `vector_stores` 继续下沉到更接近 `openai-node` 的 typed contract
- `VectorStore.file_counts`:`Option<Value>` -> **`Option<VectorStoreFileCounts>`**
- `VectorStore.metadata`:`Option<Value>` -> **`Option<VectorStoreMetadata>`**
- 新增:
- `VectorStoreExpiresAfter`
- `VectorStoreAttributes`
- `VectorStoreAttributeValue`
- `VectorStoreFileLastError`
- `VectorStoreFileChunkingStrategy`
- `VectorStoreStaticFileChunkingStrategy`
- `VectorStoreFileContent`
- `VectorStoreSearchResult`
- `VectorStoreSearchContent`
- `VectorStoreFilesResource::content()` 已从原始 `BytesRequestBuilder` 提升为:
- **`JsonRequestBuilder<Page<VectorStoreFileContent>>`**
- `vector_stores` 全命名空间已补齐 `openai-beta: assistants=v2` header helper
- 新增 typed regression,覆盖:
- vector store retrieve
- vector store file retrieve
- file content page
- vector store search result
- static chunking strategy 反序列化
一个重要信号是:`src/resources/vector_stores.rs` 里原先那些结构性 `Value` 字段已经被清掉,剩下的 `Value` 基本都是 `#[serde(flatten)] extra` 这类保留扩展位,不再是核心 contract 本身。
#### B. ecosystem fixture 从 compile-check 升级为 runtime smoke
- 新增本地 stub server:
- `scripts/ecosystem_smoke_server.py`
- `scripts/check-ecosystem.sh` 现在会:
- 先 `cargo check --offline`
- 再启动本地 fixture server
- 再逐个 `cargo run --offline`
- fixture 已补成真实运行断言:
- `tokio_responses_client`:真实发送 `responses.create()` 并校验输出
- `structured_output_client`:真实发送 `responses.parse()` 并校验结构化结果
- `realtime_client`:真实发送 `client_secrets.create()` 并校验 secret
- `axum_webhook`:使用有效签名样例做真实 webhook unwrap
这意味着它现在已经不是“只要类型能编译就算过”,而是能覆盖一层最小但真实的 runtime integration。
#### C. `cargo deny` duplicate warning 已清零
- 我没有去冒险改 `reqwest / rustls` 传输链路
- 而是把已确认无法在当前依赖面内消除的重复依赖,明确登记进 `deny.toml`
- 当前 `cargo deny check` 结果已经变成:
- **`advisories ok, bans ok, licenses ok, sources ok`**
- 无 duplicate warning 噪音
这一步的价值不是“依赖树 magically 变干净”,而是把“已知且可解释的外部生态重复”从 CI 噪音降成显式治理项。
### 13.2 本轮完整回归结果
本轮我重新执行的完整回归如下:
| `cargo test --all-features` | 通过 | 新增 vector store typed tests 在内 |
| `cargo test --no-default-features` | 通过 | 最小特性面未回退 |
| `cargo nextest run --all-features` | 通过 | `134 passed, 31 skipped` |
| `cargo fmt --all -- --check` | 通过 | |
| `cargo clippy --all-targets --all-features -- -D warnings` | 通过 | |
| `cargo check --examples --all-features` | 通过 | |
| `RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --all-features --no-deps` | 通过 | |
| `bash ./scripts/check-public-api.sh` | 通过 | 已同步更新 baseline |
| `python3 ./scripts/generate_endpoints.py --check` | 通过 | generated catalog 未漂移 |
| `bash ./scripts/check-ecosystem.sh` | 通过 | 已升级为 runtime smoke |
| `cargo deny check` | 通过 | duplicate warning 已清零 |
### 13.3 评分更新
如果继续以 `openai-node = 100` 为基线,这一轮之后我会把 `openai-rs` 的评分更新为:
| 功能覆盖 | `94` | **`95`** | 本轮不是加很多新端点,而是把 vector stores 的 contract 补完整 |
| 类型质量 / API 人体工学 | `91` | **`94`** | `vector_stores` 这块从可用提升到了明显更稳、更接近 node contract |
| 测试深度 | `91` | **`93`** | 多了 vector store typed regression 与 ecosystem runtime smoke |
| 可维护性 | `88` | **`90`** | `vector_stores` 类型分层更清晰,deny 噪音治理更明确 |
| 工程化 / 发布成熟度 | `91` | **`94`** | runtime smoke 与 clean deny 让 CI 信号更接近对外 SDK 的要求 |
| 综合评分 | `92` | **`94`** | 已进一步逼近“官方级长期维护 SDK”的下半区门槛 |
### 13.4 现在还差多少
我的最新判断是:
- 如果 `openai-node = 100`,那么当前 `openai-rs` 大约是 **`94 / 100`**
- 相比上一轮的 **`92 / 100`**,这次又补上了大约 **`2` 分**
- 离“真正官方级、长期稳定、陌生用户也能直接放心接入”的状态,现在大约还差 **`6` 分左右**
剩余差距主要集中在:
1. **schema/type codegen 仍然不够深**
- 现在的 generated layer 主要还是 endpoint catalog
- 真正要追平 `openai-node`,还需要把更多 schema/type generation 落地
2. **复杂对象内部仍有大量 `Value`**
- 当前最明显的存量集中在:
- `src/resources/mod.rs` 的 `Response / EmbeddingResponse / ChatCompletion` 一带
- `src/resources/beta.rs`
- `src/resources/longtail.rs`
- 也就是说,typed surface 已经明显变好了,但 typed depth 还没有完全追上
3. **ecosystem smoke 还属于“最小闭环”**
- 现在已经不是 compile-only 了
- 但离 `openai-node` 那种更重的跨运行时 / 更宽集成矩阵还有距离
### 13.5 最新结论
这一轮之后,我的结论更新为:
- **`openai-rs` 现在已经明显超过“可以用”,进入“可以认真对外推广和承接生产”的阶段**
- **和 `openai-node` 的差距,已经不再是基础可用性,而是深层 schema/codegen 与超宽生态验证密度**
- **下一轮如果继续往 `Response / beta / longtail` 的复杂对象里下沉类型,并把 generated layer 从 endpoint catalog 推到 schema/type 级别,综合分数有机会继续往 `95-96` 区间走**
## 14. 第三轮剩余差距优化回归(2026-04-09)
> 本节覆盖第 `13` 节中的“还差约 6 分”判断;当前以这里的结论为准。
这一轮我继续沿着上一节剩余差距收口,重点没有再去堆新端点,而是针对 `Response` / `Embedding` 这类核心 contract 的 typed depth 和 runtime verification 做补强。
### 14.1 本轮实际完成的优化
#### A. `Response` 核心 contract 继续下沉到 typed surface
- `Response.output`:`Vec<Value>` -> **`Vec<ResponseOutputItem>`**
- `Response.usage`:`Option<Value>` -> **`Option<ResponseUsage>`**
- `Response.error`、`incomplete_details`、`metadata`、`created_at` 已补成显式 typed 字段
- 新增并导出:
- `ResponseError`
- `ResponseIncompleteDetails`
- `ResponseUsage`
- `ResponseInputTokensDetails`
- `ResponseOutputTokensDetails`
- `ResponseOutputItem`
- `KnownResponseOutputItem`
- `ResponseOutputMessage`
- `ResponseFunctionToolCall`
- `ResponseOutputContentPart`
- `KnownResponseOutputContentPart`
- `ResponseOutputText`
- `ResponseOutputRefusal`
- 公开 API 已新增 typed helper:
- `ResponseOutputItem::as_message()`
- `ResponseOutputItem::as_function_call()`
- `ResponseOutputItem::as_raw()`
- `ResponseOutputItem::output_text()`
这一轮的关键点不是“彻底消灭所有 raw JSON”,而是把 `Response` 最常用、最核心、最影响 IDE 补全和编译期约束的那一层先收成 typed contract,同时保留 `Raw(Value)` fallback,避免对兼容 provider 或未知对象形态做过度假设。
#### B. `EmbeddingResponse` 继续收口
- `EmbeddingResponse.data`:`Vec<Value>` -> **`Vec<EmbeddingData>`**
- `EmbeddingResponse.usage`:`Option<Value>` -> **`Option<EmbeddingUsage>`**
- 新增并导出:
- `EmbeddingData`
- `EmbeddingUsage`
这一步的价值不只是“少几个 `Value`”,而是把 embeddings 这条高频主链路也从“能取字段”提升到“有稳定 contract”。
#### C. 流式聚合内部改为 raw snapshot,公开结果保持 typed
- `src/stream/responses.rs` 已新增内部 `RawResponseSnapshot`
- 对外 `ResponseStream::snapshot()` / `final_response()` 现在返回 typed `Response`
- SSE / out-of-order merge 仍在 raw snapshot 上做,避免在流式累积阶段丢失兼容性
这意味着现在的设计变成了:
- **内部合并逻辑继续保留协议容错能力**
- **对外读取结果尽量 typed 化**
这比“直接把累积器也硬改成纯 typed”更稳,因为它不会为了表面类型完整度牺牲事件序列兼容性。
#### D. `Response` / `Embedding` contract tests 与 runtime smoke 补强
- 新增 spec fixture:
- `tests/spec_fixtures/response.json`
- `tests/spec_fixtures/embedding.json`
- `typed_endpoints`、`spec_contract`、`contract/resources`、`parser`、`snapshots` 已补齐对新 typed surface 的回归
- `ecosystem-tests/fixtures/tokio_responses_client` 现在除了 `responses.create()`,还会真实走一遍:
- `responses.stream().send().await.final_response().await`
- `scripts/ecosystem_smoke_server.py` 已补齐 `/v1/responses` 的 SSE fixture,能在本地 stub server 上覆盖最小闭环的 responses streaming runtime smoke
这一步的价值在于:上一轮 ecosystem runtime smoke 主要证明“fixture 会跑”;这一轮开始明确覆盖 `responses` SSE 这条最容易在 typed migration 后回退的主链路。
#### E. `public-api` 基线已同步
- 由于本轮新增了大量公开 typed 类型,`public-api/all-features.txt` 已同步更新
- `bash ./scripts/check-public-api.sh` 已重新验证通过
### 14.2 本轮完整回归结果
本轮我重新执行并确认通过:
| `cargo test --all-features` | 通过 | 包含 `Response` / `Embedding` typed regression |
| `cargo test --no-default-features` | 通过 | 快照测试已同步到 typed access |
| `cargo nextest run --all-features` | 通过 | `136 passed, 31 skipped` |
| `cargo fmt --all -- --check` | 通过 | |
| `cargo clippy --all-targets --all-features -- -D warnings` | 通过 | |
| `cargo check --examples --all-features` | 通过 | |
| `cargo +nightly doc --all-features --no-deps` | 通过 | |
| `bash ./scripts/check-public-api.sh` | 通过 | 已同步本轮新增的 typed public surface |
| `python3 ./scripts/generate_endpoints.py --check` | 通过 | generated endpoint catalog 未漂移 |
| `bash ./scripts/check-ecosystem.sh` | 通过 | 已覆盖 `responses.create` + `responses` SSE runtime smoke |
| `cargo deny check` | 通过 | `advisories / bans / licenses / sources` 全绿 |
### 14.3 评分更新
如果继续以 `openai-node = 100` 为基线,这一轮之后我会把 `openai-rs` 的评分更新为:
| 功能覆盖 | `95` | **`95`** | 本轮重点不是扩端点,而是补核心 contract 深度 |
| 类型质量 / API 人体工学 | `94` | **`96`** | `Response` / `Embedding` 主链路明显更接近官方 SDK 的 typed surface |
| 测试深度 | `93` | **`94`** | 增加了 `Response` / `Embedding` typed contract 与 responses SSE runtime smoke |
| 可维护性 | `90` | **`91`** | raw merge 与 public typed surface 分层更清楚 |
| 工程化 / 发布成熟度 | `94` | **`94`** | 本轮主要是质量收口,不是新增 CI 类能力 |
| 综合评分 | `94` | **`95`** | 已进入“距离官方级主要剩深层类型与 codegen”的区间 |
### 14.4 现在还差多少
我的最新判断是:
- 如果 `openai-node = 100`,那么当前 `openai-rs` 大约是 **`95 / 100`**
- 相比上一轮的 **`94 / 100`**,这次再补上了大约 **`1` 分**
- 离“真正官方级、长期稳定、陌生用户直接放心接入”的状态,现在大约还差 **`5` 分左右**
剩余差距主要集中在:
1. **schema/type codegen 仍然不够深**
- 现在 generated layer 主要还是 endpoint catalog
- 真正追平 `openai-node`,还需要把更多 schema/type generation 落地,而不是继续手写扩张
2. **复杂对象内部仍有深层 `Value` 存量**
- 当前最明显的存量集中在:
- `src/resources/mod.rs` 里 `ChatCompletion`、`ResponseOutputText.annotations / logprobs` 等更深层字段
- `src/resources/beta.rs`
- `src/resources/longtail.rs`
- 也就是说,主链路 surface 已经 typed 化得更像 SDK,但复杂对象的“最后一层”还没有完全收干净
3. **ecosystem runtime smoke 仍然是最小矩阵**
- 现在已经覆盖 compile + runtime
- 但还没有扩到更多运行时、更多 provider 形态、更多 consumer crate 组合
### 14.5 最新结论
这一轮之后,我的结论更新为:
- **`openai-rs` 现在已经非常接近“官方级可对外推广 SDK”的门槛**
- **和 `openai-node` 的主要差距,进一步收缩到“深层 schema/type codegen”与“更宽的生态级验证矩阵”**
- **如果后面再补一轮 `beta / longtail / ChatCompletion` 的深层类型下沉,并把 generated layer 推到 schema/type 级别,综合分数有机会继续往 `96+` 走**