AI 开发教程

OpenAI-compatible API 调用教程:Python 与 Postman 从零接入

用 Python 和 Postman 调用 OpenAI-compatible Chat Completions,掌握 Base URL、Bearer 认证、模型 ID、响应解析与流式输出的关键细节。

客户端与 API 服务之间传递请求的青色光桥

第一次调用 AI API 时,最常见的障碍往往不是提示词,而是地址拼错、密钥没有进入运行环境,或者把模型展示名称当成了模型 ID。本文用同一条文本请求,分别演示 Postman 与 Python 的接入方法。

示例使用 OpenAI-compatible Chat Completions 格式。它适合学习兼容接口的基本结构;服务商是否支持对应路径、参数和流式协议,需要查阅其文档。OpenAI 官方也提供其他 API,本文不将它们混为同一个接口。

一、先理解兼容范围

“OpenAI-compatible”通常表示服务采用了某些相似的请求或响应结构,并不是对全部 API 功能的统一认证。一个服务可能支持文本聊天,却不支持 Responses、图片生成或工具调用。

本文只要求最小文本请求具有以下结构:请求指定 model 和 messages,响应中可以读取 choices[0].message.content。这个消息式结构可对照 Chat Completions 官方参考理解;第三方差异仍以各自文档为准。

二、准备配置:地址、凭证、模型

变量 示例或含义
AI_BASE_URL 例如 https://api.example.com/v1,必须换成服务商实际地址
AI_API_KEY 有效密钥,不能使用文章里的演示占位值
AI_MODEL 当前账户有权限调用的精确模型 ID

本文的 example.com 地址不会作为可用 AI 服务使用。你应先在服务文档中找到真实配置,再运行示例。

若 Base URL 已经带有 /v1,不要再手动添加一层 /v1。Python SDK 的 base_url 使用 API 根路径;Postman 则需要完整请求地址。对于本文的示例路径,完整 URL 是 {{base_url}}/chat/completions。

三、先用 Postman 验证请求

1. 建立环境变量

创建一个测试环境,配置 base_url、api_key、model 三个变量。base_url 末尾不带斜线。发送请求前选中该环境,确认变量已解析,而不是原样发送 {{model}}。

Postman 用双花括号引用变量。变量可以存在于不同作用域,同名值可能覆盖彼此;具体行为可查看 Postman 变量文档。排错时先减少同名变量。密钥避免同步或导出到共享环境,分享集合前检查是否包含敏感值。

2. 配置 URL 与认证

新建 POST 请求,URL 填写:

{{base_url}}/chat/completions

在 Authorization 中选择 Bearer Token,Token 填写 {{api_key}}。它通常会生成 Authorization: Bearer ... 请求头,不要在 Token 输入框中再重复写 Bearer。

Body 选择 raw 和 JSON,确保 Content-Type 是 application/json。

3. 添加最小请求体

{
  "model": "{{model}}",
  "messages": [
    {
      "role": "user",
      "content": "请用三句话解释 HTTP API,每句话不超过四十个字。"
    }
  ]
}

点击 Send 后,先观察 HTTP 状态码,再查看响应体。不要只判断界面是否出现了一段文本:如果返回的是网页 HTML,可能请求到了网页路由或被网关拦截,并未得到 API JSON。

成功响应通常含有 choices。文本位于第一个 choice 的 message.content。返回内容的具体措辞不是固定答案;你要验证的是接口能成功认证、接受指定模型并返回预期结构。

可以在 Post-response 脚本中添加一个基础检查:

pm.test("返回成功状态和文本回答", function () {
  pm.expect(pm.response.code).to.eql(200);
  const body = pm.response.json();
  pm.expect(body.choices).to.be.an("array").that.is.not.empty;
  pm.expect(body.choices[0].message.content).to.be.a("string").and.not.empty;
});

这个检查用于本文的纯文本请求。工具调用或其他类型响应不应套用同一断言。

四、使用 Python 发送相同请求

1. 安装与配置

建议使用 Python 3.10 或更新版本,在项目虚拟环境中安装依赖:

python -m pip install openai

Windows PowerShell 的环境变量写法如下。请将三个占位值换成自己的配置;这些变量作用于当前终端及其启动的进程。

$env:AI_BASE_URL = "https://api.example.com/v1"
$env:AI_API_KEY = "替换为真实密钥"
$env:AI_MODEL = "替换为可用模型ID"

macOS 或 Linux 的常见 shell 写法:

export AI_BASE_URL="https://api.example.com/v1"
export AI_API_KEY="替换为真实密钥"
export AI_MODEL="替换为可用模型ID"

不要把带真实密钥的命令复制到工单或公开截图中。使用 .env 时还需要显式加载它;Python 不会自动读取该文件。

2. 保存并运行代码

将下列代码保存为 chat_demo.py,在已配置环境变量的终端运行 python chat_demo.py。

import os
from openai import OpenAI, APIConnectionError, APIStatusError, APITimeoutError

def required(name):
    value = os.getenv(name, "").strip()
    if not value:
        raise RuntimeError(f"请先设置环境变量 {name}")
    return value

def main():
    client = OpenAI(
        api_key=required("AI_API_KEY"),
        base_url=required("AI_BASE_URL").rstrip("/"),
        timeout=30.0,
        max_retries=0,
    )
    try:
        result = client.chat.completions.create(
            model=required("AI_MODEL"),
            messages=[{
                "role": "user",
                "content": "请用三句话解释 HTTP API,每句话不超过四十个字。",
            }],
        )
    except APITimeoutError:
        raise SystemExit("请求超时;先检查链路,不要立即连续重发。")
    except APIConnectionError:
        raise SystemExit("连接失败;检查地址、DNS、代理与证书。")
    except APIStatusError as exc:
        request_id = getattr(exc, "request_id", None)
        raise SystemExit(
            f"API 返回 HTTP {exc.status_code},request_id={request_id}"
        )

    if not result.choices:
        raise SystemExit("响应中没有 choices,请核对接口兼容性。")
    choice = result.choices[0]
    if not choice.message.content:
        raise SystemExit(
            f"没有文本回答,finish_reason={choice.finish_reason}"
        )
    print(choice.message.content)
    print(f"finish_reason={choice.finish_reason}")

if __name__ == "__main__":
    main()

首次调试关闭自动重试,有助于观察一次请求的真实结果。超时值是演示配置,不能解释为服务响应时间承诺。代码不直接输出完整错误体,是为了减少日志泄露输入或凭证的机会;进一步排错时可以在本机查看经过脱敏的错误信息。

官方 Python SDK 的安装和基础用法可参考 OpenAI SDK 文档。固定项目依赖版本后再做回归验证,能减少环境变化造成的差异。

五、需要逐字显示时,再加入流式输出

非流式请求拿到完整结果后再显示。流式请求会陆续收到片段,适合降低用户等待完整回答的感知时间,但它不会保证总耗时更短。

服务确认支持 Chat Completions 流式输出后,可用下列独立示例:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AI_API_KEY"],
    base_url=os.environ["AI_BASE_URL"].rstrip("/"),
    timeout=60.0,
    max_retries=0,
)
with client.chat.completions.create(
    model=os.environ["AI_MODEL"],
    messages=[{"role": "user", "content": "用一个生活例子解释缓存。"}],
    stream=True,
) as stream:
    for chunk in stream:
        if not chunk.choices:
            continue
        text = chunk.choices[0].delta.content
        if text:
            print(text, end="", flush=True)
print()

注意读取的是 delta.content,而不是非流式的 message.content。某些片段没有文本,不能把每个 chunk 都当作一个完整回答。生产应用还要处理流中断:已经展示给用户的内容不能在重试后无提示地重复追加。

六、调用成功后的三个检查

检查输出是否完整。 如果结束原因显示长度限制,应查阅模型支持的输出上限参数,并检查输入上下文;不要盲目复制其他模型的参数。

检查业务格式。 要求模型输出 JSON 不等于获得有效 JSON。需要解析、校验必要字段,支持结构化输出时再按实际文档启用。

检查凭证边界。 网页应用应通过自己的后端调用 API。浏览器可见的配置、前端打包变量和网络请求都可能暴露密钥,不能把“用户看不到源码”当作保护手段。

七、常见问题

Postman 能调用,Python 为什么不行?

对比实际 Base URL、模型 ID 和运行环境,而不是只对比代码。Python 可能从另一个终端启动,没有继承密钥;也可能使用了不同代理。先让两者发送同一条最小请求,再检查依赖版本。

为什么收到 404?

检查完整请求路径,尤其是重复的版本前缀。404 也可能表示模型或资源不可用,应结合脱敏错误体判断,不能只归因于网址。

为什么不一开始就加入 temperature 等参数?

不同模型对参数的支持范围可能不同。最小请求先验证连接,然后每次只增加一个参数,便于区分基础接入问题和能力兼容问题。

完成这条最小调用后,你就获得了一条可复现的基线。接下来无论加入多轮对话、流式显示还是业务校验,都应从这条基线逐步扩展。