四.干货干货!!!SpringAI入门到实战-RAG知识库检索

认识RAG原理

RAG(Retrieval-Augmented Generation)(本地知识库)是一种结合信息检索和大语言模型(LLM)的技术,目的是在解决传统生成模型的局限性。

  • 传统大语言模型(如 GPT-4、Llama 3)依赖训练时的数据,无法动态获取最新信息,有了RAG在生成答案前,先从外部知识库(如数据库、文档、网页)检索最新信息,确保答案的时效性
  • LLM 可能会生成看似合理但实际错误的答案(即“幻觉”),基于检索到的可信数据生成答案可以减少编造信息的风险
  • 通用 LLM 可能缺乏特定行业(如医疗、法律)或企业内部数据(如公司文档)的知识。RAG 允许接入自定义知识库(如企业文档、科研论文),提供更精准的回答。

RAG 的核心价值在于让 LLM 的生成能力与外部知识库的动态检索相结合,既保留了 LLM 的语言理解能力,又弥补了其在时效性、准确性和专业性上的不足。对于需要实时数据、私有知识或可解释性的应用,RAG 是目前最有效的解决方案之一

RAG的工作原理

RAG 流程分为两个不同的阶段:索引(创建RAG)和检索(搜索RAG),LangChain4j 为这两个阶段提供了工具。索引阶段指的是把提前准备好的数据给LLM建立RAG知识库,这些数据可以是公司的内部数据,某在线文档,或者用户上传的文档等。以下是索引阶段的简化图

在这里插入图片描述

  • Document : 我们准备用来建立知识库的数据
  • TextSplitter : 文本切割器,用于把一段大文本按照某种规则切成多个小段,以方便创建向量,因为每个模型处理的文本都是有长度限制的。
  • Segments : 代表文本切割后的每个分段
  • EmbeddingModel : 向量模型,创建RAG索引的过程需要通过 向量模型 为文本创建向量并存储到向量数据库中。向量是数学中的一个定义,这里的意思是文本向量化:将单词、句子或文档转换为数值向量(如 [0.2, -0.7, 0.5, …])
  • EmbeddingStore :向量存储,需要准备向量数据库用于存储文本转换后的向量

检索阶段通常发生在线,当用户提交需要使用索引文档来回答的问题时,LLM根据用户的提问去RAG中进行搜索。以下是检索阶段的简化图
在这里插入图片描述
用户的提问会被EmbeddingModel向量模型转化为向量去向量数据库中进行查找,检索到的相关数据会通过LanguageModel对话模型处理后响应给用户。

Docker安装Pgvector

可以支持向量存储的数据库很多,比如:Redis,ES都可以,我这里选择使用PGVector,参考官网文档:https://docs.spring.io/spring-ai/reference/api/vectordbs/pgvector.html#page-title

1. 安装DockerDesk

因为没有服务器,我就在windows电脑上通过DockerDesk来安装了,首先需要下载docker-desktop:https://www.docker.com/products/docker-desktop/,根据引导安装好DockerDesktop,可以参考《Ollama+WebUI+DeepSeek部署自己的本地大模型》docker-desktop安装部分。

2. 安装Pgvector

通过终端执行docker命令创建pgvecor容器

docker run --name pgvector -v c:/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5433:5432 -d ankane/pgvector
  • POSTGRES_PASSWORD : 密码
  • -p 5433:5432 :端口是5433

在这里插入图片描述
使用navcat新建连接选择:postgressql ,数据库和用户名默认写postgres
在这里插入图片描述
选中数据 - 编辑数据库 - 扩展 - 找到vector - 移动到后边代表已安装该插件
在这里插入图片描述
PS:也可以通过CREATE EXTENSION vector; 来创建插件

执行下面SQL测试向量数据库

-- 创建测试向量表
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
-- 插入向量数据
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;

效果如下
在这里插入图片描述

Windows安装Pgvector

1.安装PgSql

首先需要先安装PGSql ,下载路径 : https://www.enterprisedb.com/downloads/postgres-postgresql-downloads , 安装参考文档:https://www.enterprisedb.com/docs/supported-open-source/postgresql/installing/windows/,

2.开启Pgector

开启Pgector 需要有C++环境,所以先在电脑上安装 Visual Studio 下载路径:https://learn.microsoft.com/en-us/visualstudio/releases/2022/system-requirements ,下载执行安装,选择使用c++桌面开发
在这里插入图片描述

确保安装了Visual Studio中的C++支持,并运行:

call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"

注意:具体路径将根据 Visual Studio 版本而有所不同,然后使用nmake来构建:

set "PGROOT=C:\Program Files\PostgreSQL\16"
cd %TEMP%
git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git
cd pgvector
nmake /F Makefile.win
nmake /F Makefile.win install

其他注意事项

  • 缺少标头 :如果编译失败Cannot open include file: ‘postgres.h’: No such file or directory,请确保PGROOT正确。

  • 不匹配的架构 :如果编译失败error C2196: case value ‘4’ already used,请确保vcvars64.bat已调用。然后运行nmake /F Makefile.win clean并重新运行安装说明。

  • 缺少符号 :如果unresolved external symbol float_to_shortest_decimal_bufn与 Postgres 17.0-17.2 链接失败,请升级到 Postgres 17.3+。

  • 权限 :如果安装失败Access is denied,请以管理员身份重新运行安装说明。

RAG实战

1.导入依赖

  • spring-ai-starter-vector-store-pgvector 是用于支撑pgvector向量存储的基础依赖
  • spring-ai-advisors-vector-store : 是支撑向量数据库检索的基础依赖
  <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-advisors-vector-store</artifactId>
  </dependency>

2.修改yml配置

在之前的yml基础上做一些修改

  • 数据源我修改为了pgsql数据库
  • 增加spring.ai.vectorstore 向量存储相关配置
  • 增加ollama本地向量模型配置

spring:
  datasource:
    #    datasourcedriver-class-name: com.mysql.cj.jdbc.Driver
    #    username: root
    #    password: 123456
    #    url: jdbc:mysql://127.0.0.1/ai-girl
    url: jdbc:postgresql://localhost:5433/postgres
    username: postgres
    password: 123456
  ai:
    vectorstore: #向量存储相关
      pgvector:
        initialize-schema: true #自动创建表
        index-type: HNSW #索引的算法
        distance-type: COSINE_DISTANCE #使用 余弦距离 作为度量标准
        dimensions: 384 #向量模型 all-minilm:latest 的维度
    openai:
      api-key: ${API_KEY}
      base-url: https://dashscope.aliyuncs.com/compatible-mode
      chat:
        options:
          model: qwen-max-latest
          temperature: 1
    chat:
      memory:
        repository:
          jdbc:
            initialize-schema: never #不要初始化表,不然会报错
    model:
      embedding: ollama #启用ollama
    ollama:
      embedding: #ollama本地向量模型配置
        options:
          model: all-minilm:latest #向量模型
          truncate: true
      base-url: http://localhost:11434 

server:
  port: 8888

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    org.springframework.ai: debug
    org.ai.agent: debug

在SpringAI中当我们导入了 vector 相关依赖,并在yml做了相关配置后,SpringAI会自动帮我们装配好VectorStore Bean,直接使用即可。且启动查询SpringAI会自动创建 vector_store 表

注意:我这里使用的是Ollama本地向量模型,如果要使用远程的可以参考Spring官网的配置:https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embeddings.html

3.定义一个RAG Client

定义一个专门用于RAG检索的client,当然也可以使用之前的client

    @Bean
    public ChatClient ragClient(OpenAiChatModel model){
        return ChatClient.builder(model)
                //日志打印的增强器
                .defaultAdvisors(new SimpleLoggerAdvisor()).build();
    }

4.基于TXT创建知识库

现在我们需要把PDF,或者TXT文档作为知识库源文件Load到知识库,这里以txt文本为例

@RequestMapping(value = "/ai/rag/load")
 public String ragLoad(@RequestParam("file") MultipartFile file){
     //把上传的txt文件转化为Document
     DocumentReader txtReader = new TextReader(file.getResource());
     List<Document> documents = txtReader.read();

	 //文档切块
     //chunkSize :表示每个文本块的目标大小,通常以token数量为单位
     //minChunkSizeChars :每个块必须包含的最小字符数,用于确保块不会太小
     //minChunkLengthToEmbed:只有达到这个长度的块才会被处理/嵌入
     //maxNumChunks:从单个文档生成的最大块数限制 防止单个文档产生过多的块
     //keepSeparator (保留分隔符)
     DocumentTransformer textSplitter = new TokenTextSplitter(200,20,5,10000,true);
     List<Document> transformDocuments = textSplitter.transform(documents);

     //Load
     vectorStore.write(transformDocuments);

     return "success";
 }

定义一个RAG检索的Controller

private final VectorStore vectorStore;
private final ChatClient ragClient;

@RequestMapping(value = "/ai/rag/search")
public Flux<String>  ragSearch(@RequestParam String prompt){

    //配置向量检索增强器
    var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
            //设置答案的准确度  和  前N条数据。准确率越高答案越准确,同时也有可能无法找到内容
            .searchRequest(SearchRequest.builder().similarityThreshold(0.8d).topK(6).build())
            .build();

    return ragClient
            .prompt("请基于知识库检索到的内容来回答").user(prompt)
            .advisors(qaAdvisor)
            .stream().content();
}
  • 首先需要通过prompt指定系统提示词,明确的告诉大模型需要去知识库来检索内容
  • 通过QuestionAnswerAdvisor去构建RAG检索增强,可以指定准确率和前N条数据作为参考

5.RAG测试

首先需要准备一个TXT文档,通过上传接口上传RAG知识库文档,上传成功后 观察 vector_store 表中的数据。然后调用RAG检索接口,观察是不是从RAG知识库中检索到的档案
在这里插入图片描述

6.基于PDF创建RAG

如果要使用PDF作为知识库上传,那么需要导入如下依赖

PDF加载到知识库代码如下

 // 1.创建PDF的读取器
  PagePdfDocumentReader reader = new PagePdfDocumentReader(
          file.getResource(), // 文件源
          PdfDocumentReaderConfig.builder()
          .withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
          .withPagesPerDocument(1) // 每1页PDF作为一个Document
          .build()
  );
...省略...

总结

本片文章到这里就结束了,我们学习了什么是RAG知识库以及它的原理,然后基于Ollama本地模型all-minilm:latest完成了RAG的创建和检索,这个过程并不复杂,麻烦的是SpringAI 1.0.0和之前的版本的API差异很大,无法完全复用,所以需要多参考官方文档。本文知识使用其中一种方式来实现RAG知识库,你可以自己尝试更多的向量模型,或者向量数据库。如果文章对你有帮助不要吝啬你的三连,你的鼓励是我最大的动力哦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨家巨子@俏如来

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值