之前做个几个大模型的应用,都是使用Python语言,后来有一个项目使用了Java,并使用了Spring AI框架。随着Spring AI不断地完善,最近它发布了1.0正式版,意味着它已经能很好的作为企业级生产环境的使用。对于Java开发者来说真是一个福音,其功能已经能满足基于大模型开发企业级应用。借着这次机会,给大家分享一下Spring AI框架。
注意:由于框架不同版本改造会有些使用的不同,因此本次系列中使用基本框架是 Spring AI-1.0.0,JDK版本使用的是19。
代码参考: https://github.com/forever1986/springai-study
目录
- 1 RAG
- 2 示例演示
- 2.1 初始化
- 2.2 实现RAG
- 2.3 演示
大模型训练数据是大模型公司自身或公开的数据,并不具备某些公司自身的企业内部数据。这时候有两种方法可以让大模型学习企业内部数据,一种是微调,一种就是RAG。随着大模型的token长度越来越长,RAG比微调更具备安全性和可靠性的优势,因此越来越多的应用都是基于RAG。现在来看看Spring AI如何使用RAG。
1 RAG
提示:学习Spring AI中的RAG,建议最好想了解什么是RAG,可以参考我之前写的系列《检索增强生成RAG系列》
RAG的全称是Retrieval-Augment Generation,即称为检索增强生成。通过特定prompt方式为 LLM 提供了从某些数据源检索到的信息,并基于此修正生成的答案。其中有几个关键的点需要知道:
- 一个是从某些数据源检索到的信息
- 提供特定的prompt
- 修正生成答案
简单用一句话来说就是:利用特定知识库(一般是向量数据库)将格外的知识以向量或其它方式存储,然后在回答用户问题时,先将用户问题在知识库(向量数据库)中进行查询(比如相似度查询、关键字查询等),再将查询结果以prompt的方式扔给大模型,获得最终答案。
以下就是RAG常见的整体架构:
RAG的步骤:
- 1)专业知识向量化之后,存入向量数据库
- 2)通过用户提出的问题,进行向量检索向量数据库(一般使用相似度等查询算法),为了限制token长度,一般取Top-N数据
- 3)使用特定的prompt提示词,将问题和查出来的Top-N数据给大模型
- 4)大模型根据问题和参考数据,进行回答
关于RAG的内容很多,本人在之前写过《检索增强生成RAG系列》的文章,有兴趣的朋友可以去先了解RAG的内容,再来看看接下来的几章就会比较容易理解。
2 示例演示
代码参考lesson11子模块的get-start子模块
示例说明:通过将文档进行embedding,存入向量数据库。之后通过Spring AI的QuestionAnswerAdvisor进行封装提问
2.1 初始化
1)由于需要将数据进行embedding,这里使用线上智谱的模型,因此需要充值(关于加载本地embedding模型,后续会再讲)
2)新建lesson11子模块
3)在lesson11子模块下,新建get-start子模块,其pom的引入如下:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-zhipuai</artifactId></dependency><!-- 引入向量数据库插件 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-advisors-vector-store</artifactId></dependency>
</dependencies>
4)配置application.properties文件
# 聊天模型
spring.ai.zhipuai.api-key=你的智谱模型的API KEY
spring.ai.zhipuai.chat.options.model=GLM-4-Flash-250414
spring.ai.zhipuai.chat.options.temperature=0.7
5)新建启动类Lesson11GetStartApplication:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Lesson11GetStartApplication{public static void main(String[] args) {SpringApplication.run(Lesson11GetStartApplication.class, args);}
}
2.2 实现RAG
1)将文档数据embedding后,存入向量数据库
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;@Configuration
public class VectorStoreConfig {/*** @param embeddingModel - 这里如果没有特殊配置,默认使用的是你引入model的embedding模型*/@Beanpublic VectorStore vectorStore(EmbeddingModel embeddingModel){SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(embeddingModel).build();List<Document> documents = List.of(new Document("ChatGLM3 是北京智谱华章科技有限公司和清华大学 KEG 实验室联合发布的对话预训练模型。ChatGLM3-6B 是 ChatGLM3 系列中的开源模型,在保留了前两代模型对话流畅、部署门槛低等众多优秀特性的基础上,ChatGLM3-6B 引入了如下特性:\n" +"\n" +"更强大的基础模型: ChatGLM3-6B 的基础模型 ChatGLM3-6B-Base 采用了更多样的训练数据、更充分的训练步数和更合理的训练策略。在语义、数学、推理、代码、知识等不同角度的数据集上测评显示,* ChatGLM3-6B-Base 具有在 10B 以下的基础模型中最强的性能*。\n" +"更完整的功能支持: ChatGLM3-6B 采用了全新设计的 Prompt 格式 ,除正常的多轮对话外。同时原生支持工具调用(Function Call)、代码执行(Code Interpreter)和 Agent 任务等复杂场景。\n" +"更全面的开源序列: 除了对话模型 ChatGLM3-6B 外,还开源了基础模型 ChatGLM3-6B-Base 、长文本对话模型 ChatGLM3-6B-32K 和进一步强化了对于长文本理解能力的 ChatGLM3-6B-128K。以上所有权重对学术研究完全开放 ,在填写 问卷 进行登记后亦允许免费商业使用。\n" +"\n" +"北京智谱华章科技有限公司是一家来自中国的公司,致力于打造新一代认知智能大模型,专注于做大模型创新。"));simpleVectorStore.add(documents);return simpleVectorStore;}
}
2)创建RAGController 演示类:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RAGController {private ChatClient chatClient;public RAGController(ChatClient.Builder chatClientBuilder, VectorStore vectorStore) {this.chatClient = chatClientBuilder// 通过Advisors方式,对向量数据库进行封装.defaultAdvisors(new QuestionAnswerAdvisor(vectorStore)).build();}/*** @param message 问题*/@GetMapping("/ai/rag")public String rag(@RequestParam(value = "message", required = true, defaultValue = "ChatGLM3是哪个国家的大模型?") String message) {return this.chatClient.prompt().user(message).call().content();}}
2.3 演示
1)访问地址:
http://localhost:8080/ai/rag
说明:从上图可以看到通过知识库的嵌入,并查询,将结果以prompt方式提供给大模型,最终大模型根据上下文给出问题的答案。
结语:本章讲解了RAG的原理,并通过Spring AI一个入门示例,就实现了RAG的功能。从示例可以看到Spring AI对RAG的封装后,对用户的使用十分简便。关于Spring AI实现RAG还有更深入的功能,接下来几章会详细讲解。
Spring AI系列上一章:《Spring AI 系列之八 - MCP Server》
Spring AI系列下一章:《Spring AI 系列之十 - RAG-进阶QuestionAnswerAdvisor》