在这里插入图片描述

  【个人主页:玄同765

大语言模型(LLM)开发工程师中国传媒大学·数字媒体技术(智能交互与游戏设计)

深耕领域:大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调

技术栈:Python / LangChain/RAG(Dify+Redis+Milvus)| SQL/NumPy | FastAPI+Docker ️

工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案 

     

「让AI交互更智能,让技术落地更高效」

欢迎技术探讨/项目合作! 关注我,解锁大模型与智能交互的无限可能!

核心内容:本文将深入解析传统RAG与Agentic RAG的核心差异,通过对比架构设计、实现方式和实战案例,帮助你理解为什么Agentic RAG是下一代AI应用的关键技术。


一、RAG技术概述

1.1 什么是RAG

RAG(Retrieval-Augmented Generation,检索增强生成) 是一种将外部知识检索与大语言模型生成能力相结合的技术架构。它通过从外部知识库中检索相关信息,并将其作为上下文提供给LLM,从而生成更准确、更可靠的回答。

1.2 RAG的核心价值

┌─────────────────────────────────────────────────────────────┐
│                      RAG核心价值                             │
├─────────────────────────────────────────────────────────────┤
│  ✅ 解决知识截止问题    - 访问最新、私有数据                  │
│  ✅ 减少幻觉生成        - 基于检索到的真实信息                │
│  ✅ 提供可溯源回答      - 引用具体文档来源                    │
│  ✅ 降低微调成本        - 无需重新训练模型                    │
│  ✅ 支持动态更新        - 知识库可实时更新                    │
└─────────────────────────────────────────────────────────────┘

1.3 RAG的典型应用场景

场景 说明 示例
企业知识库问答 基于内部文档的智能客服 产品手册查询、HR政策咨询
法律文档分析 合同审查、案例检索 法规查询、判例匹配
医疗辅助诊断 医学文献检索 症状分析、治疗方案推荐
学术研究助手 论文检索与综述 文献综述、研究趋势分析
代码智能助手 技术文档查询 API使用、最佳实践查询

二、传统RAG架构详解

2.1 传统RAG的工作流程

传统RAG采用线性管道架构,遵循固定的处理流程:

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   用户查询    │ --> │   向量检索    │ --> │   生成回答    │
│   (Query)    │     │  (Retrieve)  │     │  (Generate)  │
└──────────────┘     └──────────────┘     └──────────────┘
                              │
                              v
                       ┌──────────────┐
                       │   向量数据库   │
                       │ (Vector DB)  │
                       └──────────────┘

标准流程

  1. 索引阶段(离线)
  2. 文档加载 → 文本分割 → 嵌入生成 → 向量存储

  3. 查询阶段(在线)

  4. 查询向量化 → 相似度检索 → 上下文构建 → LLM生成

2.2 传统RAG的实现代码

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_classic.chains.combine_documents import create_stuff_documents_chain
from langchain_classic.chains.retrieval import create_retrieval_chain
from langchain_core.prompts import ChatPromptTemplate

# 1. 加载和分割文档
loader = TextLoader("knowledge_base.txt")
docs = loader.load()

splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)

# 2. 创建向量数据库
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)

# 3. 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 4. 创建RAG链
prompt = ChatPromptTemplate.from_messages([
    ("system", "基于以下上下文回答问题:\n{context}"),
    ("human", "{input}")
])

document_chain = create_stuff_documents_chain(ChatOpenAI(), prompt)
rag_chain = create_retrieval_chain(retriever, document_chain)

# 5. 执行查询
response = rag_chain.invoke({"input": "什么是RAG技术?"})
print(response["answer"])

2.3 传统RAG的局限性

局限性 说明 影响
单次检索 只执行一次检索,无法迭代优化 复杂问题检索不充分
静态流程 固定流程,无法根据问题调整 简单问题过度检索
无自我纠错 无法验证生成内容的准确性 可能产生幻觉
缺乏推理 不能进行多步推理和规划 复杂查询处理能力弱
上下文限制 检索结果一次性输入LLM 长文档处理能力受限

三、Agentic RAG:下一代RAG架构

3.1 什么是Agentic RAG

Agentic RAG(智能体化RAG) 是将AI Agent的智能决策能力引入RAG系统的下一代架构。它不再遵循固定的线性流程,而是通过智能体动态决策每个步骤的执行方式。

3.2 Agentic RAG vs 传统RAG

┌─────────────────────────────────────────────────────────────────────┐
│                     架构对比:传统RAG vs Agentic RAG                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   传统RAG(线性管道)          Agentic RAG(智能决策网络)            │
│   ┌─────────┐                  ┌─────────┐                          │
│   │  查询   │                  │  查询   │                          │
│   └────┬────┘                  └────┬────┘                          │
│        │                            │                               │
│        v                            v                               │
│   ┌─────────┐              ┌───────────────┐                        │
│   │  检索   │              │  查询分析Agent │  ← 判断是否需要检索     │
│   └────┬────┘              └───────┬───────┘                        │
│        │                           │                                │
│        v                           v                                │
│   ┌─────────┐              ┌───────────────┐                        │
│   │  生成   │              │  检索Agent    │  ← 决定检索策略        │
│   └─────────┘              └───────┬───────┘                        │
│                                    │                                │
│                                    v                                │
│                            ┌───────────────┐                        │
│                            │  验证Agent    │  ← 检查结果质量        │
│                            └───────┬───────┘                        │
│                                    │                                │
│                                    v                                │
│                            ┌───────────────┐                        │
│                            │  生成Agent    │  ← 生成最终回答        │
│                            └───────────────┘                        │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3.3 Agentic RAG的核心特征

特征 传统RAG Agentic RAG
决策能力 无,固定流程 有,动态决策
检索次数 单次 可多次迭代
查询改写 智能改写优化
自我验证 幻觉检测与纠正
工具使用 仅向量检索 多工具协同
推理能力 多步推理规划

四、Agentic RAG架构深度解析

4.1 Agentic RAG的核心组件

# Agentic RAG核心组件
class AgenticRAGComponents:
    """Agentic RAG的核心组件"""

    def __init__(self):
        # 1. 查询分析器 - 理解用户意图
        self.query_analyzer = QueryAnalyzer()

        # 2. 检索策略选择器 - 选择最佳检索方式
        self.retrieval_selector = RetrievalSelector()

        # 3. 文档评估器 - 评估检索结果质量
        self.doc_evaluator = DocumentEvaluator()

        # 4. 答案生成器 - 生成最终回答
        self.answer_generator = AnswerGenerator()

        # 5. 幻觉检测器 - 验证答案准确性
        self.hallucination_checker = HallucinationChecker()

        # 6. 查询改写器 - 优化检索查询
        self.query_rewriter = QueryRewriter()

4.2 Agentic RAG的工作流程

┌─────────────────────────────────────────────────────────────────┐
│                    Agentic RAG 工作流程                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────┐                                                   │
│  │ 用户输入  │                                                   │
│  └────┬─────┘                                                   │
│       │                                                         │
│       v                                                         │
│  ┌─────────────────────────────────────┐                       │
│  │ Step 1: 查询分析 (Query Analysis)   │                       │
│  │ - 理解查询意图                        │                       │
│  │ - 判断复杂度                          │                       │
│  │ - 决定是否需要检索                     │                       │
│  └──────────────┬──────────────────────┘                       │
│                 │                                               │
│       ┌─────────┴─────────┐                                     │
│       │                   │                                     │
│       v                   v                                     │
│  ┌─────────┐        ┌─────────┐                                │
│  │直接回答  │        │需要检索  │                                │
│  └────┬────┘        └────┬────┘                                │
│       │                  │                                      │
│       v                  v                                      │
│  ┌──────────┐    ┌─────────────────────────────────────┐       │
│  │ 生成答案  │    │ Step 2: 检索策略选择                 │       │
│  └──────────┘    │ - 选择检索工具                        │       │
│                  │ - 确定检索参数                        │       │
│                  └──────────────┬──────────────────────┘       │
│                                 │                               │
│                                 v                               │
│                  ┌─────────────────────────────────────┐       │
│                  │ Step 3: 执行检索                     │       │
│                  │ - 向量检索                           │       │
│                  │ - 关键词检索                         │       │
│                  │ - 网络搜索                           │       │
│                  └──────────────┬──────────────────────┘       │
│                                 │                               │
│                                 v                               │
│                  ┌─────────────────────────────────────┐       │
│                  │ Step 4: 结果评估                     │       │
│                  │ - 评估文档相关性                      │       │
│                  │ - 判断是否足够                        │       │
│                  └──────────────┬──────────────────────┘       │
│                                 │                               │
│                    ┌────────────┴────────────┐                 │
│                    │                          │                 │
│                    v                          v                 │
│         ┌──────────────┐           ┌──────────────┐            │
│         │ 结果充足      │           │ 结果不足      │            │
│         └──────┬───────┘           └──────┬───────┘            │
│                │                          │                     │
│                v                          v                     │
│         ┌──────────┐           ┌─────────────────────┐         │
│         │生成答案   │           │ Step 5: 查询改写     │         │
│         └──────────┘           │ - 优化查询词        │         │
│                                │ - 重新检索          │         │
│                                └──────────┬──────────┘         │
│                                           │                    │
│                                           └──────→ (回到Step 3)│
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ Step 6: 答案验证 (Hallucination Check)                  │   │
│  │ - 验证答案是否基于检索内容                                │   │
│  │ - 检测幻觉                                              │   │
│  └────────────────────────┬────────────────────────────────┘   │
│                           │                                     │
│                 ┌─────────┴─────────┐                           │
│                 │                   │                           │
│                 v                   v                           │
│          ┌──────────┐        ┌──────────┐                      │
│          │ 验证通过  │        │ 验证失败  │                      │
│          └────┬─────┘        └────┬─────┘                      │
│               │                   │                             │
│               v                   v                             │
│          ┌──────────┐        ┌──────────┐                      │
│          │ 返回答案  │        │ 重新生成  │                      │
│          └──────────┘        └──────────┘                      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.3 Agentic RAG的关键技术

4.3.1 查询分析与路由
from typing import Literal
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field

class QueryAnalysis(BaseModel):
    """查询分析结果"""
    query_type: Literal["factual", "analytical", "creative", "ambiguous"] = Field(
        description="查询类型:事实性、分析性、创造性、模糊"
    )
    complexity: Literal["simple", "medium", "complex"] = Field(
        description="复杂度级别"
    )
    needs_retrieval: bool = Field(
        description="是否需要检索外部知识"
    )
    reasoning_steps: int = Field(
        description="预估需要的推理步骤数"
    )

def analyze_query(query: str) -> QueryAnalysis:
    """分析用户查询"""
    prompt = ChatPromptTemplate.from_messages([
        ("system", """分析用户查询的特征,包括:
        1. 查询类型:事实性(需要具体信息)、分析性(需要推理)、创造性(需要生成)、模糊(需要澄清)
        2. 复杂度:简单(直接回答)、中等(需要一些推理)、复杂(需要多步推理)
        3. 是否需要检索:判断是否需要外部知识
        4. 推理步骤:预估需要的推理步骤数"""),
        ("human", "查询: {query}")
    ])

    llm = ChatOpenAI(model="gpt-4o-mini")
    structured_llm = llm.with_structured_output(QueryAnalysis)

    chain = prompt | structured_llm
    return chain.invoke({"query": query})

# 使用示例
result = analyze_query("比较Transformer和RNN在序列建模中的优缺点")
print(f"查询类型: {result.query_type}")
print(f"复杂度: {result.complexity}")
print(f"需要检索: {result.needs_retrieval}")
4.3.2 自适应检索策略
from typing import List, Optional
from langchain_core.documents import Document

class AdaptiveRetriever:
    """自适应检索器"""

    def __init__(self, vectorstore, web_search_tool=None):
        self.vectorstore = vectorstore
        self.web_search = web_search_tool

    def retrieve(self, query: str, strategy: str = "auto") -> List[Document]:
        """
        根据策略执行检索

        Args:
            query: 查询字符串
            strategy: 检索策略 ("vector", "keyword", "web", "hybrid", "auto")
        """
        if strategy == "auto":
            strategy = self._select_strategy(query)

        if strategy == "vector":
            return self._vector_search(query)
        elif strategy == "keyword":
            return self._keyword_search(query)
        elif strategy == "web":
            return self._web_search(query)
        elif strategy == "hybrid":
            return self._hybrid_search(query)
        else:
            return self._vector_search(query)

    def _select_strategy(self, query: str) -> str:
        """自动选择检索策略"""
        # 简单启发式规则
        if any(word in query.lower() for word in ["latest", "recent", "news", "2024", "2025"]):
            return "web"  # 需要最新信息
        elif any(word in query.lower() for word in ["compare", "difference", "vs"]):
            return "hybrid"  # 需要对比,使用混合检索
        elif len(query.split()) < 5:
            return "keyword"  # 短查询,关键词检索
        else:
            return "vector"  # 默认向量检索

    def _vector_search(self, query: str) -> List[Document]:
        """向量相似度搜索"""
        retriever = self.vectorstore.as_retriever(search_kwargs={"k": 5})
        return retriever.invoke(query)

    def _keyword_search(self, query: str) -> List[Document]:
        """关键词搜索(使用BM25)"""
        from langchain_community.retrievers import BM25Retriever
        # 实现关键词检索逻辑
        pass

    def _web_search(self, query: str) -> List[Document]:
        """网络搜索"""
        if self.web_search:
            results = self.web_search.invoke(query)
            return [Document(page_content=r["content"], metadata={"source": r["url"]}) 
                    for r in results]
        return []

    def _hybrid_search(self, query: str) -> List[Document]:
        """混合检索:向量 + 关键词"""
        vector_results = self._vector_search(query)
        keyword_results = self._keyword_search(query)
        # 融合两种检索结果
        return self._merge_results(vector_results, keyword_results)

    def _merge_results(self, results1: List[Document], results2: List[Document]) -> List[Document]:
        """合并检索结果并去重"""
        seen = set()
        merged = []
        for doc in results1 + results2:
            key = doc.page_content[:100]  # 使用内容前100字符作为去重键
            if key not in seen:
                seen.add(key)
                merged.append(doc)
        return merged[:10]  # 返回前10个结果
4.3.3 迭代检索与查询改写
class IterativeRetriever:
    """迭代检索器 - 支持多轮检索"""

    def __init__(self, llm, retriever, max_iterations=3):
        self.llm = llm
        self.retriever = retriever
        self.max_iterations = max_iterations

    def retrieve_with_refinement(self, query: str) -> List[Document]:
        """
        通过迭代优化进行检索

        策略:
        1. 初始检索
        2. 评估结果质量
        3. 如果质量不足,改写查询并重新检索
        4. 重复直到满意或达到最大迭代次数
        """
        all_docs = []
        current_query = query

        for i in range(self.max_iterations):
            # 执行检索
            docs = self.retriever.invoke(current_query)
            all_docs.extend(docs)

            # 评估检索质量
            quality_score = self._evaluate_quality(docs, query)

            if quality_score >= 0.8:  # 质量足够
                break

            if i < self.max_iterations - 1:  # 还有迭代次数
                # 改写查询
                current_query = self._rewrite_query(current_query, docs, query)
                print(f"迭代 {i+1}: 查询改写为 -> {current_query}")

        # 去重并返回
        return self._deduplicate(all_docs)

    def _evaluate_quality(self, docs: List[Document], query: str) -> float:
        """评估检索结果质量"""
        if not docs:
            return 0.0

        # 使用LLM评估相关性
        prompt = f"""评估以下文档与用户查询的相关性(0-1分):

查询: {query}

文档:
{docs[0].page_content[:500]}

只返回一个0到1之间的数字,表示相关性得分。"""

        try:
            response = self.llm.invoke(prompt)
            score = float(response.content.strip())
            return min(max(score, 0.0), 1.0)  # 确保在0-1范围内
        except:
            return 0.5  # 默认中等质量

    def _rewrite_query(self, current_query: str, docs: List[Document], original_query: str) -> str:
        """基于已有结果改写查询"""
        prompt = f"""基于原始查询和已检索到的信息,生成一个新的查询以获取更多相关信息。

原始查询: {original_query}
当前查询: {current_query}

已检索到的信息片段:
{chr(10).join([f"- {doc.page_content[:200]}..." for doc in docs[:3]])}

请生成一个更具体、更有针对性的查询,以获取缺失的信息。只返回查询字符串。"""

        response = self.llm.invoke(prompt)
        return response.content.strip()

    def _deduplicate(self, docs: List[Document]) -> List[Document]:
        """文档去重"""
        seen = set()
        unique = []
        for doc in docs:
            key = hash(doc.page_content[:200])
            if key not in seen:
                seen.add(key)
                unique.append(doc)
        return unique
4.3.4 幻觉检测与自我纠正
from typing import Tuple

class HallucinationDetector:
    """幻觉检测器"""

    def __init__(self, llm):
        self.llm = llm

    def check(self, answer: str, context: List[Document]) -> Tuple[bool, str]:
        """
        检测答案中是否存在幻觉

        Returns:
            (是否存在幻觉, 解释说明)
        """
        context_text = "\n\n".join([doc.page_content for doc in context])

        prompt = f"""验证以下答案是否完全基于提供的上下文,是否存在幻觉(编造信息)。

上下文:
{context_text[:2000]}

答案:
{answer}

请分析:
1. 答案中的每个事实是否都能在上下文中找到依据?
2. 是否存在上下文之外的信息?
3. 是否存在过度推断?

以JSON格式返回:
{{
    "has_hallucination": true/false,
    "explanation": "详细解释",
    "unsupported_claims": ["具体的不受支持的陈述"]
}}"""

        try:
            response = self.llm.invoke(prompt)
            # 解析JSON响应
            import json
            result = json.loads(response.content)
            return result.get("has_hallucination", False), result.get("explanation", "")
        except:
            # 如果解析失败,保守起见认为可能存在幻觉
            return True, "无法验证答案"

    def correct(self, answer: str, context: List[Document]) -> str:
        """纠正幻觉,基于上下文重新生成答案"""
        context_text = "\n\n".join([doc.page_content for doc in context])

        prompt = f"""基于以下上下文重新生成答案。确保答案完全基于上下文,不要添加外部信息。

上下文:
{context_text[:2000]}

原答案(可能包含幻觉):
{answer}

请生成一个准确、基于上下文的答案:"""

        response = self.llm.invoke(prompt)
        return response.content


class SelfCorrectingRAG:
    """自我纠正的RAG系统"""

    def __init__(self, llm, retriever, max_retries=2):
        self.llm = llm
        self.retriever = retriever
        self.detector = HallucinationDetector(llm)
        self.max_retries = max_retries

    def generate(self, query: str) -> dict:
        """生成答案,包含自我纠正机制"""
        # 检索相关文档
        docs = self.retriever.invoke(query)
        context = "\n\n".join([doc.page_content for doc in docs])

        # 初始生成
        answer = self._generate_answer(query, context)

        # 幻觉检测与纠正
        for i in range(self.max_retries):
            has_hallucination, explanation = self.detector.check(answer, docs)

            if not has_hallucination:
                break

            print(f"检测到幻觉,正在纠正... (尝试 {i+1}/{self.max_retries})")
            print(f"原因: {explanation}")

            # 重新生成
            answer = self.detector.correct(answer, docs)

        return {
            "answer": answer,
            "context": docs,
            "has_hallucination": has_hallucination if 'has_hallucination' in locals() else False
        }

    def _generate_answer(self, query: str, context: str) -> str:
        """基于上下文生成答案"""
        prompt = f"""基于以下上下文回答问题。

上下文:
{context}

问题: {query}

答案:"""

        response = self.llm.invoke(prompt)
        return response.content

五、使用LangGraph构建Agentic RAG

5.1 LangGraph简介

LangGraph 是LangChain的扩展库,专门用于构建复杂的多智能体工作流。它使用图(Graph)结构来定义状态机,非常适合实现Agentic RAG。

5.2 Agentic RAG状态机设计

from typing import TypedDict, List, Annotated
from langgraph.graph import StateGraph, END
from langchain_core.documents import Document
import operator

class AgenticRAGState(TypedDict):
    """Agentic RAG的状态定义"""
    query: str                          # 用户查询
    query_type: str                     # 查询类型
    documents: List[Document]           # 检索到的文档
    rewritten_queries: List[str]        # 改写后的查询历史
    iteration: int                      # 当前迭代次数
    answer: str                         # 生成的答案
    needs_retrieval: bool               # 是否需要检索
    quality_score: float                # 答案质量评分
    has_hallucination: bool             # 是否存在幻觉

def create_agentic_rag_graph(llm, retriever):
    """创建Agentic RAG的状态图"""

    # 1. 查询分析节点
    def analyze_query_node(state: AgenticRAGState) -> AgenticRAGState:
        query = state["query"]

        # 分析查询
        analysis = analyze_query(query)

        return {
            **state,
            "query_type": analysis.query_type,
            "needs_retrieval": analysis.needs_retrieval,
            "iteration": 0,
            "rewritten_queries": []
        }

    # 2. 检索节点
    def retrieve_node(state: AgenticRAGState) -> AgenticRAGState:
        query = state["query"]

        # 如果有改写查询,使用最新的
        if state["rewritten_queries"]:
            query = state["rewritten_queries"][-1]

        # 执行检索
        docs = retriever.invoke(query)

        return {
            **state,
            "documents": docs,
            "iteration": state["iteration"] + 1
        }

    # 3. 评估节点
    def evaluate_node(state: AgenticRAGState) -> AgenticRAGState:
        docs = state["documents"]
        query = state["query"]

        # 评估检索质量
        detector = HallucinationDetector(llm)
        quality_score = detector._evaluate_quality(docs, query)

        return {
            **state,
            "quality_score": quality_score
        }

    # 4. 查询改写节点
    def rewrite_node(state: AgenticRAGState) -> AgenticRAGState:
        query = state["query"]
        docs = state["documents"]

        # 改写查询
        iterative_retriever = IterativeRetriever(llm, retriever)
        rewritten = iterative_retriever._rewrite_query(
            state["rewritten_queries"][-1] if state["rewritten_queries"] else query,
            docs,
            query
        )

        return {
            **state,
            "rewritten_queries": state["rewritten_queries"] + [rewritten]
        }

    # 5. 生成答案节点
    def generate_node(state: AgenticRAGState) -> AgenticRAGState:
        query = state["query"]
        docs = state["documents"]

        context = "\n\n".join([doc.page_content for doc in docs])

        # 生成答案
        prompt = f"""基于以下上下文回答问题。

上下文:
{context}

问题: {query}

请提供详细、准确的答案:"""

        response = llm.invoke(prompt)

        return {
            **state,
            "answer": response.content
        }

    # 6. 幻觉检测节点
    def hallucination_check_node(state: AgenticRAGState) -> AgenticRAGState:
        answer = state["answer"]
        docs = state["documents"]

        detector = HallucinationDetector(llm)
        has_hallucination, _ = detector.check(answer, docs)

        return {
            **state,
            "has_hallucination": has_hallucination
        }

    # 7. 直接回答节点(无需检索)
    def direct_answer_node(state: AgenticRAGState) -> AgenticRAGState:
        query = state["query"]

        response = llm.invoke(f"回答以下问题:{query}")

        return {
            **state,
            "answer": response.content,
            "documents": []
        }

    # 构建图
    workflow = StateGraph(AgenticRAGState)

    # 添加节点
    workflow.add_node("analyze", analyze_query_node)
    workflow.add_node("retrieve", retrieve_node)
    workflow.add_node("evaluate", evaluate_node)
    workflow.add_node("rewrite", rewrite_node)
    workflow.add_node("generate", generate_node)
    workflow.add_node("hallucination_check", hallucination_check_node)
    workflow.add_node("direct_answer", direct_answer_node)

    # 设置入口
    workflow.set_entry_point("analyze")

    # 添加条件边
    workflow.add_conditional_edges(
        "analyze",
        lambda state: "retrieve" if state["needs_retrieval"] else "direct_answer"
    )

    workflow.add_edge("direct_answer", END)

    workflow.add_edge("retrieve", "evaluate")

    workflow.add_conditional_edges(
        "evaluate",
        lambda state: (
            "generate" if state["quality_score"] >= 0.7 or state["iteration"] >= 3 
            else "rewrite"
        )
    )

    workflow.add_edge("rewrite", "retrieve")

    workflow.add_edge("generate", "hallucination_check")

    workflow.add_conditional_edges(
        "hallucination_check",
        lambda state: (
            END if not state["has_hallucination"] 
            else "generate"  # 可以添加一个纠正节点
        )
    )

    # 编译图
    return workflow.compile()

# 使用示例
# graph = create_agentic_rag_graph(llm, retriever)
# result = graph.invoke({"query": "什么是Agentic RAG?"})
# print(result["answer"])

5.3 可视化工作流

def visualize_workflow(graph):
    """可视化Agentic RAG工作流"""
    try:
        from IPython.display import Image, display

        # 生成Mermaid图
        mermaid_code = """
        graph TD
            A[查询分析] -->|需要检索| B[检索文档]
            A -->|直接回答| C[生成答案]
            B --> D[评估质量]
            D -->|质量不足| E[改写查询]
            E --> B
            D -->|质量足够| F[生成答案]
            F --> G[幻觉检测]
            G -->|存在幻觉| H[纠正答案]
            H --> G
            G -->|通过检测| I[返回答案]
            C --> I
        """

        print("Agentic RAG工作流:")
        print(mermaid_code)

    except ImportError:
        print("请安装IPython以查看可视化图形")

# 可视化
# visualize_workflow(graph)

六、RAG vs Agentic RAG 实战对比

6.1 测试场景设计

# 测试用例
test_cases = [
    {
        "name": "简单事实查询",
        "query": "什么是RAG技术?",
        "expected_behavior": "传统RAG和Agentic RAG都应该能很好回答"
    },
    {
        "name": "复杂多跳查询",
        "query": "比较Transformer和RNN在序列建模中的优缺点,并说明为什么Transformer更适合并行计算",
        "expected_behavior": "Agentic RAG应该进行多步检索和推理"
    },
    {
        "name": "模糊查询",
        "query": "那个新技术",
        "expected_behavior": "Agentic RAG应该进行查询澄清或改写"
    },
    {
        "name": "需要最新信息",
        "query": "2024年最新的LLM模型有哪些?",
        "expected_behavior": "Agentic RAG应该使用网络搜索工具"
    }
]

6.2 性能对比

指标 传统RAG Agentic RAG 说明
响应时间 快(1-2秒) 较慢(3-10秒) Agentic需要多步推理
准确率 中等(70-80%) 高(85-95%) Agentic能处理更复杂问题
复杂问题处理能力 Agentic支持多步推理
幻觉率 中等(15-20%) 低(5-10%) Agentic有自我验证机制
成本 Agentic需要更多LLM调用
可解释性 Agentic有明确的推理步骤

6.3 选择建议

使用传统RAG的场景
- ✅ 查询简单明确,不需要复杂推理
- ✅ 对响应时间要求高
- ✅ 预算有限,需要控制成本
- ✅ 知识库稳定,不需要频繁更新

使用Agentic RAG的场景
- ✅ 查询复杂,需要多步推理
- ✅ 对答案准确性要求极高
- ✅ 需要处理模糊或不完整的查询
- ✅ 需要最新信息(结合网络搜索)
- ✅ 需要可解释的推理过程


七、最佳实践与优化建议

7.1 混合架构设计

class HybridRAG:
    """混合RAG架构 - 根据查询复杂度自动选择策略"""

    def __init__(self, simple_rag, agentic_rag):
        self.simple_rag = simple_rag
        self.agentic_rag = agentic_rag
        self.llm = ChatOpenAI(model="gpt-4o-mini")

    def route_query(self, query: str) -> str:
        """路由查询到合适的RAG系统"""
        prompt = f"""判断以下查询的复杂度,选择最适合的处理方式。

查询: {query}

选项:
1. "simple" - 简单查询,直接回答或单次检索即可
2. "agentic" - 复杂查询,需要多步推理、查询改写或工具使用

只返回 "simple" 或 "agentic"。"""

        response = self.llm.invoke(prompt)
        return response.content.strip().lower()

    def query(self, query: str) -> dict:
        """执行查询"""
        route = self.route_query(query)

        if route == "simple":
            print("使用传统RAG处理...")
            return self.simple_rag.invoke({"input": query})
        else:
            print("使用Agentic RAG处理...")
            return self.agentic_rag.invoke({"query": query})

7.2 成本优化策略

  1. 分层检索:先使用轻量级模型进行初步筛选
  2. 缓存机制:缓存常见查询的结果
  3. 智能路由:简单查询使用传统RAG,复杂查询才使用Agentic RAG
  4. 批量处理:合并多个查询进行批量处理

7.3 评估与监控

class RAGEvaluator:
    """RAG系统评估器"""

    def __init__(self, llm):
        self.llm = llm

    def evaluate(self, query: str, answer: str, context: List[Document]) -> dict:
        """评估RAG回答质量"""

        # 1. 相关性评估
        relevance = self._evaluate_relevance(query, context)

        # 2. 忠实度评估(是否有幻觉)
        faithfulness = self._evaluate_faithfulness(answer, context)

        # 3. 完整性评估
        completeness = self._evaluate_completeness(query, answer)

        return {
            "relevance": relevance,
            "faithfulness": faithfulness,
            "completeness": completeness,
            "overall": (relevance + faithfulness + completeness) / 3
        }

    def _evaluate_relevance(self, query: str, context: List[Document]) -> float:
        """评估检索文档的相关性"""
        # 实现相关性评估逻辑
        pass

    def _evaluate_faithfulness(self, answer: str, context: List[Document]) -> float:
        """评估答案的忠实度"""
        detector = HallucinationDetector(self.llm)
        has_hallucination, _ = detector.check(answer, context)
        return 0.0 if has_hallucination else 1.0

    def _evaluate_completeness(self, query: str, answer: str) -> float:
        """评估答案的完整性"""
        # 实现完整性评估逻辑
        pass

八、总结与展望

8.1 核心要点回顾

  1. 传统RAG:线性管道架构,适合简单查询,成本低但能力有限
  2. Agentic RAG:智能决策架构,适合复杂查询,能力强但成本高
  3. 核心差异:Agentic RAG引入了查询分析、自适应检索、迭代优化和自我验证
  4. LangGraph:构建Agentic RAG的理想工具,支持状态机和工作流编排

8.2 技术演进趋势

阶段 特点 代表技术
RAG 1.0 基础检索+生成 向量检索、简单prompt
RAG 2.0 高级检索策略 Hybrid Search、Reranking
RAG 3.0 Agentic RAG LangGraph、多智能体协作
RAG 4.0 自主智能体 完全自主规划、执行、验证

8.3 未来发展方向

  1. 多模态RAG:支持文本、图像、音频、视频的统一检索
  2. 联邦RAG:跨多个知识源的分布式检索
  3. 个性化RAG:基于用户画像的个性化检索策略
  4. 实时RAG:支持流式数据的实时检索与更新
  5. 可解释RAG:提供清晰的推理过程和决策依据

8.4 学习资源


结语:从传统RAG到Agentic RAG的演进,代表了AI系统从被动工具向主动智能体的转变。理解这两种架构的差异和适用场景,将帮助你构建更强大、更可靠的AI应用。

选择建议
- 从传统RAG开始,满足基本需求
- 逐步引入Agentic特性,解决复杂场景
- 最终构建混合架构,实现最佳性价比

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐