大数跨境
0
0

Spring AI + RAG:网页智能解析,精准问答一键开启!

Spring AI + RAG:网页智能解析,精准问答一键开启! Spring全家桶实战案例
2025-07-23
0
导读:Spring AI + RAG:网页智能解析,精准问答一键开启!
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!

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

💪💪永久更新承诺

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

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

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

本篇文章将使用 Spring AI 实现网页问答。给定一个网页地址,在本案例中应用程序会将其内容加载到向量数据库中进行存储,当我们进行提问时,会先从向量数据库中进行相似性查询,将查询到的结果 + 用户的提问 一起发送给 LLM 形成最终的回答返回给用户。

2.实战案例

2.1 准备环境

引入依赖

<dependency>  <groupId>org.springframework.ai</groupId>  <artifactId>spring-ai-advisors-vector-store</artifactId></dependency><!--使用ollama上的bge-m3模型将文本生成向量数据--><dependency>  <groupId>org.springframework.ai</groupId>  <artifactId>spring-ai-starter-model-ollama</artifactId></dependency><!--将向量数据存入Miluvs向量数据库--><dependency>  <groupId>org.springframework.ai</groupId>  <artifactId>spring-ai-starter-vector-store-milvus</artifactId></dependency><!--阿里百炼平台--><dependency>  <groupId>com.alibaba.cloud.ai</groupId>  <artifactId>spring-ai-alibaba-autoconfigure-dashscope</artifactId>  <version>1.0.0.2</version></dependency><!--使用该库进行网页内容的读取--><dependency>  <groupId>org.jsoup</groupId>  <artifactId>jsoup</artifactId>  <version>1.18.3</version></dependency>

配置文件

spring:  ai:    dashscope:      api-key: sk-xxxooo      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1      chat:        options:          model: qwen-turbo      embedding:        enabled: false---spring:  ai:    ollama:      base-url: http://localhost:11111      embedding:        model: bge-m3:latest---spring:  ai:    vectorstore:      milvus:        client:          host: localhost          port: 19530          username: xxx          password: ooo        initialize-schema: true        databaseName: "mydb"        collectionName: "mydocs"        autoId: true        id-field-name: id        embeddingDimension: 1024

由于我们同时引入了ollama及阿里的百炼,这时候的ChatClient及Embedding就会配置2个;所以,我们这里要将不用的排除自动配置:

@SpringBootApplication(  exclude = {    OllamaChatAutoConfiguration.class    DashScopeEmbeddingAutoConfiguration.class  })public class SpringBootAiWebQaApplication {}

以上基础环境就配置完成了,接下来我们就可以实现具体的功能了。

2.2 文档读取器

首先,我们要根据提供的URL加载网页内容。通过 jsoup 库来完成。而这里我们需要实现 Spring AI 中 DocumentReader 接口,它负责将网页内容转换为 Document 对象。

public class WebDocumentReader implements DocumentReader {  private static final Logger logger = LoggerFactory.getLogger(WebDocumentReader.class);  private final String url;  public WebDocumentReader(String url) {    this.url = url;  }  @Override  public List<Documentget() {    try {      X509ExtendedTrustManager trustManager = createTrustManager();      SSLContext sslContext = SSLContext.getInstance("TLS");      sslContext.init(nullnew TrustManager[]{trustManager}, new SecureRandom());      org.jsoup.nodes.Document doc = Jsoup.connect(url).sslSocketFactory(sslContext.getSocketFactory()).get();      Map<StringObject> metadata = Map.of("source", url,           "date"DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));      return List.of(new Document(doc.body().text(), metadata));    } catch (Exception e) {      logger.error("加载【{}】发生错误: {}"this.url, e);      return List.of() ;    }  }  private X509ExtendedTrustManager createTrustManager() {    return new X509ExtendedTrustManager() {      public X509Certificate[] getAcceptedIssuers() {        return new X509Certificate[0];      }      // 其它方法    };  }}

2.3 文档写入向量数据库

在上一步我们将网页内容转换为Document对象后,接下来,我们就需要对这些Document切割并保存到向量数据库。

@Servicepublic class WebDocumentService {  private final VectorStore vectorStore ;  public WebDocumentService(VectorStore vectorStore) {    this.vectorStore = vectorStore;  }
  public void save(String url) {    WebDocumentReader reader = new WebDocumentReader(url) ;    List<Document> docs = reader.get() ;    TokenTextSplitter splitter = new TokenTextSplitter(1000400105000true);    List<Document> result = splitter.apply(docs);    this.vectorStore.add(result) ;  }}

Spring AI还提供了如下几种切割文档的实现:

  • TokenTextSplitter

    该类 是 TextSplitter 的一种实现,它使用 CL100K_BASE 编码,根据标记数将文本分割成块。

  • ContentFormatTransformer

    内容格式转换器

  • KeywordMetadataEnricher

    一个文档转换器,它使用生成式人工智能模型从文档内容中提取关键词,并将其添加为元数据。

  • SummaryMetadataEnricher

    摘要元数据丰富器(SummaryMetadataEnricher)是一个文档转换器,它使用生成式人工智能模型为文档创建摘要并将其添加为元数据。它可以为当前文档以及相邻文档(上一个和下一个)生成摘要。

2.4 配置ChatClient

@Configurationpublic class ChatConfig {  @Bean  ChatClient chatClient(ChatClient.Builder builder, VectorStore vectorStore) {    // 默认是英文的,所以我们这里简单点就是翻译过来    PromptTemplate promptTemplate = new PromptTemplate("""        上下文信息如下。        ---------------------        {context}        ---------------------        根据上下文信息且无先验知识的情况下,回答查询。        遵循以下规则:        1.如果答案不在上下文中,直接说明"我不知道"。        2.避免使用"根据上下文……"或"提供的信息……"等表述。        查询: {query}        回答:        """) ;    QueryAugmenter queryAugmenter = ContextualQueryAugmenter.builder()        .promptTemplate(promptTemplate )        .build() ;    Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()        .queryAugmenter(queryAugmenter)        .documentRetriever(VectorStoreDocumentRetriever.builder()                .similarityThreshold(0.40)                .topK(1)                .vectorStore(vectorStore)                .build())        .build();
    List<Advisor> advisors = List.of(new SimpleLoggerAdvisor(), retrievalAugmentationAdvisor);    return builder        .defaultAdvisors(advisors)        .build() ;  }}

上面我们配置了 RetrievalAugmentationAdvisor 切面,Spring AI 包含一系列检索增强生成(RAG)模块库,你可利用这些模块构建自己的 RAG 流程。RetrievalAugmentationAdvisor 是一个顾问类(Advisor),它基于模块化架构,为最常见的 RAG 流程提供了开箱即用的实现方案。

简单说,该切面就是根据你的提示词(你的问题)到向量数据库中进行查询数据,最后将查询的结果一起发送给大模型。

2.5 Controller接口

定义两个接口,分别用来将网页内容存入向量数据库和聊天对话。

@RestController@RequestMapping("/web")public class WebController {  private final WebDocumentService webDocumentService ;  public WebController(WebDocumentService webDocumentService) {    this.webDocumentService = webDocumentService;  }
  @GetMapping("/load")  public ResponseEntity<?> load(String url) {    this.webDocumentService.save(url) ;    return ResponseEntity.ok("success") ;  }}@RestController@RequestMapping("/chat")public class ChatController {  private final ChatClient chatClient ;  public ChatController(ChatClient chatClient) {    this.chatClient = chatClient;  }
  @GetMapping("")  public ResponseEntity<?> chat(String prompt) {    String body = this.chatClient.prompt(prompt)        .call()        .content() ;    return ResponseEntity.ok(body) ;  }}

2.6 测试

首先,我们将如下的url网页内容保存到向量数据库中

https://news.cctv.com/2025/07/12/ARTIQut4IA1QEu4yRQfAyTfj250712.shtml?spm=C73544894212.P9moqzeXHoOr.EogkW3VdRtw6.8

数据成功保存到Milvus中,并且对应的文本都转换为向量数据。

接下来进行查询

控制台输出如下:



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

推荐文章

Spring Boot 加载配置的6种骚操作,第6种知道的人很少

Spring Boot Rest API十大常见错误及避免方法

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

手写Spring MVC核心组件,底层原理如此简单

基于 Spring Boot 玩转JPA各种锁的应用(乐观锁,悲观锁)

强大!Spring Boot全新模块化管理方式

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

Jackson才是王!SpringBoot优雅的控制JSON数据

提升性能:Java工程师必备的20条SQL最佳实践

SpringBoot+Nginx+Lua接口性能提升N倍

虚拟线程在Spring Boot中的应用及性能对比

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