跳转至

openai/openai-go

仓库:openai/openai-go

这个项目在系统里负责哪一层

openai-go 负责的是模型供应商适配层。它解决的不是“少写几行 HTTP 请求”,而是怎样把同步生成、流式生成、结构化输出、工具调用、会话续接和后台执行这些常见能力收进一套类型化 SDK。

对 Go 后端来说,它最值得学的不是某个字段名,而是 provider adapter 应该怎么长。业务层真正需要的是稳定能力边界,而不是供应商原始请求体和响应体。

先抓整体结构

读这个项目时,先按一条真实链路走:

  1. 普通请求怎么发。
  2. 流式事件怎么收。
  3. 工具 schema 怎么表达。
  4. 结构化输出怎么约束。
  5. 会话续接怎么做。
  6. 后台 response 和取消怎么处理。

这个顺序的价值在于,它是沿复杂度往上加。先把一次响应如何建模看清,再去理解为什么流式、工具和结构化输出没有被做成互相割裂的几套接口。

一条典型执行链

如果你用它写一个带工具的问答接口,一条链路大致会这样跑:

  1. 服务端组装请求,明确模型、输入、输出约束和可用工具。
  2. SDK 发起 Responses 请求,拿到同步结果或流式事件流。
  3. 如果模型产生工具调用建议,服务端按 schema 解析,再走自己的权限和执行层。
  4. 工具结果整理成结构化对象,再继续送回模型或直接收口。
  5. 如果是长对话或多步执行,服务端按续接机制接住状态,而不是每轮无脑拼全量历史。
  6. 如果请求变成长任务,后台模式和取消机制要一起考虑。

这个链路最重要的提醒是:SDK 可以帮你表达能力,但执行权和治理仍然在服务端。

值得学的设计

openai-go 有两个设计特别值得学。

第一,它尽量把同步响应、流式响应、工具调用和结构化结果收在同一条 response 心智下。这样你在业务里思考的是“这次执行有哪些阶段”,而不是“我要不要切到另一套完全不同的 SDK 写法”。

第二,它会不断把你拉回状态管理问题。很多 demo 喜欢把历史消息一直往上堆,但这个项目更像是在提醒你:对话不是无限历史,真正要管理的是这次执行该续接哪些状态、何时停止、何时取消。

这两点对 Go 项目很重要,因为一旦模型调用分散在 handler 里,后面想统一超时、日志、trace、重试和模型分级会非常痛苦。

适合借回自己项目的点

  • 单独做 provider adapter,例如 llmclientaimodel 包。
  • 对上只暴露稳定能力,例如 GenerateStreamRunToolsParseStructured
  • 把模型名、超时、重试、日志字段和 trace 收在适配层,而不是散在 handler 里。
  • 把会话续接当状态管理问题,而不是聊天记录拼接问题。

不要照抄的地方

  • 不要把 SDK 类型直接传到业务层。供应商细节一旦扩散,后面很难收。
  • 不要把 provider 的错误模型原样往上抛。业务层需要更稳定的错误语义。
  • 不要把“支持续接”理解成“历史可以无限增长”。成本和噪声都会很快找上门。