文章目录
- LangChain 模型参数调优:temperature、max_tokens 这些到底怎么设
- 一、先认识三个最常用的
- 二、temperature:不是" creativity 旋钮"
- 2.1 它实际在做什么
- 2.2 怎么选
- 2.3 temperature=0 也做不到 100% 复现
- 三、max_tokens:控制输出的刹车
- 3.1 它控制的是"输出",不是"上下文"
- 3.2 设多大的经验
- 四、top_p:另一种控制随机的方式
- 五、stop:让模型知道什么时候闭嘴
- 六、timeout 与 max_retries:生产必配
- 七、运行时改参数:bind
- 八、按任务分档:一份配置清单
- 九、不同模型的参数差异
- 十、小结
LangChain 模型参数调优:temperature、max_tokens 这些到底怎么设
很多人从头到尾只用
ChatOpenAI(model="gpt-4o-mini"),
其他参数一个不动,然后抱怨"输出不稳定"“老是截断”“太慢了”。这篇把常用参数讲清楚:每个参数解决什么问题、典型取值、
以及哪些组合会互相打架。
一、先认识三个最常用的
fromlangchain_openaiimportChatOpenAI llm=ChatOpenAI(model="gpt-4o-mini",temperature=0,# 随机性max_tokens=1000,# 输出上限timeout=30,# 超时(秒)max_retries=2,# 失败重试)| 参数 | 作用 | 典型取值 |
|---|---|---|
temperature | 采样温度,越高越随机 | 0(确定性任务)/ 0.7(创作) |
max_tokens | 单次输出最大 token | 按需,别设太大 |
timeout | 单次请求超时 | 30~60 |
max_retries | 失败自动重试 | 2~3 |
二、temperature:不是" creativity 旋钮"
2.1 它实际在做什么
模型每一步输出的是一个概率分布。temperature 决定"怎么从这个分布里挑词":
temperature=0:每次都选概率最高的(贪心),同样的输入永远同样的输出;temperature=0.7:按概率加权随机采样,小概率词也有机会;temperature=1.5:分布被拉平,输出接近胡说。
2.2 怎么选
| 任务 | 推荐 | 理由 |
|---|---|---|
| 信息抽取 / 分类 / JSON 输出 | 0 | 要稳定可复现 |
| RAG 问答 | 0 ~ 0.2 | 要忠于原文,别发挥 |
| 代码生成 | 0 ~ 0.2 | 要正确 |
| 一般对话 | 0.5 ~ 0.7 | 自然一点 |
| 创意写作 / 头脑风暴 | 0.8 ~ 1.0 | 要多样性 |
RAG 和结构化输出一律设 0。
我见过太多"RAG 答案每次不一样"的问题,
一问就是 temperature 用的默认值 0.7。
2.3 temperature=0 也做不到 100% 复现
即使 temperature=0,模型服务端有批处理优化、浮点不确定性,
偶尔仍会有细微差异。要做到严格可复现,可以再加seed:
llm=ChatOpenAI(model="gpt-4o-mini",temperature=0,seed=42)但别依赖它做单元测试——更可靠的做法见后面"测试"那篇,
用 Fake LLM 而不是依赖真实模型的确定性。
三、max_tokens:控制输出的刹车
3.1 它控制的是"输出",不是"上下文"
常见误解:以为max_tokens限制的是总长度。
实际上它只限制这次生成能输出多少 token,输入不算。
3.2 设多大的经验
# 简短回答(分类、标签、一句话)max_tokens=50# 常规问答max_tokens=500# 长文生成max_tokens=2000设太小的后果:输出被硬截断,句子写到一半没了,
JSON 少了后半截导致解析失败。
# 被截断的 JSON{"name":"张三","age":28,"cit这个坑非常常见,尤其是结构化输出时。
如果你发现 JSON 偶尔解析失败,先看看是不是被截断了:
result=llm.invoke(messages)print(result.response_metadata.get("finish_reason"))# "length" ← 就是被 max_tokens 截断了# "stop" ← 正常结束设太大的后果:成本失控。某个异常输入让模型喋喋不休输出 4000 token,
你就要为这 4000 token 买单。
四、top_p:另一种控制随机的方式
llm=ChatOpenAI(model="gpt-4o-mini",temperature=0.7,top_p=0.9)top_p(核采样):只从"累积概率达到 p 的候选词"里采样。
比如top_p=0.9意味着只考虑概率加起来到 90% 的那些词。
官方建议:temperature 和 top_p 只调一个,不要同时调。
两个一起动会让行为难以预测。实践中用temperature就够了,top_p保持默认 1。
五、stop:让模型知道什么时候闭嘴
llm=ChatOpenAI(model="gpt-4o-mini",stop=["\n\n用户:","###"])遇到这些字符串就停止生成。适合:
- 少样本示例场景,防止模型自己编出下一轮对话;
- 结构化输出,防止模型在 JSON 后面追加解释。
llm=ChatOpenAI(model="gpt-4o-mini",temperature=0,stop=["\n}"])六、timeout 与 max_retries:生产必配
llm=ChatOpenAI(model="gpt-4o-mini",timeout=30,max_retries=2,)timeout:单次请求超时。不设的话可能挂很久,
在 Web 服务里会拖垮整个线程池;max_retries:自动重试。LangChain 内置了指数退避,
不用自己写。只重试可重试的错误(限流、5xx),
参数错误不会重试。
注意重试会放大成本:一次超时重试 3 次 = 最多 4 次调用。
配合上层自己的重试策略时,别叠成"3 × 3 = 9 次"。
七、运行时改参数:bind
不想为每个参数组合都建一个模型实例,用bind:
base=ChatOpenAI(model="gpt-4o-mini",temperature=0)# 临时要个有创意的版本creative=base.bind(temperature=0.9)bind返回一个新对象,原对象不变,可以放心复用。
同理还可以 bind 工具、bind 停止词:
with_tools=base.bind_tools([get_weather])with_stop=base.bind(stop=["###"])八、按任务分档:一份配置清单
# 抽取 / 分类 / JSON —— 要稳EXTRACT=ChatOpenAI(model="gpt-4o-mini",temperature=0,max_tokens=500,timeout=30,max_retries=2)# RAG 问答 —— 忠于原文RAG=ChatOpenAI(model="gpt-4o-mini",temperature=0,max_tokens=800,timeout=60,max_retries=2)# 对话助手 —— 自然一点CHAT=ChatOpenAI(model="gpt-4o-mini",temperature=0.7,max_tokens=600,timeout=30,max_retries=2)# 复杂推理 —— 用强模型,给足输出空间REASON=ChatOpenAI(model="gpt-4o",temperature=0,max_tokens=2000,timeout=120,max_retries=1)不要所有场景共用一个模型实例。
分成几个"预设",用的时候挑,比每次临时调参清晰得多。
九、不同模型的参数差异
上面都是 OpenAI 的参数。换模型时参数名可能不一样:
| 模型 | 差异 |
|---|---|
| OpenAI | temperature/max_tokens/top_p/seed |
| Anthropic | max_tokens必填,还有top_k |
| 部分国产模型 | 可能有top_p但不支持seed |
| Ollama 本地模型 | 参数通过num_predict/num_ctx等传递 |
# Ollama 的参数风格完全不同fromlangchain_community.chat_modelsimportChatOllama llm=ChatOllama(model="qwen2.5",temperature=0,num_predict=512,num_ctx=4096)统一接口不代表参数统一。换模型时务必查一下该实现支持哪些参数,
传了不支持的参数有的会静默忽略(最坑),有的会报错。
十、小结
- RAG 和结构化输出 →
temperature=0,这是最重要的一条; max_tokens只限制输出,设太小会导致 JSON 被硬截断
(用finish_reason == "length"判断);temperature和top_p只调一个;- 生产必配
timeout和max_retries,但注意重试会放大成本; - 用
bind()临时改参数,不改原对象; - 按任务分档建几个预设实例,别所有场景共用一个;
- 换模型时参数名可能不同,别照抄。
下一篇讲 Few-shot 与示例选择——不微调也能提升效果的实用技巧。