用 OpenAI 库调 Gemini:官方说只改三行
数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。
Gemini 官方文档对 OpenAI 库用户给出的说法很直白:从 OpenAI 库切过来只需改三行——api_key、base_url、model。base_url 指向官方的 OpenAI 兼容端点 https://generativelanguage.googleapis.com/v1beta/openai/,鉴权用 Authorization: Bearer 头承载 Gemini 的 API 密钥。但同一页官方紧接着补了一句常被忽略的建议:如果你还没在用 OpenAI 库,官方推荐直接调用 Gemini 原生 API,而不是走兼容层。也就是说,这条路是给存量代码准备的迁移通道,不是给新项目准备的推荐姿势。真正要留神的地方在三行之外:思考参数的映射规则、流式过程中的错误传递方式,以及官方文档在兼容层这一侧没有说明的那些能力边界。
那三行到底改成什么
先把三处落到实处。
api_key:换成你的 Gemini API 密钥。官方示例里通过环境变量GEMINI_API_KEY传入。base_url:换成https://generativelanguage.googleapis.com/v1beta/openai/。注意路径末尾的openai/这一段,兼容层是挂在v1beta下面的一个子路径,不是另开一个域名。model:换成 Gemini 的模型名。
官方给了 Python、JavaScript、REST 三种形态的示例,三种都齐备。官方示例覆盖的就是这三种形态;如果你用的是别的语言,兼容层本质上仍然是一次普通的 HTTP 请求,可以照着 REST 那一份把路径、请求头和请求体原样拼出来,不必等官方出对应语言的示例。
from openai import OpenAI
client = OpenAI(
api_key="你的 Gemini API 密钥",
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
)
response = client.chat.completions.create(
model="模型名以官方文档当前版本为准",
messages=[{"role": "user", "content": "写一段自我介绍"}],
)
这里有个容易混淆的点值得单独点出来:兼容层的鉴权方式和 Gemini 原生 REST 接口不是一回事。兼容层走的是 OpenAI 生态惯用的 Authorization: Bearer 请求头,而 Gemini 原生 REST 走的是自定义头 x-goog-api-key。密钥本身是同一个,但塞的位置不同。如果你在同一个项目里既有一段原生 curl 调用、又有一段跑 OpenAI SDK 的代码,把两套请求头记串了是很自然的事。这种错法从代码上看不出破绽:两处的密钥字符串一模一样,肉眼扫过去毫无异常,差别只在它被写进了哪一个请求头。所以在同一项目里两套调用并存时,值得把「这条请求走的是兼容层还是原生 REST」和「对应的请求头有没有配对」当成一条固定的核对项,写进联调清单里,而不是等出问题了再回头翻。各家兼容端点在这类细节上的差异,可以对照各家 OpenAI 兼容端点的路径与差异一起看。
官方为什么反过来劝你别用
Gemini 官方在这一段的措辞相当克制,值得逐字读一遍:只有当你已经在用 OpenAI 库时,才建议走兼容层;如果尚未使用,官方推荐直接调用原生 API。
这句话的分量比看上去重。它实际上是在告诉你:兼容层承担的是「让存量代码跑起来」这一件事,而不是「让你完整拿到 Gemini 的全部能力」。凡是 OpenAI 的请求体结构里没有对应位置的 Gemini 专有能力,都得靠额外的通道往里塞,而不是天然可用。
所以做技术选型时,判断依据不该是「兼容层能不能跑通一个 hello world」——它当然能跑通。判断依据应该是:你的项目未来半年会不会用到 Gemini 那些没有 OpenAI 对应字段的东西。如果会,那么现在省下的迁移成本,之后会以「到处打补丁」的形式还回来。反过来,如果你手上是一套已经跑了很久、抽象层写得还算干净的 OpenAI 客户端代码,只想换个模型跑跑对比,那这条通道正是为你准备的。
思考参数:改完三行之后第一个撞上的东西
真正会让人卡住的第一个差异,是推理模型的思考控制。
OpenAI 那边的 reasoning_effort 参数在兼容层里是能用的,官方给出的映射关系是:reasoning_effort 映射到 Gemini 3.x 的 thinking_level,或者 Gemini 2.5 的 thinking_budget。档位是 minimal、low、medium、high 四档。
几条必须记住的规则:
- **
reasoning_effort与thinking_level/thinking_budget功能重叠,不能同时使用。**官方是把它作为硬约束写出来的:有人把 OpenAI 侧的参数留着,又顺手用别的通道塞了一个 Gemini 侧的思考参数进去,以为是「双保险」,实际是冲突。 - 不指定
reasoning_effort时,走的是模型自己的默认级别或默认预算,具体值以官方文档当前版本为准。 - 关闭思考这件事分模型:2.5 系列可以把
reasoning_effort设成"none";但官方明文写着 Gemini 2.5 Pro 与 Gemini 3 系列无法关闭推理。别在这些型号上浪费时间调参数,关不掉就是关不掉。这一层的完整名单见哪些 Gemini 模型的推理是关不掉的。 - 想在兼容层里传 Gemini 专有的思考字段,官方给的通道是
extra_body,路径为extra_body.google.thinking_config,下面可以放thinking_level与include_thoughts。
extra_body 这个设计值得多说一句。它本质上是在 OpenAI 的请求体上开了一个厂商专属的口袋,凡是标准结构里没位置的东西都从这里进。好处是不用改 SDK,OpenAI 那套请求结构一个字都不用动;代价是这个口袋里的字段名、层级和取值范围都不属于 OpenAI 标准结构的约定范围,只能完全照官方给的路径写。路径要记全:google 这一层不能省,往下是 thinking_config,再往下才是 thinking_level 与 include_thoughts 这两个字段。官方文档里没有说明键名写错时会如何反馈,所以联调阶段稳妥的做法是把「这段配置到底有没有生效」单独确认一遍,而不是默认它已经生效、直接进入下一步。映射关系的细节可以对照reasoning_effort 和 thinking_level 怎么对应。
另外,Gemini 3 支持在 chat completions API 中使用 OpenAI 兼容的思考签名(thought signatures)。做多轮工具调用时这是一个要留意的机制。
流式能用,但错误未必出现在状态码里
兼容层支持 stream=True 流式输出,这一点官方有明确说明,不用担心迁移过来之后打字机效果没了。
但流式这条路上有个结构性的坑,官方在错误参考文档里写得很清楚:标准请求与流式请求的错误传递方式不同。标准(非流式)请求出错时,服务端设置 HTTP 状态码,同时在 JSON body 里返回一个 error 对象,含 code(机器可读的 snake_case)和 message(人类可读)两个字段。而流式请求出错时,错误是通过 SSE 流发送一个 event_type 为 "error" 的事件,error 字段的结构相同。
直接后果就是:只判 HTTP 状态码的客户端,会漏掉流式过程中发生的错误。连接建立成功、状态码一切正常、流也开始推了,然后中途出问题——如果你的错误处理只挂在状态码上,这个错误对你的监控是隐形的,表现出来就是「回答莫名其妙断了但没有任何报错」。写流式消费逻辑时,事件类型必须判,不能只判状态码。这一层展开见流式响应里的错误事件怎么接。
需要说明限定条件:上述错误结构来自官方的 Interactions API 错误参考页。官方文档并没有逐条说明 OpenAI 兼容层的错误对象会被 OpenAI SDK 包装成什么形状,所以不要假设它和你熟悉的 OpenAI 异常类型一一对应。稳妥做法是在联调阶段把原始响应打出来看一眼实际结构,而不是照着记忆里的异常类名写 catch 分支。
三行之外,官方没说的部分要当成没有
这一节是给容易乐观的人准备的。兼容层跑通之后,很自然会产生一种「那 Gemini 的其他能力应该也能从这条路上用」的联想。这个联想在文档层面是没有依据的。
举两个具体的例子:
其一,Batch 批量推理。官方在 Batch API 页首的注意事项里写明,Batch API 目前仅适用于 generateContent API。而官方在兼容层这一侧,并没有给出批量提交的用法说明。所以如果你的规划里包含大批量离线任务,别默认它能沿用同一套 OpenAI 客户端代码,这部分要按原生接口的形态单独设计。
其二,缓存。Gemini 的缓存机制本身在官方文档里说得很细,但那些说明是挂在原生接口的语境下的;兼容层调用的缓存行为,官方文档里没有找到对应说明。同理,官方给出的 token 计数方法写作 GenerativeModel.count_tokens,而它在 OpenAI 兼容层这一侧要怎么用,官方文档里没有找到对应说明。如果你的系统要在发请求之前先估一遍输入规模——比如做预算控制、做超长上下文的截断判断——这一环得单独确认接法,别默认它会跟着 OpenAI 客户端对象一起过来。
一句话概括这条判断准则:**在兼容层这条路上,官方文档没写的能力就当作没有,等真需要时切回原生接口去查。**把「大概能用吧」当成设计前提,代价往往要到编码后期才显现出来。
区域与合规:动手之前先确认这一层
这条通道再顺手,前提也是你能合规地使用这项服务。
官方的可用区域页列出了 Gemini API 与 Google AI Studio 推出的国家和地区,该列表中不包含中国大陆。官方对不在支持区域的用户给出的路径是改用 Gemini Enterprise Agent Platform 中的 Gemini API。除区域之外,官方另有两条准入条件:最低年龄 18 周岁,以及需要在 Google 账号中完成年龄验证。还有一个细节值得记:在 Colab 环境里,区域限制是按 Colab 实例所在区域判定的,不是按用户所在区域,官方给的自查命令是 !curl ipinfo.io。
国内团队要把这件事做扎实,方向只有两个:走官方给出的企业采购路径,或者选国内合规平台的服务。这两条之外的任何做法都不在本文讨论范围内。选型阶段先把接口差异摸清楚,比事后返工划算。
顺带一提:还有一条「只改几行」的路
如果你最终走的是原生 SDK 而不是兼容层,官方还给了另一条同样低成本的迁移路径,方向是从 Gemini Developer API 切到 Gemini Enterprise Agent Platform API。
两条产品线共用统一的 Google Gen AI SDK,迁移时改的只是客户端初始化那几行:Python 的 google-genai 从 genai.Client() 改成 genai.Client(vertexai=True, project=..., location=...);JS/TS 的 @google/genai 从 new GoogleGenAI({}) 改成 new GoogleGenAI({vertexai: true, project, location});Go 则是在 ClientConfig 里指定 Project、Location 与 Backend。生成调用那部分代码不变。
官方对这两条线的定位是:Developer API 是构建与扩缩的最快路径,除非需要特定的企业控制,多数开发者应当用 Developer API。
最后:两个值得提前想清楚的坑
第一个坑是把「跑通」当成「迁移完成」。三行改完,一个简单请求确实能返回结果,但思考参数的冲突规则、流式错误的事件形态、以及那些官方没说明的能力边界,都要在真实业务跑起来之前逐一确认。
第二个坑是把兼容层当默认选项。官方自己都写了:没在用 OpenAI 库的话,建议直接调原生 API。这句建议不是客套,它标出了兼容层的定位——过渡通道,而不是长期方案。手上有大量存量代码就用它省事,从零开始的新项目,多花半天读原生接口文档更划算。