15-11 AgentScope Java特性:RAG
✅AgentScope Java特性:RAG
(虽然在ASJ的2.0的relesse note中提到:RAG (Knowledge / KnowledgeRetrievalTools / RAGMode) and long-term memory modules deprecated — being rewritten on the v2 architecture; don’t depend on them in new code`,但是截止目前,2.0还没正式发布,也没给出替代方案,我们先讲1.0的方案和用法,后续新版本更新了我能再单独讲方案和用法)
三个核心抽象
ASJ中针对RAG做了抽象,其中比较核心的就是Knowledge / Document / RetrieveConfig这三个。整个 RAG 子系统就由这三个类(接口)驱动,其它都是装饰。
Knowledge 接口只有两个方法:
1 | public interface Knowledge { |
整个 RAG 子系统就建立在这个接口上,所有上游(Hook、Tool、Bailian/Dify 等扩展)都只依赖它。这意味着:
写自己的接入:你只要实现 Knowledge 就能塞到 ReActAgent 里跑。
想换底座:把 SimpleKnowledge 换成 BailianKnowledge、DifyKnowledge 即可,无需动 Agent 代码。
也就是说,ASJ其实内置了很多RAG系统的支持,包括百炼、Dify、RAGFlow等。
Document 用来表示在RAG系统的每一个chunk,他的定义如下:
1 | public class Document { |
DocumentMetadata 内部装的是一个 ContentBlock——agentscope 统一的多模态块类型(TextBlock / ImageBlock 等)。这个设计让”文本块”和”图片块”共用一条 RAG 管线。
RetrieveConfig 用来配置检索参数:
1 | RetrieveConfig.builder() .limit(5) // top-k,默认 5 .scoreThreshold(0.5) // 相似度阈值,默认 0.5 .vectorName("doc_v1") // 向量空间名(可选,用于隔离不同 corpus) .conversationHistory(history) // 多轮上下文(百炼会用它做 query rewrite) .build(); |
两种 RAG 模式
这是 agentscope 给业务方提供的”插法选择”,对应 RAGMode 枚举:
1 | public enum RAGMode { |
| Column 1 | Column 2 | Column 3 | Column 4 |
|---|---|---|---|
| 模式 | 触发方 | 注入位置 | 适合场景 |
| GENERIC | 框架(每次推理前自动) | inputMessages 末尾追加 user 消息 |
FAQ / 知识助手,每条用户提问都需要查 |
| AGENTIC | LLM 自己决策 | 作为 retrieve_knowledge 工具结果回灌 |
多技能 Agent,RAG 是诸多工具之一 |
| NONE | — | — | 关掉 RAG |
Generic:
在 Generic 模式下,知识会自动检索并注入到用户的消息中,他的工作原理,和我们传统的RAG系统的流程是一样的:
用户发送查询
知识库自动检索相关文档
检索到的文档被添加到用户消息之前
Agent 处理增强后的消息并响应
只不过这个检索和追加的动作内部实现了,通过GenericRAGHook作为核心实现:
1 | private Mono<PreCallEvent> handlePreCall(PreCallEvent event) { |
Agentic
Agentic 其实是Agentic RAG的实现,也就是说让Agent来决策什么时候该调用RAG做检索,相当于把RAG当做一个工具。工作原理是:
用户发送查询
Agent 推理并决定是否检索知识
如果需要,Agent 调用
retrieve_knowledge(query="...")检索到的文档作为工具结果返回
Agent 使用检索到的信息再次推理
因为要作为一个工具,可想而知需要声明一个tool,他的实现是靠KnowledgeRetrievalTools实现的。
1 |
|
Agent agent 参数不是 @ToolParam,而是框架自动注入当前 Agent。这样工具内部能拿到完整 agent 状态,把会话历史一并送进 RetrieveConfig。
上面的Hook和工具,是在ReActAgent构造的时候,自动配置进去的:io.agentscope.core.ReActAgent.Builder#configureRAG
1 | private void configureRAG(Toolkit agentToolkit) { |
文档处理支持
Reader
ASJ中内置了很多Reader用来读取不同的类型的文档
| Field | Value |
|---|---|
| Reader | 作用 |
| TextReader | 直接吃 String 或文件 |
| PDFReader | PDFBox 解析,按页拼文本 |
| WordReader | POI 解析 .docx |
| TikaReader | Apache Tika 万能解析(PPT/HTML/Markdown 等) |
| ImageReader | 图片 → ImageBlock,配合多模态 embedding |
| ExternalApiReader | 调外部 OCR / parsing API |
这里的实现还是比较简单了,比如PDF还是用PDFBox,Word还是用POI的。效果一般。
Chunker
ASJ中内置了TextChunker用来做文档分段。支持以下几种分段策略:
| Field | Value |
|---|---|
| 策略 | 实现 |
| CHARACTER | 按字符数硬切,可能断词 |
| PARAGRAPH | 按\n\s*\n 切段;段落之间累加直到超过 chunkSize;单段超长再降级到 character 切 |
| TOKEN | 用1 token ≈ 4 chars 的简单启发式换算成 character 切 |
| SEMANTIC | 当前未实现,回退到 PARAGRAPH |
EmbeddingModel
内置了EmbeddingModel接口以及默认实现,来做embedding。
1 | public interface EmbeddingModel { |
embed()方法支持传入ContentBlock,他也有多种实现,比如文本是 TextBlock,图片走多模态实现传 ImageBlock,两者复用同一接口。
有多重默认实现:DashScopeTextEmbedding / DashScopeMultiModalEmbedding / OpenAITextEmbedding / OllamaTextEmbedding。(需要配置apikey等)
VDBStoreBase
向量数据库也提供了抽象:
1 | public interface VDBStoreBase { |
有以下5个默认实现:
| Field | Value |
|---|---|
| Store | 适用 |
| InMemoryStore | 开发/小数据集; ConcurrentHashMap<String,Document> + 余弦相似度 |
| PgVectorStore | PostgreSQL + pgvector 扩展 |
| QdrantStore | Qdrant |
| MilvusStore | Milvus |
| ElasticsearchStore | ES(dense_vector) |
Demo
GENERIC + SimpleKnowledge
这种比较适合在类似我们dodo-agent中用户上传文档做问答的场景。
1 | // 1. 起 Embedding + 内存向量库EmbeddingModel embed = DashScopeTextEmbedding.builder() .apiKey(apiKey).modelName("text-embedding-v3").dimensions(1024).build();InMemoryStore store = InMemoryStore.builder().dimensions(1024).build();SimpleKnowledge knowledge = SimpleKnowledge.builder() .embeddingModel(embed).embeddingStore(store).build(); |
使用第三方知识库
适合于那种你公司的知识库已经在百炼/Dify/RAGFlow 上维护,agent 只负责调用。
1 | BailianKnowledge knowledge = BailianKnowledge.builder() .config(bailianConfig) .indexId("your-knowledge-index-id") .build(); |
多知识库检索
如果一次回答需要从多个知识库检索,比如从FAQ、产品文档、技术手册同时检索:
1 | ReActAgent agent = ReActAgent.builder() .knowledge(productDocsKB) .knowledge(faqKB) .knowledge(internalWikiKB) // 框架自动 buildAggregatedKnowledge .ragMode(RAGMode.GENERIC) .build(); |
这种情况,会触发ReActAgent.Builder中的buildAggregatedKnowledge做多路检索和合并、重排:
1 | private Knowledge buildAggregatedKnowledge() { |
