全部笔记All notes

OpenAI Chat Completions API 详解

阅读 14m 52s14m 52s read

Chat Completions API 是 OpenAI 最核心的对话接口,支持 GPT-4、GPT-4o、GPT-3.5-Turbo 等模型。该 API 已成为行业事实标准,被众多第三方服务兼容。


核心特点

  • 消息角色系统:通过 system/user/assistant 角色构建对话
  • 流式输出:支持 SSE 实时返回生成内容
  • 工具调用:支持 Function Calling 扩展模型能力
  • 结构化输出:支持 JSON Mode 和 JSON Schema 约束输出格式
  • 多模态:GPT-4o 支持图像输入

为什么 Chat Completions API 如此重要?

Chat Completions API 不仅是 OpenAI 的核心接口,更是整个大模型行业的事实标准。理解这一点对于开发者至关重要:

1. 行业标准地位

几乎所有的 LLM 工具和框架(LangChain、LlamaIndex、Semantic Kernel 等)都以 OpenAI 格式作为首选支持。这意味着学会 Chat Completions API,你就掌握了与大多数模型交互的通用方式。

2. 广泛的兼容性

许多第三方模型提供商(如 Azure OpenAI、Groq、Together AI、Anyscale)都提供 OpenAI 兼容的 API。你只需要更换 base_url 和 API key,代码几乎不需要修改。

3. 成熟的生态系统

OpenAI SDK 是最成熟、文档最完善的 LLM SDK。Python 和 Node.js 版本都有完整的类型定义、错误处理和流式支持。

4. 持续演进

OpenAI 不断为 Chat Completions API 添加新功能(如 Structured Outputs、Vision),同时保持向后兼容。这种稳定性对于生产环境至关重要。


端点与认证

端点

POST https://api.openai.com/v1/chat/completions

这是一个标准的 RESTful POST 端点。所有请求参数都通过 JSON 请求体传递,响应也是 JSON 格式。

认证

Authorization: Bearer $OPENAI_API_KEY

OpenAI 使用 Bearer Token 认证方式,这是 OAuth 2.0 规范的标准做法。API Key 以 sk- 开头,需要妥善保管,不要泄露到公开代码库中。

安全建议:

  • 使用环境变量存储 API Key,不要硬编码在代码中
  • 在服务端调用 API,不要在前端暴露 Key
  • 定期轮换 API Key
  • 使用 OpenAI 的 Project API Keys 功能限制权限范围

请求参数

请求参数分为必需参数和可选参数。理解每个参数的作用对于优化模型输出至关重要。

必需参数

参数类型说明
modelstring模型 ID,如 gpt-4o、gpt-4-turbo、gpt-3.5-turbo
messagesarray消息数组

model 参数说明:

模型 ID 决定了使用哪个模型处理请求。不同模型在能力、速度、价格上有显著差异。模型 ID 通常包含版本信息,如 gpt-4o-2024-08-06 表示 2024 年 8 月 6 日发布的版本。使用不带日期的 ID(如 gpt-4o)会自动使用最新稳定版本。

messages 参数说明:

messages 是对话的核心,包含了完整的对话历史。模型会根据这些消息理解上下文并生成回复。消息顺序很重要,通常是 system → user → assistant → user → assistant… 的模式。

可选参数

参数类型默认值说明
temperaturenumber1随机性 0-2,越高越随机
top_pnumber1核采样,与 temperature 二选一
ninteger1生成几个回复
streambooleanfalse是否流式输出
stopstring/arraynull停止词
max_tokensinteger-最大生成 token 数
max_completion_tokensinteger-最大完成 token 数(新版)
presence_penaltynumber0存在惩罚 -2.0 到 2.0
frequency_penaltynumber0频率惩罚 -2.0 到 2.0
toolsarray-工具/函数定义
tool_choicestring/objectauto工具选择策略
response_formatobject-响应格式(JSON mode)
seedinteger-随机种子,用于可复现输出

关键参数详解:

temperature(温度)

控制输出的随机性。值越低,输出越确定、越集中;值越高,输出越多样、越有创意。

  • temperature=0:几乎确定性输出,适合需要一致性的场景(如代码生成、数据提取)
  • temperature=0.7:平衡创意和一致性,适合大多数对话场景
  • temperature=1.5+:高度随机,适合创意写作、头脑风暴

top_p(核采样)

另一种控制随机性的方式。top_p=0.9 表示只从累积概率达到 90% 的 token 中采样。通常建议只调整 temperature 或 top_p 其中之一,不要同时调整。

presence_penalty 和 frequency_penalty

这两个参数用于控制重复:

  • presence_penalty:惩罚已经出现过的 token,鼓励模型谈论新话题
  • frequency_penalty:根据 token 出现的频率进行惩罚,减少重复用词

正值会减少重复,负值会增加重复。通常设置在 0 到 1 之间。

seed(随机种子)

设置 seed 可以使输出更可复现。相同的 seed + 相同的输入通常会产生相同的输出(但不是 100% 保证)。这对于调试和测试很有用。


消息格式

消息(messages)是 Chat Completions API 的核心概念。每条消息都有一个角色(role)和内容(content),模型根据消息序列理解对话上下文。

角色类型

角色说明
system系统指令,设定 AI 行为
user用户消息
assistantAI 回复
tool工具调用结果

角色详解:

system(系统角色)

系统消息用于设定 AI 的行为、性格、能力边界。它通常放在消息数组的开头,对整个对话产生影响。好的系统提示可以显著提升模型表现。

系统消息的常见用途:

  • 定义 AI 的身份和专业领域
  • 设定回复的格式和风格
  • 规定 AI 应该做什么和不应该做什么
  • 提供背景知识和上下文

user(用户角色)

用户消息代表人类用户的输入。这是对话的驱动力,模型会针对用户消息生成回复。

assistant(助手角色)

助手消息代表 AI 的回复。在多轮对话中,你需要将之前的 AI 回复作为 assistant 消息包含在请求中,这样模型才能理解对话历史。

tool(工具角色)

工具消息用于返回函数调用的结果。当模型请求调用工具后,你执行工具并将结果以 tool 消息的形式返回给模型。

基础消息结构

{
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Hello!"}
  ]
}

多轮对话示例:

{
  "messages": [
    {"role": "system", "content": "你是一个友好的中文助手。"},
    {"role": "user", "content": "你好!"},
    {"role": "assistant", "content": "你好!有什么我可以帮助你的吗?"},
    {"role": "user", "content": "今天天气怎么样?"},
    {"role": "assistant", "content": "抱歉,我无法获取实时天气信息。你可以查看天气应用或网站获取准确的天气预报。"},
    {"role": "user", "content": "好的,谢谢!"}
  ]
}

多模态消息(图像)

GPT-4o 等视觉模型支持图像输入。图像可以通过 URL 或 Base64 编码传递。

{
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "What's in this image?"},
        {
          "type": "image_url",
          "image_url": {
            "url": "https://example.com/image.jpg",
            "detail": "high"
          }
        }
      ]
    }
  ]
}

图像参数说明:

  • url:图像的 URL 地址,或 data:image/jpeg;base64,{base64_data} 格式的 Base64 数据
  • detail:图像分析的详细程度
    • low:快速模式,消耗较少 token,适合简单识别
    • high:高清模式,消耗更多 token,适合需要细节的场景
    • auto:让模型自动选择

支持的图像格式: PNG、JPEG、GIF、WebP

图像大小限制: 单张图像最大 20MB,建议压缩到合理大小以节省成本


响应格式

理解响应格式对于正确解析模型输出、处理错误和监控使用量至关重要。

标准响应

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1677858242,
  "model": "gpt-4o-2024-08-06",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello! How can I help you today?"
      },
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 13,
    "completion_tokens": 9,
    "total_tokens": 22
  }
}

响应字段详解:

字段说明
id唯一标识符,用于日志追踪和问题排查
object对象类型,固定为 chat.completion
createdUnix 时间戳,表示响应创建时间
model实际使用的模型版本(可能与请求中的不同)
choices回复数组,通常只有一个元素(除非设置 n>1)
usageToken 使用统计,用于计费和监控

choices 数组说明:

  • index:回复的索引,从 0 开始
  • message:包含角色和内容的消息对象
  • logprobs:对数概率信息(需要在请求中启用)
  • finish_reason:生成停止的原因

usage 字段说明:

  • prompt_tokens:输入消息消耗的 token 数
  • completion_tokens:生成回复消耗的 token 数
  • total_tokens:总 token 数(用于计费)

finish_reason 值

值说明
stop正常结束或遇到停止词
length达到 max_tokens 限制
tool_calls模型调用了工具
content_filter内容被过滤

finish_reason 处理建议:

  • stop:正常情况,直接使用回复内容
  • length:回复被截断,可能需要增加 max_tokens 或让用户继续
  • tool_calls:需要执行工具并将结果返回给模型
  • content_filter:内容触发安全过滤,需要检查输入或调整提示词

流式传输 (SSE)

流式传输(Streaming)允许模型在生成过程中实时返回内容,而不是等待完整回复。这对于提升用户体验至关重要,用户可以看到”打字机效果”,而不是长时间等待。

为什么使用流式传输?

场景非流式流式
用户等待体验长时间空白等待实时看到生成内容
首字节时间数秒到数十秒通常 < 1 秒
长回复处理可能超时持续接收数据
用户中断无法中断可随时停止

请求

启用流式传输只需设置 stream: true:

{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "Hello"}],
  "stream": true
}

响应格式

流式响应使用 Server-Sent Events (SSE) 格式。每个事件以 data: 开头,包含一个 JSON 对象:

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1677858242,"model":"gpt-4o","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1677858242,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1677858242,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1677858242,"model":"gpt-4o","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]

流式响应特点:

  • 每个 chunk 的 object 是 chat.completion.chunk(而非 chat.completion)
  • 内容在 delta 字段中,而非 message 字段
  • 第一个 chunk 通常只包含 role
  • 后续 chunk 包含 content 片段
  • 最后一个 chunk 的 finish_reason 不为 null
  • 流结束时发送 data: [DONE]

注意事项:

  • 流式响应不包含 usage 字段(无法直接获取 token 统计)
  • 如需 token 统计,可设置 stream_options: {"include_usage": true}
  • 需要正确处理 SSE 格式,包括空行分隔和 data: 前缀

Function Calling / Tools

Function Calling(函数调用)是 Chat Completions API 最强大的功能之一,它允许模型在对话中调用外部函数或 API,从而扩展模型的能力边界。

工作原理

sequenceDiagram
    participant User as 用户
    participant App as 应用
    participant LLM as 模型
    participant Tool as 外部工具
    
    User->>App: 北京天气怎么样?
    App->>LLM: 发送消息 + 工具定义
    LLM->>App: 返回 tool_calls
    App->>Tool: 调用天气 API
    Tool->>App: 返回天气数据
    App->>LLM: 发送工具结果
    LLM->>App: 生成最终回复
    App->>User: 北京今天晴,22°C

模型本身不会执行函数,它只是决定应该调用哪个函数以及传递什么参数。实际的函数执行由你的应用程序完成。

定义工具

工具定义使用 JSON Schema 格式描述函数的名称、描述和参数:

{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "What's the weather in Beijing?"}],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather for a location",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "City name"
            },
            "unit": {
              "type": "string",
              "enum": ["celsius", "fahrenheit"]
            }
          },
          "required": ["location"]
        }
      }
    }
  ],
  "tool_choice": "auto"
}

工具定义要点:

  • name:函数名称,应该简洁明了,使用 snake_case
  • description:函数描述,这是模型决定是否调用的关键依据,要写清楚函数的用途
  • parameters:使用 JSON Schema 定义参数,包括类型、描述、枚举值、必填项等
  • strict:设为 true 可启用严格模式,保证参数完全符合 schema

tool_choice 选项:

值说明
auto模型自动决定是否调用工具(默认)
none禁止调用工具
required强制调用工具
{"type": "function", "function": {"name": "xxx"}}强制调用指定工具

工具调用响应

当模型决定调用工具时,响应中会包含 tool_calls 字段:

{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_abc123",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"location\": \"Beijing\", \"unit\": \"celsius\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}

注意事项:

  • content 通常为 null(模型选择调用工具而非直接回复)
  • arguments 是 JSON 字符串,需要解析
  • id 是工具调用的唯一标识,返回结果时需要引用
  • 模型可能同时调用多个工具(并行调用)

返回工具结果

执行工具后,需要将结果以 tool 角色的消息返回给模型:

{
  "messages": [
    {"role": "user", "content": "What's the weather in Beijing?"},
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [{"id": "call_abc123", "type": "function", "function": {"name": "get_weather", "arguments": "{\"location\": \"Beijing\"}"}}]
    },
    {
      "role": "tool",
      "tool_call_id": "call_abc123",
      "content": "{\"temperature\": 22, \"condition\": \"sunny\"}"
    }
  ]
}

关键点:

  • tool_call_id 必须与之前的 id 匹配
  • content 是工具执行的结果,通常是 JSON 字符串
  • 如果有多个工具调用,需要为每个调用返回对应的结果
  • 模型会根据工具结果生成最终的自然语言回复

JSON Mode

JSON Mode 强制模型输出有效的 JSON 格式,这在需要结构化数据的场景非常有用,如信息提取、数据转换、API 响应生成等。

为什么需要 JSON Mode?

默认情况下,模型可能输出:

  • 带有 markdown 代码块的 JSON(json ... )
  • 格式不完整的 JSON
  • 混合文本和 JSON 的内容

JSON Mode 保证输出是纯净的、可直接解析的 JSON。

启用 JSON 输出

{
  "model": "gpt-4o",
  "messages": [
    {"role": "system", "content": "Output valid JSON only."},
    {"role": "user", "content": "List 3 colors"}
  ],
  "response_format": {"type": "json_object"}
}

重要提示: 使用 JSON Mode 时,必须在 system 或 user 消息中明确提到 “JSON”,否则可能报错。

Structured Outputs(结构化输出)

Structured Outputs 是 JSON Mode 的增强版,不仅保证输出是 JSON,还保证输出符合指定的 JSON Schema。这是 2024 年 8 月引入的重要功能。

{
  "model": "gpt-4o-2024-08-06",
  "messages": [{"role": "user", "content": "List 3 colors with hex codes"}],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "colors",
      "schema": {
        "type": "object",
        "properties": {
          "colors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {"type": "string"},
                "hex": {"type": "string"}
              },
              "required": ["name", "hex"]
            }
          }
        },
        "required": ["colors"]
      }
    }
  }
}

Structured Outputs 的优势:

特性JSON ModeStructured Outputs
保证有效 JSON✅✅
保证符合 Schema❌✅
类型安全❌✅
必填字段保证❌✅

使用建议:

  • 简单场景使用 JSON Mode 即可
  • 需要严格数据结构时使用 Structured Outputs
  • Structured Outputs 需要 gpt-4o-2024-08-06 或更新的模型
  • Schema 中的所有字段默认都是 required,需要显式设置 required 数组

完整示例

cURL

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Hello!"}
    ],
    "temperature": 0.7,
    "max_tokens": 1000
  }'

Python

from openai import OpenAI

client = OpenAI()

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello!"}
    ],
    temperature=0.7,
    max_tokens=1000
)

print(response.choices[0].message.content)

Python 流式

from openai import OpenAI

client = OpenAI()

stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Write a haiku"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

Node.js

import OpenAI from 'openai';

const openai = new OpenAI();

const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'Hello!' }
  ],
  temperature: 0.7,
  max_tokens: 1000
});

console.log(response.choices[0].message.content);

错误处理

正确处理 API 错误是构建健壮应用的关键。OpenAI API 使用标准的 HTTP 状态码,并在响应体中提供详细的错误信息。

常见错误码

状态码说明
400请求格式错误
401API Key 无效
403无权限访问
429速率限制
500服务器错误
503服务过载

错误码详解:

400 Bad Request 请求格式有问题,常见原因:

  • JSON 格式错误
  • 缺少必需参数
  • 参数类型错误
  • 模型名称不存在

401 Unauthorized 认证失败,常见原因:

  • API Key 错误或过期
  • API Key 格式不正确
  • 未设置 Authorization 头

403 Forbidden 权限不足,常见原因:

  • 账户未开通某模型的访问权限
  • 组织/项目权限限制
  • 地区限制

429 Too Many Requests 触发速率限制,常见原因:

  • 请求频率过高(RPM 限制)
  • Token 使用量过大(TPM 限制)
  • 并发请求过多

500/503 Server Error 服务端问题,通常是临时性的,建议重试。

错误响应格式

{
  "error": {
    "message": "Invalid API Key",
    "type": "invalid_request_error",
    "param": null,
    "code": "invalid_api_key"
  }
}

错误字段说明:

  • message:人类可读的错误描述
  • type:错误类型分类
  • param:导致错误的参数名(如果适用)
  • code:机器可读的错误代码

错误处理最佳实践

from openai import OpenAI, APIError, RateLimitError, AuthenticationError

client = OpenAI()

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello"}]
    )
except AuthenticationError:
    print("API Key 无效,请检查配置")
except RateLimitError:
    print("触发速率限制,请稍后重试")
except APIError as e:
    print(f"API 错误: {e.message}")

模型列表

OpenAI 提供多种模型,各有特点和适用场景。选择合适的模型对于平衡性能和成本至关重要。

模型上下文窗口特点适用场景
gpt-4o128K最新旗舰,多模态复杂任务、图像理解
gpt-4o-mini128K快速经济简单对话、高并发
gpt-4-turbo128KGPT-4 增强版需要 GPT-4 能力但更快
gpt-48K/32K原版 GPT-4兼容旧代码
gpt-3.5-turbo16K快速经济型成本敏感场景
o1200K深度推理数学、编程、复杂逻辑
o1-mini128K轻量推理需要推理但成本敏感

模型持续更新,请查阅 OpenAI Models 获取最新列表。

模型详解

GPT-4o(推荐)

GPT-4o 是 OpenAI 当前的旗舰模型,“o” 代表 “omni”(全能)。它原生支持多模态输入(文本、图像),响应速度比 GPT-4 Turbo 快 2 倍,价格更低。对于大多数应用场景,GPT-4o 是最佳选择。

GPT-4o-mini

GPT-4o 的轻量版本,在保持较高质量的同时大幅降低成本。适合简单对话、内容分类、数据提取等不需要最强能力的场景。性价比极高。

o1 系列(推理模型)

o1 是 OpenAI 的推理模型,专门针对需要深度思考的任务优化。它会在回答前进行”思考”,适合数学证明、代码调试、复杂逻辑推理等场景。但响应时间较长,成本较高。

GPT-3.5-turbo

老一代模型,速度快、成本低,但能力明显弱于 GPT-4 系列。仍然适合一些简单场景,但建议新项目直接使用 GPT-4o-mini。

模型选择建议

简单对话/高并发 → gpt-4o-mini
通用任务 → gpt-4o
复杂推理/数学 → o1 / o1-mini
图像理解 → gpt-4o
成本优先 → gpt-3.5-turbo

选择决策树:

flowchart TD
    A[选择模型] --> B{需要图像理解?}
    B -->|是| C[gpt-4o]
    B -->|否| D{需要深度推理?}
    D -->|是| E{预算充足?}
    E -->|是| F[o1]
    E -->|否| G[o1-mini]
    D -->|否| H{任务复杂度?}
    H -->|高| C
    H -->|中| I[gpt-4o-mini]
    H -->|低| J[gpt-3.5-turbo]

最佳实践

1. 系统提示词设计

{
  "role": "system",
  "content": "你是一个专业的技术文档助手。回答要求:1. 简洁准确 2. 提供代码示例 3. 使用中文"
}

2. 控制输出长度

  • 设置合理的 max_tokens 避免浪费
  • 在 system prompt 中明确要求”简洁回答”

3. 处理长对话

  • 定期总结历史对话,压缩 context
  • 只保留最近 N 轮对话
  • 使用 tiktoken 库计算 token 数量

4. 错误重试策略

import time
from openai import RateLimitError

def call_with_retry(func, max_retries=3):
    for i in range(max_retries):
        try:
            return func()
        except RateLimitError:
            wait_time = 2 ** i  # 指数退避
            time.sleep(wait_time)
    raise Exception("Max retries exceeded")

相关指南


官方文档