如何接入大模型API
本文属于《从 0 到 1 AI 产品出海知识库》中的「AI 功能开发实战」章节。
为什么接入大模型 API 是第一步
做 AI 产品,第一件事不是设计界面、不是写 Prompt,而是跑通一次 API 调用。
原因很简单:大模型 API 是整个产品的「发动机」。无论是聊天、翻译、摘要、代码生成,还是结构化数据提取,所有功能最终都会归结为一次 HTTP 请求。先跑通 API,才能验证模型能力、测试响应延迟、估算调用成本,后续的产品设计和技术架构才有锚点。
目前主流的三家大模型 API 分别是 OpenAI(GPT 系列)、Anthropic(Claude 系列)和 Google(Gemini 系列)。它们在接入方式上高度相似,但在请求格式、流式协议细节和错误码定义上各有差异。本文将从零开始,逐步讲解如何接入这三家 API,并覆盖 Key 管理、流式响应、错误处理等工程化环节。
主流大模型 API 一览
OpenAI API
OpenAI 是最早开放商用 API 的大模型厂商,其接口设计已经成为事实上的行业标准。GPT-4o、GPT-4.1 等模型覆盖了文本生成、视觉理解、函数调用(Function Calling)、结构化输出等场景。OpenAI 的 API 提供两种主要端点:经典的 Chat Completions API(/v1/chat/completions)和新推出的 Responses API(/v1/responses)。后者是 OpenAI 在 2025 年推出的统一接口,将文本生成、工具调用、文件搜索等能力合并到一个端点中。
- 官网:https://platform.openai.com
- SDK:
openai(Python / Node.js / TypeScript) - 计费:按 token 用量计费,支持预充值和账单后付
Anthropic Claude API
Anthropic 的 Claude 系列以长上下文(最高 200K tokens)和安全性著称。Claude API 使用 Messages API 格式(/v1/messages),与 OpenAI 的 Chat Completions 在结构上有明显差异,但在语义上可以一一对应。Anthropic 也提供了 OpenAI 兼容层,允许开发者用 OpenAI SDK 直接调用 Claude,降低迁移成本。
- 官网:https://console.anthropic.com
- SDK:
anthropic(Python / TypeScript) - 计费:按 token 用量计费,支持按量付费和预付额度
Google Gemini API
Google 的 Gemini 系列以多模态能力见长,原生支持文本、图像、音频和视频输入。Gemini API 的端点为 generateContent(REST)或通过 Google Gen AI SDK 调用。Google 也提供了 OpenAI 兼容端点,开发者可以用现有的 OpenAI SDK 只需修改三行配置即可切换到 Gemini。
- 官网:https://ai.google.dev
- SDK:
google-genai(Python / TypeScript) - 计费:提供免费层(有速率限制),付费按 token 用量计费
三家 API 核心对比
| 维度 | OpenAI | Anthropic | Google Gemini |
|---|---|---|---|
| 主模型 | GPT-4o / GPT-4.1 | Claude Sonnet 4 / Opus 4 | Gemini 2.5 Pro / Flash |
| API 端点 | /v1/chat/completions | /v1/messages | /v1beta/models/{model}:generateContent |
| 最大上下文 | 128K tokens | 200K tokens | 1M tokens |
| 流式协议 | SSE(text/event-stream) | SSE(text/event-stream) | SSE / HTTP chunked |
| OpenAI 兼容 | ✅ 原生 | ✅ 兼容层 | ✅ 兼容端点 |
| 免费层 | ❌ | ❌ | ✅ 有速率限制 |
| SDK 语言 | Python / Node / TypeScript | Python / TypeScript | Python / TypeScript / Java |
| 函数调用 | ✅ | ✅(Tool Use) | ✅ |
| 视觉输入 | ✅ | ✅ | ✅(原生多模态) |
API 接入步骤
接入任何一家大模型 API,流程都可以分为四步:注册账号、获取 API Key、安装 SDK、发送第一个请求。
第一步:注册账号
- OpenAI:访问 https://platform.openai.com/signup 注册,需要绑定信用卡或购买额度。
- Anthropic:访问 https://console.anthropic.com 注册,通过 Credit 充值后使用。
- Google Gemini:访问 https://aistudio.google.com/apikey 使用 Google 账号登录即可获取免费 API Key。
需要注意的是,部分厂商对不同国家/地区的注册有限制。出海产品通常需要使用海外主体注册,或使用虚拟信用卡服务完成支付绑定。
第二步:获取 API Key
注册完成后,在平台的 API Keys 页面创建新的 Key。每个平台的操作路径略有不同:
- OpenAI:Dashboard → API keys → Create new secret key
- Anthropic:Settings → API Keys → Create Key
- Google Gemini:Google AI Studio → Get API key → Create API key
API Key 只在创建时显示一次,务必立即复制保存。
第三步:安装 SDK
以 Node.js / TypeScript 项目为例:
# OpenAI
pnpm add openai
# Anthropic
pnpm add @anthropic-ai/sdk
# Google Gemini
pnpm add @google/genaiPython 项目同理:
# OpenAI
pip install openai
# Anthropic
pip install anthropic
# Google Gemini
pip install google-genai第四步:发送第一个请求
以下是使用各官方 SDK 发送一个简单请求的示例。
OpenAI(TypeScript):
import OpenAI from 'openai'
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'user', content: '用一句话解释什么是大模型' },
],
})
console.log(response.choices[0].message.content)Anthropic(TypeScript):
import Anthropic from '@anthropic-ai/sdk'
const client = Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
})
const response = await client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [
{ role: 'user', content: '用一句话解释什么是大模型' },
],
})
console.log(response.content[0].text)Google Gemini(TypeScript):
import { GoogleGenAI } from '@google/genai'
const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY })
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: '用一句话解释什么是大模型',
})
console.log(response.text)API Key 管理
API Key 是调用大模型服务的唯一凭证,一旦泄露会导致资金损失和数据安全风险。在生产环境中管理 API Key 需要遵循以下原则。
安全存储
永远不要把 API Key 硬编码在源代码中,也不要提交到 Git 仓库。推荐的做法是使用环境变量或密钥管理服务:
# .env 文件(加入 .gitignore)
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxx
GOOGLE_API_KEY=AIzaSyxxxxxxxxxxxxxxxx// 通过环境变量读取
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})对于生产环境,建议使用专业的密钥管理服务:
| 管理方式 | 适用场景 | 代表工具 |
|---|---|---|
| 环境变量 | 本地开发、小型项目 | .env + dotenv |
| 密钥管理服务 | 生产环境、团队协作 | AWS Secrets Manager、Vault、Vercel Env |
| 配置中心 | 多环境、多服务 | Consul、Apollo Config |
| CI/CD Secrets | 自动化部署 | GitHub Secrets、GitLab CI Variables |
轮换策略
API Key 不应该「创建一次、永久使用」。建议建立定期轮换机制:
- 定期轮换:每 90 天生成新的 Key,旧 Key 在新 Key 验证通过后删除
- 泄露应急:一旦发现 Key 泄露,立即在平台撤销该 Key 并生成新 Key
- 最小权限:如果平台支持细粒度权限(如只读、特定模型访问),遵循最小权限原则
- 审计日志:定期检查 API 调用日志,发现异常调用模式及时处理
多 Key 管理
对于出海产品,可能需要同时管理多个 Key 以实现负载均衡或成本控制。常见的策略包括:
- 按功能分配:不同的功能模块使用不同的 Key,便于独立追踪用量和成本
- 按环境分配:开发、测试、生产环境使用不同的 Key
- 轮换池:维护一组 Key,调用时轮流使用,分散单个 Key 的速率限制压力
请求格式详解
三家 API 在请求格式上存在结构性差异,但核心参数高度一致。以下以 Anthropic 的 Messages API 为主线进行讲解,因为它在结构上最清晰,同时对照 OpenAI 和 Gemini 的对应写法。
Messages API 请求结构(Anthropic)
const response = await client.messages.create({
model: 'claude-sonnet-4-20250514', // 模型标识
max_tokens: 1024, // 最大输出 token 数(必填)
system: '你是一个专业的翻译助手', // 系统提示词(顶层字段)
messages: [ // 对话消息列表
{ role: 'user', content: '你好' },
{ role: 'assistant', content: '你好!有什么可以帮你的?' },
{ role: 'user', content: '把"Hello World"翻译成中文' },
],
temperature: 0.7, // 随机性(0-1)
top_p: 0.9, // 核采样
top_k: 40, // top-k 采样
stop_sequences: ['\n\n'], // 停止序列
stream: false, // 是否流式
metadata: { // 自定义元数据
user_id: 'user_123',
},
})核心参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✅ | 模型标识,如 claude-sonnet-4-20250514、gpt-4o |
messages | array | ✅ | 对话消息列表,每条包含 role 和 content |
max_tokens | number | ✅(Anthropic) | 最大输出 token 数,Anthropic 必填,OpenAI 可选 |
system | string | ❌ | 系统提示词,定义 AI 的角色和行为约束 |
temperature | number | ❌ | 控制输出随机性,0 表示确定性输出,1 表示更随机 |
top_p | number | ❌ | 核采样参数,与 temperature 二选一使用 |
stop_sequences | array | ❌ | 遇到这些字符串时停止生成 |
stream | boolean | ❌ | 是否启用流式响应,默认 false |
tools | array | ❌ | 工具定义列表,用于函数调用 |
消息角色
三家 API 都支持以下角色,但处理方式略有不同:
| 角色 | OpenAI | Anthropic | Gemini |
|---|---|---|---|
system | ✅ 作为 message | ✅ 顶层 system 字段 | ✅ 作为 systemInstruction |
user | ✅ | ✅ | ✅ |
assistant | ✅ | ✅ | ✅(model role) |
注意 Anthropic 要求消息必须从 user 角色开始,且 user 和 assistant 必须交替出现。OpenAI 则更灵活,允许连续的同角色消息。
content 字段的多模态写法
当输入包含图像等多模态内容时,content 可以从字符串变为数组:
// Anthropic 多模态请求
const response = await client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [
{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: base64String,
},
},
{
type: 'text',
text: '描述这张图片的内容',
},
],
},
],
})流式响应处理
大模型生成一段完整回复通常需要数秒甚至更长时间。如果使用非流式请求,用户必须等待全部生成完毕才能看到任何内容。流式响应(Streaming)将回复拆分成小块逐次返回,让用户可以实时看到生成内容,体验接近「逐字打出」的效果。
SSE 协议基础
三家 API 的流式响应都基于 Server-Sent Events(SSE)协议。服务端返回的 Content-Type 为 text/event-stream,每个事件以 data: 开头,事件之间用空行分隔。
原始的 SSE 数据流大致如下:
data: {"type":"content_block_delta","delta":{"text":"你"}}
data: {"type":"content_block_delta","delta":{"text":"好"}}
data: {"type":"content_block_delta","delta":{"text":"!"}}
data: {"type":"message_stop"}
每个 data: 行是一个 JSON 对象,包含一小段生成的文本(通常是一个 token 或几个字符)。最后一行是一个结束事件,表示生成完成。
使用 SDK 处理流式响应
官方 SDK 已经封装了 SSE 的解析逻辑,开发者只需关注内容处理。
OpenAI 流式调用:
const stream = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: '写一首关于春天的诗' }],
stream: true,
})
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content ?? ''
process.stdout.write(delta) // 逐块输出到终端
}Anthropic 流式调用:
const stream = await client.messages.stream({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: '写一首关于春天的诗' }],
})
for await (const event of stream) {
if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
process.stdout.write(event.delta.text)
}
}Google Gemini 流式调用:
const response = await ai.models.generateContentStream({
model: 'gemini-2.5-flash',
contents: '写一首关于春天的诗',
})
for await (const chunk of response) {
process.stdout.write(chunk.text ?? '')
}在前端实时展示流式内容
在 Web 应用中,通常使用 Next.js Route Handler 或 Express 作为中间层,将流式内容通过 SSE 转发给前端。
服务端(Next.js Route Handler):
// app/api/chat/route.ts
import Anthropic from '@anthropic-ai/sdk'
const client = Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
export async function POST(req: Request) {
const { messages } = await req.json()
const stream = await client.messages.stream({
model: 'claude-sonnet-4-20250514',
max_tokens: 2048,
messages,
})
return new Response(
new ReadableStream({
async start(controller) {
for await (const event of stream) {
if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
const text = event.delta.text
controller.enqueue(
new TextEncoder().encode(`data: ${JSON.stringify({ text })}\n\n`)
)
}
}
controller.enqueue(new TextEncoder().encode('data: [DONE]\n\n'))
controller.close()
},
}),
{
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
},
}
)
}前端(使用 fetch 消费 SSE):
async function sendMessage(userMessage: string) {
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({
messages: [{ role: 'user', content: userMessage }],
}),
})
const reader = response.body?.getReader()
const decoder = new TextDecoder()
while (reader) {
const { done, value } = await reader.read()
if (done) break
const text = decoder.decode(value)
const lines = text.split('\n').filter(line => line.startsWith('data: '))
for (const line of lines) {
const data = line.slice(6)
if (data === '[DONE]') return
const { text: chunk } = JSON.parse(data)
// 将 chunk 追加到界面显示
appendToUI(chunk)
}
}
}错误处理和重试
大模型 API 在生产环境中会遇到各种错误,建立健壮的错误处理和重试机制是工程化的关键环节。
错误码分类
| 错误类型 | HTTP 状态码 | 常见原因 | 处理策略 |
|---|---|---|---|
| 认证失败 | 401 | API Key 无效或过期 | 检查 Key,不要重试 |
| 权限不足 | 403 | Key 没有对应接口的权限 | 检查权限配置 |
| 参数错误 | 400 | 请求参数格式不正确 | 检查请求体,不要重试 |
| 速率限制 | 429 | 超出 RPM/TPM 限制 | 等待后重试,使用指数退避 |
| 服务过载 | 529 | 服务端负载过高 | 等待后重试 |
| 服务端错误 | 500 | 服务内部异常 | 短暂等待后重试 |
| 请求超时 | — | 网络问题或请求过大 | 减小请求大小,增加超时时间 |
| 上下文过长 | 400 / 413 | 输入超出模型上下文窗口 | 截断或摘要历史消息 |
指数退避重试
对于可重试的错误(429、500、529),推荐使用指数退避(Exponential Backoff)策略:
async function withRetry<T>(
fn: () => Promise<T>,
options: { maxRetries?: number; baseDelay?: number } = {}
): Promise<T> {
const { maxRetries = 3, baseDelay = 1000 } = options
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn()
} catch (error) {
if (attempt === maxRetries) throw error
// 只对可重试的错误进行重试
if (isRetryable(error)) {
const delay = baseDelay * Math.pow(2, attempt)
// 添加随机抖动,避免多个请求同时重试
const jitter = Math.random() * 1000
await new Promise(resolve => setTimeout(resolve, delay + jitter))
} else {
throw error
}
}
}
throw new Error('Unreachable')
}
function isRetryable(error: unknown): boolean {
if (error instanceof Error) {
const status = (error as any).status
return status === 429 || status === 500 || status === 529
}
return false
}
// 使用
const response = await withRetry(() =>
client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: '你好' }],
})
)超时控制
大模型请求的响应时间不可预测,必须设置超时以避免请求无限挂起:
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), 60_000) // 60 秒超时
try {
const response = await client.messages.create(
{
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: '你好' }],
},
{ signal: controller.signal }
)
} catch (error) {
if (error instanceof DOMException && error.name === 'AbortError') {
console.error('请求超时,请稍后重试')
}
} finally {
clearTimeout(timeoutId)
}内容安全过滤
大模型 API 可能因为输入或输出触发安全过滤(Content Filter),返回的内容不完整或被拒绝。处理这类情况需要:
- 检查响应的
stop_reason字段,判断是否因为安全过滤而中断 - 对用户展示友好的提示,而不是原始错误信息
- 在日志中记录被过滤的请求,用于分析和调整 Prompt
成本控制和用量监控
大模型 API 按 token 计费,如果不加控制,成本可能快速攀升。
Token 用量估算
在发送请求前,可以大致估算输入 token 数量。一个经验法则是:中文大约 1.5-2 个字符为一个 token,英文大约 4 个字符为一个 token。
// 粗略估算 token 数
function estimateTokens(text: string): number {
const chineseChars = (text.match(/[一-鿿]/g) || []).length
const otherChars = text.length - chineseChars
return Math.ceil(chineseChars / 1.5 + otherChars / 4)
}模型选择的成本权衡
| 场景 | 推荐模型 | 原因 |
|---|---|---|
| 日常对话、简单任务 | GPT-4o-mini / Claude Haiku / Gemini Flash | 成本低、速度快 |
| 复杂推理、长文写作 | GPT-4o / Claude Sonnet / Gemini Pro | 质量更高 |
| 超长文档处理 | Claude Sonnet(200K)/ Gemini Pro(1M) | 上下文窗口大 |
| 多模态理解 | Gemini Pro / GPT-4o | 原生多模态支持 |
| 高并发、低延迟 | GPT-4o-mini / Gemini Flash | 响应速度快、成本低 |
实战案例
案例一:构建多模型对话服务
一个出海 SaaS 产品需要支持 AI 对话功能,要求能在多个模型之间切换,并在某个模型不可用时自动降级。
// 模型提供商抽象
interface LLMProvider {
name: string
chat(messages: Message[], options?: ChatOptions): Promise<string>
chatStream(messages: Message[], options?: ChatOptions): AsyncIterable<string>
}
// 降级链实现
class LLMRouter {
private providers: LLMProvider[]
constructor(providers: LLMProvider[]) {
this.providers = providers
}
async chat(messages: Message[], options?: ChatOptions): Promise<string> {
for (const provider of this.providers) {
try {
return await provider.chat(messages, options)
} catch (error) {
console.warn(`${provider.name} 调用失败,尝试下一个:`, error)
continue
}
}
throw new Error('所有模型提供商均不可用')
}
}
// 使用
const router = new LLMRouter([
new AnthropicProvider(), // 首选
new OpenAIProvider(), // 降级 1
new GeminiProvider(), // 降级 2
])
const reply = await router.chat(messages)这种设计的好处在于:单一供应商故障不会导致产品完全不可用,同时可以根据成本和性能动态调整优先级。
案例二:流式翻译服务
一个文档翻译产品需要实时展示翻译进度,用户在原文提交后立即看到翻译结果逐步出现。
async function* translateStream(text: string, targetLang: string) {
const systemPrompt = `你是一个专业翻译。将用户输入翻译为${targetLang}。
要求:
- 保持原文的段落结构
- 专有名词保留原文并附翻译
- 只输出翻译结果,不要解释`
const stream = await client.messages.stream({
model: 'claude-sonnet-4-20250514',
max_tokens: 4096,
system: systemPrompt,
messages: [{ role: 'user', content: text }],
})
// 逐块 yield,上层可实时推送到前端
for await (const event of stream) {
if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
yield event.delta.text
}
}
}
// 在 Route Handler 中使用
export async function POST(req: Request) {
const { text, targetLang } = await req.json()
return new Response(
new ReadableStream({
async start(controller) {
const encoder = new TextEncoder()
for await (const chunk of translateStream(text, targetLang)) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ text: chunk })}\n\n`)
)
}
controller.enqueue(encoder.encode('data: [DONE]\n\n'))
controller.close()
},
}),
{
headers: { 'Content-Type': 'text/event-stream' },
}
)
}大模型 API 调用流程
以下流程图展示了一次完整的 API 调用过程,包括请求构建、发送、流式处理和错误重试。
SDK 与工具生态对比
| 工具 / SDK | 类型 | 特点 | 适用场景 |
|---|---|---|---|
openai (官方) | SDK | 覆盖 OpenAI 全系模型,支持 Responses API | OpenAI 模型直接调用 |
@anthropic-ai/sdk (官方) | SDK | Anthropic 原生接口,流式处理完善 | Claude 模型直接调用 |
@google/genai (官方) | SDK | Google Gen AI 统一接口 | Gemini 模型直接调用 |
| LangChain | 框架 | 多模型抽象层,支持链式调用 | 复杂 AI 应用、Agent |
| LiteLLM | 代理 | 统一 100+ 模型的 OpenAI 格式接口 | 多模型统一网关 |
| Vercel AI SDK | 框架 | React/Next.js 深度集成,流式 UI 组件 | Web 应用快速开发 |
| OpenRouter | 服务 | 统一 API 访问多家模型,按量计费 | 快速原型、模型对比 |
接入前检查清单
在将大模型 API 集成到生产环境之前,逐项确认以下清单:
- API Key 存储在环境变量或密钥管理服务中,未硬编码在源代码中
-
.env文件已加入.gitignore,不会被提交到版本控制 - 已设置请求超时时间(建议 30-120 秒,根据模型和场景调整)
- 已实现指数退避重试机制,覆盖 429、500、529 等可重试错误
- 流式响应已做前端实时展示处理,包含结束事件判断
- 已实现 token 用量监控和成本预警机制
- 已处理内容安全过滤的异常情况,对用户展示友好提示
- 生产环境使用模型版本标识(如
claude-sonnet-4-20250514),而非别名(如claude-sonnet-4),避免模型升级导致行为变化 - 已配置速率限制感知的请求队列,避免在高峰期大量 429 错误
- 已实现多模型降级策略,单一供应商故障不影响产品可用性
- 日志中记录了每次 API 调用的模型、token 用量、延迟和错误信息
- 已对输入长度进行截断或摘要处理,避免超出模型上下文窗口
参考资料
- OpenAI API 官方文档 - OpenAI API 的完整参考文档,包含所有端点、参数和示例
- Anthropic API 官方文档 - Claude API 的完整参考文档,包含 Messages API 详解
- Google Gemini API 官方文档 - Gemini API 的接入指南和多模态能力说明
- Streaming API Responses - OpenAI Developers - OpenAI 流式响应官方指南
- How Streaming LLM APIs Work - Simon Willison - 深入讲解 LLM API 流式传输的底层原理
- The Complete Guide to Streaming LLM Responses - 从 SSE 到实时 UI 的完整前端实现指南
- Using SSE to Stream LLM Responses in Next.js - Upstash - Next.js 环境下实现 SSE 流式响应的实战教程
- OpenAI vs Anthropic vs Google: 三大 LLM API 深度对比 - 三家 API 的统一兼容方案与架构设计思路