后台文章发布页添加 AI 自动生成摘要功能

文章目录

  • [后台文章发布页添加 AI 自动生成摘要功能](#后台文章发布页添加 AI 自动生成摘要功能)
    • 需求
    • 实现思路
    • 后端实现
      • [1. AI 服务类添加摘要生成方法](#1. AI 服务类添加摘要生成方法)
      • [2. 控制器添加接口](#2. 控制器添加接口)
    • 前端实现
      • [1. API 函数](#1. API 函数)
      • [2. 页面添加按钮](#2. 页面添加按钮)
      • [3. 添加逻辑](#3. 添加逻辑)
    • 遇到的问题
      • [1. 超时问题](#1. 超时问题)
      • [2. AI 返回格式问题](#2. AI 返回格式问题)
      • [3. 文章内容过长](#3. 文章内容过长)
    • 使用效果
    • 总结

后台文章发布页添加 AI 自动生成摘要功能

之前给博客加了个 AI 智能助手,用户搜索时可以对话。最近又加了个小功能:在后台写文章时,可以一键让 AI 生成文章摘要,不用自己手写了。

需求

后台文章发布页面有个「文章摘要」字段,最多 100 字。之前都是手动写,或者从文章内容里截取前 100 字。现在想加个按钮,点击后 AI 自动读取文章内容,生成一段 100 字左右的摘要。

实现思路

  • 后端:新增一个接口,接收文章内容,调用 AI API(非流式,同步返回),生成摘要
  • 前端:在「文章摘要」输入框旁边加个「AI 生成」按钮,点击后调用接口,把返回的摘要填入输入框

后端实现

1. AI 服务类添加摘要生成方法

AiService.java 中添加一个非流式的方法:

java 复制代码
/**
 * 生成文章摘要(非流式,同步调用)
 *
 * @param content 文章内容
 * @return 100字左右的摘要
 */
public String generateSummary(String content) {
    // 截取前 3000 字,避免 token 过长
    String truncated = content.length() > 3000 ? content.substring(0, 3000) : content;

    JSONArray messagesArray = new JSONArray();

    // 系统提示词:要求生成 100 字摘要,不要 Markdown,直接输出文本
    JSONObject systemMsg = new JSONObject();
    systemMsg.put("role", "system");
    systemMsg.put("content", "你是一个文章摘要生成助手。请根据用户提供的文章内容,生成一段100字左右的中文摘要。" +
            "要求:简洁明了,提炼核心内容,不要使用 Markdown 格式,不要加任何前缀(如"摘要:"),直接输出摘要文本。");
    messagesArray.add(systemMsg);

    // 用户消息:文章内容
    JSONObject userMsg = new JSONObject();
    userMsg.put("role", "user");
    userMsg.put("content", "请为以下文章生成100字左右的摘要:\n\n" + truncated);
    messagesArray.add(userMsg);

    JSONObject requestBody = new JSONObject();
    requestBody.put("model", deepSeekProperties.getModel());
    requestBody.put("messages", messagesArray);
    requestBody.put("stream", false); // 非流式,同步返回
    requestBody.put("temperature", 0.3); // 降低随机性,更稳定
    requestBody.put("max_tokens", 200); // 最多 200 token,约 100 字

    Request request = new Request.Builder()
            .url(deepSeekProperties.getApiUrl())
            .addHeader("Authorization", "Bearer " + deepSeekProperties.getApiKey())
            .addHeader("Content-Type", "application/json")
            .post(RequestBody.create(requestBody.toJSONString(), MediaType.parse("application/json")))
            .build();

    try (Response response = httpClient.newCall(request).execute()) {
        if (!response.isSuccessful()) {
            String body = response.body() != null ? response.body().string() : "";
            log.error("AI 摘要生成失败: {} {}", response.code(), body);
            throw new RuntimeException("AI 摘要生成失败: " + response.code());
        }
        String responseBody = response.body().string();
        JSONObject jsonResponse = JSON.parseObject(responseBody);
        JSONArray choices = jsonResponse.getJSONArray("choices");
        if (choices != null && !choices.isEmpty()) {
            JSONObject message = choices.getJSONObject(0).getJSONObject("message");
            if (message != null) {
                String summary = message.getString("content");
                // 去除首尾空白,截取前 100 字
                if (summary != null) {
                    summary = summary.trim();
                    if (summary.length() > 100) {
                        summary = summary.substring(0, 100);
                    }
                    return summary;
                }
            }
        }
        return "";
    } catch (IOException e) {
        log.error("AI 摘要生成异常", e);
        throw new RuntimeException("AI 摘要生成异常: " + e.getMessage());
    }
}

关键点

  • stream: false:非流式调用,同步返回结果
  • temperature: 0.3:降低随机性,摘要更稳定
  • max_tokens: 200:限制输出长度,约 100 字
  • 截取前 3000 字:避免文章太长导致 token 超限
  • 系统提示词明确要求:不要 Markdown,不要前缀,直接输出摘要文本

2. 控制器添加接口

AiController.java 中添加:

java 复制代码
/**
 * AI 生成文章摘要
 *
 * @param body 请求体,包含 content 字段(文章内容)
 * @return 100字左右的摘要
 */
@ApiOperation(value = "AI 生成文章摘要")
@PostMapping("/admin/ai/summary")
public Result<String> generateSummary(@RequestBody Map<String, String> body) {
    String content = body.get("content");
    if (content == null || content.trim().isEmpty()) {
        return Result.fail("文章内容不能为空");
    }
    String summary = aiService.generateSummary(content);
    return Result.success(summary);
}

接口放在 /admin/ 路径下,需要登录才能访问(后台管理功能)。

前端实现

1. API 函数

api/article/index.ts 中添加:

typescript 复制代码
/**
 * AI 生成文章摘要
 * @param content 文章内容
 * @returns 摘要文本
 */
export function generateAiSummary(content: string): AxiosPromise<Result<string>> {
  return request({
    url: "/admin/ai/summary",
    method: "post",
    timeout: 60000, // AI 调用可能需要较长时间,设置 60 秒超时
    data: { content },
  });
}

注意设置了 timeout: 60000(60 秒),因为 AI 调用可能需要几秒到十几秒。

2. 页面添加按钮

views/blog/article/write.vue 中,找到「文章摘要」的表单项,修改为:

vue 复制代码
<el-form-item label="文章摘要" prop="articleDesc">
    <div style="display: flex; flex-direction: column; gap: 8px;">
        <el-input v-model="articleForm.articleDesc" resize="none" maxlength="100"
            :autosize="{ minRows: 5, maxRows: 5 }" style="width: 300px" show-word-limit
            type="textarea" />
        <el-button type="primary" :loading="aiLoading" :icon="MagicStick"
            style="width: 120px;" @click="handleAiSummary">
            {{ aiLoading ? 'AI生成中...' : 'AI 生成' }}
        </el-button>
    </div>
</el-form-item>

按钮使用了 Element Plus 的 MagicStick 图标(魔法棒),点击时显示 loading 状态。

3. 添加逻辑

在 script 部分:

typescript 复制代码
import { generateAiSummary } from "@/api/article";
import { MagicStick } from '@element-plus/icons-vue';

// 添加 loading 状态
const aiLoading = ref(false);

// AI 生成摘要的处理函数
const handleAiSummary = async () => {
    const content = articleForm.value.articleContent;
    if (!content || content.trim() === '') {
        ElMessage.warning('请先编写文章内容');
        return;
    }
    aiLoading.value = true;
    try {
        const { data } = await generateAiSummary(content);
        if (data.flag && data.data) {
            articleForm.value.articleDesc = data.data;
            ElMessage.success('AI 摘要生成成功');
        } else {
            ElMessage.error(data.msg || 'AI 摘要生成失败');
        }
    } catch (e: any) {
        ElMessage.error('AI 摘要生成失败,请稍后重试');
    } finally {
        aiLoading.value = false;
    }
};

逻辑

  1. 检查文章内容是否为空
  2. 调用 API,显示 loading
  3. 成功后把返回的摘要填入 articleForm.articleDesc
  4. 失败显示错误提示

遇到的问题

1. 超时问题

问题:前端请求超时(默认 10 秒),AI 调用可能需要 10-20 秒。

解决 :在 API 函数中设置 timeout: 60000,单个请求覆盖全局超时设置。

2. AI 返回格式问题

问题 :AI 可能返回带 Markdown 格式的文本(如 **摘要:**这是内容),或者带前缀「摘要:」。

解决:在系统提示词中明确要求「不要使用 Markdown 格式,不要加任何前缀,直接输出摘要文本」。后端再截取前 100 字,确保长度符合要求。

3. 文章内容过长

问题:文章可能有几万字,全部传给 AI 会超出 token 限制。

解决:后端截取前 3000 字,足够生成摘要,也避免 token 超限。

使用效果

  1. 在后台写文章页面,先写好文章内容
  2. 点击「发布文章」打开弹窗
  3. 在「文章摘要」下方点击「AI 生成」按钮
  4. 等待几秒(按钮显示「AI生成中...」)
  5. AI 自动生成 100 字摘要并填入输入框
  6. 可以手动修改后再发布

总结

这个功能实现起来不算复杂:

  1. 后端:新增一个非流式的 AI 调用方法,专门用于生成摘要
  2. 前端:加个按钮,调用 API,把结果填入输入框

关键是:

  • 系统提示词要明确(不要 Markdown,不要前缀)
  • 设置合适的 temperaturemax_tokens
  • 前端设置足够的超时时间
  • 处理错误情况,给用户友好提示

现在写文章时,摘要可以一键生成,省了不少时间。如果生成的不满意,还可以手动修改。

相关推荐
9呀7 小时前
【ros2】OccupancyGrid消息里的resolution
人工智能·机器人
DuHz7 小时前
通过超宽带信号估计位置——论文精读
论文阅读·人工智能·机器学习·自动驾驶·汽车
静听松涛1337 小时前
大语言模型长上下文技术突破:如何处理超长文本的注意力机制与架构图解
人工智能·语言模型·架构
我送炭你添花7 小时前
电子世界的奇妙冒险:从一个电阻开始(系列目录)
人工智能·单片机·嵌入式硬件·fpga开发
数据智能老司机7 小时前
用于构建多智能体系统的智能体架构模式——可解释性与合规性的智能体模式
人工智能·llm·agent
数据智能老司机7 小时前
用于构建多智能体系统的智能体架构模式——人类—智能体交互模式
人工智能·llm·agent
一个处女座的程序猿7 小时前
LLMs之Benchmark:《CL-bench: A Benchmark for Context Learn》翻译与解读
人工智能·benchmark·llms
Node全栈8 小时前
AI时代,不准备换行吗?
人工智能
数据智能老司机8 小时前
用于构建多智能体系统的智能体架构模式——高级适配:打造具备学习能力的智能体
人工智能·llm·agent