LangChain
为各种大型语言模型应用提供通用接口,从而简化应用程序的开发流程,轻松地构建如下所示的 RAG 应用
-
理解langchain的运作机制
LangChain 是一个为构建大型语言模型(LLMs)驱动的应用程序而设计的框架。它的核心目标是简化从开发到生产的整个应用程序生命周期。
模块化构建:LangChain 提供了一套模块化的构建块和组件,这些组件可以集成到第三方服务中,帮助开发者构建应用程序。
生命周期支持:LangChain 支持整个应用程序的生命周期,从开发到生产化再到部署。
开源与集成:它提供了开源的库和工具,以及与第三方服务的集成。
生产化工具:LangSmith 是一个开发平台,用于调试、测试、评估和监控基于LLM的应用程序。
部署:LangServe 允许将LangChain链作为REST API部署,从而方便应用程序的访问和使用。
-
理解什么是agent,什么是chain
Chain:在LangChain中,Chain 是指一系列按顺序执行的任务或操作,这些任务通常涉及与语言模型的交互。Chain 可以被看作是处理输入、执行一系列决策和操作,最终产生输出的流程。Chain 可以是非常简单的,比如只有一个提示(prompt)和一个语言模型的调用;也可以是非常复杂的,涉及多个步骤和决策点。
Agent:Agent 在LangChain中是一个更为高级和自主的实体,它负责管理和执行Chain。Agent 可以决定何时、如何以及以何种顺序执行Chain中的各个步骤。Agent 通常基于一组规则或策略来模拟决策过程,它们可以观察执行的结果,并根据这些结果来调整后续的行动。Agent 使得LangChain能够构建更为复杂和动态的应用程序,如自动化的聊天机器人或个性化的问答系统。
Agent:基于某模型实现的一个问答系统,就可以看做是一个Agent
Chain:问答系统需要根据一个prompt给出一个回答,这样的任务可以看做是一个Chain,当然,实际的回答过程一般是多个任务(Chain)一个接一个执行得到的。
一个更复杂一些的路由链:
DAG
检索增强生成(RAG, Retrieval-Augmented Generation)。该架构巧妙地整合了从庞大知识库中检索到的相关信息,并以此为基础,指导大型语言模型生成更为精准的答案,从而显著提升了回答的准确性与深度。
目前 LLM 面临的主要问题有:
-
信息偏差/幻觉: LLM 有时会产生与客观事实不符的信息,导致用户接收到的信息不准确。RAG 通过检索数据源,辅助模型生成过程,确保输出内容的精确性和可信度,减少信息偏差。
-
知识更新滞后性: LLM 基于静态的数据集训练,这可能导致模型的知识更新滞后,无法及时反映最新的信息动态。RAG 通过实时检索最新数据,保持内容的时效性,确保信息的持续更新和准确性。
-
内容不可追溯: LLM 生成的内容往往缺乏明确的信息来源,影响内容的可信度。RAG 将生成内容与检索到的原始资料建立链接,增强了内容的可追溯性,从而提升了用户对生成内容的信任度。
-
领域专业知识能力欠缺: LLM 在处理特定领域的专业知识时,效果可能不太理想,这可能会影响到其在相关领域的回答质量。RAG 通过检索特定领域的相关文档,为模型提供丰富的上下文信息,从而提升了在专业领域内的问题回答质量和深度。
-
推理能力限制: 面对复杂问题时,LLM 可能缺乏必要的推理能力,这影响了其对问题的理解和回答。RAG 结合检索到的信息和模型的生成能力,通过提供额外的背景知识和数据支持,增强了模型的推理和理解能力。
-
应用场景适应性受限: LLM 需在多样化的应用场景中保持高效和准确,但单一模型可能难以全面适应所有场景。RAG 使得 LLM 能够通过检索对应应用场景数据的方式,灵活适应问答系统、推荐系统等多种应用场景。
-
长文本处理能力较弱: LLM 在理解和生成长篇内容时受限于有限的上下文窗口,且必须按顺序处理内容,输入越长,速度越慢。RAG 通过检索和整合长文本信息,强化了模型对长上下文的理解和生成,有效突破了输入长度的限制,同时降低了调用成本,并提升了整体的处理效率。
RAG 是一个完整的系统,其工作流程可以简单地分为数据处理、检索、增强和生成四个阶段:
-
数据处理阶段
-
对原始数据进行清洗和处理。
-
将处理后的数据转化为检索模型可以使用的格式。
-
将处理后的数据存储在对应的数据库中。
-
-
检索阶段
-
将用户的问题输入到检索系统中,从数据库中检索相关信息。
-
-
增强阶段
-
对检索到的信息进行处理和增强,以便生成模型可以更好地理解和使用。
-
-
生成阶段
-
将增强后的信息输入到生成模型中,生成模型根据这些信息生成答案。
-
在提升大语言模型效果中,RAG 和 微调(Finetune)是两种主流的方法
微调: 通过在特定数据集上进一步训练大语言模型,来提升模型在特定任务上的表现。
RAG 和 微调的对比可以参考下表
特征比较 | RAG | 微调 |
---|---|---|
知识更新 | 直接更新检索知识库,无需重新训练。信息更新成本低,适合动态变化的数据。 | 通常需要重新训练来保持知识和数据的更新。更新成本高,适合静态数据。 |
外部知识 | 擅长利用外部资源,特别适合处理文档或其他结构化/非结构化数据库。 | 将外部知识学习到 LLM 内部。 |
数据处理 | 对数据的处理和操作要求极低。 | 依赖于构建高质量的数据集,有限的数据集可能无法显著提高性能。 |
模型定制 | 侧重于信息检索和融合外部知识,但可能无法充分定制模型行为或写作风格。 | 可以根据特定风格或术语调整 LLM 行为、写作风格或特定领域知识。 |
可解释性 | 可以追溯到具体的数据来源,有较好的可解释性和可追踪性。 | 黑盒子,可解释性相对较低。 |
计算资源 | 需要额外的资源来支持检索机制和数据库的维护。 | 依赖高质量的训练数据集和微调目标,对计算资源的要求较高。 |
推理延迟 | 增加了检索步骤的耗时 | 单纯 LLM 生成的耗时 |
降低幻觉 | 通过检索到的真实信息生成回答,降低了产生幻觉的概率。 | 模型学习特定领域的数据有助于减少幻觉,但面对未见过的输入时仍可能出现幻觉。 |
伦理隐私 | 检索和使用外部数据可能引发伦理和隐私方面的问题。 | 训练数据中的敏感信息需要妥善处理,以防泄露。 |
核心组件
LangChian 作为一个大语言模型开发框架,可以将 LLM 模型(对话模型、embedding 模型等)、向量数据库、交互层 Prompt、外部知识、外部代理工具整合到一起,进而可以自由构建 LLM 应用。 LangChain 主要由以下 6 个核心组件组成:
-
模型输入/输出(Model I/O):与语言模型交互的接口
-
数据连接(Data connection):与特定应用程序的数据进行交互的接口
-
链(Chains):将组件组合实现端到端应用。比如像
检索问答链
来完成检索问答。 -
记忆(Memory):用于链的多次运行之间持久化应用程序状态;
-
代理(Agents):扩展模型的推理能力。用于复杂的应用的调用序列,执行复杂任务和流程的关键组件,代理集成,以扩展其功能,连接到用户自己的信息源或API;
-
回调(Callbacks):扩展模型的推理能力。用于复杂的应用的调用序列;
在开发过程中,我们可以根据自身需求灵活地进行组合。
LangChain-CLI
langchain提供了一个命令行工具,langchain-cli 通过这个命令行工具可以快速创建基于langchain的应用(访问方式是基于rest api的)。
https://github.com/langchain-ai/langchain/tree/master/libs/cli
使用见视频:https://www.youtube.com/watch?v=r4G2RrLKvF0
对应项目地址: https://github.com/langchain-ai/langchain/tree/master/templates/csv-agent
对应的配置(pirate-speak模板案例)
-
git配置
-
环境变量配置OPENAI_API_KEY和OPENAI_BASE_URL(如果转发API不是直接向api.openai.com发起请求就需要配置后面的base_url)
-
conda创建新环境 python3.11并切换到该环境下,后续操作均在此环境执行(这个模版采用的python版本为3.11)
-
pip换源:
python -m pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
-
安装peotry:
pip install poetry
或pip install poetry --force -i https://mirrors.aliyun.com/pypi/simple/
-
安装langchain:
pip install langchain
-
创建langchain应用:
langchain app new my-app
-
在my-app目录下进入poetry:
poetry shell
-
安装pyproject.toml下定义的poetry依赖:
poetry install
-
运行该模版:
poetry run langchain app add pirate-speak
(y之后等待,该步骤需要下载github上的模板内容,如果报错可能是网络问题,换个网络再试试) -
在./app/server.py中去掉注释内容及if语句上一行的add_routes语句(未添加),加入以下内容:
from pirate_speak.chain import chain as pirate_speak_chain
add_routes(app, pirate_speak_chain, path="\pirate-speak")需要注意,如果是在Windows端启动,path="\pirate-speak“中的斜杠需要换一下,换成path="/pirate-speak",win和Linux的区别。
-
添加完就可以run了:
poetry run langchain serve
-
最后即可在url:http://127.0.0.1:8000/pirate-speak/playground/中查看和使用了
对应的配置(csv-agent模板案例)
在上述模板已经配置过后,配置该模板就可以跳过部分步骤。
-
在my-app目录下:
poetry run langchain app add csv-agent
(Y之后等待即可,网络问题参考上述解决办法) -
在./app/server.py中添加:
from csv_agent import agent_executor as csv_agent_chain
add_routes(app, csv_agent_chain, path="\csv-agent") # win “\”改为“/” -
启动:
poetry run langchain serve
如果爆了如下错:File "C:\xxxxxx\anaconda3\envs\LCTest\Lib\site-packages\langchain_community\vectorstores\faiss.py", line 1078, in load_local #这个路径是你自己的路径
raise ValueError(
ValueError: The de-serialization relies loading a pickle file. Pickle files can be modified to deliver a malicious payload that results in execution of arbitrary code on your machine.You will need to set `allow_dangerous_deserialization` to `True` to enable deserialization. If you do this, make sure that you trust the source of the data. For example, if you are loading a file that you created, and no that no one else has modified the file, then this is safe to do. Do not set this to `True` if you are loading a file from an untrusted source (e.g., some random site on the internet.).那么你需要打开报错中说的faiss.py文件,修改其中的
allow_dangerous_deserialization
为True
即可。这个错误主要是在尝试反序列化(de-serialization)一个使用FAISS库创建的本地向量存储时遇到的问题。FAISS是一个用于高效相似性搜索和密集向量聚类的库,它使用二进制格式存储数据,这需要Python的pickle库来反序列化。
而错误核心在于pickle文件的反序列化被认为是一种安全风险,因为pickle文件可以被修改以执行恶意代码。因此,FAISS库要求在反序列化pickle文件时明确允许这一操作。
-
在urlhttp://127.0.0.1:8000/csv-agent/playground中查看和使用如下:
LangChain LCEL
了解langchain LCEL是什么,看看官方文档提供的示例 https://github.com/langchain-ai/langchain/tree/master/libs/cli 参考:
https://zhuanlan.zhihu.com/p/642443742
https://zhuanlan.zhihu.com/p/651175513
LCEL的设计理念是提供一个强大而灵活的方式来组合不同的组件和服务,从而创建复杂的工作流程。通过LCEL,开发者可以定义数据的流动方式,以及如何在LangChain的不同组件之间转换和处理数据。这种语法的引入,显著提高了LangChain框架的表达能力和易用性。
LCEL(LangChain Expression Language)是LangChain工具包的重要组成部分,它是一种声明式方法,用于组合不同的组件来创建处理链(chain)。LCEL的设计目标是提高文本处理任务的效率和灵活性,它支持流处理、批处理和异步任务,并且具有模块化架构,方便用户定制和修改链组件。
LECL(LangChain Expression Language)是LangChain官方推出的一种新的语法,用于通过组合方式创建链(chain)。这种语言设计出来是为了更易于构建复杂的链,它支持批处理、异步和流处理功能。LCEL的出现是为了与LangChain官方最新发布的LangSmith平台配合使用,帮助用户从原型开发过渡到生产阶段。
LCEL的主要特点包括:
-
简化复杂链的构建:LCEL为构建涉及多次大型语言模型(LLM)调用、构建LLM的输入和使用LLM的输出的复杂链提供了简单的解决方案。
-
自动支持流处理、批处理和异步处理:LCEL内建了对这些高级处理方式的支持,使得开发者可以更容易地实现这些功能。
-
与LangSmith平台的兼容性:LCEL设计时考虑了与LangSmith平台的配合,LangSmith是一个用于构建和部署基于语言模型的应用程序的平台。
-
社区文档和学习资源:LangChain社区提供了关于LCEL的详细介绍和使用方法,包括示例和教程,帮助开发者快速上手。
-
实际应用:LCEL可以用于实现各种应用,如与向量数据库结合,进行知识库的自然语言查询等。
LCEL的关键特性
-
流媒体支持:LCEL构建的链可以以流的形式直接从语言模型(LLM)获取并处理输出,提供快速响应。
-
异步支持:允许链以同步或异步的方式执行,适合在不同环境下(如Jupyter笔记本或LangServe服务器)使用。
-
优化的并行执行:LCEL链中的步骤如果能够并行执行,框架会自动优化以减少延迟。
-
重试和回退机制:为链的任何部分配置重试和回退策略,提高链的可靠性。
-
访问中间结果:允许在最终输出产生之前访问中间步骤的结果,有助于调试和提供反馈。
-
输入和输出模式:为每个LCEL链提供推断出的Pydantic和JSONSchema模式,有助于验证输入和输出。
-
与LangSmith和LangServe的集成:LCEL链自动记录到LangSmith以便于跟踪和调试,同时可以使用LangServe进行部署。
LCEL的应用示例
LCEL通过管道符|
来连接不同的组件,创建一个处理链。例如,一个简单的链可能包含提示模板(prompt)、模型(model)和输出解析器(output_parser)。
chain = (prompt | model | output_parser)
这个链将用户的输入传递给提示模板,模板生成的提示再传递给模型进行处理,最后由输出解析器将模型的输出转换为最终结果。
LCEL的实际应用
LCEL不仅支持简单的链,还可以构建更复杂的链,如结合向量数据库进行检索增强的生成(RAG)查询。在这些复杂的应用中,LCEL提供了RunnableMap、RunnableParallel等原语来并行化组件、动态配置内部链等。