LangChain Chat Model 常用参数
上一节我们学习了 init_chat_model() 函数的基本用法。
使用 LangChain 调用大语言模型时,除了指定模型名称,还可以配置输出随机性、最大 Token 数、请求超时、失败重试和 API 地址等参数。
合理使用这些参数,可以更好地控制模型行为、接口响应时间和调用成本。
本章节将介绍 LangChain Chat Model 的常用参数,并使用 DeepSeek 模型进行演示。
注意:LangChain 提供统一的模型调用接口,但不同提供商、模型版本和思考模式支持的参数可能不同。某个参数可以成功传入,并不意味着它一定会影响模型输出。
一、安装与准备
本教程使用 LangChain 1.x 和 DeepSeek 官方模型接口。
首先安装依赖:
pip install -U langchain langchain-deepseek python-dotenv
在项目目录创建 .env 文件:
DEEPSEEK_API_KEY=your_deepseek_api_key
然后使用 load_dotenv() 加载环境变量:
实例
from langchain.chat_models import init_chat_model
load_dotenv()
# 使用 DeepSeek Flash
model = init_chat_model(
"deepseek:deepseek-flash"
)
response = model.invoke("你好,LangChain!")
print(response.content)
根据 DeepSeek 当前官方 API 文档,常用模型名称如下:
| 模型 | API 模型 ID | LangChain 初始化名称 |
|---|---|---|
| DeepSeek Flash | deepseek-flash |
deepseek:deepseek-flash |
| DeepSeek Pro | deepseek-v4-pro |
deepseek:deepseek-v4-pro |
旧名称 deepseek-v4-flash 等可能仍作为兼容别名存在,新代码建议使用 deepseek-flash。
二、temperature:控制生成随机性
temperature 是聊天模型中常用的采样参数,用于调整模型生成内容时的随机程度。
通常情况下:
- 较低的 temperature:模型更倾向于选择概率较高的 Token。
- 较高的 temperature:模型可能产生更多样化的输出。
对于支持该参数的 DeepSeek Chat Completions 接口,temperature 的取值范围为 0~2。
例如:
temperature=0.0 temperature=0.7 temperature=1.5
需要注意,这个范围不是 LangChain 对所有模型统一规定的范围。
实例:比较不同 temperature
下面通过相同问题,对比不同温度设置下的模型输出。
此示例仅适用于实际支持 temperature 调整的非思考模型或模式。
实例
from langchain.chat_models import init_chat_model
load_dotenv()
question = "用一句话介绍菜鸟教程 RUNOOB"
# 较低温度
model_low = init_chat_model(
"deepseek:deepseek-flash",
temperature=0.2
)
# 较高温度
model_high = init_chat_model(
"deepseek:deepseek-flash",
temperature=1.2
)
print("=== 较低温度 ===")
for i in range(2):
response = model_low.invoke(question)
print(f"第 {i + 1} 次:{response.content}")
print("\n=== 较高温度 ===")
for i in range(2):
response = model_high.invoke(question)
print(f"第 {i + 1} 次:{response.content}")
如果当前模型处于非思考模式并实际支持 temperature 调整,可以观察其对输出的影响。
但模型每次生成的结果并不固定,较低温度也不能保证完全相同。
temperature 的使用建议
| 参考范围 | 通常的生成特点 | 适用场景 |
|---|---|---|
| 0~0.3 | 更偏向高概率输出 | 分类、信息提取、格式化任务 |
| 0.4~0.7 | 相对均衡 | 一般问答、内容整理 |
| 0.8~1.2 | 更强调多样性 | 创意写作、方案探索 |
| 1.3~2.0 | 随机性可能明显增大 | 实验性生成、创意探索 |
这张表仅提供一般性的采样思路,并不是适用于所有模型的推荐配置。
DeepSeek 思考模式的特殊规则
根据 DeepSeek 当前官方文档,思考模式不支持通过 temperature 调整采样行为。
为了兼容已有软件,即使请求中包含 temperature,接口也可能不报错,但该参数不会生效。
因此:
- 使用普通非思考模式时,应查看当前模型是否支持温度调整。
- 使用思考模式时,不应依赖 temperature 控制输出随机性。
- 不应通过两次输出是否相同来判断 temperature 一定生效。
建议:先确认当前模型模式和参数支持情况,再进行温度实验。如果希望比较采样参数的影响,应固定模型版本和其他请求设置。
三、max_tokens:限制输出 Token 数
max_tokens 用于设置模型单次请求允许生成的最大 Token 数量。
Token 是模型处理文本时使用的基本单位,但并不等同于字符或单词。
例如,下面几段文本的 Token 数可能不同:
Hello, world!
你好,世界!
print("Hello, world!")
Token 数取决于具体模型使用的分词器,不能简单认为一个中文字一定等于两个 Token,或者一个 Token 一定对应固定数量的英文单词。
实例:设置最大输出长度
推荐在初始化模型时设置 max_tokens。
实例
from langchain.chat_models import init_chat_model
load_dotenv()
question = "介绍 Python 编程语言的主要特点。"
# 较短输出限制
model_short = init_chat_model(
"deepseek:deepseek-flash",
max_tokens=100
)
# 较长输出限制
model_long = init_chat_model(
"deepseek:deepseek-flash",
max_tokens=500
)
response_short = model_short.invoke(question)
response_long = model_long.invoke(question)
print("=== max_tokens=100 ===")
print(response_short.content)
print("\n=== max_tokens=500 ===")
print(response_long.content)
如果模型和接口支持该参数,较低的上限通常会限制可生成的内容长度。
但 max_tokens=500 不代表模型一定会生成 500 个 Token。它设置的是上限,而不是目标输出数量。
max_tokens 的注意事项
- 限制的是输出 Token,而不是输入内容长度。
- 达到上限时,模型回答可能不完整。
- 对于思考模型,输出预算可能同时涉及思考内容和最终回答。
- 实际计费可能包括输入、输出以及模型特定的其他 Token 类别。
- 参数名称和限制规则需要以具体模型 API 为准。
因此,max_tokens 可以帮助控制单次输出预算,但不能单独保证最终 API 费用。
使用 bind() 创建不同配置
如果已经创建了模型,可以使用 LangChain 的 bind() 方法生成带有额外调用参数的模型包装对象。
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
# 为调用绑定输出上限
short_model = model.bind(max_tokens=100)
long_model = model.bind(max_tokens=500)
question = "介绍 Python 的主要特点。"
print(short_model.invoke(question).content)
print(long_model.invoke(question).content)
bind() 不会修改原模型的初始化配置,而是返回一个带有绑定参数的新 Runnable。
这种方式适合在不同任务中复用同一个模型配置。
例如,分类任务可以使用较小的输出预算,而教程生成任务可以使用较大的输出预算。
四、查看实际 Token 使用量
相比简单计算输出文本的字符数,更可靠的做法是读取模型返回的 Token 使用统计。
LangChain 的 AIMessage 通常通过 usage_metadata 暴露标准化的 Token 统计信息。
实例
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
response = model.invoke(
"用 100 字左右介绍 Python。"
)
print("模型回答:")
print(response.content)
print("\nToken 使用统计:")
print(response.usage_metadata)
if response.usage_metadata:
usage = response.usage_metadata
print("输入 Token:", usage.get("input_tokens"))
print("输出 Token:", usage.get("output_tokens"))
print("总 Token:", usage.get("total_tokens"))
对于提供使用量统计的模型,可能返回类似:
{
'input_tokens': 20,
'output_tokens': 85,
'total_tokens': 105
}
以上只是结构示例,不代表实际调用产生的固定 Token 数量。
不同模型还可能提供额外的 Token 明细,例如缓存命中或思考 Token 等。
如果 usage_metadata 为 None,表示该次响应没有提供标准化的使用量数据,不能直接认为实际消耗为零。
五、timeout:设置请求超时
timeout 用于控制模型请求的等待时间,避免网络请求长时间无法结束。
例如:
timeout=30
通常表示按底层模型集成的定义设置 30 秒的请求超时。
实例
实例
model = init_chat_model(
"deepseek:deepseek-flash",
timeout=30
)
try:
response = model.invoke(
"介绍 Python 编程语言。"
)
print(response.content)
except Exception as error:
print(
"模型调用失败:",
type(error).__name__,
str(error)
)
设置超时时间可以避免部分网络请求无限等待,但具体超时行为可能涉及连接、读取和 SDK 的内部实现。
对于耗时较长的模型任务,不宜直接使用过短的超时时间,否则可能导致正常请求被提前中断。
timeout 参考设置
| 场景 | 参考超时 | 说明 |
|---|---|---|
| 简短问答 | 15~30 秒 | 适合响应速度要求较高的交互 |
| 一般文本生成 | 30~60 秒 | 根据输出长度和服务速度调整 |
| 长文本或复杂推理 | 60 秒或更长 | 需要考虑模型推理耗时和流式响应 |
以上只是工程配置参考值,不是 LangChain 或 DeepSeek 的强制规定。
六、max_retries:请求失败重试
max_retries 用于设置模型请求失败后的最大重试次数。
例如:
max_retries=2
在集成支持相应重试策略的情况下,发生符合条件的临时错误时,可以重新发起请求。
实例
实例
model = init_chat_model(
"deepseek:deepseek-flash",
# 请求超时
timeout=30,
# 失败重试次数
max_retries=2
)
try:
response = model.invoke(
"菜鸟教程 RUNOOB 是什么?"
)
print("调用成功:")
print(response.content)
except Exception as error:
print("调用失败:", error)
max_retries 主要用于提高临时网络故障或部分服务端错误下的请求成功率。
但它不能修复所有错误。
例如:
- API Key 无效。
- 模型名称不存在。
- 请求参数不受支持。
- 账户没有模型调用权限。
这些错误一般需要修正配置,而不是通过增加重试次数解决。
timeout 与 max_retries 的关系
假设设置:
timeout=30 max_retries=3
如果当前模型集成允许初次请求之外再重试 3 次,那么在全部请求都失败时,可能进行最多 4 次尝试。
但不能简单地认为整个过程最多需要:
4 × 30 = 120 秒
因为实际总耗时还可能包含:
- 重试前的等待和指数退避。
- 连接建立和网络延迟。
- 不同阶段的超时机制。
- SDK 或 HTTP 客户端的额外开销。
如果业务存在严格的整体请求时间预算,需要在应用层增加总超时控制,而不能只依赖模型初始化参数。
七、base_url:自定义 API 地址
base_url 用于指定模型请求发送到的 API 地址。
常见用途包括:
- 连接 OpenAI 兼容接口。
- 访问公司内部的模型网关。
- 连接本地部署的 vLLM 服务。
- 使用经过授权的 API 代理。
需要注意,base_url 只改变请求目标地址,不会自动改变底层协议。
provider 决定使用哪个 LangChain 集成,base_url 决定请求发送到哪里。
实例 1:通过 DeepSeek 原生集成
使用 DeepSeek 原生集成时,通常不需要自己配置 base_url。
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
response = model.invoke("你好")
print(response.content)
集成包会使用相应的默认 DeepSeek API 地址。
实例 2:通过 OpenAI 兼容接口调用 DeepSeek
DeepSeek 官方提供 OpenAI 兼容接口,其 API 地址为:
https://api.deepseek.com
如果希望通过 langchain-openai 访问,可以使用以下方式:
先安装:
pip install -U langchain-openai
实例
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
load_dotenv()
model = init_chat_model(
"deepseek-flash",
# 使用 OpenAI 集成
model_provider="openai",
# DeepSeek 官方兼容接口
base_url="https://api.deepseek.com",
api_key=os.environ["DEEPSEEK_API_KEY"]
)
response = model.invoke("你好")
print(response.content)
这里使用的是 openai provider,但实际访问的是 DeepSeek 的服务器。
需要注意,接口兼容不代表所有高级功能都完全一致,第三方模型特有的响应数据也可能无法通过通用集成完整获取。
实例 3:调用本地 vLLM 服务
如果本地 vLLM 已启动 OpenAI 兼容 API 服务,可以使用相同的方式连接。
实例
model = init_chat_model(
"Qwen/Qwen2.5-7B-Instruct",
model_provider="openai",
# 本地 vLLM 的 OpenAI 兼容接口
base_url="http://127.0.0.1:8000/v1",
# 仅作为本地示例
api_key="not-needed"
)
response = model.invoke(
"介绍一下 Python。"
)
print(response.content)
注意:这里假设本地 vLLM 服务已启动,且实际暴露的模型 ID 为 Qwen/Qwen2.5-7B-Instruct。
如果启动服务时指定了其他模型名称,应改为服务端实际提供的 ID。
api_key="not-needed" 仅适用于未启用认证、但兼容客户端要求传入一个密钥值的本地测试服务,不应作为公网接口的安全配置。
base_url 安全注意事项
不要直接将不可信用户输入作为 base_url。
如果允许客户端随意修改 API 地址,可能导致:
- API Key 被发送到非预期服务器。
- 内部网络地址被访问。
- 模型请求内容泄露。
实际项目中,应通过服务器端白名单限制可使用的 API 服务地址。
八、top_p:核采样参数
top_p 是另一种控制 Token 采样范围的参数,也称为核采样(Nucleus Sampling)。
例如:
top_p=0.9
一般而言,核采样会选择累计概率达到指定阈值的一组候选 Token,再从这组候选中进行采样。
需要注意,top_p=0.1 并不是从"概率最高的 10% 数量的词"中选择,而是使用累计概率阈值。
通用参数示例
对于支持该参数的模型,可以这样设置:
model = init_chat_model(
"openai:gpt-4o-mini",
top_p=0.9
)
具体是否支持以及允许的取值范围,应以对应模型 API 为准。
DeepSeek 的特殊规则
DeepSeek 当前官方 API 对 top_p 的处理具有特别的限制:
| 运行模式 | top_p 行为 |
|---|---|
| 非思考模式 | 固定为 1.0,传入的 top_p 值会被忽略 |
| 思考模式 | 生效范围为 0.95~1.0,低于 0.95 的值按 0.95 处理 |
因此,不建议继续使用旧教程中的:
top_p=0.1
作为 DeepSeek 随机性控制示例。
即便请求成功,也不意味着该值按照普通核采样规则生效。
对于同时支持温度和核采样的模型,通常建议先只调整其中一个参数,以便观察效果。
九、stop:设置停止序列
stop 用于指定一个或多个停止序列。
在模型与接口支持的情况下,当生成内容遇到停止序列时,会结束当前生成。
例如:
stop=["END"]
表示在模型生成指定停止字符串时终止输出。
实例
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
# 绑定停止序列
model_with_stop = model.bind(
stop=["END"]
)
response = model_with_stop.invoke(
"写三句介绍 Python 的话,最后输出 END。"
)
print(response.content)
如果接口正确执行停止序列规则,返回内容通常不会包含作为停止标记的 END。
但要注意,stop 的支持情况、停止字符串是否出现在输出中,以及具体截断行为,取决于所使用的模型和接口。
此外,停止序列只能用于文本生成控制,不应将其视为严格的输出结构校验手段。
如果需要 JSON 等结构化输出,应优先使用模型支持的结构化输出功能。
十、seed:控制可重复性
部分模型提供商提供 seed 参数,用于尽可能提高相同请求的可重复性。
例如,对于支持 seed 的模型,可以使用类似写法:
model = init_chat_model(
"openai:gpt-4o-mini",
seed=42
)
但需要注意:
- 不是所有模型都支持
seed。 - 相同 seed 不保证输出内容完全相同。
- 模型服务升级、后端配置变化或其他参数不同,都可能影响结果。
- 某些模型可能忽略不支持的参数,也可能直接返回错误。
目前不建议在 DeepSeek 的入门示例中直接使用:
seed=42
并声称两次输出一定相同。应先确认目标 DeepSeek 模型接口是否明确支持该参数。
如果业务要求严格可重复的结果,通常还需要固定模型版本、输入、参数,并结合缓存、输出校验等机制。
十一、rate_limiter:限制请求速率
对于需要连续调用模型的应用,可以通过 rate_limiter 配置客户端请求速率限制。
例如,在批量文本处理或自动化任务中,可以避免程序瞬间发起大量请求。
LangChain 提供 InMemoryRateLimiter,用于进程内的简单速率限制。
实例
实例
from langchain_core.rate_limiters import InMemoryRateLimiter
# 平均每秒允许 1 个请求
rate_limiter = InMemoryRateLimiter(
requests_per_second=1,
check_every_n_seconds=0.1,
max_bucket_size=1
)
model = init_chat_model(
"deepseek:deepseek-flash",
rate_limiter=rate_limiter
)
questions = [
"什么是 Python?",
"什么是 Java?",
"什么是 JavaScript?"
]
for question in questions:
response = model.invoke(question)
print(response.content)
InMemoryRateLimiter 使用进程内状态,因此适合简单的单进程应用或开发测试。
它并不是跨多个服务器共享的分布式限流器。
另外,客户端限流不等于提供商服务端的配额限制,服务端仍可能返回限流错误。
十二、初始化参数与调用参数的区别
LangChain 的模型参数可以在不同阶段设置。
方式一:初始化时指定
model = init_chat_model(
"deepseek:deepseek-flash",
max_tokens=200,
timeout=30,
max_retries=2
)
这种方式适合为一个模型对象设置默认配置。
方式二:通过 bind() 绑定
short_model = model.bind(max_tokens=100)
response = short_model.invoke("介绍 Python")
这种方式适合在复用原模型对象时,额外绑定某些调用参数。
方式三:使用可配置模型
如果需要在运行时通过 config 修改初始化字段,可以结合 configurable_fields。
实例
model = init_chat_model(
"deepseek:deepseek-flash",
max_tokens=200,
configurable_fields=[
"model",
"max_tokens"
]
)
# 默认配置
response = model.invoke(
"介绍 Python。"
)
print(response.content)
# 运行时覆盖最大输出 Token
response = model.invoke(
"介绍 Python。",
config={
"configurable": {
"max_tokens": 500
}
}
)
print(response.content)
这里的 config 不等同于模型 API 原生的请求参数,而是 LangChain Runnable 的运行时配置机制。
只有事先声明的可配置字段,才能按照相应规则通过 configurable 修改。
因此,bind() 和 configurable_fields 虽然都可以实现参数复用或覆盖,但它们的用途并不完全相同。
十三、完整实例:常用参数组合
下面将常用参数组合到一个可运行的程序中。
该示例以 DeepSeek Flash 为模型,设置输出上限、请求超时、重试次数,并显示 Token 使用统计。
实例
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
load_dotenv()
# 初始化模型
model = init_chat_model(
"deepseek:deepseek-flash",
# 最大输出 Token
max_tokens=300,
# 请求超时
timeout=30,
# 失败重试
max_retries=2
)
def ask(question: str):
"""调用模型并显示结果及 Token 统计。"""
try:
response = model.invoke(question)
print("问题:", question)
print("回答:", response.content)
# Token 使用统计
usage = response.usage_metadata
if usage:
print("输入 Token:", usage.get("input_tokens"))
print("输出 Token:", usage.get("output_tokens"))
print("总 Token:", usage.get("total_tokens"))
else:
print("模型没有返回标准化 Token 统计")
print("-" * 40)
except Exception as error:
print("调用失败:")
print(type(error).__name__)
print(str(error))
if __name__ == "__main__":
ask("用一句话介绍菜鸟教程 RUNOOB。")
ask("列出 Python 的三个优点。")
运行代码:
python chat_model_params.py
程序会输出:
- 用户问题。
- 模型生成的回答。
- 输入和输出 Token 统计(如果服务端提供)。
- 请求失败时的错误信息。
由于模型输出和 Token 统计会发生变化,这里不提供固定的运行结果。
说明:本例没有主动设置 temperature 或 top_p,而是使用对应模型模式下的默认行为,避免在不了解当前采样参数支持情况时传入可能无效的配置。
十四、参数速查表
| 参数 | 常见类型 | 作用 | 注意事项 |
|---|---|---|---|
temperature |
float | 调整生成随机性 | DeepSeek 思考模式下不生效 |
max_tokens |
int | 限制输出 Token 数 | 可能导致回答被截断 |
timeout |
int / float | 控制请求超时 | 具体超时机制由集成实现决定 |
max_retries |
int | 控制失败重试次数 | 不保证所有错误都会重试 |
base_url |
str | 指定 API 地址 | 必须与所使用的 provider 协议兼容 |
top_p |
float | 控制核采样阈值 | DeepSeek 当前存在模式相关限制 |
stop |
list[str] | 设置停止序列 | 具体支持情况由模型决定 |
seed |
int | 提高部分模型的可重复性 | 并非通用参数,不保证结果完全一致 |
rate_limiter |
BaseRateLimiter | 限制客户端请求速率 | 不能替代服务端限流 |
上表中的参数类型和用途属于常见用法。具体默认值、可接受范围和行为需要查看对应模型集成的文档。
十五、常见问题
1、temperature=0 为什么两次输出仍然不同?
较低温度不等于严格确定性。
此外,某些模型模式会忽略 temperature,或者服务端存在其他影响输出的因素。
因此,不能将 temperature=0 视为绝对保证相同输出的方法。
2、设置 max_tokens 后为什么回答被截断?
因为模型的实际输出可能达到了最大 Token 限制。
可以适当提高输出上限,或者在提示词中要求更精简的回答。
如果模型提供了结束原因,可以结合 response.response_metadata 中的相关字段进一步判断。
3、为什么设置 top_p 后没有效果?
首先检查具体模型是否支持调整该参数。
对于当前 DeepSeek API:
- 非思考模式会忽略传入的 top_p。
- 思考模式只在 0.95~1.0 范围内生效。
因此,参数设置成功不代表实际采样策略发生了变化。
4、timeout=30 是否意味着整个程序最多运行 30 秒?
不一定。
请求重试、指数退避、连接处理和其他程序逻辑都可能增加总耗时。
如果必须限制整个任务的最长运行时间,应在应用层另外实现总超时机制。
5、max_retries 越大越好吗?
不是。
增加重试次数可能提高临时错误下的成功率,但也会增加等待时间、请求次数和成本。
对认证错误、非法参数等不可恢复问题,增加重试次数通常没有意义。
6、base_url 能不能填写任意模型服务地址?
不能。
必须确保该地址提供的 API 协议与使用的 LangChain 集成兼容。
例如,使用 model_provider="openai" 时,目标服务通常需要兼容对应的 OpenAI API 格式。
7、为什么不同模型的 max_tokens 行为不同?
不同服务商对于输出长度、思考 Token 和响应格式的定义可能存在差异。
LangChain 会通过相应集成映射参数,但无法保证所有模型拥有完全相同的行为。
8、能否在每次调用时使用不同参数?
可以根据模型集成的支持情况使用 bind(),或者通过 configurable_fields 创建可配置模型。
例如:
model = init_chat_model(
"deepseek:deepseek-flash"
)
short_model = model.bind(max_tokens=100)
response = short_model.invoke("介绍 Python")
如果需要根据用户或业务场景动态修改初始化参数,推荐结合配置白名单使用可配置模型。
总结
LangChain Chat Model 的常用参数可以分为以下几类:
- 生成控制:
temperature、top_p、stop。 - 输出控制:
max_tokens。 - 网络可靠性:
timeout、max_retries。 - 接口配置:
base_url。 - 速率管理:
rate_limiter。 - 可重复性:部分模型支持的
seed。
对于初学者,建议先掌握 max_tokens、timeout 和 max_retries,然后再根据具体模型的 API 支持情况调整采样参数。
尤其需要记住:LangChain 统一的是调用接口,具体参数是否生效由模型提供商和模型运行模式决定。
在实际项目中,建议从最小可运行配置开始,逐步增加参数,并记录实际响应、Token 消耗和请求耗时。
