对话补全
POST /v1/chat/completions最核心的接口,也是所有客户端都会调的那个。
请求
请求头
http
Authorization: Bearer sk-你的密钥
Content-Type: application/json请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✅ | 模型 ID,从 /v1/models 获取 |
messages | array | ✅ | 对话消息数组,见下 |
stream | boolean | 是否流式返回,默认 false | |
temperature | number | 采样温度,0~2。越低越确定,越高越发散 | |
top_p | number | 核采样,和 temperature 二选一调,别同时改 | |
max_tokens | integer | 最多生成多少 token | |
stop | string / array | 遇到这些字符串就停 | |
presence_penalty | number | -2~2,越大越倾向聊新话题 | |
frequency_penalty | number | -2~2,越大越不重复用词 | |
response_format | object | 传 {"type":"json_object"} 要求返回 JSON | |
tools | array | 工具定义,供模型调用 | |
user | string | 终端用户标识,便于风控追踪 |
messages 的结构
每条消息有三个字段:
| 字段 | 取值 |
|---|---|
role | system / user / assistant / tool |
content | 文本内容;多模态时是数组 |
name | 可选,角色名 |
json
{
"model": "deepseek-v4-pro-0813",
"messages": [
{ "role": "system", "content": "你是一个简洁的助手,回答不超过三句话。" },
{ "role": "user", "content": "什么是向量检索?" }
]
}system 放在第一条
system 消息定义模型的角色和行为,要放在数组最前面。放在后面部分模型会忽略。
响应
json
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1793000000,
"model": "deepseek-v4-pro-0813",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "向量检索是把文字转成一串数字……"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 28,
"completion_tokens": 156,
"total_tokens": 184
}
}finish_reason 的含义
| 值 | 意思 | 该怎么办 |
|---|---|---|
stop | 正常结束 | 正常,不用管 |
length | 达到 max_tokens 被截断 | 调大 max_tokens,或者让它分段写 |
tool_calls | 模型要调用工具 | 执行工具后把结果作为 tool 消息传回去 |
content_filter | 被内容安全策略拦截 | 换个说法,或改用输出内容 |
finish_reason 是 length 时不要直接用
这时候回答是半截的。直接展示给用户会显得很蠢。要么调大 max_tokens 重试,要么在提示词里要求它控制篇幅。
完整示例
bash
curl https://api.blueworkshop.top/v1/chat/completions \
-H "Authorization: Bearer $CYAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro-0813",
"messages": [
{"role": "system", "content": "你是一个简洁的技术助手。"},
{"role": "user", "content": "用一句话解释什么是 RAG"}
],
"temperature": 0.7,
"max_tokens": 200
}'python
from openai import OpenAI
client = OpenAI(
api_key="sk-你的密钥",
base_url="https://api.blueworkshop.top/v1",
timeout=120.0,
)
resp = client.chat.completions.create(
model="deepseek-v4-pro-0813",
messages=[
{"role": "system", "content": "你是一个简洁的技术助手。"},
{"role": "user", "content": "用一句话解释什么是 RAG"},
],
temperature=0.7,
max_tokens=200,
)
print(resp.choices[0].message.content)
print("用了", resp.usage.total_tokens, "token")
print("结束原因", resp.choices[0].finish_reason)javascript
import OpenAI from 'openai'
const client = new OpenAI({
apiKey: process.env.CYAN_API_KEY,
baseURL: 'https://api.blueworkshop.top/v1',
timeout: 120_000,
})
const resp = await client.chat.completions.create({
model: 'deepseek-v4-pro-0813',
messages: [
{ role: 'system', content: '你是一个简洁的技术助手。' },
{ role: 'user', content: '用一句话解释什么是 RAG' },
],
temperature: 0.7,
max_tokens: 200,
})
console.log(resp.choices[0].message.content)多轮对话
模型本身不记得上一轮,每次都要把历史带上:
python
messages = [
{"role": "system", "content": "你是一个技术助手。"},
{"role": "user", "content": "什么是向量?"},
{"role": "assistant", "content": "向量是一串数字,用来表示语义。"},
{"role": "user", "content": "那它和数组有什么区别?"}, # ← 只发这一句它不懂
]历史越长越贵
每轮都把全部历史发过去,token 数会线性增长。长对话到后期成本会飙升。
对策:只保留最近 N 轮,或者把早期对话压缩成一段摘要放进 system。
返回 JSON
python
resp = client.chat.completions.create(
model="deepseek-v4-pro-0813",
messages=[{"role": "user", "content": "列出三种水果,只要 JSON 数组"}],
response_format={"type": "json_object"}, # 部分模型支持
)如果模型不支持 response_format,就在提示词里写清楚「只输出 JSON,不要任何解释」。
看图
支持视觉的模型可以传图片 URL 或 base64:
json
{
"role": "user",
"content": [
{ "type": "text", "text": "这张图里有什么?" },
{ "type": "image_url", "image_url": { "url": "https://example.com/a.png" } }
]
}不是所有模型都能看图
先确认模型名带 vision 或在文档里标了多模态。传了图给纯文本模型会直接报错。