Cookbook
聊天补全 Chat Completions 示例
Chat Completions API 接入 OfApp.cn 教程,覆盖 messages、system/user/assistant、curl、Python、JavaScript、stream、多轮对话、finish_reason、常见错误和上线前检查。
Chat Completions 是许多 OpenAI 兼容服务、AI 客户端和旧项目仍在使用的聊天请求形态。它的核心很简单:把一组 messages 发给模型,再从 choices[0].message.content 读取回复。
本文示例基于 OfApp.cn 的 OpenAI 兼容接口写法。Base URL 使用 https://api.ofapp.cn/v1。具体可用模型、价格、额度、套餐和能力,请以 OfApp.cn 控制台或官方文档为准。
| 项目 | 内容 |
|---|---|
| 阅读时间 | 约 8 分钟 |
| 更新时间 | 2026-07-03 |
| 适合场景 | OpenAI 兼容 API 连通性验证、旧项目迁移、AI 客户端配置、聊天功能封装、Prompt 学习 |
| 核心问题 | 如何用 messages 稳定组织一次聊天请求,并判断 OfApp.cn 兼容入口是否适合当前项目 |
| 你会完成 | curl、Python、JavaScript 三种最小请求,一份任务选择矩阵,以及 messages、finish_reason、stream 和上线前检查清单 |
| 边界提醒 | OfApp.cn 官方文档展示了 /v1/chat/completions 示例;具体可用模型、价格、额度、套餐、速率限制和能力边界请以 OfApp.cn 控制台或官方文档为准 |
| 读者 | 正在处理的问题 | 读完能得到什么 |
|---|---|---|
| 第一次接 API 的开发者 | 不确定 Base URL、Key、模型名怎么放 | 用最小请求确认接口能返回内容 |
| 迁移旧项目的人 | 项目里已经写了 chat.completions.create |
判断哪些配置可以替换,哪些能力要验证 |
| AI 客户端用户 | 客户端要求填写 OpenAI 兼容接口 | 理解 /v1/chat/completions 和模型名的关系 |
| 后端维护者 | 要把聊天能力接进服务端 | 建立错误处理、超时、日志脱敏和流式输出习惯 |
| Prompt 学习者 | 想理解 system、user、assistant 的位置 | 学会把指令、问题和历史对话分开组织 |
这张图提醒你把调试顺序拆开。只要最小请求没有稳定返回,就先不要叠加工具调用、长上下文、复杂 Prompt、数据库检索或业务侧状态管理。
Chat Completions 是什么
Section titled “Chat Completions 是什么”Chat Completions 是一种面向对话的生成接口。请求体通常包含:
| 字段 | 作用 | 调试建议 |
|---|---|---|
model |
指定要调用的模型 | 不要猜模型名,先用账号可用模型或控制台展示的名称 |
messages |
按顺序提供对话消息 | 最小验证只放一条 user 消息即可 |
stream |
是否开启流式输出 | 调试阶段先用 false,页面体验再打开 |
temperature |
控制输出随机性 | 业务场景要求稳定时调低 |
max_tokens |
限制输出长度 | 出现 finish_reason: "length" 时检查这里 |
OpenAI 官方文档中,Chat Completions 的响应会返回 choices 数组;每个 choice 包含 message 和 finish_reason。很多兼容服务也沿用这种结构,但边界能力仍要按服务商当前文档验证。
Chat Completions 任务选择矩阵
Section titled “Chat Completions 任务选择矩阵”Chat Completions 最适合那些已经围绕 messages 组织输入的场景。它不只服务聊天窗口,也常用于把一段材料转成可读回复、分类结果或办公初稿。
| 任务 | 推荐 messages 结构 | 第一次验证 | 主要风险 |
|---|---|---|---|
| 连通性测试 | 一条 user 消息 |
curl 最小请求能返回 choices[0].message.content |
一开始就加入复杂参数,导致问题难定位 |
| AI 客户端配置 | 客户端按 OpenAI 兼容格式生成 messages | 确认最终地址是 /v1/chat/completions |
客户端自动拼接 /v1,造成路径重复 |
| 多轮聊天 | system 固定边界,保留必要 user / assistant 历史 |
用 2 到 4 轮脱敏对话验证上下文效果 | 历史过长、旧信息冲突、成本不可控 |
| 办公初稿 | system 写格式和语气,user 放会议、邮件或资料摘要 |
先生成一份人工可复核初稿 | 敏感内容进入日志,缺少人工复核 |
| 旧项目迁移 | 保留原有 messages,替换 Base URL、Key 和模型名 | 先跑原有最小用例 | 模型名、工具调用或返回结构差异被忽略 |
| 流式聊天界面 | 非流式成功后再开启 stream: true |
终端或服务端先打印增量片段 | 代理缓冲、前端取消、中途断开未处理 |
如果新项目需要结构化输出、工具调用、多模态或代理式流程,可以同时评估 Responses API 示例。如果只是验证 Key、Base URL 和模型名,Chat Completions 仍然是一条短路径。
messages 怎么组织
Section titled “messages 怎么组织”messages 是 Chat Completions 的核心。它不是一段长文本,而是一段对话历史。
| role | 放什么内容 | 例子 |
|---|---|---|
system |
助手身份、回答风格、边界要求 | 你是一个简洁的中文技术助手。 |
user |
用户这轮提出的问题或任务 | 把这段会议记录整理成 5 个行动项。 |
assistant |
历史中模型已经说过的话 | 我已经整理出初稿,请确认负责人。 |
实用写法:
- 系统指令保持短而明确,不要把整份业务规则都塞进去。
- 用户输入和系统指令分开,方便日志、审计和 Prompt 版本管理。
- 多轮对话要保留必要历史,但过旧、重复、无关的内容应压缩或摘要。
- 如果某个兼容服务要求使用其他 role,按该服务当前文档调整。
messages 质量检查清单
Section titled “messages 质量检查清单”很多 Chat Completions 问题不是接口坏了,而是消息组织不清。上线前可以用这张表做一次自检。
| 检查项 | 通过标准 | 不通过时的表现 |
|---|---|---|
| 角色分工 | system 管边界,user 放任务,assistant 只放历史回复 |
模型把规则当材料,或把历史回复当新问题 |
| 输入来源 | 用户材料、系统规则和调试信息分开保存 | 日志难脱敏,Prompt 版本难回放 |
| 历史长度 | 只保留当前任务必要事实,旧内容摘要化 | 上下文过长、成本升高、回答被旧信息带偏 |
| 输出要求 | 格式、语气、长度和禁止事项写清楚 | 回复漂移,人工编辑成本高 |
| 敏感信息 | Key、账号、客户资料和内部文件已脱敏 | 响应和日志里出现不该公开的内容 |
| 失败复现 | 能用同一组脱敏 messages 复现错误 | 线上问题只能靠猜,难以定位模型、接口还是业务层 |
把配置放进环境变量,避免把 Key 写进代码、截图、日志或公开仓库。
export OPENAI_BASE_URL="https://api.ofapp.cn/v1"export OPENAI_API_KEY="sk-xxxx"export OPENAI_MODEL="以 OfApp.cn 控制台可用模型为准"如果你的工具会自动拼接 /v1,Base URL 可能需要填写 https://api.ofapp.cn。判断标准很简单:最终请求路径应只出现一个 /v1/chat/completions。
curl 最小请求
Section titled “curl 最小请求”curl 适合排查 Key、Base URL、模型名和网络问题。它绕开了 SDK 封装,能更快看清真实请求。
curl "$OPENAI_BASE_URL/chat/completions" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"model\": \"$OPENAI_MODEL\", \"messages\": [ {\"role\":\"user\",\"content\":\"用一句话说明 Chat Completions 的用途。\"} ], \"stream\": false }"预期结果不是固定文案,而是一个带有 choices 的 JSON。调试时先保存完整响应,再提取 choices[0].message.content。
Python 最小请求
Section titled “Python 最小请求”Python 适合脚本、数据处理、自动化办公、研究辅助和服务端任务。
import osfrom openai import OpenAI
client = OpenAI( api_key=os.environ["OPENAI_API_KEY"], base_url=os.environ["OPENAI_BASE_URL"],)
completion = client.chat.completions.create( model=os.environ["OPENAI_MODEL"], messages=[ {"role": "system", "content": "你是一个简洁的中文技术助手。"}, {"role": "user", "content": "把 Chat Completions 解释给非技术同事。"}, ], stream=False,)
print(completion.choices[0].message.content)生产代码里建议再加上超时、重试、错误分层和日志脱敏。不要把 OPENAI_API_KEY 打印到日志系统。
JavaScript 最小请求
Section titled “JavaScript 最小请求”JavaScript 适合 Node.js 服务端、命令行工具、Next.js API Route、Astro 后端接口和内部自动化工具。
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, baseURL: process.env.OPENAI_BASE_URL,});
const completion = await client.chat.completions.create({ model: process.env.OPENAI_MODEL, messages: [ { role: "system", content: "你是一个简洁的中文技术助手。" }, { role: "user", content: "给我一个适合新手的 Chat Completions 示例。" }, ], stream: false,});
console.log(completion.choices[0]?.message?.content);浏览器前端不要直接暴露 API Key。把请求放在服务端接口、边缘函数或后端服务中,再由前端调用你自己的接口。
多轮对话怎么写
Section titled “多轮对话怎么写”Chat Completions 本身不会自动记住你的前文。你需要在下一次请求里把必要历史一起发送。
const messages = [ { role: "system", content: "你是一个负责整理会议纪要的助手。" }, { role: "user", content: "今天会议讨论了新版官网、SEO 和错误页优化。" }, { role: "assistant", content: "可以整理为目标、决策、行动项和风险。" }, { role: "user", content: "请把行动项按负责人和截止时间整理成表格。" },];
const completion = await client.chat.completions.create({ model: process.env.OPENAI_MODEL, messages,});多轮对话越长,请求越重,也越容易遇到上下文限制。更稳的做法是保留关键轮次,把旧内容压缩成摘要,并在业务数据库中保存结构化状态。
流式输出怎么写
Section titled “流式输出怎么写”聊天界面通常希望边生成边显示,这时可以打开 stream: true。流式响应读取的是增量片段,不是完整 message。
const stream = await client.chat.completions.create({ model: process.env.OPENAI_MODEL, messages: [ { role: "user", content: "用 5 个短句解释为什么流式输出适合聊天界面。" }, ], stream: true,});
for await (const chunk of stream) { const text = chunk.choices[0]?.delta?.content ?? ""; process.stdout.write(text);}如果非流式请求能返回、流式请求失败,优先检查客户端是否支持 Server-Sent Events、代理是否缓冲响应、超时时间是否过短。
如何读取响应
Section titled “如何读取响应”非流式响应建议按这几个字段检查:
| 字段 | 说明 | 常见用途 |
|---|---|---|
id |
本次生成的响应标识 | 排查日志、关联请求 |
model |
实际返回使用的模型名 | 确认模型路由是否符合预期 |
choices[0].message.content |
模型文本输出 | 展示给用户或进入下一步处理 |
choices[0].finish_reason |
生成停止原因 | 判断是否被长度、工具调用或安全策略影响 |
usage |
token 用量信息,是否返回取决于服务 | 做成本观察和异常排查 |
如果页面只显示空白,不要只看 content。把完整 JSON 临时打印出来,确认返回结构、错误字段和 finish_reason。
finish_reason 不应只作为调试字段丢掉。它往往决定下一步怎么处理。
| finish_reason | 常见含义 | 建议动作 |
|---|---|---|
stop |
正常停止 | 读取 message.content,进入业务复核 |
length |
达到输出长度限制 | 压缩输入、提高允许输出长度或提示用户缩小任务 |
content_filter |
内容被安全策略影响 | 给用户明确提示,不要当作空白回复 |
tool_calls |
模型请求调用工具 | 只有在项目支持工具调用时才继续处理 |
function_call |
旧式函数调用路径 | 老项目要保留兼容处理,新项目应评估当前服务商推荐方式 |
常见错误速查
Section titled “常见错误速查”| 现象 | 可能原因 | 建议处理 |
|---|---|---|
| 401 Unauthorized | Key 缺失、拼错、过期或没有放进 Authorization |
检查环境变量和请求头,不在日志里暴露完整 Key |
| 404 Not Found | Base URL 重复或漏掉 /v1,路径拼错 |
确认最终路径是 /v1/chat/completions |
| model not found | 模型名不可用或账号没有权限 | 使用 OfApp.cn 控制台或官方文档中的可用模型名 |
choices 为空 |
服务返回错误结构,或被代理改写 | 打印完整响应和状态码 |
finish_reason 是 length |
输出达到长度限制 | 调整 max_tokens 或压缩输入 |
| 流式输出中断 | 客户端、代理或网关超时 | 先跑非流式,再检查 SSE、超时和重试策略 |
| 上下文过长 | messages 历史太长 |
摘要旧历史,只保留必要事实 |
| 本地能跑,线上失败 | 线上环境变量、网络出口或运行时不同 | 对比线上最终 Base URL、Key 来源和 Node/Python 版本 |
什么时候不用 Chat Completions
Section titled “什么时候不用 Chat Completions”Chat Completions 很适合验证兼容接口和迁移旧项目,但不是所有新需求都必须从它开始。
| 需求 | 更适合的方向 | 原因 |
|---|---|---|
| 新项目文本生成 | 同时了解 Responses API | OpenAI 已把 Responses 作为新项目推荐方向 |
| 工具调用、联网搜索、文件检索 | 查看服务商支持的 Responses 或专用接口 | Chat Completions 的兼容边界可能更窄 |
| Claude 生态工具 | 使用 Anthropic Messages 风格接口 | 请求结构和 OpenAI Chat Completions 不一样 |
| 只想普通聊天、写作、读文件 | 先用天才游乐场 | 不必从接口参数开始理解 |
OfApp.cn 官方文档展示了 /v1/chat/completions 示例,也展示了 /v1/responses、/v1/messages 等入口。具体项目选哪个,应看工具要求、服务商支持情况和你要用的模型能力。
上线前检查清单
Section titled “上线前检查清单”| 检查项 | 通过标准 |
|---|---|
| Key 管理 | Key 只存在服务端环境变量或安全密钥系统中 |
| Base URL | 最终请求地址只出现一个 /v1 |
| 模型名 | 来自控制台、官方文档或 Models API 返回结果 |
| 最小请求 | curl、Python 或 JavaScript 至少一种能稳定返回 |
| 错误处理 | 401、404、429、5xx、超时和上下文过长都有明确提示 |
| 日志 | 记录 request id、状态码、耗时,不记录完整 Key 和敏感用户内容 |
| 流式输出 | 客户端能处理中断、重连和空增量 |
| 成本观察 | 记录调用频率、平均输入长度和异常长输出 |
| 降级方案 | 接口失败时给用户可理解的错误,不让页面一直转圈 |
system 消息一定支持吗?
Section titled “system 消息一定支持吗?”常见 Chat Completions 接口会支持 system、user、assistant 这种 messages 结构,但兼容服务的细节可能不同。最小验证可以只保留一条 user 消息,跑通后再加入系统指令。
只保留 user 消息可以吗?
Section titled “只保留 user 消息可以吗?”可以。连通性验证时,一条 user 消息反而更清楚。需要稳定人格、格式和边界时,再加入 system。
choices[0].message.content 为空怎么办?
Section titled “choices[0].message.content 为空怎么办?”先打印完整响应。检查是否返回了错误对象、finish_reason 是否为 content_filter 或 tool_calls、是否开启了流式输出却按非流式结构读取。
多轮对话要把历史全部发过去吗?
Section titled “多轮对话要把历史全部发过去吗?”不建议无脑全发。只保留当前任务需要的事实、约束和结论。旧对话可以压缩成摘要,详细历史放在你自己的数据库或文件里。
Chat Completions 和 Responses 应该选哪个?
Section titled “Chat Completions 和 Responses 应该选哪个?”旧项目、AI 客户端和 OpenAI 兼容工具通常更容易从 Chat Completions 起步。新项目可以同时了解 Responses API。真正的选择取决于服务商支持情况、项目代码结构和你要使用的能力。
OfApp.cn 支持 Chat Completions 吗?
Section titled “OfApp.cn 支持 Chat Completions 吗?”OfApp.cn 官方文档展示了 POST /v1/chat/completions 示例。具体可用模型、计费规则、额度、速率限制和能力边界,请以 OfApp.cn 控制台或官方文档为准。
流式输出和非流式输出返回结构一样吗?
Section titled “流式输出和非流式输出返回结构一样吗?”不一样。非流式通常读取 choices[0].message.content;流式要按 chunk 读取 choices[0].delta.content,并处理空片段和结束事件。
可以把真实对话历史写进日志吗?
Section titled “可以把真实对话历史写进日志吗?”谨慎处理。聊天内容可能包含个人信息、业务资料、文件摘要或客户数据。生产环境建议做脱敏、采样、权限隔离和保留周期控制。
- OpenAI 兼容 API 快速调用:从 Base URL、Key、模型名和最小请求开始。
- curl 示例:用终端排查请求路径、请求头和状态码。
- Python SDK 示例:把 Chat Completions 放进脚本和服务端任务。
- JavaScript SDK 示例:在 Node.js 服务端调用兼容接口。
- Responses API 示例:了解新式输入结构和返回结构。
- OpenAI API 流式输出示例:处理流式输出和前端展示。
- 错误重试示例:为 429、5xx 和超时建立重试策略。
- Base URL 配置:避免
/v1重复或缺失。 - 快速排错:按状态码定位接入问题。
- context length exceeded:压缩长对话和长文档上下文。
- invalid API key:排查 Key 格式和环境变量。
- OfApp.cn OpenAI API 直转文档:用于核对 OfApp.cn 公开的 Base URL、Bearer 鉴权、
/v1/chat/completions和messages示例。 - OfApp.cn 首页:用于理解 OfApp.cn 作为统一 API 入口的品牌和产品入口。
- OfApp.cn 天才游乐场:用于确认 OfApp.cn 面向体验和模型试用的公开入口。
- OpenAI Chat API Reference:用于核对 Chat Completions 的端点、
choices、message和finish_reason等返回结构。 - OpenAI Responses 与 Chat Completions 迁移指南:用于理解 Chat Completions 与 Responses API 的适用边界。
Chat Completions 的价值在于稳定、直观、容易验证。先用一条 user 消息跑通 /v1/chat/completions,再按业务需要加入系统指令、多轮历史、流式输出和错误处理。接入 OfApp.cn 时,Base URL、Key、模型名和能力边界都以 OfApp.cn 控制台或官方文档为准。