【Spring AI 集成 DeepSeek 实现 AI 摘要与 RAG 问答】:从原理到落地实践

🔥你好我是fengxin_rou这是我的个人主页 fengxin_rou的主页

❄️欢迎查看我的专栏我的专栏

《Java后端学习》《JAVASE基础》《JUC并发》《redis》《JVM虚拟机》《MYSQL》《黑马点评》《rabbitmq》《JavaWeb+AI的talis学习系统》《苍穹外卖》

目录

前言

[一、项目基础配置:Spring AI 对接 DeepSeek 大模型](#一、项目基础配置:Spring AI 对接 DeepSeek 大模型)

[1.1 核心配置类设计](#1.1 核心配置类设计)

[1.2 配置要点说明](#1.2 配置要点说明)

[二、AI 一键生成摘要:文章描述自动生成](#二、AI 一键生成摘要:文章描述自动生成)

[2.1 功能逻辑](#2.1 功能逻辑)

[2.2 核心实现代码](#2.2 核心实现代码)

[2.3 关键参数解析](#2.3 关键参数解析)

[三、RAG 索引构建:私有知识向量化管理](#三、RAG 索引构建:私有知识向量化管理)

[3.1 RAG 核心原理](#3.1 RAG 核心原理)

[3.2 索引全流程](#3.2 索引全流程)

[3.3 索引服务核心逻辑](#3.3 索引服务核心逻辑)

[3.4 指纹作用](#3.4 指纹作用)

[四、RAG 问答查询:流式精准回答](#四、RAG 问答查询:流式精准回答)

[4.1 问答流程](#4.1 问答流程)

[4.2 宽召回机制](#4.2 宽召回机制)

[4.3 流式问答实现代码](#4.3 流式问答实现代码)

[4.4 向量检索原理](#4.4 向量检索原理)

五、关键技术细节与优化建议

[5.1 Embedding 模型配置](#5.1 Embedding 模型配置)

[5.2 核心优化点](#5.2 核心优化点)

结语

前言

在企业级知识管理场景中,自动生成内容摘要基于私有文档的精准问答是提升信息效率的核心需求。本文基于 Spring AI 框架,整合 DeepSeek 大模型与向量数据库,完整实现 AI 一键摘要与 RAG 检索增强生成功能,覆盖配置、编码、索引、检索全流程,兼顾入门与实战。

一、项目基础配置:Spring AI 对接 DeepSeek 大模型

1.1 核心配置类设计

大模型接入的关键是通过 Spring 依赖注入明确指定模型实现,避免多模型注入冲突。@Qualifier 注解用于精准绑定 Bean,确保 ChatClient 使用 DeepSeek 模型。

复制代码
/**
 * 大模型配置类:定义ChatClient Bean并绑定DeepSeek模型
 */
@Configuration
public class LlmConfig {
    /**
     * 创建ChatClient,指定使用deepSeekChatModel
     */
    @Bean
    public ChatClient chatClient(@Qualifier("deepSeekChatModel") ChatModel chatModel) {
        return ChatClient.builder(chatModel).build();
    }
}

1.2 配置要点说明

  • @Configuration:标记为配置类,Spring 启动时加载。
  • @Bean:将方法返回值注册为 Spring 容器中的 Bean。
  • @Qualifier:解决多 ChatModel 实现注入歧义,强制使用 DeepSeek 模型。

该配置是后续所有 AI 能力的基础,统一管理大模型调用入口,降低业务层耦合。

二、AI 一键生成摘要:文章描述自动生成

2.1 功能逻辑

接收文章正文 → 拼接系统与用户提示词 → 调用 DeepSeek → 结果后处理 → 返回 50 字内精简描述。系统提示词 定义 AI 角色与规则,用户提示词传递具体任务,二者结合保证输出规范。

2.2 核心实现代码

复制代码
/**
 * AI生成知文摘要实现类
 */
@Service
@RequiredArgsConstructor
public class KnowPostDescriptionServiceImpl implements KnowPostDescriptionService {
    private final ChatClient chatClient;

    /**
     * 生成不超过50字的中文描述
     */
    public String generateDescription(String content) {
        // 非空校验
        if (content == null || content.trim().isEmpty()) {
            throw new BusinessException(ErrorCode.BAD_REQUEST, "正文内容不能为空");
        }
        // 系统提示:定义角色与输出规则
        String system = "你是中文文案编辑。请基于知文正文生成简洁有吸引力的描述,不超过50字,仅输出结果";
        // 用户提示:传递待处理内容
        String user = "正文如下:\n\n" + content + "\n\n请直接给出不超过50字的中文描述";
        try {
            // 调用大模型
            String result = chatClient.prompt()
                    .system(system)
                    .user(user)
                    .options(DeepSeekChatOptions.builder()
                            .model("deepseek-chat") // 指定模型
                            .temperature(0.8) // 创造性参数
                            .maxTokens(120) // 最大输出token
                            .build())
                    .call()
                    .content();
            return postProcess(result);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.INTERNAL_ERROR, "大模型调用失败");
        }
    }

    /**
     * 结果后处理:格式化、去冗余、截断至50字
     */
    private String postProcess(String text) {
        if (text == null) return "";
        // 标准化、去换行、合并空格
        String t = Normalizer.normalize(text, Normalizer.Form.NFKC)
                .replaceAll("\r\n|\r|\n", " ")
                .replaceAll("\\s+", " ").trim();
        // 去除首尾引号与标点
        t = t.replaceAll("^[\"'""'']+|[\"'""'']+$", "")
                .replaceAll("[。!!??;;、]+$", "");
        // 按Unicode码点截断至50字
        int limit = 50;
        int count = t.codePointCount(0, t.length());
        if (count <= limit) return t;
        StringBuilder sb = new StringBuilder();
        int i = 0, added = 0;
        while (i < t.length() && added < limit) {
            int cp = t.codePointAt(i);
            sb.appendCodePoint(cp);
            i += Character.charCount(cp);
            added++;
        }
        return sb.toString();
    }
}

2.3 关键参数解析

  • temperature:0 - 1,值越高输出越随机,摘要场景设 0.8 兼顾创意与规范。
  • maxTokens:限制输出长度,避免内容溢出。
  • 后处理:解决格式混乱、字数超标问题,保证展示友好。

三、RAG 索引构建:私有知识向量化管理

3.1 RAG 核心原理

RAG(检索增强生成)通过文档切片 + 向量存储 + 指纹校验,实现私有知识精准检索,避免大模型幻觉。指纹(SHA - 256)用于判断文档是否更新,决定是否重建索引。

3.2 索引全流程

  1. 首次上传:前端计算 SHA - 256 与 ETag → 上传 OSS → 后端存指纹到 MySQL → 触发索引 → 文档切片存入向量库并携带指纹。
  2. 查询校验:问答前比对 MySQL 与向量库指纹,一致则跳过重建。
  3. 修改重传:指纹变更 → 删除旧索引 → 生成新索引。

3.3 索引服务核心逻辑

复制代码
/**
 * RAG索引服务:确保索引最新
 */
@Service
@RequiredArgsConstructor
public class RagIndexService {
    /**
     * 确保单篇知文索引最新
     */
    public void ensureIndexed(long postId) {
        // 从MySQL获取当前指纹
        String currentSha = getCurrentShaFromDB(postId);
        // 查询向量库已存指纹
        String indexedSha = getIndexedShaFromVector(postId);
        // 指纹不一致则重建索引
        if (!currentSha.equals(indexedSha)) {
            deleteOldIndex(postId);
            buildNewIndex(postId, currentSha);
        }
    }
}

3.4 指纹作用

  • 唯一标识文档内容,避免重复索引,提升性能。
  • 保证向量库数据与源文档一致,防止检索失效。

四、RAG 问答查询:流式精准回答

4.1 问答流程

  1. 确保索引最新;
  2. 向量相似度检索上下文;
  3. 组装提示词;
  4. 流式调用大模型;
  5. 返回结果。

4.2 宽召回机制

先检索 20 条相似文档(宽召回),再按 postId 过滤,取前 5 条作为上下文,提升检索准确率。

4.3 流式问答实现代码

复制代码
/**
 * RAG问答查询服务:流式返回回答
 */
@Service
@RequiredArgsConstructor
public class RagQueryService {
    private final VectorStore vectorStore;
    private final ChatClient chatClient;
    private final RagIndexService indexService;

    /**
     * 流式问答接口
     */
    public Flux<String> streamAnswerFlux(long postId, String question, int topK, int maxTokens) {
        // 确保索引最新
        indexService.ensureIndexed(postId);
        // 检索上下文
        List<String> contexts = searchContexts(String.valueOf(postId), question, topK);
        String context = String.join("\n\n---\n\n", contexts);
        // 提示词组装
        String system = "你是中文知识助手,仅依据上下文作答,不确定则说明";
        String user = "问题:" + question + "\n\n上下文:\n" + context;
        // 流式调用大模型
        return chatClient.prompt()
                .system(system)
                .user(user)
                .options(DeepSeekChatOptions.builder()
                        .model("deepseek-chat")
                        .temperature(0.2) // 低温度保证严谨
                        .maxTokens(maxTokens)
                        .build())
                .stream()
                .content();
    }

    /**
     * 向量检索上下文:宽召回+postId过滤
     */
    private List<String> searchContexts(String postId, String query, int topK) {
        int fetchK = Math.max(topK * 3, 20);
        // 向量相似度搜索
        List<Document> docs = vectorStore.similaritySearch(
                SearchRequest.builder().query(query).topK(fetchK).build()
        );
        List<String> out = new ArrayList<>();
        for (Document d : docs) {
            // 仅保留当前帖子切片
            if (postId.equals(String.valueOf(d.getMetadata().get("postId")))) {
                out.add(d.getText());
                if (out.size() >= topK) break;
            }
        }
        return out;
    }
}

4.4 向量检索原理

用户问题经 Embedding 模型转为 1536 维向量,与向量库中文档向量计算余弦相似度,排序后取最相似结果。1536 维平衡语义表达、计算效率与存储成本。

五、关键技术细节与优化建议

5.1 Embedding 模型配置

复制代码
embedding:
  options:
    model: text-embedding-v4 # 向量模型
    dimensions: 1536 # 向量维度

5.2 核心优化点

  • 指纹校验:减少无效索引,提升系统响应速度。
  • 宽召回:提升检索覆盖率,避免遗漏关键信息。
  • 流式输出:提升用户体验,适用于长文本回答。
  • 温度参数:摘要用 0.8 增强创意,问答用 0.2 保证严谨。

结语

本文基于 Spring AI 与 DeepSeek,完整实现AI 自动摘要RAG 检索问答两大核心功能,覆盖配置、编码、索引、检索全流程。该方案可直接落地到企业知识平台、文档管理系统等场景,解决私有知识高效利用与大模型幻觉问题。后续可优化文档切片策略、引入多模型切换、提升向量检索性能,进一步增强系统能力。

相关推荐
思诺学长12 小时前
MySQL——数据库并发控制策略: 乐观锁与悲观锁
数据库
No8g攻城狮12 小时前
【异常解决】SpringBoot3 + 人大金仓 V8+MyBatis-Plus 获取新增自增 ID
数据库·mybatis·人大金仓·国产信创
鱼听禅12 小时前
CentOS搭建SVN服务器
数据库·postgresql·sqlserver
ylscode13 小时前
微软Edge浏览器启动时停止将已保存的密码加载到内存中
网络·数据库·安全·安全威胁分析
Terrence Shen17 小时前
Agent面试八股文(系列之二)
人工智能·大模型·agent·rag
电魂泡哥19 小时前
SQL出现filesort 一定慢吗
数据库·sql
muddjsv21 小时前
大中小型企业数据层配置规模分析与选型指南
数据库
Runawayliquor21 小时前
opbase:CANN 所有算子的公共地基
大数据·数据库·人工智能·算法
yangshicong1 天前
第11章:结构化输出与数据提取 —— 让 AI 直接返回你想要的数据格式
数据库·人工智能·redis·python·langchain·ai编程