4、API 调用与SDK入门:OpenAI API、文心一言API、通义千问API的调用方式与鉴权
好,咱们进入第四讲。API 调用,说白了就是让我们的代码去跟大模型「对话」。
我刚开始接触大模型时,觉得这东西很神秘。后来发现,本质上就是发一个 HTTP 请求,拿回一个 JSON 响应。嗯,就这么简单。
但不同厂商的 API,鉴权方式、参数格式、返回结构,各有各的脾气。今天我就带你一次性搞定三家主流 API:OpenAI、文心一言、通义千问。
4.1 鉴权:你的「通行证」
调用任何大模型 API,第一步都是鉴权。说白了,就是告诉服务器「我是谁,我有权限调用」。
每家厂商的鉴权方式不太一样,我整理了一张表,你一看就明白:
| 厂商 | 鉴权方式 | 关键参数 | 有效期 |
|---|---|---|---|
| OpenAI | API Key(Bearer Token) | Authorization: Bearer sk-xxx | 永久(可撤销) |
| 文心一言 | Access Token(通过 API Key + Secret Key 获取) | grant_type, client_id, client_secret | 默认 30 天 |
| 通义千问 | API Key(Header 或 Query 参数) | X-DashScope-SSE: enable / disable | 永久(可撤销) |
核心要点:OpenAI 和通义千问是「一次鉴权,永久使用」。文心一言需要先拿 API Key 和 Secret Key 去换一个临时 Access Token,过期了得重新换。
4.2 OpenAI API:最经典的调用方式
OpenAI 的 API 设计,可以说是行业标杆。我建议你从它入手,一通百通。
先看一个最简单的例子——用 Python 调用 GPT-3.5-turbo:
import openai
# 设置 API Key
openai.api_key = "sk-your-api-key-here"
# 调用 Chat Completion
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "你是一个资深的编程导师。"},
{"role": "user", "content": "请用 Python 写一个快速排序。"}
],
temperature=0.7,
max_tokens=500
)
# 提取回复内容
reply = response.choices[0].message.content
print(reply)
这里有几个关键点,我当年踩过坑:
- messages 数组:这是核心。system 角色设定 AI 的行为,user 是用户输入,assistant 是 AI 回复。多轮对话就是不断往这个数组里追加消息。
- temperature:控制随机性。0 表示完全确定,1 表示天马行空。我个人习惯用 0.7,既有创意又不至于跑偏。
- max_tokens:限制回复长度。注意,这是输入+输出的总 token 数,不是只限制输出。
我的经验:我曾经在项目中把 max_tokens 设得太小,结果 AI 话说到一半被截断了,返回的内容不完整。后来我改成动态计算:先估算输入 token 数,再用总限制减去输入,剩下的给输出。
4.3 文心一言 API:先换令牌再说话
文心一言的鉴权流程,说白了就是「两步走」。
第一步,用 API Key 和 Secret Key 换 Access Token:
import requests
# 你的 API Key 和 Secret Key
API_KEY = "your-api-key"
SECRET_KEY = "your-secret-key"
# 获取 Access Token
url = "https://aip.baidubce.com/oauth/2.0/token"
params = {
"grant_type": "client_credentials",
"client_id": API_KEY,
"client_secret": SECRET_KEY
}
response = requests.post(url, params=params)
access_token = response.json().get("access_token")
print(f"Access Token: {access_token}")
第二步,拿着 Access Token 去调用对话接口:
# 调用文心一言对话 API
url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions"
headers = {
"Content-Type": "application/json"
}
params = {
"access_token": access_token
}
data = {
"messages": [
{"role": "user", "content": "请用 Python 写一个快速排序。"}
],
"temperature": 0.7
}
response = requests.post(url, headers=headers, params=params, json=data)
result = response.json()
reply = result.get("result")
print(reply)
注意:Access Token 默认有效期是 30 天。我曾经在生产环境中忘记刷新 Token,结果凌晨三点服务挂了。建议写个定时任务,每 25 天自动刷新一次。
文心一言的返回结构跟 OpenAI 不太一样。OpenAI 用 choices[0].message.content,文心一言直接用 result 字段。嗯,这个细节容易搞混。
4.4 通义千问 API:阿里系的简洁风格
通义千问的 API 设计,我个人觉得介于 OpenAI 和文心一言之间。鉴权简单,但参数命名有点不一样。
先看代码:
import dashscope
# 设置 API Key
dashscope.api_key = "sk-your-dashscope-api-key"
# 调用通义千问
response = dashscope.Generation.call(
model="qwen-turbo",
prompt="请用 Python 写一个快速排序。",
temperature=0.7,
max_tokens=500
)
# 提取回复
reply = response.output.text
print(reply)
你看,跟 OpenAI 很像,但有两个关键区别:
- 参数名不同:OpenAI 用
messages,通义千问用prompt(单轮对话)或messages(多轮)。 - 返回结构不同:OpenAI 用
choices[0].message.content,通义千问用output.text。
避坑指南:我曾经在切换模型时,直接把 OpenAI 的代码复制过来改个 endpoint 就跑了。结果通义千问返回的字段名不一样,程序直接报 KeyError。后来我养成了一个习惯——每次换 API,先打印一次完整的 response 看看结构。
4.5 流式输出:让 AI 边想边说
上面讲的都是「一次性返回」。但实际产品中,用户更希望看到 AI 一个字一个字地往外蹦。这就是流式输出(Streaming)。
以 OpenAI 为例,开启流式输出只需要加一个参数:
import openai
openai.api_key = "sk-your-api-key"
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "讲一个冷笑话。"}],
stream=True # 开启流式输出
)
# 逐块读取
for chunk in response:
if chunk.choices[0].delta.get("content"):
print(chunk.choices[0].delta.content, end="")
流式输出的核心是 stream=True。返回的不再是一个完整的 JSON,而是一个生成器,每次吐出一小块数据。
文心一言和通义千问也支持流式,但参数名略有不同:
- 文心一言:在请求体中加
"stream": true - 通义千问:在 Header 中加
X-DashScope-SSE: enable
我的建议:流式输出在用户体验上提升巨大。但要注意,前端需要处理 SSE(Server-Sent Events)协议。如果你用 React,可以用 EventSource 或 fetch 的 ReadableStream 来接收。
4.6 错误处理:别让用户看到 500
API 调用一定会遇到错误。我总结了几种常见情况:
| 错误类型 | HTTP 状态码 | 常见原因 | 处理方式 |
|---|---|---|---|
| 鉴权失败 | 401 | API Key 错误或过期 | 提示用户重新配置 |
| 频率限制 | 429 | 请求太快太多 | 等待后重试(指数退避) |
| 模型不可用 | 503 | 服务过载或维护 | 切换备用模型或提示稍后重试 |
| 参数错误 | 400 | messages 格式不对 | 检查请求体结构 |
我建议你封装一个统一的调用函数,把错误处理逻辑写进去:
def call_llm(messages, model="gpt-3.5-turbo", max_retries=3):
for attempt in range(max_retries):
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=30
)
return response.choices[0].message.content
except openai.error.RateLimitError:
wait_time = 2 ** attempt
print(f"频率限制,等待 {wait_time} 秒...")
time.sleep(wait_time)
except openai.error.AuthenticationError:
raise Exception("API Key 无效,请检查配置")
except Exception as e:
print(f"未知错误:{e}")
if attempt == max_retries - 1:
raise
return None
注意:千万不要把 API Key 硬编码在代码里。我见过有人把 Key 提交到 GitHub 公开仓库,结果几分钟内就被盗刷了几千美元。建议用环境变量或密钥管理服务。
4.7 小结:选哪家?
说实话,没有绝对的「最好」。我个人的选择标准是这样的:
- OpenAI:生态最成熟,文档最清晰,适合快速原型验证。但国内访问需要代理,延迟较高。
- 文心一言:中文理解能力强,对国内场景优化好。但鉴权流程稍繁琐,需要定期刷新 Token。
- 通义千问:阿里系产品,跟阿里云生态集成好。API 设计简洁,但模型种类不如 OpenAI 丰富。
我的建议是:原型阶段用 OpenAI 快速验证,产品化阶段根据部署环境选择国内模型。嗯,灵活切换才是王道。
下一讲,我们会深入 Prompt Engineering,教你如何「调教」大模型,让它输出你想要的内容。