导读
在很多RAG系统中(包括传统的搜索引擎),均需要根据用户的输入首先分析用户的查询意图,以便执行不同的分支获取最优答案, 本文详细介绍RAG中的查询意图驱动Router逻辑。
根据查询意图引导应用程序流程
根据用户查询的意图来控制 RAG 应用程序的流程,可以帮助我们创建更有用和更加强大的检索增强生成(RAG)应用程序。
我们希望用户能够与数据进行交互,这些数据可能来自各种各样的来源。
例如报告、文档、图片、数据库和第三方系统。
对于基于业务的 RAG 应用程序,我们可能希望用户能够与业务的各个领域的信息进行交互,例如销售、订购和会计系统的信息。
由于数据来源的多样性,信息的存储方式以及我们希望与之交互的方式也可能是多样的。
一些数据可能存储在向量存储中,一些存储在 SQL 数据库中,还有一些可能需要通过 API 调用来访问,因为它们位于第三方系统中。
同样,对于相同的数据,也可能设置了不同的向量存储,针对不同的查询类型进行优化。
例如,一个向量存储可以用于回答摘要类型的问题,另一个用于回答具体的、定向的问题。
我们可能还希望根据问题的性质,路由到不同的组件类型。
例如,根据问题的性质,我们可能希望将查询传递给Agent、向量存储,或者直接传递给 LLM 进行处理。
甚至可能根据所提出的问题定制提示模板。
总的来说,有很多原因我们希望改变并引导用户查询通过应用程序的流程。
我们的应用程序尝试满足的用例越多,我们就越有可能在整个应用程序中有更多的路由要求。
路由器(Router)本质上只是我们可以使用的 If/Else 语句,用于引导查询的控制流程。
但有趣的是,它们需要根据自然语言输入做出决策。
因此,我们正在寻找基于自然语言描述的离散路径输出。
由于很多路由逻辑是基于 LLM 或机器学习算法的使用,这些算法是非确定性的,我们无法保证路由器总是能够100%地做出正确的选择。再加上我们不太可能能够预测所有进入路由器的不同查询变体。
然而,通过使用最佳实践和一些测试,我们应该能够利用路由器来帮助创建更强大的 RAG 应用程序。
自然语言Router
我们将在这里探讨一些我发现的由一些不同的 RAG 和 LLM 框架和库实现的自然语言路由器。
-
LLM 完成路由器
-
LLM 函数调用路由器
-
语义路由器
-
zero-shot 分类路由器
-
语言分类路由器
下面的图表描述了这些路由器,以及它们所在的框架/包。
该图表还包括逻辑路由器,我定义为基于离散逻辑工作的路由器
例如根据字符串长度、文件名、整数值等条件。换句话说,它们不是基于必须理解自然语言查询意图的。
LLM 路由器
利用LLM的决策能力根据用户的查询选择路由。
LLM 完成路由器
这些使用 LLM 完成调用,要求 LLM 传递的prompt选项列表中返回最佳描述查询的单词。
然后,可以将此单词用作 If/Else 条件的一部分,以控制应用程序流程。
这就是 LlamaIndex 中的 LLM 选择器路由器 的工作原理。这也是 LangChain 文档中路由器的示例。
让我们看一个代码示例,基于 LangChain 文档中提供的示例,以使这一点更加清晰。正如您所看到的,在 LangChain 中自己编写其中之一是非常简单的。
from langchain_anthropic import ChatAnthropic` `from langchain_core.output_parsers import StrOutputParser` `from langchain_core.prompts import PromptTemplate
设置LLM链以根据查询返回单个单词
llm_completion_select_route_chain = ( ``PromptTemplate.from_template("""` `根据我们在提示模板中提供的单词列表,对下面的用户问题进行分类。`` ``不要用超过一个词来回答。`` ``{question}` ` ``分类:""" `` ) `` | ChatAnthropic(model_name="claude-3-haiku") ``| StrOutputParser()` `)
我们设置了一个IF/Else条件,将查询路由到正确的链路
基于上面的LLM完成调用
def route_to_chain(route_name):` ` ` `if "anthropic" == route_name.lower():``return anthropic_chain` ` ` `elif "langchain" == route_name.lower():``return langchain_chain` ` ` `else:`` return general_chain
应用程序后期,我们可以使用LLM的响应
完成链用于控制(即路由)应用程序的流程
通过我们创建的 route_to_chain 方法将正确的链路路由
route_name = llm_completion_select_route_chain.invoke(user_query)` `chain = route_to_chain(route_name)` `chain.invoke(user_query)
LLM 功能调用路由
这利用了LLM的函数调用能力来选择遍历的路线。不同的路线被设置为LLM函数调用中具有适当描述的函数。然后,基于传递给LLM的查询,它能够返回正确的函数(即路线),供我们采取。
这就是 Pydantic Router 在 LlamaIndex 内部的工作原理。这也是大多数代理人工作的方式,也是选择要使用的正确工具的方式。他们利用LLM的函数调用能力来根据用户的查询选择适当的工具。
语义路由器
这种路由器类型利用嵌入和相似性搜索来选择最佳的遍历路线。
每条路线都有一组与之关联的示例查询,这些查询会被嵌入并存储为向量。传入的查询也会被嵌入,然后与路由器中的其他示例查询进行相似性搜索。选择与最接近匹配的查询相关的路线。
事实上,有一个名为semantic-router的Python包就是这样做的。让我们看一些实现细节,以更好地了解整个工作原理。这些示例直接来自该库的 GitHub 页面。
让我们设置两条路线,一条用于关于政治的问题,另一条用于一般的闲聊类型问题。对于每条路线,我们分配一个可能会被问到的问题列表,以触发该路线。这些示例查询被称为话语。这些话语将被嵌入,以便我们可以将它们用于与用户查询的相似性搜索。
from semantic_router import Route` `# 我们可以将这作为我们的聊天机器人的指南,避免政治话题` `# 对话` `政治= Route( `` name="politics", `` utterances=[ `` "政治难道不是最好的东西吗", `` "为什么不告诉我你的政治观点", `` "你难道不喜欢总统吗", `` "他们将毁掉这个国家!", `` "他们将拯救这个国家!", ``],` `)` `# 这可以作为指示我们的聊天机器人切换到更多...` `# 闲聊提示` `chitchat = Route( `` name="chitchat", `` utterances=[ `` "今天天气怎么样?", `` "最近怎么样?", `` "今天天气真好", `` "天气太可怕了", `` "我们去吃炸鱼薯条吧", ``],` `) ``# 我们将我们的两个决策放在一个列表中` `routes = [politics, chitchat]
我们将OpenAI分配为编码器,尽管任何嵌入库都可以使用。接下来,我们使用路由器和编码器创建我们的路由层。
encoder = OpenAIEncoder() ``from semantic_router.layer import RouteLayer ``route_layer = RouteLayer(encoder=encoder, routes=routes)
然后,当我们对路由器层应用我们的查询时,它会返回应该用于查询的路由
route_layer("你不喜欢政治吗?").name ``Output:` ` `` `` ``# -> '政治'` ` `` `` ``## zero-shot 分类路由器
[“zero-shot 文本分类](https://huggingface.co/tasks/zero-shot-classification) 是自然语言处理中的一项任务,模型在一组标记示例上进行训练,然后能够对以前未见过的类别的新示例进行分类”。这些路由器利用零-shot分类模型,将标签分配给文本片段,从您传递给路由器的预定义标签集中选择。
**示例:** Haystack 中的 [ZeroShotTextRouter](https://docs.haystack.deepset.ai/reference/routers-api#module-zero_shot_text_router),利用了 Hugging Face 的零-shot分类模型。查看 [源代码](https://github.com/deepset-ai/haystack/blob/main/haystack/components/routers/zero_shot_text_router.py#L130) 以了解神奇发生的地方。
语言分类路由器
这种类型的路由器能够识别查询所使用的语言,并根据此进行路由。如果您的应用程序需要某种多语言解析能力,这将非常有用。
**示例:** [Haystack 的 TextClassificationRouter](https://docs.haystack.deepset.ai/reference/routers-api#module-text_language_router)。[它利用 langdetect python 库](https://github.com/deepset-ai/haystack/blob/main/haystack/components/routers/text_language_router.py#L90) 来检测文本的语言,该库本身使用 [朴素贝叶斯](https://www.slideshare.net/shuyo/language-detection-library-for-java) 算法来检测语言。
关键词路由器
这篇来自 LlamaIndex 的联合创始人 Jerry Liu 的[文章](https://betterprogramming.pub/unifying-llm-powered-qa-techniques-with-routing-abstractions-438e2499a0d0)讨论了 RAG 应用程序内部的路由,其中提出了一种关键词路由器,该路由器尝试通过匹配查询和路由列表之间的关键词来选择路由。 这个关键词路由器可以由 LLM 来识别关键词,或者通过其他关键词匹配库来实现。我还没有找到任何实现这种路由器类型的软件包。
逻辑路由器
这些使用逻辑检查对变量进行操作,比如字符串长度、文件名和值比较,以处理如何路由查询。它们与编程中使用的典型的 If/Else 条件非常相似。
换句话说,它们不是基于理解自然语言查询的意图,而是可以根据现有的离散变量做出选择。
**示例:** [ConditionalRouter](https://docs.haystack.deepset.ai/docs/conditionalrouter) 和 [FileTypeRouter](https://docs.haystack.deepset.ai/docs/filetyperouter) 来自 HayStack。
Agent vs 路由器
乍一看,Agent和Router之间确实有很多相似之处,可能很难区分它们的不同之处。
这种相似之处存在是因为代理实际上在其流程中执行路由。它们使用路由机制来选择正确的工具来完成任务。它们经常利用函数调用来选择正确的工具,就像上面描述的 “LLM 函数调用路由器” 一样。 路由器比代理简单得多,通常只是将任务路由到正确的位置,而不进行与该任务相关的任何逻辑或处理。
另一方面,Agent通常负责处理逻辑,包括管理其可以访问的工具所完成的工作。
结论
我们在这里介绍了目前在不同的RAG和LLM框架和包中找到的几种不同的自然语言路由器。
随着时间的推移,围绕路由的概念、包和库肯定会增加。在构建RAG应用程序时,您会发现,在某个时候,路由能力确实变得必要,以便构建对用户有用的应用程序。
路由器是这些基本构建模块,它们允许您将自然语言请求路由到您的应用程序的正确位置,以便尽可能最好地满足用户的查询。
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。