每一个参数背后都是一种权衡

为什么要把参数讲清楚

前面主线我们用 chat.completions.create 时大多只传 modelmessagestemperature=0 点到即止。真实项目里这个 API 还有十几个参数,每个都对应一种可调的权衡。不懂它们意味着你只在用 10% 的控制力。本篇按类别把关键参数讲清楚,并给"什么时候该调、调成什么值"的实战建议。

核心参数:model 和 messages

这两个不用多说,前面已经讲透。唯一提醒:model 字符串要和后端支持的完全匹配,DeepSeek 是 deepseek-chat / deepseek-reasoner,OpenAI 是 gpt-4o / gpt-4o-mini 等。写错了会直接报错而不是 fallback。

采样相关:控制随机性

temperature(0~2,默认 1)

控制采样的"锐度"。数学上它是 softmax 函数的缩放系数,直观理解:

  • temperature=0——模型每次都选概率最高的 token,输出最确定
  • temperature=1——按模型输出的原始概率分布采样
  • temperature>1——拉平分布,低概率 token 被选中的机会上升,输出更发散

选值建议:

  • 分类、抽取、Function Calling——设 0
  • 代码生成——00.3
  • 日常对话、摘要——0.50.7
  • 创意写作、头脑风暴——0.81.2
  • >1.5 基本不用,容易胡言乱语

top_p(0~1,默认 1)

采样另一个维度的控制。top_p=0.9 意味着"只从累积概率 0.9 的最可能 token 集合里采样"。它和 temperature 可以单独或组合使用,但实务上调一个就够——大多数人调 temperaturetop_p 留默认。

seed(整数,可选)

固定随机种子,同样输入 + 同样 seed 应该产生相同输出。注意:这是"尽力而为"的保证,GPU 非确定性浮点运算可能让结果有微小差异。对需要可复现调试的场景有用。

长度相关

max_tokens / max_completion_tokens

限制模型最多生成多少 token。不设默认值很大(几千到一两万)。设它的两个场景:

  • 防失控——避免模型被诱导写几千字长文烧钱
  • 强制简洁——搭配 Prompt "简洁回答"双重保障

注意它限制的是输出长度,不是输入。如果输出被这个值截断,模型可能在句子中间戛然而止,要做好处理。

较新的模型(OpenAI o 系列)用的是 max_completion_tokens,语义一样,参数名变了。

流式相关

stream(布尔,默认 False)

打开 SSE 流式输出。第 02 篇讲过,不再赘述。值得补一句:流式和非流式在计费上完全一样,区别仅在延迟和可中断。开发/生产建议常开。

stream_options(对象,可选)

最常用的是 {"include_usage": True}——让流式模式下也能收到 token 使用量统计(默认流式不给 usage)。监控和成本统计时必加:

stream = client.chat.completions.create(
    model="deepseek-chat",
    messages=messages,
    stream=True,
    stream_options={"include_usage": True},
)

结构化输出相关

response_format

  • {"type": "text"}(默认)——普通文本
  • {"type": "json_object"}——强制返回合法 JSON(Prompt 里必须出现 "JSON" 字样)
  • PydanticModel(新版 SDK 支持)——严格按 schema 返回

第 04 篇深入讲过,不展开。实务上优先使用 Pydantic 模型 + instructor 库。

工具相关

toolstool_choice

第 07 篇讲过 toolstool_choice 控制模型是否必须调用工具:

  • "auto"(默认)——模型自行决定
  • "none"——禁止调用工具
  • "required"——必须调用某个工具
  • {"type": "function", "function": {"name": "x"}}——强制调用指定的工具

强制某工具的场景:你想让模型必须先分类意图(调用分类工具),再决定后续。

惩罚与偏置

frequency_penalty(-2~2,默认 0)

已出现的 token按出现次数施加惩罚。正值让模型避免重复(比如防止"非常非常非常"),负值鼓励重复。

presence_penalty(-2~2,默认 0)

已出现的 token施加一次性惩罚(不按次数)。正值鼓励引入新话题,负值让模型坚持已有话题。

实务经验:绝大多数场景都留 0 别动。这两个参数对模型行为影响微妙,不懂机制调乱比不调更差。真需要防重复时,写 Prompt 或者调 temperature 效果更可控。

logit_bias(字典,可选)

对特定 token 的 logit 值加偏置,强制提升或禁止某些 token 的生成概率。典型用途是"禁止输出某些词":

# 把 "抱歉" "对不起" 这类词压制掉(需要先用 tokenizer 拿到 token id)
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[...],
    logit_bias={50256: -100, 123: -100},  # -100 约等于禁止
)

使用前提是你能拿到 token id,tiktoken 能帮你做。用起来比较麻烦,属于"Prompt 搞不定再考虑"的兜底手段。

调试用的高级参数

logprobs(布尔,默认 False)

返回每个生成 token 的概率。配合 top_logprobs=N 能看到"每一步模型考虑了哪几个候选 token 和它们的概率"。

resp = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "今天是"}],
    logprobs=True,
    top_logprobs=5,
    max_tokens=5,
)

for token_info in resp.choices[0].logprobs.content:
    print(f"选中:{token_info.token}")
    for alt in token_info.top_logprobs:
        print(f"  候选:{alt.token}  p={alt.logprob}")

实战价值:做置信度估计(预测结果的概率)、理解模型为什么这么输出做模型对比研究。非研究场景很少用。

n(整数,默认 1)

一次请求让模型生成 N 个不同回答。想用于"多路采样取最好"时可以用,但成本是 N 倍。推理模型(o 系列)不支持 n

stop(字符串或字符串列表)

命中这些字符串时立即停止生成。典型用法:让模型生成到某个标记就停。

resp = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "列举 3 个 Python web 框架"}],
    stop=["END"],
)

推理模型的特殊参数

新一代推理模型(OpenAI o 系列、DeepSeek R1)引入了一些特有参数:

reasoning_effort"low" / "medium" / "high"

控制模型的"思考深度"。高档位推理时间更长、成本更高、结果更准。简单任务用 low 省钱。

不支持的传统参数:temperaturetop_pfrequency_penaltypresence_penaltylogprobs 在推理模型上一般无效或不支持。推理模型的输出变化性由它自己内部控制。

一个实战组合

整合一下,一个"稳定提取 JSON"的典型调用应该长这样:

resp = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "system", "content": "你是一个信息抽取器,输出 JSON。"},
        {"role": "user", "content": text},
    ],
    temperature=0,              # 降随机性
    max_tokens=800,             # 防失控
    response_format={"type": "json_object"},  # 强制合法 JSON
    stream=False,               # 一次性拿完整结果
)

而一个"创意写作"的调用看起来这样:

resp = client.chat.completions.create(
    model="deepseek-chat",
    messages=[...],
    temperature=1.0,
    max_tokens=2000,
    stream=True,                # 流式改善等待体验
    stream_options={"include_usage": True},
)

一个经验:把参数标准化到业务场景。分类类调用共用一组参数、写作类调用共用一组参数,不要每个地方自己拍脑袋。可以把场景参数封装成一组 preset:

PRESETS = {
    "extract": {"temperature": 0, "response_format": {"type": "json_object"}},
    "chat": {"temperature": 0.7},
    "creative": {"temperature": 1.0, "max_tokens": 2000},
}

def chat(messages, scenario: str = "chat", **overrides):
    params = {**PRESETS[scenario], **overrides}
    return client.chat.completions.create(model=..., messages=messages, **params)

相关阅读

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:番外 2:API 参数全解,temperature 到 logprobs

本文链接:https://www.sshipanoo.com/blog/ai/ai-for-python/番外02-API参数详解/

本文最后一次更新为 天前,文章中的某些内容可能已过时!