这篇文档介绍了LangChain大模型应用开发框架的入门知识和核心内容,包括LangChain是什么、为什么需要它、典型使用场景、基础概念与模块化设计等。同时,还详细阐述了该框架的核心模块如标准化的大模型抽象、大模型应用的最佳实践、赋予应用记忆的能力、框架原生的数据处理流等。
Q:为什么开发者要用 LangChain 而不是直接使用 OpenAl 或者Hugging Face 上的模型?
A:Hugging Face、OpenAl、Cohere 可以提供底座模型和 API, 但是在产品中集成和使用它们仍然需要大量的工作。
可以理解为,LangChain 框架有利于应用开发者通过调用一个统一的接口,代替产品研发过程中模型、数据结构等变动因素,从而实现相同接口直接调用,而不是单一修改源代码或模型。为上面的应用开发者提供了便利,那对下面的模型也是一样啊,因为下面的模型不管你怎么迭代,你最终一个大模型。
产品示例1: OpenAI-Translator
LangChain 典型使用场景:RAG (Retrieval-Augmented Generation)
- Embedding Model:将文本变成高维向量;
- 向量数据库:存储高维向量,是大语言模型的第二大脑;
- 大语言模型:解码向量数据库的内容后,可以通过prompt实现大语言模型来完成任务总结并返回用户的过程。
- 提示模板(Prompt Templates):参数化的模型输入,Prompt Templates 提供了一种预定义、动态注入、模型无关和参数化的提示词生成方式,以便在不同的语言模型之间重用模板。一个模板可能包括指令、少量示例以及适用于特定任务的具体背景和问题。
- 示例选择器(Example Selectors):动态选择要包含在提示中的示例
Memory
第三个重要功能模块就是Memory,实现记忆历史对话内容。大多数LLM应用都具有对话界面。对话的一个重要组成部分是能够引用先前在对话中介绍过的信息。至少,一个对话系统应该能够直接访问一些过去消息的窗口。更复杂的系统将需要拥有一个不断更新的世界模型,使其能够保持关于实体及其关系的信息。大模型本身是概率模型,基于前置条件,即输入和分布,即可得出对应输出。但是整个流程是一次性的,对于初始的且没有经过任何处理的大模型,是不具备记忆存储功能,这个功能模块是需要应用开发者进行开发的。
Agent
最后就是Agent,包括应用实际运行起来的运行时,典型的内置实现叫做Agent Executor。由于大模型只有一个大脑,成为真正的智能体应用就需要连接并调用外部的工具,Langchain也预定义了很多Toolkits。
对于data connection功能模块,实现了数据的连接转换。那怎么体现data connection呢?其实从上图可以看到主要的四个模块,包括chain和最终的应用。这些流动的链条实质是各种各样类型的数据,而不同格式、不同类型、形态等的数据转换其实就是data connection模块所解决的问题。那Chain应该怎么理解呢?就是提供数据流动的管道。
第一类是模型抽象Model语言模型(LLMs): LangChain 的核心组件。LangChain并不提供自己的LLMs,而是为与许多不同的LLMs(OpenAI、Cohere、Hugging Face等)进行交互提供了一个标准接口。LLMs属于较低层次的大语言模型,因为该阶段的大语言模型只有生成能力,还没有对话能力。
第二类聊天模型(Chat Models): 语言模型的一种变体。虽然聊天模型在内部使用了语言模型,但它们提供的接口略有不同。与其暴露一个“输入文本,输出文本”的API不同,它们提供了一个以“聊天消息”作为输入和输出的接口。该模型是优化了模型对话能力的提升后的大模型,例如Open AI的GPT系列。该模型存在角色概念以及Memory存储功能,将这些功能进行抽象后在最终应用层面体现为不同类型的Agents。当下游获取大模型的反馈结果后,其输出结果是一个统一格式,以便于后续基于结果再加工处理。针对该问题引入了一个抽象功能,即output parser。这个功能是根据输出parser类型转变为一预期特定的数据结构,例如json、key-value以及字符串模版等形式。
- Chat Models类继承关系:
BaseLanguageModel --> BaseChatModel --> name(Examples: ChatOpenAI, ChatGooglePalm) - Chat Models主要抽象:
AIMessage, BaseMessage, HumanMessage
输出解析器 Output Parser
语言模型的输出是文本。
但很多时候,用户可能希望获得比纯文本更结构化的信息。这就是输出解析器的价值所在。
输出解析器是帮助结构化语言模型响应的类。它们必须实现两种主要方法:
- “获取格式指令”:返回一个包含有关如何格式化语言模型输出的字符串的方法。
- “解析”:接受一个字符串(假设为来自语言模型的响应),并将其解析成某种结构。
然后还有一种可选方法:
- “使用提示进行解析”:接受一个字符串(假设为来自语言模型的响应)和一个提示(假设为生成此响应的提示),并将其解析成某种结构。在需要重新尝试或修复输出,并且需要从提示中获取信息以执行此操作时,通常会提供提示。
LangChain 设计:实现联网查询
LangChain 设计:结合联网与向量数据库
LLMChain: 整合语言模型和提示模板的最简单链
SequentialChain: 串联式调用语言模型链
串联式调用语言模型(将一个调用的输出作为另一个调用的输入)。
顺序链(Sequential Chain)允许用户连接多个链并将它们组合成执行特定场景的流
水线(Pipeline)。有两种类型的顺序链:
- SimpleSequentialChain:最简单形式的顺序链,每个步骤都具有单一输入/输出,
并且一个步骤的输出是下一个步骤的输入。 - SequentialChain:更通用形式的顺序链,允许多个输入/输出。
SequentialChain: 多输入/输出串联调用
TransformChain: 处理超长文本的转换链
RouterChain: 实现条件判断的大模型调用
LangChain提供了许多用于向应用/系统中添加 Memory 的实用工具。这些工具可以单独使用,也可以无缝地集成到链中。
一个记忆系统(Memory System)需要支持两个基本操作:读取(READ)和写入(WRITE)。
每个链都定义了一些核心执行逻辑,并期望某些输入。其中一些输入直接来自用户,但有些输入可能来自 Memory。
在一个典型 Chain 的单次运行中,将与其 Memory System 进行至少两次交互:
- 在接收到初始用户输入之后,在执行核心逻辑之前,链将从其 Memory 中读取并扩充用户输入。
- 在执行核心逻辑之后但在返回答案之前,一个链条将把当前运行的输入和输出写入 Memory ,以便在未来的运行中可以引用它们。
- CSV
- HTML
- JSON
- Markdown
- File Directory
- …
部分典型数据源:
- ArXiv
- BiiBii
- Discord
- Figma
- GitHub
- TensorFlow Datasets
- …
- 这个类旨在为所有这些提供者提供一个标准接口。
嵌入将一段文本创建成向量表示。这非常有用,因为它意味着我们可以在向量空间中思考文本,并且可以执行语义搜索等操作,在向量空间中寻找最相似的文本片段。
LangChain中基础的Embeddings类公开了两种方法:一种用于对文档进行嵌入,另一种用于对查询进行嵌入。前者输入多个文本,而后者输入单个文本。之所以将它们作为两个独立的方法,是因为某些嵌入提供者针对要搜索的文件和查询(搜索查询本身)具有不同的嵌入方法。
- Document 类:Document的类,允许用户与文档的内容进行交互,可以查看文档的段落、摘要,以及使用查找功能来查询文档中的特定字符串。
- 使用 OpenAIEmbeddings 调用 OpenAI 嵌入模型
- 使用 embed_documents 方法嵌入文本列表
- 使用 embed_query 方法嵌入问题