|
|
@ -1,11 +1,20 @@
|
|
|
|
package com.dsideal.base.AI.Controller;
|
|
|
|
package com.dsideal.base.AI.Controller;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.dsideal.base.AI.Generator.WordGenerator;
|
|
|
|
import com.dsideal.base.AI.Model.YunNanModel;
|
|
|
|
import com.dsideal.base.AI.Model.YunNanModel;
|
|
|
|
|
|
|
|
import com.dsideal.base.Util.CallDeepSeek;
|
|
|
|
import com.jfinal.aop.Before;
|
|
|
|
import com.jfinal.aop.Before;
|
|
|
|
import com.jfinal.core.Controller;
|
|
|
|
import com.jfinal.core.Controller;
|
|
|
|
import com.jfinal.ext.interceptor.GET;
|
|
|
|
import com.jfinal.ext.interceptor.GET;
|
|
|
|
import com.jfinal.kit.PathKit;
|
|
|
|
import com.jfinal.kit.PathKit;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
public class YunNanAiController extends Controller {
|
|
|
|
public class YunNanAiController extends Controller {
|
|
|
|
YunNanModel ym = new YunNanModel();
|
|
|
|
YunNanModel ym = new YunNanModel();
|
|
|
|
|
|
|
|
|
|
|
@ -18,13 +27,124 @@ public class YunNanAiController extends Controller {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@Before({GET.class})
|
|
|
|
@Before({GET.class})
|
|
|
|
public void compareShiZhou(String shiZhouA, String shiZhouB) {
|
|
|
|
public void compareShiZhou(String shiZhouA, String shiZhouB) {
|
|
|
|
|
|
|
|
// 设置SSE响应头
|
|
|
|
|
|
|
|
getResponse().setContentType("text/event-stream");
|
|
|
|
|
|
|
|
getResponse().setCharacterEncoding("UTF-8");
|
|
|
|
|
|
|
|
getResponse().setHeader("Cache-Control", "no-cache");
|
|
|
|
|
|
|
|
getResponse().setHeader("Connection", "keep-alive");
|
|
|
|
|
|
|
|
getResponse().setHeader("Access-Control-Allow-Origin", "*");
|
|
|
|
|
|
|
|
getResponse().setHeader("Access-Control-Allow-Headers", "Cache-Control");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
PrintWriter writer = getResponse().getWriter();
|
|
|
|
|
|
|
|
|
|
|
|
String[] regions = {shiZhouA, shiZhouB};
|
|
|
|
String[] regions = {shiZhouA, shiZhouB};
|
|
|
|
// 第一步:数据获取
|
|
|
|
// 第一步:数据获取
|
|
|
|
String dataContent = ym.collectEducationData(regions);
|
|
|
|
String dataContent = ym.collectEducationData(regions);
|
|
|
|
String analysisPrompt = ym.createAnalysisPrompt(dataContent, regions);
|
|
|
|
String analysisPrompt = ym.createAnalysisPrompt(dataContent, regions);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 生成输出文件名相关信息
|
|
|
|
|
|
|
|
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
|
|
|
|
|
|
|
String regionName = String.join("与", regions);
|
|
|
|
|
|
|
|
String uploadPath = PathKit.getWebRootPath() + "/upload";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送开始事件
|
|
|
|
|
|
|
|
writer.write("data: {\"type\":\"start\",\"message\":\"开始分析数据...\"}\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:AI分析并生成Word文档
|
|
|
|
// 第二步:AI分析并生成Word文档
|
|
|
|
ym.generateWordReport(analysisPrompt, regions, PathKit.getWebRootPath() + "/upload");
|
|
|
|
CallDeepSeek.callDeepSeekStream(analysisPrompt, new CallDeepSeek.SSEListener() {
|
|
|
|
|
|
|
|
private StringBuilder fullResponse = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void onData(String data) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
fullResponse.append(data);
|
|
|
|
|
|
|
|
// 发送分析数据
|
|
|
|
|
|
|
|
String escapedData = data.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r");
|
|
|
|
|
|
|
|
writer.write("data: {\"type\":\"analysis\",\"content\":\"" + escapedData + "\"}\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void onComplete(String response) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 发送分析完成事件
|
|
|
|
|
|
|
|
writer.write("data: {\"type\":\"analysis_complete\",\"message\":\"分析完成,开始生成文档...\"}\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 使用完整的分析结果
|
|
|
|
|
|
|
|
String analysisResult = fullResponse.toString();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 生成Word文档
|
|
|
|
|
|
|
|
String wordOutputPath = uploadPath + "/" + regionName + "_教育分析报告_" + timestamp + ".docx";
|
|
|
|
|
|
|
|
String wordFilePath = WordGenerator.generateWordDocument(analysisResult, wordOutputPath, regions);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 构建返回的文件信息
|
|
|
|
|
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
|
|
|
|
|
result.put("success", true);
|
|
|
|
|
|
|
|
result.put("message", "报告生成完成");
|
|
|
|
|
|
|
|
result.put("wordFile", "/upload/" + regionName + "_教育分析报告_" + timestamp + ".docx");
|
|
|
|
|
|
|
|
result.put("wordFilePath", wordFilePath);
|
|
|
|
|
|
|
|
result.put("timestamp", timestamp);
|
|
|
|
|
|
|
|
result.put("regions", regions);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送完成事件和文件地址
|
|
|
|
|
|
|
|
String resultJson = com.jfinal.kit.JsonKit.toJson(result);
|
|
|
|
|
|
|
|
writer.write("data: {\"type\":\"complete\",\"result\":" + resultJson + "}\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送结束标记
|
|
|
|
|
|
|
|
writer.write("data: [DONE]\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 最后使用renderJson返回结果(用于非SSE客户端)
|
|
|
|
|
|
|
|
renderJson(result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
Map<String, Object> errorResult = new HashMap<>();
|
|
|
|
|
|
|
|
errorResult.put("success", false);
|
|
|
|
|
|
|
|
errorResult.put("message", "生成文档时出错: " + e.getMessage());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String errorJson = com.jfinal.kit.JsonKit.toJson(errorResult);
|
|
|
|
|
|
|
|
writer.write("data: {\"type\":\"error\",\"result\":" + errorJson + "}\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderJson(errorResult);
|
|
|
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
|
|
ex.printStackTrace();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void onError(String error) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
Map<String, Object> errorResult = new HashMap<>();
|
|
|
|
|
|
|
|
errorResult.put("success", false);
|
|
|
|
|
|
|
|
errorResult.put("message", "DeepSeek分析出错: " + error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String errorJson = com.jfinal.kit.JsonKit.toJson(errorResult);
|
|
|
|
|
|
|
|
writer.write("data: {\"type\":\"error\",\"result\":" + errorJson + "}\n\n");
|
|
|
|
|
|
|
|
writer.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderJson(errorResult);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
|
|
|
// 如果SSE失败,降级为普通JSON响应
|
|
|
|
|
|
|
|
Map<String, Object> errorResult = new HashMap<>();
|
|
|
|
|
|
|
|
errorResult.put("success", false);
|
|
|
|
|
|
|
|
errorResult.put("message", "SSE连接失败: " + e.getMessage());
|
|
|
|
|
|
|
|
renderJson(errorResult);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|