Routing机制与Query Construction策略

  • 前言
  • Routing
    • Logical Routing
      • ChatOpenAI
      • Structured
      • Routing Datasource
      • Conclusion
    • Semantic Routing
      • Embedding & LLM
      • Prompt
      • Rounting Prompt
      • Conclusion
  • Query Construction
    • Grab Youtube video information
    • Structured
    • Prompt
  • Github
  • References

前言

本文引用上一篇博客的作法。在本地开启一个代理服务器,然后使用OpenAI的ChatOpenAI作为聊天接口客户端,使其发送的请求链接到我们的本地服务器。

Routing

在传统的 RAG 架构中,所有查询都走统一的 Retriever和 Prompt 模板,这在多源数据或多任务系统中存在检索结果不相关、内容不精准、用户意图模糊等局限性。为了解决这一问题,Routing机制可以根据用户提出的问题,智能地路由到最相关的知识源或处理流程中,以提升回答的精准性与效率。

Logical Routing

ChatOpenAI

如前言所述,使用ChatOpenAI聊天接口客户端,但不适用GPT模型。

os.environ['VLLM_USE_MODELSCOPE'] = 'True'
chat = ChatOpenAI(model='Qwen/Qwen3-0.6B',openai_api_key="EMPTY",openai_api_base='http://localhost:8000/v1',stop=['<|im_end|>'],temperature=0
)

在这里插入图片描述
Fig .1 Logical Routing framework diagram

Structured

Prompt中,指示LLM根据当前编程语言选择最相关的数据源。然后通过|管道运算符传入with_structured_output。其中, with_structured_output的作用是让大模型生成和RouteQuery数据格式一样的数据结构。也称结构化数据。

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严格地按照RouteQuery结构体格式化为对应的JSON格式,并自动解析成Python对象。”
"""
数据结构:
RouteQuery(datasource='python_docs'  # 或 'js_docs' 或 'golang_docs'
)
JSON格式:
{"datasource": "python_docs"
}
"""
structured_llm = chat.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

当运行这一部分之后,LLM只会生成["python_docs", "js_docs", "golang_docs"]三者中的其中一个,因为datasource: Literal["python_docs", "js_docs", "golang_docs"] 指定了它们三个作为候选值。输出的结果如下所示。

"""
数据结构:
RouteQuery(datasource='python_docs'  # 或 'js_docs' 或 'golang_docs'
)
JSON格式:
{"datasource": "python_docs"
}
"""

在这里插入图片描述
Fig .2 Data structured flow chart

Routing Datasource

Question中给出需要判断的编程语言。然后经过上一节Structured的运算后,得到一个结构化数据。最终只需要调用choose_route匹配对应数据源即可。

question = """Why doesn't the following code work:from langchain_core.prompts import ChatPromptTemplateprompt = ChatPromptTemplate.from_messages(["human", "speak in {language}"])
prompt.invoke("french")
"""# result = router.invoke({"question": question})
def choose_route(result):if "python_docs" in result.datasource.lower():### Logic herereturn "chain for python_docs"elif "js_docs" in result.datasource.lower():### Logic herereturn "chain for js_docs"else:### Logic herereturn "golang_docs"full_chain = router | RunnableLambda(choose_route)full_chain.invoke({"question": question})

Conclusion

上述内容通过一个甄别编程语言的案例,讲述了如何结构化数据,以及如何根据结构化后的数据选择对应的数据源。这有利于我们在实际应用中,根据用户所提问题,Rounting到最相关的数据源或向量数据库中,可以极大地提升召回率。

Semantic Routing

Embedding & LLM

定义ModelScope社区中开源的EmbeddingText Generation模型。

embedding = ModelScopeEmbeddings(model_id='iic/nlp_corom_sentence-embedding_english-base')
# 使用vllm部署OpenAI Serve,然后使用ChatOpenAI
os.environ['VLLM_USE_MODELSCOPE'] = 'True'
chat = ChatOpenAI(model='Qwen/Qwen3-0.6B',openai_api_key="EMPTY",openai_api_base='http://localhost:8000/v1',stop=['<|im_end|>'],temperature=0
)

Prompt

定义两个prompt template,并对其向量化。用于后续根据用户所提问题,选择合适的prompt

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}"""prompt_templates = [physics_template, math_template]
prompt_embeddings = embedding.embed_documents(prompt_templates)

在这里插入图片描述
Fig .3 Semantic Routing framework diagram

Rounting Prompt

对用户查询进行向量化,便于计算用户查询和prompt template之间的余弦相似度,根据相似度最高的下标,获取对应的prompt。最终交予LLM处理。

# 根据计算余弦相似度,得到输入`query`和`templates`中相似度最高的一个`template`
def prompt_router(input):# 向量化 `query`query_embedding = embedding.embed_query(input["query"])# 计算输入`query`和`prompt`之间的余弦相似度similarity = cosine_similarity([query_embedding], prompt_embeddings)[0]# 以相似度最高的下标获取对应的templatemost_similar = prompt_templates[similarity.argmax()]# Chosen promptprint("Using MATH" if most_similar == math_template else "Using PHYSICS")return PromptTemplate.from_template(most_similar)# RunnablePassthrough直接返回原值
chain = ({"query": RunnablePassthrough()}| RunnableLambda(prompt_router)| chat| StrOutputParser()
)answer = chain.invoke("What's a black hole")
print(answer)

Conclusion

上述内容描述了一种根据用户查询动态匹配Prompt的策略。

Query Construction

Grab Youtube video information

国内访问下述内容,可能会出现urllib.error.HTTPError: HTTP Error 400: Bad Request异常。为了解决这一问题,我们通过另外一种方式,同样可以构造datasource

docs = YoutubeLoader.from_youtube_url("https://www.youtube.com/watch?v=pbAd8O1Lvm4", add_video_info=False
).load()print(docs[0].metadata)

通过subprocess.run执行一个脚本,并使用yt-dlp下载视频信息,然后以JSON数据格式输出。最后,根据数据信息构造我们所需的datasource即可。

result = subprocess.run(["yt-dlp", "--dump-json", f"https://www.youtube.com/watch?v=pbAd8O1Lvm4"],capture_output=True, text=True)
video_info = json.loads(result.stdout)metadata = {"source": 'pbAd8O1Lvm4',"title": video_info.get("title", "Unknown"),"description": video_info.get("description", "Unknown"),"view_count": video_info.get("view_count", 0),"thumbnail_url": video_info.get("thumbnail", ""),"publish_date": datetime.strptime(video_info.get("upload_date", "19700101"), "%Y%m%d").strftime("%Y-%m-%d 00:00:00"),"length": video_info.get("duration", 0),"author": video_info.get("uploader", "Unknown"),
}

Structured

下列定义了一个结构化搜索查询模式,与Routing中的Structured一样。其目的是将自然语言转为结构化搜索查询。

class TutorialSearch(BaseModel):"""Search over a database of tutorial videos about a software library."""content_search: str = Field(...,description="Similarity search query applied to video transcripts.",)title_search: str = Field(...,description=("Alternate version of the content search query to apply to video titles. ""Should be succinct and only include key words that could be in a video ""title."),)min_view_count: Optional[int] = Field(None,description="Minimum view count filter, inclusive. Only use if explicitly specified.",)max_view_count: Optional[int] = Field(None,description="Maximum view count filter, exclusive. Only use if explicitly specified.",)earliest_publish_date: Optional[date] = Field(None,description="Earliest publish date filter, inclusive. Only use if explicitly specified.",)latest_publish_date: Optional[date] = Field(None,description="Latest publish date filter, exclusive. Only use if explicitly specified.",)min_length_sec: Optional[int] = Field(None,description="Minimum video length in seconds, inclusive. Only use if explicitly specified.",)max_length_sec: Optional[int] = Field(None,description="Maximum video length in seconds, exclusive. Only use if explicitly specified.",)def pretty_print(self) -> None:for field in self.__fields__:if getattr(self, field) is not None and getattr(self, field) != getattr(self.__fields__[field], "default", None):print(f"{field}: {getattr(self, field)}")

在这里插入图片描述
Fig .4 Data structured flow chart

Prompt

下述Prompt引导模型将用户的自然语言问题转化为结构化的数据库查询指令。

system = """You are an expert at converting user questions into database queries. \
You have access to a database of tutorial videos about a software library for building LLM-powered applications. \
Given a question, return a database query optimized to retrieve the most relevant results.If there are acronyms or words you are not familiar with, do not try to rephrase them."""
prompt = ChatPromptTemplate.from_messages([("system", system),("human", "{question}"),]
)# 根据问题语义,将问题中涉及的内容映射到 metadata 的结构化字段中。
structured_llm = llm.with_structured_output(TutorialSearch)
query_analyzer = prompt | structured_llm

对于用户的提问,则将此Question根据Prompt进行结构化。其目的是将用户提问中所包含的单词映射到datasource中合适的字段。

query_analyzer.invoke({"question": "rag from scratch"}).pretty_print()

上述代码运行之后,LLM会根据语义自动构造合适的结构化数据。

content_search: rag from scratch
title_search: rag from scratch

再例如,Question2023 年在 Chat Langchain 上发布的视频,其中很明显日期应该对应datasource字段中的包含时间日期的对应项,例如earliest_publish_date,latest_publish_date

query_analyzer.invoke({"question": "videos on chat langchain published in 2023"}
).pretty_print()
content_search: chat langchain
title_search: 2023
earliest_publish_date: 2023-01-01
latest_publish_date: 2024-01-01

Github

https://github.com/FranzLiszt-1847/LLM

References

[1] https://github.com/langchain-ai/rag-from-scratch/blob/main/rag_from_scratch_5_to_9.ipynb

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87436.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87436.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/87436.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于python的web系统界面登录

#让我们的电脑可以支持服务访问 #需要一个web框架 #pip install Flask from flask import Flask, render_template,request from random import randint app Flask(__name__) app.route(/index) def index():uname request.args.get("uname")return f"主页&am…

MATLAB Simulink 终极入门指南:从零设计智能控制系统

为什么工程师都爱Simulink? 想象一下:不写一行代码就能设计机器人控制器、飞行算法甚至核反应堆! MATLAB Simulink正是这样的可视化神器。全球70%的汽车ECU、航天器控制系统用它开发。本文将带你从零设计一个智能温控系统,融入创新性的模糊PID控制,并生成可部署的C代码!…

vue3 javascript 复杂数值计算操作技巧

在Vue 3中处理复杂数值计算&#xff0c;你可以采用多种策略来确保代码的可读性、可维护性和性能。以下是一些实用的技巧和最佳实践&#xff1a; 1. 使用计算属性&#xff08;Computed Properties&#xff09; Vue 3的computed属性非常适合处理复杂的数值计算。它们是基于响应…

26.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--角色权限管理

在现代企业级应用中&#xff0c;角色权限管理是保障系统安全和提升用户体验的核心基础功能。一个高效的角色权限系统不仅能够有效防止越权访问&#xff0c;还能简化系统的维护和扩展。本文将系统性介绍角色权限管理的核心实现思路&#xff0c;包括架构设计、性能优化、安全机制…

[VSCode] VSCode 设置 python 的编译器

VSCode 设置 python 的编译器 快捷键&#xff1a;CTRL SHIFT P 弹出 VSCode 的命令框输入 Python : select Interpretor选择自己需要的 python 环境&#xff1b;如 python 3.8 或者 python 3.10 版本

基于PEMFC质子交换膜燃料电池系统的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序 4.系统仿真参数 5.系统原理简介 6.参考文献 7.完整工程文件 1.课题概述 本课题是一个燃料电池&#xff08;大概率是质子交换膜燃料电池&#xff0c;PEMFC &#xff09;的数学模型仿真框图&#xff0c;用于模拟燃料电池的电特…

git-build-package 工具代码详细解读

git-build-package&#xff08;gbp&#xff09;是一个用于从 Git 仓库管理 Debian 软件包的工具&#xff0c;其代码架构和实现原理体现了对 Git 版本控制系统和 Debian 打包流程的深度整合。以下是对其代码的详细解读&#xff1a; 代码架构设计 gbp 的代码架构设计围绕其核心…

如何使用ChatGPT快速完成一篇论文初稿?

2小时写完论文初稿&#xff0c;学境思源&#xff0c;听起来是不是有点不真实&#xff1f;一键生成论文初稿&#xff01;但如果你有一个清晰的框架、良好的写作节奏&#xff0c;acaids.com。再配合像ChatGPT这样的写作助手——真的可以做到。 这篇文章就是手把手告诉你&#xf…

Docker PowerJob

1. Docker PowerJob 1. 拉取PowerJob服务端镜像 docker pull tjqq/powerjob-server:4.3.92. 创建数据卷目录用于持久化数据 mkdir -p /home/docker/powerjob/logs mkdir -p /home/docker/powerjob/data mkdir -p /home/docker/powerjob/server mkdir -p /home/docker/powerjob…

Python数据可视化:NumPy生成与Matplotlib折线图绘制

一、数据生成与可视化概述 在数据分析和科学计算领域,Python已成为最受欢迎的编程语言之一。这主要得益于其丰富的数据处理库和强大的可视化工具。数据可视化是将抽象数据转化为直观图形表示的过程,它能够帮助我们发现数据中的模式、趋势和异常值,从而做出更明智的决策。 …

26.多表查询

1.笛卡尔集 创建俩表&#xff1a; -- 创建部门表&#xff08;dept&#xff09; use mysql_learn CREATE TABLE dept (deptno INT PRIMARY KEY, dname VARCHAR(50) NOT NULL, loc VARCHAR(50) );-- 创建员工表&#xff08;emp&#xff09; CREATE TABLE emp (em…

深度学习题目(仅供参考)

一、注意力和transformer 一、选择题 注意力机制的核心步骤不包括&#xff1f; A. 计算注意力分布 B. 加权平均输入信息 C. 随机丢弃部分输入 D. 打分函数计算相关性 答案&#xff1a;C&#xff08;硬性注意力虽随机选择输入&#xff0c;但核心步骤仍为分布计算与加权&#xf…

WebWorker:提升前端性能的多线程利器

简介 在现代Web开发中&#xff0c;随着应用越来越复杂&#xff0c;JavaScript的单线程模型开始显现其局限性。Web Workers的出现为解决这一问题提供了优雅的方案&#xff0c;它允许开发者在后台线程中运行脚本&#xff0c;而不会影响主线程的性能。 Web Workers是HTML5标准的…

milvus教程:collection和scheme

环境配置&#xff1a;可以看上一节 一.数据库使用 连接 Milvus Standalone创建数据库 my_database_1&#xff08;无额外属性&#xff09;创建数据库 my_database_2&#xff08;设置副本数为 3&#xff09;列出所有数据库查看默认数据库&#xff08;default&#xff09;详情修…

14:00开始面试,14:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到6月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Electron(01)

Electron Electron是什么 electron可以使用前端技术开发桌面应用&#xff0c;跨平台性&#xff0c;开发一套应用&#xff0c;可以打包到三个平台。 electron结合Chromium&#xff08;谷歌内核&#xff09;和 Node.js 和Native Api 当使用 Electron 时&#xff0c;很重要的一…

Kafka 拦截器深度剖析:原理、配置与实践

引言 在构建高可用、可扩展的消息系统时&#xff0c;Kafka以其卓越的性能和稳定性成为众多企业的首选。而Kafka拦截器作为Kafka生态中强大且灵活的功能组件&#xff0c;能够在消息的生产和消费过程中实现自定义逻辑的注入&#xff0c;为消息处理流程带来极大的扩展性和可控性。…

Flutter 与原生技术(Objective-C/Swift,java)的关系

在 iOS 开发中&#xff0c;Flutter 与原生技术&#xff08;Objective-C/Swift&#xff09;的关系 一、技术定位与核心差异 Flutter 语言&#xff1a;使用Dart 语言开发&#xff0c;通过 AOT&#xff08;提前编译&#xff09;将代码转换为原生 ARM 指令&#xff0c;无需依赖 iOS…

最新期刊影响因子,基本包含全部期刊

原文链接&#xff1a;2024年期刊最新影响因子&#xff08;IF&#xff09; 2024年期刊最新影响因子&#xff08;IF&#xff09; BioinfoR生信筆記 &#xff0c;注于分享生物信息学相关知识和R语言绘图教程。

java 设计模式_行为型_14策略模式

14.策略模式 策略模式作为一种软件设计模式&#xff0c;指对象有某个行为&#xff0c;但是在不同的场景中&#xff0c;该行为有不同的实现算法。 策略模式把这些算法&#xff0c;都抽取出来&#xff0c;组成一个一个的类&#xff0c;可以任意的替换&#xff0c;大大降低了代码…