AI超级智能开发系列从入门到上天第九篇:SpringAI搭建本地知识库

一:SpringAI搭建本地知识库

Spring AI 与 RAG

Spring AI 框架为 RAG 提供全流程支持,可参考 Spring AI 及 Spring AI Alibaba 官方文档。

标准 RAG 开发步骤

  1. 文档收集和切割
  2. 向量转换和存储
  3. 切片过滤和检索
  4. 查询增强和关联

简化后的 RAG 开发步骤

  1. 文档准备
  2. 文档读取
  3. 向量转换和存储
  4. 查询增强

二:文档准备

文档准备要求

  • 用于 AI 知识库的知识文档,推荐Markdown 格式,尽量结构化。

基于大模型生成文档

三:文档读取

1:RAG 知识库处理流程

对知识库文档进行处理并保存到向量数据库的过程俗称 ETL(抽取、转换、加载),Spring AI 提供了对 ETL 的支持。

2:ETL 三大核心组件

  1. DocumentReader:读取文档,得到文档列表
  2. DocumentTransformer:转换文档,得到处理后的文档列表
  3. DocumentWriter:将文档列表保存到存储中(可以是向量数据库,也可以是其他存储)

刚开始学习 RAG,无需关注过多 ETL 细节,也无需对文档做特殊处理。我们将先用 Spring AI 读取准备好的 Markdown 文档,为写入向量数据库做准备。

3:引入依赖

复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-markdown-document-reader</artifactId>
    <version>1.0.0-M6</version>
</dependency>

4:编写代码

复制代码
/**
 * 恋爱大师应用文档加载器
 */
@Component
@Slf4j
public class LoveAppDocumentLoader {

    private final ResourcePatternResolver resourcePatternResolver;

    public LoveAppDocumentLoader(ResourcePatternResolver resourcePatternResolver) {
        this.resourcePatternResolver = resourcePatternResolver;
    }

    /**
     * 加载多篇 Markdown 文档
     * @return
     */
    public List<Document> loadMarkdowns() {
        List<Document> allDocuments = new ArrayList<>();
        try {
            Resource[] resources = resourcePatternResolver.getResources("classpath:document/*.md");
            for (Resource resource : resources) {
                String filename = resource.getFilename();
                // 提取文档倒数第 3 和第 2 个字作为标签
                String status = filename.substring(filename.length() - 6, filename.length() - 4);
                MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
                        .withHorizontalRuleCreateDocument(true)
                        .withIncludeCodeBlock(false)
                        .withIncludeBlockquote(false)
                        .withAdditionalMetadata("filename", filename)
                        .withAdditionalMetadata("status", status)
                        .build();
                MarkdownDocumentReader markdownDocumentReader = new MarkdownDocumentReader(resource, config);
                allDocuments.addAll(markdownDocumentReader.get());
            }
        } catch (IOException e) {
           log.error("Markdown 文档加载失败", e);
        }
        return allDocuments;
    }
}

5:最终效果

这样的话,一共三篇文章,每一篇文章都有五块,一共拆分出来了15块内容。我们原始的文档要尽量的结构化。这样才方便与进行拆分

四:向量转换和存储

1:向量存储选型

为实现方便,先使用Spring AI 内置的、基于内存读写的向量数据库 SimpleVectorStore 来保存文档 。SimpleVectorStore 实现了 VectorStore 接口,而 VectorStore 接口集成了 DocumentWriter,因此具备文档写入能力。

如果我们有使用其他的向量数据库,需要实现VectorStore接口。DocumentWriter是真正有能力写出数据到向量数据库的。

2:向量化源码

简单了解源码,在将文档写入到数据库前,会先调用 Embedding 大模型将文档转换为向量,实际保存到数据库中的是向量类型的数据。

这个SimpleVectorStor是基于内存进行读写的。

3:将文档读取、转换、存储整合在一起

将文档读取、转换、存储整合到一起。

复制代码
@Configuration
public class LoveAppVectorStoreConfig {

    @Resource
    private LoveAppDocumentLoader loveAppDocumentLoader;

    @Resource
    private MyTokenTextSplitter myTokenTextSplitter;

    @Resource
    private MyKeywordEnricher myKeywordEnricher;

    @Bean
    VectorStore loveAppVectorStore(EmbeddingModel dashscopeEmbeddingModel) {
        SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(dashscopeEmbeddingModel).build();
        // 加载文档
        List<Document> documentList = loveAppDocumentLoader.loadMarkdowns();
        // 自主切分文档
//        List<Document> splitDocuments = myTokenTextSplitter.splitCustomized(documentList);
        // 自动补充关键词元信息
        List<Document> enrichedDocuments = myKeywordEnricher.enrichDocuments(documentList);
        // 进行Embadding和Store到Java对象当中。
        simpleVectorStore.add(enrichedDocuments);
        return simpleVectorStore;
    }
}

五:查询增强

Spring AI 通过 Advisor 特性提供了开箱即用的 RAG 功能。主要是 QuestionAnswerAdvisor 问答拦截器和 RetrievalAugmentationAdvisor 检索增强拦截器,前者更简单易用、后者更灵活强大。

查询增强的原理其实很简单。向量数据库存储着 AI 模型本身不知道的数据,当用户问题发送给 AI 模型时,QuestionAnswerAdvisor 会查询向量数据库,获取与用户问题相关的文档。然后从向量数据库返回的响应会被附加到用户文本中,为 AI 模型提供上下文,帮助其生成回答。

查看 QuestionAnswerAdvisor 源码,可以看到让 AI 基于知识库进行问答的 Prompt:

1:引入依赖

复制代码
<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>

2:编写代码

复制代码
 public String doChatWithRag(String message, String chatId) {
        // 查询重写
        String rewrittenMessage = queryRewriter.doQueryRewrite(message);
        ChatResponse chatResponse = chatClient
                .prompt()
                // 使用改写后的查询
                .user(rewrittenMessage)
                .advisors(spec -> spec.param(ChatMemory.CONVERSATION_ID, chatId))
                // 开启日志,便于观察效果
                .advisors(new MyLoggerAdvisor())
                // 应用 RAG 知识库问答
                .advisors(new QuestionAnswerAdvisor(loveAppVectorStore))
                // 应用 RAG 检索增强服务(基于云知识库服务)
//                .advisors(loveAppRagCloudAdvisor)
                // 应用 RAG 检索增强服务(基于 PgVector 向量存储)
//                .advisors(new QuestionAnswerAdvisor(pgVectorVectorStore))
                // 应用自定义的 RAG 检索增强服务(文档查询器 + 上下文增强器)
//                .advisors(
//                        LoveAppRagCustomAdvisorFactory.createLoveAppRagCustomAdvisor(
//                                loveAppVectorStore, "单身"
//                        )
//                )
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }

    @Test
    void doChatWithRag() {
        String chatId = UUID.randomUUID().toString();
        String message = "我已经结婚了,但是婚后关系不太亲密,怎么办?";
        String answer = loveApp1.doChatWithRag(message, chatId);
        Assertions.assertNotNull(answer);
    }

3:查看结果

从结果上看,在QuestionAnswerAdvisor这个拦截器当中已经将检索到的知识拼接到了userMessage当中,SpringAI提供的这个类,提供了完整的检索、拼接能力。

六:总结

实际开发过程中,这种方式极少使用,额外占用很多的JVM内存,接下来,我们要采用云知识库进行存储。

相关推荐
宁小法2 小时前
MySQL - 读写延迟, 并发导致的问题-分析与解决
数据库·mysql·主从延迟·并发请求
hutengyi2 小时前
Redis基础——1、Linux下安装Redis(超详细)
linux·数据库·redis
一直都在5722 小时前
AI 视觉图像形状识别全流程解析
人工智能·计算机视觉·目标跟踪
mldlds2 小时前
postgresql链接详解
数据库·postgresql
椎4952 小时前
Redis day03-应用-实战-黑马点评-商户查询缓存
数据库·redis·缓存
Hyxino2 小时前
科技向善,守护心灵|海曦技AI心理筛查设备落地西安高新三初,以科技护航青少年心理健康
大数据·人工智能
AI视觉网奇2 小时前
docker v2安装
人工智能·python
空间宇航2 小时前
智能制造软件厂商市场与销售价值转型总体解决方案:从成本中心到增长引擎
大数据·人工智能·项目管理·软件构建·智能制造
踩着两条虫2 小时前
VTJ.PRO 在线应用开发平台入门与项目初始化
前端·人工智能·ai编程