(9)批量生成文章并同步存入 MySQL 和 Redis

目录

利用我现有的 Java 业务逻辑,结合大模型(LLM)自动生成能力,编写一个集成测试类。


🍥一、技术选型

  1. LangChain4j (ChatLanguageModel):调用我本地的 Ollama (Gemma 3),让它扮演不同领域的学者。
  2. Spring Boot Test / CommandLineRunner:用于触发批量执行逻辑。
  3. 现有业务 Service (PostService):直接复用我写好的 publishArticle 方法。

🍥二、具体实现步骤(附流程图)

  1. 准备种子数据(学科与用户)
    在数据库里先手动准备好几个用户(User ID: 1, 2, 3...)和话题(Topic ID: 1, 2, 3...)。
  2. 编写批量生成脚本 (DataGeneratorService)
    在 src/test/java 下或者 service 包下创建一个工具类。
  3. 写一个单元测试来触发脚本

🍥三、核心代码实现

1. 文章生成Prompt设计

需要考虑能被程序解析所以提示词中采用格式约束,减少数据清洗的成本。

java 复制代码
// 在 DataGeneratorService 中定义指令模板
String promptTemplate = """
    你是一个【%s】领域的资深专家。
    请撰写一篇前沿的学术博客,要求:
    1. 标题必须具有专业性(包含行业黑话)。
    2. 正文约300字,逻辑严密,描述该领域的一个具体技术问题或趋势。
    3. 严格遵守输出格式,不得包含任何开场白:
       标题: [此处填标题]
       内容: [此处填正文]
    """;

// 调用时动态注入学科名称
String finalPrompt = String.format(promptTemplate, topic.getName());
String aiResponse = chatModel.generate(finalPrompt);

2. 数据解析逻辑

大模型的输出有时会带有不可控的空格或换行,直接解析容易报错。于是我利用较为健壮的边界搜索算法提取核心内容。

利用try-catch 捕获和边界判定。

java 复制代码
/**
 * 健壮的文本提取逻辑
 * @param text  LLM返回的全文本
 * @param start 标识符(如"标题:")
 * @param end   结束标识符(如"内容:")
 */
private String parse(String text, String start, String end) {
    try {
        int startIndex = text.indexOf(start);
        if (startIndex == -1) return "未知标题";
        startIndex += start.length();

        int endIndex = (end == null || text.indexOf(end) == -1) 
                       ? text.length() 
                       : text.indexOf(end);

        // 过滤首尾空格及特殊字符
        return text.substring(startIndex, endIndex).trim();
    } catch (Exception e) {
        log.error("解析文本块失败: {}", e.getMessage());
        return "数据解析异常";
    }
}

3. 自动化的Ingestion Pipeline(双路写入)

这是整个流程的灵魂:复用生产环境的业务逻辑。通过调用现有的 postService,确保了每一条合成数据都完美经历了 MySQL 持久化与 Redis 向量化。

利用 MyBatis 的 useGeneratedKeys,使向量库中的 articleId 元数据与 MySQL 的自增 ID 严丝合缝地关联(PostMapper.xml中)。

java 复制代码
public void generateBatchData(int countPerTopic) {
        // 1. 动态获取数据库里现有的所有分类
        List<Topic> dbTopics = topicMapper.findAll();
        if (dbTopics.isEmpty()) {
            System.err.println("❌ 数据库 topic 表是空的,请先添加分类!");
            return;
        }

        for (Topic topic:dbTopics) {
            for (int i = 0; i < countPerTopic; i++) {
                // 1. 让 AI 产生一篇伪学术文章
                String prompt = String.format(
                        "你是一个%s领域的专家。请写一篇简短的学术博客。要求:" +
                                "1. 标题新颖且具有专业性。2. 正文约300-500字,包含具体的专业术语。3. 只返回结果,格式为 标题:xxx 内容:xxx",
                        topic.getTitle()
                );

                String aiResponse = chatModel.generate(prompt);


                // 构造 Post 对象
                Post post = new Post();
                post.setTitle(parse(aiResponse, "标题:", "内容:"));
                post.setContent(parse(aiResponse, "内容:", null));

                // 2. 使用数据库里真实的 ID
                post.setTopic_id(topic.getId());

                // 设置一个默认的 userID(确保该用户在 user 表里存在)
                post.setUser_id(1L);

                // 4. ⭐ 触发核心业务逻辑
                // 此处会同步触发:MySQL保存 -> 文本切片 -> 语义向量化 -> RedisStack存入
                postService.publishArticle(post);

                System.out.println("已为分类 [" + topic.getTitle() + "] 生成文章");
            }
        }
    }

🍥四、效果展示

前端:

Redis Stack:

相关推荐
时间静止不是简史37 分钟前
生产事故排查:Redis 宕机导致补偿队列消费线程死亡,通话录音未上送业务平台
java·redis
2301_32241428044 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
catoop7 小时前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全
Web极客码7 小时前
我用 Claude 分析 Redis 哨兵日志,实现跨机房数据不一致自动对齐
数据库·redis·php
库库的数据库笔记7 小时前
国产信创数据库的MySQL兼容性深度对比解析
大数据·数据库·mysql·oceanbase·政务
姚远Oracle ACE8 小时前
为什么无法连接到 PostgreSQL?
数据库·postgresql
ss2738 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 22 PostgreSQL实例与集群
数据库·笔记·postgresql
ss2738 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 21 PostgreSQL进程与内存架构介绍
数据库·笔记·postgresql
Henry-SAP9 小时前
SAP PP模块全景概览
数据库