📅 更新日期:2026-06-11


1. LangChain 简介

1.1 LangChain 是什么?

LangChain 不开发大模型,而是为各种大模型提供统一的调用接口和功能封装。 可以把它理解成大模型开发的万能工具箱,把开发 LLM 应用时的常见操作(调用模型、管理提示词、存储对话记忆、分析文档等)封装成标准化的 API,让开发者能像搭积木一样快速构建复杂的 LLM 应用。

1.2 LangChain 的六大核心功能模块

LangChain 的架构围绕六个核心模块展开,每个模块解决 LLM 应用开发中的一个关键环节:

模块 功能说明 类比理解
模型调用(Model I/O) 提供统一接口调用各类大模型 万能遥控器,一键切换不同品牌
提示词工程(Prompt) 管理和复用提示词模板,支持变量插值、少样本示例等 给模型的问题模板库
会话记忆(Memory) 存储和管理多轮对话的上下文历史 给模型配上一个记忆力
文档处理(Retrieval) 加载、分割、向量化外部文档,实现 RAG(检索增强生成) 给模型外挂一个知识库
执行链(Chains) 将多个操作串联成流水线,上一个的输出 → 下一个的输入 工厂流水线,多道工序自动衔接
智能体(Agents) 让模型自主决策调用哪些工具、按什么顺序执行 给模型装上大脑和双手

核心设计理念:我认为 链(Chain)是 LangChain 的灵魂。 LangChain 这个名字本身就包含了 “Chain”(链),它的精髓在于:将多个独立操作串联起来,上一步的输出自动成为下一步的输入。比如:加载文档 → 文本分割 → 生成向量 → 存入数据库 → 检索 → 生成回答,这一整套流程在 LangChain 中可以用几行代码清晰地串联起来。

1.3 链式调用中的内存优化:流式(Stream)机制

一个常见的问题是:链式调用时,上一步的输出是暂存在内存里再传给下一步的吗?如果输出特别大,会不会撑爆内存?

答案是:取决于你使用哪种调用方式。

  • invoke()(阻塞式):默认情况下,上一步的完整结果确实会先完整存储在内存中,再传递给下一步。如果中间结果是一个 10MB 的 JSON,这 10MB 就会完整占据内存。
  • stream()(流式):模型逐 token 生成并返回,数据像水流一样向前推进,每个环节只处理当前这个片段,不需要在内存中一次性缓存完整结果,从而大幅降低内存峰值。

但是需要注意:要实现真正的全链路流式,Chain 中的每一个环节都必须支持流式传递。 如果中间某个环节不支持流式,数据仍然会在那个环节被完整缓存。

一句话总结:选择 stream() 还是 invoke(),取决于你对实时性和内存占用的需求。这在后续的代码实践中会具体体现。


2. 环境安装与依赖解析

2.1 一键安装

pip install langchain langchain-openai langchain-ollama langchain-chroma dashscope chromadb bs4 jq -i https://pypi.tuna.tsinghua.edu.cn/simple

小技巧:使用清华镜像源(-i https://pypi.tuna.tsinghua.edu.cn/simple)可以大幅提升国内用户的下载速度。

2.2 各依赖包的作用

包名 作用 通俗理解
langchain 核心包,提供 LangChain 最核心的功能(链、提示词模板、记忆、init_chat_model 统一入口等) 工具箱的本体
langchain-openai OpenAI 协议适配包,调用所有兼容 OpenAI API 协议的模型(DeepSeek、千问、智谱、OpenAI 官方等)。注意:不限于 OpenAI 公司,任何兼容 OpenAI 接口的服务都可以用它调用 最常用的万能遥控器
langchain-ollama Ollama 支持包,专门用于调用本地 Ollama 部署的大模型 本地模型的专用遥控器
langchain-chroma ChromaDB 支持包,向量数据库适配器,用于 RAG(检索增强生成) 给知识库配备的「搜索引擎接口」
dashscope 阿里云通义千问 Python SDK。SDK(Software Development Kit)即模型厂商提供的官方代码库,封装了认证、请求、响应解析等细节 千问的「官方遥控器」
chromadb ChromaDB 数据库本身,一个轻量级的向量数据库 向量搜索引擎本体
bs4 BeautifulSoup4,HTML 解析库,加载网页文档时用于提取内容 网页内容提取器
jq 轻量灵活的命令行 JSON 处理工具 JSON 数据处理小助手

补充说明:之后我们所说的 langchain.chat_models 是 langchain 核心包内的一个模块(不是独立的 pip 包),init_chat_model() 函数就定义在其中。导入方式为 from langchain.chat_models import init_chat_model。
init_chat_model() 只省记类名和路径的力气,但省不了 pip install,也省不了 API Key 的配置。

2.3 ⚠️ langchain-community 已被淘汰

因为在学习的时候,学习的教程内容是 pip install langchain-community,但是在实践写代码的时候,发现它已被官方淘汰

在 LangChain v1.0(2025 年 10 月发布)之后,langchain-community 的 GitHub 仓库已归档(只读),不再维护。所有模型类已迁移到专用 provider 包:

# ❌ 旧写法(langchain-community,已废弃)
from langchain_community.chat_models import ChatOpenAI

现代 LangChain(v1.0+)的安装策略是:

# 核心包(必装)
pip install langchain langchain-core

# 按需安装厂商专用包用到什么装什么
pip install langchain-openai          # OpenAI / 任何 OpenAI 协议兼容的模型
pip install langchain-deepseek        # DeepSeek 官方集成(v1.0.1,PyPI 月下载量 54 万+)
pip install langchain-ollama          # Ollama 本地模型
pip install langchain-anthropic       # Claude 系列
pip install langchain-google-genai    # Gemini 系列

2.4 init_chat_model():它到底帮你做了什么?

学习的过程中,疑问:init_chat_model 是万能接口吗?我是不是装了它就不用装厂商包了?API Key 它能帮我自动搞定吗?

我们来一步步拆解。

2.4.1 init_chat_model 的本质:一个智能分发器

init_chat_model() 会根据你指定的 "provider:model" 字符串,自动去 import 对应的厂商包(比如 langchain-deepseeklangchain-openai),然后创建对应的模型实例。
所以,你仍然需要提前 pip install 好对应的厂商包。

# 写法1:用独立的厂商类(需要自己记类名和导入路径)
from langchain_deepseek import ChatDeepSeek          # 需要 pip install langchain-deepseek
model = ChatDeepSeek(model="deepseek-chat")

# 写法2:用 init_chat_model(只需一个字符串,内部自动帮你找到 ChatDeepSeek)
from langchain.chat_models import init_chat_model    # 核心包已装
model = init_chat_model("deepseek:deepseek-chat")    # 内部会 import langchain_deepseek(也需要你装)

init_chat_model 帮你省掉的是:记忆每个厂商的类名和导入路径的麻烦,切换厂商只需改一个字符串。

2.4.2 API Key 和环境变量是怎么处理的?

规则很简单init_chat_model 会根据 provider 自动去读对应厂商的环境变量。

provider 自动读取的环境变量 对应的厂商包 备注
openai OPENAI_API_KEY langchain-openai
deepseek DEEPSEEK_API_KEY langchain-deepseek
anthropic ANTHROPIC_API_KEY langchain-anthropic
google_genai GOOGLE_API_KEY langchain-google-genai
ollama 不需要 API Key langchain-ollama 本地服务,默认地址 http://localhost:11434

如果你在代码里显式传了 api_key="sk-xxx",它就优先用你传的;如果不传,就自动去读对应的环境变量。
init_chat_model 不会帮你“变出” API Key,你需要自己申请并设置到环境变量里。

2.4.3 init_chat_model 提供了什么?

  • 自动设置 base_url:比如你写 "deepseek:deepseek-chat",它会自动把 base_url 设为 https://api.deepseek.com,你不需要去查文档。
  • 厂商特有能力的支持:如果安装了厂商专用包,init_chat_model 内部会优先使用专用类(如 ChatDeepSeek),这样就能拿到一些通用接口拿不到的“特产”。比如 DeepSeek R1 模型的 reasoning_content(思考过程),用 ChatOpenAI 套壳是拿不到的。

一个极简的总结

  • init_chat_model("deepseek:deepseek-chat") 时,它自动帮你做了三件事:
    ① 自动 import langchain_deepseek(你需要提前装)
    ② 自动设置 base_url="https://api.deepseek.com"
    ③ 自动读取环境变量 DEEPSEEK_API_KEY
  • 如果你用 ChatOpenAI 去调 DeepSeek,必须手动指定 base_urlapi_key,并且 api_key 的默认环境变量名是 OPENAI_API_KEY,很容易搞混。

3. ChatModel 调用

这是 LangChain 最核心、最常用的模块。我们将从统一入口函数开始,逐步深入到各种调用方式和消息类型。

3.1 初始化模型:init_chat_model

3.1.1 为什么需要 init_chat_model()?

如果按需安装厂商专用包用到什么装什么,切换模型厂商意味着要改类名、改导入路径、甚至改参数名:

# ❌ 旧方式:每个厂商一个类,切换成本高
from langchain_openai import ChatOpenAI       # OpenAI
from langchain_anthropic import ChatAnthropic  # Anthropic
from langchain_ollama import ChatOllama        # Ollama

model = ChatOpenAI(model="gpt-4o")            # 切到 Claude 就得改类名和导入
model = ChatAnthropic(model="claude-sonnet-4-5-20250929")

init_chat_model() 解决了这个痛点:一个函数初始化所有厂商的模型

from langchain.chat_models import init_chat_model

# ===== 方式一:明确指定 provider(推荐,最可靠)=====
model = init_chat_model("openai:gpt-4o")                    # OpenAI
model = init_chat_model("anthropic:claude-sonnet-4-5-20250929")  # Anthropic(固定版本,推荐)
model = init_chat_model("deepseek:deepseek-chat")            # DeepSeek
model = init_chat_model("google_genai:gemini-2.5-flash")     # Gemini
model = init_chat_model("ollama:llama3.1")                   # Ollama 本地

# ===== 方式二:自动推断 provider(仅限知名模型前缀)=====
model = init_chat_model("gpt-4o")              # 自动识别 → openai
model = init_chat_model("claude-sonnet-4-5")   # 自动识别 → anthropic(claude 前缀)
model = init_chat_model("deepseek-chat")        # 自动识别 → deepseek
model = init_chat_model("gemini-2.5-flash")     # 自动识别 → google_genai

格式说明"provider:model_name",冒号前是 provider 标识,冒号后是具体的模型名。provider 标识由对应的 langchain-<provider> 包定义。

关于 Anthropic 模型名:官方推荐使用固定版本 ID(如 claude-sonnet-4-5-20250929),避免使用浮动别名(如 claude-sonnet-4-5)。因为浮动别名可能被 Anthropic 静默升级指向新版本,导致你的应用行为意外变化。同理,OpenAI 的 gpt-4o 也是浮动别名,生产环境建议固定到具体日期版本。

3.1.2 传递模型参数

init_chat_model() 支持两类参数:

① 标准参数(所有厂商通用):

model = init_chat_model(
    "deepseek-chat",              # model_provider 自动推断
    api_key="sk-xxxxxxxxxxxxx",   # API 密钥(不传则自动读环境变量)
    base_url="https://api.deepseek.com",  # 自定义 API 地址(不传则使用厂商默认值)
    temperature=0.5,              # 控制随机性(范围 0~2,0 = 最确定,2 = 最随机)
    max_tokens=1000,              # 最大输出 token 数
    timeout=60,                   # 请求超时秒数
    max_retries=3,                # 失败重试次数
    stop=["\n\n"],                # 停用词,遇到这些词就停止生成
)

temperature 取值指南(范围 0~2,遵循 OpenAI API 规范):

温度区间 效果 适用场景
0 ~ 0.3 输出确定、稳定,几乎每次一致 数据提取、分类、代码生成、翻译
0.4 ~ 0.7 适度创造性,自然但不偏离主题 日常对话、内容总结
0.8 ~ 1.2 输出多样化 创意写作、头脑风暴
1.3 ~ 2.0 非常随机,可能出现意外结果 探索性生成(实际使用较少)

② 非标准参数(厂商特有)—— 用 model_kwargs 透传:

model = init_chat_model(
    "deepseek:deepseek-chat",
    temperature=0.0,
    model_kwargs={
        "top_p": 0.9,               # 核采样参数(厂商特有)
        "frequency_penalty": 0.5,   # 频率惩罚(减少重复)
    }
)

原理model_kwargs 中的参数会被原封不动地合并到发送给模型 API 的请求体中。这样即使某些参数不是 LangChain 标准参数,也能正常传递。你可以把它理解为:“LangChain 不认识这些参数,但请帮我把它们原样传给模型厂商。”


3.2 调用方式

方法 行为 返回值 适用场景 类比
invoke() 阻塞式,等待模型生成完整响应后一次性返回 一个完整的 AIMessage 对象 需要完整结果再继续处理 等人把话全部说完再转述给你
stream() 流式,逐 token 返回 一个生成器/迭代器,每次 yield 一个 AIMessageChunk 需要实时展示(如聊天 UI) 同声传译,来一句翻一句
batch() 阻塞式,客户端并发处理多个请求 list[AIMessage] 大量独立请求,提高吞吐量 同时给多人布置任务,等所有人完成后一起收结果

补充知识 — batch_as_completed():除了 batch(),LangChain 还提供了 batch_as_completed() 方法。它同样是批量处理,但每完成一个请求就立即返回该结果(不等待其他请求完成),结果可能乱序到达。适合需要尽快展示部分结果的场景。

3.2.1 invoke() 基础调用

from langchain.chat_models import init_chat_model

model = init_chat_model(
    model="deepseek-v4-pro"
)

# 传入字符串(内部自动包装成 HumanMessage)
response = model.invoke("Hello, world!")
print(response.content)
# 输出: "Hello, world! How can I help you today?"

3.2.2 stream() 流式输出

response = model.stream("Hello, world!")

for chunk in response:
    print(chunk.content, end="", flush=True)
    # 逐字输出,用户体验更好:不需要盯着空白屏幕等待

代码细节解释:

  • end="":避免 print 默认的换行符导致每个 token 独占一行(否则输出会变成每个字后面都换行)
  • flush=True:强制立即将缓冲区内容输出到屏幕,确保用户能实时看到每个字(否则 Python 可能等缓冲区满了才输出,失去流式意义)

3.2.3 batch() 批量处理

questions = [
    "什么是 Python?",
    "什么是 JavaScript?",
    "什么是 Rust?",
]

responses = model.batch(questions)    # 一次性提交,内部线程池并发处理
for q, r in zip(questions, responses):
    print(f"Q: {q}")
    print(f"A: {r.content}\n")

性能提示batch() 适合需要同时处理大量独立请求的场景。相比循环调用 invoke(),batch 内部使用线程池并发执行,能显著提高吞吐量。你还可以通过 config={"max_concurrency": 5} 控制最大并发数。

注意区分:这里的 batch()客户端并发,不同于 OpenAI 等厂商提供的服务端 Batch API(后者提交任务后异步处理,通常有延迟但费用更低)。


3.2.4 关键问题:invoke() 只能放字符串吗?三种方法的界限是什么?

这是很多初学者困惑的地方。让我来梳理清楚。

答案:invoke()stream()batch() 都可以接收字符串,也都可以接收消息列表。 这两个维度是正交的,调用方式和输入格式是两套独立的分类体系。

用一张图来理解:

        输入格式(传什么)                 调用方式(怎么传)
    ─────────────────────           ─────────────────────
    字符串 "你好"                     invoke()  → 阻塞,返回完整结果
    消息列表 [SystemMessage,          stream()  → 流式,逐 token 返回
              HumanMessage]          batch()   → 批量,一次处理多个

四种合法的组合示例:

from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, SystemMessage

model = init_chat_model(
    model="deepseek-v4-pro"
)

# 组合1:字符串 + invoke
response = model.invoke("你好")
print(response.content)

# 组合2:字符串 + stream
for chunk in model.stream("你好"):
    print(chunk.content, end="", flush=True)

# 组合3:消息列表 + invoke
messages = [
    SystemMessage(content="你是专业的翻译助手"),
    HumanMessage(content="请翻译:Hello world")
]
response = model.invoke(messages)
print(response.content)

# 组合4:消息列表 + stream
for chunk in model.stream(messages):
    print(chunk.content, end="", flush=True)

结论:选择字符串还是消息列表,取决于你是否需要设定系统角色;选择 invoke 还是 stream,取决于你是否需要实时展示。


3.3 使用消息列表:SystemMessage、HumanMessage、AIMessage

当需要设定 AI 的系统角色(行为规则、语气、输出格式等)时,就要传入消息列表而不是简单字符串。

为什么需要传入消息列表而不是简单字符串?

三个核心原因:

  1. 设定系统角色:通过 SystemMessage 控制 AI 的行为风格和输出格式——字符串做不到这一点
  2. 多轮对话:需要把之前的 HumanMessageAIMessage 一同传入,维持对话上下文
  3. 接入 Memory 模块:后续的会话记忆功能要求使用消息列表格式,它是 LangChain 生态的标准数据格式

3.3.1 完整写法

from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, SystemMessage

model = init_chat_model(
    model="deepseek-v4-pro"
)

messages = [
    SystemMessage(content="你是一个专业的代码审查助手,回复请使用 Markdown 格式。"),
    HumanMessage(content="请审查这段代码:def add(a,b): return a+b")
]

response = model.invoke(messages)
print(response.content)

三种消息类型与 OpenAI 协议的对应关系

LangChain 消息类型 OpenAI role 作用 举例
SystemMessage system 设定 AI 的行为规则、角色、输出格式 “你是专业的代码审查助手,回复用 Markdown 格式”
HumanMessage user 用户的问题或指令 “帮我写一个快速排序算法”
AIMessage assistant AI 的回复(多轮对话时用于传入历史回复) “好的,以下是快速排序的实现…”

三种消息在多轮对话中的流转示意:

第1轮:用户输入 → HumanMessage
    模型回复 → AIMessage
第2轮:[SystemMessage, HumanMessage₁, AIMessage₁, HumanMessage₂]
    模型回复 → AIMessage₂
第3轮:[SystemMessage, HM₁, AIM₁, HM₂, AIM₂, HM₃]
    ...

可以看到,每一轮都需要把之前的 HumanMessageAIMessage 全部带上,会话记忆。

3.3.2 简写形式(元组)

LangChain 还支持用元组代替消息对象,代码更简洁:

from langchain.chat_models import init_chat_model


model = init_chat_model(
    model="deepseek-v4-pro"
)

messages = [
    ("system", "你是一个专业的代码审查助手,回复请使用 Markdown 格式。"),
    ("human", "请审查这段代码:def add(a,b): return a+b")
]

response = model.invoke(messages)
print(response.content)

转换规则(LangChain 内部自动完成):

元组写法 自动转换为
('system', '...') SystemMessage(content='...')
('human', '...') HumanMessage(content='...')
('ai', '...') AIMessage(content='...')

优点:少写 import,代码更紧凑直观。

局限:简写只支持这三种基本角色。如果后续用到 ToolMessage(工具调用消息)、FunctionMessage(函数调用消息)等高级类型,还是需要用完整的消息类。另外,元组写法无法携带 nameadditional_kwargs 等附加字段。


3.4 与原生 OpenAI SDK 对照

把 LangChain 的调用方式和原生 OpenAI SDK 放在一起对比,能更清楚地理解 LangChain 做了哪些封装:

原生 OpenAI SDK 方式:

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxx",
    base_url="https://api.deepseek.com"  # 调用 DeepSeek 兼容接口
)

response = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=[
        {"role": "system", "content": "You are a helpful assistant"},
        {"role": "user", "content": "Hello, world!"},
    ],
    stream=False
)
print(response.choices[0].message.content)

LangChain 方式:

from langchain.chat_models import init_chat_model

model = init_chat_model("deepseek:deepseek-v4-pro")

response = model.invoke("Hello, world!")
print(response.content)

对照总结:

步骤 原生 OpenAI SDK LangChain
初始化客户端 OpenAI(api_key=..., base_url=...) init_chat_model("provider:model")ChatOpenAI(model=..., api_key=..., base_url=...)
发起调用 client.chat.completions.create(...) client.invoke(...) / client.stream(...) / client.batch(...)
传入消息 messages=[{"role": ..., "content": ...}](字典列表) 直接传字符串(简单对话)或消息对象列表
获取结果 response.choices[0].message.content response.content
流式控制 通过 stream=True/False 参数切换 通过 invoke() / stream() 两个不同方法切换
代码嵌套层级 3 层(.choices[0].message.content 1 层(.content

3.5 Ollama 本地部署的模型如何使用?

Ollama 让你可以在本地运行开源大模型,无需联网、无需 API Key、完全免费。LangChain 通过 langchain-ollama 包提供了完整的支持。

from langchain.chat_models import init_chat_model

# ===== 方式一:init_chat_model 统一入口(推荐)=====
model = init_chat_model("ollama:llama3.1")    # 自动使用本地 Ollama 服务
# 等价于 init_chat_model("ollama:qwen2.5")   # 切换模型只需要改名字

# ===== 方式二:直接使用 langchain-ollama 包 =====
from langchain_ollama import ChatOllama

model = ChatOllama(
    model="llama3.1",                       # 本地已下载的模型名
    temperature=0.7,
    base_url="http://localhost:11434",      # Ollama 默认地址,一般不需要改
)

response = model.invoke("用一句话解释什么是机器学习")
print(response.content)

前置条件:使用前需要先安装 Ollama 并拉取模型:

# 安装 Ollama(macOS/Linux/Windows 均支持)
# 然后拉取模型
ollama pull llama3.1      # Meta 的 Llama 3.1
ollama pull qwen2.5       # 阿里的通义千问 2.5
ollama pull nomic-embed-text  # 嵌入模型(RAG 用)

# 查看已安装的模型
ollama list

4 嵌入模型调用(Embeddings)

嵌入模型和对话模型有本质区别:对话模型输出文字,嵌入模型输出向量。 两者不能混用,你无法用对话模型来生成向量做语义搜索。

4.1 调用 OpenAI 嵌入模型

from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(
    model="text-embedding-3-small",    # 输出 1536 维向量,性价比高
    # model="text-embedding-3-large",  # 输出 3072 维向量,更精确但更贵
)

vector = embeddings.embed_query("什么是机器学习?")
print(f"向量维度: {len(vector)}")   # 1536
print(f"前5个值: {vector[:5]}")     # 示例:[0.023, -0.145, 0.008, -0.067, 0.034]

4.2 调用 Ollama 本地嵌入模型

from langchain_ollama import OllamaEmbeddings

embeddings = OllamaEmbeddings(
    model="nomic-embed-text",    # 免费本地嵌入模型,输出 768 维向量
)
# 使用前需要先拉取:ollama pull nomic-embed-text

vector = embeddings.embed_query("Hello world!")
print(f"向量维度: {len(vector)}")   # 768

4.3 embed_query vs embed_documents两个方法

# embed_query:对单个查询文本生成向量
query_vec = embeddings.embed_query("如何学 Python?")
# → [0.023, -0.145, 0.008, -0.067, 0.034, ...](一个向量)

# embed_documents:对批量待检索的文档生成向量
doc_vecs = embeddings.embed_documents([
    "Python 是解释型语言",
    "Java 是编译型语言",
    "Rust 是系统编程语言",
])
# → [[0.023, ...], [0.112, ...], [-0.045, ...]](三个向量,每个都是浮点数列表)

为什么要分成两个方法? 因为部分嵌入模型(如 OpenAI 的 text-embedding-3 系列、BGE 系列、E5 系列等)对查询和文档使用不同的编码策略(非对称嵌入),以提升检索精度。

直观理解:查询通常是简短的问句(“怎么学Python?”,可能就几个词),文档则是大段的长文本(几百到几千字)。如果用完全相同的编码方式,「短查询」和「长文档」在向量空间中的分布会有偏差。非对称嵌入就是让模型学会「这是查询格式,用查询编码器处理;那是文档格式,用文档编码器处理」,从而让匹配更准确。

当然,对于简单场景或部分模型(如 nomic-embed-text),两个方法底层可能没什么区别——但有了这个接口设计,切换高级模型时你就无需改代码了。


补充:LLM 、ChatModel、Embedding 三大类的历史问题

在旧教程中学习到:"模型分三大类:LLM 、ChatModel、Embedding。

在 LangChain v1.0 中,这个区分已经是历史问题了。 原因:

  1. BaseLLM 类虽然还存在于 langchain-core 中(兼容考虑),但所有主流厂商包(langchain-openailangchain-anthropic 等)都只提供 BaseChatModel 实现
  2. init_chat_model() 只返回 BaseChatModel 子类实例
  3. 官方文档已经不再提及独立的 LLM 接口
  4. 在 LangChain 0.2.0 中,from langchain.llms import XXX 已经被标记为 deprecated

LangChain 核心架构(本文覆盖范围)

┌─────────────────────────────────────────────────┐
│              模型调用 (Model I/O)                 │
│                                                  │
│  init_chat_model()  ← 统一入口,替代所有厂商类     │
│  ├── invoke()       ← 阻塞,返回完整 AIMessage    │
│  ├── stream()       ← 流式,逐 token 实时输出     │
│  ├── batch()        ← 批量并发,提高吞吐量         │
│  └── batch_as_completed() ← 批量流式,完成即返回   │
│                                                  │
│  输入格式(与调用方式正交,可任意组合):             │
│  ├── 字符串 "你好"                                │
│  ├── 消息列表 [System, Human, AI, ...]            │
│  └── 元组简写 [('system', '...'), ('human', '...')]│
├─────────────────────────────────────────────────┤
│            嵌入模型 (Embeddings)                  │
│  ├── OpenAIEmbeddings    ← 云端(1536/3072 维)   │
│  ├── OllamaEmbeddings    ← 本地(如 768 维)      │
│  ├── embed_query()       ← 单个查询 → 向量        │
│  └── embed_documents()   ← 批量文档 → 向量列表     │
└─────────────────────────────────────────────────┘

以上为个人学习总结,旨在梳理个人理解。如有疏漏或不当之处,欢迎指正与交流。如果文章对你有帮助,别忘了点个赞、留个言,让更多的小伙伴看到~ 我们下篇再见!

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐