Java 版本 RAG 示例(Spring AI + Milvus)

Java RAG 示例:Spring AI + Milvus

Spring‑AI 0.8.1,Milvus 2.4+,JDK17,SpringBoot3.x 整体流程:文档加载 → 文本分块 → Embedding 向量化 → 存入 Milvus 向量库 → 检索向量 → 组装上下文 Prompt → LLM 生成回答。 依赖:SpringAI Milvus 向量存储、OpenAI 兼容大模型(Qwen/DeepSeek 均可)、BGE embedding(本地或 API)。

1. pom.xml 核心依赖

xml

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/>
    </parent>

    <groupId>com.demo</groupId>
    <artifactId>spring‑ai‑rag‑milvus</artifactId>
    <version>0.0.1‑SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
        <spring-ai.version>0.8.1</spring-ai.version>
    </properties>

    <dependencies>
        <!-- SpringBoot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring AI Milvus 向量库 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring‑ai‑milvus‑store‑spring‑boot‑starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <!-- SpringAI OpenAI兼容 LLM (通义千问/DeepSeek都兼容openai接口) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring‑ai‑openai‑spring‑boot‑starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <!-- PDF文档解析 -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring‑ai‑bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

2. application.yml 配置

Milvus 先 docker 启动,默认端口19530;示例使用通义千问兼容 OpenAI 接口,也可以换成 DeepSeek。

yaml

复制代码
spring:
  ai:
    # LLM大模型配置,openai兼容接口
    openai:
      api-key: sk‑xxxx你的key
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      chat:
        options:
          model: qwen-plus
          temperature: 0.0

    # Milvus向量数据库配置
    vectorstore:
      milvus:
        client:
          host: 127.0.0.1
          port: 19530
        database-name: default
        collection-name: spring_ai_kb
        # bge‑small‑zh 向量维度为512,务必和embedding模型保持一致!
        embedding-dimension: 512
        # 检索返回topN
        top-k: 4
        # 是否自动创建表
        auto-create-collection: true

⚠️重要:embedding‑dimension必须和 Embedding 模型输出维度完全匹配。

  • bge‑small‑zh‑v1.5 → 512 维
  • bge‑m3 → 1024 维
    SpringAI 内置 Embedding 默认调用 OpenAI 的 text‑embedding,中文效果差;实际项目建议替换为 BGE 本地 Embedding。下面示例先用 API 快速跑通,后面给 BGE 自定义 Embedding 扩展代码。

3. 核心 RAG 服务类

java

运行

复制代码
package com.demo.rag.service;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class RagService {

    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    /**
     * 1、加载PDF文档,分块,写入Milvus知识库(离线构建,执行一次)
     */
    public void loadPdfToVectorStore(String pdfFilePath) {
        // 读取PDF
        PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(pdfFilePath);
        List<Document> originDocs = pdfReader.get();

        // 文本分块 TokenTextSplitter
        // 中文经验:chunkSize=500‑700,overlap=120‑150
        TokenTextSplitter splitter = new TokenTextSplitter(700, 150, 10, 1000, true);
        List<Document> splitDocs = splitter.apply(originDocs);

        // 写入Milvus向量库,自动embedding
        vectorStore.add(splitDocs);
        System.out.println("✅文档入库完成,分块数量:" + splitDocs.size());
    }

    /**
     * 2、RAG问答:检索Milvus + LLM生成答案
     */
    public String chat(String userQuestion) {
        // 向量检索,top‑k=4
        List<Document> recallDocs = vectorStore.similaritySearch(
                SearchRequest.builder()
                        .query(userQuestion)
                        .topK(4)
                        .build()
        );

        // 拼接检索到的知识库上下文
        StringBuilder contextSb = new StringBuilder();
        for (Document doc : recallDocs) {
            contextSb.append(doc.getContent()).append("\n");
        }

        // RAG固定Prompt模板,约束不要幻觉
        String promptTemplate = """
                你是内部知识库问答助手,请严格依据【参考上下文】回答用户的问题。
                如果参考上下文中没有相关信息,直接回复:知识库未查询到相关内容,禁止编造任何信息。
                
                【参考上下文】
                {context}
                
                【用户问题】
                {question}
                """;

        return chatClient.prompt()
                .user(u -> u.text(promptTemplate)
                        .param("context", contextSb.toString())
                        .param("question", userQuestion))
                .call()
                .content();
    }

    /**
     * 清空Milvus当前collection全部数据(测试用)
     */
    public void clearKb() {
        vectorStore.delete(List.of("*"));
    }
}

4. 测试 Controller

java

运行

复制代码
package com.demo.rag.controller;

import com.demo.rag.service.RagService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rag")
@RequiredArgsConstructor
public class RagController {

    private final RagService ragService;

    // 上传PDF构建知识库,本地文件路径
    @GetMapping("/load")
    public String loadKb(@RequestParam String filePath) {
        ragService.loadPdfToVectorStore(filePath);
        return "load success";
    }

    // RAG问答接口
    @GetMapping("/chat")
    public String chat(@RequestParam String q) {
        return ragService.chat(q);
    }

    // 清空知识库
    @GetMapping("/clear")
    public String clear() {
        ragService.clearKb();
        return "clear ok";
    }
}

5. 启动类

java

运行

复制代码
package com.demo.rag;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RagMilvusApplication {
    public static void main(String[] args) {
        SpringApplication.run(RagMilvusApplication.class, args);
    }
}

6. Milvus 快速 Docker 启动

bash

复制代码
docker run -d --name milvus‑standalone \
  -p 19530:19530 \
  -p 9091:9091 \
  milvusdb/milvus:v2.4.15‑standalone

替换为中文 BGE Embedding(生产必做)

SpringAI 默认是 OpenAI embedding,中文效果很差。 两种方案:

  1. 部署 bge‑small‑zh OpenAI 兼容 Embedding 服务,修改 yml 的 embedding base‑url。
  2. 实现EmbeddingModel接口接入本地 BGE 模型。
相关推荐
OFIRM碳基硅基5 小时前
西游金蝉劫 IP · 之 《金蝉子前传渡缘劫》电影 20 亿票房触发 · 项目专项扶持协议 总览 拉格朗日光影动画-西游金蝉劫项目组
大数据·人工智能·西游金蝉劫·蝎子精·蝎子精女妖王·金蝉子前传渡缘劫
银空飞羽5 小时前
职型求职工具实测:把简历分析、岗位匹配和定向优化串成一条求职链路
人工智能·经验分享·面试·职场和发展·跳槽·求职招聘·创业创新
ChaITSimpleLove5 小时前
AI时代 “本体” 的 “标准化” 定义
人工智能·dsl·rdf·ontology·ai本体·json-ld
FL16238631296 小时前
基于YOLOv8的智慧校园人脸识别和公路汽车检测项目源码+训练好的模型
人工智能
进化矩阵6 小时前
别把指标当目的:当数字开始反噬你
大数据·人工智能·职场和发展·创业创新
万物智能信息科技6 小时前
电容触摸 FT5406,另一颗芯片、同一条总线—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
人工智能·华为·开源·harmonyos·鸿蒙
doudoudalao6 小时前
TikTok 带货视频怎么做?AI 一键生成带货视频提示词分享,怎么写出爆款的 AI 带货视频提示词
人工智能
十正6 小时前
把表变成模型够得着的句柄
人工智能·ai·agent
captain3766 小时前
网络原理(3)-TCP核心机制连接管理▲▲▲
java·服务器·网络·ide·网络协议·tcp/ip·java-ee
林浩杨_6 小时前
港科大(广州)× 南航 × OPPO:DPPMG——个性化多模态生成框架
人工智能