1. 引言
传统 RAG 在复杂问答场景下缺乏主动推理与多步检索能力;本文介绍如何将 Agent 与本地知识库 RAG 系统联用,实现更智能的问答。读完本文你将掌握:Agentic RAG 的核心概念、基于 Langchain4j + PGVector 搭建本地 RAG 知识库的方法、Agent 接入多轮对话的实现步骤,以及使用 DSPy 优化检索性能的进阶思路。
2. 核心概念:RAG 与 Agentic RAG
2.1 RAG 基础
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与文本生成相结合的技术范式。其核心流程分为三步:
检索(Retrieve):当用户提出问题时,系统首先将问题编码为向量,然后在知识库的向量索引中执行近似最近邻(ANN)搜索,召回与问题语义最相关的文档片段。
增强(Augment):将检索到的文档片段作为上下文信息,与用户的原始问题拼接在一起,形成增强后的提示(Prompt)。
生成(Generate):将增强后的提示送入大语言模型,模型基于问题与上下文信息生成最终答案。
RAG 的主要优势体现在三个方面:
- 减少幻觉:通过外挂知识库提供事实依据,LLM 无需依赖自身参数化记忆,显著降低编造信息的概率。
- 知识更新:只需更新知识库文档或向量索引,无需重新训练或微调模型,成本远低于全量微调。
- 特定领域知识:企业可以构建专属领域的知识库(如技术文档、内部规范、产品手册),让通用 LLM 也能回答垂直领域的问题。
在实践中,RAG 系统通常还需要处理文档分块策略、Embedding 模型选型、检索结果重排序等问题。例如,文档分块(chunking)要考虑段落语义的完整性,Embedding 模型要根据语言、文本长度和预算进行选型,检索结果可以使用 RRF(Reciprocal Rank Fusion)融合向量检索与关键字 BM25 的结果,提升召回质量。
2.2 Agentic RAG 演进
传统 RAG 虽然解决了知识外挂问题,但在复杂问答场景下仍存在明显局限。以“请找出2024年财报中涉及研发投入的部分,并对比2023年的数据,给出增长率”这样的查询为例,传统 RAG 可能无法一次完成多条件筛选与跨文档比较。这正是 Agentic RAG 要解决的问题。
Agentic RAG 将大型语言模型与智能 Agent 相结合,Agent 不再是被动地执行一次检索然后生成,而是像智能助手一样主动思考、规划、执行,并与用户进行交互,最终完成任务。具体来说,Agentic RAG 引入了以下能力:
- 主动规划检索策略:Agent 可以将复杂问题拆解为多个子查询。例如,对于上述财务问题,Agent 可能先检索“2024年财报 研发投入”,再检索“2023年财报 研发投入”,然后让另一个工具计算增长率。
- 使用工具(Tools):Agent 可以调用多个工具,例如本地 RAG 知识库查询、Web 搜索、API 调用、代码执行器、数据库查询等。
每个工具都有明确的描述和接口定义。
- 管理多轮对话上下文:Agent 能够记住对话历史,在后续提问中自动关联之前提到的实体或约束条件。例如,用户问“刚才提到的那个方案,具体费用是多少?”Agent 需要从历史记录中找出“那个方案”指的是什么。
- 错误恢复与异常处理:当某个工具调用失败或返回异常结果时,Agent 可以尝试替代策略或向用户请求澄清。
目前,已经有成熟的框架支持 Agentic RAG 的构建,例如微软的 AutoGen(用于构建基于 LLM 的多 Agent 工作流)、Langchain4j(Java 生态下的 Agent 框架)以及 LangChain(Python 生态下的 Agent 框架)。
2.3 适用场景对比
| 场景特征 | 推荐方案 | 说明 |
|---|---|---|
| 简单的单次事实查询 | 传统 RAG | 如“公司的注册地址是什么?” |
| 多条件筛选 | Agentic RAG | 如“查找2024年第一季度,华东区销售额超过100万的客户” |
| 需要多步推理 | Agentic RAG | 如“分析最近三个季度的毛利率变化趋势” |
| 涉及外部系统调用 | Agentic RAG | 如“查询订单状态后,调用CRM系统更新客户等级” |
| 对延迟敏感 | 传统 RAG | Agent 的多步推理会增加响应时间 |
3. 本地知识库搭建:基于 Langchain4j + PGVector
3.1 技术选型理由
在本地知识库 RAG 的搭建中,技术选型需综合考虑生态适配、数据一致性、部署复杂度等因素。Langchain4j 是 Java/Spring 生态下的 LLM 集成框架,提供便捷的 RAG 流程 API;PGVector 是 PostgreSQL 的向量检索扩展,允许在关系数据库中直接存储和查询向量。
选型 PGVector 的核心理由:
- 数据一致性:向量数据与业务关系数据存储在同一个数据库,便于维护元数据关联和事务操作。
- 企业级部署友好:大多数企业内部已部署 PostgreSQL,无需额外引入专用向量数据库(如 Milvus、Qdrant),降低运维复杂度。
- 功能完整:支持多种索引类型(IVFFlat、HNSW)、多种距离度量(余弦、欧氏距离、内积),性能在百万级向量规模下可接受。
3.2 搭建步骤概要
步骤一:安装 PGVector 并创建向量表
确保 PostgreSQL 版本 ≥ 12,然后安装 PGVector 插件:
1 | |
创建向量表时,需要根据 Embedding 模型的输出维度定义列类型。例如,使用 bge-m3 模型(输出 1024 维)时:
1 | |
注意:vector(1024) 中的维度必须与 Embedding 模型的输出维度完全一致。
步骤二:配置 Langchain4j 的向量存储
使用 Langchain4j 的 PgVectorEmbeddingStore 连接 PostgreSQL:
1 | |
对于开发阶段的快速验证,也可以使用 EmbeddingStoreInMemory:
1 | |
步骤三:文档分块与 Embedding 模型选择
文档分块的策略直接影响检索质量。实践中建议:
- 文本类文档:使用段落做天然切割,每个 chunk 保留标题、小标题等上下文信息。
- 表格数据:单独处理,保留表头与行列结构。
- 代码片段:按函数或类分块,保留注释。
分块示例参数:
1 | |
Embedding 模型推荐选择开源且支持多语言的模型,如 bge-m3(BAAI 出品,支持 1024 维、多语言)或 BAAI/bge-large-zh-v1.5(中文场景优先)。Langchain4j 中使用 Embedding 模型:
1 | |
步骤四:写入向量库并验证检索效果
1 | |
检索验证关注 Recall@k 指标(即前 k 个结果中包含正确结果的比例)。对于常见的知识问答场景,k=5 时 Recall 应达到 0.85 以上。
3.3 关键技术细节
- 连接池配置:生产环境下使用 HikariCP 连接池,最小空闲连接设为 5,最大连接数设为 30。
- 相似度检索:PGVector 支持
<->(L2 距离)、<=>(余弦距离)和<#>(内积)。对于语义检索,余弦距离是最常用的度量方式,因为它对向量长度不敏感。 - 检索结果重新排序(RRF 融合):当同时使用向量检索和 BM25 关键字检索时,通过 RRF 公式融合排名:
1 | |
提示:初始搭建时使用 IVFFlat 索引(ivfflat lists = 100)即可满足百万级向量下的毫秒级检索;若数据量达到千万级,建议升级为 HNSW 索引(hnsw ef_construction = 200)。
4. Agent 接入实践:将本地 RAG 作为 Agent 的工具
4.1 Agent 架构设计
一个典型的 Agent 内部结构包括:
- 主 Agent:负责解析用户输入、决定调用哪个工具、管理多轮对话上下文。
- 工具注册表:所有可用的工具列表,每个工具有唯一的名称、描述和调用接口。
- 记忆模块:维护对话历史,用于给 Agent 提供上下文信息。
本地 RAG 知识库作为一类检索工具注册到 Agent 中。当 Agent 判断用户问题需要知识库查询时,它会调用该工具。
4.2 主要工具类型
在 Agent 实践中,除了 RAG 检索工具,通常还会注册以下几类工具:
- RAG 查询工具:从本地知识库检索相关文档片段。
- Web 搜索工具:通过搜索引擎获取外部信息。
- 代码执行工具:运行 Python/SQL 代码并返回结果。
- API 调用工具:调用内部 REST API 获取业务数据。
4.3 实现步骤
4.3.1 定义 RAG 工具接口
在 Langchain4j 中,使用 @Tool 注解定义工具:
1 | |
注意:工具的描述应该清晰明确,以便 Agent 能正确判断何时使用该工具。实践中,可以增加一个示例占位符(如“用法:当用户询问公司政策、产品手册内容时使用此工具”)。
4.3.2 创建 Agent
使用 Assistant 模式创建 Agent,并绑定 LLM 与工具:
1 | |
4.3.3 执行多轮对话
1 | |
4.4 易错点与调优提示
- 工具返回值格式:工具返回的字符串应当尽量结构化,包含文档来源或 ID,便于 Agent 后续引用。例如在结果前加上
[来源:文档A]。 - 超时设置:工具调用应设置超时(建议 15 秒),避免 Agent 因某个工具长时间未响应而卡死。
- 异常处理:在工具方法内部捕获异常,返回友好的错误消息,而不是抛出异常中断 Agent 执行。
5. 多轮对话增强:Agent+RAG 的上下文融合
5.1 问题分析
在传统 RAG 中,每一轮查询都是独立的,丢失了历史对话信息。例如,用户先问“2024年第一季度营收是多少?”,接着追问“比上个季度增长了多少?”,RAG 如果不结合历史,无法知道“上个季度”指的是 2023 年第四季度。
5.2 上下文融合方案
Agent 在构造检索查询时,自动将多轮对话中的关键实体与约束条件拼接进去。具体实现有两种常用方式:
方案一:利用 LLM 的对话摘要能力
让 LLM 在对之前的对话进行总结后,生成当前查询的完整描述。Langchain4j 的 MessageWindowChatMemory 会自动管理历史消息,Agent 会在系统提示中包含对话历史。
在 Agent 内部,工具调用前可以嵌入一个“查询构造”步骤:
1 | |
方案二:手动维护结构化历史
在 Agent 的上下文中维护一个结构化摘要(如 HashMap<String, Object>),记录用户提到的关键实体(例如合同编号、时间范围、产品名称)。工具调用前,从摘要中提取相关约束条件注入查询。
5.3 实现示例
使用 Langchain4j 的 ConversationMemory 时,只需在创建 Agent 时配置即可:
1 | |
5.4 注意事项
- 避免上下文过长:对话历史随着轮数增加会迅速消耗 token。可以设置滑动窗口(例如最近 10 轮对话),或者将历史摘要化(只保留关键实体与问题概要)。
- 定期清理混淆上下文:如果用户在一个会话中讨论了无关的多个话题,Agent 可能检索到错误的上文。可以在每次用户问题时,让 Agent 先判断当前查询是否切换了主题。
6. 进阶技巧:使用 DSPy 优化 RAG 检索与生成性能
6.1 DSPy 简介
DSPy(Declarative Self-improving Language Programs)是一个用于构建和优化 RAG 系统的声明式框架,由斯坦福大学 NLP 组开发。它的核心思想是:开发者以声明方式描述希望程序实现的目标,DSPy 自动优化提示(Prompts)和模型参数,以达到最佳性能。
相比于手动调整提示词,DSPy 的优化流程更加系统化:
- 定义 pipeline 的输入/输出。
- 声明模块(如检索器、生成器)。
- 提供少量标注样本。
- 自动搜索最佳优化策略(如 query 改写、few-shot 示例选择、prompt 模板优化)。
6.2 典型优化场景
查询改写策略优化:用户的原始查询可能不够精确(例如“介绍一下产品”过于宽泛),DSPy 可以自动训练一个“查询重写器”,将用户问题改写为更适合检索的形式(例如“描述公司2024年新推出的ERP产品功能特性”)。
生成阶段 prompt 优化:DSPy 可以优化生成阶段的 prompt,例如在不同任务上自动选择最佳示例数量或调整指令措辞。
6.3 集成路径建议
DSPy 目前主要支持 Python 生态。对于 Java 技术栈的团队,可以考虑以下集成路径:
- 方案一:独立 Python 服务:将 DSPy 优化的 RAG pipeline 封装为一个微服务,通过 gRPC/HTTP 与 Java Agent 通信。
- 方案二:引入 DSPy 的优化结果:在本地训练好最优的 query 改写规则或 prompt 模板后,将规则迁移到 Java Agent 中硬编码。
示例:使用 DSPy 优化查询改写(Python 伪代码)
1 | |
6.4 效果评估
DSPy 优化的效果可以通过对比优化前后的检索与生成指标来量化:
| 指标 | 说明 | 优化前 | 优化后 |
|---|---|---|---|
| Recall@5 | 前5个结果中包含正确文档的比例 | 0.78 | 0.91 |
| NDCG@5 | 排序质量,考虑文档的相关性等级 | 0.65 | 0.82 |
| 生成准确率 | 最终回答与人工标注答案的匹配度 | 0.72 | 0.88 |
评估数据集建议从真实用户问题中采样 200-500 条并人工标注正确答案,保证评估的可靠性。
7. 踩坑记录与性能调优
7.1 常见问题与解决方案
向量库索引选择不当导致检索慢:PGVector 支持 IVFFlat 和 HNSW 两种索引。IVFFlat 索引需要指定 lists 参数(推荐 sqrt(data_size)),当数据量超过 500 万时建议切换为 HNSW。首次建立索引时注意采样完整性:
1 | |
Agent 工具调用循环错误:Agent 可能重复调用同一个工具(例如连续多次调用 RAG 查询,每次返回相似结果)。可以通过设定“最大工具调用次数”来终止循环,或者让工具在返回值中附带“无新信息”标记。
1 | |
多轮对话中历史信息污染:当用户讨论 A 主题后突然切换到 B 主题,Agent 可能错误地融合了 A 主题的上下文。解决方案是在 Agent 的判断逻辑中增加“主题切换检测”,当检测到查询与当前主题无关时,清除之前的上下文。
7.2 性能优化方向
Embedding 模型领域微调:使用高质量的领域数据微调 Embedding 模型,尤其要构造难负样本(hard negatives)。例如,对于技术文档,可以将“Linux 系统安装”与“MySQL 数据库安装”这样容易混淆的文档对作为难负样本。微调后 Recall@5 可提升 5-15%。
1 | |
元数据过滤 + 混合检索:在企业内部知识库中,元数据(如文档类型、创建时间、所属部门)可以有效缩小检索范围。例如,用户提问“2024年的研发政策”,可以先用元数据过滤 year=2024 && type='policy',再执行向量检索。
混合检索使用“向量相似度 (0.7) + 关键字BM25 (0.3)”加权融合,在语义匹配和精确匹配之间取得平衡。
将 Agent 的 LLM 替换为本地小模型:如果 Agent 的响应延迟过高,可以考虑将 LLM 从 GPT-4 切换到本地模型(如 Qwen2.5-7B 或 Llama-3-8B)。虽然部分复杂推理能力会下降,但延迟可从 3 秒降至 0.5 秒。对于简单场景(如工具调用),本地小模型通常足够胜任。
8. 总结与拓展
8.1 核心回顾
本文完整介绍了 Agent 接入本地知识库 RAG 的工程路径,核心要点如下:
本地 RAG 知识库搭建:基于 Langchain4j + PGVector 实现端到端的向量存储与检索,包括插件安装、表结构设计、文档分块策略、Embedding 模型选型与索引配置。
Agent 工具封装:将 RAG 检索功能封装为 Agent 的可调用工具,通过
@Tool注解定义名称、描述和参数,实现 Agent 对知识库的主动、多步调用。多轮对话上下文融合:利用 Langchain4j 的
MessageWindowChatMemory自动管理对话历史,并利用 Agent 的规划能力在每次检索前构造优化查询。DSPy 优化:通过声明式编程与自动化优化,提升 RAG 流水线的检索准确率和生成质量。
8.2 未来方向
- 引入图嵌入与知识图谱:将知识图谱中的实体和关系映射到向量空间,与文档向量共存在同一个检索体系中。这样,Agent 不仅能够检索文档片段,还能直接检索实体之间的关联知识(如“A 部门负责 B 产品线的售后维护”),实现关联推理。
- 多 Agent 协作:一个 Agent 负责检索信息,另一个 Agent 负责验证答案的准确性,第三个 Agent 负责与用户对话。
通过 AutoGen 等框架,让多个 Agent 通过消息传递协同完成任务,提升系统的可靠性和可扩展性。
- 离线评估流程:建立持续的离线评估 pipeline,使用 MTEB (Massive Text Embedding Benchmark) 或其他领域自定义基准,跟踪 Embedding 模型和 RAG pipeline 的质量变化,防止模型更新或数据变化导致性能退化。
8.3 参考资源
GitHub 社区讨论:本地知识库引入 Agentic RAG 或 DSPy 的技术原理与集成建议(可搜索相关 Issue #1889)。
Langchain4j 官方文档:提供了 Java 环境下 Agent 与 RAG 的完整 API 说明。
DSPy 官方教程:包含丰富的 RAG 优化案例,覆盖问答、摘要、生成等场景。
《RAG 离线部分:Embedding模型选型与领域适配微调》系列文章:深入探讨了 Embedding 模型的选型方法、微调策略与评估指标,以及元数据增强、知识图谱融合等进阶方向。
总结
通过本文的学习,相信你已经对「Agent接入本地知识库」有了更深入的理解。建议结合实际项目多加练习。如有疑问,欢迎交流!