diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java index 9544f950..8dd087d8 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java @@ -89,6 +89,7 @@ public class CaseAiChatApi extends ApiBaseController { @PostMapping("/likeMsg") public JsonResponse likeMsg(@RequestBody CaseAiMsgLikeDto caseAiMsgLikeDto) { try { + caseAiMsgLikeDto.setOperation(true); if (caseAiChatService.msgFeedback(caseAiMsgLikeDto)) { return success(true, "保存成功"); } else { @@ -109,6 +110,7 @@ public class CaseAiChatApi extends ApiBaseController { @PostMapping("/msgFeedback") public JsonResponse msgFeedback(@RequestBody CaseAiMsgLikeDto caseAiMsgLikeDto) { try { + caseAiMsgLikeDto.setOperation(false); if (caseAiChatService.msgFeedback(caseAiMsgLikeDto)) { return success(true, "保存成功"); } else { diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java index 2f533b70..6384a76a 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java @@ -21,4 +21,12 @@ public class CaseAiMsgLikeDto { * 反馈 */ private String feedback; + + /** + * 操作 + * true: 点踩 + * false: 反馈 + * 为空:其他情况 + */ + private Boolean operation; } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java index 8916dbfa..34ab36bc 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java @@ -130,7 +130,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { // 2. 查询历史 List historyMessages = elasticSearchIndexService.queryData(conversationId); - + // 3. 构建请求参数 String userId = currentUser.getCode(); @@ -165,7 +165,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { } String chatParamStr = chatParam.toJSONString(); log.info("案例问答接口请求参数: [{}]", chatParamStr); - + // 4. 设置请求头 String accessToken; try { @@ -195,7 +195,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { RequestBody bodyRequestBody = RequestBody.create(chatParamStr, MediaType.parse("application/json")); builder.post(bodyRequestBody); Request request = builder.build(); - + // 7. 创建事件监听器 EventSourceListener listener = new EventSourceListener() { @Override @@ -257,14 +257,14 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { @Override public void onEvent(@NotNull EventSource eventSource, @Nullable String id, @Nullable String type, @NotNull String data) { log.info("调用接口 [{}] 监听数据 id: [{}] type: [{}] data: [{}]", request.url(), id, type, data); - + try { // 解析返回的数据 JSONObject jsonData = JSONObject.parseObject(data); if (jsonData.getBooleanValue("success") && jsonData.getIntValue("code") == 0) { JSONObject responseData = jsonData.getJSONObject("data"); Integer status = responseData.getInteger("status"); - + if (status != null) { CaseAiChatStatusEnum statusEnum = CaseAiChatStatusEnum.getByCode(status); if (statusEnum == CaseAiChatStatusEnum.REFERS) { // 返回引用文件 @@ -350,7 +350,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { saveConversationData(conversationData); } }; - + // 8. 执行HTTP请求 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(60, TimeUnit.SECONDS) @@ -361,16 +361,16 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { .build(); EventSource.Factory factory = EventSources.createFactory(client); factory.newEventSource(request, listener); - + return sseEmitter; } - + /** * 获取或创建会话ID */ private String getOrCreateConversationId(CaseAiChatDto caseAiChatDto, CurrentUser currentUser) { String conversationId = caseAiChatDto.getConversationId(); - + if (StringUtils.isEmpty(conversationId)) { // 新会话,调用创建会话接口 String conversationName = "AI案例咨询-" + LocalDateTime.now().toString(); @@ -388,39 +388,39 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { String url = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/conversation"; HttpPost httpPost = new HttpPost(url); - + // 设置请求头 String accessToken = aiAccessTokenService.getAccessToken(); String apiCode = caseAiProperties.getChatApiCode(); httpPost.setHeader("access_token", accessToken); httpPost.setHeader("X-AI-ApiCode", apiCode); httpPost.setHeader("Content-Type", "application/json"); - + // 设置请求体 JSONObject requestBody = new JSONObject(); requestBody.put("userId", userId); requestBody.put("name", conversationName); StringEntity entity = new StringEntity(requestBody.toJSONString(), StandardCharsets.UTF_8); httpPost.setEntity(entity); - + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - + if (statusCode == 200) { JSONObject result = JSONObject.parseObject(responseBody); if (result.getIntValue("code") == 0 && result.getBooleanValue("success")) { JSONObject data = result.getJSONObject("data"); String aiConversationId = data.getString("id"); String name = data.getString("name"); - + // 保存到数据库 CaseAiConversations conversation = new CaseAiConversations(); conversation.setAiConversationId(aiConversationId); conversation.setConversationName(name); conversation.setConversationUser(userId); caseAiConversationsDao.save(conversation); - + log.info("创建AI会话成功,aiConversationId: {}, name: {}", aiConversationId, name); return conversation; } else { @@ -503,44 +503,44 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { CaseAiMessageVo messageVo = new CaseAiMessageVo(); messageVo.setQuery((String) sourceMap.get("query")); messageVo.setAnswer((String) sourceMap.get("answer")); - + // 解析 suggestions Object suggestionsObj = sourceMap.get("suggestions"); if (suggestionsObj instanceof List) { messageVo.setSuggestions((List) suggestionsObj); } - + // 解析 caseRefer Object caseReferObj = sourceMap.get("caseRefer"); if (caseReferObj instanceof List) { List caseReferList = new ArrayList<>(); List> caseReferMaps = (List>) caseReferObj; - + for (Map caseReferMap : caseReferMaps) { CaseReferVo caseRefer = new CaseReferVo(); caseRefer.setCaseId((String) caseReferMap.get("caseId")); caseRefer.setTitle((String) caseReferMap.get("title")); caseRefer.setAuthorName((String) caseReferMap.get("authorName")); caseRefer.setContent((String) caseReferMap.get("content")); - + // 解析 keywords Object keywordsObj = caseReferMap.get("keywords"); if (keywordsObj instanceof List) { caseRefer.setKeywords((List) keywordsObj); } - + caseReferList.add(caseRefer); } messageVo.setCaseRefer(caseReferList); } - + return messageVo; } catch (Exception e) { log.error("解析ES消息数据异常", e); return null; } } - + /** * 处理文件引用并构建返给前端的响应数据 */ @@ -549,7 +549,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { // 先处理文件引用,收集CaseReferVo数据 List currentCaseRefers = new ArrayList<>(); Set docIds = new HashSet<>(); - + JSONObject fileRefer = responseData.getJSONObject("fileRefer"); if (fileRefer != null && fileRefer.containsKey("files")) { JSONArray files = fileRefer.getJSONArray("files"); @@ -567,13 +567,13 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { } } } - + // 构建返给前端的数据结构 JSONObject data = new JSONObject(); data.put("status", 0); data.put("conversationId", conversationData.getConversationId()); data.put("content", responseData.getString("content")); - + // 添加处理后的案例引用数据 JSONArray caseReferArray = new JSONArray(); for (CaseReferVo caseRefer : currentCaseRefers) { @@ -589,11 +589,11 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { caseReferArray.add(caseReferObj); } - + // 构建新的fileRefer结构,包含案例引用 JSONObject newFileRefer = new JSONObject(); newFileRefer.put("caseRefers", caseReferArray); - + // 保留原始的docs和files信息(如果需要) if (fileRefer != null) { if (fileRefer.containsKey("docs")) { @@ -603,19 +603,19 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { newFileRefer.put("files", fileRefer.get("files")); } } - + data.put("fileRefer", newFileRefer); data.put("suggestions", responseData.get("suggestions")); - + log.info("处理文件引用成功,返回 {} 个案例引用", currentCaseRefers.size()); return data; - + } catch (Exception e) { log.error("处理文件引用并构建响应数据异常", e); return null; } } - + /** * 处理文件引用(原方法,保留用于数据收集) */ @@ -641,7 +641,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { log.error("处理文件引用异常", e); } } - + /** * 处理建议 */ @@ -660,7 +660,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { log.error("处理建议异常", e); } } - + /** * 根据docId查询案例引用信息 */ @@ -671,7 +671,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { if (docLog == null) { return null; } - + // 根据 case_id 查询案例详情 Cases caseEntity = casesDao.get(docLog.getCaseId()); if (caseEntity == null) { @@ -688,7 +688,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { caseRefer.setContent(caseEntity.getSummary()); caseRefer.setUploadTime(caseEntity.getSysCreateTime()); caseRefer.setOrgInfo(authorOrg.getName()); - + // 构建关键词列表 List keywords = new ArrayList<>(); if (caseEntity.getKeyword1() != null) keywords.add(caseEntity.getKeyword1()); @@ -697,14 +697,14 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { if (caseEntity.getKeyword4() != null) keywords.add(caseEntity.getKeyword4()); if (caseEntity.getKeyword5() != null) keywords.add(caseEntity.getKeyword5()); caseRefer.setKeywords(keywords); - + return caseRefer; } catch (Exception e) { log.error("根据docId查询案例引用信息异常", e); return null; } } - + /** * 当 SSE 失败时,作为普通 HTTP 请求处理 * 不再使用 @@ -717,12 +717,12 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { .writeTimeout(60, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); - + Response response = client.newCall(request).execute(); if (response.isSuccessful()) { String responseBody = response.body().string(); log.info("作为普通 HTTP 请求处理成功,将响应原封不动推送给前端"); - + // 将响应内容原封不动地推送到 SseEmitter JSONObject responseData = JSONObject.parseObject(responseBody); if (responseBody.contains("message")) { @@ -810,9 +810,17 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { log.error("操作失败,docId为空"); return false; } - if ((StringUtils.equalsAny(caseAiMsgLikeDto.getLikeStatus(), "0", "1", "-1")) || StringUtils.isBlank(caseAiMsgLikeDto.getFeedback())) { - log.error("操作失败,参数错误"); - return false; + if (Boolean.TRUE.equals(caseAiMsgLikeDto.getOperation())) { + String likeStatus = caseAiMsgLikeDto.getLikeStatus(); + if (!StringUtils.equals(likeStatus, "1") && !StringUtils.equals(likeStatus, "0") && !StringUtils.equals(likeStatus, "-1")) { + log.error("操作失败,参数错误"); + return false; + } + } else if (Boolean.FALSE.equals(caseAiMsgLikeDto.getOperation())) { + if (StringUtils.isBlank(caseAiMsgLikeDto.getFeedback())) { + log.error("操作失败,参数错误"); + return false; + } } aiChatConversationData.setLikeStatus(caseAiMsgLikeDto.getLikeStatus()); aiChatConversationData.setFeedback(caseAiMsgLikeDto.getFeedback()); diff --git a/servers/boe-server-all/src/main/resources/application-dev.yml b/servers/boe-server-all/src/main/resources/application-dev.yml index f8e9a0fd..3ba63ee3 100644 --- a/servers/boe-server-all/src/main/resources/application-dev.yml +++ b/servers/boe-server-all/src/main/resources/application-dev.yml @@ -11,22 +11,22 @@ spring: cloud: nacos: discovery: - server-addr: 192.168.0.253:8848 + server-addr: 192.168.10.74:8848 config: - server-addr: 192.168.0.253:8848 + server-addr: 192.168.10.74:8848 redis: - database: 1 - host: 192.168.0.253 - password: boe@123 - port: 6379 + database: 2 + host: 39.104.123.58 + password: Ebiz2020 + port: 6378 jpa: hibernate: ddl-auto: none datasource: driverClassName: com.mysql.jdbc.Driver - url: jdbc:mysql://192.168.0.253:3306/boe_base?useSSL=false&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull - username: root - password: boe#1234A + url: jdbc:mysql://rm-hp3cpkk0u50q90eu9vo.mysql.huhehaote.rds.aliyuncs.com:3306/ebiz_doc_manage?characterEncoding=utf8&useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true + username: ebiz_ai + password: ebiz_ai123 type: com.zaxxer.hikari.HikariDataSource hikari: auto-commit: true @@ -36,7 +36,7 @@ spring: max-lifetime: 1800000 maximum-pool-size: 20 activemq: - broker-url: tcp://192.168.0.253:61616 + broker-url: tcp://192.168.10.74:61616 user: admin password: admin jms: @@ -113,7 +113,7 @@ aop-log-record: #不进行拦截的包或者类 excludeClassNames: activemq: - broker-url: tcp://192.168.0.253:61616 + broker-url: tcp://192.168.10.74:61616 user: admin password: admin elasticsearch: