开启左侧

LangChain到底是什么?

[复制链接]
KosSashaHelloWo 发表于 5 小时前 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
作者:Peter_Monster
关键组件说明


  • 文档加载器
      PyPDFLoader:处理 PDF 文件TextLoader:处理纯文本文件WebBaseLoader:抓取网页内容

  • 文本处理
      RecursiveCharacterTextSplitter:按 1000 字符分块,保留 200 字符重叠

  • 向量存储
      FAISS:高性能本地向量数据库,支持余弦相似度搜索

  • 核心链
      ConversationalRetrievalChain:结合检索器和 LLM,支持多轮对话

  • 工具调用
      PythonAstREPLTool:执行 Python 代码,用于数据分析或计算

  • 记忆模块
      ConversationBufferMemory:保存最近 5 轮对话历史

技术选型依据

    向量数据库:FAISS 在本地部署场景下具有较高的检索效率,适合中小型知识库文本分割:RecursiveCharacterTextSplitter 能在保持语义完整的前提下优化上下文窗口工具集成:Python 解释器工具可以扩展系统能力,处理需要动态计算的复杂问题模型选择: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进行大模型开发,需要安装相关包依赖,安装命令:
  1. # LangChain框架安装
  2. pip install langchain
  3. # 版本查看
  4. pip show langchain
复制代码
LangChain V1.0 vs LangGraph V1.0:分工与定位

    LangChain :构建 AI 智能体的 最快方式 。提供标准的工具调用架构、供应商无关设计和可插拔的中间件系统,让开发者高效构建通用 Agent。
    LangGraph :一个 底层运行时框架 ,专为需要长期运行、可控且高定制化的生产级智能体设计。
三、使用LangChain框架,调用AI大模型

构建的工作流用途不同,调用的方式也会稍有区别:
1. 专注于生成单段文本(如回答问题或写一段文字)
  1. from config import Config
  2. conf=Config()
  3. #1、openai方式连接大模型
  4. from openai import OpenAI
  5. # 初始化Deepseek的API客户端
  6. client = OpenAI(api_key = conf.API_KEY, base_url="https://api.deepseek.com")
  7. # 调用Deepseek的API,生成回答
  8. response =client.chat.completions.create(model="deepseek-chat'
  9. messages=[
  10. {"role": "system","content":"你是传智教育的助手传智小智,,请根据用户的问题给出回答"},
  11. {"role": "user","content":"你好,请你介绍一下你自己。"}
  12. ]
  13. # 打印模型最终的响应结果
  14. print(response.choices[0].message.content)
复制代码
2. 能聊天的应用(如客服机器人或问答系统)

2.1 OpenAI标准库调用:
  1. from langchain_openai import ChatOpenAI
  2. from langchain.schema import HumanMessage, SystemMessage
  3. # 初始化 ChatOpenAI,配置 DeepSeek API
  4. llm = ChatOpenAI(
  5. model=conf.MODEL,
  6. api_key=conf.API_KEY,   
  7. base_url=conf.API_URL,
  8. temperature=0.7,
  9. max_tokens=150
  10. )
  11. messages = [SystemMessage(content = "你是一个从事大模型开发多年的工程师,请根据用户的问题给出回答。"),
  12. HumanMessage(content = "请你用一句话介绍一下LangChain")
  13. ]
  14. result = llm.invoke(message)
  15. print(result.content)
复制代码
2.2 LangChain-模型厂商调用:
  1. model = ChatDeepSeek(
  2. model="...",
  3. api_key="...",
  4. api_base="https://DeepSeek.ai/api/v1",
  5. temperature = 0.5
  6. )
复制代码
区别:在调用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,也就是链的意思,指的是按照某一种逻辑,按顺序组合成一个流水线的方式。
  1. from langchain_openai import ChatOpenAI
  2. from langchain.schema import HumanMessage, SystemMessage
  3. # 初始化 ChatOpenAI,配置 DeepSeek API
  4. llm = ChatOpenAI(
  5. model=conf.MODEL,
  6. api_key=conf.API_KEY,   
  7. base_url=conf.API_URL,
  8. temperature=0.7,
  9. max_tokens=150
  10. )
  11. # 直接使用模型+ 输出解析器搭建一个链
  12. basic_chain = llm | StrOutputParaser()
  13. '''
  14. 这是一个最简单的链式结构,模型+结果解析器
  15. '''
  16. # 查看输出结果
  17. question = "你是哪个?"
  18. result = basic_chain.invoke(question)
  19. print(result)
复制代码
问:前面有提到LECL,Chain与其有何区别?
答:用最接地气的话讲,核心区别就一个:Chain 是 “固定好的流程模板”,LCEL 是 “能自由拼搭的积木语法” —— 前者帮你把 “做事步骤” 固定死,后者让你随便组合步骤,想怎么搭就怎么搭。
1. Chain:像“现成的组装玩具说明书”

比如你买了个 “乐高小车”,Chain 就相当于说明书上写死的步骤:
    先拼车轮(对应 “调用工具查数据”);
    再拼车身(对应 “把数据传给 AI 处理”);
    最后装车灯(对应 “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. 串行链
  1. # 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
  2. llm = ChatOpenAI(  
  3.     model=conf.MODEL,  
  4.     api_key=conf.API_KEY,  
  5.     base_url=conf.API_URL,  
  6.     temperature=0.7,  
  7.     max_tokens=150  
  8. )  
  9.   
  10. print("--- 1. 串行链 (Sequential Chain) 示例 ---")  
  11.   
  12. # 定义流水线的三个“工位”  
  13. prompt = ChatPromptTemplate.from_template("写一句关于“{topic}”的七言绝句。")  
  14. # llm 在通用环境中已定义  
  15. parser = StrOutputParser()  
  16. # 使用 LCEL `|` 管道符,将三个工位连接成一条串行流水线  
  17. serial_chain = prompt | llm | parser  
  18. print(type(serial_chain))  
  19.   
  20. # 启动流水线,投入原材料  
  21. input_data = {"topic": "月色"}  
  22. result = serial_chain.invoke(input_data)  
  23.   
  24. print(f"【输入】: {input_data}")  
  25. print(f"【最终输出】: {result}")
复制代码
2. 并行链
  1. # langchain_4_2_chain.py (Corrected)  
  2. from langchain.prompts import PromptTemplate  
  3. from config import Config  
  4. import json  
  5. from langchain_openai import ChatOpenAI  
  6. from langchain_core.prompts import ChatPromptTemplate  
  7. from langchain_core.output_parsers import StrOutputParser  
  8. # Import the necessary class  
  9. from langchain_core.runnables import RunnableParallel  
  10.   
  11. # 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
  12. llm = ChatOpenAI(  
  13.     model=conf.MODEL,  
  14.     api_key=conf.API_KEY,  
  15.     base_url=conf.API_URL,  
  16.     temperature=0.7,  
  17.     max_tokens=150  
  18. )  
  19.   
  20. print("\n--- 2. 并行链 (Parallel Chain) 示例 ---")  
  21.   
  22. # 定义两条独立的子流水线  
  23. poem_chain = ChatPromptTemplate.from_template("写一首关于“{topic}”的诗。") | llm | StrOutputParser()  
  24. joke_chain = ChatPromptTemplate.from_template("讲一个关于“{topic}”的俏皮话。") | llm | StrOutputParser()  
  25.   
  26. # 使用 RunnableParallel 将字典结构转换为一个可执行的并行链  
  27. parallel_chain = RunnableParallel({  
  28.     "poem": poem_chain,  
  29.     "joke": joke_chain  
  30. })  
  31. # 启动并行流水线  
  32. input_data = {"topic": "程序员"}  
  33. # Now .invoke() works because parallel_chain is a Runnable object, not a dict  
  34. result = parallel_chain.invoke(input_data)  
  35.   
  36. print(f"【输入】: {input_data}")  
  37. print("【最终输出】:")  
  38. # 结果是一个字典,包含了所有子流水线的输出  
  39. print(json.dumps(result, indent=2, ensure_ascii=False))
复制代码
3. 分支与RunnablePassthrough()

该函数可以保留一份原本的数据文件
  1. # 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
  2. llm = ChatOpenAI(  
  3.     model=conf.MODEL,  
  4.     api_key=conf.API_KEY,  
  5.     base_url=conf.API_URL,  
  6.     temperature=0.7,  
  7.     max_tokens=150  
  8. )  
  9.   
  10. print("\n--- 3. 分支与 RunnablePassthrough 示例 ---")  
  11.   
  12. # 1. 模拟一个检索器  
  13. def fake_retriever(query: str) -> str:  
  14.     """一个模拟的检索器,根据查询返回固定的上下文。"""  
  15.     return f"关于“{query}”的背景知识是:这是一个非常重要的概念。"  
  16.   
  17. # 2. 定义需要同时接收 context 和 question 的 Promptrag_prompt = ChatPromptTemplate.from_template(  
  18.     "根据以下上下文回答问题。\n上下文: {context}\n问题: {question}"  
  19. )  
  20.   
  21. # 3. 构建包含 Passthrough 的并行链  
  22. # 这条链接收一个字符串(问题)作为输入  
  23. # rag_prompt  
  24. chain = {  
  25.     # "context" 分支:对输入运行检索器  
  26.     "context": fake_retriever,  
  27.     # "question" 分支:直接“透传”原始输入  
  28.     "question": RunnablePassthrough()  
  29. } | rag_prompt | llm | StrOutputParser()  
  30.   
  31. print(type(chain))  
  32. # 4. 执行链  
  33. user_question = "LCEL"  
  34. result = chain.invoke(user_question)
复制代码
4. RunnableLambda自定义

RunnableLambda是一个“适配器”,它可以将任何普通的python函数包装成一个标准的LangChain组件,让它无缝接入到LCEL的“|”流水线中。
实现方式:
  1. # 初始化 ChatOpenAI,配置 DeepSeek APIconf=Config()  
  2. llm = ChatOpenAI(  
  3.     model=conf.MODEL,  
  4.     api_key=conf.API_KEY,  
  5.     base_url=conf.API_URL,  
  6.     temperature=0.7,  
  7.     max_tokens=150  
  8. )  
  9.   
  10. print("\n--- 4. RunnableLambda 示例 ---")  
  11.   
  12. # 1. 定义一个普通的 Python 函数,它不是标准的 LangChain 组件  
  13. def add_comment(text: str) -> str:  
  14.     """百度官方网站"""  
  15.     return text.strip() + "\n 关于更多信息,欢迎访问:https://www.baidu.com/"  
  16.   
  17. # 2. 使用 RunnableLambda 将其包装成一个“标准工位”  
  18. custom_processor = RunnableLambda(add_comment)  
  19.   
  20. # 3. 构建一条包含自定义工位的串行链  
  21. chain = (  
  22.     ChatPromptTemplate.from_template("请解释一下“{concept}”是什么。最多100字")  
  23.     | llm  
  24.     | StrOutputParser()  
  25.     | custom_processor # 在这里接入我们的自定义函数  
  26. )  
  27.   
  28. # 4. 执行链  
  29. result = chain.invoke({"concept": "大模型"})  
  30.   
  31. print("【最终输出】:")  
  32. print(result)
复制代码
七、输出解析器(output Parsers)

输出解析器是LangChain“模型I/O”模块中的关键组件。他的核心职责是扮演一个翻译官。
应用程序需要精确、结构化的数据,OutputParser接收LLM返回的文本以后,根据我们预先设定好的规则,将其解析转换为程序可以使用的、干净的结构化数据
解析器名称核心功能输出的 Python 类型工业级应用场景
StrOutputParser默认解析器。将 LLM 的输出直接解析为字符串。str简单的文本生成、内容续写、摘要、翻译等。
JsonOutputParser极其常用。将 LLM 输出的 JSON 字符串解析为 Python 字典。dictAPI 调用:生成符合 API 规范的 JSON 请求体。

数据提取:从非结构化文本(如邮件、报告)中提取实体信息。
PydanticOutputParser极其常用。将 LLM 输出解析为预先定义的 Pydantic 对象,提供类型安全和数据验证。自定义的 pydantic.BaseModel 对象高可靠性系统:从简历中提取信息并存入数据库,确保字段类型正确(如年龄是整数)。

配置生成:根据自然语言生成严格的 JSON 配置文件。
CommaSeparatedListParser将 LLM 输出的、用逗号分隔的文本解析为列表。list[str]标签生成:为文章、产品生成关键词标签。

头脑风暴:生成一系列相关的想法或选项。
DatetimeOutputParser从文本中智能地解析出日期和时间信息。datetime.datetime任务调度:从 “明天下午三点提醒我开会” 中提取精确时间。

信息归档:从新闻或日志中提取事件发生的时间。
来个实现示例吧,这里我们使用的是JsonOutputParser:
  1. # 确保您已安装必要的库,并已在环境中设置好 API 密钥  from langchain_openai import ChatOpenAI  
  2. from langchain_core.prompts import ChatPromptTemplate  
  3. from langchain_core.output_parsers import JsonOutputParser, PydanticOutputParser,StrOutputParser  
  4. from pydantic.v1 import BaseModel, Field  
  5. from typing import List  
  6. from config import Config  
  7. conf=Config()  
  8. llm = ChatOpenAI(  
  9.     model=conf.MODEL,  
  10.     api_key=conf.API_KEY,  
  11.     base_url=conf.API_URL,  
  12.     temperature=0.7,  
  13.     max_tokens=150)print("--- 1. JsonOutputParser 示例 ---")# 1. 创建一个 JsonOutputParser 实例  
  14. json_parser = JsonOutputParser()# 2. 创建一个 Prompt 模板,并注入格式化指令  #    .get_format_instructions() 会自动生成告诉 LLM 如何输出 JSON 的指令  
  15. prompt = ChatPromptTemplate.from_template("""从以下文本中提取用户的姓名和城市。  
  16.   
  17. {format_instructions}  
  18.   
  19. 文本: {text}""")# 3. 构建 LCEL 链  
  20. chain = prompt | llm | json_parser  
  21.   
  22. # 4. 准备输入数据  
  23. unstructured_text ="张伟是一位居住在北京的软件工程师,他今年30岁。"# 5. 调用链并传入格式化指令和文本  
  24. result = chain.invoke({"format_instructions": json_parser.get_format_instructions(),"text": unstructured_text  
  25. })# 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 或 HTMLlangchain_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:
  1. from langchain_community.document_loaders import TextLoader  # 使用新模块路径  from config import Config  
  2. from langchain_openai import ChatOpenAI  
  3. from datetime import datetime  
  4.   
  5. # 初始化配置和模型  
  6. conf = Config()  
  7. llm = ChatOpenAI(  
  8.     model=conf.MODEL,# 直接指定模型名称  
  9.     api_key=conf.API_KEY,  
  10.     base_url=conf.API_URL,  
  11.     temperature=0.7,  
  12.     max_tokens=150)# Document Loaders 示例:加载文档并接入大模型总结  
  13. loader = TextLoader(r"D:\LLM_Codes\Chapter3_RAG\rag_base_frame\data\林青霞.txt", encoding="utf-8")  
  14.   
  15. documents = loader.load()  
  16. doc=documents[0]print("\n--- 1. 加载后的原始元信息 ---")print(doc.metadata)# 1.2 像操作字典一样,为 Document 对象添加自定义元信息  print("\n--- 2. 添加自定义元信息 ---")  
  17. doc.metadata['author']='DT.L'  
  18. doc.metadata['version']='1.1'  
  19. doc.metadata['processed_at']= datetime.now().isoformat()  
  20. 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. 清空文本信息 ---")  
  21. 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:
  1. # ----------------------------------------------------  #               1. 准备环境和依赖库  # ----------------------------------------------------  # 确保你已经安装了 langchain# pip install langchain langchain-core  import logging  
  2. from langchain_core.documents import Document  
  3. from langchain.text_splitter import RecursiveCharacterTextSplitter  
  4.   
  5. # ----------------------------------------------------  #               2. 配置日志  # ----------------------------------------------------  # 配置一个简单的日志记录器,方便在控制台清晰地看到输出  
  6. logging.basicConfig(  
  7.     level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s')  
  8. log = logging.getLogger(__name__)# ----------------------------------------------------  #               3. 准备示例文本和Document对象  # ----------------------------------------------------  # 模拟一段工业监控报告,这段文本包含了由空行分隔的段落、  # 由换行符分隔的列表项,以及一个没有内部换行的长句子。  
  9. sample_text ="""  
  10. LangChain框架是构建大语言模型应用的核心工具。它提供了模块化的组件和标准化的接口,极大地简化了从数据处理到模型调用和输出解析的整个流程。  
  11.   
  12. 在工业监控领域,LangChain展现了巨大潜力。例如,工程师可以利用它快速构建一个RAG系统,该系统能够:  
  13. 1. 实时读取设备传感器日志。  
  14. 2. 将非结构化的日志文本分割、向量化并存入知识库。  
  15. 3. 当检测到异常指标时,自动从知识库中检索相关维护手册和历史故障案例。  
  16. 4. 利用LLM分析检索到的信息,并生成一份详细的故障诊断报告和操作建议。  
  17.   
  18. 这个过程不仅响应迅速,而且极大地提升了故障排查的准确性和效率。传统的监控系统通常依赖固定的规则和阈值,而基于LangChain的智能系统则能理解日志的深层语义,从而发现更复杂的潜在问题。  
  19. """# 将原始文本封装成 LangChain 的 Document 对象  # metadata 字段可以用来存储文档的来源、ID等元信息  
  20. doc = Document(  
  21.     page_content=sample_text,  
  22.     metadata={"source":"industrial_monitor_log.txt","id":"doc_001"})  
  23.   
  24. 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: 定义了分割文本时尝试使用的分隔符列表,按从左到右的优先级顺序。  
  25. text_splitter = RecursiveCharacterTextSplitter(  
  26.     chunk_size=100,  
  27.     chunk_overlap=50,  
  28.     length_function=len,  
  29.     is_separator_regex=False,  
  30.     separators=["\n\n","\n"," ",""]# 默认分隔符,这里显式写出以便理解  )# 执行分割操作  # 注意:split_documents 方法接收一个 Document 列表,返回也是一个 Document 列表  
  31. chunks = text_splitter.split_documents([doc])# ----------------------------------------------------  #               5. 打印和验证分割结果  # ----------------------------------------------------  
  32. log.info(f"文本分割完成,共生成 {len(chunks)} 个块(chunks)。")print("\n"+"="*80)print("                           分割结果展示")print("="*80+"\n")for i, chunk inenumerate(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。整个过程无需人工干预,工具调用逻辑完全自动化。
代码落地:
  1. # --- 步骤2: 定义我们的工具 ---@tool  defmultiply(a:int, b:int)->int:"""用于计算两个整数的乘积。"""print(f"正在执行乘法: {a} * {b}")return a * b  
  2. @tooldefsearch_weather(city:str)->str:"""用于查询指定城市的实时天气。"""print(f"正在查询天气: {city}")if"北京"in city:return"北京今天是晴天,气温25摄氏度。"elif"上海"in city:return"上海今天是阴天,有小雨,气温22摄氏度。"else:returnf"抱歉,我没有'{city}'的天气信息。"
复制代码
完整代码:
  1. # -*- coding: utf-8 -*-  from langchain_openai import ChatOpenAI  
  2. from langchain_core.tools import tool  
  3. from langchain_core.messages import HumanMessage, AIMessage  
  4.   
  5. # --- DeepSeek API 配置 ---# 请替换为你的 DeepSeek API 密钥  
  6. API_KEY ="sk-52****************************"  
  7. API_URL ="https://api.deepseek.com/v1"  
  8. MODEL ="deepseek-chat"# --- 步骤1: 初始化 ChatOpenAI ---# 虽然我们用的是DeepSeek,但它兼容OpenAI的API格式,所以可以使用ChatOpenAI类  
  9. llm = ChatOpenAI(  
  10.     model=MODEL,  
  11.     api_key=API_KEY,  
  12.     base_url=API_URL,  
  13.     temperature=0.8,  
  14.     max_tokens=300)# --- 步骤2: 定义我们的工具 ---@tooldefmultiply(a:int, b:int)->int:"""用于计算两个整数的乘积。"""print(f"正在执行乘法: {a} * {b}")return a * b  
  15.    
  16. '''
  17. 下面的工具中,返回的东西是写死的,真实的业务场景中,会去调用其他数据提供商的api接口来调用实时数据
  18. '''@tooldefsearch_weather(city:str)->str:"""用于查询指定城市的实时天气。"""print(f"正在查询天气: {city}")if"北京"in city:return"北京今天是晴天,气温25摄氏度。"elif"上海"in city:return"上海今天是阴天,有小雨,气温22摄氏度。"else:returnf"抱歉,我没有'{city}'的天气信息。"# 将工具列表放入一个变量  
  19. tools =[multiply, search_weather]# --- 步骤3: 将工具绑定到LLM ---  # .bind_tools() 方法会将工具的结构信息(名称、描述、参数)传递给模型  # 这样模型在推理时就知道自己有哪些"超能力"了  
  20. llm_with_tools = llm.bind_tools(tools)# --- 步骤4: 发起调用 ---# 第一次调用:让模型决定是否以及如何调用工具  print("--- 第一次调用:模型生成工具调用指令 ---")  
  21. query ="北京今天天气怎么样?另外请帮我计算一下 12乘以8 等于多少?"# invoke 方法会返回一个 AIMessage 对象  # 如果模型决定调用工具,相关信息会储存在 .tool_calls 属性中  
  22. ai_msg = llm_with_tools.invoke(query)print("模型返回的AIMessage:")print(ai_msg)print("\n解析出的工具调用请求:")print(ai_msg.tool_calls)# --- 步骤5: 执行工具调用 ---print("\n--- 执行工具调用 ---")  
  23. tool_results =[]for tool_call in ai_msg.tool_calls:# 根据工具名称找到对应的工具函数  
  24.     tool_name = tool_call["name"]  
  25.     tool_args = tool_call["args"]# 查找对应的工具  
  26.     selected_tool =Nonefor t in tools:if t.name == tool_name:  
  27.             selected_tool = t  
  28.             breakif selected_tool:print(f"执行工具: {tool_name}, 参数: {tool_args}")# 执行工具并获取结果  """  
  29.         使用 @tool 装饰器定义函数时,LangChain 会自动将这个普通函数包装成一个 Tool 对象。  
  30.         这个 Tool 类继承了 Runnable 基类,因此具有 invoke() 方法。  
  31.         """        result = selected_tool.invoke(tool_args)  
  32.         tool_results.append({"tool_call_id": tool_call["id"],"name": tool_name,"result": result  
  33.         })print(f"工具执行结果: {result}")else:print(f"未找到工具: {tool_name}")
复制代码
十一、智能代理(Agent)

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

默认情况下,大模型是无状态的,也就是它不会记住你之前的任何交互。所以每一次提问都是一次全新的、独立的对话。
记忆模块 的作用就是赋予LLM上下文感知能力。通过存储、管理和传递历史对话信息,让LLM能够“记住”之前的交流内容,从而实现连贯的、有逻辑的多轮对话。
对比维度ConversationBufferMemoryConversationBufferWindowMemory
核心机制完整保留全部对话历史(用户提问 + 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等等我们不再详细介绍,自己补充一下吧~~

原文地址:https://blog.csdn.net/weixin_63182000/article/details/155467750
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题
阅读排行更多+

Powered by Discuz! X3.4© 2001-2013 Discuz Team.( 京ICP备17022993号-3 )