Agentic RAG:Agent 驱动的自主检索

进阶 C · Agentic RAG:Agent 驱动的自主检索

当问题需要"先查 A,根据 A 的结果再查 B,最后对比 C"时,传统的一轮检索不够。Agentic RAG 让 AI 自主决定检索策略。


1. 从被动检索到主动探索

css 复制代码
传统 RAG:    User→检索→生成   (一轮定胜负)

Agentic RAG: User→Agent 自我规划
                     ├─ 检索A → 分析 → 发现需要B
                     ├─ 检索B → 分析 → 还需要C
                     └─ 检索C → 综合回答

核心变化:检索不再是"用户问什么就搜什么",而是 Agent 自主决定"搜什么、搜几次、怎么搜"。


2. Agentic RAG 节点实现

php 复制代码
// agentic-rag/agent.ts
import { tool } from "@langchain/core/tools";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";

// Tool 1: 搜索知识库
const searchKB = tool(
  async ({ query }) => {
    const results = await vectorStore.similaritySearch(query, 5);
    return results.map(r =>
      `[来源: ${r.metadata.source}]\n${r.pageContent}`
    ).join("\n\n---\n\n");
  },
  {
    name: "search_knowledge_base",
    description: "搜索知识库中的文档。输入一个具体的搜索问题。",
    schema: z.object({ query: z.string().describe("搜索查询") }),
  }
);

// Tool 2: 搜索代码仓库
const searchCode = tool(
  async ({ query, repoPath }) => {
    // 调用 grep 或代码搜索 API
    const { stdout } = await execAsync(`grep -rn "${query}" ${repoPath} --include="*.ts" | head -20`);
    return stdout || "未找到匹配";
  },
  {
    name: "search_codebase",
    description: "在代码仓库中搜索。输入关键词和路径。",
    schema: z.object({
      query: z.string(),
      repoPath: z.string().optional(),
    }),
  }
);

// Tool 3: 比较文档
const compareDocs = tool(
  async ({ doc1Id, doc2Id, aspect }) => {
    const [doc1, doc2] = await Promise.all([
      getDocument(doc1Id), getDocument(doc2Id)
    ]);
    return llm.invoke(`比较以下两篇文档关于"${aspect}"的异同:\n文档1: ${doc1}\n文档2: ${doc2}`);
  },
  {
    name: "compare_documents",
    description: "比较两篇文档在某个方面的异同。",
    schema: z.object({
      doc1Id: z.string(),
      doc2Id: z.string(),
      aspect: z.string(),
    }),
  }
);

// 组装 Agent
const agent = await createOpenAIFunctionsAgent({
  llm: new ChatOpenAI({ model: "gpt-4o" }),
  tools: [searchKB, searchCode, compareDocs],
  prompt: ChatPromptTemplate.fromMessages([
    ["system", `你是一个知识检索 Agent。对于复杂问题:
1. 先分解问题,确定需要检索哪些信息
2. 逐一检索,分析结果
3. 如果信息不足,继续检索
4. 综合所有检索结果给出回答,并标注来源`],
    ["human", "{input}"],
    ["placeholder", "{agent_scratchpad}"],
  ]),
});

const executor = new AgentExecutor({ agent, tools: [searchKB, searchCode, compareDocs] });

3. 实战:复杂技术问题的多轮检索

vbnet 复制代码
const result = await executor.invoke({
  input: "我们项目的认证方案和业界最佳实践有哪些差距?需要改动哪些文件?"
});

// Agent 自主执行过程:
// Step 1: search_knowledge_base("认证最佳实践")
// Step 2: search_knowledge_base("当前项目认证实现")
// Step 3: search_codebase("authenticate", "./src")
// Step 4: compare_documents(doc1, doc2, "认证方案")
// Step 5: 综合回答

4. GraphRAG + AgenticRAG 组合

当 Agent 能同时操作文本检索和图谱检索:

php 复制代码
// Tool 4: 图谱查询
const queryGraph = tool(
  async ({ entity, relation }) => {
    const result = await graphRetriever.search(entity);
    return `与"${entity}"的关系:${JSON.stringify(result.relations)}`;
  },
  {
    name: "query_knowledge_graph",
    description: "查询知识图谱中某个实体的关联关系。",
    schema: z.object({
      entity: z.string(),
      relation: z.string().optional(),
    }),
  }
);

典型对话

css 复制代码
User: "支付模块挂了会影响哪些服务?"
Agent: 
  1. query_graph("支付模块", "depends_on")  → 发现 6 个直接依赖
  2. search_kb("支付模块故障处理")           → 拿到故障预案文档
  3. 综合回答:列出影响的服务链 + 推荐的故障处理步骤

5. Agentic RAG 的工程挑战

挑战 表现 应对
过度检索 Agent 连续检索 10+ 次不停止 设置 maxIterations=5
检索漂移 偏离原始问题,越搜越远 每次检索前让 Agent 确认"这一步能帮回答原问题吗"
重复检索 用相似关键词反复搜 缓存检索结果,去重
成本爆炸 Agent 每一步都调 LLM + Embedding 设置 token 预算,简单问题降级为传统 RAG
幻觉放大 Agent 误解检索结果,基于错误信息继续检索 要求每轮输出"当前发现"供审计

6. 何时用 Agentic RAG

arduino 复制代码
问题复杂度评估:
├─ 单概念查询 ("React.memo 怎么用") → 传统 RAG
├─ 比较查询 ("memo vs useMemo") → 传统 RAG + 多检索
└─ 探索性查询 ("我们的系统有哪些性能瓶颈?")
    └─ Agentic RAG(需要自主探索)

经验法则:如果人类回答这个问题需要查 3 个以上不同来源,就值得用 Agentic RAG。


7. 最小可运行 Agentic RAG

php 复制代码
// agentic-rag/minimal.ts
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { ChatOpenAI } from "@langchain/openai";

export async function createMinimalAgentRAG(vectorStore: any) {
  const searchTool = tool(
    async ({ query }) => {
      const results = await vectorStore.similaritySearch(query, 5);
      return results.map(r => r.pageContent).join("\n---\n");
    },
    { name: "search", description: "搜索知识库", schema: z.object({ query: z.string() }) }
  );

  const agent = await createOpenAIFunctionsAgent({
    llm: new ChatOpenAI({ model: "gpt-4o" }),
    tools: [searchTool],
    prompt: ChatPromptTemplate.fromMessages([
      ["system", "你是知识库助手。复杂问题可以多次搜索后再回答。"],
      ["human", "{input}"],
      ["placeholder", "{agent_scratchpad}"],
    ]),
  });

  return new AgentExecutor({
    agent,
    tools: [searchTool],
    maxIterations: 5,
    returnIntermediateSteps: true,  // 返回中间步骤供 UI 展示
  });
}

上一篇:B · Graph RAG:知识图谱增强检索

系列完结。回到第一篇:RAG 架构全景与 Node.js 选型地图

相关推荐
阿黎梨梨8 小时前
AI 推理太慢用户要退钱?前端流式输出(Stream)究竟是何方神圣?
前端·vue.js
只一8 小时前
从0到1吃透AI流式输出:Vue3+DeepSeek实战,解锁丝滑对话体验
前端·vue.js
JZC_xiaozhong8 小时前
OA调价审批后,采购调价单如何自动同步到ERP?解决漏录错价难题
大数据·linux·服务器·前端·数据库·数据孤岛解决方案·数据集成与应用集成
卷无止境8 小时前
Flet 完全教程:用纯 Python 构建跨平台应用
前端·python
Cobyte8 小时前
24.Vue Vapor 组件事件 emit 的实现
前端·javascript·vue.js
Flynt8 小时前
TypeScript 5.8 让我少踩了一个大坑,顺手再聊聊 --erasableSyntaxOnly
前端·javascript·typescript
用户2930750976698 小时前
# 从零开始,打造 AI 产品的第一个关键体验——流式输出
前端·vue.js
小杍随笔8 小时前
【 .npmrc 终极配置指南:统一管理 npm/pnpm 缓存与全局目录,告别磁盘混乱】
前端·缓存·npm
默_笙8 小时前
👍 手写一个 MCP 文件读取服务:原来 AI 能"读"我的文件,全靠这个协议
前端·javascript
饮茶三千8 小时前
基于 WangEditor 的富文本编辑器定制实践
前端·vue.js·设计模式