SpringAI + RagFlow的火花

嗨嗨嗨,时隔多日,喵喵又来更新了,为什么过了这么久才来补上SpringAI的Rag捏,因为项目更改方向了,用DIFY来构建智能体,操作确实简单,但是拓展上还是有一些局限的,所以到现在才来更新,这次更新直接上硬核的,两个不同的框架如何兼容

首先,RagFlow是什么,RAGFlow 是一款基于深度文档理解构建的开源 RAG(Retrieval-Augmented Generation)引擎。RAGFlow 可以为各种规模的企业及个人提供一套精简的 RAG 工作流程,结合大语言模型(LLM)针对用户各类不同的复杂格式数据提供可靠的问 答以及有理有据的引用。 本文用到的仅限于使用其中的知识库功能

开始

SpringAI添加Rag功能

根据SpringAI的官方文档,我是用ES作为Rag驱动的向量数据库

添加依赖

<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-elasticsearch-store-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.13.3</version>
</dependency>

配置ES

spring:
elasticsearch:
uris: <elasticsearch instance URIs>
username: <elasticsearch username>
password: <elasticsearch password>
ai:
vectorstore:
elasticsearch:
initialize-schema: true
index-name: custom-index
dimensions: 1536
similarity: cosine
batching-strategy: TOKEN_COUNT # Optional: Controls how documents are batched for embedding

更多参数以及参数说明详见上面的官方文档

将数据语料进行向量化

直接上代码

// 注入向量数据库,我们只配了ES,所以注入进来的就是ES的向量数据库
@Autowired
private VectorStore vectorStore;

public void initializeVectorStore() {
// 构建描述文档
String content = """
代码与月光在此停泊,而思想的潮汐仍向未知奔涌。所有深夜的变量、断点与重构,终将风化成长卷边角的注脚。
此刻合页,如同拾起一片落叶的纹路——那些 曾令人窒息的庞杂逻辑,原不过是万物递归的寻常一瞬。
长夏倾尽,算法归于星群,而答案永远流浪在下一个春天。
""";

// 将描述文档添加到向量存储
vectorStore.add(List.of(new Document(content)));
}

将向量化的语料查询出来

List<Document> vectorStoreResult =
vectorStore.similaritySearch(SearchRequest.builder().topK(5).similarityThreshold(0.0).query(userInput).build());
String documents = vectorStoreResult.stream()
.map(Document::getFormattedContent).collect(Collectors.joining());
log.info("知识库查询结果:{}", documents);
chatClient.prompt("你是智能助手,请根据提供的知识库回答问题,以下是知识库"+documents)
.user(userInput) // 用户提示词
.stream().content();

恭喜你,最简单的Rag被你实现了,那么我们开始正题

修改连接配置

我们假设你已经安装并且部署好了RagFlow
修改配置文件为RagFlow提供的ES地址

spring:
elasticsearch:
uris: <elasticsearch instance URIs>
username: elastic
password: infini_rag_flow(可以在RagFlow的Docker文件中找到)
ai:
vectorstore:
elasticsearch:
initialize-schema: true
index-name: ragflow_xxxxx(可以连接上RagFlow的ES来查看)
dimensions: 1536
similarity: cosine
batching-strategy: TOKEN_COUNT # Optional: Controls how documents are batched for embedding
filedName: q_1024_vec(重点!!!这个是我自己定义的)

image-20250410105201942

修改spring-ai-elasticsearch的源码

目录结构
image-20250410105545386
我们要做的就是复写这两个类

  1. 包名 org.springframework.ai.vectorstore.elasticsearch
    image-20250410110028808
    image-20250410110047130
  2. 包名org.springframework.ai.document
    image-20250410110320082

那为什么要换成content_with_weight和q_1024_vec呢

打开ES我们就能看到
image-20250410112240120
这样我们就能使用RagFlow喂语料,使用SpringAI查询检索了

进阶改法

直接干源码,不做过多讨论 LINK
image-20250410113211921

总结

这种改法只适合玩玩,我刚刚看到了有人在SpringAI提交了PR,我相信社区肯定会将这些功能全都加入进去的。