LangChain:模型的创建与调用
介绍云端与本地模型接入、参数配置,以及同步、流式、批量和异步调用。
正文目录
模型接入是构建大模型应用的起点。本章介绍云端与本地模型的创建方式、常用调用接口,以及参数配置和排错方法。
适用版本: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=填写账号可用的模型IDimport osfrom dotenv import load_dotenvfrom 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 osfrom dotenv import load_dotenvfrom 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 osfrom dotenv import load_dotenvfrom 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 演示,实际模型选择要兼顾内存、显存、响应速度与能力。
ollama pull deepseek-r1:1.5bollama listollama run deepseek-r1:1.5bollama psfrom 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、包版本,再判断是否重试。
思考题
batch与batch_as_completed顺序有什么区别?content为什么不总是字符串?- 统一初始化入口为什么仍要安装伙伴包?