Spring AI Alibaba 集成 Redis 向量数据库实现 RAG 与记忆功能

概述

本文基于一个完整的 Spring Boot 项目示例,详细讲解如何使用 Spring AI Alibaba 框架集成 Redis 向量数据库,实现检索增强生成(RAG)和对话记忆功能。项目包含向量存储、文档加载、多模型配置、记忆管理等核心模块,适用于构建具备知识库检索和上下文记忆的 AI 应用。

项目架构概览

整个项目采用分层架构设计,主要包含以下核心组件:

  • 配置层:Redis 连接配置、AI 模型配置、向量存储配置
  • 数据层:文档加载器、向量存储实现
  • 业务层:RAG 检索、对话记忆管理
  • 控制层:RESTful API 接口

一、环境准备与依赖配置

1.1 Maven 依赖配置

pom.xml 中配置 Spring AI Alibaba 相关依赖:

<properties>
    <spring-ai.version>1.0.0</spring-ai.version>
    <spring-ai-alibaba.version>1.0.0.2</spring-ai-alibaba.version>
    <spring-boot.version>3.4.5</spring-boot.version>
    <java.version>17</java.version>
</properties>

<dependencies>
    <!-- Spring AI Alibaba BOM -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-bom</artifactId>
        <version>${spring-ai-alibaba.version}</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    
    <!-- DashScope 模型支持 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        <version>${spring-ai-alibaba.version}</version>
    </dependency>
    
    <!-- Redis 记忆存储 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>
        <version>${spring-ai-alibaba.version}</version>
    </dependency>
    
    <!-- 向量存储核心 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-vector-store</artifactId>
        <version>${spring-ai.version}</version>
    </dependency>
    
    <!-- Redis 客户端 -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    
    <!-- 其他基础依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

1.2 配置文件(application.yml)

spring:
  data:
    redis:
      host: localhost
      port: 6379
      password: 123456
      lettuce:
        pool:
          max-active: 16
          max-idle: 8
          min-idle: 4
      timeout: 2000ms
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
  application:
    name: Roadnetworktraffic
  ai:
    vectorstore:
      redis:
        initialize-schema: true
        index-name: custom-index
        prefix: custom-prefix
    dashscope:
      embedding:
        baseUrl: https://dashscope.aliyuncs.com # 向量模型
        api-key: your-api-key-here
        options:
          model: text-embedding-v4
      api-key: your-api-key-here
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      chat:
        options:
          model: qwen-flash

关键配置说明

  • spring.data.redis:Redis 连接配置,用于向量存储和记忆存储
  • spring.ai.vectorstore.redis:向量存储的 Redis 索引配置
  • spring.ai.dashscope:通义千问模型配置,包括嵌入模型和对话模型

二、核心组件实现

2.1 Redis 记忆存储配置

@Configuration
public class RedisMemoryConfig {
    @Value("${spring.data.redis.host}")
    private String host;
    @Value("${spring.data.redis.port}")
    private int port;
    @Value("${spring.data.redis.password}")
    private String password;
    
    @Bean
    public RedisChatMemoryRepository redisChatMemoryRepository() {
        return RedisChatMemoryRepository.builder()
                .host(host)
                .password(password)
                .port(port)
                .build();
    }
}

功能说明

  • 通过 @Value 注入配置文件中的 Redis 连接参数
  • 创建 RedisChatMemoryRepository Bean,用于存储对话历史
  • 支持多会话隔离,每个会话 ID 对应独立的记忆存储

2.2 多模型配置(DeepSeek + Qwen)

@Configuration
public class SaaLLMConfig {
    @Value("${spring.ai.dashscope.api-key}")
    private String apiKey;
    
    // 模型名称常量
    private final String DEEPSEEK_MODEL = "deepseek-v3.2";
    private final String QWEN_MODEL = "qwen-flash";
    
    @Bean(name = "deepseek")
    public ChatClient deepSeek(RedisChatMemoryRepository redisChatMemoryRepository) {
        DashScopeChatModel dashScopeChatModel = DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder().apiKey(apiKey).build())
                .defaultOptions(DashScopeChatOptions.builder()
                        .withModel(DEEPSEEK_MODEL)
                        .build())
                .build();
        
        return ChatClient.builder(dashScopeChatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(
                        MessageWindowChatMemory.builder()
                                .chatMemoryRepository(redisChatMemoryRepository)
                                .maxMessages(10)
                                .build())
                        .build())
                .defaultOptions(ChatOptions.builder()
                        .model(DEEPSEEK_MODEL)
                        .build())
                .build();
    }
    
    @Bean(name = "qwen")
    public ChatClient qwen(RedisChatMemoryRepository redisChatMemoryRepository) {
        DashScopeChatModel dashScopeChatModel = DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder().apiKey(apiKey).build())
                .defaultOptions(DashScopeChatOptions.builder()
                        .withModel(QWEN_MODEL)
                        .build())
                .build();
        
        return ChatClient.builder(dashScopeChatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(
                        MessageWindowChatMemory.builder()
                                .chatMemoryRepository(redisChatMemoryRepository)
                                .maxMessages(10)
                                .build())
                        .build())
                .defaultOptions(ChatOptions.builder()
                        .model(QWEN_MODEL)
                        .build())
                .build();
    }
}

核心特性

  • 多模型支持:通过 @Qualifier@Bean(name) 实现多模型注入
  • 记忆集成:每个模型都配置了 MessageChatMemoryAdvisor,自动管理对话历史
  • 记忆窗口maxMessages(10) 限制每个会话最多保留 10 条消息,避免内存溢出

2.3 文档加载与向量存储

2.3.1 文档加载器
@Slf4j
@Component
public class AppDocumentLoader {
    @Value("classpath:/prompt/Gompt.txt")
    private Resource opsFile;
    
    public List<Document> loadMarkdowns() {
        TextReader textReader = new TextReader(opsFile);
        textReader.setCharset(Charset.defaultCharset());
        
        // 使用 TokenTextSplitter 进行文本分割
        List<Document> list = new TokenTextSplitter().transform(textReader.read());
        return list;
    }
}

关键点

  • 使用 TextReader 读取本地文档(支持多种格式)
  • TokenTextSplitter 对长文本进行分块,便于向量化
  • 返回 Document 列表,每个文档包含内容和元数据
2.3.2 向量存储 Bean
@Configuration
public class VectorStoreBean {
    @Resource
    private AppDocumentLoader appDocumentLoader;
    @Resource
    private EmbeddingModel embeddingModel;
    
    @Bean
    public VectorStore vectorStore() {
        // 创建 SimpleVectorStore(底层使用 Redis)
        VectorStore build = SimpleVectorStore.builder(embeddingModel)
                .build();
        
        // 加载文档并添加到向量库
        List<Document> documents = appDocumentLoader.loadMarkdowns();
        build.add(documents);
        
        return build;
    }
}

RAG 核心流程

  1. 通过 SimpleVectorStore.builder() 创建向量存储实例
  2. 调用 appDocumentLoader.loadMarkdowns() 加载本地文档
  3. 使用 build.add(documents) 将文档向量化并存储到 Redis
  4. 应用启动时自动完成知识库构建

三、RESTful API 实现

3.1 控制器层

@RestController
@RequestMapping("/aichat/stream")
@Slf4j
public class AiController {
    
    @Qualifier("deepseek")
    @Autowired
    private ChatClient deepseekModel;
    
    @Qualifier("qwen")
    @Autowired
    private ChatClient qwenModel;
    
    @Autowired
    private VectorStore vectorStore;
    
    @Value("classpath:/prompt/story-prompt.txt")
    private Resource storyPrompt;
    
    @GetMapping(value = "/deepseek")
    public Flux<String> chatDeepseek(@RequestParam String sessionId, 
                                    @RequestParam String userContent) {
        return deepseekModel.prompt()
                .system(storyPrompt)  // 系统提示词
                .user(userContent)    // 用户输入
                .advisors(message -> {
                    // 设置会话 ID,用于记忆隔离
                    if (message != null) {
                        message.param(CONVERSATION_ID, sessionId);
                    }
                })
                .advisors(RetrievalAugmentationAdvisor.builder()
                        .documentRetriever(VectorStoreDocumentRetriever.builder()
                                .vectorStore(vectorStore)
                                .build())
                        .build())
                .stream()  // 流式输出
                .content()
                .doOnError(e -> log.error("Stream error: " + e.getMessage()));
    }
    
    @GetMapping("/qwen")
    public Flux<String> chatQwen(@RequestParam String sessionId, 
                                @RequestParam String userContent) {
        return qwenModel.prompt()
                .system(storyPrompt)
                .user(userContent)
                .advisors(message -> {
                    if (message != null) {
                        message.param(CONVERSATION_ID, sessionId);
                    }
                })
                .stream()
                .content()
                .doOnError(e -> log.error("Stream error: " + e.getMessage()));
    }
}

API 特性

接口路径 方法 参数 功能
/aichat/stream/deepseek GET sessionId, userContent DeepSeek 模型流式对话(带 RAG)
/aichat/stream/qwen GET sessionId, userContent Qwen 模型流式对话

核心功能实现

  1. RAG 检索增强

    • 通过 RetrievalAugmentationAdvisor 集成向量检索
    • 用户提问时,自动从向量库检索相关文档片段
    • 将检索结果作为上下文注入到模型提示词中
  2. 记忆管理

    • message.param(CONVERSATION_ID, sessionId) 设置会话标识
    • 同一会话 ID 的对话会共享历史上下文
    • 支持多用户、多会话并行处理
  3. 流式响应

    • 使用 .stream() 返回 Flux<String> 实现流式输出
    • 支持 SSE(Server-Sent Events)协议,前端可实时接收

四、RAG 与记忆功能原理解析

4.1 检索增强生成(RAG)工作流程

用户提问 → 向量化查询 → Redis 向量库相似度检索 → 获取 top-k 相关文档
    ↓
构建提示词(系统提示 + 检索文档 + 历史对话 + 用户问题)
    ↓
调用 AI 模型生成 → 返回响应

检索过程

  • 用户输入的问题被 text-embedding-v4 模型向量化
  • 在 Redis 向量索引中执行相似度搜索(默认使用余弦相似度)
  • 返回最相关的文档片段作为上下文

4.2 对话记忆实现机制

Spring AI 通过 ChatMemory 抽象层管理对话状态:

// 记忆存储接口
public interface ChatMemory {
    void add(ChatMessage message);
    List<ChatMessage> getMessages();
    void clear();
}

// Redis 实现
public class RedisChatMemory implements ChatMemory {
    // 使用 Redis 存储,key 格式:memory:sessionId
}

记忆存储结构

  • 每个会话 ID 对应一个独立的 Redis key
  • 使用 List 结构存储消息序列
  • 支持 LRU 淘汰策略(通过 maxMessages 控制)

4.3 向量存储底层实现

SimpleVectorStore 底层使用 Redis 作为存储引擎:

public class RedisVectorStore implements VectorStore {
    // 使用 RedisSearch 模块创建向量索引
    public void createIndex(String indexName, VectorFieldSchema fieldSchema) {
        // 创建 HNSW 索引
        FT.CREATE indexName ...
    }
    
    public void add(List<Document> documents) {
        // 调用 embeddingModel 生成向量
        List<Float> vector = embeddingModel.embed(document.getContent());
        // 存储到 Redis Hash
        redis.hset(key, "vector", vector, "content", content);
    }
}

技术栈

  • Redis 7.0+ 支持向量搜索(需启用 RedisSearch 模块)
  • HNSW(Hierarchical Navigable Small World)索引算法
  • 支持余弦相似度、欧氏距离等多种相似度计算

五、部署与测试

5.1 环境要求

  • JDK 17+
  • Redis 7.0+(需启用 RedisSearch 模块)
  • Maven 3.6+
  • 通义千问 API Key(用于模型调用)

5.2 Redis 配置

启动 Redis 时需启用模块:

redis-server --loadmodule /path/to/redisearch.so

或使用 Docker:

docker run -p 6379:6379 redislabs/redisearch:latest

5.3 应用启动

mvn clean package
java -jar target/your-app.jar

5.4 API 测试

测试 RAG 功能

# 测试 DeepSeek 模型(带 RAG)
curl "http://localhost:8080/aichat/stream/deepseek?sessionId=test123&userContent=什么是GIS?"

# 测试 Qwen 模型(不带 RAG)
curl "http://localhost:8080/aichat/stream/qwen?sessionId=test123&userContent=你好"

测试记忆功能

# 第一次对话
curl "http://localhost:8080/aichat/stream/deepseek?sessionId=user1&userContent=我叫张三"

# 第二次对话(会记住上下文)
curl "http://localhost:8080/aichat/stream/deepseek?sessionId=user1&userContent=我的名字是什么?"

六、常见问题与优化建议

6.1 性能优化

向量检索优化

  • 调整 HNSW 索引参数(M、ef_construction)
  • 使用 GPU 加速嵌入模型计算
  • 对文档进行预处理(去重、关键信息提取)

内存优化

  • 合理设置 maxMessages,避免内存泄漏
  • 使用 Redis 集群分担存储压力
  • 定期清理过期会话

6.2 功能扩展

多知识库支持

@Bean(name = "vectorStoreA")
public VectorStore vectorStoreA() { ... }

@Bean(name = "vectorStoreB")
public VectorStore vectorStoreB() { ... }

// 根据业务场景选择不同的向量库

混合检索策略

  • 结合关键词检索 + 向量检索
  • 实现多路召回 + 重排序
  • 支持元数据过滤(文档来源、时间范围等)

6.3 监控与日志

  • 集成 Spring Boot Actuator 监控指标
  • 记录向量检索耗时、模型调用延迟
  • 设置告警阈值(如响应时间 > 3s)

七、总结

本文通过完整可运行的代码示例,详细介绍了 Spring AI Alibaba 集成 Redis 向量数据库实现 RAG 和记忆功能的完整方案。核心要点包括:

  1. 配置简化:Spring AI 提供了声明式配置,大幅降低集成复杂度
  2. 开箱即用:向量存储、记忆管理、模型调用等组件可快速集成
  3. 生产就绪:支持流式响应、多会话隔离、性能优化等生产特性
  4. 扩展性强:支持多模型、多知识库、自定义检索策略

该方案适用于智能客服、知识问答、文档检索等多种 AI 应用场景,具备良好的可维护性和扩展性。


源码地址:本文示例代码已整理到 GitHub,可访问 [项目地址] 获取完整可运行项目。

注意事项

  • 确保 Redis 已安装并启用 RedisSearch 模块
  • 替换配置文件中的 API Key 为实际值
  • 根据业务需求调整向量索引参数和记忆窗口大小

通过本文的实践,您可以快速构建具备 RAG 和记忆能力的 AI 应用,提升用户体验和回答准确性。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐