我的 LangChain 学习之旅:从核心概念到动手实践

2025 年 9 月 8 日 星期一(已编辑)
15
这篇文章上次修改于 2025 年 9 月 8 日 星期一,可能部分内容已经不适用,如有疑问可询问作者。

我的 LangChain 学习之旅:从核心概念到动手实践

前言

我最近正在学习 LangChain,这是一个强大的大型语言模型(LLM)应用开发框架。为了检验自己的学习水平并明确下一步的方向,我与 AI 进行了一次深入的问答式学习。这篇笔记记录了从评估我的初始认知,到深入理解核心组件,再到解决具体疑惑的全过程。希望我的学习路径和思考,也能为同样走在这条路上的你提供一些参考。

第一站:知识水平评估——我最初的理解

在开始时,我对 LangChain 的理解停留在比较宏观的层面:

  • 核心价值:我认为 LangChain 的价值在于为 LLM 赋能,拓展其能力边界,解决大模型应用开发缓慢的问题。
  • 基础组件
    • Models: 对接 OpenAI 等大模型 API。
    • Prompts: 提示词模板。
    • Output Parsers: 用于结构化输出。
  • RAG 流程:我对检索增强生成(RAG)的流程非常熟悉,即 加载 -> 分割 -> 向量化 -> 存储 -> 检索
  • Chains vs. Agents:我能区分 Chains(确定性流程)和 Agents(动态决策)的区别。

AI 指出了我的知识盲区:Memory(记忆)、LCEL(LangChain 表达式语言)以及 Debugging(调试)。这便是我此行学习的重点。

第二站:核心组件深潜——那些我新学到的关键概念

这是本次学习的核心,我重点掌握了以下几个以前模糊不清或完全不知道的概念。

1. LCEL (LangChain Expression Language) - 现代化的构建方式

这是我此行最大的收获之一。LCEL 是 LangChain 官方推荐的、用于组合组件的声明式方法。

  • 核心语法:使用管道符 | 将组件像流水线一样连接起来。
  • 代码示例:一个简单的“提示+模型+解析器”链。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
  
prompt = ChatPromptTemplate.from_template("请告诉我关于 {topic} 的一个笑话。")
model = ChatOpenAI()
output_parser = StrOutputParser()
  
# 这就是 LCEL 的魔力!
chain = prompt | model | output_parser
  
chain.invoke({"topic": "程序员"})
  • 优势:相比旧版的 Chain 类,LCEL 更简洁、透明,并且原生支持流式(streaming)、并行(parallelism)和异步(async)调用,是现代 LangChain 开发的基石。

2. 调试 LCEL 链 - set_debug(True)

学会了如何构建,下一步就是如何调试。对于 LCEL,verbose=True 的旧方法不再适用。取而代之的是一个强大的全局函数:

  • 启用方法
from langchain.globals import set_debug
  
set_debug(True)
  • 日志解读:开启后,控制台会打印出非常详细的、带颜色的日志。通过 > 符号可以清晰地看到链的嵌套结构,[llm/start][parser/end] 等标签则标明了每个组件的类型、输入、输出和耗时。这对于理解复杂链条的数据流向至关重要。

3. RunnableSequence vs. RunnableParallel - 链的两种基本形态

在解读日志时,我遇到了这两个概念,它们的区别是理解 LCEL 工作流的关键。

  • RunnableSequence (顺序执行):就是由 | 创建的流水线。上一步的输出是下一步的输入,按顺序执行。
  • RunnableParallel (并行执行):通常表现为一个字典。它会将同一个输入分发给字典中的多个处理分支,各分支独立运行,最后将结果汇总成一个字典。它常用于为下一步的 Prompt 准备多个不同的输入变量(如 contextquestion)。

4. RunnableLambda - 流水线上的“DIY”工具

当标准组件不满足需求时,RunnableLambda 就派上了用场。

  • 作用:它可以将任何一个 Python 函数包装成一个可以在 LCEL 链中使用的组件。
  • 应用场景:执行自定义的数据转换、调用外部 API、筛选数据,或者仅仅是在链中某个位置打印中间数据进行调试。在我们的对话式 RAG 示例中,它被用来从 Memory 对象中提取历史聊天记录。

5. Retriever (检索器) - 知识库的“图书管理员”

我之前只知道从向量数据库检索,但对 Retriever 的角色有些模糊。

  • 核心职责:一个专门负责根据查询,从数据源中检索出最相关信息的接口
  • 与 Vector Store 的区别
    • Vector Store (向量数据库) 是存储和搜索的底层工具,是被动的数据库。
    • Retriever (检索器) 是封装了检索逻辑的上层应用接口。它知道“如何去取信息”。
  • 代码示例

    # 从一个向量数据库创建一个检索器
    retriever = vectorstore.as_retriever()

    这个 retriever 对象现在就是一个可以被放入 LCEL 链中的组件了。

第三站:旅途终点与新起点

通过这次深入的探讨学习,我不仅补齐了知识短板,更重要的是建立了一套完整的 LangChain 知识体系。

我的核心收获

  1. 现代化开发范式:我已完全理解 LCEL,并能用它来构建和调试链。这是从“能用”到“会用”的关键一步。
  2. 构建对话应用的核心:掌握了 Memory 组件,我终于可以构建能联系上下文的聊天机器人了。
  3. 洞察内部机制:通过学习解读 debug 日志,我对数据如何在链条中流动有了直观的认识,这让我有能力解决更复杂的问题。

接下来,我将基于今天的学习,继续我的 LangChain 探索之旅:

  • 动手实践:构建一个更复杂的、带有查询重写功能的对话式 RAG Agent。
  • 探索高级功能:研究 LangServe 以便将我的应用部署为 API。

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...