RAG实战篇:精准判断用户查询意图,自动选择最佳处理方案
wptr33 2025-04-11 08:27 24 浏览
在人工智能领域,理解和准确响应用户的查询是构建高效交互系统的关键。这篇文章将带你深入了解如何通过高级查询转换技术,优化大型语言模型的理解能力,使其更贴近用户的真正意图。
在《RAG实战篇:构建一个最小可行性的Rag系统》中,风叔详细介绍了Rag系统的整体实现框架,以及如何搭建一个最基本的Naive Rag。
在前面两篇文章中,风叔分别介绍了索引(Indexing)和查询转换(Query Translation)环节的优化方案。
在这篇文章中,围绕Routing(路由)环节,如下图橙色框内所示,风叔详细介绍一下面对不同的用户输入,如何让大模型更智能地路由到最佳方案。
路由的作用,是为每个Query选择最合适的处理管道,以及依据来自模型的输入或补充的元数据,来确定将启用哪些模块。比如当用户的输入问题涉及到跨文档检索、或者对于复杂文档构建了多级索引时,就需要使用路由机制。
下面,我们结合源代码,介绍一下Logical routing(基于逻辑的路由)和Sematic Routing(基于语义的路由)两种方案。
一、Logical routing(基于逻辑的路由)
基于逻辑的路由,其原理非常简单。大模型接收到问题之后,根据决策步骤,去选择正确的索引数据库,比如图数据库、向量数据库等等,如下图所示。
其使用函数调用(function calling)来产生结构化输出。
下面我们结合源代码来分析一下Logical Routing的流程:
- 首先我们定义了三种文档,pytion、js、golang
- 然后通过prompt告诉大模型,需要根据所涉及的编程语言,将用户问题路由到适当的数据源
- 定义Router
# Data model
class RouteQuery(BaseModel):
"""Route a user query to the most relevant datasource."""
datasource: Literal["python_docs", "js_docs", "golang_docs"] = Field(
...,
description="Given a user question choose which datasource would be most relevant for answering their question",
)
# LLM with function call
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.with_structured_output(RouteQuery)
# Prompt
system = """You are an expert at routing a user question to the appropriate data source.
Based on the programming language the question is referring to, route it to the relevant data source."""
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{question}"),
])
# Define router
router = prompt | structured_llm
接着给出了一个使用示例,用户提问后,路由器根据问题的内容判断出数据源为 python_docs,并返回了相应的结果。
question = """Why doesn't the following code work:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages(["human", "speak in {language}"])
prompt.invoke("french")
"""
result = router.invoke({"question": question})
result.datasource
def choose_route(result):
if "python_docs" in result.datasource.lower:
### Logic here
return "chain for python_docs"
elif "js_docs" in result.datasource.lower:
### Logic here
return "chain for js_docs"
else:
### Logic here
return "golang_docs"
from langchain_core.runnables import RunnableLambda
full_chain = router | RunnableLambda(choose_route)
full_chain.invoke({"question": question})
二、Sematicrouting(基于语义的路由)
基于语义的路由,其原理也非常简单,大模型根据query的语义相似度,去自动配置不同的prompt。
我们先定义两种不同的Prompt,一个让大模型扮演物理专家,一个让大模型扮演数学专家,并将其转为嵌入向量。
# Two prompts
physics_template = """You are a very smart physics professor.
You are great at answering questions about physics in a concise and easy to understand manner.
When you don't know the answer to a question you admit that you don't know.
Here is a question:
{query}"""
math_template = """You are a very good mathematician. You are great at answering math questions.
You are so good because you are able to break down hard problems into their component parts,
answer the component parts, and then put them together to answer the broader question.
Here is a question:
{query}"""
embeddings = OpenAIEmbeddings
prompt_templates = [physics_template, math_template]
prompt_embeddings = embeddings.embed_documents(prompt_templates)
然后计算query embedding和prompt embedding的向量相似度
# Route question to prompt
def prompt_router(input):
# Embed question
query_embedding = embeddings.embed_query(input["query"])
# Compute similarity
similarity = cosine_similarity([query_embedding], prompt_embeddings)[0]
most_similar = prompt_templates[similarity.argmax()]
# Chosen prompt
print("Using MATH" if most_similar == math_template else "Using PHYSICS")
return PromptTemplate.from_template(most_similar)
chain = (
{"query": RunnablePassthrough}
| RunnableLambda(prompt_router)
| ChatOpenAI
| StrOutputParser
)
print(chain.invoke("What's a black hole"))
在上述案例中,最终的输出会使用物理专家的Prompt。
到这里,两种常用的路由策略就介绍完了。当然,我们也可以自主构建更复杂的路由策略,比如构建专门的分类器、打分器等等,这里就不详细展开了。
三、总结
在这篇文章中,风叔介绍了实现查询路由的具体方法,包括Logical routing和Semantic routing两种实现方式。
很多时候,在一些特殊的场景下,我们需要将用户的输入转化为特定的语句,比如数据库查询动作。在下一篇文章中,风叔将重点围绕Query Construction(查询构建)环节,介绍如何将用户输入转变为特定的系统执行语句。
本文由人人都是产品经理作者【风叔】,微信公众号:【风叔云】,原创/授权 发布于人人都是产品经理,未经许可,禁止转载。
题图来自 Pixabay,基于 CC0 协议。
相关推荐
- redis的八种使用场景
-
前言:redis是我们工作开发中,经常要打交道的,下面对redis的使用场景做总结介绍也是对redis举报的功能做梳理。缓存Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。...
- 基于Redis的3种分布式ID生成策略
-
在分布式系统设计中,全局唯一ID是一个基础而关键的组件。随着业务规模扩大和系统架构向微服务演进,传统的单机自增ID已无法满足需求。高并发、高可用的分布式ID生成方案成为构建可靠分布式系统的必要条件。R...
- 基于OpenWrt系统路由器的模式切换与网页设计
-
摘要:目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户、提升服务的目标。传统路由器自带的Luci界面提供了工厂模式的Web界面,用户可通过该界面配置路...
- 这篇文章教你看明白 nginx-ingress 控制器
-
主机nginx一般nginx做主机反向代理(网关)有以下配置...
- 如何用redis实现注册中心
-
一句话总结使用Redis实现注册中心:服务注册...
- 爱可可老师24小时热门分享(2020.5.10)
-
No1.看自己以前写的代码是种什么体验?No2.DooM-chip!国外网友SylvainLefebvre自制的无CPU、无操作码、无指令计数器...No3.我认为CS学位可以更好,如...
- Apportable:拯救程序员,IOS一秒变安卓
-
摘要:还在为了跨平台使用cocos2d-x吗,拯救objc程序员的奇葩来了,ApportableSDK:FreeAndroidsupportforcocos2d-iPhone。App...
- JAVA实现超买超卖方案汇总,那个最适合你,一篇文章彻底讲透
-
以下是几种Java实现超买超卖问题的核心解决方案及代码示例,针对高并发场景下的库存扣减问题:方案一:Redis原子操作+Lua脚本(推荐)//使用Redis+Lua保证原子性publicbo...
- 3月26日更新 快速施法自动施法可独立设置
-
2016年3月26日DOTA2有一个79.6MB的更新主要是针对自动施法和快速施法的调整本来内容不多不少朋友都有自动施法和快速施法的困扰英文更新日志一些视觉BUG修复就不翻译了主要翻译自动施...
- Redis 是如何提供服务的
-
在刚刚接触Redis的时候,最想要知道的是一个’setnameJhon’命令到达Redis服务器的时候,它是如何返回’OK’的?里面命令处理的流程如何,具体细节怎么样?你一定有问过自己...
- lua _G、_VERSION使用
-
到这里我们已经把lua基础库中的函数介绍完了,除了函数外基础库中还有两个常量,一个是_G,另一个是_VERSION。_G是基础库本身,指向自己,这个变量很有意思,可以无限引用自己,最后得到的还是自己,...
- China's top diplomat to chair third China-Pacific Island countries foreign ministers' meeting
-
BEIJING,May21(Xinhua)--ChineseForeignMinisterWangYi,alsoamemberofthePoliticalBureau...
- 移动工作交流工具Lua推出Insights数据分析产品
-
Lua是一个适用于各种职业人士的移动交流平台,它在今天推出了一项叫做Insights的全新功能。Insights是一个数据平台,客户可以在上面实时看到员工之间的交流情况,并分析这些情况对公司发展的影响...
- Redis 7新武器:用Redis Stack实现向量搜索的极限压测
-
当传统关系型数据库还在为向量相似度搜索的性能挣扎时,Redis7的RedisStack...
- Nginx/OpenResty详解,Nginx Lua编程,重定向与内部子请求
-
重定向与内部子请求Nginx的rewrite指令不仅可以在Nginx内部的server、location之间进行跳转,还可以进行外部链接的重定向。通过ngx_lua模块的Lua函数除了能实现Nginx...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git 执行pull错误如何撤销 git pull fail
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)