当前位置: 首页 > news >正文

RAG From Scratch 系列教程-3: Routing

语义路由与逻辑路由

路由(Routing)是高级RAG系统中的关键组件,它能够根据问题类型智能选择不同的处理路径或数据源。本文将详细解析图中展示的两种路由技术,包含工作原理、执行流程和可落地的代码实现。

一、技术概览

1. 逻辑路由(Logical Routing)

通过规则或分类器显式定义路由逻辑,例如:

python

if "医疗" in question:use_medical_db()
elif "法律" in question:use_law_db()

2. 语义路由(Semantic Routing)

通过向量相似度隐式选择处理路径:

  • 将问题嵌入为向量

  • 计算与各提示模板的相似度

  • 选择最匹配的路径

二、语义路由详解

原理

利用嵌入(embedding)向量捕捉语义特征,通过向量相似度自动选择处理策略,无需硬编码规则。

工作流程

  1. Prompt #1阶段:生成候选路由选项

  2. 嵌入阶段:将问题和选项转换为向量

  3. 相似度计算:使用余弦相似度比较向量

  4. Prompt #2阶段:执行选定路径的操作

代码实现

1. 定义路由提示模板

python

from langchain_core.prompts import PromptTemplateroute_templates = {"technical": PromptTemplate.from_template("""你是一个技术专家,请用专业术语回答:
{question}"""),"general": PromptTemplate.from_template("""用通俗易懂的方式解释:
{question}"""),"creative": PromptTemplate.from_template("""用富有创意的形式(如诗歌、故事)回答:
{question}""")
}
2. 实现语义路由

python

from langchain_community.embeddings import OpenAIEmbeddings
from sklearn.metrics.pairwise import cosine_similarity
import numpy as npembeddings = OpenAIEmbeddings()def semantic_router(question):# 嵌入问题和模板question_vec = embeddings.embed_query(question)template_vecs = {k: embeddings.embed_query(v.template) for k, v in route_templates.items()}# 计算相似度similarities = {k: cosine_similarity([question_vec], [v])[0][0]for k, v in template_vecs.items()}# 选择最佳路由best_route = max(similarities.items(), key=lambda x: x[1])[0]return route_templates[best_route].format(question=question)# 使用示例
response = semantic_router("解释量子纠缠现象")
print(f"选择的路由类型:{best_route}\n回答:{response}")

三、逻辑路由详解

原理

基于预定义规则或分类模型显式选择数据源或处理流程,适合有明确领域划分的场景。

工作流程

  1. 问题分类(规则/模型)

  2. 根据类别选择数据库

  3. 从选定DB检索

  4. 生成最终回答

代码实现

1. 定义多数据源

python

from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings# 初始化不同领域的向量库
tech_embeddings = HuggingFaceEmbeddings(model_name="all-mpnet-base-v2")
medical_embeddings = HuggingFaceEmbeddings(model_name="paraphrase-multilingual-MiniLM-L12-v2")tech_db = FAISS.load_local("tech_index", tech_embeddings)
medical_db = FAISS.load_local("medical_index", medical_embeddings)
2. 实现逻辑路由

python

from langchain.chains import LLMChain
from langchain_community.llms import OpenAIclass LogicalRouter:def __init__(self):self.llm = OpenAI()self.classifier_prompt = """判断问题属于哪个领域:
选项:[技术, 医疗, 通用]
问题:{question}
领域:"""def route(self, question):# 领域分类domain = self.llm(self.classifier_prompt.format(question=question))# 选择数据源if "技术" in domain:return tech_db.similarity_search(question)elif "医疗" in domain:return medical_db.similarity_search(question)else:return general_db.similarity_search(question)# 使用示例
router = LogicalRouter()
docs = router.route("Transformer模型的核心创新是什么?")

四、技术对比与选型建议

对比维度语义路由 (Semantic Routing)逻辑路由 (Logical Routing)
核心原理基于向量相似度隐式匹配基于预定义规则/分类器显式决策
实现方式1. 问题嵌入为向量
2. 计算与模板的相似度
3. 选择最匹配路径
1. 硬编码规则或训练分类器
2. 条件分支选择数据源
代码复杂度中(需设计模板和嵌入计算)高(需维护分类规则和分支逻辑)
维护成本低(自动适应新问题)高(需手动更新规则)
决策透明度低(黑盒相似度计算)高(明确的条件分支)
适应能力强(自动处理未见过的提问方式)弱(仅能处理预设类别)
响应速度较快(20-100ms)极快(<10ms,直接匹配)
典型应用场景开放域问答
多意图混合问题
垂直领域问答
结构化业务场景
与LLM结合度深(依赖嵌入模型)浅(可完全独立于LLM)
代码示例核心cosine_similarity(query_vec, template_vec)if "关键词" in question:
最佳实践1. 设置相似度阈值
2. 模板多样化设计
1. 规则优先级管理
2. 设置默认分支
混合方案优势先逻辑路由粗筛,再语义路由精分逻辑路由为主,语义路由处理边缘案例

五、进阶组合方案

将两种路由方式结合使用可获得更好效果:

python

def hybrid_router(question):# 先用逻辑路由做粗筛domain = classify_domain(question)  # 在领域内使用语义路由if domain == "技术":return semantic_router(question, tech_templates)elif domain == "医疗":return semantic_router(question, medical_templates)

六、性能优化技巧

  1. 缓存路由结果:对相似问题复用路由决策

  2. 分层路由:先粗分类再细粒度路由

  3. 动态加载:仅加载当前需要的向量库

  4. 混合检索:结合关键词和语义路由

通过合理使用路由技术,RAG系统可实现:

  • 响应速度提升30-50%(减少不必要的检索)

  • 答案准确率提升20-35%(使用最适配的处理路径)

  • 系统扩展性增强(方便新增数据源)

http://www.dtcms.com/a/314560.html

相关文章:

  • 将AAL图谱对应到Yeo7大网络中【原理,代码分析】
  • 断点续传Demo实现
  • 16.8 华为昇腾CANN架构深度实战:3大核心引擎解析与性能优化216%秘籍
  • C++高频知识点(十四)
  • 如果发送的数据和接受的数据不一致时,怎么办?
  • 从 Hive 数仓出发,全面剖析 StarRocks、MySQL、HBase 的使用场景与区别
  • Linux-Day02.Linux指令
  • Vue 3 + AntV X6 实现流程编辑功能
  • C语言-指针[指针数组和数组指针]
  • 【web应用】Maven:Java 生态的构建与依赖管理利器
  • LeetCode算法日记 - Day 1: 移动零、复写零
  • 排序算法——归并排序(图文演示)
  • 最小二乘法MSE
  • 【Linux】重生之从零开始学习运维之GTID复制
  • 【动态规划 | 回文字串问题】动态规划解回文问题的核心套路
  • docker镜像源配置教程,以及解决安装好docker配置镜像源后,出现报错。Job for docker.service failed
  • 在 C++ 中实现类似 Vue 3 的 Pinia 状态管理库
  • C++模板知识点3『std::initializer_list初始化时逗号表达式的执行顺序』
  • 2025-08月特辑---私有化部署gitea仓库
  • Android UI 组件系列(九):ListView 性能优化与 ViewHolder 模式实战
  • 信息安全概述
  • LightRAG:大模型时代的低成本检索利器
  • HCIP笔记1
  • OpenCV计算机视觉实战(18)——视频处理详解
  • 经典设计模式
  • 电商系统想撑住大流量?ZKmall开源商城靠微服务 + Spring Boot3 解决单体架构难题
  • VS2019 Qt5.14.2 OpenCV4.4.0 全流程安装及开发环境搭建与配置(工业相机环境配置)
  • SpringMVC在前后端分离架构中的执行流程详解
  • 【C++指南】STL stack 完全解读(一):从入门到掌握基础操作
  • 【C#】操作Execl和Word文件-2