1.修改AIChat

This commit is contained in:
2025-08-18 22:09:07 +08:00
parent 6f691c6d55
commit 66fc750100

View File

@@ -88,16 +88,17 @@ public class AiChatController extends BaseController {
* 配置了5分钟的读取超时时间用于与Dify API进行通信
*/
private final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(5)) // 建连超时
.readTimeout(Duration.ofSeconds(12)) // 读超时(服务端应在此内有数据返回)
.writeTimeout(Duration.ofSeconds(12)) // 写超时
.connectTimeout(Duration.ofSeconds(5)) // 建连超时
.readTimeout(Duration.ofSeconds(12)) // 读超时(服务端应在此内有数据返回)
.writeTimeout(Duration.ofSeconds(12)) // 写超时
.retryOnConnectionFailure(true)
.build();
/** 为本次请求设置 “总超时”(含连接/读写),避免无限挂起 */
private Response execWithTimeouts(Request req, int callSecs, int readSecs, int writeSecs) throws IOException {
OkHttpClient shortClient = client.newBuilder()
.callTimeout(java.time.Duration.ofSeconds(callSecs)) // 整次调用最大时长
.readTimeout(java.time.Duration.ofSeconds(readSecs)) // 读超时(这段时间没有字节到达就超时)
.callTimeout(java.time.Duration.ofSeconds(callSecs)) // 整次调用最大时长
.readTimeout(java.time.Duration.ofSeconds(readSecs)) // 读超时(这段时间没有字节到达就超时)
.writeTimeout(java.time.Duration.ofSeconds(writeSecs)) // 写超时
.build();
return shortClient.newCall(req).execute();
@@ -173,13 +174,14 @@ public class AiChatController extends BaseController {
* @param currentUsername
* @throws IOException 当网络请求或IO操作失败时抛出
*/
private void sendToDifyAndStream(Map<String, Object> requestData, SseEmitter emitter, String currentUsername) throws IOException {
private void sendToDifyAndStream(Map<String, Object> requestData, SseEmitter emitter, String currentUsername)
throws IOException {
// 构建请求体参数
Map<String, Object> bodyMap = new HashMap<>();
bodyMap.put("query", requestData.get("query")); // 用户消息内容
bodyMap.put("user", currentUsername); // 用户标识
bodyMap.put("response_mode", "streaming"); // 设置为流式响应模式
bodyMap.put("user", currentUsername); // 用户标识
bodyMap.put("response_mode", "streaming"); // 设置为流式响应模式
// 如果请求中没有提供conversation_id则尝试获取或创建一个
if (!requestData.containsKey("conversation_id") || requestData.get("conversation_id") == null) {
@@ -232,10 +234,10 @@ public class AiChatController extends BaseController {
// 构建HTTP请求
Request httpRequest = new Request.Builder()
.url(DIFY_API_URL) // 设置请求URL
.url(DIFY_API_URL) // 设置请求URL
.addHeader("Authorization", "Bearer " + DIFY_API_KEY) // 添加认证头
.addHeader("Content-Type", "application/json") // 设置内容类型
.post(body) // 设置为POST请求
.addHeader("Content-Type", "application/json") // 设置内容类型
.post(body) // 设置为POST请求
.build();
// 执行HTTP请求
@@ -258,7 +260,8 @@ public class AiChatController extends BaseController {
try (BufferedReader reader = new BufferedReader(httpResponse.body().charStream())) {
String line;
while ((line = reader.readLine()) != null) {
if (line.isEmpty() || !line.startsWith("data:")) continue;
if (line.isEmpty() || !line.startsWith("data:"))
continue;
String jsonData = line.substring(5).trim();
if ("[DONE]".equals(jsonData)) {
break;
@@ -307,13 +310,14 @@ public class AiChatController extends BaseController {
* {
* "message_id": "msg-123",
* "user": "user-1",
* "rating": "like", // "like", "dislike", 或 null
* "rating": "like", // "like", "dislike", 或 null
* "content": "回答很好"
* }
* @return 统一响应结果
*/
@PostMapping("/feedback")
public AjaxResult submitFeedback(@org.springframework.web.bind.annotation.RequestBody Map<String, Object> feedbackData) {
public AjaxResult submitFeedback(
@org.springframework.web.bind.annotation.RequestBody Map<String, Object> feedbackData) {
// 校验必要字段
String messageId = (String) feedbackData.get("message_id");
if (messageId == null || messageId.trim().isEmpty()) {
@@ -349,16 +353,15 @@ public class AiChatController extends BaseController {
// 构建请求体(发送给 Dify
Map<String, Object> bodyMap = new HashMap<>();
bodyMap.put("user", user);
bodyMap.put("rating", rating); // 可以是 "like", "dislike", 或 null
bodyMap.put("content", content); // 可选文本反馈
bodyMap.put("rating", rating); // 可以是 "like", "dislike", 或 null
bodyMap.put("content", content); // 可选文本反馈
try {
// 序列化为 JSON
String jsonBody = mapper.writeValueAsString(bodyMap);
okhttp3.RequestBody body = okhttp3.RequestBody.create(
MediaType.get("application/json; charset=utf-8"),
jsonBody
);
jsonBody);
// 调用 Dify API
Request request = new Request.Builder()
@@ -431,12 +434,19 @@ public class AiChatController extends BaseController {
// 提取反馈信息
feedbackItem.put("id", feedbackNode.has("id") ? feedbackNode.get("id").asText() : null);
feedbackItem.put("message_id", feedbackNode.has("message_id") ? feedbackNode.get("message_id").asText() : null);
feedbackItem.put("rating", feedbackNode.has("rating") ? feedbackNode.get("rating").asText() : null);
feedbackItem.put("content", feedbackNode.has("content") ? feedbackNode.get("content").asText() : null);
feedbackItem.put("created_at", feedbackNode.has("created_at") ? feedbackNode.get("created_at").asLong() : null);
feedbackItem.put("app_id", feedbackNode.has("app_id") ? feedbackNode.get("app_id").asText() : null);
feedbackItem.put("conversation_id", feedbackNode.has("conversation_id") ? feedbackNode.get("conversation_id").asText() : null);
feedbackItem.put("message_id",
feedbackNode.has("message_id") ? feedbackNode.get("message_id").asText() : null);
feedbackItem.put("rating",
feedbackNode.has("rating") ? feedbackNode.get("rating").asText() : null);
feedbackItem.put("content",
feedbackNode.has("content") ? feedbackNode.get("content").asText() : null);
feedbackItem.put("created_at",
feedbackNode.has("created_at") ? feedbackNode.get("created_at").asLong() : null);
feedbackItem.put("app_id",
feedbackNode.has("app_id") ? feedbackNode.get("app_id").asText() : null);
feedbackItem.put("conversation_id",
feedbackNode.has("conversation_id") ? feedbackNode.get("conversation_id").asText()
: null);
feedbackList.add(feedbackItem);
}
@@ -472,13 +482,13 @@ public class AiChatController extends BaseController {
}
}
// 权限标识为辅导员
// 权限标识为辅导员
@PreAuthorize("@ss.hasPermi('cph:teacher:list')")
@GetMapping("/getMessagesToAdmin")
public AjaxResult getMessagesToAdmin(@RequestParam String user,
@RequestParam(required = false) String firstId,
@RequestParam(defaultValue = "20") int limit,
@RequestParam(defaultValue = "-updated_at") String sortBy) {
@RequestParam(required = false) String firstId,
@RequestParam(defaultValue = "20") int limit,
@RequestParam(defaultValue = "-updated_at") String sortBy) {
try {
List<ConversationDTO> conversations = getConversations(user);
@@ -501,14 +511,15 @@ public class AiChatController extends BaseController {
}
}
// 权限标识为学生
// 权限标识为学生
@GetMapping("/getMessagesToUser")
public AjaxResult getMessagesToUser(@RequestParam(required = false) String firstId,
@RequestParam(defaultValue = "20") int limit,
@RequestParam(defaultValue = "-updated_at") String sortBy) {
@RequestParam(defaultValue = "20") int limit,
@RequestParam(defaultValue = "-updated_at") String sortBy) {
try {
String user = SecurityUtils.getLoginUser().getUsername();
List<ConversationDTO> conversations = getConversations(user);
if (conversations == null || conversations.isEmpty()) {
@@ -516,6 +527,7 @@ public class AiChatController extends BaseController {
}
String conversation_id = conversations.get(0).getId();
Map<String, Object> result = getConversationHistoryMessages(conversation_id, user, firstId, limit);
AjaxResult successResult = success(result);
@@ -529,11 +541,11 @@ public class AiChatController extends BaseController {
}
}
/*
* 获取会话列表
* */
public List<ConversationDTO> getConversations(String user, String lastId, int limit, String sortBy) throws IOException {
*/
public List<ConversationDTO> getConversations(String user, String lastId, int limit, String sortBy)
throws IOException {
// 构建带查询参数的 URL
HttpUrl.Builder urlBuilder = HttpUrl.parse(DIFY_CONVERSATIONS_URL).newBuilder();
urlBuilder.addQueryParameter("user", user);
@@ -599,8 +611,7 @@ public class AiChatController extends BaseController {
return getConversations(user, null, limit, sortBy);
}
//获取历史消息
// 获取历史消息
private Map<String, Object> getConversationHistoryMessages(
String conversationId,
String user,
@@ -688,11 +699,6 @@ public class AiChatController extends BaseController {
return result;
}
/**
* 文件上传接口
* <p>
@@ -706,7 +712,7 @@ public class AiChatController extends BaseController {
*/
@PostMapping("/files/upload")
public AjaxResult uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam("user") String user) {
@RequestParam("user") String user) {
try {
// 检查文件是否为空
if (file.isEmpty()) {
@@ -718,7 +724,7 @@ public class AiChatController extends BaseController {
.setType(MultipartBody.FORM)
.addFormDataPart("user", user)
.addFormDataPart("file", file.getOriginalFilename(),
RequestBody.create(MediaType.parse("application/octet-stream"),file.getBytes()))
RequestBody.create(MediaType.parse("application/octet-stream"), file.getBytes()))
.build();
// 构建请求