为 OpenAI 兼容接口配置教程

这篇讲什么

拿到一把 OpenAI 兼容协议的 API Key 之后,代码侧真正要做的只有两件事:把 base_url 指到正确的网关地址,把鉴权头写对。听起来简单,但实际动手时最容易在路径拼接上翻车------十次报 404,九次是 /v1 多写或少写。

这篇按「环境准备 → 三种语言分别跑通 → 统一封装 → 404 定位」的顺序走一遍,每一步都有可运行代码和实际输出。

环境准备

只需要装官方 SDK,兼容协议的网关不需要额外依赖:

bash 复制代码
pip install openai>=1.0.0        # Python
npm install openai               # Node.js

另外准备两个环境变量,不要把密钥写死在代码里:

bash 复制代码
# Linux / macOS
export LLM_API_KEY="sk-xxxxxxxxxxxxxxxx"
export LLM_BASE_URL="https://your-gateway.example.com/openai/v1"
powershell 复制代码
# Windows PowerShell
$env:LLM_API_KEY = "sk-xxxxxxxxxxxxxxxx"
$env:LLM_BASE_URL = "https://your-gateway.example.com/openai/v1"

这里的 LLM_BASE_URL 请替换成你所用平台文档里给出的兼容协议地址。有一点要先分清:你登录管理密钥的站点域名,和实际发起调用的接口域名,往往不是同一个 。前者是控制台,后者才是要填进 base_url 的值。接入前务必在平台文档里核对这两个地址,直接把控制台域名填进代码是新手最常见的第一个错。

第一步:理解 base_url 该写到哪一层

OpenAI 兼容协议的路径结构是固定的:

复制代码
<网关根地址>/v1/chat/completions

而不同工具对 base_url 的处理方式不一样,这是 404 的根源:

调用方式 base_url 写到哪 说明
openai Python SDK .../openai/v1 SDK 自动补 /chat/completions
openai Node SDK .../openai/v1 同上,字段名是 baseURL
curl / requests 手写 完整端点 .../openai/v1/chat/completions 没人替你拼路径
部分三方框架 视文档,多数只到根地址 框架内部可能已带 /v1

记一句话就够了:SDK 写到 /v1,手写请求写完整端点。

第二步:鉴权怎么设置

鉴权是标准的 Bearer Token,放在 HTTP 请求头里:

复制代码
Authorization: Bearer <你的Key>
Content-Type: application/json

因为和官方协议完全一致,所以官方 SDK 不需要任何改造,只换 base_url 就能跑。用 SDK 时你甚至不用手写这个头,传 api_key 参数即可,SDK 会自动组装。

第三步:Python 跑通第一个请求

python 复制代码
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["LLM_API_KEY"],
    base_url=os.environ["LLM_BASE_URL"],   # 结尾到 /v1
)

resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "你是一个简洁的技术助手,回答不超过两句话。"},
        {"role": "user", "content": "用一句话解释什么是 Bearer Token"},
    ],
    temperature=0.3,
)

print("模型:", resp.model)
print("回复:", resp.choices[0].message.content)
print("用量:", resp.usage.prompt_tokens, "+", resp.usage.completion_tokens)

实际输出(内容每次略有不同):

复制代码
模型: gpt-4o-mini
回复: Bearer Token 是一种把令牌放在 HTTP Authorization 头里传递的鉴权方式,服务端凭这个令牌识别调用方身份。
用量: 42 + 38

跑到这一步说明三件事同时正确了:地址对、密钥有效、路径拼接没问题。

第四步:Node.js 版本

javascript 复制代码
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.LLM_API_KEY,
  baseURL: process.env.LLM_BASE_URL,   // 注意是 baseURL,驼峰
});

const resp = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "写一句项目启动的欢迎语" }],
});

console.log(resp.choices[0].message.content);

Node 端有两个坑:字段名是 baseURL(大写 URL),不是 base_url;以及 await 顶层使用要求 package.json 里声明 "type": "module",否则改用 .mjs 后缀或包一层 async 函数。

第五步:curl 快速验活

调试阶段想确认「到底是我的代码有问题,还是密钥/地址有问题」,用 curl 隔离最快:

bash 复制代码
curl "$LLM_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $LLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "只回复两个字:收到"}]
  }'

返回结构长这样(截取关键字段):

json 复制代码
{
  "id": "chatcmpl-xxxxxxxx",
  "object": "chat.completion",
  "model": "gpt-4o-mini",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "收到" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 18, "completion_tokens": 2, "total_tokens": 20 }
}

注意 curl 这里拼的是 $LLM_BASE_URL/chat/completions------因为环境变量已经带了 /v1,所以只补后半段。

第六步:封装成可复用的客户端

真实项目里不会每处都 new 一个客户端。加上启动期校验和超时重试,写成一个模块:

python 复制代码
# llm_client.py
import os
import sys
from openai import OpenAI

REQUIRED = ("LLM_API_KEY", "LLM_BASE_URL")


def _check_env() -> None:
    missing = [k for k in REQUIRED if not os.environ.get(k)]
    if missing:
        print(f"[fatal] 缺少环境变量: {', '.join(missing)}", file=sys.stderr)
        sys.exit(78)          # 78 = EX_CONFIG,配置错误


_check_env()

client = OpenAI(
    api_key=os.environ["LLM_API_KEY"],
    base_url=os.environ["LLM_BASE_URL"],
    timeout=30.0,
    max_retries=2,
)


def ask(prompt: str, model: str = "gpt-4o-mini") -> str:
    resp = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
    )
    return resp.choices[0].message.content


if __name__ == "__main__":
    print(ask("自检通过就回复 OK"))

两个细节值得说明。一是启动期就校验环境变量 ,缺失直接退出,而不是等第一次调用时抛一个语义模糊的鉴权错误;退出码用 78 是沿用 sysexits 的约定,容器编排和 CI 能据此区分配置问题和运行时问题。二是 max_retries=2 让 SDK 自己处理瞬时网络抖动,业务代码不用套一层 try/except 重试。

404 定位清单

如果上面任一步返回 404,按这个顺序查,基本一遍就能定位:

1. 打印实际请求的完整 URL

python 复制代码
import httpx, logging
logging.basicConfig(level=logging.DEBUG)
# 或者手动拼一遍确认
print(os.environ["LLM_BASE_URL"].rstrip("/") + "/chat/completions")

2. 数一下 /v1 出现了几次

出现两次(/v1/v1/chat/completions)说明 SDK 又补了一遍------把 base_url 里的 /v1 去掉,或确认 SDK 是否需要你带。出现零次说明手写请求漏了。

3. 确认没把控制台域名当接口域名

这一条单独列出来,因为它报的也是 404,很容易被误判成路径问题。管理密钥的站点通常没有 /v1/chat/completions 这个路由。

4. 用 -v 看真实响应头

bash 复制代码
curl -v "$LLM_BASE_URL/chat/completions" -H "Authorization: Bearer $LLM_API_KEY" -d '{}'

如果返回的 content-typetext/html,说明请求根本没进到 API 层,八成是地址整个写错了;返回 JSON 且带 error.message 才是 API 在正常回你。

顺手记住另外两个常见状态码的区别,能省不少排查时间:401 是密钥错 (拼写、多余空格、引号被包进值里),404 是路径错429 是频率限制。三者原因完全不重叠,别混着试。

小结

配置 OpenAI 兼容接口,本质就是两行:base_url 指向平台文档给出的网关地址,鉴权用 Bearer Token。真正需要肌肉记忆的是路径规则------SDK 写到 /v1,手写请求写完整端点;遇到 404 先数 /v1 的个数,再确认域名有没有把控制台和接口搞混。把本文的 llm_client.py 复制进项目,环境变量配好,剩下的调用逻辑和官方写法完全一致,不需要为兼容协议做任何额外适配。

相关推荐
万邦科技Lafite1 小时前
阿里巴巴拍立淘按图搜索商品API返回值实践:提升用户购物满意度的关键措施
开发语言·api·开放api·电商开放平台·京东开放平台
小小龙学IT2 小时前
Qt 6 跨平台开发完全指南:从信号槽机制到实际项目落地
开发语言·qt
leisoo80972 小时前
ig50数据落盘ClickHousevsTimescaleDBvsDuckDB实测对比 IG50免费开源股票数据API接口
开发语言·jvm·数据库·python·json
卷无止境2 小时前
FastAPI 的 Metadata 到底是什么,又牵动了哪些核心概念
后端·python
卷无止境2 小时前
FastAPI 调试实战,从断点到生产环境的排错心法
后端·python
敢敢のwings3 小时前
智元 GO-2 与 AgiBot-World 深度解读
开发语言·后端·golang
yaoxin5211233 小时前
503. Java 反射 - 编写 ServiceFactory 类
java·开发语言·python
一个帅气昵称啊3 小时前
.Net C# AI智能体开发-快速开始
开发语言·c#·.net
kyrie_sakura4 小时前
python学习笔记3 -- 流程控制语句结构
笔记·python·学习