openai/openai-go¶
这个项目在系统里负责哪一层¶
openai-go 负责的是模型供应商适配层。它解决的不是“少写几行 HTTP 请求”,而是怎样把同步生成、流式生成、结构化输出、工具调用、会话续接和后台执行这些常见能力收进一套类型化 SDK。
对 Go 后端来说,它最值得学的不是某个字段名,而是 provider adapter 应该怎么长。业务层真正需要的是稳定能力边界,而不是供应商原始请求体和响应体。
先抓整体结构¶
读这个项目时,先按一条真实链路走:
- 普通请求怎么发。
- 流式事件怎么收。
- 工具 schema 怎么表达。
- 结构化输出怎么约束。
- 会话续接怎么做。
- 后台 response 和取消怎么处理。
这个顺序的价值在于,它是沿复杂度往上加。先把一次响应如何建模看清,再去理解为什么流式、工具和结构化输出没有被做成互相割裂的几套接口。
一条典型执行链¶
如果你用它写一个带工具的问答接口,一条链路大致会这样跑:
- 服务端组装请求,明确模型、输入、输出约束和可用工具。
- SDK 发起 Responses 请求,拿到同步结果或流式事件流。
- 如果模型产生工具调用建议,服务端按 schema 解析,再走自己的权限和执行层。
- 工具结果整理成结构化对象,再继续送回模型或直接收口。
- 如果是长对话或多步执行,服务端按续接机制接住状态,而不是每轮无脑拼全量历史。
- 如果请求变成长任务,后台模式和取消机制要一起考虑。
这个链路最重要的提醒是:SDK 可以帮你表达能力,但执行权和治理仍然在服务端。
值得学的设计¶
openai-go 有两个设计特别值得学。
第一,它尽量把同步响应、流式响应、工具调用和结构化结果收在同一条 response 心智下。这样你在业务里思考的是“这次执行有哪些阶段”,而不是“我要不要切到另一套完全不同的 SDK 写法”。
第二,它会不断把你拉回状态管理问题。很多 demo 喜欢把历史消息一直往上堆,但这个项目更像是在提醒你:对话不是无限历史,真正要管理的是这次执行该续接哪些状态、何时停止、何时取消。
这两点对 Go 项目很重要,因为一旦模型调用分散在 handler 里,后面想统一超时、日志、trace、重试和模型分级会非常痛苦。
适合借回自己项目的点¶
- 单独做 provider adapter,例如
llmclient、ai或model包。 - 对上只暴露稳定能力,例如
Generate、Stream、RunTools、ParseStructured。 - 把模型名、超时、重试、日志字段和 trace 收在适配层,而不是散在 handler 里。
- 把会话续接当状态管理问题,而不是聊天记录拼接问题。
不要照抄的地方¶
- 不要把 SDK 类型直接传到业务层。供应商细节一旦扩散,后面很难收。
- 不要把 provider 的错误模型原样往上抛。业务层需要更稳定的错误语义。
- 不要把“支持续接”理解成“历史可以无限增长”。成本和噪声都会很快找上门。