LangChain到底是什么?

一、什么是LangChain

LangChain 既是一个开源框架 ,也是一套工具和库 ,但它的核心定位是框架。以下是结合官方定义和技术架构的详细解析:

既然是开源框架和库,那么它具体有什么用,能做什么?

按照我个人理解来看,LangChain 的核心价值在于------它提供了一个模块化、可插拔的集成框架,将RAG(检索增强生成)流程中的各个关键环节标准化并串联起来,形成一个完整、高效的生产流水线。

  • 数据准备时:xxLoader(PDF、txt、docs等)

  • 数据处理时:xxSplitter(按字符、递归、标记等分割)

  • 数据向量化:xxEmbeddings(OpenAI、智谱、百度千帆等)

  • 数据存储与索引:xxVectorStore(Chroma、Pinecone、Milvus、ES等)

  • 检索时:xxRetriever(向量检索、关键词检索、混合检索、重排序等)

  • 与LLM交互时:xxLLM(各类大模型接口) + xxPrompt(提示词模板) + xxMemory(对话记忆)

  • 流程编排与整合 :Chain(将以上所有环节组装成可执行的流水线,例如 RetrievalQA Chain), LCEL(LangChain表达语言)用于更灵活、可靠的链式构建。

实际意义:

LangChain 的作用是为RAG(及更多LLM应用)提供了一套"标准组件"和"装配蓝图" 。它让开发者无需从零开始造轮子,可以像搭积木一样,快速选择合适的数据加载器、文本分割策略、嵌入模型、向量数据库、检索器和大模型,并通过 Chain 的概念将它们优雅地组装成一个稳定、可维护的应用程序。这极大地降低了构建复杂LLM应用的技术门槛和工程复杂度,实现了真正的"全流程赋能"。

我们来看一个简单的业务流程:

任务目标

构建一个支持多格式文档上传、语义检索和智能问答的知识库系统,实现以下功能:

  1. 自动解析 PDF / 文本 / 网页等格式的文档
  2. 对文档内容进行语义切分和向量存储
  3. 支持基于上下文的智能问答和多轮对话
  4. 提供工具调用能力(如计算器、代码解释器)
流程图说明

PDF 文本 网页 否 是 返回工具调用结果 用户上传文档 文档类型 PyPDFLoader TextLoader WebBaseLoader RecursiveCharacterTextSplitter OllamaEmbeddings FAISS向量存储 用户提问 ConversationalRetrievalChain 检索器 ChatOpenAI模型 是否需要工具 回答用户 PythonAstREPL工具 ConversationBufferMemory

关键组件说明
  1. 文档加载器
    • PyPDFLoader:处理 PDF 文件
    • TextLoader:处理纯文本文件
    • WebBaseLoader:抓取网页内容
  2. 文本处理
    • RecursiveCharacterTextSplitter:按 1000 字符分块,保留 200 字符重叠
  3. 向量存储
    • FAISS:高性能本地向量数据库,支持余弦相似度搜索
  4. 核心链
    • ConversationalRetrievalChain:结合检索器和 LLM,支持多轮对话
  5. 工具调用
    • PythonAstREPLTool:执行 Python 代码,用于数据分析或计算
  6. 记忆模块
    • ConversationBufferMemory:保存最近 5 轮对话历史
技术选型依据
  1. 向量数据库:FAISS 在本地部署场景下具有较高的检索效率,适合中小型知识库
  2. 文本分割:RecursiveCharacterTextSplitter 能在保持语义完整的前提下优化上下文窗口
  3. 工具集成:Python 解释器工具可以扩展系统能力,处理需要动态计算的复杂问题
  4. 模型选择:ChatOpenAI 提供稳定的生成能力,OllamaEmbeddings 支持本地低成本部署

1. 框架的本质:标准化的开发范式

LangChain 的核心价值在于提供了一套结构化的开发框架,帮助开发者高效构建基于大语言模型(LLM)的复杂应用。它通过以下方式实现这一目标:

  • 模块化设计:将应用拆分为可复用的组件(如模型接口、提示模板、工具调用、内存管理等),开发者可像搭积木一样组合这些模块。

  • 标准化接口 :定义统一的交互协议(如 Runnable 接口),允许不同模型(如 OpenAI、Anthropic)、工具(如 SQL 数据库、搜索引擎)和数据源(如 PDF、Notion)无缝集成。

  • 控制流管理 :通过 链(Chains)代理(Agents) 实现多步骤任务编排。例如,链可以串联 "文档检索→信息提取→结果生成" 的流程,而代理能让 LLM 动态决定调用哪些工具(如调用 Wolfram Alpha 进行数学计算)。

  • 全生命周期支持 :从开发阶段的快速原型构建(如用 create_agent 模板生成聊天机器人),到生产阶段的部署(通过 LangServe 转为 API)和监控(通过 LangSmith 追踪模型行为),LangChain 覆盖了应用的完整生命周期。

2. 工具和库的集合:丰富的功能组件

LangChain 提供了大量开箱即用的工具和库,作为框架的 "血肉":

  • 模型集成:支持 1000+ 模型和工具,包括 GPT-4、Gemini、Wolfram Alpha、Pinecone 向量数据库等18。

  • 核心库

    • langchain-core:定义基础抽象(如消息类型、工具接口)和表达式语言(LCEL),用于声明式构建复杂逻辑25。

    • langchain-community:社区贡献的扩展库,涵盖文件加载器、自定义工具等小众需求8。

    • langgraph:用于构建有状态的多智能体应用,支持持久化对话历史和复杂控制流25。

  • 实用工具:如提示优化、输出解析、流式处理等,帮助开发者解决 LLM 应用中的常见痛点35。

3. 开源生态的核心价值

LangChain 采用 MIT 开源协议,允许自由使用和修改,其生态优势体现在:

  • 快速迭代:社区持续贡献新组件(如支持最新向量数据库或 API),开发者无需等待官方更新即可接入前沿技术。

  • 跨平台支持:同时提供 Python 和 JavaScript 版本,适配后端服务、前端应用、边缘计算等多种场景。

  • 企业级落地:通过 LangSmith 进行模型监控和评估,LangServe 实现微服务化部署,降低了从实验到生产的门槛。

4. 与工具库的本质区别

LangChain 与普通工具库的关键差异在于框架的系统性

  • 工具库 (如 Requests、Pandas)解决单一问题(如 HTTP 请求、数据处理),而 LangChain 整合这些工具,形成完整的解决方案。例如,结合 langchain-openai(模型调用)、langchain-sqlite(数据库查询)和 langchain-chains(流程编排),可快速构建一个能回答数据库问题的智能代理。

  • 动态决策能力:LangChain 的代理机制允许 LLM 根据实时反馈调整工具调用策略,而工具库通常需要开发者预先编写固定逻辑

二、LangChain的核心模块

  • LLM和提示(Prompt):统一大模型访问API,同时提供了Prompt提示模板管理机制。

  • 输出解析器(Output Parsers):LangChain接受大模型返回的文本内容之后,可以使用专门的输出解析器对文本内容进行格式化,例如解析json,或者将llm输出的内容转化为Python对象。

  • 链(Chain):对一些常见的场景封装了一些现成的模块,如:基于上下文信息的问答系统,自然语言生成SQL查询等等,因为实现这些任务的过程就像工作流一样,一步步的执行,所以叫链。

  • 表达式语言:LangChain Expression Language(LCEL),新版本特性,用于解决工作流编排问题,通过LCEL表达式,我们可以灵活的自定义AI任务处理流程,也就是灵活自定义链(Chain)。

  • 数据增强生成(RAG):大模型不了解新的信息,为了避免它一本正经的瞎讲,我们将新的信息导入到LLM,用于增强LLM生成的内容质量,这种模式叫做RAG模式

  • Agents:是一种基于大模型的应用设计模式,利用LLM的自然语言理解和推理能力,更具用户的需求自动调用外部系统、设备共同去完成任务,例如:用户输入"明天请假一天",大模型(LLM)自动调用请假系统,发起一个请假申请。

  • 模型记忆(memory):让大模型记住之前的对话内容,这种能力成为模型记忆。

使用LangChain进行大模型开发,需要安装相关包依赖,安装命令:

Bash 复制代码
# LangChain框架安装
pip install langchain
# 版本查看
pip show langchain

LangChain V1.0 vs LangGraph V1.0:分工与定位

  • LangChain :构建 AI 智能体的 最快方式 。提供标准的工具调用架构、供应商无关设计和可插拔的中间件系统,让开发者高效构建通用 Agent。

  • LangGraph :一个 底层运行时框架 ,专为需要长期运行、可控且高定制化的生产级智能体设计。

三、使用LangChain框架,调用AI大模型

构建的工作流用途不同,调用的方式也会稍有区别:

1. 专注于生成单段文本(如回答问题或写一段文字)

Python 复制代码
from config import Config
conf=Config()
#1、openai方式连接大模型
from openai import OpenAI
# 初始化Deepseek的API客户端
client = OpenAI(api_key = conf.API_KEY, base_url="https://api.deepseek.com")
# 调用Deepseek的API,生成回答
response =client.chat.completions.create(model="deepseek-chat'
messages=[
 {"role": "system","content":"你是传智教育的助手传智小智,,请根据用户的问题给出回答"},
 {"role": "user","content":"你好,请你介绍一下你自己。"}
]
# 打印模型最终的响应结果
print(response.choices[0].message.content)

2. 能聊天的应用(如客服机器人或问答系统)

2.1 OpenAI标准库调用:

Python 复制代码
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
# 初始化 ChatOpenAI,配置 DeepSeek API
llm = ChatOpenAI( 
model=conf.MODEL,
api_key=conf.API_KEY,   
base_url=conf.API_URL,
temperature=0.7,
max_tokens=150
)
messages = [SystemMessage(content = "你是一个从事大模型开发多年的工程师,请根据用户的问题给出回答。"),
 HumanMessage(content = "请你用一句话介绍一下LangChain")
]
result = llm.invoke(message)
print(result.content)

2.2 LangChain-模型厂商调用:

Python 复制代码
model = ChatDeepSeek(
model="...",
api_key="...",
api_base="https://DeepSeek.ai/api/v1",
temperature = 0.5
)

区别:在调用DeepSeek等有独立接口的厂商的深度思考模型的时候,使用厂商独立接口可以拿到深度思考的思考过程。

2.3 自定义调用

应用场景:OpenAI标准库不会把深度思考模型的思考过程给你,但你又想使用OpenAI标准库方式来调用大模型,又想获取这个思考过程(俗称犟种)。

问:这几种调用方式都用到了 invoke() 这个函数:这个函数可以传入几种数据类型?

答:三种:字符串、消息对象列表、字典列表。

问:消息对象有几种,都是什么?

答:四种message:AI_message、tool_message、human_message、system_message

四、提示词管理工具类

LangChain封装了一组专门用于提示词(Prompts)管理的工具类,方便我们格式化提示词(prompts)内容,目的是将提示的逻辑(固定结构)与提示的数据(动态变量)彻底分离,从而实现代码的简洁、复用、安全和可维护性。

模板类型 核心作用 输出格式 使用场景
ChatPromptTemplate 现代应用的主力。用于构建包含多个角色(系统、用户、AI)的对话式"剧本" ChatPromptValue(本质是List[BaseMessage]) 所有需要与聊天模型进行结构化、角色化交互的应用
PromptTemplate 基础的字符串模板,将变量填充到单个字符串中。 StringPromptValue(本质是字符串) 构建需要简单文本输入的工具提示。
FewShotChatMessage PromptTemplate 在提示中动态插入多个对话示例,引导模型进行"举一反三",极大提升复杂任务的准确性 ChatPromptValue 需要特定输出格式的复杂任务,如代码生成、简历解析、合同条款提取等等

五、Message

聊天模型(Chat Model)以聊天消息列表作为输入,这个聊天消息列表的消息内容也可以通过提示词模板进行管理。这些聊天消息与原始字符串不同,因为每个消息都与"角色(role)"相关联。

例如,在OpenAI的Chat Completion API中,Openai的聊天模型,给不同的聊天消息定义了三种角色类型分别是助手(assistant)、人类(human)或系统(system)角色:

  • AIMessagePromptTemplate:助手(Assistant)消息指的是当前消息是AI回答的内容。

  • HumanMessagePromptTemplate:人类(user)消息指的是你发给AI的内容。

  • SystemMessagePromptTemplate:系统(system)消息通常是用来给AI身份进行描述。

六、Chain

能被称作LangChain,可想而知,Chain的含金量有多高了吧。Chain,也就是链的意思,指的是按照某一种逻辑,按顺序组合成一个流水线的方式。

Python 复制代码
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
# 初始化 ChatOpenAI,配置 DeepSeek API
llm = ChatOpenAI( 
model=conf.MODEL,
api_key=conf.API_KEY,   
base_url=conf.API_URL,
temperature=0.7,
max_tokens=150
)
# 直接使用模型+ 输出解析器搭建一个链
basic_chain = llm | StrOutputParaser()
'''
这是一个最简单的链式结构,模型+结果解析器
'''
# 查看输出结果
question = "你是哪个?"
result = basic_chain.invoke(question)
print(result)

问:前面有提到LECL,Chain与其有何区别?

答:用最接地气的话讲,核心区别就一个:Chain 是 "固定好的流程模板",LCEL 是 "能自由拼搭的积木语法" ------ 前者帮你把 "做事步骤" 固定死,后者让你随便组合步骤,想怎么搭就怎么搭。

1. Chain:像"现成的组装玩具说明书"

比如你买了个 "乐高小车",Chain 就相当于说明书上写死的步骤:

  1. 先拼车轮(对应 "调用工具查数据");

  2. 再拼车身(对应 "把数据传给 AI 处理");

  3. 最后装车灯(对应 "AI 输出结果")。

它的特点是:

  • 步骤固定死,不能乱改:想在 "拼车身" 后加个 "贴贴纸"(比如加个数据过滤步骤),要么找个带 "贴贴纸" 的新说明书(对应换个现成的 Chain),要么自己拆了原步骤改(代码麻烦);

  • 不用想 "怎么组合":拿来就能用,但只能做说明书上写的事;

  • 种类多但不通用:比如有 "拼小车的 Chain""拼房子的 Chain"(对应 LLMChain、SequentialChain、RouterChain),不同场景要换不同的 Chain,记起来麻烦。

2. LCEL(LangChain Expression Language):像"乐高积木的通用拼接规则"

还是乐高,但 LCEL 不管你想拼车、拼房子还是拼飞船,只给你一套 "怎么拼" 的通用逻辑(比如 "凸点对凹点""长积木可以接短积木"),然后让你随便拿零件组合:

  • 零件就是 "功能模块":比如 "车轮模块""车身模块""贴贴纸模块""查天气模块""AI 生成模块";

  • 拼接用 "简单符号":比如用 "|"(管道符)像 "传接力棒" 一样串步骤,比如:

  • 查天气模块 | 过滤无效数据模块 | AI 推荐活动模块 | 输出结果模块

  • (意思是:先查天气→再筛掉没用的信息→再让 AI 推荐活动→最后告诉用户);

  • 想改就改,想加就加:比如突然想加 "如果下雨就提醒带伞"(条件判断),直接插个 "条件模块" 进去就行;想让 "查天气" 和 "查温度" 同时做(并行),也能直接拼,不用换整套流程。

核心区别对比(一句话总结)

维度 Chain(老方法) LCEL(新方法)
本质 固定的 "流程模板" 灵活的 "积木拼接语法"
用法 找现成模板,按模板做事 拿模块自由组合,自己定流程
灵活性 低:改步骤要换模板 / 改代码 高:随便加、减、换模块,支持条件 / 并行
学习成本 高:要记各种不同类型的 Chain 低:一套语法通吃所有模块
适用场景 简单、固定的流程(比如 "输入→AI 输出") 复杂、多变的流程(比如 "查数据→过滤→条件判断→AI 生成→多轮交互")

最后补个大白话结论:

Chain 是 LangChain 早期的 "老工具",适合新手快速上手简单需求(比如直接让 AI 回答问题);

LCEL 是现在 LangChain 推荐的 "新玩法",相当于把原来 "固定的模板" 拆成了 "可自由组合的零件 + 通用拼接规则",能搞定更复杂的需求,而且用起来更简单(不用记一堆 Chain 类型,靠 "|" 就能串流程)。

那么好,讲完这个区别之后,我们应该来看看:

都有什么链、有什么特点···

1. 串行链

Python 复制代码
# 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
llm = ChatOpenAI(  
    model=conf.MODEL,  
    api_key=conf.API_KEY,  
    base_url=conf.API_URL,  
    temperature=0.7,  
    max_tokens=150  
)  
  
print("--- 1. 串行链 (Sequential Chain) 示例 ---")  
  
# 定义流水线的三个"工位"  
prompt = ChatPromptTemplate.from_template("写一句关于"{topic}"的七言绝句。")  
# llm 在通用环境中已定义  
parser = StrOutputParser()  
# 使用 LCEL `|` 管道符,将三个工位连接成一条串行流水线  
serial_chain = prompt | llm | parser  
print(type(serial_chain))  
  
# 启动流水线,投入原材料  
input_data = {"topic": "月色"}  
result = serial_chain.invoke(input_data)  
  
print(f"【输入】: {input_data}")  
print(f"【最终输出】: {result}")

2. 并行链

Python 复制代码
# langchain_4_2_chain.py (Corrected)  
from langchain.prompts import PromptTemplate  
from config import Config  
import json  
from langchain_openai import ChatOpenAI  
from langchain_core.prompts import ChatPromptTemplate  
from langchain_core.output_parsers import StrOutputParser  
# Import the necessary class  
from langchain_core.runnables import RunnableParallel  
  
# 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
llm = ChatOpenAI(  
    model=conf.MODEL,  
    api_key=conf.API_KEY,  
    base_url=conf.API_URL,  
    temperature=0.7,  
    max_tokens=150  
)  
  
print("\n--- 2. 并行链 (Parallel Chain) 示例 ---")  
  
# 定义两条独立的子流水线  
poem_chain = ChatPromptTemplate.from_template("写一首关于"{topic}"的诗。") | llm | StrOutputParser()  
joke_chain = ChatPromptTemplate.from_template("讲一个关于"{topic}"的俏皮话。") | llm | StrOutputParser()  
  
# 使用 RunnableParallel 将字典结构转换为一个可执行的并行链  
parallel_chain = RunnableParallel({  
    "poem": poem_chain,  
    "joke": joke_chain  
})  
# 启动并行流水线  
input_data = {"topic": "程序员"}  
# Now .invoke() works because parallel_chain is a Runnable object, not a dict  
result = parallel_chain.invoke(input_data)  
  
print(f"【输入】: {input_data}")  
print("【最终输出】:")  
# 结果是一个字典,包含了所有子流水线的输出  
print(json.dumps(result, indent=2, ensure_ascii=False))

3. 分支与RunnablePassthrough()

该函数可以保留一份原本的数据文件

Python 复制代码
# 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
llm = ChatOpenAI(  
    model=conf.MODEL,  
    api_key=conf.API_KEY,  
    base_url=conf.API_URL,  
    temperature=0.7,  
    max_tokens=150  
)  
  
print("\n--- 3. 分支与 RunnablePassthrough 示例 ---")  
  
# 1. 模拟一个检索器  
def fake_retriever(query: str) -> str:  
    """一个模拟的检索器,根据查询返回固定的上下文。"""  
    return f"关于"{query}"的背景知识是:这是一个非常重要的概念。"  
  
# 2. 定义需要同时接收 context 和 question 的 Promptrag_prompt = ChatPromptTemplate.from_template(  
    "根据以下上下文回答问题。\n上下文: {context}\n问题: {question}"  
)  
  
# 3. 构建包含 Passthrough 的并行链  
# 这条链接收一个字符串(问题)作为输入  
# rag_prompt  
chain = {  
    # "context" 分支:对输入运行检索器  
    "context": fake_retriever,  
    # "question" 分支:直接"透传"原始输入  
    "question": RunnablePassthrough()  
} | rag_prompt | llm | StrOutputParser()  
  
print(type(chain))  
# 4. 执行链  
user_question = "LCEL"  
result = chain.invoke(user_question)

4. RunnableLambda自定义

RunnableLambda是一个"适配器",它可以将任何普通的python函数包装成一个标准的LangChain组件,让它无缝接入到LCEL的"|"流水线中。

实现方式:

Python 复制代码
# 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
llm = ChatOpenAI(  
    model=conf.MODEL,  
    api_key=conf.API_KEY,  
    base_url=conf.API_URL,  
    temperature=0.7,  
    max_tokens=150  
)  
  
print("\n--- 4. RunnableLambda 示例 ---")  
  
# 1. 定义一个普通的 Python 函数,它不是标准的 LangChain 组件  
def add_comment(text: str) -> str:  
    """百度官方网站"""  
    return text.strip() + "\n 关于更多信息,欢迎访问:https://www.baidu.com/"  
  
# 2. 使用 RunnableLambda 将其包装成一个"标准工位"  
custom_processor = RunnableLambda(add_comment)  
  
# 3. 构建一条包含自定义工位的串行链  
chain = (  
    ChatPromptTemplate.from_template("请解释一下"{concept}"是什么。最多100字")  
    | llm  
    | StrOutputParser()  
    | custom_processor # 在这里接入我们的自定义函数  
)  
  
# 4. 执行链  
result = chain.invoke({"concept": "大模型"})  
  
print("【最终输出】:")  
print(result)

七、输出解析器(output Parsers)

输出解析器是LangChain"模型I/O"模块中的关键组件。他的核心职责是扮演一个翻译官。

应用程序需要精确、结构化的数据,OutputParser接收LLM返回的文本以后,根据我们预先设定好的规则,将其解析转换为程序可以使用的、干净的结构化数据

解析器名称 核心功能 输出的 Python 类型 工业级应用场景
StrOutputParser 默认解析器。将 LLM 的输出直接解析为字符串。 str 简单的文本生成、内容续写、摘要、翻译等。
JsonOutputParser 极其常用。将 LLM 输出的 JSON 字符串解析为 Python 字典。 dict API 调用 :生成符合 API 规范的 JSON 请求体。 数据提取:从非结构化文本(如邮件、报告)中提取实体信息。
PydanticOutputParser 极其常用。将 LLM 输出解析为预先定义的 Pydantic 对象,提供类型安全和数据验证。 自定义的 pydantic.BaseModel 对象 高可靠性系统 :从简历中提取信息并存入数据库,确保字段类型正确(如年龄是整数)。 配置生成:根据自然语言生成严格的 JSON 配置文件。
CommaSeparatedListParser 将 LLM 输出的、用逗号分隔的文本解析为列表。 list[str] 标签生成 :为文章、产品生成关键词标签。 头脑风暴:生成一系列相关的想法或选项。
DatetimeOutputParser 从文本中智能地解析出日期和时间信息。 datetime.datetime 任务调度 :从 "明天下午三点提醒我开会" 中提取精确时间。 信息归档:从新闻或日志中提取事件发生的时间。

来个实现示例吧,这里我们使用的是JsonOutputParser

python 复制代码
# 确保您已安装必要的库,并已在环境中设置好 API 密钥  
from langchain_openai import ChatOpenAI  
from langchain_core.prompts import ChatPromptTemplate  
from langchain_core.output_parsers import JsonOutputParser, PydanticOutputParser,StrOutputParser  
from pydantic.v1 import BaseModel, Field  
from typing import List  
from config import Config  
conf=Config()  
llm = ChatOpenAI(  
    model=conf.MODEL,  
    api_key=conf.API_KEY,  
    base_url=conf.API_URL,  
    temperature=0.7,  
    max_tokens=150  
)  
  
print("--- 1. JsonOutputParser 示例 ---")  
  
# 1. 创建一个 JsonOutputParser 实例  
json_parser = JsonOutputParser()  
  
# 2. 创建一个 Prompt 模板,并注入格式化指令  
#    .get_format_instructions() 会自动生成告诉 LLM 如何输出 JSON 的指令  
prompt = ChatPromptTemplate.from_template(  
    """从以下文本中提取用户的姓名和城市。  
  
{format_instructions}  
  
文本: {text}"""  
)  
  
# 3. 构建 LCEL 链  
chain = prompt | llm | json_parser  
  
# 4. 准备输入数据  
unstructured_text = "张伟是一位居住在北京的软件工程师,他今年30岁。"  
  
# 5. 调用链并传入格式化指令和文本  
result = chain.invoke({  
    "format_instructions": json_parser.get_format_instructions(),  
    "text": unstructured_text  
})  
  
# 6. 验证输出  
print(f"【输入文本】: {unstructured_text}")  
print(f"【输出类型】: {type(result)}")  
print(f"【解析结果】: {result}")  
# 预期输出:  
# 【输出类型】: <class 'dict'>  
# 【解析结果】: {'name': '张伟', 'city': '北京'}

八、文档加载器(document_loaders)

用于从各种数据源加载文档的组件,旨在将不同格式的文件(文本、PDF、Markdown、Word、PowerPoint等)或数据源(网页、数据库)转换为统一的Document对象。每个Document对象包含page_content(文档内容)和 metadata(元数据,如文件路径、页码等)

加载器名称 支持文件类型 功能描述 模块路径 工业场景应用
TextLoader .txt 加载纯文本文件,支持指定编码(如 UTF-8) langchain_community. document_loaders 解析日志文件、用户指令、配置文件(如设备日志、控制指令)
PyPDFLoader .pdf 加载 PDF 文件,按页面提取文本 langchain_community. document_loaders 提取技术手册、合同、报告内容,生成结构化数据(如设备说明书、质量报告)
Unstructured MarkdownLoader .md 加载 Markdown 文件,保留标题、列表等结构 langchain_community. document_loaders 解析技术文档、API 文档,构建知识库或 RAG 系统(如开发手册、操作指南)
Docx2txtLoader .docx 加载 Word 文档,提取纯文本 langchain_community. document_loaders 处理企业文档、报告、会议记录(如项目计划书、操作规程)
UnstructuredPower PointLoader .ppt, .pptx 加载 PowerPoint 文件,提取幻灯片文本 langchain_community. document_loaders 解析培训材料、演示文档(如技术培训 PPT、产品介绍)
WebBaseLoader 网页 加载网页内容,支持 URL 或 HTML langchain_community. document_loaders 抓取在线技术文档、新闻、产品说明,补充知识库
CSVLoader .csv 加载 CSV 文件,支持按行或列提取数据 langchain_community. document_loaders 解析工业数据表格、传感器数据(如生产数据、设备状态记录)
JSONLoader .json 加载 JSON 文件,提取指定字段或全部内容 langchain_community. document_loaders 解析结构化数据、API 响应(如设备状态 JSON、日志文件)
DirectoryLoader 目录 批量加载目录中的多种文件类型 langchain_community. document_loaders 批量处理企业文档库、混合格式文件(如技术文档、日志文件夹)

来个实现的代码示例吧,这里示例使用的是textloader

python 复制代码
from langchain_community.document_loaders import TextLoader  # 使用新模块路径  
from config import Config  
from langchain_openai import ChatOpenAI  
from datetime import datetime  
  
# 初始化配置和模型  
conf = Config()  
llm = ChatOpenAI(  
    model=conf.MODEL,  # 直接指定模型名称  
    api_key=conf.API_KEY,  
    base_url=conf.API_URL,  
    temperature=0.7,  
    max_tokens=150  
)  
  
# Document Loaders 示例:加载文档并接入大模型总结  
loader = TextLoader(r"D:\LLM_Codes\Chapter3_RAG\rag_base_frame\data\林青霞.txt", encoding="utf-8")  
  
documents = loader.load()  
doc=documents[0]  
  
print("\n--- 1. 加载后的原始元信息 ---")  
print(doc.metadata)  
  
# 1.2 像操作字典一样,为 Document 对象添加自定义元信息  
print("\n--- 2. 添加自定义元信息 ---")  
doc.metadata['author'] = 'DT.L'  
doc.metadata['version'] = '1.1'  
doc.metadata['processed_at'] = datetime.now().isoformat()  
doc.metadata['tags'] = ['test', 'loader', 'metadata']  
  
print("更新后的元信息:")  
print(doc.metadata)  
  
print("\n--- 3. 访问特定的元信息 ---")  
print(f"Author: {doc.metadata.get('author', 'Unknown')}")  
print(f"Tags: {doc.metadata.get('tags')}")  
  
print("\n--- 4. 删除元信息 ---")  
del doc.metadata['version']  
  
print("更新后的元信息:")  
print(doc.metadata)  
print("\n--- 5. 获取文本信息 ---")  
print(doc.page_content)  
# --- 6. 清空文本信息 -不能采用del ---  
print("\n--- 6. 清空文本信息 ---")  
doc.page_content = "" # 正确做法:赋值为空字符串,而不是删除属性  
print("更新后的信息:")  
print(doc)

九、文本分割器

文本分割器是依据字符、结构、语义等规则,将各类格式的文本拆分为适配 LLM 输入、知识库检索等场景的合适片段,辅助后续文本处理的工具。

分割器名称 功能描述 类型 工业场景应用
RecursiveCharacterTextSplitter 递归按字符分割,先尝试自然边界(如段落、句子),太大则继续细分。 通用字符解析 通用文本处理,如日志、报告、PDF 文档分割,便于 RAG 检索。
CharacterTextSplitter 简单按指定分隔符(如换行、逗号)直接分割。 基础字符解析 简单字符串或 CSV 数据处理,如传感器数据日志。
TokenTextSplitter 按 token(词元)分割,支持 LLM token 计数。 Token 基于解析 LLM 输入优化,如处理 API 响应或长查询,控制 token 限制。
MarkdownTextSplitter 按 Markdown 结构(如标题、列表)智能分割。 结构化解析 Markdown 文档分割,保留语义结构,用于知识库构建。
HTMLSplitter 按 HTML 标签(如 、 )分割网页内容。 结构化解析 网页数据爬取,如在线技术文档或新闻提取。
SentenceTextSplitter 按句子边界分割,使用 NLP 识别句子(包括标点)。 语义解析 自然语言文本,如文章或对话分析,保持句子完整。
PythonCodeTextSplitter 按 Python 代码结构(如函数、类)分割。 代码解析 源代码文件分析,如脚本调试或代码库管理。
LatexTextSplitter 按 LaTeX 结构(如章节、公式)分割。 结构化解析 学术论文或数学文档处理。
SpacyTextSplitter 使用 SpaCy NLP 库按句子或实体分割(需安装 SpaCy)。 语义解析 高级 NLP 场景,如实体提取或生物医学文本。
NLTKTextSplitter 使用 NLTK 库按句子或词分割(需安装 NLTK)。 语义解析 文本研究或分析,如时间序列数据描述。

来个示例吧,这里使用的是RecursiveCharacterTextSplitter

python 复制代码
# ----------------------------------------------------  
#               1. 准备环境和依赖库  
# ----------------------------------------------------  
# 确保你已经安装了 langchain# pip install langchain langchain-core  
  
import logging  
from langchain_core.documents import Document  
from langchain.text_splitter import RecursiveCharacterTextSplitter  
  
# ----------------------------------------------------  
#               2. 配置日志  
# ----------------------------------------------------  
# 配置一个简单的日志记录器,方便在控制台清晰地看到输出  
logging.basicConfig(  
    level=logging.INFO,  
    format='%(asctime)s - %(levelname)s - %(message)s'  
)  
log = logging.getLogger(__name__)  
  
  
# ----------------------------------------------------  
#               3. 准备示例文本和Document对象  
# ----------------------------------------------------  
# 模拟一段工业监控报告,这段文本包含了由空行分隔的段落、  
# 由换行符分隔的列表项,以及一个没有内部换行的长句子。  
sample_text = """  
LangChain框架是构建大语言模型应用的核心工具。它提供了模块化的组件和标准化的接口,极大地简化了从数据处理到模型调用和输出解析的整个流程。  
  
在工业监控领域,LangChain展现了巨大潜力。例如,工程师可以利用它快速构建一个RAG系统,该系统能够:  
1. 实时读取设备传感器日志。  
2. 将非结构化的日志文本分割、向量化并存入知识库。  
3. 当检测到异常指标时,自动从知识库中检索相关维护手册和历史故障案例。  
4. 利用LLM分析检索到的信息,并生成一份详细的故障诊断报告和操作建议。  
  
这个过程不仅响应迅速,而且极大地提升了故障排查的准确性和效率。传统的监控系统通常依赖固定的规则和阈值,而基于LangChain的智能系统则能理解日志的深层语义,从而发现更复杂的潜在问题。  
"""  
  
# 将原始文本封装成 LangChain 的 Document 对象  
# metadata 字段可以用来存储文档的来源、ID等元信息  
doc = Document(  
    page_content=sample_text,  
    metadata={"source": "industrial_monitor_log.txt", "id": "doc_001"}  
)  
  
log.info(f"原始文档创建成功,总长度: {len(doc.page_content)} 字符。")  
# print("-" * 80)  
# print(f"原始文档内容:\n{doc.page_content}")  
# print("-" * 80)  
  
  
# ----------------------------------------------------  
#               4. 初始化并使用 RecursiveCharacterTextSplitter# ----------------------------------------------------  
# 初始化递归字符分割器  
# chunk_size: 定义每个文本块(chunk)的最大字符数。这是硬性限制。  
# chunk_overlap: 定义相邻块之间重叠的字符数,用于保持上下文的连续性。  
# separators: 定义了分割文本时尝试使用的分隔符列表,按从左到右的优先级顺序。  
text_splitter = RecursiveCharacterTextSplitter(  
    chunk_size=100,  
    chunk_overlap=50,  
    length_function=len,  
    is_separator_regex=False,  
    separators=["\n\n", "\n", " ", ""] # 默认分隔符,这里显式写出以便理解  
)  
  
# 执行分割操作  
# 注意:split_documents 方法接收一个 Document 列表,返回也是一个 Document 列表  
chunks = text_splitter.split_documents([doc])  
  
  
# ----------------------------------------------------  
#               5. 打印和验证分割结果  
# ----------------------------------------------------  
log.info(f"文本分割完成,共生成 {len(chunks)} 个块(chunks)。")  
print("\n" + "="*80)  
print("                           分割结果展示")  
print("="*80 + "\n")  
  
  
for i, chunk in enumerate(chunks):  
    print(f">>> --- Chunk {i+1} / {len(chunks)} ---")  
    print(f"    源数据 (Metadata): {chunk.metadata}")  
    print(f"    块长度 (Length): {len(chunk.page_content)} characters")  
    print(f"    块内容 (Content):\n\n'{chunk.page_content}'")  
    print("\n" + "-"*80 + "\n")

十、工具

工具是赋予大型语言模型(LLM)与外部世界交互能力的接口。

LangChain 工具调用的实质是让大语言模型(LLM)通过标准化接口动态调用外部工具,扩展自身能力。其核心流程包括:1、意图识别与参数提取,2、工具适配与执行,3、结果格式化反馈16。

示例

用户问 "12345×67890 是多少",LLM 调用内置的CalculatorTool,传入参数 "12345*67890",工具计算后返回结果,LLM 再整理成自然语言回答16。整个过程无需人工干预,工具调用逻辑完全自动化。

代码落地:

python 复制代码
# --- 步骤2: 定义我们的工具 ---@tool  
def multiply(a: int, b: int) -> int:  
    """用于计算两个整数的乘积。"""  
    print(f"正在执行乘法: {a} * {b}")  
    return a * b  
@tool  
def search_weather(city: str) -> str:  
    """用于查询指定城市的实时天气。"""  
    print(f"正在查询天气: {city}")  
    if "北京" in city:  
        return "北京今天是晴天,气温25摄氏度。"  
    elif "上海" in city:  
        return "上海今天是阴天,有小雨,气温22摄氏度。"  
    else:  
        return f"抱歉,我没有'{city}'的天气信息。"

完整代码:

python 复制代码
# -*- coding: utf-8 -*-  
from langchain_openai import ChatOpenAI  
from langchain_core.tools import tool  
from langchain_core.messages import HumanMessage, AIMessage  
  
# --- DeepSeek API 配置 ---# 请替换为你的 DeepSeek API 密钥  
API_KEY = "sk-52****************************"  
API_URL = "https://api.deepseek.com/v1"  
MODEL = "deepseek-chat"  
  
# --- 步骤1: 初始化 ChatOpenAI ---# 虽然我们用的是DeepSeek,但它兼容OpenAI的API格式,所以可以使用ChatOpenAI类  
llm = ChatOpenAI(  
    model=MODEL,  
    api_key=API_KEY,  
    base_url=API_URL,  
    temperature=0.8,  
    max_tokens=300  
)  
  
  
# --- 步骤2: 定义我们的工具 ---
@tool  
def multiply(a: int, b: int) -> int:  
    """用于计算两个整数的乘积。"""  
    print(f"正在执行乘法: {a} * {b}")  
    return a * b  
    
'''
下面的工具中,返回的东西是写死的,真实的业务场景中,会去调用其他数据提供商的api接口来调用实时数据
'''
@tool  
def search_weather(city: str) -> str:  
    """用于查询指定城市的实时天气。"""  
    print(f"正在查询天气: {city}")  
    if "北京" in city:  
        return "北京今天是晴天,气温25摄氏度。"  
    elif "上海" in city:  
        return "上海今天是阴天,有小雨,气温22摄氏度。"  
    else:  
        return f"抱歉,我没有'{city}'的天气信息。"  
  
  
# 将工具列表放入一个变量  
tools = [multiply, search_weather]  
  
# --- 步骤3: 将工具绑定到LLM ---  
# .bind_tools() 方法会将工具的结构信息(名称、描述、参数)传递给模型  
# 这样模型在推理时就知道自己有哪些"超能力"了  
llm_with_tools = llm.bind_tools(tools)  
  
# --- 步骤4: 发起调用 ---# 第一次调用:让模型决定是否以及如何调用工具  
print("--- 第一次调用:模型生成工具调用指令 ---")  
query = "北京今天天气怎么样?另外请帮我计算一下 12乘以8 等于多少?"  
# invoke 方法会返回一个 AIMessage 对象  
# 如果模型决定调用工具,相关信息会储存在 .tool_calls 属性中  
ai_msg = llm_with_tools.invoke(query)  
  
print("模型返回的AIMessage:")  
print(ai_msg)  
print("\n解析出的工具调用请求:")  
print(ai_msg.tool_calls)  
  
# --- 步骤5: 执行工具调用 ---print("\n--- 执行工具调用 ---")  
tool_results = []  
for tool_call in ai_msg.tool_calls:  
    # 根据工具名称找到对应的工具函数  
    tool_name = tool_call["name"]  
    tool_args = tool_call["args"]  
  
    # 查找对应的工具  
    selected_tool = None  
    for t in tools:  
        if t.name == tool_name:  
            selected_tool = t  
            break  
  
    if selected_tool:  
        print(f"执行工具: {tool_name}, 参数: {tool_args}")  
        # 执行工具并获取结果  
        """  
        使用 @tool 装饰器定义函数时,LangChain 会自动将这个普通函数包装成一个 Tool 对象。  
        这个 Tool 类继承了 Runnable 基类,因此具有 invoke() 方法。  
        """        result = selected_tool.invoke(tool_args)  
        tool_results.append({  
            "tool_call_id": tool_call["id"],  
            "name": tool_name,  
            "result": result  
        })  
        print(f"工具执行结果: {result}")  
    else:  
        print(f"未找到工具: {tool_name}")

十一、智能代理(Agent)

Agent内部包含一个LLM和一套工具,他能像一个"思考者"一样,自主规划、决定是否需要调用工具、调用哪个工具、以及如何组织调用顺序,直到最终完成任务。

适用于处理复杂、多步骤的任务,当我们武大确定完成任务需要调用多少次,调用哪些工具时,Agent就是最佳选择~

直接来个代码示例吧:

python 复制代码
# -*- coding: utf-8 -*-  
from langchain_openai import ChatOpenAI  
from langchain_core.tools import tool  
from langchain.agents import create_tool_calling_agent, AgentExecutor  
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder  # 修正:需要导入 MessagesPlaceholder  
# --- 步骤1: DeepSeek API 配置和初始化 ---# 1.1 配置API参数  
API_KEY = "sk-52e226ac3cac46838cb282b45b1a648e"  # 替换为你的实际API密钥  
API_URL = "https://api.deepseek.com/v1"  # DeepSeek API端点  
MODEL = "deepseek-chat"  # 使用的模型名称  
  
# 1.2 初始化ChatOpenAI客户端  
# 虽然使用DeepSeek,但兼容OpenAI API格式  
llm = ChatOpenAI(  
    model=MODEL,  
    api_key=API_KEY,  
    base_url=API_URL,  
    temperature=0,  # 温度参数设为0,使输出更确定性  
    max_tokens=1000  # 增加最大token数以处理更长的响应  
)  
  
  
# --- 步骤2: 定义工具函数 ---# 2.1 定义乘法计算工具  
@tool  
def multiply(a: int, b: int) -> int:  
    """  
    用于计算两个整数的乘积。  
  
    参数:  
        a: 第一个整数  
        b: 第二个整数  
  
    返回:  
        两个整数的乘积  
    """    print(f"正在执行乘法: {a} * {b}")  
    return a * b  
  
  
# 2.2 定义天气查询工具  
@tool  
def search_weather(city: str) -> str:  
    """  
    用于查询指定城市的实时天气。  
  
    参数:  
        city: 城市名称  
  
    返回:  
        该城市的天气信息  
    """    print(f" 正在查询天气: {city}")  
    if "北京" in city:  
        return "北京今天是晴天,气温25摄氏度。"  
    elif "上海" in city:  
        return "上海今天是阴天,有小雨,气温22摄氏度。"  
    elif "广州" in city:  
        return "广州今天是多云,气温28摄氏度。"  
    elif "深圳" in city:  
        return "深圳今天是晴天,气温30摄氏度。"  
    else:  
        return f"抱歉,我没有'{city}'的天气信息。"  
  
  
# 2.3 创建工具列表  
tools = [multiply, search_weather]  
  
# --- 步骤3: 创建Agent提示模板 ---# 3.1 构建提示模板  
# ChatPromptTemplate用于定义对话的结构和内容  
prompt = ChatPromptTemplate.from_messages([  
    # 系统消息:定义AI助手的角色和行为准则  
    ("system", "你是一个乐于助人的AI助手。请根据用户需求选择合适的工具来解决问题。"),  
  
    # 用户输入:{input}是占位符,运行时会被实际用户输入替换  
    ("human", "{input}"),  
  
    # 关键修正:使用MessagesPlaceholder而不是("placeholder", "...")  
    # agent_scratchpad用于存储Agent思考过程中的中间步骤(工具调用和结果)  
    # agent_scratchpad 是 LangChain Agent 框架中一个预定义的、固定的变量名,用于存储Agent思考过程中的中间步骤。  
    MessagesPlaceholder(variable_name="agent_scratchpad"),  
])  
  
# --- 步骤4: 创建工具调用Agent ---  
# 4.1 使用create_tool_calling_agent创建Agent  
# 这个函数将LLM、工具和提示模板组合成一个完整的Agent  
agent = create_tool_calling_agent(  
    llm=llm,  # 语言模型  
    tools=tools,  # 可用工具列表  
    prompt=prompt  # 提示模板  
)  
  
# --- 步骤5: 创建Agent执行器 ---# 5.1 创建AgentExecutor  
# AgentExecutor负责管理Agent的执行循环:思考->调用工具->整合结果->继续思考  
agent_executor = AgentExecutor(  
    agent=agent,  # 要执行的Agent  
    tools=tools,  # 可用工具列表  
    verbose=True,  # 开启详细日志,显示Agent的思考过程  
    handle_parsing_errors=True,  # 自动处理解析错误  
    max_iterations=5  # 最大迭代次数,防止无限循环  
)  
  
# --- 步骤6: 运行Agent处理任务 ---print("=" * 60)  
print("=" * 60)  
  
# 6.1 处理单步任务  
print("\n--- 运行Agent处理单步任务 ---")  
print("用户问题: 上海今天天气怎么样?")  
response1 = agent_executor.invoke({"input": "上海今天天气怎么样?"})  
print("\n 最终回答:")  
print(response1["output"])  
  
# 6.2 处理多步任务  
print("\n" + "=" * 60)  
print("--- 运行Agent处理多步任务 ---")  
print("用户问题: 先帮我查一下北京的天气,然后计算 35 乘以 3 的结果是多少?")  
response2 = agent_executor.invoke({  
    "input": "先帮我查一下北京的天气,然后计算 35 乘以 3 的结果是多少?"  
})  
print("\n最终回答:")  
print(response2["output"])  
  
# 6.3 处理更复杂的任务  
print("\n" + "=" * 60)  
print("--- 运行Agent处理复杂任务 ---")  
print("用户问题: 请告诉我广州的天气,然后计算23乘以4,最后告诉我深圳的天气")  
response3 = agent_executor.invoke({  
    "input": "请告诉我广州的天气,然后计算23乘以4,最后告诉我深圳的天气"  
})  
print("\n最终回答:")  
print(response3["output"])  
  
print("\n" + "=" * 60)

十二、记忆模块

默认情况下,大模型是无状态的,也就是它不会记住你之前的任何交互。所以每一次提问都是一次全新的、独立的对话。
记忆模块 的作用就是赋予LLM上下文感知能力。通过存储、管理和传递历史对话信息,让LLM能够"记住"之前的交流内容,从而实现连贯的、有逻辑的多轮对话。

对比维度 ConversationBufferMemory ConversationBufferWindowMemory
核心机制 完整保留全部对话历史(用户提问 + AI 回复),无自动清理逻辑 仅保留最近 N 轮对话(N 为窗口大小,可配置),自动丢弃早期历史
优点 1. 上下文完整性最高,可回溯任意早期对话信息; 2. 配置简单(无需设置窗口大小); 3. 无信息丢失风险,适合依赖长历史的任务 1. 严格控制 Token 消耗,降低 API 成本; 2. 减少冗余信息,提升模型响应速度; 3. 灵活适配不同对话长度需求(调整 N 值); 4. 避免历史信息过载导致的模型逻辑偏移
缺点 1. 对话越长,Token 消耗越大,成本越高; 2. 长历史可能包含冗余信息,拖慢响应速度; 3. 极端长对话可能触发模型 Token 上限(如 GPT-3.5 的 4k/8k 上下文); 4. 历史信息过载可能导致模型聚焦性下降 1. 无法回溯窗口外的早期对话,可能丢失关键历史信息; 2. 需手动调试窗口大小(N 过小可能缺失必要上下文,N 过大则失去窗口意义); 3. 短窗口场景下,模型无法感知远期对话逻辑
适用场景 1. 短对话交互(如单轮 / 3-5 轮问答、简单咨询); 2. 需完整回溯历史的任务(如复杂问题拆解、多步骤协作、上下文依赖强的推理); 3. 对 Token 成本不敏感、追求上下文完整性的场景 1. 长对话场景(如客服对话、多轮聊天、持续任务协作); 2. 对 Token 成本和响应速度敏感的场景(如批量交互、高频调用); 3. 仅需基于近期上下文决策的任务(如日常聊天、即时咨询、短期任务跟进); 4. 模型上下文窗口有限的场景(如使用 4k 上下文的模型处理长对话)
Token 消耗 随对话长度线性增长(无上限,除非手动清理) Token 消耗稳定在窗口大小对应的范围(可控)
配置难度 低(仅需初始化,无需额外参数) 中(需合理设置 k 参数,如 k=5 表示保留最近 5 轮)

至此我们才算是大概的过了一遍LangChain都有什么组件,这些组件的作用和如何使用,还有其他的组件比如embedding Models、Retrievers等等我们不再详细介绍,自己补充一下吧~~

相关推荐
一水鉴天33 分钟前
整体设计 定稿 之16 三层智能合约体系实现设计和开发的实时融合
前端·人工智能·架构·智能合约
HAPPY酷37 分钟前
技术沟通的底层逻辑:用结构化方法提升协作效率
大数据·人工智能
java_logo38 分钟前
Prometheus Docker 容器化部署指南
运维·人工智能·docker·容器·prometheus·ai编程
非著名架构师40 分钟前
【光伏功率预测】EMD 分解 + PCA 降维 + LSTM 的联合建模与 Matlab 实现
人工智能·matlab·lstm·高精度光伏功率预测模型
Aspect of twilight40 分钟前
KNN分类器与K-means无监督聚类详解
人工智能·机器学习·kmeans·knn
nn在炼金1 小时前
FlashAttention 1 深度解读:原理、价值、应用与实战
人工智能·算法
沐雪轻挽萤1 小时前
pytorch模型部署基础知识
人工智能·pytorch·python
极客BIM工作室1 小时前
从GAN到Sora:生成式AI在图像与视频领域的技术演进全景
人工智能·生成对抗网络·计算机视觉
nix.gnehc1 小时前
PyTorch数据加载与预处理
人工智能·pytorch·python