这部分包含了对LangChain关键部分的介绍。
架构
LangChain作为一个框架,由多个包组成。
langchain-core
这个包包含了不同组件的基础抽象以及将它们组合在一起的方式。这里定义了LLMs(大型语言模型)、向量存储(vectorstores)、检索器(retrievers)等核心组件的接口。这里没有定义第三方集成。故意保持依赖非常轻量。
合作伙伴包
虽然大部分集成都在langchain-community
中,我们将流行的集成拆分到它们自己的包中(例如langchain-openai
、langchain-anthropic
等)。这样做是为了改善对这些重要集成的支持。
langchain
主要的langchain
包包含了构成应用程序认知架构的链条、代理和检索策略。这些不是第三方集成。这里的所有链条、代理和检索策略都不是针对任何特定集成的,而是通用于所有集成。
langchain-community
这个包包含了由LangChain社区维护的第三方集成。关键的合作伙伴包被分开出来(见下文)。它包含了各种组件(LLMs、向量存储、检索器)的所有集成。这个包中的所有依赖都是可选的,以保持包尽可能轻量。
langgraph
langgraph
是langchain
的扩展,旨在通过将步骤建模为图中的边和节点,构建健壮且具有状态的多参与者应用程序与LLMs。
LangGraph提供了创建常见类型代理的高级接口,以及用于组合自定义流程的低级API。
langserve
langserve
是一个包,用于将 LangChain 链条部署为 REST API。它使得轻松地启动一个生产就绪的API变得容易。
LangSmith
LangSmith 是一个开发平台,让您可以调试、测试、评估和监控LLM应用程序。
LangChain 表达式语言(LCEL)
LangChain 表达式语言(LCEL)是一种声明式方法,用于连接 LangChain 组件。LCEL 从第一天起就被设计为支持将原型产品化,无需代码变更,从最简单的“提示 + LLM”链到最复杂的链(我们看到有人成功地在生产中运行了具有数百个步骤的 LCEL 链)。以下是您可能想要使用 LCEL 的几个原因:
一流的流式支持 当您使用 LCEL 构建链时,您将获得最佳的首次令牌时间(直到第一个输出块出现所经过的时间)。对于一些链,这意味着例如我们直接从 LLM 流式传输到流式输出解析器,并且您以与 LLM 提供商输出原始令牌的相同速率获得解析后的增量输出块。
异步支持 使用 LCEL 构建的任何链都可以使用同步 API(例如,在原型设计时在您的 Jupyter 笔记本中)以及异步 API(例如,在 LangServe 服务器中)进行调用。这使得您可以在原型和生产中使用相同的代码,具有出色的性能,并且能够在同一个服务器中处理许多并发请求。
优化的并行执行 每当您的 LCEL 链有可以并行执行的步骤时(例如,如果您从多个检索器获取文档),我们会自动执行它,无论是在同步还是异步接口中,以实现最小的延迟。
重试和回退 为您的 LCEL 链的任何部分配置重试和回退。这是使您的链在大规模上更可靠的一种好方法。我们目前正在努力为重试/回退添加流式支持,以便您可以在不增加任何延迟成本的情况下获得额外的可靠性。
访问中间结果 对于更复杂的链,通常在最终输出产生之前访问中间步骤的结果非常有用。这可以让用户知道正在发生一些事情,或者只是调试您的链。您可以流式传输中间结果,并且它在每个 LangServe 服务器上都可用。
输入和输出模式 输入和输出模式为每个 LCEL 链提供了从链的结构中推断出的 Pydantic 和 JSONSchema 模式。这可以用于验证输入和输出,并且是 LangServe 的一个重要部分。
无缝 LangSmith 跟踪 当您的链变得越来越复杂时,了解每一步确切发生的情况变得越来越重要。使用 LCEL,所有 步骤都会自动记录到 LangSmith,以实现最大的可观察性和可调试性。
无缝 LangServe 部署 使用 LCEL 创建的任何链都可以轻松地使用 LangServe 进行部署。
Runnable 接口
为了尽可能容易地创建自定义链,我们实现了一个 “Runnable” 协议。许多 LangChain 组件实现了 Runnable
协议,包括聊天模型、LLM、输出解析器、检索器、提示模板等。还有一些有用的原语用于处理可运行项,您可以在下面阅读有关它们的信息。
这是一个标准接口,使您能够以标准方式定义自定义链以及以标准方式调用它们。标准接口包括:
这些也有相应的异步方法,应该与 asyncio await
语法一起使用以实现并发:
astream
: 异步流式返回响应块ainvoke
: 异步对输入调用链abatch
: 异步对输入列表调用链astream_log
: 除了最终响应外,还流式返回中间步骤astream_events
: beta 在链中发生时流式传输事件(在langchain-core
0.1.14 中引入)
输入类型 和 输出类型 因组件而异:
组件 | 输入类型 | 输出类型 |
---|---|---|
提示 | 字典 | PromptValue |
聊天模型 | 单个字符串、聊天消息列表或 PromptValue | 聊天消息 |
LLM | 单个字符串、聊天消息列表或 PromptValue | 字符串 |
输出解析器 | LLM 或聊天模型的输出 | 取决于解析器 |
检索器 | 单个字符串 | 文档列表 |
工具 | 单个字符串或字典,取决于工具 | 取决于工具 |
所有可运行项都公开输入和输出 模式 以检查输入和输出:
input_schema
: 从 Runnable 结构自动生成的输入 Pydantic 模型output_schema
: 从 Runnable 结构自动生成的输出 Pydantic 模型
组件
LangChain 提供了标准、可扩展的接口和各种组件的外部集成,这些组件对于使用 LLMs 构建非常有用。LangChain 实现了一些组件,我们依赖第三方集成提供一些组件,还有一些是混合的。
聊天模型
将一系列消息作为输入并返回聊天消息作为输出的语言模型(与使用纯文本不同)。这些通常是更新的模型(旧模型通常是 LLMs
,请参见上文)。聊天模型支持为对话消息分配不同角色,有助于区分来自 AI、用户和系统消息的消息。
尽管底层模型是消息输入、消息输出,但 LangChain 包装器还允许这些模型将字符串作为输入。这意味着您可以轻松地将聊天模型用于 LLMs。
当将字符串作为输入传递时,它会被转换为 HumanMessage,然后传递给底层模型。
LangChain 没有提供任何聊天模型,而是依赖于第三方集成。
我们在构建 ChatModels 时有一些标准化参数:
model
: 模型的名称
ChatModels 还接受特定于该集成的其他参数。
信息
工具调用 一些聊天模型已经针对工具调用进行了微调,并提供了专用的 API 用于工具调用。通常,这类模型在工具调用方面比未微调的模型更好,建议在需要工具调用的用例中使用。有关更多信息,请参见 工具调用部分。
LLMs
接受字符串作为输入并返回字符串的语言模型。这些通常是旧模型(新模型通常是 ChatModels
,请参见上文)。
尽管底层模型是字符串输入、字符串输出,但 LangChain 包装器还允许这些模型将消息作为输入。这使它们与 ChatModels 可互换。当将消息作为输入传递时,它们将在内部转换为字符串,然后传递给底层模型。
LangChain 没有提供任何 LLMs,而是依赖于第三方集成。
消息
一些语言模型以消息列表作为输入并返回一条消息。有几种不同类型的消息。所有消息都有 role
、content
和 response_metadata
属性。
role
描述了谁在说这条消息。LangChain 为不同的角色有不同的消息类。
content
属性描述了消息的内容。这可以是几种不同的事物:
- 一个字符串(大多数模型处理这种类型的内容)
- 一个字典列表(这用于多模态输入,其中字典包含有关输入类型和输入位置的信息)
HumanMessage
这代表来自用户的消息。
AIMessage
这代表来自模型的消息。除了 content
属性外,这些消息还有:
response_metadata
response_metadata
属性包含有关响应的额外元数据。这里的数据通常特定于每个模型提供商。这是存储诸如 log-probs 和 token 使用情况等信息的地方。
tool_calls
这些表示语言模型调用工具的决定。它们被包括在 AIMessage
输出中。您可以使用 .tool_calls
属性从那里访问它们。
此属性返回一个字典列表。每个字典都有以下键:
name
: 应调用的工具的名称。args
: 该工具的参数。id
: 该工具调用的 id。
SystemMessage
这代表系统消息,它告诉模型如何表现。并非每个模型提供商都支持这一点。
FunctionMessage
这代表函数调用的结果。除了 role
和 content
,此消息还有一个 name
参数,它传达了为产生此结果而调用的函数的名称。
ToolMessage
这代表工具调用的结果。为了与 OpenAI 的 function
和 tool
消息类型匹配,这与 FunctionMessage 不同。除了 role
和 content
,此消息还有一个 tool_call_id
参数,它传达了为产生此结果而调用的工具的 id。
提示模板
提示模板有助于将用户输入和参数转换为给语言模型的指令。这可以用来引导模型的响应,帮助它理解上下文并生成相关和连贯的语言输出基础。
提示模板以字典作为输入,其中每个键代表提示模板中要填充的变量。
提示模板输出一个 PromptValue。这个 PromptValue 可以传递给 LLM 或聊天模型,也可以转换为字符串或消息列表。存在 PromptValue 的原因是为了方便在字符串和消息之间进行切换。
有几种不同类型的提示模板
字符串提示模板
这些提示模板用于格式化一个单独的字符串,通常用于更简单的输入。例如,构建和使用 PromptTemplate 的一个常见方式如下:
from langchain_core.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template("Tell me a joke about {topic}")
prompt_template.invoke({"topic": "cats"})
API 参考:PromptTemplate
聊天提示模板
这些提示模板用于格式化消息列表。这些“模板”由它们自己的模板列表组成。例如,构建和使用 ChatPromptTemplate 的一个常见方式如下:
from langchain_core.prompts import ChatPromptTemplate
prompt_template = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
("user", "Tell me a joke about {topic}")])
prompt_template.invoke({"topic": "cats"})
API 参考:ChatPromptTemplate
在上面的示例中,当调用这个 ChatPromptTemplate 时,它将构造两条消息。第一个是系统消息,没有变量要格式化。第二个是 HumanMessage,将由用户传入的 topic
变量格式化。
消息占位符
此提示模板负责在特定位置添加消息列表。在上面的 ChatPromptTemplate 中,我们看到了如何格式化两条消息,每个消息都是一个字符串。但是,如果我们想要用户传入一个消息列表,我们将它们插入到特定位置呢?这就是如何使用 MessagesPlaceholder。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage
prompt_template = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
MessagesPlaceholder("msgs")])
prompt_template.invoke({"msgs": [HumanMessage(content="hi!")]})
API 参考:ChatPromptTemplate | MessagesPlaceholder | HumanMessage
这将产生两条消息的列表,第一条是系统消息,第二条是我们传入的 HumanMessage。如果我们传入了 5 条消息,那么它将总共产生 6 条消息(系统消息加上传入的 5 条)。这有助于将消息列表插入到特定位置。
实现同样事情的另一种方法是不显式使用 MessagesPlaceholder
类:
prompt_template = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
("placeholder", "{msgs}") # <-- 这是改变的部分])
示例选择器
为了获得更好的性能,包括示例作为提示的一部分是一种常见的提示技术。这为语言模型提供了它应该如何表现的具体示例。有时这些示例被硬编码到提示中,但对于更高级的情况,动态选择它们可能更好。示例选择器是负责选择然后格式化示例到提示中的类。
输出解析器
注意
这里指的是将模型的文本输出解析成更结构化表示的解析器。越来越多的模型支持函数(或工具)调用,这可以自动处理。建议使用函数/工具调用而不是输出解析。请参见这里的文档。
负责将模型的输出转换为更适合下游任务的格式。当您使用 LLM 生成结构化数据或规范化聊天模型和 LLM 的输出时非常有用。
LangChain 有许多不同类型的输出解析器。这是 LangChain 支持的输出解析器列表。下面的表格有各种信息:
名称: 输出解析器的名称
支持流式: 输出解析器是否支持流式。
具有格式指令: 输出解析器是否有格式指令。这通常可用,除非(a)期望的模式不是在提示中指定的,而是在其他参数中(如 OpenAI 函数调用),或(b)当 OutputParser 包装另一个 OutputParser 时。
调用 LLM: 此输出解析器本身是否调用 LLM。这通常只由试图纠正格式错误的输出解析器完成。
输入类型: 预期的输入类型。大多数输出解析器在字符串和消息上工作,但有些(如 OpenAI 函数)需要具有特定 kwargs 的消息。
输出类型: 由解析器返回的对象的输出类型。
描述: 我们对这种输出解析器的评论以及何时使用它。
名称 | 支持的流 | 有格式说明 | Calls LLM | 输入类型 | 输出类型 | 描述 | |
---|---|---|---|---|---|---|---|
JSON | ✅ | ✅ | str |
Message |
JSON object | 返回指定的 JSON 对象。您可以指定一个 Pydantic 模型,它将返回该模型的 JSON。可能是获取结构化数据最可靠的输出解析器,不使用函数调用。 | |
XML | ✅ | ✅ | str |
Message |
dict |
返回标签的字典。当需要 XML 输出时使用。使用擅长编写 XML 的模型(如 Anthropic 的模型)。 | |
CSV | ✅ | ✅ | str |
Message |
List[str] |
返回逗号分隔值的列表。 | |
OutputFixing | ✅ | str |
Message |
包装另一个输出解析器。如果该输出解析器出错,那么这个解析器会将错误信息和错误输出传递给 LLM 并请求修正输出。 | |||
RetryWithError | ✅ | str |
Message |
包装另一个输出解析器。如果该输出解析器出错,那么这个解析器会将原始输入、错误输出和错误信息传递给 LLM 并请求修正。与 OutputFixingParser 相比,这个解析器还会发送原始指令。 | |||
Pydantic | ✅ | str |
Message |
pydantic.BaseModel |
接受用户定义的 Pydantic 模型并返回该格式的数据。 | ||
YAML | ✅ | str |
Message |
pydantic.BaseModel |
接受用户定义的 Pydantic 模型并返回该格式的数据。使用 YAML 进行编码。 | ||
PandasDataFrame | ✅ | str |
Message |
dict |
用于执行 Pandas DataFrame 操作。 | ||
Enum | ✅ | str |
Message |
Enum |
将响应解析为提供的枚举值之一。 | ||
Datetime | ✅ | str |
Message |
datetime.datetime |
将响应解析为 datetime 字符串。 | ||
Structured | ✅ | str |
Message |
Dict[str, str] |
一个返回结构化信息的输出解析器。它比其他输出解析器功能弱,因为它只允许字段为字符串。当使用较小的 LLM 时,这可能是有用的。 |
Chat history
大多数 LLM 应用都有对话界面。对话的一个基本组成部分是能够引用对话中先前引入的信息。至少,一个对话系统应该能够直接访问某些过去消息的窗口。
ChatHistory
概念指的是 LangChain 中的一个类,它可以用于包装任意链。这个 ChatHistory
将跟踪基础链的输入和输出,并将它们作为消息附加到消息数据库中。未来的交互将加载这些消息,并将它们作为输入的一部分传递给链。
Documents
LangChain 中的 Document 对象包含有关某些数据的信息。它有两个属性:
page_content: str
: 文档的内容。目前只是一串文本。metadata: dict
: 与此文档关联的任意元数据。可以跟踪文档 ID、文件名等。
Document loaders
这些类加载 Document 对象。LangChain 有数百个与各种数据源的集成,以加载数据:Slack、Notion、Google Drive 等。
每个 DocumentLoader 都有自己特定的参数,但它们都可以通过 .load
方法以相同的方式调用。一个示例用例如下:
from langchain_community.document_loaders.csv_loader import CSVLoader
loader = CSVLoader( ... # <-- Integration specific parameters here)
data = loader.load()
API Reference:CSVLoader
Text splitters
加载文档后,您通常希望对其进行转换以更好地适应您的应用程序。最简单的例子是您可能希望将长文档拆分为更小的块,以适应模型的上下文窗口。LangChain 有许多内置的文档转换器,可以轻松地拆分、组合、过滤和以其他方式操作文档。
当您需要处理长文本时,有必要将文本拆分成块。虽然听起来很简单,但这里有很多潜在的复杂性。理想情况下,您希望将语义相关的文本片段保持在一起。”语义相关” 的含义可能取决于文本的类型。本笔记本展示了几种实现方法。
在高层次上,文本拆分器的工作方式如下:
- 将文本拆分成小的、语义有意义的块(通常是句子)。
- 开始将这些小块组合成更大的块,直到达到一定大小(由某些函数测量)。
- 一旦达到该大小,就将该块作为独立的文本片段,然后开始创建一个新的文本块,并有一些重叠(以保持块之间的上下文)。
这意味着您可以沿两个不同的轴自定义文本拆分器:
- 文本的拆分方式
- 块大小的测量方式
Embedding models
Embeddings 类是一个用于与文本嵌入模型交互的类。有很多嵌入模型提供者(OpenAI、Cohere、Hugging Face 等) - 这个类旨在为所有这些提供标准接口。
嵌入模型为一段文本创建一个向量表示。这很有用,因为这意味着我们可以在向量空间中思考文本,并进行语义搜索等操作,查找在向量空间中最相似的文本片段。
LangChain 中的基础 Embeddings 类提供了两种方法:一种用于嵌入文档,另一种用于嵌入查询。前者以多个文本作为输入,而后者接受单个文本。之所以将这两种方法分开,是因为一些嵌入提供者对文档(要搜索的内容)和查询(搜索查询本身)有不同的嵌入方法。
Vector stores
存储和搜索非结构化数据的最常见方法之一是将其嵌入并存储生成的嵌入向量,然后在查询时嵌入非结构化查询,并检索与嵌入查询 “最相似” 的嵌入向量。向量存储负责为您存储嵌入的数据并执行向量搜索。
可以通过以下方式将向量存储转换为检索器接口:
vectorstore = MyVectorStore()
retriever = vectorstore.as_retriever()
Retrievers
检索器是一个接口,它在给定非结构化查询的情况下返回文档。它比向量存储更通用。检索器不需要能够存储文档,只需要返回(或检索)它们。检索器可以由向量存储创建,但也足够广泛,可以包括 Wikipedia 搜索 和 Amazon Kendra.
检索器接受字符串查询作为输入,并返回一个 Document 列表作为输出。
Tools
工具是代理、链或聊天模型/LLM 用来与外界交互的接口。
工具由以下组件组成:
- 工具名称
- 工具功能描述
- 工具输入的 JSON 模式
- 调用的函数
- 工具结果是否直接返回给用户(仅对代理相关)
工具的名称、描述和 JSON 模式作为上下文提供给 LLM,使 LLM 能够确定如何适当地使用工具。
给定可用工具列表和提示,LLM 可以请求调用一个或多个工具并传递适当的参数。
通常,在设计供聊天模型或 LLM 使用的工具时,需牢记以下几点:
- 针对工具调用进行微调的聊天模型比未微调的模型更擅长工具调用。
- 未微调的模型可能根本无法使用工具,尤其是当工具复杂或需要多次调用时。
- 如果工具名称、描述和 JSON 模式设计得当,模型的表现会更好。
- 简单的工具比复杂的工具更容易被模型使用。
Toolkits
工具包是为特定任务设计的一组工具,它们有方便的加载方法。
所有工具包都提供 get_tools
方法,该方法返回工具列表。因此,可以这样做:
# 初始化一个工具包
toolkit = ExampleTookit(...)
# 获取工具列表
tools = toolkit.get_tools()
Agents
语言模型本身无法采取行动 - 它们只输出文本。LangChain 的一个大用例是创建代理。代理是使用 LLM 作为推理引擎来确定要采取哪些行动以及这些行动的输入应该是什么的系统。这些行动的结果可以反馈给代理,并由代理决定是否需要更多行动,或者是否可以结束。
LangGraph 是 LangChain 的一个扩展,专门用于创建高度可控和可定制的代理。请查看该文档以获得更深入的代理概念概述。
在 LangChain 中有一个遗留的代理概念,我们正逐步淘汰:AgentExecutor
。AgentExecutor 本质上是一个代理的运行时。它是一个很好的入门点,但当您开始拥有更多自定义代理时,它的灵活性不足。为了解决这个问题,我们构建了 LangGraph 作为这种灵活、高度可控的运行时。
如果您仍在使用 AgentExecutor,请不要担心:我们仍然有一个关于如何使用 AgentExecutor 的指南。不过,建议您开始向 LangGraph 过渡。为此,我们整理了一个过渡指南。
Multimodal
一些模型是多模态的,接受图像、音频甚至视频作为输入。这些模型仍然比较少见,这意味着模型提供者还没有标准化“最佳”定义 API 的方式。多模态输出更为少见。因此,我们将多模态抽象保持得相当轻量,并计划随着该领域的成熟进一步完善多模态 API 和交互模式。
在 LangChain 中,大多数支持多模态输入的聊天模型也接受 OpenAI 内容块格式的那些值。目前,这仅限于图像输入。对于支持视频和其他字节输入的模型(如 Gemini),API 也支持原生的、特定于模型的表示。
Callbacks
LangChain 提供了一个回调系统,允许您挂钩到 LLM 应用程序的各个阶段。这对于日志记录、监控、流式传输和其他任务非常有用。
您可以使用 callbacks
参数订阅这些事件,该参数在整个 API 中都可用。这是一个处理程序对象的列表,期望实现下面更详细描述的一个或多个方法。
Callback Events
Event | Event Trigger | Associated Method |
---|---|---|
Chat model start | When a chat model starts | on_chat_model_start |
LLM start | When a llm starts | on_llm_start |
LLM new token | When an llm OR chat model emits a new token | on_llm_new_token |
LLM ends | When an llm OR chat model ends | on_llm_end |
LLM errors | When an llm OR chat model errors | on_llm_error |
Chain start | When a chain starts running | on_chain_start |
Chain end | When a chain ends | on_chain_end |
Chain error | When a chain errors | on_chain_error |
Tool start | When a tool starts running | on_tool_start |
Tool end | When a tool ends | on_tool_end |
Tool error | When a tool errors | on_tool_error |
Agent action | When an agent takes an action | on_agent_action |
Agent finish | When an agent ends | on_agent_finish |
Retriever start | When a retriever starts | on_retriever_start |
Retriever end | When a retriever ends | on_retriever_end |
Retriever error | When a retriever errors | on_retriever_error |
Text | When arbitrary text is run | on_text |
Retry | When a retry event is run | on_retry |
Callback handlers
回调处理程序可以是 sync
或 async
:
- 同步回调处理程序实现 BaseCallbackHandler 接口。
- 异步回调处理程序实现 AsyncCallbackHandler 接口。
在运行时,LangChain 会配置一个适当的回调管理器(例如 CallbackManager 或 AsyncCallbackManager),该管理器将负责在事件触发时调用每个“注册”回调处理程序的相应方法。
Passing callbacks
callbacks
属性在整个 API(模型、工具、代理等)中的大多数对象上都可用,具体有两个地方:
- 请求时回调:在请求时与输入数据一起传递。在所有标准
Runnable
对象上可用。这些回调由定义它们的对象的所有子对象继承。例如chain.invoke({"number": 25}, {"callbacks": [handler]})
。 - 构造函数回调:
chain = TheNameOfSomeChain(callbacks=[handler])
。这些回调作为参数传递给对象的构造函数。这些回调仅限于定义它们的对象,并且不会被对象的任何子对象继承。
构造函数回调仅限于定义它们的对象,并且不会被对象的子对象继承。
如果您正在创建自定义链或可运行对象,则需要记住将请求时回调传递给任何子对象。
Python <=3.10 中的异步
任何
RunnableLambda
、RunnableGenerator
或Tool
在 python <=3.10 中运行异步时,都必须手动将回调传递给子对象。这是因为 LangChain 无法自动将回调传递给这种情况下的子对象。这是您可能未能看到自定义可运行对象或工具发出事件的常见原因。
技术
函数/工具调用
info
我们将工具调用和函数调用这两个术语互换使用。虽然函数调用有时指单个函数的调用,但我们认为所有模型在每条消息中都可以返回多个工具或函数调用。
工具调用允许模型通过生成符合用户定义模式的输出来响应给定的提示。虽然名称暗示模型在执行某些操作,但实际情况并非如此!模型只是为工具提供参数,而实际运行工具(或不运行)则取决于用户。例如,如果你想从非结构化文本中提取符合某种模式的输出,可以给模型一个“提取”工具,该工具接收符合所需模式的参数,然后将生成的输出视为最终结果。
一个工具调用包括名称、参数字典和一个可选标识符。参数字典的结构为 {argument_name: argument_value}
。
许多大型语言模型提供商,包括 Anthropic、Cohere、Google、Mistral 和 OpenAI 等,支持各种工具调用功能。这些功能通常允许请求中包含可用的工具及其模式,并在响应中包含对这些工具的调用。例如,给定一个搜索引擎工具,大型语言模型可能会通过首先调用搜索引擎来处理查询。调用该大型语言模型的系统可以接收工具调用、执行并将输出返回给模型以告知其响应。LangChain 包含一套内置工具并支持几种定义自定义工具的方法。
LangChain 提供了一种在不同模型之间一致的标准化工具调用接口。
标准接口包括:
ChatModel.bind_tools()
: 用于指定模型可调用的工具的方法。AIMessage.tool_calls
:AIMessage
返回的属性,用于访问模型请求的工具调用。
函数/工具调用有两个主要用途:
检索
LangChain 提供几种高级检索类型。以下是完整列表及相关信息:
名称: 检索算法的名称。
索引类型: 该方法依赖的索引类型(如有)。
是否使用大型语言模型: 该检索方法是否使用大型语言模型。
使用时机: 何时应考虑使用该检索方法的建议。
描述: 该检索算法的描述。
名称 | 索引类型 | 是否使用大型语言模型 | 使用时机 | 描述 |
---|---|---|---|---|
向量存储 | 向量存储 | 否 | 如果你刚开始并寻找简单易用的方法。 | 这是最简单的方法,也是最容易开始的方法。它涉及为每段文本创建嵌入。 |
父文档 | 向量存储 + 文档存储 | 否 | 如果你的页面有很多较小的独立信息片段,最好单独索引,但最好一起检索。 | 这涉及为每个文档索引多个块。然后你找到嵌入空间中最相似的块,但检索整个父文档并返回(而不是单个块)。 |
多向量 | 向量存储 + 文档存储 | 有时在索引期间 | 如果你能从文档中提取比文本本身更相关的信息来索引。 | 这涉及为每个文档创建多个向量。每个向量可以通过多种方式创建——例如文本摘要和假设问题。 |
自查询 | 向量存储 | 是 | 如果用户提问更适合基于元数据而非文本相似性来获取文档。 | 这使用大型语言模型将用户输入转换为两件事:(1)语义查找字符串,(2)元数据过滤器。这很有用,因为问题往往是关于文档的元数据(而不是内容本身)。 |
上下文压缩 | 任意 | 有时 | 如果你发现检索到的文档包含太多无关信息并且分散大型语言模型的注意力。 | 这是在另一个检索器上添加后处理步骤,仅提取检索文档中最相关的信息。可以通过嵌入或大型语言模型完成。 |
时间加权向量存储 | 向量存储 | 否 | 如果你有与文档关联的时间戳,并且希望检索最新的文档。 | 这基于语义相似性(如正常向量检索)和时间戳(查看索引文档的时间戳)组合来获取文档。 |
多查询检索器 | 任意 | 是 | 如果用户提问复杂,需要多个独立的信息片段来响应。 | 这使用大型语言模型从原始问题生成多个查询。这在原始查询需要多个主题信息片段才能正确回答时很有用。通过生成多个查询,我们可以为每个查询获取文档。 |
集合 | 任意 | 否 | 如果你有多种检索方法并想尝试组合它们。 | 这从多个检索器中获取文档并将它们组合。 |
文本分割
LangChain 提供多种 文本分割器
。这些都在 langchain-text-splitters
包中。
表格列:
- 名称: 文本分割器的名称
- 类: 实现该文本分割器的类
- 分割方式: 该文本分割器的分割方式
- 是否添加元数据: 是否添加有关每个块来源的元数据。
- 描述: 分割器的描述,包括何时使用的建议。
名称 | 类 | 分割方式 | 是否添加元数据 | 描述 |
---|---|---|---|---|
递归 | RecursiveCharacterTextSplitter、RecursiveJsonSplitter | 用户定义字符列表 | 递归地分割文本。此分割方式尝试将相关文本片段保持在一起。这是 推荐的 文本分割方式。 |
|
HTML | HTMLHeaderTextSplitter、HTMLSectionSplitter | HTML 特定字符 | ✅ | 基于 HTML 特定字符分割文本。特别是,这会根据 HTML 添加有关该块来源的相关信息。 |
Markdown | MarkdownHeaderTextSplitter | Markdown 特定字符 | ✅ | 基于 Markdown 特定字符分割文本。特别是,这会根据 Markdown 添加有关该块来源的相关信息。 |
代码 | 多种语言 | 代码(Python、JS)特定字符 | 基于编码语言特定字符分割文本。可选择 15 种不同语言。 | |
令牌 | 多种类 | 令牌 | 基于令牌分割文本。有几种不同的方法来衡量令牌。 | |
字符 | CharacterTextSplitter | 用户定义字符 | 基于用户定义字符分割文本。这是较简单的方法之一。 | |
语义分块器(实验性) | SemanticChunker | 句子 | 首先按句子分割。然后,如果相邻句子在语义上足够相似,则将它们组合在一起。来源于 Greg Kamradt。 | |
集成: AI21 语义 | AI21SemanticTextSplitter | ✅ | 确定形成 |