跳到正文

LangChain:模型的创建与调用

介绍云端与本地模型接入、参数配置,以及同步、流式、批量和异步调用。

12 分钟阅读

模型接入是构建大模型应用的起点。本章介绍云端与本地模型的创建方式、常用调用接口,以及参数配置和排错方法。

适用版本:LangChain 1.2.12。模型 ID、服务地址与参数支持以所用提供商和集成包版本为准。

1. 模型接入的三个维度

模型接入要分别决定:用什么初始化接口、走什么服务协议、模型部署在哪里。

维度 选择 需要理解的区别
初始化入口 专用模型类 / init_chat_model() 前者显式选择适配器,后者统一创建入口
服务接口 厂商原生接口 / OpenAI 兼容接口 URL、鉴权、字段及能力支持可能不同
部署位置 云端服务 / 本地服务 前者按服务配额使用;后者需要本机资源与模型文件

LangChain 不自带大模型权重或免费推理服务。调用通常需要 模型 ID、API Key、服务地址,并安装相应的集成包。网页聊天产品账号与 API 额度也不应直接等同。

2. 创建云端聊天模型

2.1 专用模型类

常见专用模型类包括 ChatDeepSeek、ChatZhipuAI、ChatTongyi、ChatOpenRouter 等。专用集成通常更方便处理厂商独有能力,但不同类的配置字段和环境变量可能不同。

运行前在项目的 .env 中填写可用模型和密钥,配置形式如下:

DEEPSEEK_API_KEY=填写自己的密钥
DEEPSEEK_MODEL=填写账号可用的模型ID
import os
from dotenv import load_dotenv
from langchain_deepseek import ChatDeepSeek
load_dotenv()
model = ChatDeepSeek(model=os.environ["DEEPSEEK_MODEL"])
answer = model.invoke("用一句话解释 LangChain 的作用。")
print(answer.content)

load_dotenv() 把配置加载为环境变量,集成类再读取约定的 Key。.env 应在版本控制忽略列表中;分享配置时只给占位值。

2.2 OpenAI 兼容接口

兼容调用通过 ChatOpenAI 配置目标平台的 base_url、api_key 与 model,不意味着模型来自 OpenAI。

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
model = ChatOpenAI(
model=os.environ["MODEL_ID"],
api_key=os.environ["MODEL_API_KEY"],
base_url=os.environ["MODEL_BASE_URL"],
timeout=60,
max_retries=2,
)

匹配原则: Key、URL 和模型 ID 必须属于同一服务平台。兼容聊天接口不代表同时兼容多模态、工具调用、原生结构化输出或所有推理参数。

以百炼为例,两种接入方式分别为:ChatTongyi 使用原生 SDK;ChatOpenAI 使用百炼的 OpenAI 兼容地址。不要把兼容接口的 URL 填入原生 SDK 的配置中。OpenRouter 等聚合平台也有自己的 Key、模型命名与配额;选择平台时需综合考虑模型能力、接口支持、成本与服务可用性。

2.3 init_chat_model() 统一创建入口

import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
load_dotenv()
model = init_chat_model(
model=os.environ["DEEPSEEK_MODEL"],
model_provider="deepseek",
timeout=60,
max_retries=2,
)

它按支持的 provider 创建相应适配器;不是对任意厂商、任意名称都能自动推断。名字有歧义时显式传 model_provider。统一入口仍要求提前安装伙伴包,不会自动替你安装依赖。

2.4 常用参数

参数 作用 注意点
model 服务端的模型 ID 与平台提供的名称一致
model_provider 统一入口选择适配器 不属于每个具体模型类的通用参数
api_key、base_url 鉴权与地址 默认值和别名随集成而异
temperature 调整采样随机性 低温度不保证事实正确,也不保证完全可复现
max_tokens 限制输出长度 部分服务使用其他字段,并可能计入推理 Token
timeout 请求超时 单位、覆盖范围参考具体适配器
max_retries 可重试错误的次数 多层重试叠加可能放大耗时

参数的默认值和取值范围由提供商、模型与集成包共同决定。Token 是分词器产生的单位,不能用固定的“一个 Token 等于几个汉字”精确计算费用;应看实际 usage 或对应模型分词器。

3. 本地 Ollama

流程:安装 Ollama → 下载模型 → 确认服务运行 → 用 ChatOllama 调用。下面使用 deepseek-r1:1.5b 演示,实际模型选择要兼顾内存、显存、响应速度与能力。

Terminal window
ollama pull deepseek-r1:1.5b
ollama list
ollama run deepseek-r1:1.5b
ollama ps
from langchain_ollama import ChatOllama
local_model = ChatOllama(
model="deepseek-r1:1.5b",
base_url="http://localhost:11434",
)
print(local_model.invoke("你好").content)

pull 下载,run 进入交互,serve 提供 API 服务,show 查看信息,stop 停止运行,rm 删除模型,create 根据 Modelfile 创建模型配置。Windows 可通过 OLLAMA_MODELS 指定模型存储位置,修改后重启相关服务。模型下载成功并不代表适合工具调用,要单独确认模型能力。

4. 模型调用方式

4.1 输入与输出

聊天模型一般接受字符串、消息字典列表、消息对象列表或 PromptValue。单个字符串便于一次性提问;消息列表可以表达系统规则与历史。

messages = [
{"role": "system", "content": "你是耐心的 Python 教师。"},
{"role": "user", "content": "我正在学习装饰器。"},
{"role": "assistant", "content": "我们可以先从包装函数理解。"},
{"role": "user", "content": "给我一个简单例子。"},
]
response = model.invoke(messages) # model 为前面创建的模型
print(response.content)

返回的是 AIMessage,不是裸字符串。常用字段:

字段 用途
content 文本或内容块列表,不能一概当字符串
content_blocks 标准化内容块,可按类型处理文本、多模态与推理等内容
tool_calls 模型提出的工具调用列表
invalid_tool_calls 未能正常解析的工具调用
usage_metadata 标准化 Token 用量;不保证每家都完整提供
response_metadata 服务商响应信息,如结束原因、模型名
additional_kwargs 适配器保留的扩展字段
id 消息标识,不应普遍认定为 LangSmith Run ID

只有再次传入历史,模型才能在普通无状态调用中利用前文;记忆机制在第 9 章展开。

4.2 同步、流式、批量、异步对照

方法 返回与顺序 场景
invoke() 完整 AIMessage 一次性问答
stream() 逐块产生 AIMessageChunk 实时展示
batch() 结果列表保持输入顺序 多个独立请求
batch_as_completed() 按完成顺序产生 (原始索引, 结果) 单项耗时差异较大
ainvoke() await 后得到完整消息 异步服务
astream() 异步迭代响应块 异步流式界面
abatch() await 后得到结果列表 异步批量任务
abatch_as_completed() 异步按完成顺序迭代 提前处理已完成结果
# 以下片段沿用已创建的 model,假设是纯文本模型输出。
for chunk in model.stream("解释什么是 Token"):
print(chunk.content, end="", flush=True)
results = model.batch(
["解释 Prompt", "解释 Embedding"],
config={"max_concurrency": 2},
return_exceptions=True,
)
for result in results:
if isinstance(result, Exception):
print("本项调用失败:", type(result).__name__)
else:
print(result.content)

流式块不一定恰好是一个 Token,也可能只包含元数据。批量通常是客户端并发多次调用,不等同于厂商离线 Batch API,不自动享受价格折扣。异步改善等待期间的资源利用,但连续逐个 await 不会自动并行;可用 abatch 等明确表达并发。

调用失败先分清原因:鉴权与模型 ID 错误需要修正配置,限流与暂时网络故障可退避重试。设置并发和超时;有副作用的操作还需避免重复执行。

5. 配置、扩展与排错

5.1 调试输出与模型画像

response.pretty_print() 更适合看消息;终端也可用 Rich 展示 Markdown。model.profile 是集成提供的能力元数据,可能为空;空值不等于模型没有该能力,非空也不能替代服务端实测。

通过 type(model).model_fields 可查看 Pydantic 模型暴露的配置字段。字段存在不代表目标兼容服务支持它,也不代表它是发往模型的采样参数。

5.2 model_kwargs 与 extra_body

  • model_kwargs:某些适配器用来传递未显式暴露的标准请求参数。
  • extra_body:OpenAI 风格客户端中常用于服务商扩展 JSON 字段。
  • 已有显式字段优先直接传;工具优先用 bind_tools();不要把同一参数重复放到多个位置。

推理开关等扩展参数需由目标提供商与模型明确支持,参数透传本身不会增加接口能力。

5.3 运行时 config

配置 作用
run_name、tags、metadata 给本次运行命名、分类和附加追踪信息
callbacks 运行生命周期回调
max_concurrency 支持并发执行的 Runnable 的最大并发数,不是每分钟请求配额
recursion_limit 图运行的步数保护,不能简单等同于工具调用次数
configurable 给明确支持可配置字段的组件传运行配置
configurable_model = init_chat_model(
model=os.environ["DEEPSEEK_MODEL"],
model_provider="deepseek",
configurable_fields=("temperature",),
)
result = configurable_model.invoke(
"写一句课程介绍",
config={
"run_name": "course-intro",
"tags": ["chapter02"],
"configurable": {"temperature": 0.3},
},
)

这里沿用前面的导入与 .env,并假设模型支持温度参数。直接向任意模型的 configurable 塞 temperature,不会保证覆盖成功;必须由组件声明与处理。

6. 本章要点

  • 创建时确定提供商、协议和模型;调用时决定同步、异步、批量或流式。
  • model.invoke() 返回消息;后续 agent.invoke() 通常返回状态字典,两者不要混用。
  • 看到错误先核对 Key、URL、模型 ID、包版本,再判断是否重试。

思考题

  1. batch 与 batch_as_completed 顺序有什么区别?
  2. content 为什么不总是字符串?
  3. 统一初始化入口为什么仍要安装伙伴包?

7. 参考资料

你可能还想看