LLM API 接口设计原则

从 REST 到 SSE,从认证到容错 —— 构建生产级大模型 API 的完整指南

0 总览:LLM API 的核心挑战

与传统 REST API 不同,LLM API 面临高延迟、流式输出、Token 计量、上下文窗口约束等独特挑战。设计一个「好用的」LLM API 需要在以下维度做权衡:

延迟 吞吐 成本 可靠性 易用性

1 通信协议选择

最基础也是最关键的决定 —— 用什么协议传输数据。

协议适用场景优点缺点
REST (JSON) 同步短回答、管理类接口 简单、工具链成熟、缓存友好 不支持原生流式,轮询浪费资源
SSE 流式对话生成 单向推送、浏览器原生支持、断线重连 仅服务端→客户端,不支持二进制
WebSocket 实时双向通信、语音对话 全双工、低延迟、二进制支持 需自行处理重连逻辑,复杂
gRPC 内部微服务调用 强类型、高性能、双向流 浏览器支持弱,调试不便
推荐方案 对外 API 采用 REST + SSE 组合:短请求用 REST,长生成用 SSE。内部服务用 gRPC。90% 的 LLM 平台(OpenAI、Anthropic、Gemini)都走这条路。

2 认证与鉴权

保护 API 不被滥用,同时保持接入简单。

方案适用场景说明
API Key (Bearer Token)最通用简单,放在 Authorization: Bearer sk-xxx
OAuth 2.0第三方应用授权码流程,适合让用户授权
JWT + 签名分发密钥服务端签发,客户端带签名请求,防篡改
mTLS企业级双向证书认证,高安全场景
安全要点 API Key 不应出现在 URL 参数中(会被日志记录);建议支持 Key 轮转(旧 Key 保留一段时间过渡);按 Key 维度做用量统计和限流。

3 请求/响应模型设计

一个良好的请求结构应同时支持简单场景和高级定制。

3.1 核心请求参数

// POST /v1/chat/completions
{
  "model":       "gpt-4o",                // 模型选择(必填)
  "messages":    [                           // 对话历史(必填)
    { "role": "system",  "content": "..." },
    { "role": "user",    "content": "..." }
  ],
  "stream":      true,                    // 是否流式输出
  "temperature": 0.7,                     // 随机性控制
  "max_tokens":  4096,                    // 最大输出 token 数
  "top_p":       0.95,                    // 核采样阈值
  "tools":       [...],                     // Function Calling 工具定义
  "user":        "user_123"               // 终端用户标识(用于监控/滥用检测)
}

3.2 非流式响应 vs 流式响应

// 非流式 — 一次返回完整结果
{
  "id":      "chatcmpl-xxx",
  "object":  "chat.completion",
  "created": 1717401600,
  "model":   "gpt-4o",
  "choices": [{
    "index":        0,
    "message":      { "role": "assistant", "content": "..." },
    "finish_reason": "stop"
  }],
  "usage":   { "prompt_tokens": 42, "completion_tokens": 128, "total_tokens": 170 }
}
// 流式 (SSE) — 逐 token 推送
data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"你"}}]}
data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"好"}}]}
data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"!"}}]}
data: {"id":"chatcmpl-xxx","choices":[{"delta":{},"finish_reason":"stop"}]}
data: [DONE]
设计考量 流式响应的 delta 字段只包含增量,前端需要自己拼接。最后一条带 finish_reason 表示结束。有些平台会在最后一条额外返回 usage 信息。

4 采样参数设计

控制模型「创造力」与「确定性」的平衡。

参数作用典型范围使用建议
temperature控制随机性,越高越「放飞」0 ~ 2代码/事实类用 0~0.3,创意写作用 0.7~1.0
top_p (核采样)只从累计概率 ≥ p 的 token 中采样0 ~ 1一般设 0.9~0.95,与 temperature 二选一
top_k只从概率最高的 k 个 token 中采样1 ~ NGemini 等部分模型支持
max_tokens生成 token 上限1 ~ 上下文窗口防止无限生成、控制成本
stop停止序列字符串数组如 ["\n\n", "###"] 遇到就停
presence_penalty惩罚已出现的 token-2 ~ 2正值鼓励说新内容,避免重复
frequency_penalty按频率惩罚重复-2 ~ 2比 presence_penalty 更激进
seed随机种子整数确保可复现输出
兼容性注意 并非所有参数所有模型都支持。建议采用「宽松接受、严格验证」策略:未知参数忽略并记录日志,已知参数做范围校验。

5 Function Calling / Tool Use 设计

让 LLM 能调用外部工具,这是 Agent 的基石。

用户提问 LLM 决定调用工具 客户端执行函数 结果返回 LLM 生成最终回答

工具定义示例

{
  "type": "function",
  "function": {
    "name":        "get_weather",
    "description": "获取指定城市的天气信息",
    "parameters": {
      "type": "object",
      "properties": {
        "city": { "type": "string", "description": "城市名" },
        "unit": { "type": "string", "enum": ["celsius","fahrenheit"] }
      },
      "required": ["city"]
    }
  }
}
最佳实践 description 写得越具体,LLM 越不容易选错工具。字段级描述比顶层描述更有价值。支持 strict 模式确保输出格式合规。建议限制同时可用的工具数量(≤ 25 个为宜)。

6 错误处理设计

错误信息应该让调用方能「程序化处理」,而非只能人工阅读。

HTTP 状态码含义典型场景
200成功正常返回
400请求参数错误temperature 超出范围、messages 格式错误
401认证失败API Key 缺失/无效/过期
402余额不足账户欠费
403权限不足地区限制、模型未开放
429速率限制请求过于频繁 —— 返回 Retry-After 头
500服务端错误模型推理异常 —— 客户端应重试
503服务不可用过载、维护 —— 返回 Retry-After
// 错误响应体规范
{
  "error": {
    "type":    "invalid_request_error",   // 机器可读的错误类型
    "code":    "context_length_exceeded",  // 具体错误码
    "message": "上下文超过 128k token 限制", // 人类可读的描述
    "param":   "messages"                   // 出错的参数名(可选)
  }
}

7 速率限制 (Rate Limiting)

保护后端资源,保证公平使用。

维度说明示例
RPM (每分钟请求数)限制调用频率免费用户 20 RPM,付费 500 RPM
TPM (每分钟 Token 数)按 token 消耗限制免费用户 40K TPM,付费 1M TPM
并发数同时进行的请求上限排队机制,超限返回 429
QPD (每天配额)日总请求上限适用于固定的配额套餐
响应头规范 服务器应在响应中包含 X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset 等标准头,方便客户端做自适应限速。

8 API 版本控制

随着模型迭代,API 必然要演进。如何兼容旧版?

策略示例评价
URL 路径版本/v1/chat/v2/chat最直观,OpenAI 采用
Header 版本API-Version: 2024-06-01灵活,Anthropic 采用(日期版)
模型名版本model 参数区分行为适合 model 级别的差异
查询参数版本?version=2简单但不够 RESTful
核心原则 V1 不应立即废弃。保持至少 3~6 个月的并行支持期。废弃时通过响应头 SunsetDeprecation 提前通知。

9 上下文窗口管理

LLM 的上下文窗口有限(从 4K 到 1M+ tokens),API 需要帮助用户管理。

10 多模态支持

现代 LLM 能处理图片、音频、视频。API 如何优雅地支持?

// Content Part 模式 —— 一条消息可混合文本+图片
{
  "role": "user",
  "content": [
    { "type": "text", "text": "这张图片里有什么?" },
    { "type": "image_url", "image_url": { "url": "https://..." } },
    { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,..." } }
  ]
}

11 高级:缓存、幂等与可观测性

生产环境的必备能力。

11.1 语义缓存

对相似的问题(非完全相同)返回缓存结果。实现方式:用 Embedding 向量计算问题相似度,超过阈值命中缓存。代价是牺牲一点准确性换取 50%~80% 的延迟和成本降低。

11.2 请求幂等

通过 X-Idempotency-Key 请求头实现:相同 key 的重复请求返回已缓存的结果,避免网络重试导致重复计费。服务端保留时效一般设为 24 小时。

11.3 可观测性

  • 每个请求返回唯一 id:便于排查问题
  • 日志记录:输入/输出(脱敏)、延迟、token 用量
  • Metrics:TTFT(首 token 延迟)、TPOT(token 间延迟)、吞吐量、错误率
  • 成本追踪:按 user 参数区分终端用户,精确计费

11.4 结构化输出

通过 response_format: { "type": "json_schema", "json_schema": {...} } 约束模型输出格式。底层通常通过 grammar-based sampling 或 constrained decoding 实现,保证输出 100% 符合 Schema。

12 总结:一张总览表

设计维度核心决策业界主流做法
协议REST + SSEOpenAI / Anthropic / Gemini 一致
认证Bearer Token (API Key)最通用,OAuth 仅授权场景
流式SSE,delta 增量逐 token 推送,EventSource 原生支持
错误统一 error 对象 + 标准 HTTP 码type + code + message + param
限流RPM + TPM 双维度429 + Retry-After 头
版本URL 路径 (/v1) 或日期 HeaderOpenAI 用路径,Anthropic 用日期
工具调用JSON Schema 定义 functionOpenAI / Gemini 统一标准
多模态Content Part (type: text/image_url)OpenAI 首创,已成事实标准
缓存语义缓存 + 请求幂等高 QPS 场景必备
输出格式structured outputs (json_schema)OpenAI / Gemini / Anthropic 均已支持

最终的 API 设计不是单纯的「技术选型」,而是在开发者体验、系统可靠性、成本控制、安全性之间找到平衡。好的 API 让开发者感觉「理所当然就该这样」——那说明你设计对了。