在构建RAG问答系统时,不同类型的问题需要不同的处理策略。本文将介绍如何通过路由机制,对简单、复杂和无关问题进行分流,从而提升系统的效率与回答质量。

一、为什么需要路由?

传统的RAG系统对所有用户问题都采用相同的“检索-生成”流程。然而,在实际应用中,问题的复杂度差异很大:

  • 简单问题:如“公司年假有几天?”——只需基础检索即可。

  • 复杂问题:如“对比去年和今年的销售增长率,并分析原因?”——需要多步推理、多次检索甚至调用计算工具。

  • 无关问题:如“讲个笑话”——与知识库无关,无需检索。

如果不加区分,对所有问题都执行完整的RAG流程,会导致:

  • 简单问题响应慢(检索浪费)

  • 复杂问题回答不准确(检索不足)

  • 无关问题产生幻觉(强行检索反而引入噪声)

路由的核心思想:先对问题进行分类,再根据类别将请求导向最合适的处理流程。


二、问题分类与处理策略

类型特征处理策略示例
简单事实性、单跳、答案短基础RAG(快速检索+生成)“2024年春节是几月几号?”
复杂多跳、比较、总结、推理Agent或多步检索+工具调用“A产品和B产品的利润差异原因?”
不相干与知识库主题无关、闲聊、恶意通用LLM直接回答(无检索)“你好”、“讲个笑话”

通过这种分流,系统可以:

  • 简单问题快速响应(节省资源)

  • 复杂问题精准处理(动用高级能力)

  • 无关问题友好回应(避免检索噪音)


三、路由实现思路

3.1 分类器设计

有三种实现方式:

方式优点缺点适用场景
基于LLM灵活、准确高耗时、消耗token问题类型多样,精度要求高
基于规则极快、零成本覆盖有限,易误判问题模式固定,可枚举
基于嵌入分类器速度快、可离线需要标注训练大规模生产环境

推荐混合方式:先用规则快速命中明显类型(如“你好”归为无关),其余交给LLM分类。

LLM分类提示词示例

python

classification_prompt = """
将以下用户问题分类为:simple、complex、irrelevant。
- simple:事实性、单步查询、答案短。
- complex:需要多步推理、比较、计算或总结。
- irrelevant:与知识库主题无关或闲聊。

问题:{user_query}
输出仅为一个单词。
"""

3.2 路由分发逻辑

python

def route_question(user_query):
    category = classify(user_query)   # 返回 'simple' / 'complex' / 'irrelevant'
    
    if category == 'simple':
        return simple_rag_chain.invoke(user_query)
    elif category == 'complex':
        return complex_agent_chain.invoke(user_query)
    else:
        return general_llm.invoke(user_query)

四、各分支的具体设计

4.1 简单问题:基础RAG

  • 检索:向量相似度检索,取Top-3。

  • 生成:简洁提示词,要求直接给出答案。

  • 优化:可缓存高频问题结果。

python

from langchain.chains import RetrievalQA

simple_qa = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
    chain_type_kwargs={"prompt": SIMPLE_PROMPT}
)

4.2 复杂问题:Agent或多步检索

复杂问题通常需要多跳推理。可以使用:

  • ReAct Agent:赋予工具(检索、计算、搜索)。

  • 多步检索链:先检索初步答案,再根据答案中的实体进行二次检索。

python

from langchain.agents import create_react_agent

tools = [retrieve_tool, calculator_tool, web_search_tool]
agent = create_react_agent(llm, tools, COMPLEX_PROMPT)

4.3 不相干问题:通用LLM

  • 不检索任何知识库。

  • 系统提示:设定为友好助手,可闲聊,但告知无法回答业务相关问题时可引导回主题。

python

response = general_llm.invoke(user_query)

五、LangChain 完整示例

python

from langchain.chains import RetrievalQA
from langchain.agents import create_react_agent
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama

# 初始化模型和检索器
llm = ChatOllama(model="qwen2.5:7b")
retriever = vectorstore.as_retriever()

# 定义三个处理链
simple_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
complex_agent = create_react_agent(llm, tools, ...)
general_llm = llm

# 分类函数(简化版,实际可用LLM)
def classify(query):
    if any(kw in query for kw in ["你好", "谢谢", "天气"]):
        return "irrelevant"
    elif any(kw in query for kw in ["为什么", "对比", "分析", "总结"]):
        return "complex"
    else:
        return "simple"

def router(query):
    cat = classify(query)
    if cat == "simple":
        return simple_chain.invoke(query)
    elif cat == "complex":
        return complex_agent.invoke({"input": query})
    else:
        return general_llm.invoke(query)

# 使用
while True:
    q = input("问题:")
    print(router(q))

六、优化建议与避坑指南

  • 分类准确性:LLM分类可能出错,可设置置信度阈值,低置信度时走默认策略(如complex)。

  • 性能与成本:路由本身会消耗时间,对于高频场景可缓存分类结果。

  • 动态调整:根据用户反馈(如“答案不准确”)可调整路由策略或重新训练分类器。

  • 安全:对不相干问题也要防止注入攻击,可增加内容过滤。


七、总结

通过引入路由机制,RAG系统能够:

  • 简单问题快速响应,节省资源。

  • 复杂问题精准处理,动用多步推理。

  • 无关问题友好回应,避免检索噪声。


参考资料

  • LangChain 文档:Agents, RetrievalQA

  • 论文:ReAct: Synergizing Reasoning and Acting in Language Models

本文为原创,转载请注明出处。欢迎在评论区交流讨论!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐