diff --git a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java index 78154b5c..c0ceab09 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java +++ b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java @@ -1,5 +1,7 @@ package xiaozhi.common.constant; +import lombok.Getter; + /** * 常量 * Copyright (c) 人人开源 All rights reserved. @@ -174,6 +176,23 @@ public interface Constant { } } + @Getter + enum ChatHistoryConfEnum { + IGNORE(0, "不记录"), + RECORD_TEXT(1, "记录文本"), + RECORD_AUDIO(2, "记录音频"), + RECORD_TEXT_AUDIO(3, "文本音频都记录") + ; + + private final int code; + private final String name; + + ChatHistoryConfEnum(int code, String name) { + this.code = code; + this.name = name; + } + } + /** * 版本号 */ diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java index 9368cf6b..f72a1ba3 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java @@ -109,6 +109,7 @@ public class AgentController { entity.setMemModelId(template.getMemModelId()); entity.setIntentModelId(template.getIntentModelId()); entity.setSystemPrompt(template.getSystemPrompt()); + entity.setChatHistoryConf(template.getChatHistoryConf()); entity.setLangCode(template.getLangCode()); entity.setLanguage(template.getLanguage()); } @@ -166,6 +167,9 @@ public class AgentController { if (dto.getSystemPrompt() != null) { existingEntity.setSystemPrompt(dto.getSystemPrompt()); } + if (dto.getChatHistoryConf() != null) { + existingEntity.setChatHistoryConf(dto.getChatHistoryConf()); + } if (dto.getLangCode() != null) { existingEntity.setLangCode(dto.getLangCode()); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java index d54685d8..1082d00b 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java @@ -45,6 +45,9 @@ public class AgentUpdateDTO implements Serializable { @Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题并提供帮助", required = false) private String systemPrompt; + @Schema(description = "聊天记录配置(0不记录 1仅记录文本 2仅记录语音 3记录文本和语音)", example = "3", required = false) + private Integer chatHistoryConf; + @Schema(description = "语言编码", example = "zh_CN", required = false) private String langCode; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java index 917fe6d2..39fd7682 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java @@ -48,6 +48,9 @@ public class AgentEntity { @Schema(description = "意图模型标识") private String intentModelId; + @Schema(description = "聊天记录配置(0不记录 1仅记录文本 2仅记录语音 3记录文本和语音)") + private Integer chatHistoryConf; + @Schema(description = "角色设定参数") private String systemPrompt; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTemplateEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTemplateEntity.java index 6d83e4fe..cc132260 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTemplateEntity.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTemplateEntity.java @@ -69,6 +69,11 @@ public class AgentTemplateEntity implements Serializable { */ private String intentModelId; + /** + * 聊天记录配置(0不记录 1仅记录文本 2仅记录语音 3记录文本和语音) + */ + private Integer chatHistoryConf; + /** * 角色设定参数 */ diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java index 21e645de..48d02171 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java @@ -2,12 +2,14 @@ package xiaozhi.modules.agent.service.biz.impl; import java.util.Base64; import java.util.Date; +import java.util.Objects; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import xiaozhi.common.constant.Constant; import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; import xiaozhi.modules.agent.dto.AgentChatHistoryReportDTO; @@ -47,8 +49,36 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic Byte chatType = report.getChatType(); log.info("小智设备聊天上报请求: macAddress={}, type={}", macAddress, chatType); - // 1. base64解码report.getOpusDataBase64(),存入ai_agent_chat_audio表 + // 根据设备MAC地址查询对应的默认智能体,判断是否需要上报 + AgentEntity agentEntity = agentService.getDefaultAgentByMacAddress(macAddress); + if (agentEntity == null) { + return Boolean.FALSE; + } + + Integer chatHistoryConf = agentEntity.getChatHistoryConf(); + String agentId = agentEntity.getId(); + + if (Objects.equals(chatHistoryConf, Constant.ChatHistoryConfEnum.RECORD_TEXT.getCode())) { + saveChatText(report, agentId, macAddress, null); + } else if (Objects.equals(chatHistoryConf, Constant.ChatHistoryConfEnum.RECORD_AUDIO.getCode())) { + saveChatAudio(report); + } else if (Objects.equals(chatHistoryConf, Constant.ChatHistoryConfEnum.RECORD_TEXT_AUDIO.getCode())) { + String audioId = saveChatAudio(report); + saveChatText(report, agentId, macAddress, audioId); + } + + // 更新设备最后对话时间 + redisUtils.set(RedisKeys.getAgentDeviceLastConnectedAtById(agentId), new Date()); + + return Boolean.TRUE; + } + + /** + * base64解码report.getOpusDataBase64(),存入ai_agent_chat_audio表 + */ + private String saveChatAudio(AgentChatHistoryReportDTO report) { String audioId = null; + if (report.getAudioBase64() != null && !report.getAudioBase64().isEmpty()) { try { byte[] audioData = Base64.getDecoder().decode(report.getAudioBase64()); @@ -56,20 +86,18 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic log.info("音频数据保存成功,audioId={}", audioId); } catch (Exception e) { log.error("音频数据保存失败", e); - return false; + return null; } } + return audioId; + } - // 2. 组装上报数据 - // 2.1 根据设备MAC地址查询对应的默认智能体,判断是否需要上报 - AgentEntity agentEntity = agentService.getDefaultAgentByMacAddress(macAddress); - if (agentEntity == null) { - return false; - } - String agentId = agentEntity.getId(); - log.info("设备 {} 对应智能体 {} 上报", macAddress, agentEntity.getId()); + /** + * 组装上报数据 + */ + private void saveChatText(AgentChatHistoryReportDTO report, String agentId, String macAddress, String audioId) { - // 2.2 构建聊天记录实体 + // 构建聊天记录实体 AgentChatHistoryEntity entity = AgentChatHistoryEntity.builder() .macAddress(macAddress) .agentId(agentId) @@ -79,10 +107,9 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic .audioId(audioId) .build(); - // 3. 保存数据 + // 保存数据 agentChatHistoryService.save(entity); - // 4. 更新设备最后对话时间 - redisUtils.set(RedisKeys.getAgentDeviceLastConnectedAtById(agentId), new Date()); - return Boolean.TRUE; + + log.info("设备 {} 对应智能体 {} 上报成功", macAddress, agentId); } } diff --git a/main/manager-web/src/apis/module/agent.js b/main/manager-web/src/apis/module/agent.js index 8aa89072..756e1bef 100644 --- a/main/manager-web/src/apis/module/agent.js +++ b/main/manager-web/src/apis/module/agent.js @@ -50,9 +50,9 @@ export default { }).send(); }, // 获取智能体配置 - getDeviceConfig(deviceId, callback) { + getDeviceConfig(agentId, callback) { RequestService.sendRequest() - .url(`${getServiceUrl()}/agent/${deviceId}`) + .url(`${getServiceUrl()}/agent/${agentId}`) .method('GET') .success((res) => { RequestService.clearRequestTime(); @@ -61,7 +61,7 @@ export default { .fail((err) => { console.error('获取配置失败:', err); RequestService.reAjaxFun(() => { - this.getDeviceConfig(deviceId, callback); + this.getDeviceConfig(agentId, callback); }); }).send(); }, diff --git a/main/manager-web/src/views/roleConfig.vue b/main/manager-web/src/views/roleConfig.vue index 8b9504da..b38035d4 100644 --- a/main/manager-web/src/views/roleConfig.vue +++ b/main/manager-web/src/views/roleConfig.vue @@ -65,12 +65,18 @@ :key="`option-${index}-${optionIndex}`" :label="item.label" :value="item.value" /> - + + + + + + @@ -96,6 +102,7 @@ export default { agentCode: "", agentName: "", ttsVoiceId: "", + chatHistoryConf: "", systemPrompt: "", langCode: "", language: "", @@ -121,6 +128,24 @@ export default { templates: [], loadingTemplate: false, voiceOptions: [], + chatHistoryOptions: [ + { + "value": 0, + "label": "不记录" + }, + { + "value": 1, + "label": "仅记录文本" + }, + { + "value": 2, + "label": "仅记录语音" + }, + { + "value": 3, + "label": "文本音频都记录" + } + ], } }, methods: { @@ -136,6 +161,7 @@ export default { llmModelId: this.form.model.llmModelId, ttsModelId: this.form.model.ttsModelId, ttsVoiceId: this.form.ttsVoiceId, + chatHistoryConf: this.form.chatHistoryConf, memModelId: this.form.model.memModelId, intentModelId: this.form.model.intentModelId, systemPrompt: this.form.systemPrompt, @@ -167,6 +193,7 @@ export default { agentCode: "", agentName: "", ttsVoiceId: "", + chatHistoryConf: "", systemPrompt: "", langCode: "", language: "", @@ -220,6 +247,7 @@ export default { ...this.form, agentName: templateData.agentName || this.form.agentName, ttsVoiceId: templateData.ttsVoiceId || this.form.ttsVoiceId, + chatHistoryConf: templateData.chatHistoryConf || this.form.chatHistoryConf, systemPrompt: templateData.systemPrompt || this.form.systemPrompt, langCode: templateData.langCode || this.form.langCode, model: {