大数跨境
0
0

太炸裂了!Spring AI:三行代码,RAG技术直接拿捏

太炸裂了!Spring AI:三行代码,RAG技术直接拿捏 Spring全家桶实战案例
2025-04-10
1
导读:惊掉下巴!Spring AI:三行代码让RAG技术轻松落地!
Spring Boot 3实战案例锦集PDF电子书已更新至100篇!
图片

🎉🎉《Spring Boot实战案例合集》目前已更新114个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

现在就订阅合集




环境:SpringBoot3.4.2



1. 简介

1. 什么是RAG?

检索增强生成(Retrieval-Augmented Generation,简称RAG)是一种结合大型语言模型(LLM)和外部知识库的技术,旨在提高生成文本的准确性和相关性。

如下是维基百科的对RAG的解释:

RAG是赋予生成式人工智能模型信息检索能力的技术。检索增强生成优化大型语言模型(LLM) 的交互方式,让模型根据指定的一组文件内容回答用户的查询,并使用这些信息增强模型从自身庞大的静态训练数据中提取的信息。

简单说,RAG通过引入外部知识源来增强LLM的输出能力。它允许模型在生成答案之前,从特定的知识库中检索相关信息,从而提供更准确和上下文相关的回答。

如下图是整个RAG技术的应用过程:

上图总结:

  • (线下)将一个完整的文档查分了多个较小的文档片段存入向量数据库

  • (运行时)当回答用户的问题时,先根据问题(提示词)从向量数据库中查找相似的内容,最后会将问题和所有“相似”的文档片段放入发送给AI模型的提示信息中

     

1.2 什么是向量数据库?

在向量数据库中,查询方式与传统关系型数据库不同。它不进行精确匹配,而是执行相似性搜索。当给定一个向量作为查询条件时,向量数据库会返回与该查询向量“相似”的向量。

通俗点讲:如果你有一堆照片,你想快速找到 "某一个人",或者你有一篇文章,想找出“和这句话意思最接近的话”。这时候,用传统数据库(比如按文件名、标签搜索)根本搞不定,因为电脑看不懂图片和文字里的 "意思"。向量数据库就是帮电脑 "看懂" 内容——它把图片、文字、视频都变成一串数字(向量),然后通过“计算数字之间的距离”来判断内容有多像。比如,两张猫图的数字串离得近,一张猫图和一张狗图的数字串离得远,这样就能快速找到相似的东西。 

向量长啥样?

文本内容:我爱Spring全家桶实战案例源码

通过Embedding模型生成对应的向量数字:[0.24, -0.56, 0.89]

最终将文本内容转换为一种数字,而这种数字是能被计算机"认识"的,最终会通过该向量数据来计算相似性。

向量数据库有很多,本篇文章将通过Milvus实现数据向量化存储。

1.3 Milvus简介

关于Milvus的详细介绍,不在本篇文章范围内(我们只需要知道如何使用即可);如需要详细了解学习请查看下面链接:

https://milvus.io/docs/zh

接下来,我们将详细的介绍如何通过Spring AI + ARG实现本地知识库。

2. 实战案例

2.1 环境准备

我们需要先准备如下环境:

  • 向量数据库Milvus的安装

# 下载脚本$ curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh -o standalone_embed.sh# 启动容器$ bash standalone_embed.sh start
  • Embedding模型bge-m3安装

    我们还需要一个能够将文本转换为向量数据的大模型;我们这里使用bge-m3模型,该模型能够生成1024纬的向量。

$ ollama pull bge-m3:latest

环境准备好后,我们就可以开始本地知识库的实现了。

2.2 项目配置

首先,我们需要引入如下的依赖:

<dependency>  <groupId>org.springframework.ai</groupId>  <artifactId>spring-ai-milvus-store-spring-boot-starter</artifactId></dependency><dependency>  <groupId>org.springframework.ai</groupId>  <artifactId>spring-ai-ollama-spring-boot-starter</artifactId></dependency><dependency>  <groupId>com.alibaba.cloud.ai</groupId>  <artifactId>spring-ai-alibaba-starter</artifactId>  <version>1.0.0-M6.1</version></dependency>

说明:

  • Milvus用来存储我们的文档数据

  • Ollama引入是我们需要调用对应的接口来生成向量数据

  • alibaba ai我们将使用它的模型进行Chat对话

     

相关配置

spring:  ai:    dashscope:      api-key: sk-xxxooo      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1      chat:        options:          model: qwen-turbo      # 关闭嵌入模型的自动配置,使用下面的ollama嵌入模型          embedding:        enabled: false---# 配置ollama的嵌入式模型,我们需要通过该模型将对应的文本生成向量数据spring:  ai:    ollama:      chat:        enabled: false      base-url: http://localhost:11111      embedding:        enabled: true        model: bge-m3:latest---# 向量数据库配置(本人配置了其它数据库不生效,只能使用默认的)spring:  ai:    vectorstore:      milvus:        client:          host: localhost          port: 19530          username: root          password: root        # 如果对应的Schema(与关系数据库的DDL类似)不存在则进行创建        initialize-schema: true        embeddingDimension: 1024

说明:上面有2个enabled必须进行相应的关闭,否则无法启动服务(存在多个对应的实现)。

接下来我们开始代码编写。

2.3 向量数据库基本操作

我们这里只实现了文本内容的保存和相似性搜索功能。

@Servicepublic class DocumentService {  private final VectorStore vectorStore ;  public DocumentService(VectorStore vectorStore) {    this.vectorStore = vectorStore;  }    // 将任何文本内容保存到向量数据库  public void save() {    List<Document> documents = List.of(        new Document("香蕉"), new Document("苹果"),         new Document("橘子"), new Document("草莓"),        new Document("Java"), new Document("python"),         new Document("C#"), new Document("老虎")) ;    // 在插入内容时会自动的调用Embedding模型将文本内容转换为向量    this.vectorStore.add(documents) ;  }  // 根据提示词在向量数据库中进行相似性搜索  // prompt  提示词  // topK    返回多少结果(越靠后相似性越低,得分越小)  public List<Document> query(String prompt, int topK) {    SearchRequest request = SearchRequest.builder()        .query(prompt)        .topK(topK)        .build();    // 相似性搜索;会自动将提示词转换为向量后再进行搜索    return this.vectorStore.similaritySearch(request) ;  }}

Controller接口测试

@RestController@RequestMapping("/rag")public class RagController {  private final DocumentService documentService ;  public RagController(DocumentService documentService) {    this.documentService = documentService;  }  @GetMapping("/save")  public ResponseEntity<String> save() {    this.documentService.save() ;    return ResponseEntity.ok("success") ;  }  @GetMapping("/{topK}")  public ResponseEntity<List<Document>> query(@PathVariable Integer topK, String prompt) {    return ResponseEntity.ok(this.documentService.query(prompt, topK)) ;  }}

首先,调用/rag/save方法后,我们通过attu客户端查看Milvus中的数据

最后,我们调用/rag/{topK}接口进行相似性搜索

注意,我们使用的提示词。我们设置的topK为5,水果数据我们插入的是4条,最后一条将编程语言也搜索出来了;因为是相似性搜索这很正常(只要你想,你都能将所有结果拿出,只是越相似的越靠前)。

所以,我们还需要通过LLM来重新组织过滤最终的结果。

接下来我们要将从向量数据库中查询出的结果与LLM结合输出最终的结果。

2.4 结合LLM模型

首先,我们需要配置ChatClient:

@Configurationpublic class ChatConfig {  @Bean  ChatClient chatClient(ChatClient.Builder chatClientBuilder) {    return chatClientBuilder        .defaultAdvisors(List.of(new SimpleLoggerAdvisor()))        .build() ;  }}

我们添加了日志切面,这样方便我们查看请求响应的数据内容。

接下来,我们就可以构建最终的提示词Prompt:

@GetMapping("/query/{topK}")public ResponseEntity<StringqueryLLM(@PathVariable Integer topK, String prompt) {  SearchRequest request = SearchRequest.builder().query(prompt).topK(topK).build();  List<Document> docs = this.vectorStore.similaritySearch(request) ;  // 提示词模板  PromptTemplate promptTemplate = new PromptTemplate("{userMessage}\n\n 用以下信息回答问题:\n {contents}");  // 组装提示词  Prompt finalPrompt = promptTemplate.create(Map.of("userMessage", prompt, "contents", docs)) ;  String result = this.chatClient.prompt(finalPrompt)      .call()      .content() ;  return ResponseEntity.ok(result) ;}

自动过滤了 "python" 并给了提示。

修改查询的提示词如下:

干净的结果。

以上就RAG技术的整个应用过程。


以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

优雅!Spring 基于 Plugin 插件开发(官方推荐)

Spring Boot 多版本API控制 5 种实现方案

Tika 与 Spring Boot 的完美结合:支持任意文档解析的神器

高级开发!扩展@Async功能,动态管理异步任务

高级版@ResponseBody,接口响应数据格式完全自定义

技术专家:零代码,Spring Boot存储加密解密,支持JDBC、MyBatis及JPA

两种方式实现SpringBoot外部配置实时刷新最佳实践

王炸!Spring AI+MCP 三步实现智能体开发

太强了!Spring AI调用本地函数,实时获取最新数据

七大陷阱!99%的Java开发者都会遇到

Spring Boot 3太强:全新Controller接口定义方式

Spring Boot开发利器:精通六大必备技能,轻松应对开发挑战

强大!@DefaultValue注解你用过吗?

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读195
粉丝0
内容832