第10章 RAG 知识检索
本章目标
- 理解 RAG(检索增强生成)的核心原理和应用场景
- 掌握 AgentScope-Java 的 RAG 架构设计
- 学会使用本地知识库(SimpleKnowledge)构建 RAG 系统
- 了解云端知识库集成(百炼、Dify、RAGFlow、Haystack)
- 掌握两种 RAG 模式:Generic 模式和 Agentic 模式
10.1 RAG 概述
10.1.1 什么是 RAG?
RAG(Retrieval-Augmented Generation,检索增强生成) 是一种将信息检索与文本生成相结合的技术架构。它通过从外部知识库中检索相关文档,将检索到的信息作为上下文注入到语言模型的提示中,从而增强模型的回答质量。
┌─────────────────────────────────────────────────────────────┐
│ RAG 工作流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户问题 向量检索 上下文增强 生成回答 │
│ ┌─────┐ ┌─────────┐ ┌─────────┐ ┌─────┐ │
│ │ Q │──────▶│Knowledge│─────▶│ Prompt │─────▶│ LLM │ │
│ └─────┘ │ Base │ │+Context │ └──┬──┘ │
│ └─────────┘ └─────────┘ │ │
│ ▼ │
│ ┌─────┐ │
│ │ A │ │
│ └─────┘ │
│ │
│ 1. 接收问题 │
│ 2. 将问题转换为向量,在知识库中检索相似文档 │
│ 3. 将检索到的文档作为上下文添加到提示词中 │
│ 4. LLM 结合上下文生成更准确的回答 │
└─────────────────────────────────────────────────────────────┘
10.1.2 为什么需要 RAG?
| 问题 | RAG 如何解决 |
|---|---|
| 知识过时 | LLM 的训练数据有截止日期,无法回答最新信息。RAG 可以实时检索最新知识 |
| 幻觉问题 | LLM 可能生成看似合理但实际错误的内容。RAG 基于真实文档回答,减少幻觉 |
| 领域知识 | 通用 LLM 缺乏特定领域专业知识。RAG 可以注入企业文档、专业资料等 |
| 隐私安全 | 敏感数据不适合发送给 LLM 训练。RAG 让数据留在本地,只在推理时使用 |
| 可解释性 | LLM 回答来源不透明。RAG 可以追溯答案的文档来源 |
10.1.3 AgentScope-Java RAG 架构
┌─────────────────────────────────────────────────────────────────┐
│ AgentScope-Java RAG 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ReActAgent │ │
│ │ ┌─────────────────────┬────────────────────────────┐ │ │
│ │ │ Generic 模式 │ Agentic 模式 │ │ │
│ │ │ (GenericRAGHook) │ (KnowledgeRetrievalTools) │ │ │
│ │ └─────────────────────┴────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Knowledge 接口 │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ + addDocuments(documents): Mono<Void> │ │ │
│ │ │ + retrieve(query, config): Mono<List<Document>> │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │SimpleKnowledge│ │BailianKnowledge│ │DifyKnowledge│ │
│ │ (本地向量库) │ │ (百炼云知识库) │ │(Dify 知识库)│ │
│ └──────┬──────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ┌────┴────┐ │
│ ▼ ▼ │
│ ┌───────┐ ┌─────────┐ │
│ │Embedding│ │VectorStore│ │
│ │ Model │ │(向量存储) │ │
│ └───────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
10.2 核心组件详解
10.2.1 Knowledge 接口
Knowledge 是 RAG 系统的核心抽象接口,定义了知识库的基本操作:
package io.agentscope.core.rag;
import io.agentscope.core.rag.model.Document;
import io.agentscope.core.rag.model.RetrieveConfig;
import java.util.List;
import reactor.core.publisher.Mono;
/**
* 知识库统一接口
* 提供文档存储和检索的标准 API
*/
public interface Knowledge {
/**
* 添加文档到知识库
*
* 文档会被向量化并存储到向量数据库中
*
* @param documents 要添加的文档列表
* @return 完成添加后的 Mono
*/
Mono<Void> addDocuments(List<Document> documents);
/**
* 根据查询检索相关文档
*
* 查询会被向量化,然后在知识库中搜索相似文档
* 结果按相关性分数过滤和排序
*
* @param query 搜索查询文本
* @param config 检索配置(数量限制、分数阈值等)
* @return 按相关性排序的文档列表
*/
Mono<List<Document>> retrieve(String query, RetrieveConfig config);
}
10.2.2 Document 文档模型
Document 是 RAG 系统中的核心数据结构,代表一个文档片段:
// Document 结构示例
Document doc = new Document(metadata);
// 核心字段
doc.getId(); // 文档唯一 ID(自动生成的 UUID)
doc.getMetadata(); // 文档元数据(包含内容)
doc.getEmbedding(); // 向量嵌入(由 EmbeddingModel 生成)
doc.getScore(); // 相似度分数(检索时填充)
doc.getPayload(); // 自定义业务数据
// DocumentMetadata 包含实际内容
metadata.getContent(); // ContentBlock 内容(文本、图片等)
metadata.getContentText(); // 便捷方法:获取文本内容
metadata.getDocId(); // 原始文档 ID
metadata.getChunkId(); // 分块 ID
10.2.3 RetrieveConfig 检索配置
import io.agentscope.core.rag.model.RetrieveConfig;
// 构建检索配置
RetrieveConfig config = RetrieveConfig.builder()
// 最大返回文档数(默认 5)
.limit(5)
// 最小相似度分数阈值(0.0-1.0,默认 0.5)
// 低于此分数的文档会被过滤
.scoreThreshold(0.5)
// 向量名称(可选,用于多向量场景)
.vectorName("default")
// 对话历史(可选,用于多轮检索上下文)
// 百炼等知识库支持基于历史的查询改写
.conversationHistory(conversationHistory)
.build();
提示:
scoreThreshold的最佳值取决于你的嵌入模型和数据质量。建议从 0.5 开始,根据实际效果调整。太高会遗漏相关文档,太低会引入噪声。
10.3 本地知识库:SimpleKnowledge
SimpleKnowledge 是一个完全本地化的 RAG 实现,适合开发测试和中小规模应用。
10.3.1 架构组成
┌────────────────────────────────────────────────────────┐
│ SimpleKnowledge │
├────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ ┌─────────────────────┐ │
│ │ EmbeddingModel │ │ VDBStoreBase │ │
│ │ (嵌入模型) │ │ (向量存储) │ │
│ └───────┬────────┘ └──────────┬──────────┘ │
│ │ │ │
│ │ 文本 → 向量 │ 向量存储/检索 │
│ │ │ │
│ ┌───────┴────────────────────────────┴───────┐ │
│ │ SimpleKnowledge │ │
│ │ - addDocuments(): 嵌入 + 存储文档 │ │
│ │ - retrieve(): 嵌入查询 + 向量搜索 │ │
│ └─────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────┘
10.3.2 完整示例
import io.agentscope.core.embedding.EmbeddingModel;
import io.agentscope.core.embedding.dashscope.DashScopeTextEmbedding;
import io.agentscope.core.rag.Knowledge;
import io.agentscope.core.rag.knowledge.SimpleKnowledge;
import io.agentscope.core.rag.model.Document;
import io.agentscope.core.rag.model.RetrieveConfig;
import io.agentscope.core.rag.reader.ReaderInput;
import io.agentscope.core.rag.reader.SplitStrategy;
import io.agentscope.core.rag.reader.TextReader;
import io.agentscope.core.rag.store.InMemoryStore;
import io.agentscope.core.rag.store.VDBStoreBase;
import java.util.List;
public class SimpleKnowledgeExample {
// 向量维度(需与嵌入模型匹配)
private static final int EMBEDDING_DIMENSIONS = 1024;
public static void main(String[] args) {
String apiKey = System.getenv("DASHSCOPE_API_KEY");
// ========================================
// 步骤 1:创建嵌入模型
// ========================================
// 嵌入模型负责将文本转换为向量
EmbeddingModel embeddingModel = DashScopeTextEmbedding.builder()
.apiKey(apiKey)
.modelName("text-embedding-v3") // 通义千问嵌入模型
.dimensions(EMBEDDING_DIMENSIONS)
.build();
// ========================================
// 步骤 2:创建向量存储
// ========================================
// InMemoryStore 适合开发测试,生产环境建议使用持久化存储
VDBStoreBase vectorStore = InMemoryStore.builder()
.dimensions(EMBEDDING_DIMENSIONS) // 必须与嵌入模型维度一致
.build();
// ========================================
// 步骤 3:创建知识库实例
// ========================================
Knowledge knowledge = SimpleKnowledge.builder()
.embeddingModel(embeddingModel)
.embeddingStore(vectorStore)
.build();
// ========================================
// 步骤 4:准备文档并添加到知识库
// ========================================
addDocumentsToKnowledge(knowledge);
// ========================================
// 步骤 5:检索相关文档
// ========================================
RetrieveConfig config = RetrieveConfig.builder()
.limit(3) // 返回前 3 个最相关的文档
.scoreThreshold(0.3) // 分数阈值
.build();
List<Document> results = knowledge
.retrieve("AgentScope 支持哪些向量数据库?", config)
.block();
// 输出检索结果
System.out.println("检索到 " + results.size() + " 个相关文档:");
for (Document doc : results) {
System.out.printf(" - 分数: %.3f, 内容: %s%n",
doc.getScore(),
truncate(doc.getMetadata().getContentText(), 100));
}
}
/**
* 添加示例文档到知识库
*/
private static void addDocumentsToKnowledge(Knowledge knowledge) {
// 示例文档内容
String[] texts = {
"AgentScope 是一个多智能体系统框架,由 ModelScope 开发。" +
"它提供了统一的接口用于构建和管理多智能体应用。",
"AgentScope 支持多种向量存储,包括 InMemoryStore(内存存储)、" +
"Qdrant、Milvus 和 PgVector(PostgreSQL)。",
"RAG(检索增强生成)是一种增强语言模型的技术," +
"通过从知识库检索相关信息来减少幻觉并提供最新信息。"
};
// 使用 TextReader 读取和分块文本
TextReader reader = new TextReader(
512, // 每块最大 512 字符
SplitStrategy.PARAGRAPH,// 按段落分割
50 // 块之间 50 字符重叠
);
for (String text : texts) {
// 从字符串创建输入
ReaderInput input = ReaderInput.fromString(text);
// 读取并分块
List<Document> docs = reader.read(input).block();
// 添加到知识库(自动嵌入和存储)
if (docs != null && !docs.isEmpty()) {
knowledge.addDocuments(docs).block();
System.out.println("已添加文档: " + truncate(text, 50) + "...");
}
}
}
private static String truncate(String text, int maxLength) {
return text.length() > maxLength
? text.substring(0, maxLength) + "..."
: text;
}
}
10.3.3 嵌入模型选择
AgentScope-Java 支持多种嵌入模型:
| 模型 | 类名 | 适用场景 | 依赖 |
|---|---|---|---|
| DashScope | DashScopeTextEmbedding | 中文场景首选,通义千问系列 | agentscope-extensions-rag-simple |
| OpenAI | OpenAITextEmbedding | 英文场景,兼容 API | agentscope-extensions-rag-simple |
| Ollama | OllamaTextEmbedding | 本地部署,隐私优先 | agentscope-extensions-rag-simple |
// DashScope 嵌入模型(推荐中文场景)
EmbeddingModel dashscopeEmbedding = DashScopeTextEmbedding.builder()
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.modelName("text-embedding-v3")
.dimensions(1024)
.build();
// OpenAI 嵌入模型
EmbeddingModel openaiEmbedding = OpenAITextEmbedding.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-3-small")
.dimensions(1536)
.build();
// Ollama 本地嵌入模型
EmbeddingModel ollamaEmbedding = OllamaTextEmbedding.builder()
.baseUrl("http://localhost:11434")
.modelName("nomic-embed-text")
.dimensions(768)
.build();
10.3.4 向量存储选择
| 存储类型 | 类名 | 特点 | 适用场景 |
|---|---|---|---|
| InMemoryStore | InMemoryStore | 内存存储,重启丢失 | 开发测试、原型验证 |
| PgVectorStore | PgVectorStore | PostgreSQL + pgvector | 生产环境,已有 PG 基础设施 |
| QdrantStore | QdrantStore | 专业向量数据库 | 大规模生产环境 |
| MilvusStore | MilvusStore | 分布式向量数据库 | 超大规模、高并发 |
// 内存存储(开发测试)
VDBStoreBase inMemory = InMemoryStore.builder()
.dimensions(1024)
.build();
// PostgreSQL + pgvector(生产环境)
VDBStoreBase pgVector = PgVectorStore.builder()
.jdbcUrl("jdbc:postgresql://localhost:5432/vectordb")
.username("postgres")
.password("password")
.tableName("documents")
.dimensions(1024)
.build();
// Qdrant(专业向量数据库)
VDBStoreBase qdrant = QdrantStore.builder()
.host("localhost")
.port(6334)
.collectionName("my_collection")
.dimensions(1024)
.build();
10.4 文档读取与分块
10.4.1 Reader 体系
AgentScope-Java 提供了丰富的文档读取器:
┌────────────────────────────────────────────────────────┐
│ Reader 体系 │
├────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ ReaderInput │◀─── 输入源抽象 │
│ │ - fromString()│ - 字符串 │
│ │ - fromFile() │ - 文件路径 │
│ │ - fromBytes() │ - 字节数组 │
│ └──────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Reader 实现 │ │
│ ├──────────────────────────────────────────────────┤ │
│ │ TextReader │ 纯文本、Markdown、RST │ │
│ │ PDFReader │ PDF 文档 │ │
│ │ WordReader │ Word 文档 (.docx) │ │
│ │ TikaReader │ 通用格式(基于 Apache Tika) │ │
│ │ ImageReader │ 图片(用于多模态嵌入) │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────┘
10.4.2 分块策略
import io.agentscope.core.rag.reader.SplitStrategy;
// 分块策略枚举
public enum SplitStrategy {
PARAGRAPH, // 按段落分割(推荐用于文章)
SENTENCE, // 按句子分割(保持语义完整)
CHARACTER, // 按字符数分割(固定大小)
TOKEN // 按 Token 数分割(精确控制)
}
import io.agentscope.core.rag.reader.TextReader;
import io.agentscope.core.rag.reader.SplitStrategy;
// 创建文本读取器
TextReader reader = new TextReader(
512, // chunkSize: 每块目标大小
SplitStrategy.PARAGRAPH, // strategy: 分块策略
50 // overlapSize: 块间重叠字符数
);
// 读取文件
ReaderInput input = ReaderInput.fromFile("/path/to/document.txt");
List<Document> documents = reader.read(input).block();
// 读取字符串
ReaderInput stringInput = ReaderInput.fromString("长文本内容...");
List<Document> docs = reader.read(stringInput).block();
注意:
overlapSize(重叠大小)很重要!它确保跨块边界的信息不会丢失。通常设置为 chunk 大小的 10%-20%。
10.4.3 PDF 和 Word 文档
import io.agentscope.core.rag.reader.PDFReader;
import io.agentscope.core.rag.reader.WordReader;
// PDF 读取器
PDFReader pdfReader = new PDFReader(
1000, // chunkSize
SplitStrategy.PARAGRAPH,
100 // overlapSize
);
List<Document> pdfDocs = pdfReader
.read(ReaderInput.fromFile("/path/to/manual.pdf"))
.block();
// Word 读取器
WordReader wordReader = new WordReader(
800,
SplitStrategy.PARAGRAPH,
80
);
List<Document> wordDocs = wordReader
.read(ReaderInput.fromFile("/path/to/report.docx"))
.block();
10.5 云端知识库集成
对于生产环境,AgentScope-Java 支持多种云端知识库服务。
10.5.1 百炼知识库(BailianKnowledge)
阿里云百炼提供企业级的知识库服务,支持自动文档解析、向量化和检索:
import io.agentscope.core.rag.integration.bailian.BailianConfig;
import io.agentscope.core.rag.integration.bailian.BailianKnowledge;
// 配置百炼连接
BailianConfig config = BailianConfig.builder()
// 阿里云访问密钥
.accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// 工作空间 ID(在百炼控制台获取)
.workspaceId("llm-xxxxxxxx")
// 知识库索引 ID
.indexId("mymxbdxxxxxxxx")
// 可选:启用查询改写(多轮对话场景)
.enableRewrite(true)
.build();
// 创建知识库实例
BailianKnowledge knowledge = BailianKnowledge.builder()
.config(config)
.build();
// 检索文档
RetrieveConfig retrieveConfig = RetrieveConfig.builder()
.limit(5)
.scoreThreshold(0.5)
// 可选:传入对话历史用于查询改写
.conversationHistory(conversationHistory)
.build();
List<Document> results = knowledge
.retrieve("产品退货政策是什么?", retrieveConfig)
.block();
注意:百炼知识库目前不支持通过 API 上传文档,需要在控制台管理文档。
10.5.2 Dify 知识库
import io.agentscope.core.rag.integration.dify.DifyKnowledge;
import io.agentscope.core.rag.integration.dify.DifyRAGConfig;
// 配置 Dify
DifyRAGConfig config = DifyRAGConfig.builder()
.apiKey(System.getenv("DIFY_API_KEY"))
.baseUrl("https://api.dify.ai/v1") // 或自托管地址
.datasetId("your-dataset-id")
.build();
// 创建知识库实例
DifyKnowledge knowledge = DifyKnowledge.builder()
.config(config)
.build();
10.5.3 RAGFlow 知识库
import io.agentscope.core.rag.integration.ragflow.RAGFlowConfig;
import io.agentscope.core.rag.integration.ragflow.RAGFlowKnowledge;
// 配置 RAGFlow
RAGFlowConfig config = RAGFlowConfig.builder()
.apiKey(System.getenv("RAGFLOW_API_KEY"))
.baseUrl("http://localhost:8080")
.knowledgeBaseId("kb-xxxxx")
.build();
// 创建知识库
RAGFlowKnowledge knowledge = RAGFlowKnowledge.builder()
.config(config)
.build();
10.5.4 Haystack 知识库
import io.agentscope.core.rag.integration.haystack.HayStackConfig;
import io.agentscope.core.rag.integration.haystack.HayStackKnowledge;
// 配置 Haystack
HayStackConfig config = HayStackConfig.builder()
.pipelineUrl("http://localhost:8000/query")
.build();
// 创建知识库
HayStackKnowledge knowledge = HayStackKnowledge.builder()
.config(config)
.build();
10.6 RAG 模式详解
AgentScope-Java 提供两种 RAG 集成模式:
10.6.1 RAGMode 枚举
public enum RAGMode {
/**
* Generic 模式:自动检索
* 知识在每次推理前通过 Hook 自动检索并注入到提示词中
*/
GENERIC,
/**
* Agentic 模式:主动检索
* 智能体通过工具主动决定何时检索知识
*/
AGENTIC,
/**
* 禁用模式:不使用 RAG
*/
NONE
}
10.6.2 Generic 模式(自动检索)
Generic 模式通过 GenericRAGHook 实现,在每次推理前自动检索知识:
┌────────────────────────────────────────────────────────┐
│ Generic 模式流程 │
├────────────────────────────────────────────────────────┤
│ │
│ 用户提问 │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ GenericRAGHook │◀── 拦截 PreCallEvent │
│ │ 1. 提取查询 │ │
│ │ 2. 检索知识库 │ │
│ │ 3. 注入上下文 │ │
│ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ 增强的提示词 │ │
│ │ <retrieved_knowledge> │
│ │ - 文档1: xxx │
│ │ - 文档2: xxx │
│ │ </retrieved_knowledge> │
│ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ LLM │ │
│ │ 生成回答 │ │
│ └──────────────────┘ │
│ │
└────────────────────────────────────────────────────────┘
使用方式一:内置配置(推荐)
import io.agentscope.core.ReActAgent;
import io.agentscope.core.rag.RAGMode;
// 通过 ReActAgent 的内置配置
ReActAgent agent = ReActAgent.builder()
.name("RAGAssistant")
.sysPrompt("你是一个有知识库访问权限的助手,请基于知识库内容准确回答问题。")
.model(chatModel)
// 配置 RAG
.knowledge(knowledge) // 设置知识库
.ragMode(RAGMode.GENERIC) // 使用 Generic 模式
.retrieveConfig( // 检索配置
RetrieveConfig.builder()
.limit(3)
.scoreThreshold(0.3)
.build()
)
.build();
使用方式二:手动配置 Hook
import io.agentscope.core.rag.GenericRAGHook;
// 创建 RAG Hook
GenericRAGHook ragHook = new GenericRAGHook(
knowledge, // 知识库
RetrieveConfig.builder()
.limit(5)
.scoreThreshold(0.5)
.build()
);
// 将 Hook 添加到智能体
ReActAgent agent = ReActAgent.builder()
.name("Assistant")
.model(chatModel)
.hooks(List.of(ragHook)) // 手动添加 Hook
.build();
适用场景:
- 用户问题通常需要知识库支持
- 需要简单的"问答"模式
- 不需要智能体自主判断是否检索
10.6.3 Agentic 模式(主动检索)
Agentic 模式通过 KnowledgeRetrievalTools 实现,智能体自主决定何时检索:
┌────────────────────────────────────────────────────────┐
│ Agentic 模式流程 │
├────────────────────────────────────────────────────────┤
│ │
│ 用户提问 │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ ReActAgent │ │
│ │ 推理决策 │ │
│ └────────┬─────────┘ │
│ │ │
│ 需要知识? │
│ ┌────┴────┐ │
│ ▼ ▼ │
│ 是 否 │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │retrieve_ │ │ │
│ │knowledge │ │ │
│ │工具调用 │ │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ 检索结果 │ │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ │
│ │ 综合信息生成回答 │ │
│ └──────────────────┘ │
│ │
└────────────────────────────────────────────────────────┘
使用方式一:内置配置(推荐)
import io.agentscope.core.rag.RAGMode;
ReActAgent agent = ReActAgent.builder()
.name("RAGAgent")
.sysPrompt("""
你是一个智能助手,拥有知识库检索工具。
当你需要查找信息时,请使用 retrieve_knowledge 工具。
请在使用工具前解释你的思考过程。
""")
.model(chatModel)
.toolkit(toolkit)
// 配置 Agentic RAG
.knowledge(knowledge)
.ragMode(RAGMode.AGENTIC) // 使用 Agentic 模式
.build();
使用方式二:手动注册工具
import io.agentscope.core.rag.KnowledgeRetrievalTools;
import io.agentscope.core.tool.Toolkit;
// 创建检索工具
KnowledgeRetrievalTools retrievalTools = new KnowledgeRetrievalTools(knowledge);
// 注册到工具包
Toolkit toolkit = new Toolkit();
toolkit.registerObject(retrievalTools);
// 创建智能体
ReActAgent agent = ReActAgent.builder()
.name("Agent")
.model(chatModel)
.toolkit(toolkit)
.build();
retrieve_knowledge 工具定义:
@Tool(
name = "retrieve_knowledge",
description = "从知识库检索相关文档。当需要查找特定信息或用户询问知识库内容时使用。"
)
public String retrieveKnowledge(
@ToolParam(
name = "query",
description = "在知识库中搜索的查询文本"
)
String query,
@ToolParam(
name = "limit",
description = "最多返回的文档数量(默认: 5)",
required = false
)
Integer limit,
Agent agent // 自动注入,用于获取对话历史
) {
// 实现检索逻辑...
}
适用场景:
- 智能体需要多种工具,知识检索只是其一
- 需要智能体自主判断何时使用知识库
- 复杂的多步推理任务
10.6.4 模式对比与选择
| 特性 | Generic 模式 | Agentic 模式 |
|---|---|---|
| 检索时机 | 每次推理自动检索 | 智能体主动决定 |
| 实现方式 | Hook 拦截 | 工具调用 |
| Token 消耗 | 较高(每次都检索) | 较低(按需检索) |
| 控制灵活性 | 低 | 高 |
| 适用场景 | 纯知识问答 | 复杂多工具任务 |
| 配置复杂度 | 简单 | 中等 |
10.7 最佳实践
10.7.1 知识库构建建议
// 1. 选择合适的分块策略
// 对于技术文档,建议使用较大的 chunk 保持上下文完整
TextReader techReader = new TextReader(
1000, // 较大的块
SplitStrategy.PARAGRAPH,
150 // 较大的重叠
);
// 对于问答对,可以使用较小的块
TextReader qaReader = new TextReader(
300,
SplitStrategy.SENTENCE,
30
);
// 2. 添加元数据提高检索质量
DocumentMetadata metadata = new DocumentMetadata(content, docId, chunkId);
// 可以通过 payload 添加业务元数据
// metadata.setPayload(Map.of("category", "技术文档", "version", "2.0"));
// 3. 定期更新知识库
// 删除过时文档
vectorStore.delete(outdatedDocId).block();
// 添加新文档
knowledge.addDocuments(newDocuments).block();
10.7.2 检索配置优化
// 针对不同场景的配置示例
// 高精度检索(宁缺毋滥)
RetrieveConfig preciseConfig = RetrieveConfig.builder()
.limit(3)
.scoreThreshold(0.7) // 高阈值
.build();
// 高召回检索(宁多勿少)
RetrieveConfig recallConfig = RetrieveConfig.builder()
.limit(10)
.scoreThreshold(0.3) // 低阈值
.build();
// 平衡配置(推荐默认)
RetrieveConfig balancedConfig = RetrieveConfig.builder()
.limit(5)
.scoreThreshold(0.5)
.build();
10.7.3 生产环境建议
// 1. 使用持久化向量存储
VDBStoreBase productionStore = PgVectorStore.builder()
.jdbcUrl(System.getenv("DATABASE_URL"))
.username(System.getenv("DB_USER"))
.password(System.getenv("DB_PASSWORD"))
.tableName("knowledge_vectors")
.dimensions(1024)
.build();
// 2. 配置执行超时和重试
ExecutionConfig execConfig = ExecutionConfig.builder()
.timeout(Duration.ofSeconds(30))
.maxRetries(3)
.build();
EmbeddingModel embeddingModel = DashScopeTextEmbedding.builder()
.apiKey(apiKey)
.modelName("text-embedding-v3")
.dimensions(1024)
.executionConfig(execConfig)
.build();
// 3. 考虑使用云知识库服务
// - 百炼:企业级,自动管理
// - Dify:开源可控,功能丰富
// - RAGFlow:开源,深度解析
10.8 完整示例
以下是一个综合了 RAG 各组件的完整示例:
import io.agentscope.core.ReActAgent;
import io.agentscope.core.embedding.EmbeddingModel;
import io.agentscope.core.embedding.dashscope.DashScopeTextEmbedding;
import io.agentscope.core.memory.InMemoryMemory;
import io.agentscope.core.model.DashScopeChatModel;
import io.agentscope.core.rag.Knowledge;
import io.agentscope.core.rag.RAGMode;
import io.agentscope.core.rag.knowledge.SimpleKnowledge;
import io.agentscope.core.rag.model.Document;
import io.agentscope.core.rag.model.RetrieveConfig;
import io.agentscope.core.rag.reader.ReaderInput;
import io.agentscope.core.rag.reader.SplitStrategy;
import io.agentscope.core.rag.reader.TextReader;
import io.agentscope.core.rag.store.InMemoryStore;
import io.agentscope.core.tool.Toolkit;
import java.util.List;
import java.util.Scanner;
/**
* RAG 知识问答智能体示例
* 演示如何构建一个基于知识库的问答系统
*/
public class RAGChatbotExample {
public static void main(String[] args) {
String apiKey = System.getenv("DASHSCOPE_API_KEY");
int dimensions = 1024;
// ========================================
// 1. 构建知识库基础设施
// ========================================
System.out.println("初始化知识库...");
// 嵌入模型
EmbeddingModel embeddingModel = DashScopeTextEmbedding.builder()
.apiKey(apiKey)
.modelName("text-embedding-v3")
.dimensions(dimensions)
.build();
// 向量存储
InMemoryStore vectorStore = InMemoryStore.builder()
.dimensions(dimensions)
.build();
// 知识库
Knowledge knowledge = SimpleKnowledge.builder()
.embeddingModel(embeddingModel)
.embeddingStore(vectorStore)
.build();
// ========================================
// 2. 加载知识内容
// ========================================
System.out.println("加载知识文档...");
loadKnowledgeDocuments(knowledge);
// ========================================
// 3. 创建 RAG 智能体
// ========================================
System.out.println("创建智能体...\n");
DashScopeChatModel chatModel = DashScopeChatModel.builder()
.apiKey(apiKey)
.modelName("qwen-max")
.stream(true)
.build();
// 使用 Agentic 模式,让智能体自主决定何时检索
ReActAgent agent = ReActAgent.builder()
.name("KnowledgeAssistant")
.sysPrompt("""
你是一个智能知识助手,拥有访问公司知识库的能力。
工作原则:
1. 当用户问题涉及知识库内容时,使用 retrieve_knowledge 工具检索
2. 基于检索到的信息提供准确回答
3. 如果知识库没有相关信息,诚实告知用户
4. 始终说明信息来源
请用简洁专业的语言回答问题。
""")
.model(chatModel)
.toolkit(new Toolkit())
.memory(new InMemoryMemory())
// RAG 配置
.knowledge(knowledge)
.ragMode(RAGMode.AGENTIC)
.build();
// ========================================
// 4. 开始对话
// ========================================
System.out.println("=== 知识问答助手 ===");
System.out.println("试试问:");
System.out.println(" - AgentScope 是什么?");
System.out.println(" - 支持哪些向量数据库?");
System.out.println(" - RAG 有什么优势?");
System.out.println("输入 'exit' 退出\n");
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("你: ");
String input = scanner.nextLine().trim();
if ("exit".equalsIgnoreCase(input)) {
System.out.println("再见!");
break;
}
if (input.isEmpty()) continue;
// 调用智能体
System.out.print("助手: ");
agent.stream(input)
.doOnNext(msg -> System.out.print(msg.getTextContent()))
.blockLast();
System.out.println("\n");
}
scanner.close();
}
/**
* 加载示例知识文档
*/
private static void loadKnowledgeDocuments(Knowledge knowledge) {
String[] documents = {
// 产品介绍
"AgentScope-Java 是 AgentScope 框架的 Java 实现版本。" +
"它提供了构建多智能体应用的完整解决方案,支持 ReAct 算法、" +
"工具调用、记忆管理等核心功能。",
// 技术特性
"AgentScope-Java 基于 Project Reactor 实现响应式编程," +
"使用 Mono 和 Flux 处理异步操作,非常适合构建高并发的智能体应用。",
// 向量存储
"AgentScope 支持多种向量存储后端,包括:" +
"InMemoryStore(内存存储,适合开发测试)、" +
"PgVectorStore(PostgreSQL + pgvector,适合生产)、" +
"QdrantStore(专业向量数据库)、" +
"MilvusStore(分布式向量数据库)。",
// RAG 功能
"RAG(检索增强生成)是 AgentScope 的核心功能之一。" +
"它通过从知识库检索相关文档来增强 LLM 的回答质量," +
"有效减少幻觉并支持实时知识更新。" +
"AgentScope 支持 Generic 和 Agentic 两种 RAG 模式。"
};
TextReader reader = new TextReader(500, SplitStrategy.PARAGRAPH, 50);
for (String doc : documents) {
try {
List<Document> chunks = reader
.read(ReaderInput.fromString(doc))
.block();
if (chunks != null && !chunks.isEmpty()) {
knowledge.addDocuments(chunks).block();
}
} catch (Exception e) {
System.err.println("加载文档失败: " + e.getMessage());
}
}
System.out.println("已加载 " + documents.length + " 个知识文档");
}
}
10.9 本章小结
本章详细介绍了 AgentScope-Java 的 RAG(检索增强生成)功能:
- RAG 原理:通过检索外部知识增强 LLM 的回答能力
- 核心组件:
- Knowledge 接口:统一的知识库抽象
- Document 和 RetrieveConfig:数据和配置模型
- 多种 Reader:文档读取和分块
- 本地知识库:
SimpleKnowledge+ 嵌入模型 + 向量存储 - 云端知识库:百炼、Dify、RAGFlow、Haystack 集成
- 两种模式:
- Generic 模式:自动检索,简单易用 - Agentic 模式:主动检索,灵活可控
RAG 是让智能体"知其所以然"的关键技术,掌握它能够构建真正有用的企业级 AI 应用。
练习
- 使用
SimpleKnowledge构建一个本地知识库,添加一些文档并测试检索效果 - 尝试不同的分块策略(
PARAGRAPH、SENTENCE、CHARACTER),比较检索质量 - 将 RAG 模式从
GENERIC切换到AGENTIC,观察智能体行为的变化 - (进阶)集成 PgVectorStore,实现持久化的知识库存储
上一章:第09章-MCP协议集成 | 下一章:第11章-Pipeline管道