深入理解 LLM Chat API 调用参数:从 OpenAI 标准到国内厂商实践

一、引言

调用 LLM API 看起来很简单------装一个 SDK,填几个字段,拿到结果。不少开发者第一次调用时的代码长这样:

python 复制代码
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "你好"}]
)
print(response.choices[0].message.content)

这段代码能跑,但 create() 方法实际接受几十个参数。这些参数控制着模型的行为------输出的随机性、长度、格式、是否可以调用工具、是否流式返回------而大多数开发者只接触到其中的三四个。

更复杂的是,当你从 OpenAI 切换到国内厂商(DeepSeek、通义千问、智谱 GLM 等)时,这些参数的行为会发生变化。有的参数不再支持,有的参数行为有微妙差异,有的则需要通过特殊的扩展字段传入。

这篇文章的路线图如下:

  • 第二章:先看一次 Chat API 调用实际发出了什么 HTTP 请求------揭开 SDK 的黑箱
  • 第三章:逐一介绍所有稳定参数的分类、语义和用法
  • 第四章:区分 SDK 消费了哪些参数、哪些透传到 body
  • 第五章:对比国内 7 家厂商在每个参数上的兼容性
  • 第六章:分析参数组合的意图模式和常见程序类型
  • 第七章:以项目中的自动续写功能为案例,串联各个参数
  • 第八章:总结最佳实践

本文以 gpt-4o 对应的 OpenAI Chat Completions API 稳定版本(2024-08-06)为基准,不覆盖仍在实验阶段的参数。代码示例基于 OpenAI Python SDK(openai>=1.0)。本文基于 2025 年中的 API 版本编写,厂商 API 可能更新,请以各厂商最新文档为准。

二、客户端协议:一次 Chat API 调用到底发出了什么

2.1 HTTP 请求全貌

当你调用 client.chat.completions.create() 时,SDK 最终向服务端发送了一个 HTTP POST 请求。以下是一个完整请求的全貌:

http 复制代码
POST /v1/chat/completions HTTP/1.1
Host: api.openai.com
Authorization: Bearer sk-proj-xxxxxxxxxxxxxxxx
Content-Type: application/json
User-Agent: OpenAI/Python 1.55.0

{
    "model": "gpt-4o",
    "messages": [
        {"role": "system", "content": "你是一位助手。"},
        {"role": "user", "content": "请用一句话介绍 Python"}
    ],
    "max_tokens": 200,
    "temperature": 1.0,
    "top_p": 1.0,
    "frequency_penalty": 0,
    "presence_penalty": 0,
    "stream": false,
    "stop": null,
    "seed": null,
    "response_format": {"type": "text"},
    "tools": null,
    "tool_choice": "auto",
    "parallel_tool_calls": true,
    "logprobs": false,
    "top_logprobs": null,
    "n": 1,
    "user": null,
    "logit_bias": null
}

这就是 SDK 替你构造并发送出去的 JSON body。注意到即使你没有显式传参,SDK 也会用默认值填充所有字段。

2.2 参数的两类去向

从 SDK 到 HTTP 请求的过程中,参数的去向分为两类:

  1. 被 SDK 消费:不进入 body,而是被 SDK 用于构造请求的 header、URL、连接配置等
  2. 透传到 body:SDK 不做任何处理,直接序列化到 JSON body 中

例如,api_key 被 SDK 消费后放入 Authorization header,base_url 用于拼接 URL,http_client 用于配置连接池------这些参数永远不会出现在 body 中。而 modelmessagesmax_tokens 等则原样进入 body。

此外,SDK 提供了一个后门机制 extra_body,用于传入 body 中没有对应字段的自定义参数。这在调用国内厂商时非常有用,因为许多厂商在 OpenAI 标准之上增加了自己的字段。

三、参数详解

本章按功能分类逐一说明每个参数。每个参数包含:语义(它控制什么)、类型/范围/默认值、以及使用场景。

3.1 消息结构:messages

messages 是最核心的参数,它构成了与模型对话的全部上下文。它是一个对象数组,每种对象通过 role 字段区分角色:

text 复制代码
messages: [
    { role: "system",    content: "..." },                     // 系统指令
    { role: "user",      content: "..." },                     // 用户输入
    { role: "assistant", content: "...",  tool_calls?: [...] }, // 模型回复
    { role: "tool",      content: "...",  tool_call_id: "..." } // 工具调用结果
]

四种角色的语义:

角色 用途 说明
system 设定模型的行为和风格 可选的顶层指令,影响整个对话的基调
user 用户输入 问题、指令或需要模型处理的内容
assistant 模型回复 在多轮对话中,需要将历史回复拼入 messages
tool 工具调用结果 配合 tool_calling 使用,回填函数执行结果

content 的两种形态:

简单的文本请求中,content 是一个字符串:

json 复制代码
{"role": "user", "content": "请解释量子纠缠"}

在需要传入多模态内容时,content 是一个数组:

json 复制代码
{
    "role": "user",
    "content": [
        {"type": "text", "text": "这张图里有什么?"},
        {"type": "image_url", "image_url": {"url": "https://..."}}
    ]
}

目前 content 数组支持的类型有 textimage_url 两种。国内厂商中,通义 Qwen、智谱 GLM、MiniMax 和 StepFun 支持图片输入,百度和 Moonshot 不支持。

关于 system 角色的说明:

在较新的 API 版本中(2024-08-06+),也可以在顶层使用 system 参数直接传入:

json 复制代码
{"system": "你是一位助手", "messages": [...]}

这个方式与在 messages 中放入 system 角色效果相同,但部分国内厂商只支持 messages 中的 system 角色,不支持顶层 system 参数。

3.2 基础生成控制

这组参数控制模型"如何生成"输出------随机性多高、输出多长、是否重复相同的内容。

model

model 是最重要的一个参数,它决定了模型的能力边界------知识范围、推理能力、上下文窗口大小、对工具调用的支持程度等。

python 复制代码
# OpenAI 系列
model="gpt-4o"           # 最新旗舰模型
model="gpt-4o-mini"      # 轻量版,性价比高

# 国内厂商
model="deepseek-chat"     # DeepSeek 对话模型
model="qwen-max"          # 通义千问
model="glm-4-plus"        # 智谱 GLM
  • 类型: string
  • 必须: 是
max_tokens

控制模型输出的最大 token 数量(注意是输出 token,不是总 token)。

python 复制代码
max_tokens=50     # 短回答,适合分类、提取
max_tokens=500    # 标准回答
max_tokens=4096   # 长文本输出
  • 类型: int
  • 范围: 1 到模型的最大输出 token 数
  • 默认值: 由各厂商自行设定(OpenAI 为 4096)
  • 重要: 当输出达到 max_tokens 时,finish_reason"length"------这不是错误,而是截断信号。程序应该检测这个信号并决定是否续写
temperature 与 top_p

这对参数配合使用,控制输出分布的随机性。

temperature 控制概率分布的"平滑度":

python 复制代码
temperature=0    # 确定输出:每次调用返回概率最高的 token(argmax)
temperature=0.7  # 平衡:有一定随机性,但不会偏离太远
temperature=1.0  # 默认值:模型训练时使用的分布
temperature=1.5  # 高随机性:低概率词更容易被选中

temperature 的底层机制很简单:模型输出每个 token 时有一个概率分布,temperature 作为分母除一下 logits 再做 softmax。temperature=0 是 argmax(只选最高概率的 token),temperature 越大分布越平缓。

注意temperature=0 在数学上等价于贪心解码,但实际实现中因浮点精度和不同厂商的实现差异,不能 100% 保证每次调用的输出完全一致。

top_p(Nucleus Sampling / 核采样)是另一种随机性控制方式:

python 复制代码
top_p=1.0  # 默认:考虑全部 token
top_p=0.9  # 只考虑累积概率前 90% 的 token
top_p=0.1  # 只考虑累积概率前 10% 的 token,非常集中

实际效果对比(相同 prompt,不同的组合):

text 复制代码
temperature=0.0, top_p=1.0
  "写一句关于春天的诗"
  → "春眠不觉晓,处处闻啼鸟" (每次相同)

temperature=0.8, top_p=1.0
  "写一句关于春天的诗"
  → "春风又绿江南岸" 或 "杏花春雨江南" 或 "草长莺飞二月天" (随机变化)

frequency_penalty=-2.0  ← 鼓励重复
  "写一句关于春天的诗"
  → "春天春天春天春天春天" (负值惩罚让模型反复使用已出现的词)

OpenAI 官方和国内厂商都建议:只调 temperature 或只调 top_p,不要同时调整二者。同时调整时,两者的交互效果难以预测。

国内厂商差异 :所有厂商都支持 temperature,Qwen 和 DeepSeek 行为与 OpenAI 一致。智谱 GLM 额外提供了 do_sample 参数,设为 false 时等同于 temperature=0 的贪心解码。

frequency_penalty 与 presence_penalty

这对参数配合使用,控制输出的重复程度。

两者的区别可以从命名中看出:

参数 惩罚的对象 效果
frequency_penalty 同一个 token 出现的频次 换词不换话题
presence_penalty token 是否已经出现过 推动话题前进

实例效果:

text 复制代码
# 不加惩罚:容易重复
frequency_penalty=0, presence_penalty=0
"写一首关于猫的诗"
→ "小猫小猫真可爱,小猫小猫喵喵叫,小猫小猫爱吃鱼..."

# 加频次惩罚:换词
frequency_penalty=2, presence_penalty=0
"写一首关于猫的诗"
→ "喵星人跳上窗台,尾巴轻摇,胡须颤动..."

# 加存在惩罚:换话题
frequency_penalty=0, presence_penalty=2
"先聊猫,再聊狗,再聊鱼"
→ 模型不会反复回到猫的话题,会主动推进到狗和鱼
  • 类型: float
  • 范围: -2.02.0
  • 默认值: 0
  • 负值 → 鼓励重复(几乎没有使用场景)

最佳实践 :长文本生成设置 frequency_penalty=0.3~0.5 避免词汇重复;多轮对话设置 presence_penalty=0.3~0.5 避免死循环话题。

国内厂商差异:智谱 GLM-4 系列完整支持 frequency_penalty 和 presence_penalty,GLM-3 及以下版本不支持。七家厂商中完全支持两者的是 DeepSeek、通义 Qwen、智谱 GLM 和 StepFun。

stop

指定一个或多个字符串,当模型生成到这些字符串时停止:

python 复制代码
stop=["\n", "结束"]   # 遇到换行或"结束"就停止
stop="?"              # 遇到问号就停止
  • 类型: stringarray[string]
  • 最多支持 4 个停止词
  • 默认值: null(不设置停止词)
seed

指定随机数种子,配合 temperature=0 实现可复现的生成:

python 复制代码
seed=42, temperature=0  # 每次调用返回相同结果
  • 类型: int
  • 默认值: null(不指定种子)
  • 注意:确定性不是 100% 保证的。国内厂商中 DeepSeek、通义 Qwen、智谱 GLM 支持;Moonshot、MiniMax、百度不支持
logit_bias

直接修改某个 token 出现的概率:

python 复制代码
logit_bias={
    24939: -100,   # 让 token ID 24939 几乎不可能出现
    584: 20        # 让 token ID 584 更可能出现
}
  • 类型: dict(key 是 token ID,value 是偏置值)
  • 范围: -100100
  • 极少使用的参数,需要先通过 tokenizer 查到 token ID
  • 国内兼容性:只有 DeepSeek 完全支持,Qwen 部分版本支持,其余厂商均不支持

3.3 输出格式控制

response_format

控制模型输出的格式,有三种模式:

python 复制代码
# 模式一:自由文本(默认)
response_format={"type": "text"}

# 模式二:JSON 对象
response_format={"type": "json_object"}

# 模式三:JSON Schema(严格校验)
response_format={
    "type": "json_schema",
    "json_schema": {
        "name": "person",
        "strict": true,
        "schema": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "age": {"type": "integer"}
            },
            "required": ["name", "age"],
            "additionalProperties": false
        }
    }
}

三种模式的区别:

模式 保证的内容 适用场景
text 无约束 通用对话、写作
json_object 输出是合法的 JSON 需要结构化但 schema 动态
json_schema 输出符合预定义 Schema 严格结构化输出、数据管道

json_object 模式的使用要求:必须在 messages 或 system prompt 中提示模型输出 JSON(如"请以 JSON 格式输出"),否则模型不会知道要输出什么字段。

json_schema 模式的优势strict: true 强制 Schema 校验,模型不会输出未定义的字段。

国内兼容性

  • json_object:DeepSeek、Qwen、智谱 GLM(部分)、MiniMax、StepFun 支持;Moonshot、百度不支持
  • json_schema:DeepSeek 和 Qwen 支持较好,智谱不支持

3.4 工具调用(Tool Calling)

tools

定义一组可供模型调用的工具:

python 复制代码
tools=[{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "获取指定城市的天气信息",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "城市名"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["city"]
        }
    }
}]
tool_choice

控制模型是否调用工具:

python 复制代码
tool_choice="auto"               # 模型自主决定是否调用(默认)
tool_choice="none"               # 强制不调用
tool_choice="required"           # 强制调用(必须至少调用一个)
tool_choice={"type": "function", "function": {"name": "get_weather"}}  # 强制调用指定工具
parallel_tool_calls

是否允许模型在一次响应中调用多个工具:

python 复制代码
parallel_tool_calls=true   # 允许并行调用(默认)
parallel_tool_calls=false  # 每次只调用一个工具

完整的数据流

text 复制代码
应用层                    模型                     工具
  │                        │                       │
  ├─ 请求(含 tools 定义)──▶                        │
  │                        │                       │
  │                        ├─ 决定调用工具           │
  │◀── tool_calls 响应 ─────┤                       │
  │                        │                       │
  ├─ 执行本地函数 ──────────┼──────────────────────▶│
  │                        │                       │
  ├─ tool 结果回填到 messages▶                       │
  │                        │                       │
  │                        ├─ 基于工具结果继续回答    │
  │◀── 最终响应 ────────────┤                       │
  │                        │                       │

国内兼容性 :DeepSeek、Qwen、智谱 GLM(有限制)、Moonshot、StepFun 支持工具调用;百度 ERNIE 不支持。注意智谱 GLM 的 tool_choice 只支持 "auto" 和具名 function,不支持 "required"parallel_tool_calls 仅 DeepSeek 和 Qwen 支持。

3.5 流式输出

stream

stream=false(默认)时,SDK 发起一个普通 HTTP 请求,在完整的响应返回后才将结果交给应用层:

python 复制代码
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "写一首短诗"}],
    stream=False  # 默认
)
# 等待完整响应
print(response.choices[0].message.content)

stream=true 时,SDK 发起一个 SSE(Server-Sent Events)流式请求,服务端逐 token 推送数据,SDK 逐 chunk 返回给应用层:

python 复制代码
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "写一首短诗"}],
    stream=True
)
for chunk in stream:          # 逐 token 到达
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

流式传输的 SSE 事件格式如下(每个 chunk 是一个独立事件):

text 复制代码
data: {"id":"...","choices":[{"delta":{"content":"春"},"finish_reason":null}]}

data: {"id":"...","choices":[{"delta":{"content":"眠"},"finish_reason":null}]}

data: {"id":"...","choices":[{"delta":{"content":"不"},"finish_reason":null}]}

...

data: [DONE]
stream_options

从 2024-08-06 版本开始,可以通过 stream_options 在流式响应结束时附带 token 用量信息:

python 复制代码
stream = client.chat.completions.create(
    ...,
    stream=True,
    stream_options={"include_usage": True}
)

最后一个 chunk 会包含 usage 字段,包含 prompt_tokens、completion_tokens 等统计。不是所有国内厂商的流式响应都支持 include_usage------DeepSeek 和 Qwen 支持,其余大多不支持。

3.6 推理模型参数

从 OpenAI o1/o3 系列开始,以及 DeepSeek R1 等国内推理模型,引入了推理模型专属的参数概念。

reasoning_effort(OpenAI o1/o3 系列)

控制模型在推理上投入多少计算量:

python 复制代码
reasoning_effort="low"     # 轻量推理
reasoning_effort="medium"  # 默认
reasoning_effort="high"    # 深度推理
  • reasoning_effort 越高,模型花在"思考"上的 token 越多,答案质量可能更高,但响应时间更长
  • 该参数目前仅 OpenAI o1/o3 系列支持,国内厂商无对应参数
max_completion_tokens(替代 max_tokens)

在 o1/o3 推理模型中,推荐使用 max_completion_tokens 替代 max_tokens

python 复制代码
max_completion_tokens=4096  # 总的 completion token 预算(含 reasoning + 回答)

传统的 max_tokens 只控制输出 token 数量。但在推理模型中,输出包含两个部分:推理(reasoning)和回答(answer)。max_completion_tokens 的预算同时覆盖这两部分。如果推理过程消耗了大部分预算,回答部分可能很少甚至为空。

reasoning_content(国内推理模型特有字段)

DeepSeek R1 等国内推理模型的响应中包含一个标准 OpenAI 规范中没有的字段 reasoning_content

python 复制代码
response = client.chat.completions.create(model="deepseek-reasoner", ...)
message = response.choices[0].message

reasoning = getattr(message, "reasoning_content", None)  # 思考过程
content = message.content                                  # 最终回答

这个字段在同步响应的 message 对象上,也在流式响应的 chunk.choices[0].delta 上:

python 复制代码
stream = client.chat.completions.create(model="deepseek-reasoner", ..., stream=True)
for chunk in stream:
    delta = chunk.choices[0].delta
    if getattr(delta, "reasoning_content", None):
        print("[思考]", delta.reasoning_content)    # 推理过程输出
    if delta.content:
        print(delta.content)                        # 回答内容输出

重要影响 :当 max_tokens 设置过小时,推理模型可能把所有 token 预算都消耗在 reasoning_content 上,导致 content 为空。程序逻辑不能假设 content 一定非空------需要检测 reasoning_content 是否有值来判断模型是否在思考,并相应调整 token 预算。

3.7 边缘参数

n

生成多个候选回答:

python 复制代码
n=3  # 一次请求返回 3 个不同的候选回答
  • 类型: int(默认 1)
  • 注意:n > 1 时不能与 stream=true 同时使用(API 会报错)
  • 国内兼容性:DeepSeek 部分支持(只生效第一个候选),其余厂商基本不支持
logprobs 与 top_logprobs

返回每个输出 token 的对数概率值:

python 复制代码
logprobs=True          # 返回每个 token 的对数概率
top_logprobs=5         # 额外返回每个 token 位置的前 5 个候选概率
  • 国内兼容性:DeepSeek 和 Qwen 支持,其余不支持
user

一个简单但实用的参数,用于标识请求的终端用户身份,方便在 OpenAI 侧进行用量监控和滥用检测:

python 复制代码
user="user_abc123"
  • 类型: string
  • 不影响模型行为,仅用于标识

四、参数的去向:哪些被 SDK 消费,哪些透传

4.1 参数分流全景图

OpenAI Python SDK 处理参数的逻辑分为三层:

text 复制代码
┌──────────────────────────────────────────────────────────────┐
│                    OpenAI Python SDK                           │
├──────────────────────────────────────────────────────────────┤
│                                                                │
│  创建 Client 时消耗(永远不会进入 HTTP body)                    │
│  ─────────────────────────────────────────                     │
│  api_key          → Authorization header                        │
│  base_url         → 拼出 POST /v1/chat/completions              │
│  organization     → OpenAI-Organization header                  │
│  http_client      → httpx 实例,控制连接池/超时/代理             │
│  default_headers  → 附加到每个请求的 headers                    │
│  default_query    → 附加到每个 URL 的 query params              │
│  timeout          → httpx.Timeout 配置                          │
│  max_retries      → 重试策略                                    │
│                                                                │
│  调用 create() 时处理(部分消费,部分透传)                      │
│  ────────────────────────────────                               │
│  stream           → 如果 true,SDK 切换到 SSE 流解析            │
│                     同时 body 中写入 "stream": true              │
│  response_format  → SDK 做 type 校验后原样写入 body             │
│  extra_body       → 直接 merge 进 body(扩展的后门)            │
│                                                                │
│  透传到 body(SDK 不消费,直接 json 序列化)                    │
│  ──────────────────────────────                                  │
│  model, messages, max_tokens, temperature, top_p                │
│  frequency_penalty, presence_penalty, stop, seed                │
│  logit_bias, n, logprobs, top_logprobs, user                    │
│  tools, tool_choice, parallel_tool_calls                        │
│  reasoning_effort, max_completion_tokens                        │
│  stream_options                                                 │
└──────────────────────────────────────────────────────────────┘

这个分层意味着:当你给 client.chat.completions.create() 传入参数时,不能假设所有参数都会进入 body。例如 api_keyhttp_client 一定不会------它们是用来配置 Client 行为的,不是模型行为。

4.2 extra_body:扩展参数的后门机制

extra_body 是 OpenAI SDK 提供的一个特殊参数,它的内容会直接合并(merge)进最终发送的 JSON body。这是调用国内厂商时最重要的机制,因为国内厂商的扩展字段在标准 SDK 中没有对应的参数名。

python 复制代码
# 传入 DeepSeek 的 prefix 扩展字段
client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "从前有座山"}],
    extra_body={"prefix": True}  # 合并到 body: {... "prefix": true}
)

# 传入通义 Qwen 的 enable_search 扩展字段
client.chat.completions.create(
    model="qwen-max",
    messages=[{"role": "user", "content": "2025年诺贝尔奖"}],
    extra_body={"enable_search": True}
)

如果不使用 extra_body,要传入这些扩展字段就需要直接操作 HTTP 请求,或者使用厂商提供的自定义 SDK。

五、国内厂商兼容性深度对比

5.1 兼容性矩阵

以下对比基于 OpenAI Chat Completions API 稳定版本(2024-08-06),覆盖 7 家国内厂商。✓=完全兼容,△=部分兼容/行为差异,✗=不支持。

参数 GPT DeepSeek Qwen 智谱GLM Moonshot StepFun MiniMax 百度ERNIE
model
messages: system
messages: user/text
messages: user/image
messages: tool
max_tokens
temperature
top_p
frequency_penalty
presence_penalty
stop
seed
logit_bias
response_format/text
response_format/json
response_format/schema
stream
stream_options/usage
tools + tool_choice
parallel_tool_calls
logprobs + top_logprobs
n
user

5.2 典型差异案例分析

案例一:百度 ERNIE 的消息格式

百度 ERNIE 的 API 不是直接的 OpenAI 兼容接口。其消息格式与标准不同:

json 复制代码
// OpenAI 标准
{"messages": [{"role": "user", "content": "你好"}]}

// 百度 ERNIE(非兼容模式)
{"messages": [{"role": "user", "content": "你好"}], "system": "..."}

在使用百度原生 API 格式时,ERNIE 的 system 指令需要通过顶层参数传入,且某些模型版本要求不同的消息角色名。而在 OpenAI 兼容模式下(通过百度千帆平台的 OpenAI 兼容接口),messages 数组中的 system 角色是受支持的。要使用标准的 OpenAI SDK 调用 ERNIE,需要通过一层协议转换中间件(如 LiteLLM、One API)。

案例二:智谱 GLM 的工具调用限制

智谱 GLM 支持基本的工具调用功能,但有以下限制:

  • tool_choice 只支持 "auto" 和具名 function,不支持 "required"
  • 复杂嵌套 JSON Schema 的工具参数可能解析失败
  • 不支持 parallel_tool_calls
案例三:流式输出的 token usage 差异

在 OpenAI 的流式响应中,可以通过 stream_options={"include_usage": True} 在最后一个 chunk 获取 prompt_tokens 和 completion_tokens。DeepSeek 和 Qwen 支持此功能,但智谱 GLM、Moonshot、StepFun、MiniMax、百度均不支持。需要 token 统计时,这些厂商只能通过非流式请求获取。

5.3 国内厂商扩展字段

以下是各厂商在 OpenAI 标准 body 之外的专有请求字段:

厂商 扩展字段 类型 说明
DeepSeek prefix bool 将最后一个 user 消息的 content 视为文本前缀而非指令(续写场景),需配合特定消息结构使用,通过 extra_body 传入
通义 Qwen enable_search bool 启用联网搜索增强回答
智谱 GLM do_sample bool 是否使用采样策略,设为 false 等同 temperature=0
MiniMax role_play bool 角色扮演模式
MiniMax mask_sensitive_info bool 敏感信息自动打码

这些扩展字段的标准传入方式是通过 extra_body

python 复制代码
response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[...],
    extra_body={"prefix": True}  # DeepSeek 续写模式
)

六、参数组合与使用模式

6.1 参数的四个控制维度

所有参数组合,归根到底在四个维度上控制模型行为:

text 复制代码
维度A:输出一致性 ←→ 创造性
  控制每次调用结果的稳定程度
  temperature=0 + seed → 确定输出
  temperature=0.7 → 有一定随机性
  temperature=1.2 + top_p=0.9 → 高创意

维度B:输出长度预算管理
  控制一次请求能拿到多少内容
  max_tokens=50 → 短回答
  max_tokens=500 → 标准回答
  max_tokens=4000 + 续写循环 → 长文本

维度C:话题聚焦 ←→ 话题探索
  控制模型在内容上的粘性和跳跃
  penalty 全 0 → 容易重复
  frequency_penalty=0.5 → 换词不换话题
  presence_penalty=0.6 → 主动推动话题

维度D:输出形式约束强度
  控制返回内容的结构严格度
  response_format="text" → 无约束
  response_format="json_object" → 弱约束(只保证是 JSON)
  response_format="json_schema" + strict → 严格约束
  tool_choice="required" → 严格约束(曲线救国)

6.2 有意义与无意义的组合

理解每个维度的意图后,就能看出哪些组合是矛盾的:

组合 效果 评价
temperature=0 + seed=42 确定输出 ✅ 推荐,生产环境标配
temperature=0 + top_p=0.1 极度确定 ✅ 可用,但 top_p 多余
temperature=0 + stream=true 确定性流式 ✅ 常见,不冲突
temperature=1.5 + frequency_penalty=2 高创意但惩罚词 ⚠️ 矛盾------temperature 在发散、penalty 在收敛,效果不可预测
response_format=json_schema + temperature=1.5 严格结构 + 高创意 ⚠️ 矛盾------大概率输出无效 JSON
max_tokens=50 + presence_penalty=2 短输出 + 推话题 ⚠️ 浪费------token 预算不够说完一句话
stream=true + n>1 流式 + 多候选 ❌ API 报错
tool_choice="required" + 无 tools 强制调用 + 无工具 ❌ API 报错
reasoning_effort="high" + max_tokens=50 深度推理 + 短预算 ❌ 必然截断,content 永远为空

6.3 实际程序中的常见模式

模式 A:纯管道

最常见的模式------temperature=0、无工具、短 max_tokens。

python 复制代码
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "分类这条文本:..."}],
    max_tokens=50,
    temperature=0
)
  • 用途:分类、提取、翻译、重写
  • 程序结构:请求 → 解析 → 返回,无状态
  • 风险:几乎无风险
模式 B:对话引擎

messages 持续增长,temperature=0.7~0.9,无 penalty。

  • 用途:聊天机器人、客服
  • 程序结构:维护 messages 历史列表,每次追加
  • 风险:messages 无限增长 → token 成本 + 上下文窗口溢出
  • 缓解:滑动窗口 / 摘要压缩历史
模式 C:结构化生成器

temperature=0 + response_format(json_schema) + max_tokens 充足。

  • 用途:数据合成、结构化输出管道
  • 程序结构:解析 JSON → 校验 schema → 失败重试
  • 风险:strict 模式下仍可能输出无效内容
  • 缓解:重试逻辑 + fallback
模式 D:长文生成器

temperature=0.8 + frequency_penalty=0.5 + 续写循环。

  • 用途:写作、报告生成、故事
  • 程序结构:检测 finish_reason → 拼 messages → 递归
  • 风险:无限循环、推理模型 content 为空
  • 缓解:max_continuations 限制 + reasoning_content 检测
模式 E:工具执行器

tools + tool_choice + 循环执行 + 结果回填。

  • 用途:Agent 系统
  • 程序结构:请求 → 解析 tool_calls → 执行 → 回填 → 再请求
  • 风险:tool calling 循环死锁
  • 缓解:max_tool_calls 限制

七、典型案例:自动续写中的参数协作

以项目 llmapi-example 中的自动续写功能为案例,展示多个参数如何协作。

7.1 续写场景的参数协作链

自动续写的核心流程,参数按顺序被触及:

text 复制代码
① 发起请求
   model="gpt-4o"
   messages=[system, user]
   max_tokens=200         ← 控制每次输出的 token 预算

② 检查响应
   finish_reason="length" ← 模型输出被 max_tokens 截断
   content="已生成的部分内容..."

③ 拼接历史(关键步骤)
   messages.append({"role": "assistant", "content": content})
   messages.append({"role": "user", "content": "继续"})

④ 再次请求(回到步骤①)
   ...

这个循环在 continuation.py 中实现。完整的参数协作链是:

text 复制代码
max_tokens → 控制输出长度
    ↓
finish_reason → "length" 不等于出错,程序需要识别的信号
    ↓
messages → 必须正确拼入 assistant 内容,否则上下文丢失
    ↓
max_continuations → 防止无限循环的安全边界

7.2 推理模型的特殊适配

当使用 DeepSeek R1(deepseek-reasoner)等推理模型时,上述流程会出现一个陷阱:

python 复制代码
# 陷阱:推理模型输出中可能只有 reasoning_content 没有 content
message = response.choices[0].message

reasoning = getattr(message, "reasoning_content", None)  # "有值..."
content = message.content                                  # ""(空!)

if not content and reasoning:
    # 推理占满了所有 token,content 被挤掉了
    # 不能拼入空 content → 会污染上下文
    # 应该放大 max_tokens
    max_tokens = min(max_tokens * 2, 4096)

continuation.py 中的实现(约第 51-65 行):

python 复制代码
if finish_reason == "length" and continuation_count < cfg.max_continuations:
    # 推理模式特殊处理:content 为空且 reasoning 有值
    if reasoning_content and not content:
        next_max_tokens = min(next_max_tokens * 2, 4096)
        # 不拼入空的 assistant content
    else:
        messages.append({"role": "assistant", "content": content})
    messages.append({"role": "user", "content": "继续"})
    continuation_count += 1

7.3 同步 vs 流式续写

同步续写和流式续写的参数协作逻辑基本相同,但检查点的时机不同:

方面 同步模式 流式模式
检查 finish_reason 在完整响应中一次性检查 在最后一个 chunk 中检查
拼接 content 直接取 message.content 逐 chunk 积累到完整
检测 reasoning_content message 对象上直接 getattr 逐 chunk 检查 delta.reasoning_content
用户体验 等待完整响应后一次性输出 逐 token 展示,体验更好

流式模式中,程序需要实时积累内容的同时,对最后一个 chunk 进行截断判断。

八、总结与最佳实践

8.1 参数选择决策树

从程序实现的角度,选择参数组合的决策路径:

text 复制代码
开始:我需要什么?
│
├─ 稳定输出 → temperature=0
│   ├─ 需要可复现 → + seed(如果厂商支持)
│   └─ 不需要可复现 → 不设 seed
│
├─ 长文本 → temperature=0.7~0.8
│   ├─ 需续写逻辑 → 实现 finish_reason 检测循环
│   │   ├─ 支持推理模式 → + reasoning_content 检测
│   │   └─ 非推理 → 直接续写
│   └─ 需控重复 → + frequency_penalty=0.3~0.5
│
├─ 对话 → temperature=0.7~0.9
│   └─ 需防话题循环 → + presence_penalty=0.3~0.5
│
├─ 结构化输出 → response_format 或 tools
│   ├─ 厂商支持 json_schema → response_format
│   └─ 厂商不支持 → 降级到 tool_choice="required"
│
└─ 需要工具 → tools + tool_choice + 循环执行
    └─ 国内厂商 → 先确认工具调用树兼容性

8.2 跨厂商迁移检查清单

当从 OpenAI 迁移到国内厂商时,按优先级检查:

  1. model 映射是否准确 --- 不同厂商的模型能力差异巨大
  2. response_format 是否支持 --- json_schema 和 json_object 可能不可用
  3. seed 是否支持 --- 如果程序依赖可复现输出
  4. stream_options.include_usage --- 如果程序需要 token 统计
  5. tool calling 具体限制 --- parallel_tool_calls、tool_choice 支持程度
  6. 扩展字段 --- 是否需要通过 extra_body 传入厂商特有参数
  7. 消息格式 --- 百度 ERNIE 等可能需要适配器

8.3 推荐的错误处理策略

python 复制代码
# 推荐的错误处理分层
try:
    response = client.chat.completions.create(...)
except APITimeoutError:
    # 超时重试(指数退避)
except AuthenticationError:
    # API Key 无效,提示用户检查配置
except APIStatusError as e:
    # 参数不支持、模型不存在等
    # 判断 e.status_code:
    #   400 → 参数错误,检查兼容性
    #   401/403 → 认证问题
    #   429 → 限流,退避重试
except APIError:
    # 通用错误,记录日志

需要注意的几点:

  • finish_reason="length" 不是错误,是截断信号
  • content 不一定是错误------推理模型的 content 可能为空但 reasoning_content 有值
  • 重试时注意 max_continuations 限制,避免无限循环
相关推荐
甲维斯1 小时前
MiMo的120亿,Codex的15小时,CC的30个Agent,搞定OpenAI的321个文档!
人工智能·openai
星浩AI2 小时前
(六)模型微调效果测试:基于 BERT 的中文评价情感分析[附源码]
人工智能·机器学习·llm
兆。3 小时前
如何在本地搭建天气智能体项目
langchain·openai·qwen·ollama·本地大模型
树獭非懒3 小时前
AI Agent 入门:理论、原理与5分钟代码实战
人工智能·llm·agent
swipe13 小时前
DeepAgents 实战:用多 Agent 架构搭一个深度调研助手
javascript·面试·llm
XLYcmy15 小时前
全链路验证测试系统:一个针对智能代理(Agent)系统全链路能力的自动化验证脚本
分布式·python·http·网络安全·ai·llm·agent
johnny23318 小时前
大模型测评之:CLUE、SuperCLUE、GLUE、SuperGLUE
llm·benchmark
格桑阿sir19 小时前
10-大模型智能体开发工程师:RAG检索增强生成
ai·大模型·llm·embedding·agent·检索增强·rag
guyoung19 小时前
BoxAgnts介绍(7)——OpenAI-API与Anthropic-API
openai·agent·ai编程