Commit 82c57840 by 彭顺

feat: 4月11日需求修改

parent 68f10d90
File added
package cn.iocoder.yudao.module.ai.controller.admin.agent; package cn.iocoder.yudao.module.ai.controller.admin.agent;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.agent.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.agent.vo.AgentCreateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.agent.vo.AgentMsgReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.agent.vo.AgentUsedRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.agent.vo.OrderInfoVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
...@@ -17,12 +12,16 @@ import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; ...@@ -17,12 +12,16 @@ import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService;
import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
...@@ -89,7 +88,7 @@ public class AgentChatController { ...@@ -89,7 +88,7 @@ public class AgentChatController {
AgentUsedRespVO agentUsedRespVO = new AgentUsedRespVO(); AgentUsedRespVO agentUsedRespVO = new AgentUsedRespVO();
agentUsedRespVO.setId(aiChatConversationDO.getId()); agentUsedRespVO.setId(aiChatConversationDO.getId());
agentUsedRespVO.setRoleId(aiChatConversationDO.getRoleId()); agentUsedRespVO.setRoleId(aiChatConversationDO.getRoleId());
agentUsedRespVO.setTitle(aiChatConversationDO.getTitle());
agentUsedRespVO.setCreateTime(aiChatConversationDO.getCreateTime()); agentUsedRespVO.setCreateTime(aiChatConversationDO.getCreateTime());
AiChatRoleDO aiChatRoleDO = chatRoleService.getChatRole(aiChatConversationDO.getRoleId()); AiChatRoleDO aiChatRoleDO = chatRoleService.getChatRole(aiChatConversationDO.getRoleId());
...@@ -106,13 +105,13 @@ public class AgentChatController { ...@@ -106,13 +105,13 @@ public class AgentChatController {
return success(result); return success(result);
} }
@PostMapping("/get-messages") @GetMapping("/get-extra-variables")
@Operation(summary = "获得智能体对话消息") @Operation(summary = "获得智能体额外选项")
public ResponseEntity<?> getAgentMessages(@RequestBody @Valid AgentMsgReqVO reqVO) { @Parameter(name = "roleId", required = true, description = "智能体ID", example = "1024")
public ResponseEntity<?> getAgentExtraVariables(@RequestParam("roleId") Long roleId) {
AiChatRoleDO aiRole = chatRoleService.getChatRole(reqVO.getRoleId()); AiChatRoleDO aiRole = chatRoleService.getChatRole(roleId);
AiChatConversationDO conversation = chatConversationService.getChatConversation(reqVO.getConversationId()); AiChatModelDO model = chatModelService.getChatModel(aiRole.getModelId());
AiChatModelDO model = chatModelService.getChatModel(conversation.getModelId());
AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId()); AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId());
// 目标服务的URL // 目标服务的URL
...@@ -120,9 +119,7 @@ public class AgentChatController { ...@@ -120,9 +119,7 @@ public class AgentChatController {
// 构建请求参数 // 构建请求参数
String appId = aiRole.getAppId(); String appId = aiRole.getAppId();
String chatId = String.valueOf(reqVO.getConversationId()); String chatId = "any_id_can_works";
// String appId = "66f225d52b2887652b418f82";
// String chatId = "1781604279872581766";
boolean loadCustomFeedbacks = true; boolean loadCustomFeedbacks = true;
// 构建URL与请求参数 // 构建URL与请求参数
...@@ -139,20 +136,36 @@ public class AgentChatController { ...@@ -139,20 +136,36 @@ public class AgentChatController {
// 发送请求并接收响应 // 发送请求并接收响应
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.GET, entity, String.class); ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.GET, entity, String.class);
// 返回响应 JSONObject initJson = new JSONObject(response.getBody());
return response; JSONObject initData = initJson.getJSONObject("data");
JSONArray variablesConfig = initData.getJSONObject("app")
.getJSONObject("chatConfig")
.optJSONArray("variables");
JSONObject data = new JSONObject();
data.put("status", 200);
data.put("data", variablesConfig);
data.put("msg", "");
// 4. 返回合并后的响应
return ResponseEntity.ok(data.toString());
} }
@Operation(summary = "删除指定对话的上下文") @PostMapping("/get-messages")
@DeleteMapping("/delete-context") @Operation(summary = "获得智能体对话消息")
@Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") public ResponseEntity<?> getAgentMessagesv2(@RequestBody @Valid AgentMsgReqVO reqVO) {
public ResponseEntity<?> deleteChatMessageByConversationId(@RequestParam("conversationId") Long conversationId) {
if(chatMessageService.checkMsgExist(reqVO.getConversationId())){
// 直接构建 JSON 字符串
String jsonResponse = "{ \"code\": 200, \"data\": {}, \"msg\": \"\" }";
AiChatConversationDO conversation = chatConversationService.getChatConversation(conversationId); // 创建 ResponseEntity
if(conversation.getRoleId() == null){ ResponseEntity<String> response = ResponseEntity.ok(jsonResponse);
throw exception(CHAT_AGENT_NOT_EXISTS); return response;
} }
AiChatRoleDO aiRole = chatRoleService.getChatRole(conversation.getRoleId());
AiChatRoleDO aiRole = chatRoleService.getChatRole(reqVO.getRoleId());
AiChatConversationDO conversation = chatConversationService.getChatConversation(reqVO.getConversationId());
AiChatModelDO model = chatModelService.getChatModel(conversation.getModelId()); AiChatModelDO model = chatModelService.getChatModel(conversation.getModelId());
AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId()); AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId());
...@@ -161,10 +174,20 @@ public class AgentChatController { ...@@ -161,10 +174,20 @@ public class AgentChatController {
// 构建请求参数 // 构建请求参数
String appId = aiRole.getAppId(); String appId = aiRole.getAppId();
String chatId = String.valueOf(conversationId); String chatId = String.valueOf(reqVO.getConversationId());
boolean loadCustomFeedbacks = true;
// 构建请求体
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("offset", reqVO.getOffset());
requestBody.put("pageSize", reqVO.getPageSize());
requestBody.put("chatId", chatId);
requestBody.put("appId", appId);
requestBody.put("loadCustomFeedbacks", loadCustomFeedbacks);
requestBody.put("type", "normal");
// 构建URL与请求参数 // 构建URL与请求参数
String requestUrl = baseUrl + "/core/chat/delHistory?appId=" + appId + "&chatId=" + chatId; String requestUrl = baseUrl + "/core/chat/getPaginationRecords";
// 设置请求头 // 设置请求头
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
...@@ -172,15 +195,97 @@ public class AgentChatController { ...@@ -172,15 +195,97 @@ public class AgentChatController {
headers.set("Authorization", "Bearer " + apiKeyDO.getApiKey()); headers.set("Authorization", "Bearer " + apiKeyDO.getApiKey());
// 构建请求实体 // 构建请求实体
HttpEntity<String> entity = new HttpEntity<>(headers); HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
// 发送请求并接收响应 // 发送请求并接收响应
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.DELETE, entity, String.class); ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.POST, entity, String.class);
chatMessageService.deleteChatMessageByConversationId(conversationId, getLoginUserId()); // 返回响应
return response; return response;
} }
// @PostMapping("/get-messages")
// @Operation(summary = "获得智能体对话消息")
// public ResponseEntity<?> getAgentMessagesv2(@RequestBody @Valid AgentMsgReqVO reqVO) {
// if(chatMessageService.checkMsgExist(reqVO.getConversationId())) {
// // 直接构建 JSON 字符串
// String jsonResponse = "{ \"code\": 200, \"data\": {}, \"msg\": \"\" }";
// // 创建 ResponseEntity
// return ResponseEntity.ok(jsonResponse);
// }
//
// AiChatRoleDO aiRole = chatRoleService.getChatRole(reqVO.getRoleId());
// AiChatConversationDO conversation = chatConversationService.getChatConversation(reqVO.getConversationId());
// AiChatModelDO model = chatModelService.getChatModel(conversation.getModelId());
// AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId());
//
// // 目标服务的URL
// String baseUrl = apiKeyDO.getUrl();
//
// // 构建请求参数
// String appId = aiRole.getAppId();
// String chatId = String.valueOf(reqVO.getConversationId());
// boolean loadCustomFeedbacks = true;
//
// // 1. 首先获取init数据
// String initUrl = baseUrl + "/core/chat/init?appId=" + appId + "&chatId=" + chatId + "&loadCustomFeedbacks=" + loadCustomFeedbacks;
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_JSON);
// headers.set("Authorization", "Bearer " + apiKeyDO.getApiKey());
// HttpEntity<String> initEntity = new HttpEntity<>(headers);
// ResponseEntity<String> initResponse = restTemplate.exchange(initUrl, HttpMethod.GET, initEntity, String.class);
//
// // 解析init响应获取variables和app.chatConfig.variables
// JSONObject initJson = new JSONObject(initResponse.getBody());
// JSONObject initData = initJson.getJSONObject("data");
//// JSONObject variables = initData.optJSONObject("variables");
// JSONArray variablesConfig = initData.getJSONObject("app")
// .getJSONObject("chatConfig")
// .optJSONArray("variables");
//
// // 2. 获取分页记录
// Map<String, Object> requestBody = new HashMap<>();
// requestBody.put("offset", reqVO.getOffset());
// requestBody.put("pageSize", reqVO.getPageSize());
// requestBody.put("chatId", chatId);
// requestBody.put("appId", appId);
// requestBody.put("loadCustomFeedbacks", loadCustomFeedbacks);
// requestBody.put("type", "normal");
//
// String recordsUrl = baseUrl + "/core/chat/getPaginationRecords";
// HttpEntity<Map<String, Object>> recordsEntity = new HttpEntity<>(requestBody, headers);
// ResponseEntity<String> recordsResponse = restTemplate.exchange(recordsUrl, HttpMethod.POST, recordsEntity, String.class);
//
// // 3. 合并数据到分页记录响应中
// JSONObject recordsJson = new JSONObject(recordsResponse.getBody());
// JSONObject data = recordsJson.optJSONObject("data");
// if (data == null) {
// data = new JSONObject();
// recordsJson.put("data", data);
// }
//
// // 合并variables和variablesConfig
//// if (variables != null) {
//// data.put("variables", variables);
//// }
// if (variablesConfig != null) {
// data.put("variables", variablesConfig);
// }
//
// // 4. 返回合并后的响应
// return ResponseEntity.ok(recordsJson.toString());
// }
@Operation(summary = "删除指定对话的上下文")
@DeleteMapping("/delete-context")
@Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024")
public CommonResult<Boolean> deleteChatMessageByConversationId(@RequestParam("conversationId") Long conversationId) {
chatMessageService.deleteChatMessageByConversationId(conversationId, getLoginUserId());
return success(true);
}
@PostMapping("/get-order-info") @PostMapping("/get-order-info")
@Operation(summary = "获取jp通知单所需信息") @Operation(summary = "获取jp通知单所需信息")
@Parameter(name = "vbeln", required = true, description = "SAP销售订单编号", example = "2024102922") @Parameter(name = "vbeln", required = true, description = "SAP销售订单编号", example = "2024102922")
...@@ -204,4 +309,63 @@ public class AgentChatController { ...@@ -204,4 +309,63 @@ public class AgentChatController {
return success(orderInfoService.getOrderInfoRequest(url, payload)); return success(orderInfoService.getOrderInfoRequest(url, payload));
} }
@PostMapping("/feedback")
@Operation(summary = "更新反馈信息")
public ResponseEntity<?> updateUserFeedback(@RequestBody @Valid AgentFeedBackReqVO reqVO) {
AiChatRoleDO aiRole = chatRoleService.getChatRole(reqVO.getRoleId());
AiChatConversationDO conversation = chatConversationService.getChatConversation(reqVO.getConversationId());
AiChatModelDO model = chatModelService.getChatModel(conversation.getModelId());
AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId());
// 目标服务的URL
String baseUrl = apiKeyDO.getUrl();
// 构建请求参数
String appId = aiRole.getAppId();
String chatId = String.valueOf(reqVO.getConversationId());
String chatItemId = reqVO.getMessageId();
String userBadFeedback = reqVO.getUserBadFeedback();
String userGoodFeedback = reqVO.getUserGoodFeedback();
// 构建请求体
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("appId", appId);
requestBody.put("chatId", chatId);
requestBody.put("chatItemId", chatItemId);
// 判断 userBadFeedback 和 userGoodFeedback 哪个不为 null
if (userBadFeedback != null) {
requestBody.put("userBadFeedback", userBadFeedback);
} else if (userGoodFeedback != null) {
requestBody.put("userGoodFeedback", userGoodFeedback);
}
// 将请求体转换为JSON字符串
ObjectMapper objectMapper = new ObjectMapper();
String requestBodyJson;
try {
requestBodyJson = objectMapper.writeValueAsString(requestBody);
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to convert request body to JSON", e);
}
// 构建URL与请求参数
String requestUrl = baseUrl + "/core/chat/feedback/updateUserFeedback";
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + apiKeyDO.getApiKey());
// 构建请求实体
HttpEntity<String> entity = new HttpEntity<>(requestBodyJson, headers);
// 发送请求并接收响应
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.POST, entity, String.class);
// 返回响应
return response;
}
} }
...@@ -10,4 +10,7 @@ public class AgentCreateReqVO { ...@@ -10,4 +10,7 @@ public class AgentCreateReqVO {
@Schema(description = "智能体编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") @Schema(description = "智能体编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long roleId; private Long roleId;
@Schema(description = "第一条消息作为标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好")
private String firstMsg;
} }
package cn.iocoder.yudao.module.ai.controller.admin.agent.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - Agent FeedBack Request VO")
@Data
public class AgentFeedBackReqVO {
@Schema(description = "智能体编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32")
private Long roleId;
@Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long conversationId;
@Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String messageId;
@Schema(description = "好反馈", example = "yes")
private String userGoodFeedback;
@Schema(description = "坏反馈", example = "回复效果差")
private String userBadFeedback;
}
...@@ -11,4 +11,10 @@ public class AgentMsgReqVO { ...@@ -11,4 +11,10 @@ public class AgentMsgReqVO {
@Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long conversationId; private Long conversationId;
@Schema(description = "分页偏移", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Long offset;
@Schema(description = "分页大小", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long pageSize;
} }
...@@ -20,6 +20,9 @@ public class AgentUsedRespVO { ...@@ -20,6 +20,9 @@ public class AgentUsedRespVO {
@Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = {"name", "avatar"}, refs = {"roleName", "roleAvatar"}) @Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = {"name", "avatar"}, refs = {"roleName", "roleAvatar"})
private Long roleId; private Long roleId;
@Schema(description = "对话标题", example = "你好")
private String title;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime; private LocalDateTime createTime;
...@@ -28,7 +31,7 @@ public class AgentUsedRespVO { ...@@ -28,7 +31,7 @@ public class AgentUsedRespVO {
@Schema(description = "智能体头像", example = "https://www.iocoder.cn/1.png") @Schema(description = "智能体头像", example = "https://www.iocoder.cn/1.png")
private String roleAvatar; private String roleAvatar;
@Schema(description = "智能体名字", example = "小黄") @Schema(description = "智能体名字", example = "政府PPT编制")
private String roleName; private String roleName;
} }
...@@ -8,10 +8,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; ...@@ -8,10 +8,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
...@@ -41,6 +38,8 @@ import java.net.MalformedURLException; ...@@ -41,6 +38,8 @@ import java.net.MalformedURLException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
...@@ -83,13 +82,23 @@ public class AiChatMessageController { ...@@ -83,13 +82,23 @@ public class AiChatMessageController {
public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) throws MalformedURLException { public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) throws MalformedURLException {
// 禁用ruoyi的上下文能力 // 禁用ruoyi的上下文能力
sendReqVO.setUseContext(false); sendReqVO.setUseContext(false);
String originalUrl = sendReqVO.getFileUrl(); List<String> originalUrls = sendReqVO.getFileUrl();
if(originalUrl != null && originalUrl.contains("218.77.58.8")){ if (originalUrls != null) {
// 替换IP地址 for (int i = 0; i < originalUrls.size(); i++) {
String replacedUrl = originalUrl.replace("218.77.58.8", "192.168.252.71"); String originalUrl = originalUrls.get(i);
sendReqVO.setFileUrl(replacedUrl); if (originalUrl != null && originalUrl.contains("218.77.58.8")) {
// 替换IP地址
String replacedUrl = originalUrl.replace("218.77.58.8", "192.168.252.71");
originalUrls.set(i, replacedUrl); // 更新列表中的URL
}
}
sendReqVO.setFileUrl(originalUrls); // 将更新后的列表重新设置到sendReqVO中
} }
return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); // 如果 responseChatId 为 null,则随机初始化一个 id
if (sendReqVO.getResponseChatItemId() == null) {
sendReqVO.setResponseChatItemId(generateBase62UniqueId(20));
}
return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId(), originalUrls);
} }
@Operation(summary = "获得指定对话的消息列表") @Operation(summary = "获得指定对话的消息列表")
...@@ -147,4 +156,37 @@ public class AiChatMessageController { ...@@ -147,4 +156,37 @@ public class AiChatMessageController {
return success(true); return success(true);
} }
@Operation(summary = "反馈", description = "反馈回复是否有用")
@PostMapping("/feedback")
@PreAuthorize("@ss.hasPermission('ai:chat-message:update')")
public CommonResult<Boolean> feedback(@Valid @RequestBody AiChatMessageFeedBackReqVO sendReqVO) {
chatMessageService.updateFeedback(sendReqVO);
return success(true);
}
private String generateBase62UniqueId(int length) {
// Base62 字符集(0-9, A-Z, a-z)
final String BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder(length);
// 使用 UUID 作为随机源
UUID uuid = UUID.randomUUID();
long mostSignificantBits = uuid.getMostSignificantBits();
long leastSignificantBits = uuid.getLeastSignificantBits();
// 将 UUID 的 128 位数据转换为 Base62
for (int i = 0; i < length; i++) {
// 取随机位并映射到 Base62 字符集
long randomValue = ThreadLocalRandom.current().nextLong(62);
if (i < 11) {
randomValue = (mostSignificantBits >>> (i * 5)) & 0x3F; // 取 6 位
} else {
randomValue = (leastSignificantBits >>> ((i - 11) * 5)) & 0x3F; // 取 6 位
}
sb.append(BASE62.charAt((int) (randomValue % 62)));
}
return sb.toString();
}
} }
package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message;
import cn.iocoder.yudao.framework.ai.core.model.fastgpt.FastGPTOptions;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - AI 聊天消息反馈")
@Data
public class AiChatMessageFeedBackReqVO {
@Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "消息编号不能为空")
private Long id;
@Schema(description = "反馈内容", example = "回答不准确")
// @NotEmpty(message = "聊天内容不能为空")
private String fdContent;
@Schema(description = "是否有用", example = "true")
private Boolean useful;
}
...@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; ...@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - AI 聊天消息 Response VO") @Schema(description = "管理后台 - AI 聊天消息 Response VO")
@Data @Data
...@@ -47,4 +48,13 @@ public class AiChatMessageRespVO { ...@@ -47,4 +48,13 @@ public class AiChatMessageRespVO {
@Schema(description = "角色名字", example = "小黄") @Schema(description = "角色名字", example = "小黄")
private String roleName; private String roleName;
@Schema(description = "对话文件列表")
private List<String> fileUrls;
@Schema(description = "是否有用")
private Boolean useful;
@Schema(description = "反馈内容")
private String fdContent;
} }
...@@ -8,6 +8,8 @@ import jakarta.validation.constraints.Size; ...@@ -8,6 +8,8 @@ import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.List;
@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") @Schema(description = "管理后台 - AI 聊天消息发送 Request VO")
@Data @Data
public class AiChatMessageSendReqVO { public class AiChatMessageSendReqVO {
...@@ -23,10 +25,15 @@ public class AiChatMessageSendReqVO { ...@@ -23,10 +25,15 @@ public class AiChatMessageSendReqVO {
@Schema(description = "是否携带上下文", example = "true") @Schema(description = "是否携带上下文", example = "true")
private Boolean useContext; private Boolean useContext;
// @Schema(description = "文件路径")
// private String fileUrl;
@Schema(description = "文件路径") @Schema(description = "文件路径")
private String fileUrl; private List<String> fileUrl;
@Schema(description = "变量") @Schema(description = "变量")
private FastGPTOptions.Variables variables; private FastGPTOptions.Variables variables;
@Schema(description = "回复信息预设ID")
private String responseChatItemId;
} }
...@@ -31,6 +31,9 @@ public class AiChatMessageSendRespVO { ...@@ -31,6 +31,9 @@ public class AiChatMessageSendRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String chatItemId;
} }
} }
package cn.iocoder.yudao.module.ai.dal.dataobject.chat; package cn.iocoder.yudao.module.ai.dal.dataobject.chat;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import org.springframework.ai.chat.messages.MessageType; import org.springframework.ai.chat.messages.MessageType;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
...@@ -9,13 +11,15 @@ import com.baomidou.mybatisplus.annotation.KeySequence; ...@@ -9,13 +11,15 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*; import lombok.*;
import java.util.List;
/** /**
* AI Chat 消息 DO * AI Chat 消息 DO
* *
* @since 2024/4/14 17:35 * @since 2024/4/14 17:35
* @since 2024/4/14 17:35 * @since 2024/4/14 17:35
*/ */
@TableName("ai_chat_message") @TableName(value = "ai_chat_message", autoResultMap = true)
@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
...@@ -87,4 +91,20 @@ public class AiChatMessageDO extends BaseDO { ...@@ -87,4 +91,20 @@ public class AiChatMessageDO extends BaseDO {
*/ */
private Boolean useContext; private Boolean useContext;
/**
* 文件链接
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> fileUrls;
/**
* 是否有用
*/
private Boolean useful;
/**
* 反馈内容
*/
private String fdContent;
} }
...@@ -6,12 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; ...@@ -6,12 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
...@@ -47,14 +48,31 @@ public interface AiChatMessageMapper extends BaseMapperX<AiChatMessageDO> { ...@@ -47,14 +48,31 @@ public interface AiChatMessageMapper extends BaseMapperX<AiChatMessageDO> {
record -> MapUtil.getInt(record, "count" )); record -> MapUtil.getInt(record, "count" ));
} }
default PageResult<AiChatMessageDO> selectPage(AiChatMessagePageReqVO pageReqVO) { // default PageResult<AiChatMessageDO> selectPage(AiChatMessagePageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<AiChatMessageDO>() // return selectPage(pageReqVO, new LambdaQueryWrapperX<AiChatMessageDO>()
.eqIfPresent(AiChatMessageDO::getConversationId, pageReqVO.getConversationId()) // .eqIfPresent(AiChatMessageDO::getConversationId, pageReqVO.getConversationId())
.eqIfPresent(AiChatMessageDO::getUserId, pageReqVO.getUserId()) // .eqIfPresent(AiChatMessageDO::getUserId, pageReqVO.getUserId())
.likeIfPresent(AiChatMessageDO::getContent, pageReqVO.getContent()) // .likeIfPresent(AiChatMessageDO::getContent, pageReqVO.getContent())
.betweenIfPresent(AiChatMessageDO::getCreateTime, pageReqVO.getCreateTime()) // .betweenIfPresent(AiChatMessageDO::getCreateTime, pageReqVO.getCreateTime())
.orderByDesc(AiChatMessageDO::getId)); // .orderByDesc(AiChatMessageDO::getId));
} // }
/**
* 分页查询,忽略逻辑删除的过滤条件
*/
@Select({
"<script>",
"SELECT * FROM ai_chat_message",
"<where>",
" <if test='req.conversationId != null'> AND conversation_id = #{req.conversationId} </if>",
" <if test='req.userId != null'> AND user_id = #{req.userId} </if>",
" <if test='req.content != null'> AND content LIKE CONCAT('%', #{req.content}, '%') </if>",
" <if test='req.createTime != null'> AND create_time BETWEEN #{req.createTime[0]} AND #{req.createTime[1]} </if>",
"</where>",
"ORDER BY id DESC",
"</script>"
})
IPage<AiChatMessageDO> selectPage(@Param("page") IPage<AiChatMessageDO> page, @Param("req") AiChatMessagePageReqVO pageReqVO);
default Long selectCounts(Long conId){ default Long selectCounts(Long conId){
return selectCount(new LambdaQueryWrapperX<AiChatMessageDO>() return selectCount(new LambdaQueryWrapperX<AiChatMessageDO>()
......
...@@ -169,17 +169,17 @@ public class AiChatConversationServiceImpl implements AiChatConversationService ...@@ -169,17 +169,17 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
Assert.notNull(model, "智能体未配置推理模型"); Assert.notNull(model, "智能体未配置推理模型");
validateChatModel(model); validateChatModel(model);
AiChatConversationDO conversationExist= chatConversationMapper.selectByRoleAndUserId(createReqVO.getRoleId(), userId); // AiChatConversationDO conversationExist= chatConversationMapper.selectByRoleAndUserId(createReqVO.getRoleId(), userId);
if(conversationExist != null){ // if(conversationExist != null){
return conversationExist.getId(); // return conversationExist.getId();
} // }
// 2. 创建 AiChatConversationDO 聊天对话 // 2. 创建 AiChatConversationDO 聊天对话
AiChatConversationDO conversation = new AiChatConversationDO().setUserId(userId).setPinned(false) AiChatConversationDO conversation = new AiChatConversationDO().setUserId(userId).setPinned(false)
.setModelId(model.getId()).setModel(model.getModel()) .setModelId(model.getId()).setModel(model.getModel())
.setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts()); .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts());
if (role != null) { if (role != null) {
conversation.setTitle(role.getName()).setRoleId(role.getId()).setSystemMessage(role.getSystemMessage()); conversation.setTitle(createReqVO.getFirstMsg()).setRoleId(role.getId()).setSystemMessage(role.getSystemMessage());
} else { } else {
conversation.setTitle(AiChatConversationDO.TITLE_DEFAULT); conversation.setTitle(AiChatConversationDO.TITLE_DEFAULT);
} }
......
...@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.chat; ...@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.chat;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageFeedBackReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
...@@ -36,7 +37,7 @@ public interface AiChatMessageService { ...@@ -36,7 +37,7 @@ public interface AiChatMessageService {
* @param userId 用户编号 * @param userId 用户编号
* @return 发送结果 * @return 发送结果
*/ */
Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) throws MalformedURLException; Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId, List<String> originalUrls) throws MalformedURLException;
/** /**
* 获得指定对话的消息列表 * 获得指定对话的消息列表
...@@ -62,6 +63,8 @@ public interface AiChatMessageService { ...@@ -62,6 +63,8 @@ public interface AiChatMessageService {
*/ */
void deleteChatMessageByConversationId(Long conversationId, Long userId); void deleteChatMessageByConversationId(Long conversationId, Long userId);
boolean checkMsgExist(Long conversationId);
/** /**
* 【管理员】删除消息 * 【管理员】删除消息
* *
...@@ -85,4 +88,5 @@ public interface AiChatMessageService { ...@@ -85,4 +88,5 @@ public interface AiChatMessageService {
*/ */
PageResult<AiChatMessageDO> getChatMessagePage(AiChatMessagePageReqVO pageReqVO); PageResult<AiChatMessageDO> getChatMessagePage(AiChatMessagePageReqVO pageReqVO);
void updateFeedback(AiChatMessageFeedBackReqVO sendReqVO);
} }
...@@ -9,8 +9,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; ...@@ -9,8 +9,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageFeedBackReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
...@@ -21,6 +21,8 @@ import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; ...@@ -21,6 +21,8 @@ import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.*; import org.springframework.ai.chat.messages.*;
...@@ -29,8 +31,6 @@ import org.springframework.ai.chat.model.ChatResponse; ...@@ -29,8 +31,6 @@ import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.StreamingChatModel; import org.springframework.ai.chat.model.StreamingChatModel;
import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileUrlResource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
...@@ -81,11 +81,11 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -81,11 +81,11 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
// 2. 插入 user 发送消息 // 2. 插入 user 发送消息
AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext()); userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(), sendReqVO.getFileUrl());
// 3.1 插入 assistant 接收消息 // 3.1 插入 assistant 接收消息
AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model, AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext()); userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(), sendReqVO.getFileUrl());
// 3.2 创建 chat 需要的 Prompt // 3.2 创建 chat 需要的 Prompt
Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO); Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO);
...@@ -99,7 +99,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -99,7 +99,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
} }
@Override @Override
public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) throws MalformedURLException { public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId, List<String> originalUrls) throws MalformedURLException {
// 1.1 校验对话存在 // 1.1 校验对话存在
AiChatConversationDO conversation = chatConversationService.validateChatConversationExists(sendReqVO.getConversationId()); AiChatConversationDO conversation = chatConversationService.validateChatConversationExists(sendReqVO.getConversationId());
if (ObjUtil.notEqual(conversation.getUserId(), userId)) { if (ObjUtil.notEqual(conversation.getUserId(), userId)) {
...@@ -112,13 +112,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -112,13 +112,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
// 2. 插入 user 发送消息 // 2. 插入 user 发送消息
Long count = chatMessageMapper.selectCounts(conversation.getId()); Long count = chatMessageMapper.selectCounts(conversation.getId());
if(count == 0 && Objects.equals(conversation.getTitle(), AiChatConversationDO.TITLE_DEFAULT)){ if(count == 0){
// if(count == 0 && Objects.equals(conversation.getTitle(), AiChatConversationDO.TITLE_DEFAULT)){
AiChatConversationUpdateMyReqVO updateMyReq = BeanUtils.toBean(conversation, AiChatConversationUpdateMyReqVO.class); AiChatConversationUpdateMyReqVO updateMyReq = BeanUtils.toBean(conversation, AiChatConversationUpdateMyReqVO.class);
updateMyReq.setTitle(sendReqVO.getContent()); updateMyReq.setTitle(sendReqVO.getContent());
chatConversationService.updateChatConversationMy(updateMyReq, userId); chatConversationService.updateChatConversationMy(updateMyReq, userId);
} }
AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext()); userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(), originalUrls);
// 3.1 插入 assistant 接收消息 // 3.1 插入 assistant 接收消息
// AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model, // AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
...@@ -141,7 +142,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -141,7 +142,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
contentBuffer.append(newContent); contentBuffer.append(newContent);
// 响应结果 // 响应结果
return success(new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) return success(new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class))
.setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent))); .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent).setChatItemId(sendReqVO.getResponseChatItemId())));
}).doOnComplete(() -> { }).doOnComplete(() -> {
// 忽略租户,因为 Flux 异步无法透传租户 // 忽略租户,因为 Flux 异步无法透传租户
// TenantUtils.executeIgnore(() -> chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString()))); // TenantUtils.executeIgnore(() -> chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())));
...@@ -174,8 +175,18 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -174,8 +175,18 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
contextMessages.forEach(message -> chatMessages.add(AiUtils.buildMessage(message.getType(), message.getContent()))); contextMessages.forEach(message -> chatMessages.add(AiUtils.buildMessage(message.getType(), message.getContent())));
// 1.3 user message 新发送消息 // 1.3 user message 新发送消息
UserMessage send_message; UserMessage send_message;
if(sendReqVO.getFileUrl() != null && !Objects.equals(sendReqVO.getFileUrl(), "")){ if(sendReqVO.getFileUrl() != null && !sendReqVO.getFileUrl().isEmpty()){
send_message = new UserMessage(sendReqVO.getContent(), new Media(MimeTypeUtils.TEXT_PLAIN, new URL(sendReqVO.getFileUrl()))); List<Media> mediaList = new ArrayList<>();
for (String fileUrl : sendReqVO.getFileUrl()) {
try {
mediaList.add(new Media(MimeTypeUtils.TEXT_PLAIN, new URL(fileUrl)));
} catch (MalformedURLException e) {
// 处理URL异常
e.printStackTrace();
}
}
send_message = new UserMessage(sendReqVO.getContent(), mediaList);
} else { } else {
send_message = new UserMessage(sendReqVO.getContent()); send_message = new UserMessage(sendReqVO.getContent());
} }
...@@ -185,7 +196,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -185,7 +196,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
// 2. 构建 ChatOptions 对象 // 2. 构建 ChatOptions 对象
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(),
conversation.getTemperature(), conversation.getMaxTokens(), String.valueOf(conversation.getId()), sendReqVO.getVariables()); conversation.getTemperature(), conversation.getMaxTokens(), String.valueOf(conversation.getId()), sendReqVO.getVariables(), sendReqVO.getResponseChatItemId());
return new Prompt(chatMessages, chatOptions); return new Prompt(chatMessages, chatOptions);
} }
...@@ -230,10 +241,10 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -230,10 +241,10 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
private AiChatMessageDO createChatMessage(Long conversationId, Long replyId, private AiChatMessageDO createChatMessage(Long conversationId, Long replyId,
AiChatModelDO model, Long userId, Long roleId, AiChatModelDO model, Long userId, Long roleId,
MessageType messageType, String content, Boolean useContext) { MessageType messageType, String content, Boolean useContext, List<String> fileUrls) {
AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId) AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId)
.setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId) .setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId)
.setType(messageType.getValue()).setContent(content).setUseContext(useContext); .setType(messageType.getValue()).setContent(content).setUseContext(useContext).setFileUrls(fileUrls);
message.setCreateTime(LocalDateTime.now()); message.setCreateTime(LocalDateTime.now());
chatMessageMapper.insert(message); chatMessageMapper.insert(message);
return message; return message;
...@@ -267,6 +278,13 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -267,6 +278,13 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
} }
@Override @Override
public boolean checkMsgExist(Long conversationId) {
// 1. 校验消息存在
List<AiChatMessageDO> messages = chatMessageMapper.selectListByConversationId(conversationId);
return CollUtil.isEmpty(messages);
}
@Override
public void deleteChatMessageByAdmin(Long id) { public void deleteChatMessageByAdmin(Long id) {
// 1. 校验消息存在 // 1. 校验消息存在
AiChatMessageDO message = chatMessageMapper.selectById(id); AiChatMessageDO message = chatMessageMapper.selectById(id);
...@@ -284,7 +302,26 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { ...@@ -284,7 +302,26 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
@Override @Override
public PageResult<AiChatMessageDO> getChatMessagePage(AiChatMessagePageReqVO pageReqVO) { public PageResult<AiChatMessageDO> getChatMessagePage(AiChatMessagePageReqVO pageReqVO) {
return chatMessageMapper.selectPage(pageReqVO); // return chatMessageMapper.selectPage(pageReqVO);
// 创建分页对象
IPage<AiChatMessageDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
// 调用 Mapper 方法
IPage<AiChatMessageDO> resultPage = chatMessageMapper.selectPage(page, pageReqVO);
// 转换为 PageResult
return new PageResult<>(resultPage.getRecords(), resultPage.getTotal());
}
@Override
public void updateFeedback(AiChatMessageFeedBackReqVO sendReqVO) {
// 1. 校验消息存在
AiChatMessageDO message = chatMessageMapper.selectById(sendReqVO.getId());
if (message == null) {
throw exception(CHAT_MESSAGE_NOT_EXIST);
}
// 2. 执行更新
message.setUseful(sendReqVO.getUseful());
message.setFdContent(sendReqVO.getFdContent());
chatMessageMapper.updateById(message);
} }
} }
...@@ -108,7 +108,7 @@ public class AiMindMapServiceImpl implements AiMindMapService { ...@@ -108,7 +108,7 @@ public class AiMindMapServiceImpl implements AiMindMapService {
List<Message> chatMessages = buildMessages(generateReqVO, systemMessage); List<Message> chatMessages = buildMessages(generateReqVO, systemMessage);
// 2. 构建 options 对象 // 2. 构建 options 对象
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
ChatOptions options = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens(), "", null); ChatOptions options = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens(), "", null, "");
return new Prompt(chatMessages, options); return new Prompt(chatMessages, options);
} }
......
...@@ -126,7 +126,7 @@ public class AiWriteServiceImpl implements AiWriteService { ...@@ -126,7 +126,7 @@ public class AiWriteServiceImpl implements AiWriteService {
List<Message> chatMessages = buildMessages(generateReqVO, systemMessage); List<Message> chatMessages = buildMessages(generateReqVO, systemMessage);
// 2. 构建 options 对象 // 2. 构建 options 对象
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
ChatOptions options = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens(), "", null); ChatOptions options = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens(), "", null, "");
return new Prompt(chatMessages, options); return new Prompt(chatMessages, options);
} }
......
...@@ -113,28 +113,28 @@ public class FastGPTApi { ...@@ -113,28 +113,28 @@ public class FastGPTApi {
} }
@JsonInclude(Include.NON_NULL) @JsonInclude(Include.NON_NULL)
public static record ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, String chatId, FastGPTOptions.Variables variables, Float frequencyPenalty, Map<String, Integer> logitBias, Boolean logprobs, Integer topLogprobs, Integer maxTokens, Integer n, Float presencePenalty, ResponseFormat responseFormat, Integer seed, List<String> stop, Boolean stream, Float temperature, Float topP, List<FunctionTool> tools, Object toolChoice, String user) { public static record ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, String chatId, FastGPTOptions.Variables variables, String responseChatItemId, Float frequencyPenalty, Map<String, Integer> logitBias, Boolean logprobs, Integer topLogprobs, Integer maxTokens, Integer n, Float presencePenalty, ResponseFormat responseFormat, Integer seed, List<String> stop, Boolean stream, Float temperature, Float topP, List<FunctionTool> tools, Object toolChoice, String user) {
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Float temperature) { public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Float temperature) {
this(messages, model, (String)null, (FastGPTOptions.Variables)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, false, temperature, (Float)null, (List)null, (Object)null, (String)null); this(messages, model, (String)null, (FastGPTOptions.Variables)null, (String)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, false, temperature, (Float)null, (List)null, (Object)null, (String)null);
} }
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Float temperature, boolean stream) { public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Float temperature, boolean stream) {
this(messages, model, (String)null, (FastGPTOptions.Variables)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, stream, temperature, (Float)null, (List)null, (Object)null, (String)null); this(messages, model, (String)null, (FastGPTOptions.Variables)null, (String)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, stream, temperature, (Float)null, (List)null, (Object)null, (String)null);
} }
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, List<FunctionTool> tools, Object toolChoice) { public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, List<FunctionTool> tools, Object toolChoice) {
this(messages, model, (String)null, (FastGPTOptions.Variables)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, false, 0.8F, (Float)null, tools, toolChoice, (String)null); this(messages, model, (String)null, (FastGPTOptions.Variables)null, (String)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, false, 0.8F, (Float)null, tools, toolChoice, (String)null);
} }
public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean stream) { public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean stream) {
this(messages, (String)null, (String)null, (FastGPTOptions.Variables)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, stream, (Float)null, (Float)null, (List)null, (Object)null, (String)null); this(messages, (String)null, (String)null, (FastGPTOptions.Variables)null, (String)null, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, stream, (Float)null, (Float)null, (List)null, (Object)null, (String)null);
} }
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, String chatId, FastGPTOptions.Variables variables, Boolean stream) { public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, String chatId, FastGPTOptions.Variables variables, String responseChatItemId, Boolean stream) {
this(messages, model, chatId, variables, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, stream, (Float)null, (Float)null, (List)null, (Object)null, (String)null); this(messages, model, chatId, variables, responseChatItemId, (Float)null, (Map)null, (Boolean)null, (Integer)null, (Integer)null, (Integer)null, (Float)null, (ResponseFormat)null, (Integer)null, (List)null, stream, (Float)null, (Float)null, (List)null, (Object)null, (String)null);
} }
public ChatCompletionRequest(@JsonProperty("messages") List<ChatCompletionMessage> messages, @JsonProperty("model") String model, @JsonProperty("chatId") String chatId, @JsonProperty("variables") FastGPTOptions.Variables variables, @JsonProperty("frequency_penalty") Float frequencyPenalty, @JsonProperty("logit_bias") Map<String, Integer> logitBias, @JsonProperty("logprobs") Boolean logprobs, @JsonProperty("top_logprobs") Integer topLogprobs, @JsonProperty("max_tokens") Integer maxTokens, @JsonProperty("n") Integer n, @JsonProperty("presence_penalty") Float presencePenalty, @JsonProperty("response_format") ResponseFormat responseFormat, @JsonProperty("seed") Integer seed, @JsonProperty("stop") List<String> stop, @JsonProperty("stream") Boolean stream, @JsonProperty("temperature") Float temperature, @JsonProperty("top_p") Float topP, @JsonProperty("tools") List<FunctionTool> tools, @JsonProperty("tool_choice") Object toolChoice, @JsonProperty("user") String user) { public ChatCompletionRequest(@JsonProperty("messages") List<ChatCompletionMessage> messages, @JsonProperty("model") String model, @JsonProperty("chatId") String chatId, @JsonProperty("variables") FastGPTOptions.Variables variables, @JsonProperty("responseChatItemId") String responseChatItemId, @JsonProperty("frequency_penalty") Float frequencyPenalty, @JsonProperty("logit_bias") Map<String, Integer> logitBias, @JsonProperty("logprobs") Boolean logprobs, @JsonProperty("top_logprobs") Integer topLogprobs, @JsonProperty("max_tokens") Integer maxTokens, @JsonProperty("n") Integer n, @JsonProperty("presence_penalty") Float presencePenalty, @JsonProperty("response_format") ResponseFormat responseFormat, @JsonProperty("seed") Integer seed, @JsonProperty("stop") List<String> stop, @JsonProperty("stream") Boolean stream, @JsonProperty("temperature") Float temperature, @JsonProperty("top_p") Float topP, @JsonProperty("tools") List<FunctionTool> tools, @JsonProperty("tool_choice") Object toolChoice, @JsonProperty("user") String user) {
this.messages = messages; this.messages = messages;
this.model = model; this.model = model;
this.chatId = chatId; this.chatId = chatId;
...@@ -155,6 +155,7 @@ public class FastGPTApi { ...@@ -155,6 +155,7 @@ public class FastGPTApi {
this.tools = tools; this.tools = tools;
this.toolChoice = toolChoice; this.toolChoice = toolChoice;
this.user = user; this.user = user;
this.responseChatItemId = responseChatItemId;
} }
@JsonProperty("messages") @JsonProperty("messages")
...@@ -177,6 +178,11 @@ public class FastGPTApi { ...@@ -177,6 +178,11 @@ public class FastGPTApi {
return this.variables; return this.variables;
} }
@JsonProperty("responseChatItemId")
public String responseChatItemId() {
return this.responseChatItemId;
}
@JsonProperty("frequency_penalty") @JsonProperty("frequency_penalty")
public Float frequencyPenalty() { public Float frequencyPenalty() {
return this.frequencyPenalty; return this.frequencyPenalty;
......
...@@ -164,7 +164,7 @@ public class FastGPTChatModel extends AbstractFunctionCallSupport<FastGPTApi.Cha ...@@ -164,7 +164,7 @@ public class FastGPTChatModel extends AbstractFunctionCallSupport<FastGPTApi.Cha
Set<String> promptEnabledFunctions = this.handleFunctionCallbackConfigurations(updatedRuntimeOptions, true); Set<String> promptEnabledFunctions = this.handleFunctionCallbackConfigurations(updatedRuntimeOptions, true);
functionsForThisRequest.addAll(promptEnabledFunctions); functionsForThisRequest.addAll(promptEnabledFunctions);
// request = (FastGPTApi.ChatCompletionRequest)ModelOptionsUtils.merge(updatedRuntimeOptions, request, FastGPTApi.ChatCompletionRequest.class); // request = (FastGPTApi.ChatCompletionRequest)ModelOptionsUtils.merge(updatedRuntimeOptions, request, FastGPTApi.ChatCompletionRequest.class);
request = new FastGPTApi.ChatCompletionRequest(chatCompletionMessages, updatedRuntimeOptions.getModel(), updatedRuntimeOptions.getChatId(), updatedRuntimeOptions.getVariables(), stream); request = new FastGPTApi.ChatCompletionRequest(chatCompletionMessages, updatedRuntimeOptions.getModel(), updatedRuntimeOptions.getChatId(), updatedRuntimeOptions.getVariables(), updatedRuntimeOptions.getResponseChatItemId(), stream);
} }
// if (this.defaultOptions != null) { // if (this.defaultOptions != null) {
......
...@@ -65,6 +65,9 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions { ...@@ -65,6 +65,9 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
@JsonIgnore @JsonIgnore
private Set<String> functions = new HashSet(); private Set<String> functions = new HashSet();
@JsonProperty("responseChatItemId")
private String responseChatItemId;
@JsonInclude(Include.NON_NULL) @JsonInclude(Include.NON_NULL)
public static record Variables(String scenarios) { public static record Variables(String scenarios) {
public Variables(@JsonProperty("scenarios") String scenarios) { public Variables(@JsonProperty("scenarios") String scenarios) {
...@@ -108,6 +111,14 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions { ...@@ -108,6 +111,14 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
this.chatId = chatId; this.chatId = chatId;
} }
public String getResponseChatItemId() {
return this.responseChatItemId;
}
public void setResponseChatItemId(String responseChatItemId) {
this.responseChatItemId = responseChatItemId;
}
public Float getFrequencyPenalty() { public Float getFrequencyPenalty() {
return this.frequencyPenalty; return this.frequencyPenalty;
} }
...@@ -249,6 +260,7 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions { ...@@ -249,6 +260,7 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
int result = 1; int result = 1;
result = 31 * result + (this.model == null ? 0 : this.model.hashCode()); result = 31 * result + (this.model == null ? 0 : this.model.hashCode());
result = 31 * result + (this.chatId == null ? 0 : this.chatId.hashCode()); result = 31 * result + (this.chatId == null ? 0 : this.chatId.hashCode());
result = 31 * result + (this.responseChatItemId == null ? 0 : this.responseChatItemId.hashCode());
result = 31 * result + (this.frequencyPenalty == null ? 0 : this.frequencyPenalty.hashCode()); result = 31 * result + (this.frequencyPenalty == null ? 0 : this.frequencyPenalty.hashCode());
result = 31 * result + (this.logitBias == null ? 0 : this.logitBias.hashCode()); result = 31 * result + (this.logitBias == null ? 0 : this.logitBias.hashCode());
result = 31 * result + (this.logprobs == null ? 0 : this.logprobs.hashCode()); result = 31 * result + (this.logprobs == null ? 0 : this.logprobs.hashCode());
...@@ -290,6 +302,13 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions { ...@@ -290,6 +302,13 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
} else if (!this.chatId.equals(other.chatId)) { } else if (!this.chatId.equals(other.chatId)) {
return false; return false;
} }
if (this.responseChatItemId == null) {
if (other.responseChatItemId != null) {
return false;
}
} else if (!this.responseChatItemId.equals(other.responseChatItemId)) {
return false;
}
if (this.frequencyPenalty == null) { if (this.frequencyPenalty == null) {
if (other.frequencyPenalty != null) { if (other.frequencyPenalty != null) {
...@@ -555,5 +574,10 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions { ...@@ -555,5 +574,10 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
public FastGPTOptions build() { public FastGPTOptions build() {
return this.options; return this.options;
} }
public Builder withChatItemId(String responseChatItemId) {
this.options.responseChatItemId = responseChatItemId;
return this;
}
} }
} }
...@@ -21,7 +21,7 @@ import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; ...@@ -21,7 +21,7 @@ import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
*/ */
public class AiUtils { public class AiUtils {
public static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens, String chatId, FastGPTOptions.Variables variables) { public static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens, String chatId, FastGPTOptions.Variables variables, String chatItemId) {
Float temperatureF = temperature != null ? temperature.floatValue() : null; Float temperatureF = temperature != null ? temperature.floatValue() : null;
//noinspection EnhancedSwitchMigration //noinspection EnhancedSwitchMigration
switch (platform) { switch (platform) {
...@@ -43,7 +43,7 @@ public class AiUtils { ...@@ -43,7 +43,7 @@ public class AiUtils {
case OLLAMA: case OLLAMA:
return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens); return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens);
case FAST_GPT: case FAST_GPT:
return FastGPTOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).withChatId(chatId).withVariables(variables).build(); return FastGPTOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).withChatId(chatId).withVariables(variables).withChatItemId(chatItemId).build();
default: default:
throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform));
} }
......
...@@ -75,6 +75,7 @@ mybatis-plus: ...@@ -75,6 +75,7 @@ mybatis-plus:
# id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解 # id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
logic-delete-field: deleted # 逻辑删除字段名
banner: false # 关闭控制台的 Banner 打印 banner: false # 关闭控制台的 Banner 打印
type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
encryptor: encryptor:
......
...@@ -17,6 +17,8 @@ export interface ChatMessageVO { ...@@ -17,6 +17,8 @@ export interface ChatMessageVO {
createTime: Date // 创建时间 createTime: Date // 创建时间
roleAvatar: string // 角色头像 roleAvatar: string // 角色头像
userAvatar: string // 创建时间 userAvatar: string // 创建时间
useful: boolean // 是否有用
fdContent: boolean // 反馈内容
} }
// AI chat 聊天 // AI chat 聊天
......
...@@ -10,6 +10,8 @@ declare module 'vue' { ...@@ -10,6 +10,8 @@ declare module 'vue' {
AddNode: typeof import('./../components/SimpleProcessDesigner/src/addNode.vue')['default'] AddNode: typeof import('./../components/SimpleProcessDesigner/src/addNode.vue')['default']
AppLinkInput: typeof import('./../components/AppLinkInput/index.vue')['default'] AppLinkInput: typeof import('./../components/AppLinkInput/index.vue')['default']
AppLinkSelectDialog: typeof import('./../components/AppLinkInput/AppLinkSelectDialog.vue')['default'] AppLinkSelectDialog: typeof import('./../components/AppLinkInput/AppLinkSelectDialog.vue')['default']
'AutoComponents.d': typeof import('./auto-components.d.ts')['default']
'AutoImports.d': typeof import('./auto-imports.d.ts')['default']
Backtop: typeof import('./../components/Backtop/src/Backtop.vue')['default'] Backtop: typeof import('./../components/Backtop/src/Backtop.vue')['default']
CardTitle: typeof import('./../components/Card/src/CardTitle.vue')['default'] CardTitle: typeof import('./../components/Card/src/CardTitle.vue')['default']
ColorInput: typeof import('./../components/ColorInput/index.vue')['default'] ColorInput: typeof import('./../components/ColorInput/index.vue')['default']
......
...@@ -83,6 +83,12 @@ ...@@ -83,6 +83,12 @@
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.useContext" /> <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.useContext" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否有用" align="center" prop="useful" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.useful" />
</template>
</el-table-column>
<el-table-column label="反馈内容" align="center" prop="fdContent" width="300" />
<el-table-column label="操作" align="center" fixed="right"> <el-table-column label="操作" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
......
...@@ -13,14 +13,14 @@ ...@@ -13,14 +13,14 @@
:on-exceed="handleExceed" :on-exceed="handleExceed"
:on-success="submitFormSuccess" :on-success="submitFormSuccess"
:http-request="httpRequest" :http-request="httpRequest"
accept=".jpg, .png, .gif" accept=""
drag drag
> >
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em></div> <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em></div>
<template #tip> <template #tip>
<div class="el-upload__tip" style="color: red"> <div class="el-upload__tip" style="color: red">
提示:仅允许导入 jpg、png、gif 格式文件 提示:文件大小低于64M
</div> </div>
</template> </template>
</el-upload> </el-upload>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment