API 调用实践
直接调用模型 API 时的常用写法:基础调用、流式响应、工具调用,以及错误处理、限流、密钥配置和费用控制。框架与 SDK 的选型见 AI 框架与 SDK。
主流 AI API
Anthropic Claude API
Claude 是 Anthropic 开发的 AI 助手,提供强大的对话和内容生成能力。
官方文档: platform.claude.com/docs
可用模型及其 ID 以官方 Models overview 为准,下文示例使用 claude-opus-5-5。
基础调用
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY, // 默认就读取这个环境变量,可省略
})
const message = await client.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Hello, Claude!' },
],
})
// content 是内容块数组(可能包含 thinking 等块),按 type 取出文本
for (const block of message.content) {
if (block.type === 'text') {
console.log(block.text)
}
}流式响应
const stream = client.messages
.stream({
model: 'claude-opus-5-5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello!' }],
})
.on('text', (text) => {
process.stdout.write(text)
})
// 流结束后拿到完整消息(含 usage)
const finalMessage = await stream.finalMessage()只需要原始事件、不需要 SDK 帮忙拼装最终消息时,也可以用 client.messages.create({ ..., stream: true }),遍历事件时判断 event.type === 'content_block_delta' && event.delta.type === 'text_delta'。
工具调用
const response = await client.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1024,
tools: [
{
name: 'get_weather',
description: '获取指定城市的天气信息',
input_schema: {
type: 'object',
properties: {
city: {
type: 'string',
description: '城市名称',
},
},
required: ['city'],
},
},
],
messages: [
{ role: 'user', content: '北京今天天气怎么样?' },
],
})
// stop_reason 为 'tool_use' 时,执行对应工具,再把结果作为 tool_result 发回
if (response.stop_reason === 'tool_use') {
const toolUse = response.content.find(
(block): block is Anthropic.ToolUseBlock => block.type === 'tool_use',
)
console.log(toolUse?.name, toolUse?.input) // get_weather { city: '北京' }
}不想手写这个循环,可以用 SDK 的 client.beta.messages.toolRunner() 配合 betaZodTool 定义工具,由 SDK 自动执行工具并继续对话,见 TypeScript SDK 文档。
OpenAI API
OpenAI 提供 GPT 系列模型的 API 接口。
官方文档: developers.openai.com/api/docs
Responses API
OpenAI 推荐新项目使用 Responses API;Chat Completions(openai.chat.completions.create)仍会长期支持。
import OpenAI from 'openai'
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})
const response = await openai.responses.create({
model: 'gpt-6-astra',
instructions: 'You are a helpful assistant.',
input: 'Hello!',
})
console.log(response.output_text)流式响应
const stream = await openai.responses.create({
model: 'gpt-6-astra',
input: 'Hello!',
stream: true,
})
for await (const event of stream) {
if (event.type === 'response.output_text.delta') {
process.stdout.write(event.delta)
}
}API 最佳实践
1. 错误处理
SDK 会按状态码抛出不同的错误类,用 instanceof 判断,不要去匹配错误信息字符串:
import Anthropic from '@anthropic-ai/sdk'
try {
const response = await client.messages.create({...})
}
catch (error) {
if (error instanceof Anthropic.RateLimitError) {
// 429:触发速率限制
console.error('Rate limit exceeded')
}
else if (error instanceof Anthropic.InternalServerError) {
// 5xx:服务端错误
console.error('Server error')
}
else if (error instanceof Anthropic.APIError) {
console.error(`API error ${error.status}:`, error.message)
}
throw error
}其他常见错误类:BadRequestError(400)、AuthenticationError(401)、PermissionDeniedError(403)、NotFoundError(404)、APIConnectionError(网络错误)。
2. 重试策略
SDK 内置了指数退避重试,默认重试 2 次,覆盖连接错误、408、409、429 和 5xx,不需要自己再包一层:
// 全局配置
const client = new Anthropic({
maxRetries: 5, // 默认 2,设为 0 关闭重试
timeout: 60 * 1000, // 单位毫秒,默认 10 分钟
})
// 单次请求覆盖
await client.messages.create(
{
model: 'claude-opus-5-5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello!' }],
},
{ maxRetries: 3 },
)超时的请求同样会被重试,所以最坏耗时约为 timeout × (maxRetries + 1)。
3. 速率限制
import pLimit from 'p-limit'
const limit = pLimit(5) // 最多 5 个并发请求
const tasks = prompts.map(prompt =>
limit(() => client.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
})),
)
const results = await Promise.all(tasks)环境变量
配置 API Keys
# .env
ANTHROPIC_API_KEY=sk-ant-xxx
OPENAI_API_KEY=sk-xxx读取配置
import { config } from 'dotenv'
config()
const anthropicKey = process.env.ANTHROPIC_API_KEY
const openaiKey = process.env.OPENAI_API_KEYNode.js 20.6+ 也可以不装 dotenv,直接用 node --env-file=.env app.js 加载。
费用优化
1. 选择合适的模型
// 简单任务使用较小模型
const response = await client.messages.create({
model: 'claude-haiku-5-5', // 更便宜、更快
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
})2. 控制 Token 使用
const response = await client.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1024, // 输出上限,思考 token 也计入其中
output_config: { effort: 'low' }, // 投入程度:low / medium / high / xhigh / max
messages: [{ role: 'user', content: prompt }],
})当前模型默认开启自适应思考,effort 是控制思考深度和整体 token 消耗的主要手段:简单任务调低,复杂任务调高。max_tokens 是硬上限,设得太小会把回答截断。
3. 缓存结果
const cache = new Map<string, string>()
async function cachedGenerate(prompt: string) {
if (cache.has(prompt)) {
return cache.get(prompt)
}
const response = await client.messages.create({...})
const text = response.content
.filter((block): block is Anthropic.TextBlock => block.type === 'text')
.map(block => block.text)
.join('')
cache.set(prompt, text)
return text
}4. Prompt Caching
请求之间重复的长前缀(系统提示、长文档、工具定义)可以交给服务端缓存,命中后这部分输入只按基础输入价的 10% 计费(Opus 5.5 / Sonnet 5.5 为 5%),缓存默认保留 5 分钟:
const response = await client.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1024,
cache_control: { type: 'ephemeral' }, // 自动缓存到最后一个可缓存的块
system: longDocument,
messages: [{ role: 'user', content: '总结这份文档的要点' }],
})
console.log(response.usage.cache_read_input_tokens) // 命中缓存的 token 数缓存是前缀匹配,前缀里任何一个字节变化(比如在系统提示里拼当前时间)都会让缓存失效;前缀太短(不足模型的最小长度)时不会缓存,也不会报错。详见 Prompt caching。
相关资源
- AI 框架与 SDK
- 开发工具 — API 测试、监控与本地模型
- 学习资源 — 各模型提供商的官方文档