外观
LLM 是强大的 AI 工具,可以像人类一样解释和生成文本。它们用途广泛,能够撰写内容、翻译语言、总结概括和回答问题,而无需针对每项任务进行专门训练。
除了文本生成,许多模型还支持:
- 工具调用 —— 调用外部工具(如数据库查询或 API 调用),并在响应中使用其结果。
- 结构化输出 —— 模型的响应被约束为遵循定义的格式。
- 多模态 —— 处理并返回文本以外的数据,例如图像、音频与视频。
- 推理 —— 模型执行多步推理以得出结论。
模型是智能体的推理引擎。它们驱动智能体的决策过程,决定调用哪些工具、如何解释结果,以及何时给出最终答案。
你选择的模型的质量与能力直接影响智能体的基础可靠性与性能。不同模型擅长不同任务——有些更擅长遵循复杂指令,有些擅长结构化推理,还有一些支持更大的上下文窗口以处理更多信息。
LangChain 的标准模型接口让你可以访问许多不同的提供商集成,这使得你可以轻松地试验并在模型之间切换,为你的用例找到最合适的选择。
提供商专属的集成信息与能力参见提供商的对话模型页面。
TIP
LangSmith 会追踪每次模型调用,因此你可以比较提供商、检查工具路由并调试失败。按照追踪快速入门完成设置。
我们还建议你设置 LangSmith Engine,它会监控你的追踪、检测问题并提出修复建议。
基本用法
模型可以以两种方式使用:
- 与智能体配合 —— 可以在创建智能体时动态指定模型。
- 独立使用 —— 可以直接调用模型(在智能体循环之外),用于文本生成、分类或提取等任务,无需智能体框架。
相同的模型接口在两种上下文中都适用,这让你可以灵活地从简单开始,并在需要时扩展到更复杂的基于智能体的工作流。
初始化模型
在 LangChain 中使用独立模型开始的最简单方式,是使用 init_chat_model 从你选择的对话模型提供商初始化一个模型(示例如下):
OpenAI
👉 Read the [OpenAI chat model integration docs](/oss/python/integrations/chat/openai)
bash
pip install -U "langchain[openai]"python
import os
from langchain.chat_models import init_chat_model
os.environ["OPENAI_API_KEY"] = "sk-..."
model = init_chat_model("gpt-5.5")python
import os
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "sk-..."
model = ChatOpenAI(model="gpt-5.5")Anthropic
👉 Read the [Anthropic chat model integration docs](/oss/python/integrations/chat/anthropic)
bash
pip install -U "langchain[anthropic]"python
import os
from langchain.chat_models import init_chat_model
os.environ["ANTHROPIC_API_KEY"] = "sk-..."
model = init_chat_model("claude-sonnet-4-6")python
import os
from langchain_anthropic import ChatAnthropic
os.environ["ANTHROPIC_API_KEY"] = "sk-..."
model = ChatAnthropic(model="claude-sonnet-4-6")Azure
👉 Read the [Azure chat model integration docs](/oss/python/integrations/chat/azure_chat_openai)
bash
pip install -U "langchain[openai]"python
import os
from langchain.chat_models import init_chat_model
os.environ["AZURE_OPENAI_API_KEY"] = "..."
os.environ["AZURE_OPENAI_ENDPOINT"] = "..."
os.environ["OPENAI_API_VERSION"] = "2025-03-01-preview"
model = init_chat_model(
"azure_openai:gpt-5.5",
azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
)python
import os
from langchain_openai import AzureChatOpenAI
os.environ["AZURE_OPENAI_API_KEY"] = "..."
os.environ["AZURE_OPENAI_ENDPOINT"] = "..."
os.environ["OPENAI_API_VERSION"] = "2025-03-01-preview"
model = AzureChatOpenAI(
model="gpt-5.5",
azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"]
)Google Gemini
👉 Read the [Google GenAI chat model integration docs](/oss/python/integrations/chat/google_generative_ai)
bash
pip install -U "langchain[google-genai]"python
import os
from langchain.chat_models import init_chat_model
os.environ["GOOGLE_API_KEY"] = "..."
model = init_chat_model("google_genai:gemini-2.5-flash-lite")python
import os
from langchain_google_genai import ChatGoogleGenerativeAI
os.environ["GOOGLE_API_KEY"] = "..."
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")AWS Bedrock
👉 Read the [AWS Bedrock chat model integration docs](/oss/python/integrations/chat/bedrock)
bash
pip install -U "langchain[aws]"python
from langchain.chat_models import init_chat_model
# Follow the steps here to configure your credentials:
# https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html
model = init_chat_model(
"us.anthropic.claude-sonnet-4-6",
model_provider="bedrock_converse",
)python
from langchain_aws import ChatBedrock
model = ChatBedrock(model="us.anthropic.claude-sonnet-4-6")HuggingFace
👉 Read the [HuggingFace chat model integration docs](/oss/python/integrations/chat/huggingface)
bash
pip install -U "langchain[huggingface]"python
import os
from langchain.chat_models import init_chat_model
os.environ["HUGGINGFACEHUB_API_TOKEN"] = "hf_..."
model = init_chat_model(
"microsoft/Phi-3-mini-4k-instruct",
model_provider="huggingface",
temperature=0.7,
max_tokens=1024,
)python
import os
from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
os.environ["HUGGINGFACEHUB_API_TOKEN"] = "hf_..."
llm = HuggingFaceEndpoint(
repo_id="microsoft/Phi-3-mini-4k-instruct",
temperature=0.7,
max_length=1024,
)
model = ChatHuggingFace(llm=llm)OpenRouter
👉 Read the [OpenRouter chat model integration docs](/oss/python/integrations/chat/openrouter)
bash
pip install -U "langchain-openrouter"python
import os
from langchain.chat_models import init_chat_model
os.environ["OPENROUTER_API_KEY"] = "sk-..."
model = init_chat_model(
"auto",
model_provider="openrouter",
)python
import os
from langchain_openrouter import ChatOpenRouter
os.environ["OPENROUTER_API_KEY"] = "sk-..."
model = ChatOpenRouter(model="auto")python
response = model.invoke("Why do parrots talk?")更多细节(包括如何传递模型参数)参见 init_chat_model。 在 LangChain 中使用独立模型开始的最简单方式,是使用 initChatModel 从你选择的对话模型提供商初始化一个模型(示例如下):
OpenAI
👉 Read the [OpenAI chat model integration docs](/oss/javascript/integrations/chat/openai)
bash
npm install @langchain/openaibash
pnpm install @langchain/openaibash
yarn add @langchain/openaibash
bun add @langchain/openaitypescript
import { initChatModel } from "langchain";
process.env.OPENAI_API_KEY = "your-api-key";
const model = await initChatModel("gpt-5.5");typescript
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-5.5",
apiKey: "your-api-key"
});Anthropic
👉 Read the [Anthropic chat model integration docs](/oss/javascript/integrations/chat/anthropic)
bash
npm install @langchain/anthropicbash
pnpm install @langchain/anthropicbash
yarn add @langchain/anthropicbash
pnpm add @langchain/anthropictypescript
import { initChatModel } from "langchain";
process.env.ANTHROPIC_API_KEY = "your-api-key";
const model = await initChatModel("claude-sonnet-4-6");typescript
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
model: "claude-sonnet-4-6",
apiKey: "your-api-key"
});Azure
👉 Read the [Azure chat model integration docs](/oss/javascript/integrations/chat/azure)
bash
npm install @langchain/azurebash
pnpm install @langchain/azurebash
yarn add @langchain/azurebash
bun add @langchain/azuretypescript
import { initChatModel } from "langchain";
process.env.AZURE_OPENAI_API_KEY = "your-api-key";
process.env.AZURE_OPENAI_ENDPOINT = "your-endpoint";
process.env.OPENAI_API_VERSION = "your-api-version";
const model = await initChatModel("azure_openai:gpt-5.5");typescript
import { AzureChatOpenAI } from "@langchain/openai";
const model = new AzureChatOpenAI({
model: "gpt-5.5",
azureOpenAIApiKey: "your-api-key",
azureOpenAIApiEndpoint: "your-endpoint",
azureOpenAIApiVersion: "your-api-version"
});Google Gemini
👉 Read the [Google GenAI chat model integration docs](/oss/javascript/integrations/chat/google_generative_ai)
bash
npm install @langchain/google-genaibash
pnpm install @langchain/google-genaibash
yarn add @langchain/google-genaibash
bun add @langchain/google-genaitypescript
import { initChatModel } from "langchain";
process.env.GOOGLE_API_KEY = "your-api-key";
const model = await initChatModel("google-genai:gemini-2.5-flash-lite");typescript
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
const model = new ChatGoogleGenerativeAI({
model: "gemini-2.5-flash-lite",
apiKey: "your-api-key"
});Bedrock Converse
👉 Read the [AWS Bedrock chat model integration docs](/oss/javascript/integrations/chat/bedrock_converse)
bash
npm install @langchain/awsbash
pnpm install @langchain/awsbash
yarn add @langchain/awsbash
bun add @langchain/awstypescript
import { initChatModel } from "langchain";
// Follow the steps here to configure your credentials:
// https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html
const model = await initChatModel("bedrock:gpt-5.5");typescript
import { ChatBedrockConverse } from "@langchain/aws";
// Follow the steps here to configure your credentials:
// https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html
const model = new ChatBedrockConverse({
model: "gpt-5.5",
region: "us-east-2"
});typescript
const response = await model.invoke("Why do parrots talk?");更多细节(包括如何传递模型参数)参见 initChatModel。
受支持的提供商与模型
LangChain 通过专用的集成包支持所有主要的模型提供商。每个提供商包都实现相同的标准接口,因此你可以在不重写应用逻辑的情况下切换提供商。新的模型名称立即可用——无需 LangChain 更新——因为提供商包会把模型名称直接传递给提供商的 API。
浏览受支持提供商的完整列表,或查看提供商与模型以了解提供商、包与模型名称在 LangChain 中如何协同工作的概念概述。
关键方法
- 调用(Invoke) — 模型以消息作为输入,并在生成完整响应后输出消息。
- 流式输出(Stream) — 调用模型,但在输出实时生成时对其进行流式输出。
- 批处理(Batch) — 以批处理方式向模型发送多个请求,以实现更高效的处理。
INFO
除对话模型外,LangChain 还支持嵌入模型与向量数据库等其他相关技术。详情参见集成页面。
参数
对话模型接受可用于配置其行为的参数。受支持参数的完整集合因模型与提供商而异,但标准参数包括:
model (string)(必填):要使用的特定模型的名称或标识符。你也可以使用 '{model_provider}:{model}' 格式在单个参数中同时指定模型及其提供商,例如 'openai:o1'。
api_key (string):用于向模型提供商进行身份验证所需的密钥。通常在你注册模型访问权限时发放。通常通过设置环境变量来访问。
apiKey (string):用于向模型提供商进行身份验证所需的密钥。通常在你注册模型访问权限时发放。通常通过设置环境变量来访问。
temperature (number):控制模型输出的随机性。数值越高响应越有创意;越低则越确定性。
max_tokens (number):限制响应中token的总数,实际上控制输出可以有多长。
maxTokens (number):限制响应中token的总数,实际上控制输出可以有多长。
timeout (number):在取消请求之前等待模型响应的最长时间(秒)。
max_retries (number)(默认:
6):当请求因网络超时或速率限制等问题失败时,系统重新发送请求的最大尝试次数。重试使用带抖动的指数退避。网络错误、速率限制(429)与服务器错误(5xx)会自动重试。401(未授权)或 404 等客户端错误不会重试。对于在不可靠网络上运行的长时间智能体任务,请考虑增加到 10–15。maxRetries (number)(默认:
6):当请求因网络超时或速率限制等问题失败时,系统重新发送请求的最大尝试次数。重试使用带抖动的指数退避。网络错误、速率限制(429)与服务器错误(5xx)会自动重试。401(未授权)或 404 等客户端错误不会重试。对于在不可靠网络上运行的长时间智能体任务,请考虑增加到 10–15。
使用 init_chat_model,把这些参数作为内联的**kwargs传递:
python
model = init_chat_model(
"claude-sonnet-4-6",
# 传递给模型的 kwargs:
temperature=0.7,
timeout=30,
max_tokens=1000,
max_retries=6, # 默认值;网络不可靠时加大
)使用 initChatModel,把这些参数作为内联参数传递:
typescript
const model = await initChatModel(
"claude-sonnet-4-6",
{ temperature: 0.7, timeout: 30, maxTokens: 1000, maxRetries: 6 }
)连接弹性
LangChain 对话模型会自动以指数退避重试失败的 API 请求。默认情况下,模型对网络错误、速率限制(429)与服务器错误(5xx)最多重试 6 次。401(未授权)或 404 等客户端错误不会重试。
你可以在创建模型时调整 max_retries 与 timeout,然后把该实例传给 create_agent、create_deep_agent,或独立调用它:
python
from langchain.chat_models import init_chat_model
model = init_chat_model(
"google_genai:gemini-3.6-flash",
max_retries=10, # 网络不可靠时加大(默认:6)
timeout=120, # 单位:秒;连接慢时加大
)你可以在创建模型时调整 maxRetries 与 timeout,然后把该实例传给 createAgent、createDeepAgent,或独立调用它:
typescript
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
model: "google_genai:gemini-3.6-flash",
maxRetries: 10, // 网络不可靠时加大(默认:6)
timeout: 120_000, // 单位:毫秒;连接慢时加大
});TIP
对于在不可靠网络上运行的长时间智能体图,请考虑提高 max_retries(例如 10–15)并配合检查点器,以便在失败时保留进度。
INFO
每个对话模型集成可能都有用于控制提供商专属功能的额外参数。
例如,ChatOpenAI 有 use_responses_api,用于决定是使用 OpenAI Responses API 还是 Completions API。
要查找某个对话模型支持的所有参数,请前往对话模型集成页面。
调用
必须调用对话模型才能生成输出。有三种主要的调用方法,各自适用于不同的用例。
调用(Invoke)
调用模型最直接的方式是使用 invoke() 并传入单条消息或消息列表。
python
response = model.invoke("Why do parrots have colorful feathers?")
print(response)typescript
const response = await model.invoke("Why do parrots have colorful feathers?");
console.log(response);可以向对话模型提供消息列表来表示对话历史。每条消息都有一个角色(role),模型用它来表明对话中是谁发送的消息。
角色、类型与内容的更多细节参见消息指南。
python
conversation = [
{"role": "system", "content": "You are a helpful assistant that translates English to French."},
{"role": "user", "content": "Translate: I love programming."},
{"role": "assistant", "content": "J'adore la programmation."},
{"role": "user", "content": "Translate: I love building applications."}
]
response = model.invoke(conversation)
print(response) # AIMessage("J'adore créer des applications.")python
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.")typescript
const conversation = [
{ role: "system", content: "You are a helpful assistant that translates English to French." },
{ role: "user", content: "Translate: I love programming." },
{ role: "assistant", content: "J'adore la programmation." },
{ role: "user", content: "Translate: I love building applications." },
];
const response = await model.invoke(conversation);
console.log(response); // AIMessage("J'adore créer des applications.")typescript
import { HumanMessage, AIMessage, SystemMessage } from "langchain";
const conversation = [
new SystemMessage("You are a helpful assistant that translates English to French."),
new HumanMessage("Translate: I love programming."),
new AIMessage("J'adore la programmation."),
new HumanMessage("Translate: I love building applications."),
];
const response = await model.invoke(conversation);
console.log(response); // AIMessage("J'adore créer des applications.")INFO
如果你调用的返回类型是字符串,请确保你使用的是对话模型而不是 LLM。传统的文本补全 LLM 直接返回字符串。LangChain 对话模型以 "Chat" 为前缀,例如 ChatOpenAI(/oss/integrations/chat/openai)。
流式输出(Stream)
大多数模型可以在生成输出内容的同时对其进行流式输出。通过渐进式地显示输出,流式输出显著改善了用户体验,尤其是对于较长的响应。
调用 stream() 会返回一个迭代器,它会在输出块产生时逐个产出。你可以使用循环实时处理每个块:
python
for chunk in model.stream("Why do parrots have colorful feathers?"):
print(chunk.text, end="|", flush=True)python
for chunk in model.stream("What color is the sky?"):
for block in chunk.content_blocks:
if block["type"] == "reasoning" and (reasoning := block.get("reasoning")):
print(f"Reasoning: {reasoning}")
elif block["type"] == "tool_call_chunk":
print(f"Tool call chunk: {block}")
elif block["type"] == "text":
print(block["text"])
else:
...typescript
const stream = await model.stream("Why do parrots have colorful feathers?");
for await (const chunk of stream) {
console.log(chunk.text)
}typescript
const stream = await model.stream("What color is the sky?");
for await (const chunk of stream) {
for (const block of chunk.contentBlocks) {
if (block.type === "reasoning") {
console.log(`Reasoning: ${block.reasoning}`);
} else if (block.type === "tool_call_chunk") {
console.log(`Tool call chunk: ${block}`);
} else if (block.type === "text") {
console.log(block.text);
} else {
...
}
}
}与 invoke()(在模型生成完整响应后返回单个 AIMessage)相反,stream() 返回多个 AIMessageChunk 对象,每个对象包含输出文本的一部分。重要的是,流中的每个块都被设计为可以通过求和汇总成一条完整消息:
python
full = None # None | AIMessageChunk
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
# ...
print(full.content_blocks)
# [{"type": "text", "text": "The sky is typically blue..."}]typescript
let full: AIMessageChunk | null = null;
for await (const chunk of stream) {
full = full ? full.concat(chunk) : chunk;
console.log(full.text);
}
// The
// The sky
// The sky is
// The sky is typically
// The sky is typically blue
// ...
console.log(full.contentBlocks);
// [{"type": "text", "text": "The sky is typically blue..."}]生成的消息可以像使用 invoke() 生成的消息一样处理——例如,它可以被聚合到消息历史中,并作为对话上下文传回给模型。
WARNING
流式输出只有在程序中的所有步骤都知道如何处理块流时才有效。例如,一个不支持流式的应用就是那种需要先把整个输出存到内存中才能处理的应用。
高级流式输出主题
流式事件
LangChain 对话模型还可以使用 astream_events() 流式输出语义事件。
这简化了基于事件类型和其他元数据的过滤,并会在后台聚合完整消息。示例如下。
python
async for event in model.astream_events("Hello"):
if event["event"] == "on_chat_model_start":
print(f"Input: {event['data']['input']}")
elif 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}")
else:
passtxt
Input: Hello
Token: Hi
Token: there
Token: !
Token: How
Token: can
Token: I
...
Full message: Hi there! How can I help today?TIP
事件类型与其他细节参见 astream_events() 参考。
LangChain 对话模型还可以使用 [streamEvents()][BaseChatModel.streamEvents] 流式输出语义事件。
这简化了基于事件类型和其他元数据的过滤,并会在后台聚合完整消息。示例如下。
typescript
const stream = await model.streamEvents("Hello");
for await (const event of stream) {
if (event.event === "on_chat_model_start") {
console.log(`Input: ${event.data.input}`);
}
if (event.event === "on_chat_model_stream") {
console.log(`Token: ${event.data.chunk.text}`);
}
if (event.event === "on_chat_model_end") {
console.log(`Full message: ${event.data.output.text}`);
}
}txt
Input: Hello
Token: Hi
Token: there
Token: !
Token: How
Token: can
Token: I
...
Full message: Hi there! How can I help today?事件类型与其他细节参见 streamEvents() 参考。 LangChain 通过在某些情况下自动启用流式模式来简化对话模型的流式输出,即使你没有显式调用流式方法。当你使用非流式的 invoke 方法但仍想流式输出整个应用(包括对话模型的中间结果)时,这尤其有用。
例如,在 [LangGraph 智能体](/oss/langchain/agents)中,你可以在节点内调用 `model.invoke()`,但如果以流式模式运行,LangChain 会自动改用流式输出。
#### 它如何工作
当你 `invoke()` 一个对话模型时,如果 LangChain 检测到你正在尝试流式输出整个应用,它会自动切换到内部流式模式。对于使用 invoke 的代码而言,调用结果是一样的;但是在对话模型被流式输出的同时,LangChain 会在其回调系统中触发 `on_llm_new_token` 事件。
回调事件让 LangGraph 的 stream() 与 astream_events() 能够实时呈现对话模型的输出。 回调事件让 LangGraph 的 stream() 与 streamEvents() 能够实时呈现对话模型的输出。
批处理(Batch)
把一组独立的请求批处理发送给模型可以显著提升性能并降低成本,因为处理可以并行进行:
python
responses = model.batch([
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?"
])
for response in responses:
print(response)默认情况下,batch() 只返回整个批处理的最终输出。如果你希望在每个单独输入完成生成时立即收到其输出,可以使用 batch_as_completed() 流式获取结果:
python
for response in model.batch_as_completed([
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?"
]):
print(response)INFO
使用 batch_as_completed() 时,结果可能乱序到达。每个结果都包含输入索引,以便在需要时匹配并重建原始顺序。
TIP
使用 batch() 或 batch_as_completed() 处理大量输入时,你可能希望控制最大并行调用数。这可以通过在 RunnableConfig 字典中设置 max_concurrency 属性来实现。
python
model.batch(
list_of_inputs,
config={
'max_concurrency': 5, # 限制为 5 个并行调用
}
)受支持属性的完整列表参见 RunnableConfig 参考。
批处理的更多细节参见 reference。
typescript
const responses = await model.batch([
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?",
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?",
]);
for (const response of responses) {
console.log(response);
}TIP
使用 batch() 处理大量输入时,你可能希望控制最大并行调用数。这可以通过在 RunnableConfig 字典中设置 maxConcurrency 属性来实现。
typescript
model.batch(
listOfInputs,
{
maxConcurrency: 5, // 限制为 5 个并行调用
}
)受支持属性的完整列表参见 RunnableConfig 参考。
批处理的更多细节参见 reference。
工具调用
模型可以请求调用工具来执行诸如从数据库获取数据、搜索网络或运行代码等任务。工具是以下两者的配对:
- 一个 schema,包含工具的名称、描述和/或参数定义(通常是一个 JSON schema)
- 一个函数或协程用于执行。
INFO
你可能会听到"函数调用"(function calling)这个术语。我们把它与"工具调用"(tool calling)互换使用。
以下是用户与模型之间的基本工具调用流程:
要让你定义的工具可供模型使用,你必须使用 bind_tools 绑定它们。在随后的调用中,模型可以根据需要选择调用任何已绑定的工具。
要让你定义的工具可供模型使用,你必须使用 bindTools 绑定它们。在随后的调用中,模型可以根据需要选择调用任何已绑定的工具。
某些模型提供商提供内置工具,可以通过模型或调用参数启用(例如 ChatOpenAI、ChatAnthropic)。细节请查阅相应的提供商参考。
TIP
创建工具的细节与其他选项参见工具指南。
python
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']}")typescript
import { tool } from "langchain";
import * as z from "zod";
import { ChatOpenAI } from "@langchain/openai";
const getWeather = tool(
(input) => `It's sunny in ${input.location}.`,
{
name: "get_weather",
description: "Get the weather at a location.",
schema: z.object({
location: z.string().describe("The location to get the weather for"),
}),
},
);
const model = new ChatOpenAI({ model: "gpt-5.5" });
const modelWithTools = model.bindTools([getWeather]);
const response = await modelWithTools.invoke("What's the weather like in Boston?");
const toolCalls = response.tool_calls || [];
for (const tool_call of toolCalls) {
// 查看模型发起的工具调用
console.log(`Tool: ${tool_call.name}`);
console.log(`Args: ${tool_call.args}`);
}绑定用户定义的工具时,模型的响应包含一个请求来执行工具。当独立于智能体使用模型时,你需要自行执行被请求的工具,并把结果返回给模型供后续推理使用。当使用智能体时,智能体循环会替你处理工具执行循环。
下面我们展示一些使用工具调用的常见方式。
工具执行循环
当模型返回工具调用时,你需要执行这些工具并把结果传回模型。这会创建一个对话循环,让模型可以使用工具结果生成最终响应。LangChain 包含处理这种编排的[智能体](/oss/langchain/agents)抽象。
下面是一个简单的示例:
python
# 将(可能是多个的)工具绑定到模型
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."typescript
// 将(可能是多个的)工具绑定到模型
const modelWithTools = model.bindTools([get_weather])
// 步骤 1:模型生成工具调用
const messages = [{"role": "user", "content": "What's the weather in Boston?"}]
const ai_msg = await modelWithTools.invoke(messages)
messages.push(ai_msg)
// 步骤 2:执行工具并收集结果
for (const tool_call of ai_msg.tool_calls) {
// 使用生成的参数执行工具
const tool_result = await get_weather.invoke(tool_call)
messages.push(tool_result)
}
// 步骤 3:将结果传回模型以生成最终响应
const final_response = await modelWithTools.invoke(messages)
console.log(final_response.text)
// "The current weather in Boston is 72°F and sunny." 工具返回的每个 `ToolMessage` 都包含一个与原始工具调用匹配的 `tool_call_id`,帮助模型把结果与请求关联起来。
强制工具调用
默认情况下,模型可以自由选择根据用户输入使用哪个已绑定的工具。但是,你可能希望强制选择一个工具,确保模型使用特定工具或给定列表中的**任意**工具:
python
model_with_tools = model.bind_tools([tool_1], tool_choice="any")python
model_with_tools = model.bind_tools([tool_1], tool_choice="tool_1")typescript
const modelWithTools = model.bindTools([tool_1], { toolChoice: "any" })typescript
const modelWithTools = model.bindTools([tool_1], { toolChoice: "tool_1" })并行工具调用
许多模型支持在适当时并行调用多个工具。这让模型可以同时从不同来源收集信息。
python
model_with_tools = model.bind_tools([get_weather])
response = model_with_tools.invoke(
"What's the weather in Boston and Tokyo?"
)
# 模型可能会生成多个工具调用
print(response.tool_calls)
# [
# {'name': 'get_weather', 'args': {'location': 'Boston'}, 'id': 'call_1'},
# {'name': 'get_weather', 'args': {'location': 'Tokyo'}, 'id': 'call_2'},
# ]
# 执行所有工具(可以使用 async 并行执行)
results = []
for tool_call in response.tool_calls:
if tool_call['name'] == 'get_weather':
result = get_weather.invoke(tool_call)
...
results.append(result)typescript
const modelWithTools = model.bind_tools([get_weather])
const response = await modelWithTools.invoke(
"What's the weather in Boston and Tokyo?"
)
// 模型可能会生成多个工具调用
console.log(response.tool_calls)
// [
// { name: 'get_weather', args: { location: 'Boston' }, id: 'call_1' },
// { name: 'get_time', args: { location: 'Tokyo' }, id: 'call_2' }
// ]
// 执行所有工具(可以使用 async 并行执行)
const results = []
for (const tool_call of response.tool_calls || []) {
if (tool_call.name === 'get_weather') {
const result = await get_weather.invoke(tool_call)
results.push(result)
}
} 模型会根据所请求操作的独立性智能地判断何时适合并行执行。
TIP
大多数支持工具调用的模型默认启用并行工具调用。有些(包括 OpenAI 与 Anthropic)允许你禁用此功能。为此,设置 parallel_tool_calls=False:
python
model.bind_tools([get_weather], parallel_tool_calls=False)流式工具调用
流式输出响应时,工具调用会通过 `ToolCallChunk` 逐步构建。这让你可以在工具调用生成的同时看到它们,而不是等待完整响应。
python
for chunk in model_with_tools.stream(
"What's the weather in Boston and Tokyo?"
):
# 工具调用块会逐步到达
for tool_chunk in chunk.tool_call_chunks:
if name := tool_chunk.get("name"):
print(f"Tool: {name}")
if id_ := tool_chunk.get("id"):
print(f"ID: {id_}")
if args := tool_chunk.get("args"):
print(f"Args: {args}")
# 输出:
# Tool: get_weather
# ID: call_SvMlU1TVIZugrFLckFE2ceRE
# Args: {"lo
# Args: catio
# Args: n": "B
# Args: osto
# Args: n"}
# Tool: get_weather
# ID: call_QMZdy6qInx13oWKE7KhuhOLR
# Args: {"lo
# Args: catio
# Args: n": "T
# Args: okyo
# Args: "}你可以累积块来构建完整的工具调用:
python
gathered = None
for chunk in model_with_tools.stream("What's the weather in Boston?"):
gathered = chunk if gathered is None else gathered + chunk
print(gathered.tool_calls)typescript
const stream = await modelWithTools.stream(
"What's the weather in Boston and Tokyo?"
)
for await (const chunk of stream) {
// 工具调用块会逐步到达
if (chunk.tool_call_chunks) {
for (const tool_chunk of chunk.tool_call_chunks) {
console.log(`Tool: ${tool_chunk.get('name', '')}`)
console.log(`Args: ${tool_chunk.get('args', '')}`)
}
}
}
// 输出:
// Tool: get_weather
// Args:
// Tool:
// Args: {"loc
// Tool:
// Args: ation": "BOS"}
// Tool: get_time
// Args:
// Tool:
// Args: {"timezone": "Tokyo"}你可以累积块来构建完整的工具调用:
typescript
let full: AIMessageChunk | null = null
const stream = await modelWithTools.stream("What's the weather in Boston?")
for await (const chunk of stream) {
full = full ? full.concat(chunk) : chunk
console.log(full.contentBlocks)
}结构化输出
可以要求模型提供与给定 schema 匹配格式的响应。这对于确保输出可以轻松解析并用于后续处理很有用。LangChain 支持多种 schema 类型与强制结构化输出的方法。
TIP
要了解结构化输出,参见结构化输出。
Pydantic
[Pydantic 模型](https://docs.pydantic.dev/latest/concepts/models/#basic-model-usage)提供最丰富的功能集,包含字段校验、描述与嵌套结构。
python
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 = Field(description="The movie's rating out of 10")
model_with_structure = model.with_structured_output(Movie)
response = model_with_structure.invoke("Provide details about the movie Inception")
print(response) # Movie(title="Inception", year=2010, director="Christopher Nolan", rating=8.8)TypedDict
Python 的 `TypedDict` 提供了比 Pydantic 模型更简单的替代方案,当你不需要运行时校验时非常理想。
python
from typing_extensions import TypedDict, Annotated
class MovieDict(TypedDict):
"""A movie with details."""
title: Annotated[str, ..., "The title of the movie"]
year: Annotated[int, ..., "The year the movie was released"]
director: Annotated[str, ..., "The director of the movie"]
rating: Annotated[float, ..., "The movie's rating out of 10"]
model_with_structure = model.with_structured_output(MovieDict)
response = model_with_structure.invoke("Provide details about the movie Inception")
print(response) # {'title': 'Inception', 'year': 2010, 'director': 'Christopher Nolan', 'rating': 8.8}JSON Schema
提供 [JSON Schema](https://json-schema.org/understanding-json-schema/about) 以获得最大的控制力与互操作性。
python
import json
json_schema = {
"title": "Movie",
"description": "A movie with details",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "The title of the movie"
},
"year": {
"type": "integer",
"description": "The year the movie was released"
},
"director": {
"type": "string",
"description": "The director of the movie"
},
"rating": {
"type": "number",
"description": "The movie's rating out of 10"
}
},
"required": ["title", "year", "director", "rating"]
}
model_with_structure = model.with_structured_output(
json_schema,
method="json_schema",
)
response = model_with_structure.invoke("Provide details about the movie Inception")
print(response) # {'title': 'Inception', 'year': 2010, ...}Zod
[zod schema](https://zod.dev/) 是定义输出 schema 的首选方法。注意,提供 zod schema 时,模型输出也会使用 zod 的解析方法根据 schema 进行校验。
typescript
import * as z from "zod";
const Movie = z.object({
title: z.string().describe("The title of the movie"),
year: z.number().describe("The year the movie was released"),
director: z.string().describe("The director of the movie"),
rating: z.number().describe("The movie's rating out of 10"),
});
const modelWithStructure = model.withStructuredOutput(Movie);
const response = await modelWithStructure.invoke("Provide details about the movie Inception");
console.log(response);
// {
// title: "Inception",
// year: 2010,
// director: "Christopher Nolan",
// rating: 8.8,
// }JSON Schema
为了获得最大的控制力或互操作性,你可以提供原始的 JSON Schema。
typescript
const jsonSchema = {
"title": "Movie",
"description": "A movie with details",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "The title of the movie",
},
"year": {
"type": "integer",
"description": "The year the movie was released",
},
"director": {
"type": "string",
"description": "The director of the movie",
},
"rating": {
"type": "number",
"description": "The movie's rating out of 10",
},
},
"required": ["title", "year", "director", "rating"],
}
const modelWithStructure = model.withStructuredOutput(
jsonSchema,
{ method: "jsonSchema" },
)
const response = await modelWithStructure.invoke("Provide details about the movie Inception")
console.log(response) // {'title': 'Inception', 'year': 2010, ...}Standard Schema
任何实现了 [Standard Schema](https://standardschema.dev/) 规范的库所提供的 schema 也都受支持。Standard Schema 对象会通过 schema 的 `~standard.validate()` 方法在运行时进行校验。
typescript
import * as v from "valibot";
import { toStandardJsonSchema } from "@valibot/to-json-schema";
const Movie = toStandardJsonSchema(
v.object({
title: v.pipe(v.string(), v.description("The title of the movie")),
year: v.pipe(v.number(), v.description("The year the movie was released")),
director: v.pipe(v.string(), v.description("The director of the movie")),
rating: v.pipe(v.number(), v.description("The movie's rating out of 10")),
})
);
const modelWithStructure = model.withStructuredOutput(Movie);
const response = await modelWithStructure.invoke("Provide details about the movie Inception");
console.log(response);
// {
// title: "Inception",
// year: 2010,
// director: "Christopher Nolan",
// rating: 8.8,
// }INFO
结构化输出的关键考虑事项
- 方法参数:有些提供商支持不同的结构化输出方法:
'json_schema':使用提供商提供的专用结构化输出功能。'function_calling':通过强制一个遵循给定 schema 的工具调用来派生结构化输出。'json_mode':某些提供商提供的'json_schema'的前身。会生成合法 JSON,但 schema 必须在提示词中描述。
- 包含原始输出:设置
include_raw=True可同时获得解析后的输出与原始 AI 消息。 - 校验:Pydantic 模型提供自动校验。
TypedDict与 JSON Schema 需要手动校验。
受支持的方法与配置选项参见你的提供商集成页面。
INFO
结构化输出的关键考虑事项:
- 方法参数:有些提供商支持不同的方法(
'jsonSchema'、'functionCalling'、'jsonMode') - 包含原始输出:使用
includeRaw: true同时获得解析后的输出与原始AIMessage - 校验:Zod 与 Standard Schema 对象提供自动校验,而 JSON Schema 需要手动校验
- Standard Schema:任何实现了 Standard Schema 规范的 schema 库都受支持,并在运行时进行校验
受支持的方法与配置选项参见你的提供商集成页面。
示例:消息输出与解析后的结构并存
在解析后的表示之外同时返回原始 AIMessage 对象可能会很有用,以便访问诸如 token 计数之类的响应元数据。为此,请在调用 with_structured_output 时设置 include_raw=True:
python
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 = Field(description="The movie's rating out of 10")
model_with_structure = model.with_structured_output(Movie, include_raw=True)
response = model_with_structure.invoke("Provide details about the movie Inception")
response
# {
# "raw": AIMessage(...),
# "parsed": Movie(title=..., year=..., ...),
# "parsing_error": None,
# }typescript
import * as z from "zod";
const Movie = z.object({
title: z.string().describe("The title of the movie"),
year: z.number().describe("The year the movie was released"),
director: z.string().describe("The director of the movie"),
rating: z.number().describe("The movie's rating out of 10"),
title: z.string().describe("The title of the movie"),
year: z.number().describe("The year the movie was released"),
director: z.string().describe("The director of the movie"),
rating: z.number().describe("The movie's rating out of 10"),
});
const modelWithStructure = model.withStructuredOutput(Movie, { includeRaw: true });
const response = await modelWithStructure.invoke("Provide details about the movie Inception");
console.log(response);
// {
// raw: AIMessage { ... },
// parsed: { title: "Inception", ... }
// }示例:嵌套结构
Schema 可以嵌套:
python
from pydantic import BaseModel, Field
class Actor(BaseModel):
name: str
role: str
class MovieDetails(BaseModel):
title: str
year: int
cast: list[Actor]
genres: list[str]
budget: float | None = Field(None, description="Budget in millions USD")
model_with_structure = model.with_structured_output(MovieDetails)python
from typing_extensions import Annotated, TypedDict
class Actor(TypedDict):
name: str
role: str
class MovieDetails(TypedDict):
title: str
year: int
cast: list[Actor]
genres: list[str]
budget: Annotated[float | None, ..., "Budget in millions USD"]
model_with_structure = model.with_structured_output(MovieDetails)typescript
import * as z from "zod";
const Actor = z.object({
name: z.string(),
role: z.string(),
});
const MovieDetails = z.object({
title: z.string(),
year: z.number(),
cast: z.array(Actor),
genres: z.array(z.string()),
budget: z.number().nullable().describe("Budget in millions USD"),
});
const modelWithStructure = model.withStructuredOutput(MovieDetails);高级主题
模型配置档案
INFO
模型配置档案需要 langchain>=1.1。
LangChain 对话模型可以通过 profile 属性暴露受支持特性与能力的字典:
python
model.profile
# {
# "max_input_tokens": 400000,
# "image_inputs": True,
# "reasoning_output": True,
# "tool_calling": True,
# ...
# }字段的完整集合参见 API 参考。
模型配置档案中的大部分数据由 models.dev 项目提供,这是一个提供模型能力数据的开源项目。这些数据会为在 LangChain 中使用而补充额外的字段。这些补充会随着上游项目的发展保持对齐。
模型配置档案数据让应用可以动态地适应模型能力。例如:
- 摘要中间件可以根据模型的上下文窗口大小触发摘要。
create_agent中的结构化输出策略可以自动推断(例如通过检查对原生结构化输出功能的支持)。- 模型输入可以根据受支持的模态与最大输入 token 进行门控。
- Deep Agents Code 会把交互式模型切换器过滤到其配置档案报告支持
tool_calling与文本 I/O 的模型,并在选择器详情视图中显示上下文窗口大小与能力标志。
更新或覆盖配置档案数据
如果模型配置档案数据缺失、过期或不正确,可以进行修改。
**选项 1(快速修复)**
你可以使用任何有效的配置档案实例化对话模型:
python
custom_profile = {
"max_input_tokens": 100_000,
"tool_calling": True,
"structured_output": True,
# ...
}
model = init_chat_model("...", profile=custom_profile)`profile` 也是一个普通的 `dict`,可以就地更新。如果模型实例被共享,请考虑使用 `model_copy` 以避免修改共享状态。
python
new_profile = model.profile | {"key": "value"}
model.model_copy(update={"profile": new_profile})**选项 2(在上游修复数据)**
数据的主要来源是 [models.dev](https://models.dev/) 项目。这些数据会与 LangChain [集成包](/oss/integrations/providers/overview)中的额外字段与覆盖项合并,并随这些包一起发布。
模型配置档案数据可以通过以下流程更新:
1. (如需)通过向其在 [GitHub 上的仓库](https://github.com/sst/models.dev)提交 pull request,在 [models.dev](https://models.dev/) 更新源数据。
2. (如需)通过向 LangChain [集成包](/oss/integrations/providers/overview)提交 pull request,更新 `langchain_<package>/data/profile_augmentations.toml` 中的额外字段与覆盖项。
3. 使用 [`langchain-model-profiles`](https://pypi.org/project/langchain-model-profiles/) CLI 工具从 [models.dev](https://models.dev/) 拉取最新数据,合并补充项并更新配置档案数据:
bash
pip install langchain-model-profilesbash
langchain-profiles refresh --provider <provider> --data-dir <data_dir>该命令会:
- 从 models.dev 下载 `<provider>` 的最新数据
- 合并 `<data_dir>` 中 `profile_augmentations.toml` 的补充项
- 把合并后的配置档案写入 `<data_dir>` 中的 `profiles.py`
例如:在 [LangChain monorepo](https://github.com/langchain-ai/langchain) 中的 [`libs/partners/anthropic`](https://github.com/langchain-ai/langchain/tree/master/libs/partners/anthropic) 目录下:
bash
uv run --with langchain-model-profiles --provider anthropic --data-dir langchain_anthropic/dataLangChain 对话模型可以通过 profile 属性暴露受支持特性与能力的字典:
typescript
model.profile;
// {
// maxInputTokens: 400000,
// imageInputs: true,
// reasoningOutput: true,
// toolCalling: true,
// ...
// }字段的完整集合参见 API 参考。
模型配置档案中的大部分数据由 models.dev 项目提供,这是一个提供模型能力数据的开源项目。这些数据会为在 LangChain 中使用而补充额外的字段。这些补充会随着上游项目的发展保持对齐。
模型配置档案数据让应用可以动态地适应模型能力。例如:
- 摘要中间件可以根据模型的上下文窗口大小触发摘要。
createAgent中的结构化输出策略可以自动推断(例如通过检查对原生结构化输出功能的支持)。- 模型输入可以根据受支持的模态与最大输入 token 进行门控。
- Deep Agents Code 会把交互式模型切换器过滤到其配置档案报告支持
tool_calling与文本 I/O 的模型,并在选择器详情视图中显示上下文窗口大小与能力标志。
修改配置档案数据
如果模型配置档案数据缺失、过期或不正确,可以进行修改。
**选项 1(快速修复)**
你可以使用任何有效的配置档案实例化对话模型:
typescript
const customProfile = {
maxInputTokens: 100_000,
toolCalling: true,
structuredOutput: true,
// ...
};
const model = initChatModel("...", { profile: customProfile });**选项 2(在上游修复数据)**
数据的主要来源是 [models.dev](https://models.dev/) 项目。这些数据会与 LangChain [集成包](/oss/integrations/providers/overview)中的额外字段与覆盖项合并,并随这些包一起发布。
模型配置档案数据可以通过以下流程更新:
1. (如需)通过向其在 [GitHub 上的仓库](https://github.com/sst/models.dev)提交 pull request,在 [models.dev](https://models.dev/) 更新源数据。
2. (如需)通过向 LangChain [集成包](/oss/integrations/providers/overview)提交 pull request,更新 `langchain-<package>/profiles.toml` 中的额外字段与覆盖项。
WARNING
模型配置档案是 beta 功能。配置档案的格式可能会发生变化。
多模态
某些模型可以处理并返回图像、音频与视频等非文本数据。你可以通过提供内容块把非文本数据传给模型。
TIP
所有具有底层多模态能力的 LangChain 对话模型都支持:
- 跨提供商标准格式的数据(参见我们的消息指南)
- OpenAI chat completions 格式
- 该特定提供商原生的任何格式(例如 Anthropic 模型接受 Anthropic 原生格式)
细节参见消息指南中的多模态小节。
有些模型可以在其响应中返回多模态数据。如果被要求这样做,生成的 AIMessage 将包含带多模态类型的内容块。
python
response = model.invoke("Create a picture of a cat")
print(response.content_blocks)
# [
# {"type": "text", "text": "Here's a picture of a cat"},
# {"type": "image", "base64": "...", "mime_type": "image/jpeg"},
# ]typescript
const response = await model.invoke("Create a picture of a cat");
console.log(response.contentBlocks);
// [
// { type: "text", text: "Here's a picture of a cat" },
// { type: "image", data: "...", mimeType: "image/jpeg" },
// ]特定提供商的细节参见集成页面。
推理
许多模型能够执行多步推理以得出结论。这涉及把复杂问题分解成更小、更易于管理的步骤。
如果底层模型支持, 你可以呈现这个推理过程,以更好地理解模型是如何得出最终答案的。
python
for chunk in model.stream("Why do parrots have colorful feathers?"):
reasoning_steps = [r for r in chunk.content_blocks if r["type"] == "reasoning"]
print(reasoning_steps if reasoning_steps else chunk.text)python
response = model.invoke("Why do parrots have colorful feathers?")
reasoning_steps = [b for b in response.content_blocks if b["type"] == "reasoning"]
print(" ".join(step["reasoning"] for step in reasoning_steps))typescript
const stream = model.stream("Why do parrots have colorful feathers?");
for await (const chunk of stream) {
const reasoningSteps = chunk.contentBlocks.filter(b => b.type === "reasoning");
console.log(reasoningSteps.length > 0 ? reasoningSteps : chunk.text);
}typescript
const response = await model.invoke("Why do parrots have colorful feathers?");
const reasoningSteps = response.contentBlocks.filter(b => b.type === "reasoning");
console.log(reasoningSteps.map(step => step.reasoning).join(" "));根据模型的不同,你有时可以指定它应在推理上投入的努力程度。类似地,你也可以要求模型完全关闭推理。这可能表现为分类的推理"档位"(例如 'low' 或 'high'),或整数的 token 预算。
INFO
reasoning_effort 作为标准参数需要 langchain-core>=1.5.2,以及相应的合作伙伴包版本:langchain-anthropic>=1.5.3、langchain-openai>=1.4.1、langchain-fireworks>=1.5.2、langchain-xai>=1.3.0 或 langchain-google-genai>=4.3.1。
ChatOpenAI、ChatAnthropic、ChatFireworks、ChatXAI 与 ChatGoogleGenerativeAI 支持标准的 reasoning_effort 参数。与 temperature 一样,它可以在模型构造时或每次调用时设置,每个提供商会把它转换成自己的 API 格式:
python
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-sonnet-4-6")
response = model.invoke(
"Why do parrots have colorful feathers?",
reasoning_effort="high",
)受支持的努力级别与提供商记录在案的默认值因模型而异。请检查模型的配置档案以了解它支持的级别及其默认值:
python
model.profile["reasoning_effort_levels"] # e.g. ['low', 'medium', 'high']
model.profile["reasoning_effort_default"] # e.g. 'high'某些提供商也接受 reasoning_effort 的原生别名(例如 ChatAnthropic 接受 effort,ChatGoogleGenerativeAI 接受 thinking_level)。提供商专属细节参见对话模型集成页面。
本地模型
LangChain 支持在你自己的硬件上本地运行模型。这在数据隐私至关重要、你想调用自定义模型,或想避免使用云端模型的成本时很有用。
Ollama 是在本地运行对话与嵌入模型的最简单方式之一。
提示词缓存
许多提供商提供提示词缓存功能,以减少对相同 token 重复处理的延迟与成本。你可以在三个层面参与缓存:
- 隐式提供商缓存: 如果请求命中缓存,提供商会自动传递成本节约,无需配置。示例:OpenAI 与 Gemini。
- 提供商级显式控制: 提供商让你手动标记缓存点,以获得更大的控制力或保证成本节约。这些与底层提供商/API 行为一致。示例:
ChatOpenAI(通过prompt_cache_key)- Anthropic 内容块的
cache_control - Gemini。
- AWS Bedrock 的
cachePoint块
- LangChain 中间件: 对于智能体,中间件让 LangChain 可以优化对稳定系统提示词与工具内容的缓存。示例:
- Anthropic 的
AnthropicPromptCachingMiddleware - AWS Bedrock 的
BedrockPromptCachingMiddleware
- Anthropic 的
WARNING
提示词缓存通常只在输入 token 超过最低阈值时才会启用。细节参见提供商页面。
缓存使用情况会反映在模型响应的使用情况元数据中。
服务端工具使用
某些提供商支持服务端工具调用循环:模型可以在单个对话轮次中与网络搜索、代码解释器和其他工具交互并分析结果。
如果模型在服务端调用工具,响应消息的内容将包含表示该工具调用与结果的内容。访问响应的内容块会以提供商无关的格式返回服务端工具调用与结果:
python
from langchain.chat_models import init_chat_model
model = init_chat_model("gpt-5.4-mini")
tool = {"type": "web_search"}
model_with_tools = model.bind_tools([tool])
response = model_with_tools.invoke("What was a positive news story from today?")
print(response.content_blocks)python
[
{
"type": "server_tool_call",
"name": "web_search",
"args": {
"query": "positive news stories today",
"type": "search"
},
"id": "ws_abc123"
},
{
"type": "server_tool_result",
"tool_call_id": "ws_abc123",
"status": "success"
},
{
"type": "text",
"text": "Here are some positive news stories from today...",
"annotations": [
{
"end_index": 410,
"start_index": 337,
"title": "article title",
"type": "citation",
"url": "..."
}
]
}
]typescript
import { initChatModel } from "langchain";
const model = await initChatModel("gpt-5.4-mini");
const modelWithTools = model.bindTools([{ type: "web_search" }])
const message = await modelWithTools.invoke("What was a positive news story from today?");
console.log(message.contentBlocks);这表示单个对话轮次;与客户端工具调用不同,这里没有需要传入的关联 ToolMessage 对象。
你的给定提供商的可用工具与用法细节参见集成页面。
速率限制
许多对话模型提供商对给定时间段内的调用次数施加限制。如果你触发了速率限制,通常会在提供商的错误响应中看到速率限制错误,并且需要等待后再发出更多请求。
为帮助管理速率限制,对话模型集成接受一个 rate_limiter 参数,可以在初始化时提供,以控制请求发出的速率。
初始化并使用速率限制器
LangChain 自带(可选的)内置 `InMemoryRateLimiter`。此限制器是线程安全的,可以被同一进程中的多个线程共享。
python
from langchain.rate_limiters import InMemoryRateLimiter
rate_limiter = InMemoryRateLimiter(
requests_per_second=0.1, # 每 10 秒 1 个请求
check_every_n_seconds=0.1, # 每 100 毫秒检查一次是否允许发出请求
max_bucket_size=10, # 控制最大突发请求数。
)
model = init_chat_model(
model="gpt-5.5",
model_provider="openai",
rate_limiter=rate_limiter
)WARNING
提供的速率限制器只能限制每单位时间的请求次数。如果你还需要根据请求的大小进行限制,它不会有帮助。
Base URL 与代理设置
你可以为实现了 OpenAI Chat Completions API 的提供商配置自定义 base URL。
WARNING
model_provider="openai"(或直接使用 ChatOpenAI)以官方 OpenAI API 规范为目标。来自路由器与代理的提供商专属字段可能不会被提取或保留。
对于 OpenRouter 与 LiteLLM,请优先使用专用集成:
- 通过
ChatOpenRouter使用 OpenRouter(langchain-openrouter) - 通过
ChatLiteLLM/ChatLiteLLMRouter使用 LiteLLM(langchain-litellm)
自定义 base URL
许多模型提供商提供与 OpenAI 兼容的 API(例如 Together AI、vLLM)。你可以通过指定相应的 base_url 参数,与这些提供商一起使用 init_chat_model:
python
model = init_chat_model(
model="MODEL_NAME",
model_provider="openai",
base_url="BASE_URL",
api_key="YOUR_API_KEY",
)许多模型提供商提供与 OpenAI 兼容的 API(例如 Together AI、vLLM)。你可以通过指定相应的 base_url 参数,与这些提供商一起使用 initChatModel:
python
model = initChatModel(
"MODEL_NAME",
{
modelProvider: "openai",
baseUrl: "BASE_URL",
apiKey: "YOUR_API_KEY",
}
)INFO
直接实例化对话模型类时,参数名可能因提供商而异。细节请查看相应的参考。
HTTP 代理配置
对于需要 HTTP 代理的部署,某些模型集成支持代理配置:
python
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="gpt-5.5",
openai_proxy="http://proxy.example.com:8080"
)INFO
代理支持因集成而异。代理配置选项请查看特定模型提供商的参考。
对数概率(Log probabilities)
某些模型可以在初始化时通过设置 logprobs 参数,配置为返回 token 级别的对数概率,表示给定 token 的可能性:
python
model = init_chat_model(
model="gpt-5.5",
model_provider="openai"
).bind(logprobs=True)
response = model.invoke("Why do parrots talk?")
print(response.response_metadata["logprobs"])typescript
const model = new ChatOpenAI({
model: "gpt-5.5",
logprobs: true,
});
const responseMessage = await model.invoke("Why do parrots talk?");
responseMessage.response_metadata.logprobs.content.slice(0, 5);Token 使用情况
许多模型提供商在调用响应中返回 token 使用情况信息。当可用时,这些信息会包含在相应模型生成的 AIMessage 对象上。更多细节参见消息指南。
INFO
某些提供商 API(尤其是 OpenAI 与 Azure OpenAI 的 chat completions)要求用户选择加入才能在流式上下文中接收 token 使用数据。细节参见集成指南中的流式使用情况元数据小节。
你可以使用回调或上下文管理器跟踪应用中各模型的聚合 token 计数,如下所示:
回调处理器
python
from langchain.chat_models import init_chat_model
from langchain_core.callbacks import UsageMetadataCallbackHandler
model_1 = init_chat_model(model="gpt-5.4-mini")
model_2 = init_chat_model(model="claude-haiku-4-5-20251001")
callback = UsageMetadataCallbackHandler()
result_1 = model_1.invoke("Hello", config={"callbacks": [callback]})
result_2 = model_2.invoke("Hello", config={"callbacks": [callback]})
print(callback.usage_metadata)python
{
'gpt-5.4-mini': {
'input_tokens': 8,
'output_tokens': 10,
'total_tokens': 18,
'input_token_details': {'audio': 0, 'cache_read': 0},
'output_token_details': {'audio': 0, 'reasoning': 0}
},
'claude-haiku-4-5-20251001': {
'input_tokens': 8,
'output_tokens': 21,
'total_tokens': 29,
'input_token_details': {'cache_read': 0, 'cache_creation': 0}
}
}上下文管理器
python
from langchain.chat_models import init_chat_model
from langchain_core.callbacks import get_usage_metadata_callback
model_1 = init_chat_model(model="gpt-5.4-mini")
model_2 = init_chat_model(model="claude-haiku-4-5-20251001")
with get_usage_metadata_callback() as cb:
model_1.invoke("Hello")
model_2.invoke("Hello")
print(cb.usage_metadata)python
{
'gpt-5.4-mini': {
'input_tokens': 8,
'output_tokens': 10,
'total_tokens': 18,
'input_token_details': {'audio': 0, 'cache_read': 0},
'output_token_details': {'audio': 0, 'reasoning': 0}
},
'claude-haiku-4-5-20251001': {
'input_tokens': 8,
'output_tokens': 21,
'total_tokens': 29,
'input_token_details': {'cache_read': 0, 'cache_creation': 0}
}
}调用配置
调用模型时,你可以通过 config 参数传入一个 RunnableConfig 字典来传递额外配置。这提供了对执行行为、回调与元数据跟踪的运行时控制。
调用模型时,你可以通过 config 参数传入一个 RunnableConfig 对象来传递额外配置。这提供了对执行行为、回调与元数据跟踪的运行时控制。
常见的配置选项包括:
python
response = model.invoke(
"Tell me a joke",
config={
"run_name": "joke_generation", # 此次运行的自定义名称
"tags": ["humor", "demo"], # 用于分类的标签
"metadata": {"user_id": "123"}, # 自定义元数据
"callbacks": [my_callback_handler], # 回调处理器
}
)typescript
const response = await model.invoke(
"Tell me a joke",
{
runName: "joke_generation", // 此次运行的自定义名称
tags: ["humor", "demo"], // 用于分类的标签
metadata: {"user_id": "123"}, // 自定义元数据
callbacks: [my_callback_handler], // 回调处理器
}
)这些配置值在以下场景中特别有用:
- 使用 LangSmith 追踪进行调试
- 实现自定义日志或监控
- 在生产环境中控制资源使用
- 跨复杂流水线跟踪调用
关键配置属性
run_name (string):在日志与追踪中标识此特定调用。不会被子调用继承。
tags (string[]):会被所有子调用继承的标签,用于调试工具中的过滤与组织。
metadata (object):用于跟踪额外上下文的自定义键值对,会被所有子调用继承。
max_concurrency (number):使用
batch()或batch_as_completed()时控制最大并行调用数。callbacks (array):用于在执行期间监控事件并对其做出响应的处理器。
recursion_limit (number):链的最大递归深度,以防止复杂流水线中的无限循环。
关键配置属性
runName (string):在日志与追踪中标识此特定调用。不会被子调用继承。
tags (string[]):会被所有子调用继承的标签,用于调试工具中的过滤与组织。
metadata (object):用于跟踪额外上下文的自定义键值对,会被所有子调用继承。
maxConcurrency (number):使用
batch()时控制最大并行调用数。callbacks (CallbackHandler[]):用于在执行期间监控事件并对其做出响应的处理器。
recursion_limit (number):链的最大递归深度,以防止复杂流水线中的无限循环。
TIP
所有受支持属性的完整 RunnableConfig 参考参见此处。
可配置模型
你还可以通过指定 configurable_fields 创建运行时可配置的模型。如果你不指定模型值,那么默认情况下 'model' 与 'model_provider' 是可配置的。
python
from langchain.chat_models import init_chat_model
configurable_model = init_chat_model(temperature=0)
configurable_model.invoke(
"what's your name",
config={"configurable": {"model": "gpt-5-nano"}}, # 使用 GPT-5-Nano 运行
)
configurable_model.invoke(
"what's your name",
config={"configurable": {"model": "claude-sonnet-4-6"}}, # 使用 Claude 运行
)带默认值的可配置模型
我们可以创建带默认模型值的可配置模型,指定哪些参数是可配置的,并给可配置参数添加前缀:
python
first_model = init_chat_model(
model="gpt-5.4-mini",
temperature=0,
configurable_fields=("model", "model_provider", "temperature", "max_tokens"),
config_prefix="first", # 当链中有多个模型时很有用
)
first_model.invoke("what's your name")python
first_model.invoke(
"what's your name",
config={
"configurable": {
"first_model": "claude-sonnet-4-6",
"first_temperature": 0.5,
"first_max_tokens": 100,
}
},
)`configurable_fields` 与 `config_prefix` 的更多细节参见 `init_chat_model` 参考。
声明式地使用可配置模型
我们可以在可配置模型上调用 `bind_tools`、`with_structured_output`、`with_configurable` 等声明式操作,并像使用常规实例化的对话模型对象一样链式使用可配置模型。
python
from pydantic import BaseModel, Field
class GetWeather(BaseModel):
"""Get the current weather in a given location"""
location: str = Field(description="The city and state, e.g. San Francisco, CA")
class GetPopulation(BaseModel):
"""Get the current population in a given location"""
location: str = Field(description="The city and state, e.g. San Francisco, CA")
model = init_chat_model(temperature=0)
model_with_tools = model.bind_tools([GetWeather, GetPopulation])
model_with_tools.invoke(
"what's bigger in 2024 LA or NYC", config={"configurable": {"model": "gpt-5.4-mini"}}
).tool_calls[
{
'name': 'GetPopulation',
'args': {'location': 'Los Angeles, CA'},
'id': 'call_Ga9m8FAArIyEjItHmztPYA22',
'type': 'tool_call'
},
{
'name': 'GetPopulation',
'args': {'location': 'New York, NY'},
'id': 'call_jh2dEvBaAHRaw5JUDthOs7rt',
'type': 'tool_call'
}
]python
model_with_tools.invoke(
"what's bigger in 2024 LA or NYC",
config={"configurable": {"model": "claude-sonnet-4-6"}},
).tool_calls[
{
'name': 'GetPopulation',
'args': {'location': 'Los Angeles, CA'},
'id': 'toolu_01JMufPf4F4t2zLj7miFeqXp',
'type': 'tool_call'
},
{
'name': 'GetPopulation',
'args': {'location': 'New York City, NY'},
'id': 'toolu_01RQBHcE8kEEbYTuuS8WqY1u',
'type': 'tool_call'
}
]动态模型选择
动态模型在运行时根据当前的状态与上下文被选择。这支持复杂路由逻辑与成本优化。
要使用动态模型,请使用 @wrap_model_call 装饰器创建修改请求中模型的中间件:
python
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
basic_model = ChatOpenAI(model="gpt-5.4-mini")
advanced_model = ChatOpenAI(model="gpt-5.5")
@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
"""Choose model based on conversation complexity."""
message_count = len(request.state["messages"])
if message_count > 10:
# 对于较长的对话使用高级模型
model = advanced_model
else:
model = basic_model
return handler(request.override(model=model))
agent = create_agent(
model=basic_model, # 默认模型
tools=tools,
middleware=[dynamic_model_selection]
)WARNING
使用结构化输出时,不支持预先绑定的模型(已经调用过 bind_tools 的模型)。如果你需要带结构化输出的动态模型选择,请确保传给中间件的模型没有被预绑定。
要使用动态模型,请使用修改请求中模型的 wrapModelCall 创建中间件:
ts
import { ChatOpenAI } from "@langchain/openai";
import { createAgent, createMiddleware } from "langchain";
const basicModel = new ChatOpenAI({ model: "gpt-5.4-mini" });
const advancedModel = new ChatOpenAI({ model: "gpt-5.5" });
const dynamicModelSelection = createMiddleware({
name: "DynamicModelSelection",
wrapModelCall: (request, handler) => {
// 根据对话复杂度选择模型
const messageCount = request.messages.length;
return handler({
...request,
model: messageCount > 10 ? advancedModel : basicModel,
});
},
});
const agent = createAgent({
model: "gpt-5.4-mini", // 基础模型(当 messageCount ≤ 10 时使用)
tools,
middleware: [dynamicModelSelection],
});中间件与高级模式的更多细节参见中间件文档。