📋 概述

开源地址:spring-ai-alibaba-rag-example
这个项目展示了如何使用 Spring AI Alibaba 结合 Elasticsearch 实现 RAG(检索增强生成) 功能。简单来说,就是让 AI 能"查阅资料"再回答你的问题,而不是凭空瞎编。
Elasticsearch可以参考专栏Elasticsearch从零开始

核心流程一览

🔄 RAG 智能检索增强生成系统

🔍 智能问答与生成流程

📥 文档导入与索引流程

💬 用户提问

📄 PDF 原始文档

🧩 文档解析
PagePdfDocumentReader

✂️ 文本分块
TokenTextSplitter

🔢 向量化处理
DashScope Embedding

💾 向量数据库
Elasticsearch

🔢 问题向量化

🔍 向量检索
KNN Search topK=4

⚖️ 结果重排序
RetrievalRerankAdvisor

🤖 答案生成
通义千问 LLM


🛠️ 环境准备

1. 必要软件清单

软件 版本要求 说明
JDK 17+ 必须!Spring Boot 3.x 强制要求
Elasticsearch 9.3.x 向量数据库,存储和检索向量
Maven 3.6+ 项目构建工具
Docker 20.10+ 推荐用 Docker 运行 ES(可选但方便)

2. 获取 DashScope API Key 🔑

DashScope 是阿里云提供的大模型服务平台,我们需要它的 API Key 来调用 Embedding 模型和对话模型。

获取步骤: 参考前文这里不再赘述。


🚀 部署实操

步骤一:启动 Elasticsearch

推荐方式:Docker 一键启动 🐳

# 启动单节点 Elasticsearch(生产环境请用集群)
docker run -d \
  --name elasticsearch \
  -p 9200:9200 \
  -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  docker.elastic.co/elasticsearch/elasticsearch:9.3.1

参数说明:

  • discovery.type=single-node:单节点模式,适合开发学习
  • xpack.security.enabled=false⚠️ 仅学习时关闭,生产环境务必启用安全认证
  • ES_JAVA_OPTS:限制内存 512MB,防止吃掉太多系统资源

验证启动成功:

curl http://localhost:9200

返回类似以下内容说明成功:

{
  "name": "elasticsearch",
  "cluster_name": "docker-cluster",
  "version": {
    "number": "9.3.1",
    "build_flavor": "default"
  },
  "tagline": "You Know, for Search"
}

步骤二:配置项目

在项目根目录创建或修改 application.yml

spring:
  application:
    name: rag-elasticsearch-example
  
  # ✅ 正确配置(README里的有错误!)
  ai:
    dashscope:
      api-key: ${AI_DASHSCOPE_API_KEY}  # 你的API Key
  
  # 向量存储配置
  vectorstore:
    elasticsearch:
      index-name: spring-ai-alibaba-index
      similarity: cosine      # 余弦相似度
      dimensions: 1536        # 向量维度(text-embedding-v3 默认1024,但可配置1536)

# Elasticsearch 连接配置
elasticsearch:
  uris: http://localhost:9200

🔧 环境变量设置:

# Linux/Mac
export AI_DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx

# Windows CMD
set AI_DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx

# Windows PowerShell
$env:AI_DASHSCOPE_API_KEY="sk-xxxxxxxxxxxxxxxx"

# 或者在 IDE 运行配置中设置(推荐开发时用)

⚠️ README 错误纠正:当前的git库里README 写的配置路径 ai.dashscope 应该是错的!Spring AI 正确的路径是 spring.ai.dashscope。同样 elasticsearch.uri 应该是 elasticsearch.uris(复数形式)。


步骤三:编译运行

# 进入项目目录
cd /home/tht/examples-main/spring-ai-alibaba-rag-example/rag-elasticsearch-example

# 编译(-DskipTests 跳过测试,加快编译)
./mvnw clean package -DskipTests

# 运行
./mvnw spring-boot:run

或者直接运行主类 RagExampleApplication.java(IDE 中右键运行,适合调试)。


📡 API 接口使用

项目启动后,默认在 http://localhost:8080 提供服务:

1. Local RAG(本地模式)

接口 方法 功能
/ai/rag/importDocument GET 导入 PDF 文档到 ES(首次必须执行)
/ai/rag GET 问答接口(需传 message 参数)

实操命令:

# ① 导入文档(首次运行必须执行!否则知识库是空的)
curl -X GET http://127.0.0.1:8080/ai/rag/importDocument

# ② 开始问答
curl -G 'http://127.0.0.1:8080/ai/rag' \
  --data-urlencode 'message=如何快速开始 Spring AI Alibaba'

2. Cloud RAG(云端模式)

接口 方法 功能
/ai/cloud/rag/importDocument GET 导入到云向量库(阿里云向量检索服务)
/ai/cloud/rag GET 云端问答

云端模式适合生产环境,利用阿里云托管的向量检索服务,免去自己维护 ES 集群的麻烦。


🔬 核心原理详解

1. 文档导入流程(Indexing)

💾 存储层

⚙️ 处理层

📄 输入层

PDF文件
spring_ai_alibaba_quickstart.pdf

📖 文档解析
PagePdfDocumentReader
提取文本+元数据

✂️ 智能分块
TokenTextSplitter
按Token切分,保持语义完整

🔢 向量化
DashScope Embedding API
文本→1536维向量

Elasticsearch
向量索引
index: spring-ai-alibaba-index

为什么要分块?

想象你有一本1000页的技术手册,如果直接把整本书变成一个向量,当用户问"如何配置 API Key"时,这个向量代表的是"整本书的语义",而不是"API Key 配置方法"的语义。这样检索精度会很差。

把文档切成 500-1000 Token 的小块,每块聚焦一个具体话题,检索时就能精准匹配到相关内容。

代码对应(LocalRagService.java):

// 1. 解析PDF - 提取文本内容和元数据(如页码、文件名)
DocumentReader reader = new PagePdfDocumentReader(springAiResource);
List<Document> documents = reader.get();

// 2. 分块 - 默认按token分,便于控制上下文长度
// 默认策略:每块约 800 Token,重叠 200 Token(防止语义断裂)
List<Document> splitDocuments = new TokenTextSplitter().apply(documents);

// 3. 向量化 + 存储(Spring AI 自动调用 DashScope API 生成向量)
// 每个 Document 会被转换成 1536 维的浮点数向量
vectorStore.add(splitDocuments);

2. 问答流程(Retrieval & Generation)

🤖 生成层

🔍 检索层

👤 用户层

用户提问
'如何配置 API Key?'

🔢 问题向量化
DashScope Embedding
生成查询向量

📊 向量检索
Elasticsearch KNN
topK=4 近似最近邻

⚖️ 智能重排序
RetrievalRerankAdvisor
语义相关性精排

📝 组装 Prompt
系统提示+上下文+用户问题

🧠 LLM 推理
通义千问/Qwen
生成自然语言答案

💬 返回答案

代码对应:

// 构建检索请求 - 配置检索策略
SearchRequest searchRequest = SearchRequest.builder()
    .topK(4)                    // 返回最相似的4条文档块
    .similarityThresholdAll()   // 接受所有结果(不过滤)
    .filterExpression(...)      // 可添加过滤条件(如按文件名过滤)
    .build();

// 使用 RetrievalRerankAdvisor 完成检索+重排序+生成一体化
// 这是 Spring AI Alibaba 的高级特性,简化了 RAG 流程
ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(new RetrievalRerankAdvisor(
        vectorStore,      // 向量存储(ES)
        rerankModel,      // 重排序模型(优化检索结果顺序)
        searchRequest,    // 检索配置
        systemPrompt,     // 系统提示词(定义 AI 角色和回答规则)
        0.1               // 最小相关度阈值(低于此值的文档会被过滤)
    ))
    .build();

// 执行对话 - 自动完成:问题向量化→检索→重排序→组装Prompt→调用LLM
return chatClient.prompt()
    .user(message)           // 用户问题
    .stream()              // 流式返回(打字机效果)
    .chatResponse();

什么是重排序(Rerank)?

第一次向量检索(KNN)是"粗排",快速找出大致相关的文档。但向量相似度≠语义相关性,可能找到一些表面相似但实际无关的内容。

重排序模型是"精排",用更复杂的算法(通常是交叉编码器)重新计算问题与每个候选文档的真实相关性,把最相关的排在最前面,显著提升回答质量。


3. Elasticsearch 向量索引结构

项目启动时会自动创建如下索引结构:

{
  "mappings": {
    "properties": {
      "embedding": {
        "type": "dense_vector",      // 密集向量类型
        "dims": 1536,                 // 向量维度
        "index": true,                // 开启索引(支持检索)
        "similarity": "cosine"         // 余弦相似度算法
      },
      "content": {
        "type": "text",               // 原始文本内容
        "analyzer": "ik_max_word"       // IK分词器(中文友好)
      },
      "metadata": {
        "properties": {
          "source": { "type": "keyword" },    // 来源文件名
          "page_number": { "type": "integer" } // 页码
        }
      }
    }
  }
}

⚠️ 常见问题与解决方案

Q1: 启动报 NoClassDefFoundError

原因:Maven 依赖没下载完整,或者版本冲突

解决:

# 强制更新依赖
./mvnw clean install -U

# 如果还不行,删除本地仓库重新下载
rm -rf ~/.m2/repository/com/alibaba/cloud/ai
./mvnw clean install

Q2: 连接不上 Elasticsearch?

排查步骤:

# 1. 检查 ES 是否启动
curl http://localhost:9200

# 2. 检查防火墙(Linux)
sudo ufw allow 9200/tcp
# 或
sudo iptables -I INPUT -p tcp --dport 9200 -j ACCEPT

# 3. 查看 ES 日志
docker logs elasticsearch

# 4. 检查内存(ES 默认需要较大内存)
docker stats elasticsearch

常见原因:内存不足导致 ES 启动后自动退出,建议 Docker 分配至少 2GB 内存。


Q3: DashScope API 调用失败?

检查清单:

  1. API Key 是否正确设置

    echo $AI_DASHSCOPE_API_KEY  # 检查环境变量
    
  2. 是否超过配额

    • 登录 DashScope 控制台查看用量
  3. 网络能否访问阿里云

    • 检查代理/VPN 设置
    • 测试连通性:curl https://dashscope.aliyuncs.com
  4. 查看详细错误日志

    • 开启 DEBUG 日志:logging.level.com.alibaba.cloud.ai: DEBUG

Q4: 向量维度不匹配?

错误信息dimension mismatchIncorrect dimension for field 'embedding'

解决:确认 application.ymldimensions 与使用的 Embedding 模型匹配:

模型 默认维度 可配置维度
text-embedding-v1 1536 固定
text-embedding-v2 1536 固定
text-embedding-v3 1024 512/768/1024
text-embedding-v4 1024 64-2048 多档

建议:v3/v4 模型默认 1024 维,如需 1536 维需显式配置:

spring:
  ai:
    dashscope:
      embedding:
        options:
          model: text-embedding-v3
          dimensions: 1536  # 显式指定

Q5: 检索结果不准确?

优化建议:

优化方向 具体方法
调整 topK 增大到 10-20,召回更多候选
调整重排序阈值 从 0.1 调到 0.3-0.5,过滤低质量文档
优化 Prompt 修改 system-qa.st 模板,明确回答规则
调整分块策略 TokenTextSplitter 参数:chunkSizechunkOverlap
混合检索 结合关键词检索(BM25)+ 向量检索

高级技巧 - 查询改写:
如果用户问"怎么开始",可能匹配不到"快速入门指南"。可以在检索前用 LLM 把问题改写成多个同义表达,提升召回率。


📊 技术栈版本对照

组件 本项目版本 说明
Spring Boot 3.x 框架基础,必须 JDK 17+
Spring AI 1.0.0-M6+ AI 抽象层
Spring AI Alibaba 1.0.0-M6.1+ 阿里云 AI 集成
**Elasticsearch ** 9.3.1 ES 官方客户端
DashScope SDK 最新版 阿里云模型服务
JDK 17+ 最低要求,推荐 21

🏗️ 生产环境建议

Elasticsearch 配置

# 生产级 ES 配置
elasticsearch:
  uris: https://your-es-cluster.com:9200  # HTTPS 必须
  username: elastic                         # 启用认证
  password: ${ES_PASSWORD}
  ssl:
    verification-mode: certificate          # 证书验证

性能优化

方面 建议
ES 集群 至少 3 节点,主节点与数据节点分离
内存 ES 堆内存建议 4GB+,向量运算耗内存
分片 向量索引分片数 = 节点数 × 2
刷新频率 导入时调大 refresh_interval 到 30s,减少刷盘
批量导入 使用 Bulk API,每批 500-1000 条

监控与运维

  • 监控:接入 Prometheus + Grafana,关注 search_latencyindexing_rate
  • 备份:定期快照备份向量索引
  • 限流:DashScope API 有 QPS 限制(默认 10-50),生产环境加熔断降级
  • 缓存:热点查询结果缓存到 Redis,减少重复调用

安全加固

  1. 网络安全:ES 不暴露公网,通过 VPC 或 IP 白名单访问
  2. API Key 管理:使用阿里云 KMS 或 Vault 托管,不要硬编码
  3. 输入过滤:对用户问题做敏感词检测,防止 Prompt 注入
  4. 输出审计:记录 LLM 输入输出,便于问题追溯

附:完整 Mermaid 架构图

💾 存储层

🤖 AI 模型

📚 数据处理

🚀 Spring Boot 应用

提问

存储向量

1. 问题向量化

2. 向量检索

3. 重排序

4. 生成回答

返回答案

RestController
API 接口层

RAG Service
业务逻辑层

Spring AI Alibaba
AI 抽象层

PDF 文档

PagePdfDocumentReader

TokenTextSplitter

DashScope Embedding
text-embedding-v3

DashScope Chat
qwen-max

Rerank Model
重排序模型

Elasticsearch 9.3.x
向量索引

👤 用户


希望本文能帮助你顺利搭建 RAG 应用!如有问题,欢迎留言讨论交流。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐