|
|
|
@ -1,55 +1,40 @@
|
|
|
|
|
package com.dsideal.base.Tools;
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
import com.dsideal.base.Tools.Util.CallDeepSeek;
|
|
|
|
|
import com.dsideal.base.Tools.Util.PptAIKit;
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* PPT生成器 - 负责生成分析报告的PPT演示文稿
|
|
|
|
|
*/
|
|
|
|
|
public class PptGenerator extends PptAIKit {
|
|
|
|
|
public class PptGenerator {
|
|
|
|
|
|
|
|
|
|
private static final String PPT_API_URL = "https://open.docmee.cn/api/ppt/generatePptx";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成PPT演示文稿
|
|
|
|
|
* @param analysisContent 分析内容
|
|
|
|
|
* @param analysisContent 分析内容(与Word文档相同的内容)
|
|
|
|
|
* @param regions 对比地区
|
|
|
|
|
* @param token API访问令牌
|
|
|
|
|
*/
|
|
|
|
|
public static void generatePptPresentation(String analysisContent, String[] regions) {
|
|
|
|
|
public static void generatePptPresentation(String analysisContent, String[] regions, String token) {
|
|
|
|
|
try {
|
|
|
|
|
String uid = "test";
|
|
|
|
|
|
|
|
|
|
// 生成简化的PPT提示词
|
|
|
|
|
String simplifiedPptPrompt = createPptPrompt(analysisContent, regions);
|
|
|
|
|
if (simplifiedPptPrompt == null) {
|
|
|
|
|
System.err.println("无法生成PPT提示词,跳过PPT生成");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建API token
|
|
|
|
|
String apiToken = PptAIKit.createApiToken(uid, null);
|
|
|
|
|
System.out.println("api token: " + apiToken);
|
|
|
|
|
|
|
|
|
|
// 生成大纲
|
|
|
|
|
System.out.println("\n\n========== 正在生成大纲 ==========");
|
|
|
|
|
System.out.println("提示词长度: " + simplifiedPptPrompt.length());
|
|
|
|
|
String outline = PptAIKit.generateOutline(apiToken, null, null, simplifiedPptPrompt);
|
|
|
|
|
|
|
|
|
|
// 生成大纲内容
|
|
|
|
|
System.out.println("\n\n========== 正在生成大纲内容 ==========");
|
|
|
|
|
String markdown = PptAIKit.generateContent(apiToken, outline, null, simplifiedPptPrompt);
|
|
|
|
|
// 将分析内容转换为Markdown格式
|
|
|
|
|
String markdownContent = convertToMarkdown(analysisContent, regions);
|
|
|
|
|
|
|
|
|
|
// 随机选择模板
|
|
|
|
|
System.out.println("\n\n========== 随机选择模板 ==========");
|
|
|
|
|
String templateId = PptAIKit.randomOneTemplateId(apiToken);
|
|
|
|
|
System.out.println("模板ID: " + templateId);
|
|
|
|
|
// 调用docmee API生成PPT
|
|
|
|
|
String pptFileUrl = callDocmeeApi(markdownContent, token);
|
|
|
|
|
|
|
|
|
|
// 生成PPT
|
|
|
|
|
System.out.println("\n\n========== 正在生成PPT ==========");
|
|
|
|
|
JSONObject pptInfo = PptAIKit.generatePptx(apiToken, templateId, markdown, false);
|
|
|
|
|
String pptId = pptInfo.getString("id");
|
|
|
|
|
System.out.println("pptId: " + pptId);
|
|
|
|
|
System.out.println("ppt主题:" + pptInfo.getString("subject"));
|
|
|
|
|
System.out.println("ppt封面:" + pptInfo.getString("coverUrl") + "?token=" + apiToken);
|
|
|
|
|
if (pptFileUrl != null && !pptFileUrl.trim().isEmpty()) {
|
|
|
|
|
System.out.println("PPT生成成功!");
|
|
|
|
|
System.out.println("PPT文件下载地址: " + pptFileUrl);
|
|
|
|
|
} else {
|
|
|
|
|
System.err.println("PPT生成失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("生成PPT时出错: " + e.getMessage());
|
|
|
|
@ -58,55 +43,156 @@ public class PptGenerator extends PptAIKit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建PPT生成提示词
|
|
|
|
|
* @param dataContent 数据内容
|
|
|
|
|
* 将分析内容转换为Markdown格式
|
|
|
|
|
* @param analysisContent 分析内容
|
|
|
|
|
* @param regions 对比地区
|
|
|
|
|
* @return PPT提示词
|
|
|
|
|
* @return Markdown格式的内容
|
|
|
|
|
*/
|
|
|
|
|
private static String createPptPrompt(String dataContent, String[] regions) {
|
|
|
|
|
private static String convertToMarkdown(String analysisContent, String[] regions) {
|
|
|
|
|
StringBuilder markdown = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
// 添加标题
|
|
|
|
|
String title = generateReportTitle(regions);
|
|
|
|
|
markdown.append("# ").append(title).append("\n\n");
|
|
|
|
|
|
|
|
|
|
// 处理分析内容
|
|
|
|
|
String[] lines = analysisContent.split("\n");
|
|
|
|
|
|
|
|
|
|
for (String line : lines) {
|
|
|
|
|
if (line.trim().isEmpty()) {
|
|
|
|
|
markdown.append("\n");
|
|
|
|
|
} else if (isTitle(line)) {
|
|
|
|
|
// 根据标题级别添加Markdown标题
|
|
|
|
|
if (line.matches("^\\d+\\..+")) {
|
|
|
|
|
markdown.append("## ").append(line).append("\n\n");
|
|
|
|
|
} else if (line.matches("^\\d+\\.\\d+.+")) {
|
|
|
|
|
markdown.append("### ").append(line).append("\n\n");
|
|
|
|
|
} else if (line.matches("^\\d+\\.\\d+\\.\\d+.+")) {
|
|
|
|
|
markdown.append("#### ").append(line).append("\n\n");
|
|
|
|
|
} else {
|
|
|
|
|
markdown.append("## ").append(line).append("\n\n");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 普通内容,处理列表项
|
|
|
|
|
if (line.trim().startsWith("-") || line.trim().startsWith("•")) {
|
|
|
|
|
markdown.append("- ").append(line.trim().substring(1).trim()).append("\n");
|
|
|
|
|
} else {
|
|
|
|
|
markdown.append(line).append("\n\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return markdown.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成报告标题
|
|
|
|
|
*/
|
|
|
|
|
private static String generateReportTitle(String[] regions) {
|
|
|
|
|
if (regions != null && regions.length >= 2) {
|
|
|
|
|
return String.join("与", regions) + "教育资源配置对比分析报告";
|
|
|
|
|
} else {
|
|
|
|
|
return "教育资源配置对比分析报告";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 判断是否为标题行
|
|
|
|
|
*/
|
|
|
|
|
private static boolean isTitle(String line) {
|
|
|
|
|
return line.matches("^\\d+\\..+") ||
|
|
|
|
|
line.matches("^\\d+\\.\\d+.+") ||
|
|
|
|
|
line.matches("^\\d+\\.\\d+\\.\\d+.+") ||
|
|
|
|
|
line.trim().matches("^(执行摘要|数据概览|详细对比分析|问题识别|建议与对策|结论).*");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 调用docmee API生成PPT
|
|
|
|
|
* @param markdownContent Markdown内容
|
|
|
|
|
* @param token API令牌
|
|
|
|
|
* @return PPT文件下载URL
|
|
|
|
|
*/
|
|
|
|
|
private static String callDocmeeApi(String markdownContent, String token) {
|
|
|
|
|
try {
|
|
|
|
|
// 构建给DeepSeek的精简提示词
|
|
|
|
|
String deepseekPrompt = "你是一位专业的教育数据分析专家,请将以下教育资源配置数据进行精简总结," +
|
|
|
|
|
"提取关键信息和对比要点,控制在300字以内,重点突出" + String.join("与", regions) + "的对比差异:\n\n" +
|
|
|
|
|
dataContent;
|
|
|
|
|
URL url = new URL(PPT_API_URL);
|
|
|
|
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
|
|
|
|
|
|
|
// 设置请求方法和头部
|
|
|
|
|
connection.setRequestMethod("POST");
|
|
|
|
|
connection.setRequestProperty("Content-Type", "application/json");
|
|
|
|
|
connection.setRequestProperty("token", token);
|
|
|
|
|
connection.setDoOutput(true);
|
|
|
|
|
|
|
|
|
|
// 构建请求体
|
|
|
|
|
JSONObject requestBody = new JSONObject();
|
|
|
|
|
requestBody.put("outlineContentMarkdown", markdownContent);
|
|
|
|
|
requestBody.put("pptxProperty", false); // 不返回PPT数据结构
|
|
|
|
|
// templateId 和 notes 为非必填,可以根据需要添加
|
|
|
|
|
|
|
|
|
|
// 发送请求
|
|
|
|
|
try (OutputStream os = connection.getOutputStream()) {
|
|
|
|
|
byte[] input = requestBody.toJSONString().getBytes(StandardCharsets.UTF_8);
|
|
|
|
|
os.write(input, 0, input.length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 读取响应
|
|
|
|
|
int responseCode = connection.getResponseCode();
|
|
|
|
|
System.out.println("API响应状态码: " + responseCode);
|
|
|
|
|
|
|
|
|
|
if (responseCode >= 200 && responseCode < 300) {
|
|
|
|
|
StringBuilder response = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
try (BufferedReader br = new BufferedReader(
|
|
|
|
|
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = br.readLine()) != null) {
|
|
|
|
|
response.append(line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析响应JSON
|
|
|
|
|
JSONObject responseJson = JSONObject.parseObject(response.toString());
|
|
|
|
|
|
|
|
|
|
System.out.println("正在调用 DeepSeek 精简数据...");
|
|
|
|
|
if (responseJson.getIntValue("code") == 0) {
|
|
|
|
|
JSONObject data = responseJson.getJSONObject("data");
|
|
|
|
|
if (data != null) {
|
|
|
|
|
JSONObject pptInfo = data.getJSONObject("pptInfo");
|
|
|
|
|
if (pptInfo != null) {
|
|
|
|
|
String fileUrl = pptInfo.getString("fileUrl");
|
|
|
|
|
String coverUrl = pptInfo.getString("coverUrl");
|
|
|
|
|
String pptId = pptInfo.getString("id");
|
|
|
|
|
|
|
|
|
|
// 调用DeepSeek获取精简内容
|
|
|
|
|
String simplifiedContent = CallDeepSeek.callDeepSeek(deepseekPrompt);
|
|
|
|
|
System.out.println("PPT ID: " + pptId);
|
|
|
|
|
System.out.println("PPT封面: " + coverUrl);
|
|
|
|
|
|
|
|
|
|
if (simplifiedContent != null && !simplifiedContent.trim().isEmpty()) {
|
|
|
|
|
System.out.println("DeepSeek 精简完成,精简后长度: " + simplifiedContent.length());
|
|
|
|
|
return fileUrl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
System.err.println("API返回错误: " + responseJson.getString("message"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 使用精简后的内容构建PPT提示词
|
|
|
|
|
return buildPptPrompt(regions, simplifiedContent);
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("DeepSeek 调用失败,使用基础提示词");
|
|
|
|
|
// 读取错误响应
|
|
|
|
|
StringBuilder errorResponse = new StringBuilder();
|
|
|
|
|
try (BufferedReader br = new BufferedReader(
|
|
|
|
|
new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) {
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = br.readLine()) != null) {
|
|
|
|
|
errorResponse.append(line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.err.println("API调用失败,状态码: " + responseCode);
|
|
|
|
|
System.err.println("错误信息: " + errorResponse.toString());
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("调用 DeepSeek 精简数据时出错: " + e.getMessage());
|
|
|
|
|
System.err.println("调用docmee API时出错: " + e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构建PPT提示词
|
|
|
|
|
*/
|
|
|
|
|
private static String buildPptPrompt(String[] regions, String simplifiedContent) {
|
|
|
|
|
return "请基于以下教育资源配置数据,为" + String.join("与", regions) +
|
|
|
|
|
"教育资源配置对比分析创建一个专业的PPT大纲。\n\n" +
|
|
|
|
|
"PPT应包含以下主要部分:\n" +
|
|
|
|
|
"1. 封面 - 标题和基本信息\n" +
|
|
|
|
|
"2. 目录 - 分析框架\n" +
|
|
|
|
|
"3. 数据概览 - 关键指标对比\n" +
|
|
|
|
|
"4. 详细分析 - 各维度深入对比\n" +
|
|
|
|
|
"5. 问题识别 - 存在的主要问题\n" +
|
|
|
|
|
"6. 建议方案 - 改进措施\n" +
|
|
|
|
|
"7. 总结 - 结论和展望\n\n" +
|
|
|
|
|
"请确保内容简洁明了,适合PPT展示。\n\n" +
|
|
|
|
|
"=== 精简后的关键数据 ===\n" + simplifiedContent;
|
|
|
|
|
}
|
|
|
|
|
}
|