Skip to content

模型(Models) ​

初始化和配置 Chat Models,作为 LangChain 智能体的推理引擎,支持工具调用、结构化输出和多模态输入。

LLM 是功能强大的人工智能工具,能够像人类一样理解和生成文本。它们具备极高的通用性,无需针对每项任务进行专门训练,即可胜任内容撰写、语言翻译、内容总结和问答等工作。

除了文本生成之外,许多模型还支持:

模型是智能体的推理引擎。它们驱动智能体的决策过程,决定调用哪些工具、如何解读结果以及何时给出最终答案。

所选模型的质量和能力直接影响智能体的基准可靠性与性能。不同的模型擅长不同的任务——有些更擅长遵循复杂指令,有些擅长结构化推理,还有一些支持更大的上下文窗口以处理更多信息。

LangChain 的标准模型接口使你可以接入众多不同的提供商集成,从而能够轻松地进行实验并在模型之间自由切换,找到最适合你用例的模型。

有关特定提供商的集成信息和功能,请参阅该提供商的 Chat Model 页面。

TIP

LangSmith 会追踪每一次模型调用,以便你比较不同提供商、检查工具路由并调试故障。请按照追踪快速入门进行配置。

我们建议你同时配置 LangSmith Engine,它可以监控你的追踪记录、检测问题并提出修复建议。

基础用法 ​

模型有两种使用方式:

  1. 与智能体结合 - 在创建智能体时可以动态指定模型。
  2. 独立使用 - 可以直接调用模型(在智能体循环之外),用于文本生成、分类或信息提取等任务,无需依赖智能体框架。

同一套模型接口在两种场景下均可使用,这让你能够灵活地从简单场景起步,并根据需要扩展为更复杂的基于智能体的工作流。

初始化模型 ​

在 LangChain 中使用独立模型的最简单方式是使用 initChatModel 从你选择的 Chat Model 提供商初始化一个模型(示例如下):

OpenAI

👉 阅读 OpenAI Chat Model 集成文档

bash
npm install @langchain/openai
bash
pnpm install @langchain/openai
bash
yarn add @langchain/openai
bash
bun add @langchain/openai
typescript
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

👉 阅读 Anthropic Chat Model 集成文档

bash
npm install @langchain/anthropic
bash
pnpm install @langchain/anthropic
bash
yarn add @langchain/anthropic
bash
pnpm add @langchain/anthropic
typescript
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

👉 阅读 Azure Chat Model 集成文档

bash
npm install @langchain/azure
bash
pnpm install @langchain/azure
bash
yarn add @langchain/azure
bash
bun add @langchain/azure
typescript
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

👉 阅读 ChatGoogle Chat Model 集成文档

bash
npm install @langchain/google
bash
pnpm install @langchain/google
bash
yarn add @langchain/google
bash
bun add @langchain/google
typescript
import { initChatModel } from "langchain";

process.env.GOOGLE_API_KEY = "your-api-key";

const model = await initChatModel("google:gemini-3.7-flash");
typescript
import { ChatGoogle } from "@langchain/google/node";

const model = new ChatGoogle({
  model: "gemini-3.7-flash",
  apiKey: "your-api-key"
});

Bedrock Converse

👉 阅读 AWS Bedrock Chat Model 集成文档

bash
npm install @langchain/aws
bash
pnpm install @langchain/aws
bash
yarn add @langchain/aws
bash
bun add @langchain/aws
typescript
import { initChatModel } from "langchain";

// 按照此处的步骤配置您的凭据:
// 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";

// 按照此处的步骤配置您的凭据:
// 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

批量向模型发送多个请求,以实现更高效的处理。

NOTE

除了 Chat Model 之外,LangChain 还支持其他周边技术,例如嵌入模型(Embedding Models)和向量存储(Vector Stores)。详情请参阅集成页面。

参数 ​

Chat Model 接受用于配置其行为的参数。所支持的完整参数集因模型和提供商而异,但标准参数包括:

model string 必需

你要在特定提供商中使用的具体模型的名称或标识符。你也可以使用 '{model_provider}:{model}' 格式在一个参数中同时指定模型及其提供商,例如 'openai:o1'。

apiKey string

用于在模型提供商处进行身份验证所需的密钥。这通常是在你注册获取模型访问权限时颁发的。通常通过设置环境变量(其值在程序外部设置的变量,通常通过操作系统或微服务内置的功能进行配置)来访问。

temperature number

控制模型输出的随机性。数值越高,回答越有创造性;数值越低,回答越具确定性。

maxTokens number

限制响应中的总 Token 数量(模型读取和生成的基本单位。不同提供商的定义可能有所不同,但一般来说,它们可以代表整个单词或单词的一部分),从而有效控制输出的最大长度。

timeout number

在取消请求之前,等待模型响应的最长时间(以秒为单位)。

maxRetries number(默认值:6)

如果请求由于网络超时或速率限制等问题失败,系统尝试重新发送请求的最大次数。重试采用带抖动(jitter)的指数退避。网络错误、速率限制(429)和服务器错误(5xx)会自动重试。客户端错误(如 401 未授权或 404)不会重试。对于不可靠网络上的长时间运行智能体任务,建议将此值增加到 10–15。

在支持的提供商上,模型重试中间件会接管其包裹调用的重试逻辑,此时该参数值不适用于这些调用。

使用 initChatModel 时,将这些参数作为内联参数传入:

Initialize using model parameters
typescript
const model = await initChatModel(
    "claude-sonnet-4-6",
    { temperature: 0.7, timeout: 30, maxTokens: 1000, maxRetries: 6 }
)

连接恢复能力 ​

LangChain Chat Model 会使用指数退避自动重试失败的 API 请求。默认情况下,模型针对网络错误、速率限制(429)和服务器错误(5xx)最多重试 6 次。客户端错误(如 401 未授权或 404)不会重试。

你可以在创建模型时调整 maxRetries 和 timeout,然后将该实例传递给 createAgent、createDeepAgent,或者独立调用它:

typescript
import { initChatModel } from "langchain";

const model = await initChatModel("google:gemini-3.6-flash", {
  maxRetries: 10, // 针对不稳定的网络可增加此值(默认:6)
  timeout: 120_000, // 毫秒;针对慢速连接可增加此值
});

TIP

对于不可靠网络上的长时间运行智能体图(agent graphs),建议设置更高的 max_retries(例如 10–15)并配置检查点保存器(checkpointer),以便在发生故障时保留进度。

NOTE

每个 Chat Model 集成可能具有用于控制提供商专属功能的额外参数。

例如,ChatOpenAI 具有 use_responses_api 参数,用于决定是使用 OpenAI Responses API 还是 Completions API。

要查找特定 Chat Model 支持的所有参数,请访问 Chat Model 集成页面。


调用 ​

必须调用 Chat Model 才能生成输出。主要有三种调用方法,分别适用于不同的用例。

Invoke ​

调用模型最直接的方法是将单条消息或消息列表传递给 invoke()。

Single message
typescript
const response = await model.invoke("Why do parrots have colorful feathers?");
console.log(response);

可以向 Chat Model 提供消息列表以表示对话历史记录。每条消息都有一个角色(role),模型利用角色来指示对话中是谁发送了该消息。

有关角色、类型和内容的更多详细信息,请参阅消息指南。

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.")

NOTE

如果调用的返回类型是字符串,请确保你使用的是 Chat Model 而不是 LLM。传统的文本补全 LLM 会直接返回字符串。LangChain Chat Model 的前缀为 "Chat",例如 ChatOpenAI(/oss/integrations/chat/openai)。

Stream ​

大多数模型可以在生成输出内容的同时进行流式传输。通过逐步显示输出,流式传输显著提升了用户体验,尤其是在生成较长回复时。

调用 stream() 会返回一个迭代器(iterator,按顺序逐步提供对集合中每个项的访问权限的对象),在输出分块生成时将其依次产出。你可以使用循环实时处理每个分块:

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 对象,每个对象包含输出文本的一部分。重要的是,流中的每个分块都设计为可以通过累加聚合成一条完整的消息:

Construct AIMessage
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

只有当程序中的所有步骤都知道如何处理分块流时,流式传输才能正常工作。例如,如果某个应用程序必须在内存中存储完整输出后才能进行处理,那么它就是不具备流式处理能力的。

流式传输进阶主题

流式传输事件(Streaming events)

LangChain Chat Model 还可以使用 [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() 参考文档。

Chat Model 的“自动流式传输”

LangChain 通过在某些情况下自动启用流式模式(即使你并未显式调用流式方法),简化了来自 Chat Model 的流式传输。当你使用非流式的 invoke 方法,但仍希望对整个应用程序(包括来自 Chat Model 的中间结果)进行流式传输时,这尤其有用。

例如,在 LangGraph 智能体中,你可以在节点内调用 model.invoke(),但如果是在流式模式下运行,LangChain 将自动委托为流式传输。

工作原理 ​

当你 invoke() 一个 Chat Model 时,如果 LangChain 检测到你正在尝试流式传输整个应用程序,它将自动切换到内部流式模式。对于使用 invoke 的代码而言,调用的结果保持不变;但是,在 Chat Model 进行流式传输的同时,LangChain 会负责调用 LangChain 回调系统中的 on_llm_new_token 事件。

回调事件允许 LangGraph 的 stream() 和 streamEvents() 实时呈现 Chat Model 的输出。

Batch ​

将针对模型的一组独立请求进行批量处理可以显著提高性能并降低成本,因为处理可以并行完成:

Batch
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 参考文档。

有关批处理的更多详细信息,请参阅参考文档。


工具调用 ​

模型可以请求调用工具来执行诸如从数据库获取数据、搜索网络或运行代码等任务。工具由以下两部分配对组成:

  1. 模式(Schema),包括工具名称、描述和/或参数定义(通常是 JSON Schema)
  2. 要执行的函数或协程(coroutine,一种可以暂停执行并在稍后恢复的方法)。

NOTE

你可能听说过“函数调用(function calling)”这一术语。我们将其与“工具调用(tool calling)”互换使用。

以下是用户与模型之间的基本工具调用流程:

要使你定义的工具可供模型使用,必须使用 bindTools 绑定它们。在随后的调用中,模型可以根据需要选择调用任何绑定的工具。

某些模型提供商提供了内置工具(在服务端执行的工具,例如网络搜索和代码解释器),可以通过模型或调用参数启用(例如 ChatOpenAI、ChatAnthropic)。详情请查看相应的提供商参考文档。

TIP

有关创建工具的详细信息和其他选项,请参阅工具指南。

Binding user tools
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 包含为你处理此编排的智能体抽象。

以下是一个如何实现此操作的简单示例:

typescript
// 将(可能多个)工具绑定到模型
const tools = [getWeather]
const toolsByName = Object.fromEntries(tools.map((tool) => [tool.name, tool]))
const modelWithTools = model.bindTools(tools)

// 步骤 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 = toolsByName[tool_call.name]
    const tool_result = await tool.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,这有助于模型将结果与请求关联起来。

强制工具调用

默认情况下,模型可以根据用户的输入自由选择使用哪个绑定的工具。但是,你可能希望强制选择工具,以确保模型使用特定工具或给定列表中的任意工具:

typescript
const modelWithTools = model.bindTools([tool_1], { toolChoice: "any" })
typescript
const modelWithTools = model.bindTools([tool_1], { toolChoice: "tool_1" })

并行工具调用

许多模型支持在适当时并行调用多个工具。这允许模型同时从不同的数据源收集信息。

typescript
const tools = [getWeather]
const toolsByName = Object.fromEntries(tools.map((tool) => [tool.name, tool]))
const modelWithTools = model.bindTools(tools)

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_weather', args: { location: 'Tokyo' }, id: 'call_2' }
// ]


// 执行所有工具(可以通过 async 并行执行)
const results = []
for (const tool_call of response.tool_calls || []) {
    const tool = toolsByName[tool_call.name]
    const result = await tool.invoke(tool_call)
    results.push(result)
}

模型会根据请求操作的独立性,智能地确定何时适合并行执行。

TIP

大多数支持工具调用的模型默认启用并行工具调用。某些模型(包括 OpenAI 和 Anthropic)允许你禁用此功能。为此,请设置 parallel_tool_calls=False:

python
model.bind_tools([get_weather], parallel_tool_calls=False)

流式传输工具调用

流式传输响应时,工具调用是通过 ToolCallChunk 逐步构建的。这使你能够在工具调用生成时实时查看它们,而不是等待完整响应。

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

要了解有关结构化输出的更多信息,请参阅结构化输出。

Zod

Zod Schema 是定义输出 Schema 的推荐方法。请注意,当提供 Zod Schema 时,模型输出还将使用 Zod 的 parse 方法针对该 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 规范的库的任何 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,
// }

NOTE

结构化输出的核心考量:

  • Method 参数:某些提供商支持不同的方法('jsonSchema'、'functionCalling'、'jsonMode')
  • 包含原始输出(Include raw):使用 includeRaw: true 可同时获取解析后的输出和原始 AIMessage
  • 校验(Validation):Zod 和 Standard Schema 对象提供自动校验,而 JSON Schema 需要手动校验
  • Standard Schema:支持任何实现 Standard Schema 规范的 Schema 库并在运行时进行校验

有关支持的方法和配置选项,请参阅你的提供商集成页面。

示例:消息输出与解析后的结构一并返回

将原始 AIMessage 对象与解析后的表示形式一并返回,以便访问响应元数据(例如 Token 统计),这在很多场景下非常有用。为此,在调用 with_structured_output 时设置 include_raw=True:

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 可以进行嵌套:

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);

进阶主题 (Advanced topics) ​

模型能力画像 (Model profiles) ​

NOTE

模型能力画像需要 langchain>=1.1。

LangChain 对话模型可以通过 profile 属性暴露一个包含受支持特性与能力的字典:

typescript
model.profile;
// {
//   maxInputTokens: 400000,
//   imageInputs: true,
//   reasoningOutput: true,
//   toolCalling: true,
//   ...
// }

请参阅 API 参考文档 获取完整的字段集。

模型能力画像的大部分数据由 models.dev 项目提供支持,该项目是一个提供模型能力数据的开源倡议。这些数据已针对 LangChain 的使用场景扩充了额外字段。随着上游项目的发展,这些扩充内容会与其保持同步。

模型能力画像数据使应用程序能够根据模型能力进行动态调整。例如:

  1. 摘要中间件 可以根据模型的上下文窗口大小触发摘要生成。
  2. createAgent 中的 结构化输出 策略可以自动推断(例如,通过检查是否支持原生结构化输出特性)。
  3. 可以根据支持的 多模态(modalities) 和最大输入 Token 数量对模型输入进行门禁校验。
  4. Deep Agents Code 会将 交互式模型切换器 筛选为能力画像中报告支持 tool_calling 和文本 I/O 的模型,并在选择器详细视图中显示上下文窗口大小和能力标志。

修改画像数据 (Modify profile data)

如果模型画像数据缺失、过时或不正确,可以对其进行修改。

方案 1(快速修复)

你可以使用任意有效的画像来实例化对话模型:

typescript
const customProfile = {
maxInputTokens: 100_000,
toolCalling: true,
structuredOutput: true,
// ...
};
const model = initChatModel("...", { profile: customProfile });

方案 2(在上游修复数据)

数据的原始主要来源是 models.dev 项目。这些数据会与 LangChain 集成包 中的附加字段和重写配置合并,并随这些包一同发布。

模型画像数据可以通过以下流程进行更新:

1.(如需)通过向 GitHub 仓库 提交 Pull Request,更新 models.dev 的源数据。 2.(如需)通过向 LangChain 集成包 提交 Pull Request,更新 langchain-<package>/profiles.toml 中的附加字段和重写配置。

WARNING

模型能力画像是一个测试版特性(Beta feature)。画像的格式可能会发生变更。

多模态 (Multimodal) ​

某些模型能够处理并返回非文本数据,例如图像、音频和视频。你可以通过提供 内容块(content blocks) 向模型传递非文本数据。

TIP

所有具备底层多模态能力的 LangChain 对话模型均支持:

  1. 跨供应商标准格式的数据(参见 消息指南)
  2. OpenAI Chat Completions 格式
  3. 特定供应商原生的任何格式(例如,Anthropic 模型接受 Anthropic 原生格式)

有关详细信息,请参阅消息指南中的 多模态章节。

某些模型(并非所有大语言模型的能力都相同!)可以在响应中返回多模态数据。如果调用模型执行此类操作,生成的 AIMessage 将包含多模态类型的内容块。

Multimodal output
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" },
// ]

有关特定供应商的详细信息,请参阅 集成页面。

推理 (Reasoning) ​

许多模型能够执行多步推理以得出结论。这包括将复杂问题分解为更小、更易于管理的步骤。

如果底层模型支持, 你可以暴露出这一推理过程,从而更好地理解模型是如何得出最终答案的。

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(" "));

根据模型的不同,有时你可以指定模型在推理上投入的努力程度(effort)。同样地,你也可以要求模型完全关闭推理。这可以表现为推理的类别“层级”(例如 'low' 或 'high'),或者整数形式的 Token 预算(token budgets)。

有关详细信息,请参阅对应对话模型的 集成页面 或 参考文档。

本地模型 (Local models) ​

LangChain 支持在自有硬件上本地运行模型。这在以下场景中非常有用:数据隐私至关重要、希望调用自定义模型、或者希望避免使用云端模型所产生的费用。

Ollama 是在本地运行对话和嵌入模型最简便的方式之一。

提示词缓存 (Prompt caching) ​

许多供应商提供了提示词缓存功能,以减少重复处理相同 Token 时的延迟和成本。你可以在三个层级启用缓存:

  • 供应商隐式缓存(Implicit provider caching): 如果请求命中缓存,供应商会自动给予费用减免,无需任何额外配置。示例:OpenAI 和 Gemini。
  • 供应商级显式控制(Provider-level explicit controls): 供应商允许你手动指定缓存点,以实现更精细的控制或确保节省成本。这些控制与底层供应商/API 的行为一致。示例:

WARNING

提示词缓存通常只有在超过最小输入 Token 阈值时才会生效。详情请参见 供应商页面。

缓存的使用情况将反映在模型响应的 用量元数据(usage metadata) 中。

服务端工具使用 (Server-side tool use) ​

某些供应商支持服务端 工具调用(tool-calling) 循环:模型可以在单个对话轮次中与网络搜索、代码解释器及其他工具进行交互并分析结果。

如果模型在服务端调用了工具,响应消息的内容中将包含代表该工具调用及其结果的内容。访问响应的 内容块(content blocks) 将以与供应商无关的标准格式返回服务端的工具调用与结果:

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);

这代表了单个对话轮次;无需像客户端 工具调用(tool-calling) 那样传入关联的 ToolMessage 对象。

有关可用工具和使用详情,请参阅指定供应商的 集成页面。

Base URL 与代理设置 (Base URL and proxy settings) ​

你可以为实现了 OpenAI Chat Completions API 的供应商配置自定义 Base URL。

WARNING

model_provider="openai"(或直接使用 ChatOpenAI)针对的是官方 OpenAI API 规范。来自路由器和代理的特定供应商字段可能无法被提取或保留。

对于 OpenRouter 和 LiteLLM,建议使用专用集成:

自定义 Base URL

许多模型供应商提供与 OpenAI 兼容的 API(例如 Together AI、vLLM)。你可以通过指定相应的 base_url 参数,在 initChatModel 中使用这些供应商:

python
model = initChatModel(
    "MODEL_NAME",
    {
        modelProvider: "openai",
        baseUrl: "BASE_URL",
        apiKey: "YOUR_API_KEY",
    }
)

NOTE

当直接实例化对话模型类时,参数名称可能因供应商而异。详情请查看相应的 参考文档。

对数概率 (Log probabilities) ​

某些模型可以通过在初始化模型时设置 logprobs 参数,配置为返回 Token 级别的对数概率,用以表示给定 Token 的出现几率:

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 usage) ​

许多模型供应商会在调用响应中返回 Token 用量信息。当可用时,这些信息将包含在对应模型生成的 AIMessage 对象上。有关更多详细信息,请参阅 消息 指南。

调用配置 (Invocation config) ​

在调用模型时,你可以使用 RunnableConfig 对象通过 config 参数传递额外配置。这提供了对执行行为、回调以及元数据追踪的运行时控制。

常用的配置选项包括:

Invocation with config
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 追踪进行调试
  • 实现自定义日志记录或监控
  • 在生产环境中控制资源用量
  • 在复杂流水线中追踪调用过程

关键配置属性 (Key configuration attributes)

runName string

在日志和追踪中标识本次特定的调用。不会被子调用继承。

tags string[]

被所有子调用继承的标签,用于在调试工具中进行过滤和组织。

metadata object

用于追踪额外上下文的自定义键值对,会被所有子调用继承。

maxConcurrency number

使用 batch() 时控制最大并行调用数。

callbacks CallbackHandler[]

用于在执行期间监控事件并作出响应的处理器。

recursion_limit number

链的最大递归深度,用于防止复杂流水线中出现无限循环。

TIP

查看完整的 RunnableConfig 参考文档以了解所有受支持的属性。

动态模型选择 (Dynamic model selection) ​

动态模型在运行时(智能体的执行环境,包含在整个智能体执行期间持久存在的不可变配置和上下文数据,例如用户 ID、会话详情或特定于应用程序的配置)根据当前状态(在智能体执行期间流动的数据,包括消息、自定义字段以及需要在处理过程中跟踪和可能修改的任何信息,例如用户偏好或工具使用统计)和上下文进行选择。这实现了精细复杂的路由逻辑与成本优化。

要使用动态模型,可以通过 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],
});

有关中间件和高级模式的更多详细信息,请参阅 中间件文档。

TIP

有关模型配置的详细信息,请参阅 模型 (Models)。有关动态模型选择模式,请参阅 中间件中的动态模型。