1. 背景和介绍
LangChain是一个框架,帮助开发者使用语言模型来构建应用程序,这个框架提供了一系列的工具和组件,让你可以简单的创建大模型应用程序,LangChain可以让你方便管理语言模型的交互,将多个组件链接在一起,并可以访问外部的资源,如果API和数据库等。
类比:LongChain在大模型开发中的位置,相当于Spring在java开发中的位置。
LongChain解决什么问题
目前大模型应用中遇到的问题:
- Token限制
- 数据信息滞后
- 无法联网
- 没法查询数据库
- 调用第三方API困难
- 模型技术选型多
以上问题都可以通过LongChain去优雅的解决。
总结:LongChain是目前大模型应用开发中最好用的一站式开发框架。
2. 核心模块
LongChain的核心模块包括:
- Model I/0
- Chains
- Retrieval
- Memory
- Agents
- Callbacks
- LongServer
2.1 Model I/0
主要包括以下三个部分:
- Prompts:一个语言模型的提示是用户提供的一组指令或输入,用于引导模型的响应,帮助它理解上下文并生成相关和连贯的基于语言的输出,例如回答问题、完成句子或进行对话。
- 提示模板(Prompt Templates):参数化的模型输入
- 示例选择器(Example Selectors):动态选择要包含在提示中的示例
- LLMs:LangChain 的核心组件,LangChain并不提供自己的LLMs,而是为与许多不同的LLMs(OpenAI、Cohere、Hugging Face等)进行交互提供了一个标准接口。
- Chat Models: 语言模型的一种变体。虽然聊天模型在内部使用了语言模型,但它们提供的接口略有不同。与其暴露一个“输入文本,输出文本”的API不同它们提供了一个以“聊天消息”作为输入和输出的接口(类似于Chat Completion)
- Parser:语言模型输出文本。但是很多时候,你可能希望获得比纯文本更结构化的信息。这就是输出解析器的用处。输出解析器是帮助结构化语言模型响应的类。
可以理解为:选择合适的prompt,调用去调用LLM,返回结果,然后解析为我们想要的格式。
2.2 Chains
LLM中常见的链式操作类型:
- SequentialChain: 串联式调用语言模型链
- 在调用语言模型之后,下一步是对语言模型进行一系列的调用。当您希望将一次调用的输出作为另一次调用的输入时,这是特别有用的。
- RouterChain: 实现条件判断的大模型调用
- 路由允许您创建非确定性链,其中前一步的输出定义下一步。路由有助于在与LLMs的交互中提供结构和一致性。
- Transformation: 数据传递过程中进行数据处理。
- 通常在组件之间传递输入时,我们希望对其进行转换。例如,我们将创建一个虚拟转换,它接收一个超长的文本,将文本筛选为前三段,然后将其传递到一个链中进行摘要。
2.3 Memory
大多数LLM应用程序都具有对话界面。对话的一个重要组成部分是能够引用先前在对话中介绍的信息。至少,一个对话系统应该能够直接访问一些过去消息的窗口。一个更复杂的系统需要有一个不断更新的模型,使其能够保持关于实体及其关系的信息。我们将存储关于过去交互的信息的能力称为"内存"。
LangChain为系统添加内存提供了许多实用工具。这些实用工具可以单独使用,也可以无缝地集成到链中。内存系统需要支持两个基本操作:读取和写入。
请记住,每个链都定义了某些核心执行逻辑,该逻辑期望某些输入。其中一些输入直接来自用户,但某些输入可能来自内存。在给定的运行中,链将两次与其内存系统交互。
- 在接收到初始用户输入之后但在执行核心逻辑之前,链将从其内存系统中读取并增加用户输入。
- 在执行核心逻辑后但在返回答案之前,链将将当前运行的输入和输出写入内存,以便在将来的运行中引用。
2.4 Retrieval
- Document loaders:文档加载器,不同类型的文件加载器如下:
- CSVLoader
- TextLoader
- Document transformers:
- Recursively split by character:按照字符分割
"text_splitter = RecursiveCharacterTextSplitter(\n",
"chunk_size = 100, # 块大小(每个分割文本的字符数量)\n",
"chunk_overlap = 20, # 块重叠(两个相邻块之间重叠的字符数量)\n",
"length_function = len, # 长度函数(用于计算文本长度的函数)\n",
"add_start_index = True, # 添加起始索引(是否在结果中包含分割文本的起始索引)\n",
")"
- Text embedding models
- vector store
- Retriever
- Ensemble Retriever:集合检索器(Ensemble Retriever)接受一组检索器作为输入,并将它们的get_relevant_documents()方法的结果进行集成,并根据互惠排序,融合算法对结果进行重新排序。通过发挥不同算法的优势,集合检索器可以比单一算法获得更好的性能。
- 最常见的模式是将稀疏检索器(如BM25)与密集检索器(如嵌入相似度)相结合,因为它们的优势互补。这也被称为“混合搜索”。稀疏检索器擅长基于关键词找到相关文档,而密集检索器擅长基于语义相似度找到相关文档。
2.5 Agent
如果说chains模式是model(prompt - llm - parser)普通链式调用的一层抽象,即可以实现不同链式调用。
那么,agent模式就是chain的更高一层抽象。
设计理念:
AgentExecutor:
- prompt:
- 用户输入
- 模型输入
- 上下文
- 思考链模式:
- React:通过大模型的推理能力,自己通过分析Reason,然后去获取结果,这里可以是function call 或者 各种toolkits
- Plan-and-execute Agent:按照一定策略来一步一步执行
- output
- parser
2.6 Callbacks
回调模块允许接到LLM应用程序的各个阶段,鉴于LLM的幻觉问题,这对于日志记录、监视、流式处理和其他任务非常有用。
2.7 LongServer
LangServe 则提供了将 LCEL 原型部署成产品服务的完整解决方案。它可以将 LCEL 应用链接入到一系列成熟到 Python 的 Web框架(例如 FastAPI、Pydantic、uvloop、asyncio)中并生成一套 RESTful API,开发者无需自己编写这部分逻辑就可以直接得到生产可用的 API,并得以保证 API 在高并发场景下的稳定性与性能。它同时也提供了输入输出数据结构校验、并发请求处理、流式响应等服务化所需的各种功能。有了LangServe,开发者可以“从零到一”无缝地实现 LLM 应用从原型到产品的过渡。
3. 架构设计
3.1 设计目标
- 常用的操作API能力
- Agent能力
- 快速部署能力
- 监控能力
3.2 架构之道
可以分为3层:
- 面向Model层:
- Memory:Buffer、KV DB 、vector DB、Sql DB
- DataContion:
- Medol I/O:
- 面向Chain:
- 基础大模型
- 对话QA
- 检索QA
- 面向agen
- ReAct
- Plan-execute
- Tools
3.3 特点
从工程角度看:
- Prompt设计能力是核心
- 核心使用的是大模型的对语言理解的能力
- 传统的架构能力依然是核心
能做的:
- 调整提示词
- 调整模型
- 调整描述(function call)
- 调整思维链
- 调整Tools
缺点:
- 强依赖大模型的能力
- 调用链路过程
- 迁移能力弱