摘要:大语言模型是 LangChain 应用架构中的核心推理引擎,理解其接口设计、参数体系、调用模式及高级能力是构建可靠智能代理(Agent)的基石。本文以 LangChain 的 init_chat_model 统一接口为切入点,系统梳理模型初始化、参数调优、三种核心调用范式(Invoke/Stream/Batch)、工具绑定与结构化输出机制,并深入探讨模型配置画像、多模态交互、推理链展示、动态模型选择等高级主题。通过理论阐释与代码示例相结合的方式,帮助开发者从“会调用模型”进阶到“能驾驭模型”。

关键字:LangChain;大语言模型;工具调用;结构化输出;智能代理;流式输出;动态模型选择


目录


1. Model 介绍

大语言模型是当代人工智能领域最具变革性的技术之一,它能够像人类一样理解并生成自然语言文本。凭借极强的通用性,大语言模型可胜任内容撰写、语言翻译、文本总结、问题解答等多元化任务,开发者无需再为每一项具体任务单独训练专用模型。

在现代 LLM 应用架构中,模型远不止是一个“文本生成器”。它承载着更丰富的交互能力,主要涵盖以下四个维度:
在这里插入图片描述

  • 工具调用:模型能够主动请求调用外部工具(如数据库查询、API 调用),并将获取的结果融入自身的推理与输出中。
  • 结构化输出:模型的回复可以严格遵循预先设定好的 Schema 格式(如 JSON),便于下游系统进行自动化解析与处理。
  • 多模态能力:部分模型能够处理并输出文本以外的数据,例如图像、音频、视频,实现跨模态的理解与生成。
  • 逻辑推理:模型能够通过多步骤的链式推导来得出结论,将复杂问题拆解为更易处理的子步骤。

在 LangChain 生态中,大语言模型是智能代理的推理核心。它主导着代理的决策流程:判定需要调用哪些工具、解读工具返回的结果、判断何时应该输出最终答复。一个代理的基础表现与可靠性,直接取决于其所选模型的质量与功能适配度。不同模型各有擅长:有的专精复杂指令遵循,有的在结构化逻辑推导上表现优异,还有的支持超长上下文窗口以处理海量信息。因此,深入理解模型接口并将其能力与业务需求精准匹配,是每位 LangChain 开发者的必修课。

2. 模型的基本使用

LangChain 为大语言模型提供了统一且灵活的调用入口,无论你选择哪家服务商,底层接口都保持一致。模型的使用方式主要分为两种模式:

  • 搭配智能代理使用:在创建智能代理时,将模型实例作为其“大脑”动态注入,由代理框架驱动模型的推理与工具调用循环。
  • 独立调用:无需依托代理框架,直接调用模型完成文本生成、分类、信息抽取等单一任务。这种方式适合构建简洁的 NLP 流水线。

两种模式共用同一套模型接口,这为开发者带来了极大的灵活性:你可以从一个简单的独立调用开始验证模型能力,随后再逐步扩展为功能完备的智能代理工作流,无需重写核心逻辑。

初始化模型:

import os
from langchain.chat_models import init_chat_model

os.environ["OPENAI_API_KEY"] = "sk-..."

model = init_chat_model("gpt-5.5")

支持的服务商与模型

LangChain 通过专属集成包兼容当前主流的几乎所有模型服务商。每项供应商配套包均实现统一的标准化接口,因此开发者可以无缝切换服务商,无需重写任何应用逻辑。新增模型名称可即时生效,甚至无需更新 LangChain 版本,这是因为服务商配套包会将模型名称直接透传至对应服务商的 API 端点。

深度解析init_chat_model 的设计哲学是“约定优于配置”。通过一个字符串参数即可完成模型初始化,它内部会根据模型名称自动推断服务商(如 gpt-* 映射到 OpenAI,claude-* 映射到 Anthropic),同时允许通过 model_provider 参数显式指定以消除歧义。这种设计让模型切换的成本趋近于零。

3. 参数

对话模型暴露了一系列参数来配置其运行行为。不同模型和服务商所支持的完整参数集合存在差异,但 LangChain 抽象出了一套通用的标准参数集,能够在跨供应商调用时保持一致的语义。

基础控制参数

  • model:字符串,必填
    要调用的具体模型名称或标识。你也可以通过冒号格式在同⼀个参数中同时指定服务商与模型,例如 "openai:o1"

  • api_key:字符串
    用于向模型服务商进行身份验证的密钥,通常在开通调用权限时发放。强烈建议通过环境变量或密钥管理服务注入,切勿硬编码至源码中。

  • temperature:数值(通常 0–2)
    控制模型输出内容的随机性。数值越高,生成内容越具有创意性和多样性;数值越低,输出结果越确定且可预测。对于事实性问答或代码生成场景,建议设为 0 或接近 0 的值;对于创意写作则可在 0.7–0.9 之间微调。

  • max_tokens:数值
    限制模型在单次响应中能生成的最大令牌数量,直接控制输出文本的长度上限。合理设置此参数可以有效避免不必要的 API 消耗。

连接容错能力

在生产环境中,网络抖动和 API 限流是无法避免的。LangChain 提供了完善的容错机制:

  • timeout:数值
    等待模型返回响应的最长时长(单位:秒),超时后本次请求将被终止。对于多步推理或长文本生成任务,建议适当放宽此值。

  • max_retries:数值,默认值 6
    请求因网络超时、调用频次超限等故障失败时,系统自动重试的最大次数。重试机制内部采用带抖动的指数退避策略,避免在服务端恢复瞬间形成请求风暴。
    触发自动重试的场景包括:网络异常、HTTP 429(限流)状态码、5xx 服务端错误。注意:401(未授权)或 404(资源不存在)等客户端错误不会触发重试。
    如果需要在网络环境不稳定的条件下执行长时间智能代理任务,建议将 max_retries 调整至 10—15。

model = init_chat_model(
    "claude-sonnet-4-6",
    temperature=0.7,
    timeout=120,      # 为慢速连接预留更充裕的等待时间
    max_tokens=1000,
    max_retries=6,    # 默认值;网络不稳定时可调高
)

最佳实践:将超时时间、温度等参数外置为配置文件或环境变量,方便在不同环境(开发/测试/生产)下差异化设置,避免频繁修改代码。

4. 调用

只有真正“调用”模型,才能触发其生成输出。LangChain 提供了三种核心调用方式,分别覆盖单次交互、实时展示和大批量处理的场景。

方式1:invoke()——基础调用

invoke() 是最直接的调用方式,传入单条消息或一个消息列表,返回一个完整的 AIMessage 对象。

response = model.invoke("Why do parrots have colorful feathers?")
print(response)

传递消息列表以携带对话历史:每条消息都附带角色标识(System / User / Assistant),模型以此重构对话上下文。LangChain 支持两种消息列表构建方式:

(1)通过原始字典构建:

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

(2)通过 LangChain 类型化消息对象构建:

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

推荐使用类型化消息对象:它提供了更好的类型安全性和代码可读性,并能在复杂流程中与 LangChain 的其他组件(如 Memory、Prompt Template)无缝协作。

方式2:stream()——流式输出

stream() 方法会返回一个迭代器,每当模型生成一个 token 块时便立即产出,无需等待完整响应。这对于需要实时展示生成过程的场景(如聊天界面)效果尤为显著。

for chunk in model.stream("Why do parrots have colorful feathers?"):
    print(chunk.text, end="|", flush=True)

流式输出的数据结构是 AIMessageChunk 对象序列,每个对象包含一部分输出文本。关键特性:流中每一个分块都可以通过对 chunk.text 的累积拼接,组合成一条与 invoke() 完全对等的完整消息。这意味着你可以将流式输出的消息汇总至对话历史中,作为上下文回传给模型,实现真正的“边输出边记忆”。

方式3:batch()——批量并行请求

当需要对一组互相独立的输入进行批量调用时,batch() 方法可以在客户端并行执行这些请求,显著提升吞吐量并有效降低端到端耗时。

responses = model.batch([
    "Why do parrots have colorful feathers?",
    "How do airplanes fly?",
    "What is quantum computing?"
])
for response in responses:
    print(response)

进阶用法——逐结果返回 batch_as_completed():默认情况下 batch() 会阻塞等待整批数据全部处理完毕后才返回。如果希望在每个独立输入处理完成的时刻就立即获取其输出,可以使用 batch_as_completed()

for response in model.batch_as_completed([
    "Why do parrots have colorful feathers?",
    "How do airplanes fly?",
    "What is quantum computing?"
]):
    print(response)

注意batch_as_completed() 返回结果的顺序可能与提交顺序不一致。每条结果会附带其原始输入索引,你可以通过该索引重新映射回原始数据顺序。

并行并发控制:调用 batch()batch_as_completed() 处理大量输入时,你可能希望限制并行调用的最大数量,以避免触发服务商的速率限制。可以通过 config 中的 max_concurrency 参数来实现:

model.batch(
    list_of_inputs,
    config={
        'max_concurrency': 5,  # 将并行请求上限限制为 5
    }
)

5. 工具调用

赋予模型“使用工具”的能力,是从聊天机器人升级为自主代理的关键一步。通过工具调用,模型可以突破自身的知识截止日期与推理局限,主动向外部世界获取数据、执行计算或操作第三方服务。

工具的双重构成

一个可供模型调用的工具,由两个紧密配套的部分组成:

  1. Schema 定义:包含工具名称、功能描述以及参数定义(通常为 JSON Schema 格式),告诉模型“这个工具能做什么、需要什么参数”。
  2. 执行函数:一段负责实际完成任务的 Python 函数或协程。

工具调用的完整闭环流程

用户输入消息

LLM 分析意图

需要调用工具?

直接生成回复

返回 Tool Call 请求

客户端执行工具函数

将执行结果送回 LLM

最终响应返回用户

为了让自定义工具能够被模型感知并调用,必须使用 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']}")

关键区分:绑定工具后,模型的回复中包含的是“执行工具的请求”,而非执行结果本身。如果你脱离智能代理框架独立使用模型,需要由你来执行被请求的工具,并将执行结果以 ToolMessage 的形式返回给模型,供其进行下一轮推理。而在智能代理模式下,LangChain 代理循环会自动为你处理整套“调用→执行→反馈→再推理”的流程。

6. 结构化输出

很多时候,我们需要模型以固定的、符合 Schema 规范的格式返回结果,以便程序化解析和流水线处理。LangChain 为结构化输出提供了多层抽象,适配不同场景的需求。

Pydantic 模型(推荐方式)

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

结构化输出的关键参数与考量

  • method 参数:不同服务商对结构化输出的底层实现方式不同。你可以通过 method 参数显式指定:
    • "json_schema":调用服务商提供的专用结构化输出 API(最可靠)。
    • "function_calling":通过强制触发符合指定 Schema 的工具调用,间接生成结构化输出。
    • "json_mode":部分服务商早期的 JSON 模式,通常需要在 Prompt 中补充 Schema 描述。
  • 原始内容获取:设置 include_raw=True,可以在返回对象中同时获取解析后的 Pydantic 实例和原始的 AIMessage,便于调试与审计。
  • 校验机制Pydantic 在数据返回时会自动执行类型校验;而 TypedDict 和纯 JSON Schema 方式则需要开发者手动实现校验逻辑。

TypedDict——轻量级替代

对于无需运行时校验的简单场景,TypedDict 提供了更简洁的语法。

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。

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, ...}

7. 高级主题

掌握以下高级能力,能够帮助你构建出更智能、更高效、更可靠的生产级 LLM 应用。

7.1 Model Profile——基于能力的自适应架构

版本要求langchain >= 1.1

model.profile 属性以字典的形式暴露模型自身的能力清单,包括最大输入令牌数、是否支持图像输入、是否具备推理输出能力、是否支持工具调用等。

model.profile
# {
#   "max_input_tokens": 400000,
#   "image_inputs": True,
#   "reasoning_output": True,
#   "tool_calling": True,
#   ...
# }

数据来源:大部分 model.profile 数据由 models.dev 开源项目提供,LangChain 在此基础上添加了应用层拓展字段,并与上游数据源保持同步更新。

实际价值:有了模型的“自描述”能力,应用可以在运行时动态适配不同模型的功能特性,而非为每一种模型硬编码分支逻辑。典型应用场景包括:

  • 自适应摘要中间件:依据模型上下文窗口大小自动判断是否启用文本摘要功能。
  • 智能结构化输出策略create_agent 内部可根据模型是否原生支持结构化输出,自动推导最优的实现方式。
  • 前置输入拦截:根据模型支持的模态类型与最大令牌数,在发送请求前自动裁剪或拒绝不合规的输入。

7.2 Multimodal——超越文本的多模态交互

部分前沿模型已具备处理图像、音频、视频等非文本数据的多模态能力。通过提供 content_blocks 数据结构,你可以向模型传入非文本内容;模型在回复时也能返回多模态数据。

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"},
# ]

应用启示:多模态能力使 LangChain 应用可以构建更丰富的交互体验,例如文档含图摘要、图表生成与解读、以及基于语音和图像的混合查询处理。

7.3 Reasoning——探入模型的“思考”过程

推理(Reasoning)能力使模型能够将复杂问题分解为多步骤的逻辑链条,逐步推导直至得出结论。LangChain 支持在底层模型提供能力的前提下,呈现这套完整的推理过程,让你能透明地理解模型到底“想了什么”。

根据不同模型的实现,你有时可以手动控制推理的深度:这可能是分类式推理档位(如 "low""high"),也可能是整数型的 token 预算。这种可控性在需要平衡推理深度与响应速度的场景中非常有价值。

7.4 Local Model——本地模型集成

对于数据隐私要求极高、需要调用自定义微调模型、或是希望规避云端 API 使用成本的场景,LangChain 也提供了对本地运行模型的一流支持。

Ollama 是目前在本地运行对话模型和嵌入模型最简便的选择之一。LangChain 的 ChatOllama 接口让你可以像调用云端模型一样调用本地模型,仅需将模型初始化参数指向本地服务端点即可。这为构建完全离线或混合架构的应用提供了基础。

7.5 Prompt Caching——降低重复性成本

在智能代理或多轮对话场景中,系统提示词与工具定义通常会在多次交互中保持稳定。许多服务商提供了提示词缓存(Prompt Caching)机制,允许对这部分重复发送的令牌进行复用,从而降低延迟与成本。

LangChain 在以下三个层级提供了对缓存的支持:

  • 服务商隐式缓存:若请求命中缓存,OpenAI、Gemini 等服务商自动减免费用,开发者无需做任何额外配置。
  • 服务商级显式控制:允许手动标记缓存断点,实现更精细的缓存策略。例如 ChatOpenAIprompt_cache_key 参数、Anthropic 的 cache_control 内容块标记。
  • LangChain 中间件:针对智能代理场景,通过中间件自动对固定的系统提示词与工具定义进行缓存优化(如 AnthropicPromptCachingMiddlewareBedrockPromptCachingMiddleware)。

注意:提示词缓存通常在输入令牌数达到一定阈值后才会被自动激活。

7.6 Server-Side Tool Calling——服务端工具调用

部分服务商(如 OpenAI)支持在服务端执行完整的工具调用循环:大模型可在单轮对话内自主调用网页搜索、代码解释器等工具,并对返回结果进行分析,最后统一汇总为回复。

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)
# [
#     {"type": "server_tool_call", "name": "web_search", "args": {...}, "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": [...]}
# ]

关键区别:在服务端工具调用模式下,消息内容块(content_blocks)中同时包含了工具调用记录、执行结果和最终文本回复。这是一个在单轮对话中闭环完成的完整过程,不需要开发者再手动回传 ToolMessage。这会极大简化某些高频交互场景的逻辑复杂度。

7.7 Rate Limiting——优雅地应对 API 限流

几乎所有云服务商都会对指定时间段内的 API 调用次数设置上限。一旦触发限流,服务端会返回错误响应,客户端必须等待一段时间后才能继续发起请求。LangChain 允许在模型初始化时注入一个 rate_limiter,以声明式的方式管理请求发送速率。

from langchain_core.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  
)

局限:当前内置的 InMemoryRateLimiter 仅能根据请求次数进行限流。如果还需要基于请求的 token 大小或输入长度来限制速率,目前的实现还无法满足这一需求。你可以在此基础上实现自定义限流器。

7.8 Token Usage——成本追踪与监控

令牌消耗量是衡量 LLM 应用成本的核心指标。许多模型服务商会在每次 API 响应中返回本次调用的令牌用量详情,LangChain 会自动将这些信息存入生成的 AIMessage 对象的 usage_metadata 属性中。

若需追踪应用内多个模型跨多次调用的总消耗,可以通过回调处理器或上下文管理器进行聚合统计:

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)
# 输出聚合后的各模型令牌消耗统计

7.9 Configurable & Dynamic Models——运行时的灵活度

可配置模型:创建模型时可以通过指定可配置字段,让模型在运行时动态切换身份。若不指定默认值,则 "model""model_provider" 均变为可配置项。

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"}},
)
configurable_model.invoke(
    "what's your name",
    config={"configurable": {"model": "claude-sonnet-4-6"}},
)

动态模型选择中间件:对于更复杂的路由逻辑,可以使用 @wrap_model_call 装饰器创建中间件,根据运行时上下文(如对话长度、用户等级、任务复杂度)动态决定使用哪个模型。

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:
    """根据对话复杂度动态选择模型。"""
    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]
)

重要限制:如果使用了结构化输出(with_structured_output),则不支持预绑定工具(即已调用 bind_tools)的模型作为动态选择的基础模型。请确保传入中间件的模型实例均未经预绑定处理。

8. 结语

从一段简单的 init_chat_model 初始化,到流式输出、批量并行调用,再到工具绑定与结构化输出的精细化控制,直至动态模型选择与多模态交互——LangChain 的模型接口体系以分层、渐进的方式,为开发者铺设了一条从入门到精通的成长路径。

理解模型各项能力的设计意图与适用边界,是在构建复杂 LLM 应用时做出正确架构决策的前提。希望本文能帮助你在驾驭模型时更加从容自信,并为你在 LangChain 生态中的进一步探索打下坚实基础。


参考资料
LangChain Models - Official Documentation

更多推荐