langchain

langchain官网: https://docs.langchain.com/oss/python/releases/langchain-v1

看似高大上,实则有很多 api 调用,后期找个新版本看看,或者看看官方文档。

2026 年 langchain 已经发布了新的版本,api 中存在着不少的变化,但是 langchain 整体的结构和设计思想是一样的,具体使用时, 参考官方文档。

01-LangChain使用概述

第01章:LangChain使用概述

image-20260603182851062

1、介绍LangChain

1.1 什么是LangChain

LangChain是 2022年10月,由哈佛大学的 Harrison Chase (哈里森·蔡斯)发起研发的一个开源框架,用于开发由大语言模型(LLMs)驱动的应用程序。

比如,搭建“智能体”(Agent)、问答系统(QA)、对话机器人、文档搜索系统、企业私有知识库等。

LangChain在Github上的热度变化
img

LangChain在Github上的star

image-20260604205438824

https://github.com/langchain-ai/langchain

简单概括

LangChain ≠ LLMs
LangChain 之于 LLMs,类似 Spring 之于 Java

LangChain 之于 LLMs,类似 Django、Flask 之于 Python

顾名思义,LangChain中的“Lang”是指language,即⼤语⾔模型,“Chain”即“链”,也就是将⼤模型与外部数据&各种组件连接成链,以此构建AI应⽤程序

大模型相关的岗位
img

应用开发是大模型最值得关注的方向:应用为王!

学习LangChain框架,高效开发大模型应用

1.2 有哪些大模型应用开发框架呢?

截止到2025年7月26日,GitHub统计数据:

img

* LangChain :这些工具里出现最早、最成熟的,适合复杂任务分解和单智能体应用

* LlamaIndex :专注于高效的索引和检索,适合 RAG 场景。(注意不是Meta开发的)

* LangChain4J :LangChain还出了Java、JavaScript(LangChain.js)两个语言的版本, LangChain4j的功能略少于LangChain,但是主要的核心功能都是有的

* SpringAI/SpringAI Alibaba :有待进一步成熟,此外只是简单的对于一些接口进行了封装

* SemanticKernel :也称为sk,微软推出的,对于C#同学来说,那就是5颗星

1.3 为什么需要LangChain?

问题1:LLMs用的好好的,干嘛还需要LangChain?

在大语言模型(LLM)如 ChatGPT、Claude、DeepSeek 等快速发展的今天,开发者不仅希望能“使用”这些模型,还希望能 将它们灵活集成到自己的应用中 ,实现更强大的对话能力、检索增强生成(RAG)、工具调用(Tool Calling)、多轮推理等功能。

img

LangChain 为更方便解决这些问题,而生的。比如:大模型默认不能联网,如果需要联网,用 langchain。

问题2:我们可以使用GPT 或GLM4 等模型的API进行开发,为何需要LangChain这样的框架?

不使用LangChain,确实可以使用GPT 或GLM4 等模型的API进行开发。比如,搭建“智能体”(Agent)、问答系统、对话机器人等复杂的 LLM 应用。

但使用LangChain的好处:

* 简化开发难度:更简单、更高效、效果更好

* 学习成本更低:不同模型的API不同,调用方式也有区别,切换模型时学习成本高。使用 LangChain,可以以统一、规范的方式进行调用,有更好的移植性。

* 现成的链式组装:LangChain提供了一些 现成的链式组装 ,用于完成特定的高级任务。让复杂的逻辑变得结构化,易组合,易扩展。

image-20260604075555014

问题3:LangChain 提供了哪些功能呢?

LangChain 是一个帮助你构建 LLM 应用的 全套工具集 。这里涉及到prompt 构建、LLM 接入、记忆管理、工具调用、RAG、智能体开发等模块。

1.4 LangChain的使用场景

学完LangChain,如下类型的项目,大家都可以实现:

项目名称 技术点 难度
文档问答助手 Prompt + Embedding + RetrievalQA ⭐⭐
智能日程规划助手 Agent + Tool + Memory ⭐⭐⭐
LLM+数据库问答 SQLDatabaseToolkit + Agent ⭐⭐⭐⭐
多模型路由对话系统 RouterChain + 多 LLM ⭐⭐⭐⭐
互联网智能客服 ConversationChain + RAG +Agent ⭐⭐⭐⭐⭐
企业知识库助手(RAG + 本地模型) VectorDB + LLM + Streamlit ⭐⭐⭐⭐⭐

比如:医院智能助手

image-20260604210217659

比如:万象知识库

img

比如:京东助手

image-20260604205620116

LangChain的位置:

img

1.5 LangChain资料介绍

官网地址:https://www.langchain.com/langchain

官网文档:https://python.langchain.com/docs/introduction/

API文档:https://python.langchain.com/api_reference/

github地址:https://github.com/langchain-ai/langchain

1.6 架构设计

1.6.1 总体架构图
V0.1 版本
img
V0.2 / V0.3 版本

**
**

image-20260604205648942

图中展示了LangChain生态系统的主要组件及其分类,分为三个层次:架构(Architecture)、组件 (Components)和部署(Deployment)。

版本的升级,v0.2 相较于v0.1,修改了⼤概10%-15%。功能性上差不多,主要是往稳定性(或兼容性)、安全性上使劲了,⽀持更多的⼤模型,更安全。

1.6.2 内部架构详情
结构1:LangChain

langchain:构成应用程序认知架构的Chains,Agents,Retrieval strategies等

构成应⽤程序的链、智能体、RAG。

langchain-community:第三方集成

⽐如:Model I/O、Retrieval、Tool & Toolkit;合作伙伴包 langchain-openai,langchain-anthropic等。

langchain-Core:基础抽象和LangChain表达式语言 (LCEL)

小结:LangChain,就是AI应用组装套件,封装了一堆的API。langchain框架不大,但是里面琐碎的知识点特别多。就像玩乐高,提供了很多标准化的乐高零件(比如,连接器、轮子等)

结构2:LangGraph

LangGraph可以看做基于LangChain的api的进一步封装,能够协调多个Chain、Agent、Tools完成更复杂的任务,实现更高级的功能。

结构3:LangSmith

https://docs.smith.langchain.com/

链路追踪。提供了6大功能,涉及Debugging (调试)、Playground (沙盒)、Prompt Management (提示管理)、Annotation (注释)、Testing (测试)、Monitoring (监控)等。与LangChain无缝集成,帮助你从原型阶段过渡到生产阶段。

正是因为LangSmith这样的⼯具出现,才使得LangChain意义更⼤,要不仅靠⼀些API(当然也可以不⽤,⽤原⽣的API),⽀持不住LangChain的热度。

结构4:LangServe

将LangChain的可运行项和链部署为REST API,使得它们可以通过网络进行调用。

Java怎么调用langchain呢?就通过这个langserve。将langchain应用包装成一个rest api,对外暴露服务。同时,支持更高的并发,稳定性更好。

总结:LangChain当中,最有前途的两个模块就是:LangGraph,LangSmith。

LangChain能做RAG,其它的⼀些框架也能做,而且做的也不错,⽐如LlamaIndex。所以这时候LangChain要在Agent这块发⼒,那就需要LangGraph。而LangSmith,做运维、监控。故,⼆者是LangChain⾥最有前途的。

2、开发前的准备工作

2.1 前置知识

1、Python 基础语法

* 变量、函数、类、装饰器、上下文管理器

* 模块导入、包管理(推荐用pip 或 conda)

2、大语言模型基础

* 了解什么是 LLM、Token、Prompt、Embedding

* OpenAI API 或其他模型提供商,如 Anthropic、阿里云百炼、DeepSeek等

* 通过浏览器或app使用过大模型(比如:豆包、DeepSeek等)

2.2 相关环境安装

1、安装Python或Anaconda

LangChain基于Python开发,因此需确保系统中安装了Python。

方式1 :直接下载Python安装包。推荐版本为Python 3.10及以上 Python官网:https://www.python.org/
方式2 :使用包管理工具(如Anaconda)进行安装。通过Anaconda可以轻松创建和管理虚拟环境,为项目提供独立的依赖空间,避免不同项目之间的依赖冲突。

2、创建虚拟环境

为了保持项目的独立性与环境的干净,建议使用虚拟环境。可以在Anaconda中创建虚拟环境。

验证Python版本:在激活的虚拟环境中,输入以下命令验证Python版本是否正确:

python --version

3、如何下载安装包

比如:安装langchain包

方式1:使用pip指令

基础指令

# 安装包( 默认最新版)
pip install langchain

# 指定版本
pip install langchain==0.3.7
# 批量安装( 空格分隔)
pip install langchain requests numpy
# 升级包
pip install --upgrade langchain
# 卸载包
pip uninstall langchain
# 查看已安装包
pip list

高级操作

# 国内镜像加速 ( 解决下载慢)  -i: 指定镜像源
pip install -i https://mirrors.aliyun.com/pypi/simple/ langchain

# 从本地/URL安装:
pip install ./local_package.whl
pip install https://github.com/user/repo/archive/main.zip

方式二:使用conda指令

# 安装包( 默认仓库)
conda install langchain

# 指定频道( 如 conda-forge)
conda install -c conda-forge langchain==0.3.7

# 更新包
conda update langchain
# 卸载包
conda uninstall langchain
# 查看已安装包
conda list
"""
-c :是 --channel 的缩写,conda⽤于指定包的安装来源渠道。
conda-forge :该源⽐官⽅默认渠道更新更快、包更全

"""

建议: 二者最好不好混用,推荐先conda装基础包,后 pip补充的顺序。

1 # 检查包来源
2 conda list # conda 安装的包显示频道,pip安装的显示 pypi

img
4、PyCharm开发环境

PyCharm作为专业的Python IDE,具有强大的代码编辑、调试和版本控制功能。

image-20260604205717199

创建新的工程,并设置Python解释器(选择Anaconda环境)。

import langchain
print(langchain.__version__)  # 0.3.25

import openai
print(openai.__version__) # 1.81.0

import #查看python的版本
print(sys.version) # 3. 10. 17 | packaged by conda-forge | (main, Apr 10 2025, 22:06:35) [MSC
v. 1943 64 bit (AMD64)]

3、大模型应用开发

大模型应用技术特点:门槛低,天花板高。

3.1 基于RAG架构的开发

背景:

* 大模型的知识冻结

* 大模型幻觉

而RAG就可以非常精准的解决这两个问题。

举例:

LLM在考试的时候面对陌生的领域,答复能力有限,然后就准备放飞自我了。而此时RAG给了一些提示和思路,让LLM懂了开始往这个提示的方向做,最终考试的正确率从60%到了90%!

image-20260604205756882

何为RAG?

Retrieval-Augmented Generation(检索增强生成)

image-20260603185822421

检索-增强-⽣成过程:检索可以理解为第10步,增强理解为第12步(这⾥的提⽰词包含检索到的数据),⽣成理解为第15步。

类似的细节图:

image-20260603190126946

img

这些过程中的难点:1、文件解析 2、文件切割 3、知识检索 4、知识重排序

Reranker的使用场景:

* 适合:追求 回答高精度高相关性 的场景中特别适合使用 Reranker,例如专业知识库或者客服系统等应用。

* 不适合:引入reranker会增加召回时间,增加检索延迟。服务对 响应时间要求高 时,使用reranker可能不合适。

这里有三个位置涉及到大模型的使用:

* 第3步向量化时,需要使用EmbeddingModels。

* 第7步重排序时,需要使用RerankModels。

* 第9步生成答案时,需要使用LLM。

3.2 基于Agent架构的开发

充分利用 LLM 的推理决策能力,通过增加 规划记忆工具 调用的能力,构造一个能够独立思考、逐步完成给定目标的智能体。

举例:传统的程序 vs Agent(智能体)

image-20260604205834700

OpenAI的元老翁丽莲(Lilian Weng)于2023年6月在个人博客首次提出了现代AI Agent架构。

image-20260603190459514

img

一个数学公式来表示:

Agent = LLM + Memory + Tools + Planning + Action

⽐如,打⻋到西藏玩。
⼤脑中枢:规划⾏程的你
规划:步骤1:规划打⻋路线,步骤2:定饭店、酒店,。。。
调⽤⼯具:调⽤MCP或FunctionCalling等API,滴滴打⻋、携程、美团订酒店饭店
记忆能⼒:沟通时,要知道上下⽂。⽐如定酒店得知道是西藏路上的酒店,不能聊着聊着忘了最初的⽬的。
能够执⾏上述操作。说走就走,不能纸上谈兵。

智能体核心要素被细化为以下模块:

1、大模型(LLM) 作为“大脑”

提供推理、规划和知识理解能力,是AI Agent的决策中枢。

⼤脑主要由⼀个⼤型语⾔模型 LLM 组成,承担着信息处理和决策等功能, 并可以呈现推理和规划的过程,能很好地应对未知任务。

2、记忆(Memory)

记忆机制能让智能体在处理重复⼯作时调⽤以前的经验,从而避免⽤⼾进⾏⼤量重复交互。

短期记忆:存储单次对话周期的上下文信息,属于临时信息存储机制。受限于模型的上下文窗口长度。

image-20260603191000568

ChatGPT:⽀持约8k token的上下⽂ GPT4:⽀持约32k token的上下⽂
最新的很多⼤模型:都⽀持100万、1000万 token的上下⽂ (相当于2000万字⽂本或20小时视频)
⼀般情况下模型中 token 和字数的换算⽐例⼤致如下:

1 个英⽂字符 ≈ 0.3 个 token。

1 个中⽂字符 ≈ 0.6 个 token。

长期记忆:可以横跨多个任务或时间周期,可存储并调用核心知识,非即时任务。

长期记忆,可以通过模型参数微调(固化知识)知识图谱(结构化语义网络)向量数据库

(相似性检索)方式实现。

3、工具使用(Tool Use):

调用外部工具(如API、数据库)扩展能力边界。

img
4、规划决策(Planning):

通过任务分解、反思与自省框架实现复杂任务处理。例如,利用思维链

(Chain of Thought)将目标拆解为子任务,并通过反馈优化策略。

img

image-20260604210012664

5、行动(Action):

实际执行决策的模块,涵盖软件接口操作(如自动订票)和物理交互(如机器人执行搬运)。比如:检索、推理、编程等。

智能体会形成完整的计划流程。例如先读取以前⼯作的经验和记忆,之后规划⼦⽬标并使⽤相应⼯具去处理问题,最后输出给⽤⼾并完成反思。

3.3 大模型应用开发的4个场景

场景1:纯 Prompt

* Prompt是操作大模型的唯一接口

* 当人看:你说一句,ta回一句,你再说一句,ta再回一句...

image-20260604210047942

场景2:Agent + Function Calling

* Agent:AI 主动提要求

* Function Calling:需要对接外部系统时,AI 要求执行某个函数

* 当人看:你问 ta「我明天去杭州出差,要带伞吗?」,ta 让你先看天气预报,你看了告诉ta,ta再告诉你要不要带伞

img
场景3:RAG (Retrieval-Augmented Generation)

RAG:需要补充领域知识时使用

* Embeddings:把文字转换为更易于相似度计算的编码。这种编码叫向量

* 向量数据库:把向量存起来,方便查找

* 向量搜索:根据输入向量,找到最相似的向量

举例:考试答题时,到书上找相关内容,再结合题目组成答案

img

这个在智能客服上用的最广泛。

场景4:Fine-tuning(精调/微调)

举例:努力学习考试内容,长期记住,活学活用。

img

特点:成本最高;在前面的方式解决不了问题的情况下,再使用。

如何选择

面对一个需求,如何开始,如何选择技术方案?下面是个常用思路:

image-20260603191617744

注意:其中最容易被忽略的,是准备测试数据

下面,我们重点介绍下大模型应用的开发两类:基于RAG的架构,基于Agent的架构。

4、LangChain的核心组件

学习Langchain最简单直接的方法就是阅读官方文档。 https://python.langchain.com/v0.1/docs/modules/

通过文档目录我们可以看到,Langchain构成的核心组件。

image-20260603191722161

两个红框内容是核⼼。中间的Integrations:集成各种⼯具或云平台。

4.1 一个问题引发的思考

如果要组织一个AI应用,开发者一般需要什么?

第1,提示词模板的构建,不仅仅只包含用户输入。

第2,模型调用与返回,参数设置,返回内容的格式化输出。

第3,知识库查询,这里会包含文档加载,切割,以及转化为词嵌入(Embedding)向量。

第4,其他第三方工具调用,一般包含天气查询、Google搜索、一些自定义的接口能力调用。

第5,记忆获取,每一个对话都有上下文,在开启对话之前总得获取到之前的上下文吧?

4.2 核心组件的概述

LangChain的核心组件涉及六大模块,这六大模块提供了一个全面且强大的框架,使开发者能够创建复杂、高效且用户友好的基于大模型的应用。

img

4.3 核心组件的说明

核心组件1:Model I/O

这个模块使⽤最多,也最简单

Model I/O:标准化各个大模型的输入和输出,包含输入模版,模型本身和格式化输出。以下是使用语言模型从输入到输出的基本流程。

image-20260603192048396

以下是对每一块的总结:
Format(格式化) :即指代Prompts Template,通过模板管理大模型的输入。将原始数据格式化成模型可以处理的形式,插入到一个模板问题中,然后送入模型进行处理。
Predict(预测) :即指代Models,使用通用接口调用不同的大语言模型。接受被送进来的问题,然后基于这个问题进行预测或生成回答。
Parse(生成) :即指代Output Parser 部分,用来从模型的推理中提取信息,并按照预先设定好的模版来规范化输出。比如,格式化成一个结构化的JSON对象。

核心组件2:Chains

Chain:"链条",用于将多个模块串联起来组成一个完整的流程,是 LangChain 框架中最重要的模块。

例如,一个 Chain 可能包括一个 Prompt 模板、一个语言模型和一个输出解析器,它们一起工作以处理用户输入、生成响应并处理输出。

常见的Chain类型:
LLMChain :最基础的模型调用链
SequentialChain :多个链串联执行
RouterChain :自动分析用户的需求,引导到最适合的链
RetrievalQA :结合向量数据库进行问答的链

核心组件3:Memory

Memory:记忆模块,用于保存对话历史或上下文信息,以便在后续对话中使用。常见的 Memory 类型:
ConversationBufferMemory :保存完整的对话历史
ConversationSummaryMemory :保存对话内容的精简摘要(适合长对话)
ConversationSummaryBufferMemory :混合型记忆机制,兼具上面两个类型的特点
VectorStoreRetrieverMemory :保存对话历史存储在向量数据库中

核心组件4:Agents

Agents,对应着智能体,是 LangChain 的高阶能力,它可以自主选择工具并规划执行步骤。
Agent 的关键组成:
AgentType :定义决策逻辑的工作流模式
Tool :是一些内置的功能模块,如API调用、搜索引擎、文本处理、数据查询等工具。Agents通过这些工具来执行特定的功能。
AgentExecutor :用来运行智能体并执行其决策的工具,负责协调智能体的决策和实际的工具执行。

⽬前最热⻔的智能体开发实践,未来能够真正实现通⽤⼈⼯智能的落地⽅案。

这⾥的Agent,就会涉及到前⾯讲的memory,以及tools。

核心组件5:Retrieval

Retrieval:对应着RAG,检索外部数据,然后在执行生成步骤时将其传递到 LLM。步骤包括文档加载、切割、Embedding等

image-20260603192652009

* Source :数据源,即大模型可以识别的多种类型的数据:视频、图片、文本、代码、文档等。

* Load :负责将来自不同数据源的非结构化数据,加载为文档(Document)对象

* Transform :负责对加载的文档进行转换和处理,比如将文本拆分为具有语义意义的小块。

* Embed :将文本编码为向量的能力。一种用于嵌入文档,另一种用于嵌入查询

* Store :将向量化后的数据进行存储

* Retrieve :从大规模文本库中检索和查询相关的文本段落

绿⾊的是⼊库存储前的操作。

核心组件6:Callbacks

Callbacks:回调机制,允许连接到 LLM 应用程序的各个阶段,可以监控和分析LangChain的运行情况,比如日志记录、监控、流传输等,以优化性能。

回调函数,对于程序员们应该都不陌⽣。这个函数允许我们在LLM的各个阶段使⽤各种各样的 “钩⼦”,从而达实现⽇志的记录、监控以及流式传输等功能。

4.4 小结

* Model I/O模块:使用最多,也最简单

* Chains 模块: 最重要的模块

* Retrieval模块、Agents模块:大模型的主要落地场景

在这个基础上,其它组件要么是它们的辅助,要么只是完成常规应用程序的任务。

辅助:⽐如,向量数据库的分块和嵌⼊,⽤于追踪、观测的Callbacks

任务:⽐如,Tools,Memory

image-20260603193004776

我们要做的就是⼀个⼀个module去攻破,最后将他们融会贯通,也就成为⼀名合格的LangChain学习者了

5、LangChain的helloworld

注意:⼤家如果想演⽰如下代码的话,需要准备两个前提:
① 安装必要的库和插件
② 参考后续《02-LangChain使⽤之Model IO》的2.3.2小结,配置好.env配置⽂件建议:如下的helloworld⼤家看看即可,从下⼀章开始展开讲解

5.1 获取大模型

#导入 dotenv 库的 load_dotenv 函数,用于加载环境变量文件( . env) 中的配置
import dotenv
from langchain_openai import ChatOpenAI
import os

dotenv.load_dotenv() #加载当前目录下的 . env 文件

os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")


# 创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini") # 默认使用 gpt-3. 5-turbo

# 直接提供问题,并调用llm
response = llm.invoke("什么是大模型? ")
print(response)
                     
content= ⼤模型(Large Model)通常是指在深度学习和机器学习领域中,拥有⼤量参数和复杂结构的模型。这些模型可以处理复杂的数据集,进⾏⾼级的任务,如⾃然语⾔处理、图像识别、⽣成对抗⽹络等。以下是⼀些关于⼤模型的关键点:\n\n1. 参数量:⼤模型通常具备数亿甚⾄数千亿个参数,这使得它们能够学习到更加丰富的特征和关系。\n\n2. 计算需求:由于其庞⼤的规模,⼤模型通常需要⾼性能的计算资源,例如GPU或TPU,以及⻓时间的训练过程。\n\n3. 数据需求:训练⼤模型通常需要⼤量的数据,以确保模型能够在各种情况下进⾏有效的学习和泛化。\n\n4. 应
⽤⼴泛:⼤模型在许多领域都有应⽤,包括语⾔模型(如GPT-3、BERT等)、图像处理(如卷积神经⽹络)以及⽣成模型(如GAN)。\n\n5. 转移学习:许多⼤模型允许通过转移学习的⽅式进
⾏微调,使得它们能够在特定任务上表现良好,而⽆需从头开始训练。\n\n⼤模型的出现⼤⼤推动了⼈⼯智能的发展,使得许多复杂的任务变得可⾏,并且在多个领域取得了显著的成果。'
additional_kwargs={ refusal : None} response_metadata={ token_usage :
{ completion_tokens : 289, prompt_tokens : 12, total_tokens : 301,
 completion_tokens_details : { accepted_prediction_tokens : 0, audio_tokens : 0,
 reasoning_tokens : 0, rejected_prediction_tokens : 0}, prompt_tokens_details :
{ audio_tokens : 0, cached_tokens : 0}}, model_name : gpt-4o-mini-2024-07-18 ,
 system_fingerprint : fp_efad92c60b , id : chatcmpl-BxO81Kq8FpSQgLyTikWfGzOlry2MF ,
 service_tier : None, finish_reason : stop , logprobs : None} id= run--134748c7-8c54-4784-8781-6ea143086285-0 usage_metadata={ input_tokens : 12, output_tokens : 289,
 total_tokens : 301, input_token_details : { audio : 0, cache_read : 0},
 output_token_details : { audio : 0, reasoning : 0}}

其中,需要在当前工程下提供.env文件中提供如下信息:

1	OPENAI_API_KEY1="sk-cvUm8OddQbly............. AGgIHTm9kMH7Bf226G2" #你自己的密钥
2	OPENAI_BASE_URL="https://api. openai-proxy. org/v1"	#url是固定值,统一写成这样

密钥来自于:https://www.closeai-asia.com/

image-20260603193451299

5.2 使用提示词模板

我们也可以创建prompt template, 并引入一些变量到prompt template中,这样在应用的时候更加灵活。

from langchain_core.prompts import ChatPromptTemplate

# 需要注意的一点是,这里需要指明具体的role,在这里是system和用户
prompt = ChatPromptTemplate.from_messages([ ("system", "你是世界级的技术文档编写者"), ("user", "{input}") # {input}为变量
])
# 我们可以把prompt和具体llm的调用和在一起。
chain = prompt | llm
message = chain.invoke({"input": "大模型中的LangChain是什么?"}) 
print(message)
# print(type(message))

5.3 使用输出解析器

1	from langchain_openai import ChatOpenAI
2	from langchain_core.prompts import ChatPromptTemplate
3	from langchain_core.output_parsers import StrOutputParser,JsonOutputParser 

5	# 初始化模型
6	llm = ChatOpenAI(model="gpt-4o-mini")

8	# 创建提示模板
9	prompt = ChatPromptTemplate.from_messages([
10	("system", "你是世界级的技术文档编写者。 "),
11	("user", "{input}")
12	])		
13
14	# 使用输出解析器
15	# output_parser = StrOutputParser()
16	output_parser = JsonOutputParser() 17
18	# 将其添加到上一个链中
19	# chain = prompt | llm
20	chain = prompt | llm | output_parser 21
22	# 调用它并提出同样的问题。  答案是一个字符串,而不是ChatMessage
23	# chain. invoke({"input": "LangChain是什么?"})
24	chain.invoke({"input": "LangChain是什么? 用JSON格式回复,问题用question,回答用answer"})

{ question : LangChain是什么?',
 answer :  LangChain是⼀个开源框架,⽤于构建与⼤型语⾔模型(LLMs)交互的应⽤程序。它提供了⼀个灵活的⼯具集,允许开发⼈员创建具有复杂推理能⼒、链式任务处理和上下⽂管理的智能应⽤。LangChain⽀持多种数据源和组件,可以帮助开发者在各种环境中更⾼效地利⽤语⾔模型。'}

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser,JsonOutputParser

# 初始化模型
llm = ChatOpenAI(model="gpt-4o-mini")
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是世界级的技术文档编写者。 输出格式要求: {format_instructions}"), ("user", "{input}")
])
# 使用输出解析器
# output_parser = StrOutputParser()
output_parser = JsonOutputParser()

# 将其添加到上一个链中
# chain = prompt | llm
chain = prompt | llm | output_parser
# 调用它并提出同样的问题。 答案是一个字符串,而不是ChatMessage
# chain. invoke({"input": "LangChain是什么?"})
chain.invoke({"input": "LangChain是什么? ","format_instructions":output_parser.get_format_instructions()})

{ LangChain : { description : LangChain是⼀个开源的框架,⽤于构建基于语⾔模型的应⽤程序。它旨在将不同的语⾔模型、数据源和⼯具结合起来,以便于开发者创建复杂的应⽤。',
 key_features : ['模块化设计:⽀持将不同的组件组合在⼀起,如语⾔模型、数据处理和外部
API。',
'⽀持多种语⾔模型:兼容不同类型的语⾔模型,如OpenAI的GPT系列、BERT等。',  '内置数据连接:可以与多种数据源进⾏集成,例如数据库、⽂件和外部API。',
'灵活的⼯作流管理:提供了多种⽅法来定义和管理任务的执⾏流程。',  '社区⽀持:拥有活跃的社区,提供⽂档、⽰例和⽀持。',
'可扩展性:允许开发者根据需求定制和扩展功能。'],
 use_cases : ['聊天机器⼈开发', '⽂本⽣成和摘要', '内容推荐系统', '⾃然语⾔理解任务', '⾃动化⼯作流处理'],
 getting_started : { installation : '使⽤pip安装:pip install langchain ,
 documentation_link : 'https://langchain.readthedocs.io/en/latest/'}}}

5.4 使用向量存储

使用一个简单的本地向量存储 FAISS,首先需要安装它

1	pip install faiss-cpu
2	#或者
3	conda install faiss-cpu

1	pip install langchain_community==0.3.7
2	#或者
3	conda install langchain_community==0.3.7


# 导入和使用 WebBaseLoader
from langchain_community.document_loaders import WebBaseLoader 
import bs4


loader = WebBaseLoader(
web_path="https://www.gov.cn/xinwen/2020-06/01/content_5516649.htm",  bs_kwargs=dict(parse_only=bs4.SoupStrainer(id="UCAP-CONTENT"))
)
docs = loader.load()
# print(docs)

# 对于嵌入模型,这里通过 API调用
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 使用分割器分割文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50) documents = text_splitter.split_documents(docs)
print(len(documents))
# 向量存储 embeddings 会将 documents 中的每个文本片段转换为向量,并将这些向量存储在 FAISS向量数据库中
vector = FAISS.from_documents(documents, embeddings)

5.5 RAG(检索增强生成)

基于外部知识,增强大模型回复

from langchain_core.prompts import PromptTemplate

retriever = vector.as_retriever()
retriever.search_kwargs = {"k": 3}
docs = retriever.invoke("建设用地使用权是什么? ")

# for i,doc in enumerate(docs):
# print(f"⭐ 第{i+1}条规定: ")
# print(doc)

# 6.定义提示词模版
prompt_template = """
你是一个问答机器人。
你的任务是根据下述给定的已知信息回答用户问题。
确保你的回复完全依据下述已知信息。不要编造答案。
如果下述已知信息不足以回答用户的问题,请直接回复"我无法回答您的问题"。
已知信息:
{info}
用户问:
{question}
请用中文回答用户问题。
"""
# 7.得到提示词模版对象
template = PromptTemplate.from_template(prompt_template)
# 8.得到提示词对象
prompt = template.format(info=docs, question='建设用地使用权是什么?')

## 9. 调用LLM
response = llm.invoke(prompt)
print(response.content)
建设⽤地使⽤权是指在法律规定的范围内,建设⽤地使⽤权⼈对特定⼟地的使⽤、建造建筑物及其
他设施的权利。根据相关法律规定,建设⽤地使⽤权可以通过出让或划拨等⽅式设⽴,并应当符合
资源节约、⽣态环境保护及⼟地⽤途的规定。建设⽤地使⽤权⼈有权转让、出资、赠与或抵押其使
⽤权,但需遵循法律规定和合同约定。

5.6 使用Agent

from langchain.tools.retriever import create_retriever_tool
# 检索器工具
retriever_tool = create_retriever_tool(
retriever,
"CivilCodeRetriever",
"搜索有关中华人民共和国民法典的信息。关于中华人民共和国民法典的任何问题,您必须使用此工
具!",
)
tools = [retriever_tool]
from langchain import hub
from langchain.agents import create_openai_functions_agent
from langchain.agents import AgentExecutor
# https://smith.langchain.com/hub
prompt = hub.pull("hwchase17/openai-functions-agent")
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 运行代理
agent_executor.invoke({"input": "建设用地使用权是什么"})

02-LangChain使用之Model I/O

1、Model I/O介绍

Model I/O 模块是与语言模型(LLMs)进行交互的 核心组件 ,在整个框架中有着很重要的地位。所谓的Model I/O,包括输入提示(Format)、调用模型(Predict)、输出解析(Parse)。分别对应着

针对每个环节,LangChain都提供了模板和工具,可以快捷的调用各种语言模型的接口。

2、Model I/O之调用模型1

LangChain作为一个"工具",不提供任何 LLMs,而是依赖于第三方集成各种大模型。比如,将 OpenAI、Anthropic、Hugging Face 、LlaMA、阿里Qwen、ChatGLM等平台的模型无缝接入到你的应用。

2.1模型的不同分类方式

简单来说,就是⽤谁家的API以什么⽅式调⽤哪种类型的⼤模型

角度1:按照模型功能的不同
  • 非对话模型(LLMs、Text Model)

  • 对话模型(Chat Models)( 推荐

  • 嵌入模型(Embedding Models)( 暂不考虑 )

角度2:模型调用时,几个重要参数的书写位置的不同
  • 硬编码:写在代码文件中

  • 使用环境变量

  • 使用配置文件( 推荐

角度3:具体调用的API
  • OpenAI提供的API
  • 其它大模型自家提供的API
  • LangChain的统一方式调用API( 推荐
  • image-20260604151735243

2.2角度1出发:按照功能不同举例

类型1:LLMs(非对话模型)

LLMs,也叫Text Model、非对话模型,是许多语言模型应用程序的支柱。主要特点如下:

  • 输入:接受 文本字符串PromptValue 对象

  • 输出:总是返回 文本字符串

  • 适用场景:仅需单次文本生成任务(如摘要生成、翻译、代码生成、单次问答)或对接不支持消息结构的旧模型(如部分本地部署模型)( 言外之意,优先推荐ChatModel

  • 不支持多轮对话上下文。每次调用独立处理输入,无法自动关联历史对话(需手动拼接历史文本)。

  • 局限性:无法处理角色分工或复杂对话逻辑。

    import os
    import dotenv
    from langchain_openai import OpenAI
    dotenv.load_dotenv()
    os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY1")
    os.environ["OPENAI_BASE_URL"] = os.getenv("OPENAI_BASE_URL")
    ###########核心代码############
    llm = OpenAI()
    str = llm.invoke("写一首关于春天的诗") # 直接输入字符串
    print(str)
    
    春⻛拂过⼤地
    万物复苏欣欣向荣
    花开满⼭⾕
    ⻦⼉啁啾歌声飘
    春⾬滋润⽥野
    农夫欢呼收获丰
    春⽇暖阳温柔
    ⼈们⼼情也随之舒
    春天来了
    带来新的开始
    带走冬⽇的寒冷
    带来⽣机与希望
    春天啊,美丽的季节
    让我们⼀起欢庆
    迎接春天的到来
    让快乐永远驻留⼼中。
    
类型2:Chat Models(对话模型)

ChatModels,也叫聊天模型、对话模型,底层使用LLMs。大语言模型调用,以 ChatModel 为主!

主要特点如下:

  • 输入:接收消息列表 List[BaseMessage] 或 PromptValue ,每条消息需指定角色(如 SystemMessage、HumanMessage、AIMessage)

  • 输出:总是返回带角色的 消息对象 ( BaseMessage 子类),通常是 AIMessage

  • 原生支持多轮对话。通过消息列表维护上下文(例如: [SystemMessage, HumanMessage, AIMessage, ...] ),模型可基于完整对话历史生成回复。

  • 适用场景:对话系统(如客服机器人、长期交互的AI助手)

from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
import os
import dotenv
dotenv.load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY1")
os.environ["OPENAI_BASE_URL"] = os.getenv("OPENAI_BASE_URL")
########核心代码############
chat_model = ChatOpenAI(model="gpt-4o-mini")
messages = [
SystemMessage(content="我是人工智能助手,我叫小智"),
HumanMessage(content="你好,我是小明,很高兴认识你")
]
response = chat_model.invoke(messages) # 输入消息列表
print(type(response)) # <class 'langchain_core.messages.ai.AIMessage'>
print(response.content)

image-20260604083522578

类型3:Embedding Model(嵌入模型)

Embedding Model:也叫文本嵌入模型,这些模型将 文本 作为输入并返回 浮点数列表 ,也就是 Embedding。(后面章节《07-LangChain使用之Retrieval》重点讲)

import os
import dotenv
from langchain_openai import OpenAIEmbeddings
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
#############
embeddings_model = OpenAIEmbeddings(
model="text-embedding-ada-002"
)
res1 = embeddings_model.embed_query('我是文档中的数据')
print(res1)
# 打印结果:[-0.004306625574827194, 0.003083756659179926, -0.013916781172156334, ...., ]

2.3角度2出发:参数位置不同举例

这里以 LangChain 的API为准,使用对话模型,进行测试。

2.3.1模型调用的主要方法及参数
相关方法及属性:
  • OpenAI(...) / ChatOpenAI(...) :创建一个模型对象(非对话类/对话类)

  • model.invoke(xxx) :执行调用,将用户输入发送给模型

  • .content :提取模型返回的实际文本内容

模型调用函数使用时需初始化模型,并设置必要的参数。

必须设置的参数:
  • base_url :大模型 API 服务的根地址

  • api_key :用于身份验证的密钥,由大模型服务商(如 OpenAI、百度千帆)提供

  • model/model_name :指定要调用的具体大模型名称(如 gpt-4-turboERNIE-3.5-8K 等)

其它参数:
  • temperature :温度,控制生成文本的"随机性",取值范围为0~1。

    • 值越低 → 输出越确定、保守(适合事实回答)

    • 值越高 → 输出越多样、有创意(适合创意写作)

通常,根据需要设置如下:

  • 精确模式(0.5或更低):生成的文本更加安全可靠,但可能缺乏创意和多样性。

  • 平衡模式(通常是0.8):生成的文本通常既有一定的多样性,又能保持较好的连贯性和准确性。

  • 创意模式(通常是1):生成的文本更有创意,但也更容易出现语法错误或不合逻辑的内容。

  • max_tokens :限制生成文本的最大长度,防止输出过长。

Token是什么?

基本单位 : 大模型处理文本的最小单位是token(相当于自然语言中的词或字),输出时逐个token依次生成。

收费依据 :大语言模型(LLM)通常也是以token的数量作为其计量(或收费)的依据。

max_tokens设置建议:
  • 客服短回复:128-256。比如:生成一句客服回复(如"订单已发货,预计明天送达")

  • 常规对话、多轮对话:512-1024

  • 长内容生成:1024-4096。比如:生成一篇产品说明书(包含功能、使用方法等结构)

2.3.2模型调用推荐平台:closeai
这里推荐使用的平台:

考虑到OpenAI等模型在国内访问及充值的不便,大家可以使用CloseAI网站注册和充值, 具体费用自理 。

https://www.closeai-asia.com

2.3.3 方式1:硬编码

直接将 API Key 和模型参数写入代码,仅适用于临时测试,存在密钥泄露风险,在 生产环境不推荐

from langchain_openai import ChatOpenAI
# 硬编码 API Key 和模型参数
llm = ChatOpenAI(
api_key="sk-xxxxxxxxx", # 明文暴露密钥
base_url="https://api.openai-proxy.org/v1",
model="gpt-3.5-turbo",
)
# 调用示例
response = llm.invoke("解释神经网络原理")
print(response.content)
神经⽹络是⼀种模拟⼈脑神经元之间信息传递的数学模型。神经⽹络由多层神经元组成,每个神经
元接收来⾃上⼀层神经元的输⼊信号,并通过激活函数将输⼊信号进⾏加权求和并输出⼀个结果。
在神经⽹络中,数据通过输⼊层传递到隐藏层,最终到输出层。在每⼀层中,神经元通过学习算法
不断调整连接权重,以使神经⽹络能够准确地对输⼊数据进⾏分类或预测。
神经⽹络的训练过程是通过反向传播算法进⾏的。该算法通过计算神经⽹络输出结果与实际结果之
间的误差,然后根据误差调整神经元之间的连接权重,以提⾼神经⽹络的准确性。
总的来说,神经⽹络通过模拟⼈脑神经元之间的信息传递过程,利⽤数学模型来实现对复杂问题的
学习和预测。神经⽹络的原理是基于神经元之间的连接权重调整和误差反向传播的机制。
2.3.4 方式2:配置环境变量

通过系统环境变量存储密钥,避免代码明文暴露。

方式1:终端设置环境变量(临时生效):

export OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxx" # Linux/Mac

set OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxx" # Window

方式2:从PyCharm设置

import os
from langchain_openai import ChatOpenAI
# 从环境变量读取密钥
llm = ChatOpenAI(
api_key=os.environ["OPENAI_API_KEY"], # 动态获取
base_url=os.environ["OPENAI_BASE_URL"],
model="gpt-4o-mini",
)
response = llm.invoke("LangChain 是什么?")
print(response.content)

优点:密钥与代码分离,适合单机开发

缺点:切换终端或文件后,变量失效,需重新设置。

2.3.5 方式3:使用.env配置文件

使用 python-dotenv 加载本地配置文件,支持多环境管理(开发/生产)。

  1. 安装依赖
pip install python-dotenv
#或者
conda install python-dotenv

2)创建 .env 文件(项目根目录)

OPENAI_API_KEY="sk-xxxxxxxxx" # 需填写自己的API KEY
OPENAI_BASE_URL="https://api.openai-proxy.org/v1"

方式一

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
import os
load_dotenv() # 自动加载 .env 文件
# print(os.getenv("OPENAI_API_KEY"))
# print(os.getenv("OPENAI_BASE_URL"))
llm = ChatOpenAI(
api_key=os.getenv("OPENAI_API_KEY"), # 安全读取
base_url=os.getenv("OPENAI_BASE_URL"),
model="gpt-4o-mini",
temperature=0.7,
)
response = llm.invoke("RAG 技术的核心流程")
print(response.content)

方式二:给 os 内部环境变量赋值

from langchain_openai import ChatOpenAI
import dotenv
dotenv.load_dotenv()
import os
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY1")
os.environ["OPENAI_API_BASE"] = os.getenv("OPENAI_BASE_URL")
text = "猫王是猫吗?"
chat_model = ChatOpenAI(
model="gpt-4o-mini",
temperature=0.7,
max_tokens=300,
)
response = chat_model.invoke(text)
print(type(response))
print(response.content)

image-20260604090140203

核心优势:
  • 配置文件可加入 .gitignore 避免泄露

  • 结合 LangChain 可扩展其它模型(如 DeepSeek、阿里云)

  • 生产环境推荐

小结:

image-20260604085858578

2.4 角度3出发:各平台API的调用举例(了解)

2.4.1 OpenAI 官方API

考虑到OpenAI在国内访问及充值的不便,我们仍然使用CloseAI网站( https://www.closeaiasia.com )注册和充值, 具体费用自理

调用非对话模型:
from openai import OpenAI
# 从环境变量读取API密钥(推荐安全存储)
client = OpenAI(api_key="sk-zD4CB2Qe7G2Dp6veCfPRSxeDx9fQPxCUIfOFAk20ETV5B2VA", #
填写自己的api-key
base_url="https://api.openai-proxy.org/v1") #通过代码示例获取
# 调用Completion接口
response = client.completions.create(
model="gpt-3.5-turbo-instruct", # 非对话模型
prompt="请将以下英文翻译成中文:\n'Artificial intelligence will reshape the future.'",
max_tokens=100, # 生成文本最大长度
temperature=0.7, # 控制随机性
)
# 提取结果
print(response.choices[0].text.strip())

调用对话模型:

写法1:

from openai import OpenAI
client = OpenAI(api_key="sk-zD4CB2Qe7G2Dp6veCfPRSxeDx9fQPxCUIfOFAk20ETV5B2VA", #填
写自己的api-key
base_url="https://api.openai-proxy.org/v1")
completion = client.chat.completions.create(
model="gpt-3.5-turbo", # 对话模型
messages=[
{"role": "system", "content": "你是一个乐于助人的智能AI小助手"},
{"role": "user", "content": "你好,请你介绍一下你自己"}
],
max_tokens=150,
temperature=0.5
)
print(completion.choices[0].message)

image-20260604090633967

写法2:

from openai import OpenAI
import os
import dotenv
dotenv.load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY1")
os.environ["OPENAI_BASE_URL"] = os.getenv("OPENAI_BASE_URL")
client = OpenAI()
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "我是一位乐于助人的AI智能小助手"},
{"role": "user", "content": "你好,请你介绍一下你自己。"}
]
)
print(response.choices[0])
2.4.2 百度千帆平台
开发参考文档:

https://cloud.baidu.com/doc/qianfan-docs/s/Mm8r1mejk

获取API Key和App ID:

创建API Key:https://console.bce.baidu.com/qianfan/ais/console/apiKey

创建App ID:https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/applicatio n/v2

代码举例:

from openai import OpenAI
client = OpenAI(
api_key="bce-v3/ALTAK-KZke********/f1d6ee*************", # 千帆bearer token
base_url="https://qianfan.baidubce.com/v2", # 千帆域名
default_headers={"appid": "app-MuYR79q6"} # 用户在千帆上的appid,非必传
)
completion = client.chat.completions.create(
model="ernie-4.0-turbo-8k", # 预置服务请查看模型列表,定制服务请填入API地址
messages=[{'role': 'system', 'content': 'You are a helpful assistant.'},
{'role': 'user', 'content': 'Hello!'}]
)
print(completion.choices[0].message)
2.4.3阿里云百炼平台
注册与key的获取:

提前开通百炼平台账号并申请API KEY:https://bailian.console.aliyun.com/#/home

对应的配置文件:
DASHSCOPE_API_KEY="sk-f1a87324#####e6a819a482" #使用自己的api key
DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"

模型的调用:

参考具体模型的代码示例。这里以DeepSeek为例:

举例1:通过OpenAI SDK

pip install openai
import os
from openai import OpenAI
client = OpenAI(
# 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"), # 如何获取API Key:
https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key
base_url=os.getenv("DASHSCOPE_BASE_URL")
)
completion = client.chat.completions.create(
model="deepseek-r1", # 此处以 deepseek-r1 为例,可按需更换模型名称。
messages=[
{'role': 'user', 'content': '9.9和9.11谁大'}
]
)
# 通过reasoning_content字段打印思考过程
print("思考过程:")
print(completion.choices[0].message.reasoning_content)
# 通过content字段打印最终答案
print("最终答案:")
print(completion.choices[0].message.content)

举例2:通过DashScope SDK

 pip install dashscope

    
import os
import dashscope
messages = [
{'role': 'user', 'content': '你是谁?'}
]
response = dashscope.Generation.call(
# 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv('DASHSCOPE_API_KEY'),
model="deepseek-r1", # 此处以 deepseek-r1 为例,可按需更换模型名称。
messages=messages,
# result_format参数不可以设置为"text"。
result_format='message'
)
print("=" * 20 + "思考过程" + "=" * 20)
print(response.output.choices[0].message.reasoning_content)
print("=" * 20 + "最终答案" + "=" * 20)
print(response.output.choices[0].message.content)
2.4.4智谱的GLM
注册智谱模型并获取API Key:

https://www.bigmodel.cn/usercenter/proj-mgmt/apikeys

#记录自己的api key,声明在.env文件中
ZHIPUAI_API_KEY="63a0f275b3a9###############rA4Y8daGaLydxQ"
查看《开发文档》

image-20260604091651996

或者选择如下《参考文档》皆可: https://www.bigmodel.cn/dev/api/normal-model/glm-4

代码举例

举例1:使用OpenAI SDK

from openai import OpenAI
client = OpenAI(
api_key=os.getenv("ZHIPUAI_API_KEY"),
base_url=os.getenv("ZHIPUAI_URL")
)
completion = client.chat.completions.create(
model="glm-4-air-250414",
messages=[
{"role": "system", "content": "你是一个聪明且富有创造力的小说作家"},
{"role": "user", "content": "请你作为童话故事大王,写一篇短篇童话故事,故事的主题是要永远
保持一颗善良的心,要能够激发儿童的学习兴趣和想象力,同时也能够帮助儿童更好地理解和接受故事
中所蕴含的道理和价值观。"}
],
top_p=0.7,
temperature=0.9
)
print(completion.choices[0].message)

举例2:使用Langchain SDK

import os
from langchain_openai import ChatOpenAI
from langchain.prompts import (
ChatPromptTemplate,
MessagesPlaceholder,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
llm = ChatOpenAI(
temperature=0.95,
model="glm-4-air-250414",
openai_api_key= os.getenv("ZHIPUAI_API_KEY"),
openai_api_base=os.getenv("ZHIPUAI_URL"),
)
prompt = ChatPromptTemplate(
messages=[
SystemMessagePromptTemplate.from_template(
"You are a nice chatbot having a conversation with a human."
),
MessagesPlaceholder(variable_name="chat_history"),
HumanMessagePromptTemplate.from_template("{question}")
]
)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
conversation = LLMChain(
llm=llm,
prompt=prompt,
verbose=True,
memory=memory
)
conversation.invoke({"question": "给我讲个冷笑话"})

举例3:参考langchain的文档

https://imooc-langchain.shortvar.com/docs/integrations/chat/zhipuai/

安装包:

pip install langchain-community

pip install pyjwt

代码示例:

import dotenv
from langchain_community.chat_models import ChatZhipuAI
from langchain_core.messages import AIMessage, SystemMessage, HumanMessage
#智谱大模型:参考langchain的大模型
dotenv.load_dotenv()
import os
os.environ["ZHIPUAI_API_KEY"] = os.getenv("ZHIPUAI_API_KEY")
chat = ChatZhipuAI(
model="glm-4",
temperature=0.5,
)
messages = [
AIMessage(content="哈罗~"),
SystemMessage(content="你是一个诗人"),
HumanMessage(content="写一首关于AI的七言绝句"),
]
response = chat.invoke(messages)
print(response.content) # 显示 AI 生成的诗

image-20260604092059903

2.4.5硅基流动平台

官网:https://www.siliconflow.cn/申请API Key:

参考文档:https://docs.siliconflow.cn/cn/userguide/quickstart

from openai import OpenAI
client = OpenAI(api_key=os.getenv("SILICON_API_KEY"),
base_url="https://api.siliconflow.cn/v1")
response = client.chat.completions.create(
model='Pro/deepseek-ai/DeepSeek-R1',
# model="Qwen/Qwen2.5-72B-Instruct",
messages=[
{'role': 'user',
'content': "推理模型会给市场带来哪些新的机会"}
],
stream=True
)
for chunk in response:
	if not chunk.choices:
		continue
if chunk.choices[0].delta.content:
	print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.choices[0].delta.reasoning_content:
	print(chunk.choices[0].delta.reasoning_content, end="", flush=True)

或者:

import requests
url = "https://api.siliconflow.cn/v1/chat/completions"
payload = {
"model": "deepseek-ai/DeepSeek-R1", #填写你选择的大模型
"messages": [
{
"role": "user",
"content": "1 +2 * 3 = ?"
}
]
}
headers = {
"Authorization": "Bearer sk-auciaxqpz.....zepozralhwleyrdoyjani", #填写你的api-key
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())

2.5如何选择合适的大模型

2.5.1有没有最好的大模型

凡是问「哪个大模型最好?」的,都是不懂的。

不妨反问:「无论做什么,有都表现最好的员工吗?」划重点:没有最好的大模型,只有最适合的大模型

基础模型选型,合规和安全是首要考量因素!

为什么不要依赖榜单?
  • 榜单已被应试教育污染,还算值得相信的榜单:LMSYS Chatbot Arena Leaderboard

  • 榜单体现的是整体能力,放到一件具体事情上,排名低的可能反倒更好

  • 榜单体现不出成本差异

本课程主要以OpenAI为例展开后续的课程。因为:

1、OpenAl 最流行,即便国内也是如此

2、OpenAl 最先进。别的模型有的能力,OpenAI一定都有。OpenAI有的,别的模型不一定有。

3、其它模型都在追赶和模仿OpenAl gpt-4o-mini

2.5.2 小结:获取大模型的标准方式

后续的各种模型测试,都基于如下的模型展开:

非对话模型:

import os
import dotenv
from langchain_openai import OpenAI
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
llm = OpenAI( #非对话模型
#max_tokens=512,
#temperature=0.7,
)
对话模型:
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
chat_model = ChatOpenAI( #对话模型
model="gpt-4o-mini",
#max_tokens=512,
    #temperature=0.7,
)

对应的配置文件

OPENAI_API_KEY="sk-xxxxxx" #从CloseAI平台,注册自己的账号,并获取API KEY
OPENAI_BASE_URL="https://api.openai-proxy.org/v1"

3、Model I/O之调用模型2

3.1 关于对话模型的Message(消息)

聊天模型,除了将字符串作为输入外,还可以使用 聊天消息 作为输入,并返回 聊天消息 作为输出。

LangChain有一些内置的消息类型:
  • 🔥 SystemMessage :设定AI行为规则或背景信息。比如设定AI的初始状态、行为模式或对话的总体目标。比如"作为一个代码专家",或者"返回json格式"。通常作为输入消息序列中的第一个传递。

  • 🔥 HumanMessage :表示来自用户输入。比如"实现 一个快速排序方法"

  • 🔥 AIMessage :存储AI回复的内容。这可以是文本,也可以是调用工具的请求

  • ChatMessage :可以自定义角色的通用消息类型

  • FunctionMessage/ToolMessage :函数调用/工具消息,用于函数调用结果的消息类型

    image-20260604093327049

举例1:

from langchain_core.messages import HumanMessage, SystemMessage
messages = [SystemMessage(content="你是一位乐于助人的智能小助手"),
HumanMessage(content="你好,请你介绍一下你自己"),]
print(messages)

image-20260604093359690

举例2:

image-20260604093422859

举例3:

image-20260604093436982

举例4:

image-20260604093452647

举例5:结合大模型使用

image-20260604093510253

image-20260604093521854

3.2 关于多轮对话与上下文记忆

前提:获取大模型

image-20260604093639364

测试1:

image-20260604093653746

测试2:

image-20260604093706482

测试3:

image-20260604093718846

测试4:

image-20260604093734560

测试5:

image-20260604093747664

3.3关于模型调用的方法

为了尽可能简化自定义链的创建,我们实现了一个"Runnable"协议。许多LangChain组件实现了 Runnable 协议,包括聊天模型、提示词模板、输出解析器、检索器、代理(智能体)等。

Runnable 定义的公共的调用方法如下:
invoke : 处理单条输入,等待LLM完全推理完成后再返回调用结果
stream : 流式响应,逐字输出LLM的响应结果
batch : 处理批量输入
这些也有相应的异步方法,应该与 asyncio 的 await 语法一起使用以实现并发:
astream : 异步流式响应
ainvoke : 异步处理单条输入
abatch : 异步处理批量输入
astream_log : 异步流式返回中间步骤,以及最终响应
astream_events : (测试版)异步流式返回链中发生的事件(在 langchain-core 0.1.14 中引入)

3.3.1流式输出与非流式输出

在Langchain中,语言模型的输出分为了两种主要的模式:流式输出非流式输出。下面是两个场景:

  • 非流式输出:这是Langchain与LLM交互时的 默认行为 ,是最简单、最稳定的语言模型调用方式。当用户发出请求后,系统在后台等待模型 生成完整响应 ,然后 一次性将全部结果返回

    • 举例:用户提问,请编写一首诗,系统在静默数秒后 突然弹出 了完整的诗歌。(体验较单调)

    • 在大多数问答、摘要、信息抽取类任务中,非流式输出提供了结构清晰、逻辑完整的结果,适合快速集成和部署。

  • 流式输出:一种 更具交互感 的模型输出方式,用户不再需要等待完整答案,而是能看到模型token 地实时返回内容。

  • 举例:用户提问,请编写一首诗,当问题刚刚发送,系统就开始 一字一句 (逐个token)进行回复,感觉是一边思考一边输出。

  • 更像是"实时对话",更为贴近人类交互的习惯,更有吸引力。

  • 适合构建强调"实时反馈"的应用,如聊天机器人、写作助手等。

  • Langchain 中通过设置 stream=True并配合 回调机制 来启用流式输出。

非流式输出:

image-20260604094229440

image-20260604094310809

image-20260604094326426

image-20260604094436823

image-20260604094528191

3.3.2.批量调用

image-20260604094647051

3.3.3.同步调用与异步调用(了解)
同步调用

image-20260604094745494

image-20260604094758912

异步调用

image-20260604094849028

image-20260604094901627

image-20260604094915118

image-20260604094928325

异步调用之ainvoke

image-20260604095013854

image-20260604095035915

image-20260604095048284

image-20260604095101939

4、Model I/O之Prompt Template

Prompt Template,通过模板管理大模型的输入。

4.1 介绍与分类

Prompt Template 是LangChain中的一个概念,接收用户输入,返回一个传递给LLM的信息(即提示词prompt)。

在应用开发中,固定的提示词限制了模型的灵活性和适用范围。所以,prompt template 是一个 模板化的字符串 ,你可以将 变量插入到模板 中,从而创建出不同的提示。调用时:

  • 字典 作为输入,其中每个键代表要填充的提示模板中的变量。

  • 输出一个 。这个 PromptValue 可以传递给 LLM 或 ChatModel,并且还可以转换为字符串或消息列表。

有几种不同类型的提示模板:
  • PromptTemplate :LLM提示模板,用于生成字符串提示。它使用 Python 的字符串来模板提示。

  • ChatPromptTemplate :聊天提示模板,用于组合各种角色的消息模板,传入聊天模型。

  • XxxMessagePromptTemplate :消息模板词模板,包括:SystemMessagePromptTemplate、 HumanMessagePromptTemplate、AIMessagePromptTemplate、 ChatMessagePromptTemplate等

  • FewShotPromptTemplate :样本提示词模板,通过示例来教模型如何回答

  • PipelinePrompt :管道提示词模板,用于把几个提示词组合在一起使用。

  • 自定义模板 :允许基于其它模板类来定制自己的提示词模板。

模板导入

from langchain.prompts.prompt import PromptTemplate
from langchain.prompts import ChatPromptTemplate
from langchain.prompts import FewShotPromptTemplate
from langchain.prompts.pipeline import PipelinePromptTemplate
from langchain.prompts import (
ChatMessagePromptTemplate,
SystemMessagePromptTemplate,
AIMessagePromptTemplate,
HumanMessagePromptTemplate,
)

4.2 复习:str.format()

Python的 str.format() 方法是一种字符串格式化的手段,允许在 字符串中插入变量 。使用这种方法,可以创建包含 占位符 的字符串模板,占位符由花括号 {} 标识。

  • 调用format()方法时,可以传入一个或多个参数,这些参数将被顺序替换进占位符中。

  • str.format()提供了灵活的方式来构造字符串,支持多种格式化选项。

在LangChain的默认设置下, 使用 Python 的 str.format() 方法进行模板化。这样

在模型接收输入前,可以根据需要对数据进行预处理和结构化。

带有位置参数的用法

image-20260604101329446

带有关键字参数的用法

image-20260604101339384

使用字典解包的方式

image-20260604101348247

4.3 具体使用:PromptTemplate

4.3.1使用说明

PromptTemplate类,用于快速构建 包含变量 的提示词模板,并通过 传入不同的参数值 生成自定义的提示词。

主要参数介绍:
  • template:定义提示词模板的字符串,其中包含 文本变量占位符(如{name})

  • input_variables: 列表,指定了模板中使用的变量名称,在调用模板时被替换;

  • partial_variables:字典,用于定义模板中一些固定的变量名。这些值不需要再每次调用时被替换。

函数介绍:
  • format():给input_variables变量赋值,并返回提示词。利用format() 进行格式化时就一定要赋值,否则会报错。当在template中未设置input_variables,则会自动忽略。
4.3.2 两种实例化方式
方式1:使用构造方法

举例1

image-20260604101652192

可以直观的看到PromptTemplate可以将template中声明的变量topic准确提取出来,使prompt更清晰。

举例2:定义多变量模板

image-20260604101711200

方式2:调用from_template()

举例1:

image-20260604101844756

举例2:模板支持任意数量的变量,包括不含变量:

image-20260604101855602

4.3.3 两种新的结构形式
形式1:部分提示词模版

在生成prompt前就已经提前初始化部分的提示词,实际进一步导入模版的时候只导入除已初始化的变量即可。

举例1:

image-20260604101955651

方式2:使用 PromptTemplate.partial() 方法创建部分提示模板

image-20260604102021005

举例2:

image-20260604102032490

举例3:

image-20260604102046817

形式2:组合提示词(了解)

举例:

image-20260604102116455

4.3.4 format() 与 invoke()

只要对象是RunnableSerializable接口类型,都可以使用invoke(),替换前面使用format()的调用方式。

format(),返回值为字符串类型;invoke(),返回值为PromptValue类型,接着调用to_string()返回字符串。

举例1:

image-20260604102213380

举例2:

image-20260604102224355

举例3:

image-20260604102233852

4.3.5 结合LLM调用

Prompt 与大模型结合。

问题:这里的大模型,是哪类呢?非对话大模型?对话大模型?

提供大模型:(非对话大模型)

image-20260604102324452

提供大模型:(对话大模型)

image-20260604102335117

调用过程:

image-20260604102351061

image-20260604102424163

4.4 具体使用:ChatPromptTemplate

4.4.1 使用说明

ChatPromptTemplate是创建 聊天消息列表 的提示模板。它比普通 PromptTemplate 更适合处理多角 色、多轮次的对话场景。

特点:

支持 System / Human / AI 等不同角色的消息模板

对话历史维护

参数类型:列表参数格式是tuple类型( role :str content :str 组合最常用)

元组的格式为: (role: str | type, content: str | list[dict] | list[object])

其中 role 是:字符串(如 "system" 、 "human" 、 "ai" )

4.4.2 两种实例化方式
方式1:使用构造方法

举例:

image-20260604102739258

方式2:调用from_messages()

image-20260604102809515

举例2:

image-20260604102819942

4.4.3 模板调用的几种方式

image-20260604102920335

image-20260604102940661

image-20260604102952738

image-20260604103004407

4.4.4 更丰富的实例化参数类型

前面讲了ChatPromptTemplate的两种创建方式。我们看到不管使用构造方法,还是使用 from_messages(),参数类型都是 列表类型 。列表中的元素可以是多种类型,前面我们主要测试了元组类型。

源码:

image-20260604103203913

源码:

image-20260604103214125

结论:参数是列表类型,列表的元素可以是字符串、字典、字符串构成的元组、消息类型、提示词模板类型、消息提示词模板类型等

类型1:str类型

列表参数格式是str类型(不推荐),因为默认角色都是human

image-20260604103257766

类型2:dict类型

列表参数格式是dict类型

image-20260604103315670

类型3:Message类型

image-20260604103342701

类型4:BaseChatPromptTemplate类型

使用 BaseChatPromptTemplate,可以理解为ChatPromptTemplate里嵌套了 ChatPromptTemplate。

举例1:不带参数

image-20260604103410760

举例2:带参数

image-20260604103422326

类型5:BaseMessagePromptTemplate类型

image-20260604103504691

基本概念:

image-20260604103617267

image-20260604103631489

image-20260604103642818

image-20260604103701289

image-20260604103711027

4.4.5 结合LLM

image-20260604103808357

image-20260604103833635

image-20260604103858072

4.4.5 插入消息列表:MessagesPlaceholder

当你不确定消息提示模板使用什么角色,或者希望在格式化过程中 插入消息列表 时,该怎么办? 这就需要使用 MessagesPlaceholder,负责在特定位置添加消息列表。

使用场景:多轮对话系统存储历史消息以及Agent的中间步骤处理此功能非常有用。

举例1:

image-20260604103957172

这将生成两条消息,第一条是系统消息,第二条是我们传入的 HumanMessage。 如果我们传入了 5 条消息,那么总共会生成 6 条消息(系统消息加上传入的 5 条消息)。 这对于将一系列消息插入到特定位置非常有用。

举例2:存储对话历史内容

image-20260604104022947

举例3:

image-20260604104039964

举例4:作为拓展,课下看看即可

image-20260604104104118

image-20260604104115965

4.5 具体使用:少量样本示例的提示词模板

4.5.1 使用说明

image-20260604104221515

image-20260604104237340

4.5.2 FewShotPromptTemplate的使用

image-20260604104306318

image-20260604104317473

结合大模型调用:

image-20260604104356844

image-20260604104441520

image-20260604104453454

4.5.3 FewShotChatMessagePromptTemplate的使用

除了FewShotPromptTemplate之外,FewShotChatMessagePromptTemplate是专门为 聊天对话场景 设计的少样本(few-shot)提示模板,它继承自 FewShotPromptTemplate ,但针对聊天消息的格式进行了优化。

特点

  • 自动将示例格式化为聊天消息( HumanMessage / AIMessage 等)

  • 输出结构化聊天消息( List[BaseMessage]

  • 保留对话轮次结构

    image-20260604104638444

    image-20260604104704269

    image-20260604104716769

举例3:与前面类似

image-20260604104735617

4.5.4 Example selectors(示例选择器)

前面FewShotPromptTemplate的特点是,无论输入什么问题,都会包含全部示例。在实际开发中,我们可以根据当前输入,使用示例选择器,从大量候选示例中选取最相关的示例子集。

使用的好处:避免盲目传递所有示例,减少 token 消耗的同时,还可以提升输出效果。

示例选择策略:语义相似选择、长度选择、最大边际相关示例选择等

  • 语义相似选择 :通过余弦相似度等度量方式评估语义相关性,选择与输入问题最相似的 个示例。
  • 长度选择 :根据输入文本的长度,从候选示例中筛选出长度最匹配的示例。增强模型对文本结构的理解。比语义相似度计算更轻量,适合对响应速度要求高的场景。
  • 最大边际相关示例选择 :优先选择与输入问题语义相似的示例;同时,通过惩罚机制避免返回同质化的内容

image-20260604104856800

image-20260604104920796

image-20260604104946301

image-20260604105005531

image-20260604105029530

image-20260604105041181

4.6具体使用:PipelinePromptTemplate(了解)

用于将多个提示模板按顺序组合成处理管道,实现分阶段、模块化的提示构建。它的核心作用类似于软件开发中的 管道模式 (Pipeline Pattern),通过串联多个提示处理步骤,实现复杂的提示生成逻辑。

特点

  • 将复杂提示拆解为多个处理阶段,每个阶段使用独立的提示模板

  • 前一个模板的输出作为下一个模板的输入变量

  • 使用场景:解决单一超大提示模板难以维护的问题

说明:PipelinePromptTemplate在langchain 0.3.22版本中被标记为过时,在 langchain-core==1.0之前不会删除它。

https://python.langchain.com/api_reference/core/prompts/langchain_core.prompts.pipeline.Pi pelinePromptTemplate.html

举例:

image-20260604105345956

image-20260604105411604

image-20260604105440477

4.7 具体使用:自定义提示词模版(了解)

在创建prompt时,我们也可以按照自己的需求去创建自定义的提示模版。

步骤

  • 自定义类继承提示词基类模版BasePromptTemplate

  • 重写format、format_prompt、from_template方法

举例:

image-20260604105619785

image-20260604105636748

4.8 从文档中加载Prompt(了解)

一方面,将想要设定prompt所支持的格式保存为JSON或者YAML格式文件。另一方面,通过读取指定路径的格式化文件,获取相应的prompt。

目的与使用场景:

  • 为了便于共享、存储和加强对prompt的版本控制。

  • 当我们的prompt模板数据较大时,我们可以使用外部导入的方式进行管理和维护。

4.8.1 yaml格式提示词

asset下创建yaml文件:prompt.yaml

代码:

image-20260604105727068

image-20260604105819620

4.8.2 json格式提示词

asset下创建json文件:prompt.json

image-20260604105832733

代码:

image-20260604105843669

5、Model I/O之Output Parsers

语言模型返回的内容通常都是字符串的格式(文本格式),但在实际AI应用开发过程中,往往希望 model可以返回更直观、更格式化的内容,以确保应用能够顺利进行后续的逻辑处理。此时, LangChain提供的 输出解析器 就派上用场了。

输出解析器(Output Parser)负责获取 LLM 的输出并将其转换为更合适的格式。这在应用开发中及其重要

5.1 输出解析器的分类

LangChain有许多不同类型的输出解析器

  • StrOutputParser :字符串解析器

  • JsonOutputParser :JSON解析器,确保输出符合特定JSON对象格式

  • XMLOutputParser :XML解析器,允许以流行的XML格式从LLM获取结果

  • CommaSeparatedListOutputParser :CSV解析器,模型的输出以逗号分隔,以列表形式返回输出

  • DatetimeOutputParser :日期时间解析器,可用于将 LLM 输出解析为日期时间格式

除了上述常用的输出解析器之外,还有:

  • EnumOutputParser :枚举解析器,将LLM的输出,解析为预定义的枚举值

  • StructuredOutputParser :将非结构化文本转换为预定义格式的结构化数据(如字典)

  • OutputFixingParser :输出修复解析器,用于自动修复格式错误的解析器,比如将返回的不符合预期格式的输出,尝试修正为正确的结构化数据(如 JSON)

  • RetryOutputParser :重试解析器,当主解析器(如 JSONOutputParser)因格式错误无法解析 LLM 的输出时,通过调用另一个 LLM 自动修正错误,并重新尝试解析

5.2 具体解析器的使用

① 字符串解析器 StrOutputParser

StrOutputParser 简单地将 任何输入 转换为 字符串 。它是一个简单的解析器,从结果中提取content字段

举例:将一个对话模型的输出结果,解析为字符串输出

image-20260604110043207

② JSON解析器 JsonOutputParser

image-20260604110113208

image-20260604110127942

image-20260604110144803

image-20260604110155423

③ XML解析器 XMLOutputParser

image-20260604110239911

image-20260604110251442

image-20260604110313027

image-20260604110330717

image-20260604110344048

image-20260604110355371

image-20260604110413579

④ 列表解析器 CommaSeparatedListOutputParser

列表解析器:利用此解析器可以将模型的文本响应转换为一个用 逗号分隔的列表(List[str])

image-20260604110626994

image-20260604110639761

image-20260604110709069

⑤ 日期解析器 DatetimeOutputParser (了解)

image-20260604110826994

image-20260604110841957

6、LangChain调用本地模型

6.1 Ollama的介绍

Ollama是在Github上的一个开源项目,其项目定位是:一个本地运行大模型的集成框架。目前主要针对主流的LlaMA架构的开源大模型设计,可以实现如 Qwen、Deepseek 等主流大模型的下载、启动和本地运行的自动化部署及推理流程。

目前作为一个非常热门的大模型托管平台,已被包括LangChain、Taskweaver等在内的多个热门项目高度集成。

Ollama官方地址:https://ollama.com

6.2 Ollama的下载-安装

Ollama项目支持跨平台部署,目前已兼容Mac、Linux和Windows操作系统。特别地对于Windows用户提供了非常直观的预览版。

image-20260604111010557

6.3 模型的下载-安装

image-20260604111047289

6.4 调用本地私有模型

举例1:

image-20260604111108578

image-20260604111124137

举例2:

image-20260604111139151

03- LangChain 使用之 Chains

1、Chains的基本使用

1.1 Chain的基本概念

Chain:链,用于将多个组件(提示模板、LLM模型、记忆、工具等)连接起来,形成可复用的 工作流 ,完成复杂的任务。

Chain 的核心思想是通过组合不同的模块化单元,实现比单一组件更强大的功能。比如:

  • LLMPrompt Template (提示模板)结合

  • LLM输出解析器 结合

  • LLM外部数据 结合,例如用于问答

  • LLM长期记忆 结合,例如用于聊天历史记录

  • 通过将 第一个LLM 的输出作为 第二个LLM 的输入,...,将多个LLM按顺序结合在一起

1.2 LCEL 及其基本构成

使用LCEL,可以构造出结构最简单的Chain。

LangChain表达式语言(LCEL,LangChain Expression Language)是一种声明式方法,可以轻松地将多个组件链接成 AI 工作流。它通过Python原生操作符(如管道符 | )将组件连接成可执行流程,显著简化了AI应用的开发。

LCEL的基本构成:提示(Prompt)+ 模型(Model)+ 输出解析器(OutputParser)即:

image-20260604173425571

  • Prompt:Prompt 是一个 BasePromptTemplate,这意味着它接受一个模板变量的字典并生成一个 。PromptValue 可以传递给 LLM(它以字符串作为输入)或 ChatModel(它以消息序列作为输入)。

  • Model:将 PromptValue 传递给 model。如果我们的 model 是一个 ChatModel,这意味着它将输出一个 BaseMessage

  • OutputParser:将 model 的输出传递给 output_parser,它是一个 BaseOutputParser,意味着它可以接受字符串或 BaseMessage 作为输入。

  • chain:我们可以使用元素组合在一起 | 轻松创建这个Chain | 在 LangChain 中用于将两个

  • invoke:所有LCEL对象都实现了Runable 协议,保证一致的调用方式( invoke / batch / stream

image-20260604173658340

1.3 Runnable

Runnable是LangChain定义的一个抽象接口(Protocol),它 强制要求 所有LCEL组件实现一组标准方法:

image-20260604173754170

任何实现了这些方法的对象都被视为LCEL兼容组件。比如:聊天模型、提示词模板、输出解析器、检索器、代理(智能体)等。

每个 LCEL 对象都实现了 Runnable 接口,该接口定义了一组公共的调用方法。这使得 LCEL 对象链也自动支持这些调用成为可能。

2、为什么需要统一调用方式?

传统问题

假设没有统一协议:

  • 提示词渲染用 .format()

  • 模型调用用 .generate()

  • 解析器解析用 .parse()

  • 工具调用用 .run()

代码会变成:

痛点:每个组件调用方式不同,组合时需要手动适配。

3、LCEL解决方案

通过Runable 协议统一:

image-20260604173938964

  • 一致性:无论组件的功能多复杂(模型/提示词/工具),调用方式完全相同

  • 组合性:管道操作符 | 背后自动处理类型匹配和中间结果传递

1.4 使用举例

举例1:

情况1:没有使用chain

image-20260604174043683

image-20260604174058843

情况2:使用chain:将提示模板、模型、解析器链接在一起。使用LCEL将不同的组件组合成一个单一的链条

image-20260604174155685

2、传统Chain的使用

2.1 基础链:LLMChain
2.1.1 使用说明

LCEL之前,最基础也最常见的链类型是LLMChain。

这个链至少包括一个提示词模板(PromptTemplate),一个语言模型(LLM 或聊天模型)。

注意:LLMChain was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use prompt | llm instead。

特点:

  • 用于 单次问答,输入一个 Prompt,输出 LLM 的响应。

  • 适合 无上下文 的简单任务(如翻译、摘要、分类等)。

  • 无记忆:无法自动维护聊天历史

2.1.2主要步骤

1、配置任务链:使用LLMChain类将任务与提示词结合,形成完整的任务链。

image-20260604174418901

2、执行任务链:使用invoke()等方法执行任务链,并获取生成结果。可以根据需要对输出进行处理和展示。

image-20260604174445866

2.1.3 参数说明

image-20260604174528586

image-20260604174549339

image-20260604174602080

2.2 顺序链之 SimpleSequentialChain

顺序链(SequentialChain)允许将多个链顺序连接起来,每个Chain的输出作为下一个Chain的输入,形成特定场景的流水线(Pipeline)。

顺序链有两种类型:

  • 单个输入/输出:对应着 SimpleSequentialChain

  • 多个输入/输出:对应着:SequentialChain

2.2.1 说明

SimpleSequentialChain:最简单的顺序链,多个链 串联执行 ,每个步骤都有 单一 的输入和输出,一个步骤的输出就是下一个步骤的输入,无需手动映射。

2.2.2 使用举例

image-20260604174715820

image-20260604174729097

image-20260604174745977

image-20260604174807125

image-20260604174934035

2.3 顺序链之 SequentialChain
2.3.1 说明

SequentialChain:更通用的顺序链,具体来说:

多变量支持 :允许不同子链有独立的输入/输出变量。

灵活映射 :需 显式定义 变量如何从一个链传递到下一个链。即精准地命名输入关键字和输出关键 字,来明确链之间的关系。

复杂流程控制 :支持分支、条件逻辑(分别通过 input_variables 和 output_variables 配置输入 和输出)。

2.3.2 使用举例

举例1:

image-20260604175259315

image-20260604175309571

image-20260604175330363

image-20260604175358684

image-20260604175415741

2.3.3 顺序链使用场景

场景:多数据源处理

举例:根据产品名

使用 SimpleSequentialChain(会失败)

image-20260604175552015

使用 SequentialChain(正确方式)

image-20260604175614312

2.4 数学链 LLMMathChain (了解)

image-20260604175700874

image-20260604175713043

2. 5 路由链 RouterChain (了解)

路由链(RouterChain)用于创建可以 动态选择下一条链 的链。可以自动分析用户的需求,然后引导到最适合的链中执行,获取响应并返回最终结果。

比如,我们目前有三类chain,分别对应三种学科的问题解答。我们的输入内容也是与这三种学科对应,但是随机的,比如第一次输入数学问题、第二次有可能是历史问题... 这时候期待的效果是:可以根据输入的内容是什么,自动将其应用到对应的子链中。RouterChain就为我们提供了这样一种能力。

image-20260604175809014

RouterChain图示:

2.6 文档链 StuffDocumentsChain(了解)

StuffDocumentsChain 是一种文档处理链,它的核心作用是将 多个文档内容合并 ("填充"或"塞入")到单个提示(prompt)中,然后传递给语言模型(LLM)进行处理。

使用场景 :由于所有文档被完整拼接,LLM 能同时看到全部内容,所以适合需要全局理解的任务,如总结、问答、对比分析等。但注意,仅适合处理 少量/中等长度文档 的场景。

举例:

image-20260604175904032

3、基于LCEL构建的Chains的类型

前面讲解的都是Legacy Chains,下面看最新的基于LCEL构建的Chains。

image-20260604175939350

3.1 create_sql_query_chain

create_sql_query_chain,SQL查询链,是创建生成SQL查询的链,用于将 自然语言 转换成 数据库的 SQL查询

image-20260604180042973

image-20260604180055262

3.2 create_stuff_documents_chain(了解)

image-20260604180215299

04-LangChain 使用之 Memory

1、Memory概述

1.1 为什么需要Memory

大多数的大模型应用程序都会有一个会话接口,允许我们进行多轮的对话,并有一定的上下文记忆能力。

但实际上,模型本身是 不会记忆 任何上下文的,只能依靠用户本身的输入去产生输出。

如何实现记忆功能呢?

实现这个记忆功能,就需要 额外的模块 去保存我们和模型对话的上下文信息,然后在下一次请求时,把所有的历史信息都输入给模型,让模型输出最终结果。

而在 LangChain 中,提供这个功能的模块就称为 Memory(记忆) ,用于存储用户和模型交互的历史信息。

1.2 什么是Memory

Memory,是LangChain中用于多轮对话中保存和管理上下文信息(比如文本、图像、音频等)的组件。它让应用能够记住用户之前说了什么,从而实现对话的 上下文感知能力 ,为构建真正智能和上下文感知的链式对话系统提供了基础。

1.3 Memory的设计理念

image-20260604181305806

问题:一个链如果接入了 Memory 模块,其会与Memory模块交互几次呢?链内部会与 Memory 模块进行两次交互:读取和写入:

1、收到用户输入时,从记忆组件中查询相关历史信息,拼接历史信息和用户的输入到提示词中传给 LLM。

2、返回响应之前,自动把LLM返回的内容写入到记忆组件,用于下次查询。

1.4 不使用Memory模块,如何拥有记忆?

image-20260604181421038

image-20260604181436956

image-20260604181448929

2、基础Memory模块的使用

2.1 Memory模块的设计思路

如何设计Memory模块?

image-20260604181619807

2.2 ChatMessageHistory(基础)

ChatMessageHistory是一个用于 存储和管理对话消息 的基础类,它直接操作消息对象(如 HumanMessage, AIMessage 等),是其它记忆组件的底层存储工具。

在API文档中,ChatMessageHistory 还有一个别名类:InMemoryChatMessageHistory;导包时,需使用:from langchain.memory import ChatMessageHistory

特点

  • 纯粹是消息对象的" 存储器 ",与记忆策略(如缓冲、窗口、摘要等)无关。

  • 不涉及消息的格式化(如转成文本字符串)

场景1:记忆存储

ChatMessageHistory是用于管理和存储对话历史的具体实现。

image-20260604181731330

场景2:对接LLM

image-20260604181758778

image-20260604181809872

2.3 ConversationBufferMemory

ConversationBufferMemory是一个基础的 对话记忆(Memory)组件 ,专门用于按 原始顺序存储 完整的对话历史。

适用场景:对话轮次较少、依赖完整上下文的场景(如简单的聊天机器)

image-20260604181912220

场景1:入门使用

举例1:

image-20260604181952579

举例2:

image-20260604182013832

场景2:结合chain

image-20260604182116646

image-20260604182132781

image-20260604182146544

image-20260604182217004

image-20260604182234294

2.4 ConversationChain

ConversationChain实际上是就是对 ConversationBufferMemoryLLMChain 进行了封装,并且提供一个默认格式的提示词模版(我们也可以不用),从而简化了初始化ConversationBufferMemory的步骤。

举例1:使用PromptTemplate

image-20260604182406439

举例2:使用内置默认格式的提示词模版(内部包含input、history变量)

image-20260604182436520

2.5 ConversationBufferWindowMemory

在了解了ConversationBufferMemory记忆类后,我们知道了它能够无限的将历史对话信息填充到 History中,从而给大模型提供上下文的背景。但这会 导致内存量十分大 ,并且

的,此外,每个大模型都存在最大输入的Token限制。

我们发现,过久远的对话数据往往并不能对当前轮次的问答提供有效的信息,LangChain 给出的解决方式是: ConversationBufferWindowMemory 模块。该记忆类会 保存一段时间内对话交互 的列表,

最近 K 个交互 。这样就使缓存区不会变得太大。

特点:
  • 适合长对话场景。
与 Chains/Models 无缝集成
  • 支持两种返回格式(通过 参数控制输出格式)

    • return_messages=True 返回消息对象列表( List[BaseMessage]

    • return_messages=False (默认) 返回拼接的 纯文本字符串

场景1:入门使用

通过内置在LangChain中的缓存窗口(BufferWindow)可以将meomory"记忆"下来。

举例1:

image-20260604182605067

举例2:

ConversationBufferWindowMemory 也支持使用聊天模型(Chat Model)的情况,同样可以通过

return_messages=True 参数,将对话转化为消息列表形式。

image-20260604182627171

场景2:结合chain

借助提示词模版去构建LangChain

image-20260604182727190

3. 其他Memory模块

3.1 ConversationTokenBufferMemory

ConversationTokenBufferMemory 是 LangChain 中一种基于 Token 数量控制 的对话记忆机制。如果字符数量超出指定数目,它会切掉这个对话的早期部分,以保留与最近的交流相对应的字符数量。

特点

  • Token 精准控制

  • 原始对话保留

原理:

举例:情况1:

image-20260604182905970

情况2:

image-20260604182917320

3.2 ConversationSummaryMemory

image-20260604183022008

原理:

场景1:

如果实例化ConversationSummaryMemory前,没有历史消息,可以使用构造方法实例化

image-20260604183050455

场景2:

如果实例化ConversationSummaryMemory前,已经有历史消息,可以调用from_messages()实例化

image-20260604183109959

3.3 ConversationSummaryBufferMemory

ConversationSummaryBufferMemory 是 LangChain 中一种混合型记忆机制,它结合了 ConversationBufferMemory(完整对话记录)和 ConversationSummaryMemory(摘要记忆)的优点,在保留最近 对话原始记录 的同时,对较早的对话内容进行 智能摘要

特点

  • 保留最近N条原始对话:确保最新交互的完整上下文

  • 摘要较早历史:对超出缓冲区的旧对话进行压缩,避免信息过载

  • 平衡细节与效率:既不会丢失关键细节,又能处理长对话

原理

场景1:入门使用

情况1:构造方法实例化,并设置max_token_limit

image-20260604183210833

情况2:

image-20260604183224736

场景2:客服

image-20260604183257467

3.4 ConversationEntityMemory(了解)

image-20260604183458433

image-20260604183516373

image-20260604183526998

3.5 ConversationKGMemory(了解)

image-20260604183603898

image-20260604183614376

3.6 VectorStoreRetrieverMemory(了解)

image-20260604183735840

image-20260604183746940

05-LangChain 使用之 Tools

1、Tools概述

1.1 介绍

要构建更强大的AI工程应用,只有生成文本这样的" 纸上谈兵 "能力自然是不够的。工具Tools不仅仅是"肢体"的延伸,更是为"大脑"插上了想象力的"翅膀"。借助工具,才能让AI应用的能力真正具备无限的可能,才能从" 认识世界 "走向" 改变世界 "。

Tools 用于扩展大语言模型(LLM)的能力,使其能够与外部系统、API 或自定义函数交互,从而完成仅靠文本生成无法实现的任务(如搜索、计算、数据库查询等)。

特点:

image-20260604185550308

LangChain 拥有大量第三方工具。请访问工具集成查看可用工具列表。 https://python.langchain.com/v0.2/docs/integrations/tools/

1.2 Tool 的要素

Tools 本质上是封装了特定功能的可调用模块,是Agent、Chain或LLM可以用来与世界互动的接口。

Tool 通常包含如下几个要素:
  • name :工具的名称

  • description :工具的功能描述

  • 该工具输入的 JSON模式

  • 要调用的函数

  • return_direct :是否应将工具结果直接返回给用户(仅对Agent相关)

实操步骤:
  • 步骤1:将name、description 和 JSON模式作为上下文提供给LLM
  • 步骤2:LLM会根据提示词推断出 需要调用哪些工具 ,并提供具体的调用参数信息
  • 步骤3:用户需要根据返回的工具调用信息,自行触发相关工具的回调

注意: 如果⼯具具有 精心选择 的名称、描述和JSON模式,则模型的性能将更好。 下⼀章内容我们可以看到⼯具的调⽤动作可以通过Agent⾃主接管。

2、自定义工具

2.1 两种自定义方式

image-20260604185925650

2.2 几个常用属性

image-20260604185945504

2.3 具体实现

方式1:@tool 装饰器

image-20260604190041146

image-20260604190110404

image-20260604190124091

方式2:StructuredTool的from_function()

image-20260604190209024

image-20260604190224425

2. 4 工具调用举例

我们通过大模型分析用户需求,判断是否需要调用指定工具。

举例1:大模型分析调用工具

image-20260604190327272

image-20260604190346834

调用工具说明
两种情况:

image-20260604190430660

image-20260604190519094

image-20260604190538864

06-LangChain使用之Agents

1、理解Agents

通用人工智能(AGI)将是AI的终极形态,几乎已成为业界共识。同样,构建智能体(Agent)则是AI工程应用当下的"终极形态"。

将 AI 和人类协作的程度类比自动驾驶的不同阶段:

1.1 Agent与Chain的区别

在Chain中行动序列是 硬编码的、固定流程的 ,像是"线性流水线",而Agent则采用语言模型作为 推理引擎 ,具备一定的 自主决策 能力,来确定以什么样的顺序采取什么样的行动,像是"拥有大脑的机器工人"。

它可以根据任务 动态决定

  • 如何 拆解任务

  • 需要 调用哪些工具

  • 什么顺序调用

  • 如何利用好 中间结果 推进任务

1.2 什么是Agent

Agent(智能体) 是一个通过动态协调 大语言模型(LLM)工具(Tools) 来完成复杂任务的智能系统。它让LLM充当"决策大脑",根据用户输入自主选择和执行工具(如搜索、计算、数据库查询等),最终生成精准的响应。

1.3 Agent的核心能力/组件

作为一个智能体,需要具备以下核心能力:

  1. 大模型(LLM):作为大脑,提供推理、规划和知识理解能力。

    • 比如:OpenaAI()、ChatOpenAI()
  2. 记忆(Memory):具备短期记忆(上下文)和长期记忆(向量存储),支持快速知识检索。

    • 比如:ConversationBufferMemory、ConversationSummaryMemory、 ConversationBufferWindowMemory等
  3. 工具(Tools):调用外部工具(如API、数据库)的执行单元

    • 比如:SearchTool、CalculatorTool
  4. 规划(Planning):任务分解、反思与自省框架实现复杂任务处理

  5. 行动(Action):实际执行决策的能力

    • 比如:检索、推理、编程
  6. 协作:通过与其他智能体交互合作,完成更复杂的任务目标。

问题:为什么要调用第三方工具(比如:搜索引擎或者 数据库)或借助第三方库呢?

因为大模型虽然非常强大,但是也具备一定的局限性。比如不能回答 实时信息 、处理 复杂数学逻辑 问题仍然非常初级等等。因此,可以借助第三方工具来辅助大模型的应用。

以MCP工具为例说明:https://bailian.console.aliyun.com/?tab=mcp#/mcp-market

1.4 举例

举例1:[扣子平台][https://www.coze.cn/home] 智能体演示举例2:Manus、纳米AI 使用演示

1.5 明确几个组件

Agents 模块有几个关键组件:

1、工具 Tool

LangChain 提供了广泛的入门工具,但也支持 自定义工具 ,包括自定义描述。

在框架内,每个功能或函数被 封装成一个工具 (Tools),具有自己的输入、输出及处理方法。具体使用步骤:

① Agent 接收任务后,通过大模型推理选择适合的工具处理任务。

② 一旦选定,LangChain将任务输入传递给该工具,工具处理输入生成输出。

③ 输出经过大模型推理,可用于其他工具的输入或作为最终结果返回给用户。

2、工具集 Toolkits

在构建Agent时,通常提供给LLM的工具不仅仅只有一两个,而是一组可供选择的工具集(Tool列表),这样可以让 LLM 在完成任务时有更多的选择。

3、智能体/代理 Agent

智能体/代理(agent)可以协助我们做出决策,调用相应的 API。底层的实现方式是通过 LLM 来决定下一步执行什么动作。

4、代理执行器 AgentExecutor

AgentExecutor本质上是代理的运行时,负责协调智能体的决策和实际的工具执行。

AgentExecutor是⼀个很好的起点,但是当你开始拥有更多定制化的代理时,它就不够灵活了。
为了解决这个问题,我们构建了LangGraph,使其成为这种灵活、⾼度可控的运⾏时。

2、Agent 入门使用

2.1 Agent、AgentExecutor的创建

image-20260604191451472

2.2 Agent的类型

image-20260604191545806

在LangChain中Agent的类型就是为你提供不同的"问题解决姿势"的。

API说明:https://python.langchain.com/v0.1/docs/modules/agents/agent_types/

Agents的核心类型有两种模式:

  • 方式1:Funcation Call模式

  • 方式2:ReAct 模式

2.2.1 FUNCATION_CALL模式

image-20260604191710335

2.2.2ReAct 模式

image-20260604191753227

2.3 AgentExecutor创建方式

image-20260604191852341

image-20260604191905611

image-20260604191919176

3、Agent中工具的使用

3.1 传统方式

image-20260604192012421

image-20260604192026482

image-20260604192047650

image-20260604192106179

image-20260604192120497

image-20260604192142959

image-20260604192154540

image-20260604192216643

image-20260604192241641

image-20260604192258930

3.2 通用方式

需求:今天北京的天气怎么样??

image-20260604192514218

image-20260604192534112

image-20260604192550444

image-20260604192607238

image-20260604192622214

image-20260604192642642

image-20260604192658560

image-20260604192727671

image-20260604192757348

4、Agent嵌入记忆组件

4.1 传统方式

image-20260604192907127

image-20260604192921905

image-20260604192934324

image-20260604192948388

4.2 通用方式

image-20260604193051032

image-20260604193102278

image-20260604193132624

image-20260604193149924

image-20260604193157921

image-20260604193212438

image-20260604193222672

07-LangChain使用之Retrieval

Retrieval直接翻译过来即"检索",本章Retrieval模块包括与检索步骤相关的所有内容,例如数据的获取、切分、向量化、向量存储、向量检索等模块。常被应用于构建一个" 企业/私人的知识库 ",提升大模型的整体能力。

1、Retrieval模块的设计意义

1.1 大模型的幻觉问题

拥有记忆后,确实扩展了AI工程的应用场景。

但是在专有领域,LLM无法学习到所有的专业知识细节,因此在 面向专业领域知识 的提问时,无法给出可靠准确的回答,甚至会"胡言乱语",这种现象称之为 LLM的"幻觉"

大模型生成内容的不可控,尤其是在金融和医疗领域等领域,一次金额评估的错误,一次医疗诊断的失误,哪怕只出现一次都是致命的。但,对于非专业人士来说可能难以辨识。目前还没有能够百分之百解决这种情况的方案。

当前大家普遍达成共识的一个方案:

首先,为大模型提供一定的上下文信息,让其输出会变得更稳定。

其次,利用本章的RAG,将检索出来的 文档和提示词 输送给大模型,生成更可靠的答案。

1.2 RAG的解决方案

可以说,当应用需求集中在利用大模型去 回答特定私有领域的知识 ,且知识库足够大,那么除了

微调大模型 外, RAG 就是非常有效的一种缓解大模型推理的"幻觉"问题的解决方案。

LangChain对这一流程提供了解决方案。

如果说LangChain相当于给LLM这个“⼤脑”安装了“四肢和躯⼲”,RAG则是为LLM提供了接
⼊“⼈类知识图书馆”的能⼒。

目前,已经出现了非常多的产品几乎完全建立在 RAG 之上,包括客服系统、基于大模型的数据分析,以及成千上万的数据驱动聊天应用,应用场景五花八门。

1.3 RAG的优缺点

RAG的优点
  1. 相比提示词工程,RAG有 更丰富的上下文和数据样本 ,可以不需要用户提供过多的背景描述,就能生成比较符合用户预期的答案。

  2. 相比于模型微调,RAG可以提升问答内容的 时效性 和 可靠性

  3. 在一定程度上保护了业务数据的 隐私性

RAG的缺点
  1. 由于每次问答都涉及外部系统数据检索,因此RAG的 响应时延 相对较高。

  2. 引用的外部知识数据会 消耗大量的模型Token 资源。

1.4 Retrieval流程

环节1:Source(数据源)

指的是RAG架构中所外挂的知识库。这里有三点说明:

1、原始数据源类型多样:如:视频、图片、文本、代码、文档等

2、形式的多样性:

  • 可以是上百个.csv文件,可以是上千个.json文件,也可以是上万个.pdf文件

  • 可以是某一个业务流程外放的API,可以是某个网站的实时数据等

环节2:Load(加载)

文档加载器(Document Loaders)负责将来自不同数据源的非结构化文本,加载到 内存 ,成为

文档对象包含 文档内容 和相关 元数据信息 ,例如TXT、CSV、HTML、JSON、Markdown、PDF,甚至 YouTube 视频转录等。

文档加载器还支持" 延迟加载 "模式,以缓解处理大文件时的内存压力。

文档加载器的编程接口使用起来非常简单,以下给出加载TXT格式文档的例子。

image-20260604194404469

环节3:Transform(转换)

文档转换器(Document Transformers) 负责对加载的文档进行转换和处理,以便更好地适应下游任务的需求。

文档转换器提供了一致的接口(工具)来操作文档,主要包括以下几类:

  • 文本拆分器(Text Splitters) :将长文本拆分成语义上相关的小块,以适应语言模型的上下文窗口限制。

  • 冗余过滤器(Redundancy Filters) :识别并过滤重复的文档。

  • 元数据提取器(Metadata Extractors) :从文档中提取标题、语调等结构化元数据。

  • 多语言转换器(Multi-lingual Transformers) :实现文档的机器翻译。

  • 对话转换器(Conversational Transformers) :将非结构化对话转换为问答格式的文档。

总的来说,文档转换器是 LangChain 处理管道中非常重要的一个组件,它丰富了框架对文档的表示和操作能力。

在这些功能中,文档拆分器是必须的操作。下面单独说明。

环节3.1:Text Splitting(文档拆分)
  • 拆分/分块的必要性 :前一个环节加载后的文档对象可以直接传入文档拆分器进行拆分,而文档切块后才能 向量化 并存入数据库中。

  • 文档拆分器的多样性 :LangChain提供了丰富的文档拆分器,不仅能够切分普通文本,还能切分 Markdown、JSON、HTML、代码等特殊格式的文本。

  • 拆分/分块的挑战性 :实际拆分操作中需要处理许多细节问题, 不同类型的文本不同的使用场景 都需要采用不同的分块策略。

    • 可以按照 数据类型 进行切片处理,比如针对 文本类数据 ,可以直接按照字符、段落进行切片; 代码类数据 则需要进一步细分以保证代码的功能性;

    • 可以直接根据 token 进行切片处理

在构建RAG应用程序的整个流程中,拆分/分块是最具挑战性的环节之一,它显著影响检索效果。目前还没有通用的方法可以明确指出哪一种分块策略最为有效。不同的使用场景和数据类型都会影响分块策略的选择。

环节4:Embed(嵌入)

文档嵌入模型(Text Embedding Models)负责将 文本 转换为 向量表示 ,即模型赋予了文本计算机可理解的数值表示,使文本可用于向量空间中的各种运算,大大拓展了文本分析的可能性,是自然语言处理领域非常重要的技术。

举例:

  • 实现原理:通过 特定算法 (如Word2Vec)将语义信息编码为固定维度的向量,具体算法细节需后续深入。

  • 关键特性:相似的词在向量空间中距离相近,例如"猫"和"犬"的向量夹角小于"猫"和"汽车"。

文本嵌入为 LangChain 中的问答、检索、推荐等功能提供了重要支持。具体为:

  • 语义匹配 :通过计算两个文本的向量余弦相似度,判断它们在语义上的相似程度,实现语义匹配。

  • 文本检索 :通过计算不同文本之间的向量相似度,可以实现语义搜索,找到向量空间中最相似的文本。

  • 信息推荐 :根据用户的历史记录或兴趣嵌入生成用户向量,计算不同信息的向量与用户向量的相似度,推荐相似的信息。

  • 知识挖掘 :可以通过聚类、降维等手段分析文本向量的分布,发现文本之间的潜在关联,挖掘知识。

  • 自然语言处理 :将词语、句子等表示为稠密向量,为神经网络等下游任务提供输入。

环节5:Store(存储)

LangChain 还支持把文本嵌入存储到向量存储或临时缓存,以避免需要重新计算它们。这里就出现了数据库,支持这些嵌入的高效 存储搜索 的需求。

环节6:Retrieve(检索)

检索器(Retrievers)是一种用于 响应非结构化查询 的接口,它可以返回符合查询要求的文档。

LangChain 提供了一些常用的检索器,如 向量检索器文档检索器网站研究检索器 等。

通过配置不同的检索器,LangChain 可以灵活地平衡检索的精度、召回率与效率。检索结果将为后续的问答生成提供信息支持,以产生更加准确和完整的回答。

2、文档加载器 Document Loaders

LangChain的设计:对于 Source 中多种不同的数据源,我们可以用一种统一的形式读取、调用。

2.1 加载txt

image-20260604195001366

Documment对象中有两个重要的属性:

  • page_content:真正的文档内容

  • metadata:文档内容的原数据

    image-20260604195021774

2.2 加载pdf

image-20260604195050695

image-20260604195103799

image-20260604195114755

image-20260604195126760

2.3 加载CSV

image-20260604195200267

image-20260604195214069

2.4 加载JSON

LangChain提供的JSON格式的文档加载器是 JSONLoader 。在实际应用场景中,JSON格式的数据占有很大比例,而且JSON的形式也是多样的。我们需要特别关注。

JSONLoader 使用指定的 jq结构来解析 JSON 文件。jq是一个轻量级的命令行 JSON 处理器 ,可以对 JSON 格式的数据进行各种复杂的处理,包括数据过滤、映射、减少和转换,是处理 JSON 数据的首选工具之一。

image-20260604195304430

image-20260604195313069

image-20260604195324261

image-20260604195333511

image-20260604195349111

image-20260604195357693

2.5 加载HTML(了解)

image-20260604195440368

2.6 加载 MarkDown(了解)

image-20260604195539902

image-20260604195558559

2.7 加载File Directory(了解)

image-20260604195633431

2.8 BaseLoader、Document源码分析

一方面:LangChain在设计时,要保证Source中多种不同的数据源,在接下来的流程中可以用一种统一的形式读取、调用。

另一方面:为什么 PDFloaderTextLoader 等Document Loader 都使用 load() 去加载,且都使用 .page_content.metadata 读取数据。

【解答】每一个在LangChain中集成的文档加载器,都要继承自 BaseLoader(文档加载器) , BaseLoader提供了一个名为"load"的公开方法,用于从配置的不同 数据源 加载数据,全部作为 Document 对象。实现逻辑如下所示:

BaseLoader类分析

BaseLoader类定义了如何从不同的数据源加载文档,每个基于不同数据源实现的loader,都需要继承

BaseLoader 。Baseloader要求不多,对于任何具体实现的loader,最少都要实现 load方法。

image-20260604195754739

BaseLoader 把数据加载成 Documents object ,存到 Documents 类中的 page_content 中。

Document类分析

Document 允许用户与文档的内容进行交互,可以查看文档内容。

image-20260604195848912

通过 存 + 读的两个基类的抽象,满足不同类型加载器在数据形式上的统一。除此之外,其中的

metadata 会根据loader实现的不同写入不同的数据,同样是一个必要的基础属性。

3、文档拆分器 Text Splitters

image-20260604200054022

image-20260604200107433

image-20260604200120279

image-20260604200139722

image-20260604200158309

image-20260604200301295

image-20260604200319168

image-20260604200334764

image-20260604200349013

image-20260604200401084

image-20260604200413325

image-20260604200440495

image-20260604200453209

image-20260604200508874

image-20260604200517974

image-20260604200530733

image-20260604200548332

image-20260604200600671

image-20260604200620013

image-20260604200638716

image-20260604200657425

image-20260604200716436

image-20260604200729447

image-20260604200756169

image-20260604200807511

image-20260604200820019

image-20260604200832406

4、文档嵌入模型 Text Embedding Models

4.1 嵌入模型概述

Text Embedding Models:文档嵌入模型,提供将文本编码为向量的能力,即 文档向量化 。和 用户查询匹配 前都会先执行文档嵌入编码,即向量化。

  • LangChain提供了 超过25种 不同的嵌入提供商和方法的集成,从开源到专有API,总有一款适合你。

  • Hugging Face等开源社区提供了一些文本向量化模型(例如BGE),效果比闭源且调用API的向量化模型效果好,并且向量化模型参数量小,在CPU上即可运行。所以,这里推荐在开发RAG应用的过程中,使用 开源的文本向量化模型 。此外,开源模型还可以根据应用场景下收集的数据对模型进行微调,提高模型效果。

LangChain中针对向量化模型的封装提供了两种接口,一种针对 文档的向量化(embed_documents) ,一种针对 句子的向量化embed_query

4.2 句子的向量化(embed_query)

image-20260604201052471

4.3 文档的向量化(embed_documents)

文档的向量化,接收的参数是字符串数组。

image-20260604201127718

image-20260604201137732

5、向量存储(Vector Stores)

5.1 理解向量存储

将文本向量化之后,下一步就是进行向量的存储。这部分包含两块:

  • 向量的存储 :将非结构化数据向量化后,完成存储

  • 向量的查询 :查询时,嵌入非结构化查询并检索与嵌入查询"最相似"的嵌入向量。即具有相似性检索能力

5.2 常用的向量数据库

LangChain提供了超过 50种 不同向量存储(Vector Stores)的集成,从开源的 本地向量存储 到的私有向量存储,允许你选择最适合需求的向量存储。

LangChain支持的向量存储参考 VectorStore 接口和实现。

典型的介绍如下:

image-20260604201300905

5.3 向量数据库的理解

假设你是一名摄影师,拍了大量的照片。为了方便管理和查找,你决定将这些 照片存储 到一个数据库中。传统的 关系型数据库 (如 MySQL、PostgreSQL 等)可以帮助你 存储照片的元数据 ,比如拍摄时间、地点、相机型号等。

但是,当你想要根据 照片的内容(如颜色、纹理、物体等) 进行搜索时,传统数据库将无法满足你的需 求,因为它们通常以数据表的形式存储数据,并使用查询语句进行精确搜索。那么此时,向量数据库就可以派上用场

我们可以构建一个多维的空间使得每张照片特征都存在于这个空间内,并用已有的维度进行表示,比如时间、地点、相机型号、颜色. 此照片的信息将作为一个点,存储于其中。以此类推,即可在该空间中

构建出无数的点,而后我们将这些点与空间坐标轴的原点相连接,就成为了一条条向量,当这些点变为向量之后,即可利用向量的计算进一步获取更多的信息。当要进行照片的检索时,也会变得更容易更快捷。

注意:在向量数据库中进行检索时,检索并 不是唯一的、精确的 ,而是查询和目标向量

最为相似的一些向量 ,具有模糊性。

延伸思考:只要对图片、视频、商品等素材进行向量化,就可以实现以图搜图、视频相关推荐、相似宝贝推荐等功能。

5.4 代码实现

使用向量数据库组件时需要同时传入包含 文本块的Document类对象 以及 文本向量化组件 ,向量数据库组件会自动完成将文本向量化的工作,并写入数据库中。

5.4.1 数据的存储

举例1:从TXT文档中加载数据,向量化后存储到Chroma数据库安装模块:

image-20260604201535193

思考:此时数据存储在哪里呢?

注意:Chroma主要有两种存储模式: 内存模式持久化模式 。当使用persist_directory参数时,数据会保存到指定目录;如果没有指定,则默认使用内存存储。

举例2:操作csv文档,并向量化

image-20260604201623720

5.4.2 数据的检索

举例:一个包含构建Chroma向量数据库以及向量检索的代码前置代码:

image-20260604201724997

image-20260604201743719

image-20260604201754711

image-20260604201827036

image-20260604201836654

image-20260604201848281

image-20260604201903286

image-20260604201917598

6、检索器(召回器) Retrievers

6.1介绍

从"向量存储组件"的代码实现5.4.2中可以看到,向量数据库本身已经包含了实现召回功能的函数方法 ( similarity_search )。该函数通过计算原始查询向量与数据库中存储向量之间的相似度来实现召回。

LangChain还提供了 更加复杂的召回策略 ,这些策略被集成在Retrievers(检索器或召回器)组件中。

Retrievers(检索器)是一种用于从大量文档中检索与给定查询相关的文档或信息片段的工具。检索器

不需要存储文档 ,只需要 返回(或检索)文档 即可。

Retrievers 的执行步骤:

步骤1:将输入查询转换为向量表示。

步骤2:在向量存储中搜索与查询向量最相似的文档向量(通常使用余弦相似度或欧几里得距离等度量方法)。

步骤3:返回与查询最相关的文档或文本片段,以及它们的相似度得分。

6.2 代码实现

Retriever 一般和 VectorStore 配套实现,通过 as_retriever() 方法获取。

举例:

image-20260604202112059

6.3 使用相关检索策略

image-20260604202217046

image-20260604202229658

image-20260604202256000

image-20260604202306534

image-20260604202317454

image-20260604202330856

image-20260604202345041

image-20260604202357957

image-20260604202410379

image-20260604202422153

image-20260604202431881

7、项目:智能对话助手

7.1 需求分析

我们将构建一个可以与多种不同工具进行交互的Agent:一个是本地数据库,另一个是搜索引擎。你能够向该Agent提问,观察它调用工具,并与它进行对话。

涉及的功能:
  • 使用 语言模型 ,特别是它们的工具调用能力

  • 创建 检索器 以向我们的Agent公开特定信息

  • 使用 搜索工具 在线查找信息

  • 提供 聊天历史 ,允许聊天机器人 "记住"不同id 过去的交互,并在回答后续问题时考虑它们。

7.2 代码实现

7.2.1 定义工具

image-20260604202627013

7.2.2 定义 Retriever

image-20260604202727704

7.2.3 创建工具、工具集

image-20260604202810984

7.2.4 语言模型调用工具

image-20260604202838826

7.2.5 创建 Agent程序(使用通用方式)

image-20260604202916512

7.2.6 运行 Agent

image-20260604202955925

7.2.7 添加记忆

image-20260604203024864

image-20260604203040726

8、项目:知识库问答助手(了解)

大语言模型虽然可以很好地回答很多领域的各种问题,但是由于其知识是通过语言模型训练及指令微调等方式注入模型参数中的,因此针对本地知识库中的内容,大语言模型很难通过此前的方式有效地进行学习。通过 LangChain 框架,可以有效地融合本地知识库内容与大语言模型的知识问答能力。

基于 LangChain 的知识库问答助手框架如下图所示。

知识库问答助手的工作流程主要包含以下几个步骤。
  1. 收集领域知识数据构造知识库,这些数据应当能够尽可能地全面覆盖问答需求。
  2. 对知识库中的非结构数据进行文本提取和文本分割,得到文本块。
  3. 利用嵌入向量表示模型给出文本块的嵌入表示,并利用向量数据库进行保存。
  4. 根据用户输入信息的嵌入表示,通过向量数据库检索得到最相关的文本片段,将提示词模板与用户提交问题及历史消息合并输入大语言模型。
  5. 将大语言模型结果返回给用户。

image-20260604203306691

image-20260604203322004

image-20260604203342080

image-20260604203354687

image-20260604203404320

posted @ 2026-06-04 21:07  Ref-brief  阅读(48)  评论(1)    收藏  举报