LangChain - 模型(Model)
一、模型是什么?(一句话理解)
▎ 模型是智能体(代理)的推理引擎。它们驱动智能体的决策过程,决定调用哪些工具、如何解释结果以及何时提供最终答案。
接续上一讲"代理"的内容就很好理解了:如果说代理是"一个人",那模型就是这个人的"大脑"。
代理之所以能"想了再做、做完再想"地循环,背后真正在"想"的就是模型。你选的模型有多强,代理就有多靠谱。
两个关键点:
- 不同模型擅长不同的事——有的擅长跟指令、有的擅长推理、有的上下文窗口大能装更多信息。
- LangChain 给所有模型提供了统一的标准接口,所以你可以随时换厂商,而不用重写代码。
二、模型有两种用法
页面说模型可以用在两个场景里:
- 和代理配合——创建代理时把模型传进去,让代理循环用它。
- 独立使用——不套代理框架,直接拿模型来做文本生成、分类、信息提取等任务。
好消息是:同一个模型接口在两种场景下都通用,你可以先用最简单的"独立调用"上手,需要时再升级到代理工作流。
三、怎么初始化一个模型?
最简单方式是 init_chat_model,一行就能从你想要的厂商拿到模型(OpenAI / Anthropic / Azure / Google Gemini / AWS Bedrock /HuggingFace / OpenRouter),套路都一样:
import os
from langchain.chat_models import init_chat_model
os.environ["OPENAI_API_KEY"] = "sk-..."
# 直接传模型名,init_chat_model 会自动识别厂商
model = init_chat_model("gpt-5.4")
换成别的厂商,基本上就是换模型名 + 换对应的 API Key 环境变量,例如:
# Anthropic
os.environ["ANTHROPIC_API_KEY"] = "sk-..."
model = init_chat_model("claude-sonnet-4-6")
# Google Gemini
os.environ["GOOGLE_API_KEY"] = "..."
model = init_chat_model("google_genai:gemini-2.5-flash-lite")
新模型名字可以立刻用,不需要等 LangChain 更新——因为厂商集成包会把模型名直接透传给厂商 API。
四、几个常用参数
模型可以传参数来调"脾气",页面列了几个标准参数:
| 参数 | 作用 | 大白话 |
|---|---|---|
| model | 指定用哪个模型(必填),也可用 厂商:模型 格式 | 用哪个"大脑" |
| api_key | 认证密钥,一般放环境变量 | 你的门禁卡 |
| temperature | 控制随机性,越高越有创意、越低越确定 | “稳"还是"野” |
| max_tokens | 限制输出的 token 数 | 最多说多少话 |
| timeout | 等响应的最长秒数 | 等多久算超时 |
| max_retries | 失败后最多重试几次(默认 6) | 网不好时多重试几次 |
实用建议:在不可靠网络上跑耗时的代理任务时,可以把 max_retries 调到 10–15。重试机制对网络错误、限流(429)、服务器错误(5xx)会自动重试,但 401/404这种客户端错误不会重试。
model = init_chat_model(
"claude-sonnet-4-6",
temperature=0.7,
timeout=30,
max_tokens=1000,
max_retries=6,
)
五、怎么调用模型?—— 三种主要方法
页面说有三种调用方式,对应不同场景。
1. invoke():最直接的调用(等全部生成完再返回)
可以传一个字符串,也可以传一段对话(消息列表):
# 单条
response = model.invoke("Why do parrots have colorful feathers?")
print(response)
传对话历史时,每条消息要带角色(system / user / assistant),可以用字典,也可以用消息对象类:
from langchain.messages import HumanMessage, AIMessage, SystemMessage
conversation = [
SystemMessage("You are a helpful assistant that translates English to French."),
HumanMessage("Translate: I love programming."),
AIMessage("J'adore la programmation."),
HumanMessage("Translate: I love building applications.")
]
response = model.invoke(conversation)
print(response) # AIMessage("J'adore créer des applications.")
▎ 页面有个提醒:如果你的调用返回的是字符串而不是消息对象,说明你用的是老的"文本补全 LLM"而不是"聊天模型"。LangChain 的聊天模型类名都以 Chat 开头(如 ChatOpenAI)。
2. stream():流式输出(一边生成一边吐字)
invoke 要等模型把整段话说完才返回;stream 则会一块一块地返回,适合做"打字机效果",体验更好:
for chunk in model.stream("Why do parrots have colorful feathers?"):
print(chunk.text, end="|", flush=True)
说明:stream() 返回的是一个个 AIMessageChunk,这些块可以相加拼成完整消息:
full = None
for chunk in model.stream("What color is the sky?"):
full = chunk if full is None else full + chunk
print(full.text)
# The
# The sky
# The sky is
# The sky is typically
# The sky is typically blue
还有个进阶用法 astream_events()(异步、按"事件"流式),能按事件类型过滤,比如分别处理"开始"“每个 token”“结束”:
async for event in model.astream_events("Hello"):
if event["event"] == "on_chat_model_stream":
print(f"Token: {event['data']['chunk'].text}")
elif event["event"] == "on_chat_model_end":
print(f"Full message: {event['data']['output'].text}")
聊天模型"自动流式传输":当你在代理/应用层面开了流式,哪怕节点里写的是 model.invoke(),LangChain也会自动在内部切成流式,保证实时输出。
3. batch():批量处理(并行发多个请求)
把一堆独立请求一次性发出去并行处理,更快更省:
responses = model.batch([
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?"
])
for response in responses:
print(response)
想控制最大并发数,用 RunnableConfig 里的 max_concurrency:
model.batch(
list_of_inputs,
config={"max_concurrency": 5} # 最多 5 个并行
)
页面还有个 batch_as_completed(),谁先完成谁先返回(结果可能乱序,但每个结果带输入索引,方便你还原顺序)。
▎ 页面特别澄清:这个 batch() 是客户端并行,跟 OpenAI/Anthropic 那种"批量 API"不是一回事。
六、让模型"会用工具":工具调用(Tool Calling)
这是承上启下的一节——模型有了工具调用能力,才有可能成为代理。页面说得很清楚:
▎ 模型可以请求调用执行任务的工具……您可能会听到"函数调用"这个词,我们将其与"工具调用"交替使用。
工具由两部分组成:一个 schema(名称、描述、参数定义)+ 一个要执行的函数。
关键一步:工具必须先用 bind_tools 绑定到模型上,模型才知道有哪些工具可用:
from langchain.tools import tool
@tool
def get_weather(location: str) -> str:
"""Get the weather at a location."""
return f"It's sunny in {location}."
model_with_tools = model.bind_tools([get_weather])
response = model_with_tools.invoke("What's the weather like in Boston?")
for tool_call in response.tool_calls:
print(f"Tool: {tool_call['name']}")
print(f"Args: {tool_call['args']}")
重要区别(页面反复强调,也是理解上一讲"代理"的关键):
▎ 当独立使用模型时,模型只是"提出"要调某个工具,真正去执行的是你;当使用代理时,代理循环会替你把"调工具 → 拿结果 → 喂回去"这一整套自动做完。
以下是"手动工具执行循环"的例子,正好让你看清代理在背后干了什么:
model_with_tools = model.bind_tools([get_weather])
# 第1步:模型生成工具调用请求
messages = [{"role": "user", "content": "What's the weather in Boston?"}]
ai_msg = model_with_tools.invoke(messages)
messages.append(ai_msg)
# 第2步:执行工具,收集结果
for tool_call in ai_msg.tool_calls:
tool_result = get_weather.invoke(tool_call)
messages.append(tool_result)
# 第3步:把结果传回模型,生成最终回答
final_response = model_with_tools.invoke(messages)
print(final_response.text)
# "The current weather in Boston is 72°F and sunny."
页面还提到几个工具调用的高级点:
- tool_call_id:每个工具返回的 ToolMessage 都带这个 ID,帮模型把"结果"和"请求"对上号。
- 强制工具调用:用 tool_choice=“any”(必须调任意一个工具)或指定具体工具。
- 并行工具调用:模型可以一次同时调多个工具(如同时问 Boston 和 Tokyo 的天气);OpenAI/Anthropic 等可用 parallel_tool_calls=False 关掉。
- 流式工具调用:流式时工具调用通过 ToolCallChunk 渐进式构建,能边生成边看到工具名和参数。
七、让输出格式固定:结构化输出
跟上一讲代理里讲的一样,模型也能直接产出结构化结果。页面说可以用 Pydantic、TypedDict、JSON Schema 等多种方式,Pydantic 功能最全(支持字段验证、描述、嵌套):
from pydantic import BaseModel, Field
class Movie(BaseModel):
"""A movie with details."""
title: str = Field(description="The title of the movie")
year: int = Field(description="The year the movie was released")
director: str = Field(description="The director of the movie")
rating: float = ...
这块页面主要说"支持多种模式类型",具体策略(ToolStrategy / ProviderStrategy)在上一讲的"代理"里已经细讲过,这里就不重复了。
一句话总结 + 和"代理"的关系
▎ 模型 = 代理的大脑/推理引擎。 你用 init_chat_model(“模型名”) 拿到一个模型,再通过 invoke / stream / batch 三种方式调用它。给模型 bind_tools([…]) 后,它就具备了"想用工具"的能力;当你不想自己手动写"调工具→喂结果"的循环时,就把模型交给代理(create_agent)去自动跑这个循环。
换句话说,上一讲和这一讲连起来就是:
- 模型 = 会思考、能用工具的大脑(单步)
- 代理 = 给这个大脑套上一个"思考→行动→观察→再思考"的自动循环(多步)
更多推荐


所有评论(0)