From 2f5f20a25745f9388b1b4b78ebffe35c99f1b2ed Mon Sep 17 00:00:00 2001 From: ljwwd2 <1205484020@qq.com> Date: Wed, 14 May 2025 03:27:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=99=BA=E6=8E=A7=E5=8F=B0?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E3=80=90=E6=9C=AC=E5=9C=B0=E8=AE=B0=E5=BF=86?= =?UTF-8?q?=E3=80=91=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/controller/AgentController.java | 19 +++++++++++++++++++ .../xiaozhi/modules/agent/dto/AgentDTO.java | 4 ++++ .../modules/agent/dto/AgentUpdateDTO.java | 4 ++++ .../modules/agent/entity/AgentEntity.java | 4 ++++ .../agent/entity/AgentTemplateEntity.java | 4 ++++ .../service/impl/ConfigServiceImpl.java | 4 ++++ .../modules/security/config/ShiroConfig.java | 1 + .../resources/db/changelog/202505122348.sql | 6 ++++++ .../db/changelog/db.changelog-master.yaml | 9 ++++++++- main/manager-web/src/views/roleConfig.vue | 9 +++++++++ .../config/manage_api_client.py | 15 +++++++++++++++ main/xiaozhi-server/core/connection.py | 8 +++++++- .../memory/mem_local_short/mem_local_short.py | 17 ++++++++++++----- main/xiaozhi-server/core/utils/util.py | 1 + 14 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 main/manager-api/src/main/resources/db/changelog/202505122348.sql 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 597cf985..07dba466 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 @@ -46,6 +46,7 @@ import xiaozhi.modules.agent.service.AgentChatAudioService; import xiaozhi.modules.agent.service.AgentChatHistoryService; import xiaozhi.modules.agent.service.AgentService; import xiaozhi.modules.agent.service.AgentTemplateService; +import xiaozhi.modules.device.entity.DeviceEntity; import xiaozhi.modules.device.service.DeviceService; import xiaozhi.modules.security.user.SecurityUser; @@ -109,6 +110,7 @@ public class AgentController { entity.setMemModelId(template.getMemModelId()); entity.setIntentModelId(template.getIntentModelId()); entity.setSystemPrompt(template.getSystemPrompt()); + entity.setSummaryMemory(template.getSummaryMemory()); entity.setChatHistoryConf(template.getChatHistoryConf()); entity.setLangCode(template.getLangCode()); entity.setLanguage(template.getLanguage()); @@ -126,10 +128,24 @@ public class AgentController { return new Result().ok(entity.getId()); } + @PutMapping("/device/{macAddress}") + @Operation(summary = "根据设备id更新智能体") + public Result updateByDeviceId(@PathVariable String macAddress, @RequestBody @Valid AgentUpdateDTO dto) { + DeviceEntity device = deviceService.getDeviceByMacAddress(macAddress); + if (device == null) { + return new Result<>(); + } + return updateAgentById(device.getAgentId(), dto); + } + @PutMapping("/{id}") @Operation(summary = "更新智能体") @RequiresPermissions("sys:role:normal") public Result update(@PathVariable String id, @RequestBody @Valid AgentUpdateDTO dto) { + return updateAgentById(id, dto); + } + + private Result updateAgentById(String id, AgentUpdateDTO dto) { // 先查询现有实体 AgentEntity existingEntity = agentService.getAgentById(id); if (existingEntity == null) { @@ -167,6 +183,9 @@ public class AgentController { if (dto.getSystemPrompt() != null) { existingEntity.setSystemPrompt(dto.getSystemPrompt()); } + if (dto.getSummaryMemory() != null) { + existingEntity.setSummaryMemory(dto.getSummaryMemory()); + } if (dto.getChatHistoryConf() != null) { existingEntity.setChatHistoryConf(dto.getChatHistoryConf()); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java index a63c96e7..0d1ec7b2 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java @@ -30,6 +30,10 @@ public class AgentDTO { @Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题并提供帮助") private String systemPrompt; + @Schema(description = "总结记忆", example = "构建可生长的动态记忆网络,在有限空间内保留关键信息的同时,智能维护信息演变轨迹\n" + + "根据对话记录,总结user的重要信息,以便在未来的对话中提供更个性化的服务", required = false) + private String summaryMemory; + @Schema(description = "最后连接时间", example = "2024-03-20 10:00:00") private Date lastConnectedAt; 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 e3d026e3..ccfbd53f 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,10 @@ public class AgentUpdateDTO implements Serializable { @Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题并提供帮助", required = false) private String systemPrompt; + @Schema(description = "总结记忆", example = "构建可生长的动态记忆网络,在有限空间内保留关键信息的同时,智能维护信息演变轨迹\n" + + "根据对话记录,总结user的重要信息,以便在未来的对话中提供更个性化的服务", required = false) + private String summaryMemory; + @Schema(description = "聊天记录配置(0不记录 1仅记录文本 2记录文本和语音)", example = "3", required = false) private Integer chatHistoryConf; 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 82a20489..1ffc5550 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 @@ -54,6 +54,10 @@ public class AgentEntity { @Schema(description = "角色设定参数") private String systemPrompt; + @Schema(description = "总结记忆", example = "构建可生长的动态记忆网络,在有限空间内保留关键信息的同时,智能维护信息演变轨迹\n" + + "根据对话记录,总结user的重要信息,以便在未来的对话中提供更个性化的服务", required = false) + private String summaryMemory; + @Schema(description = "语言编码") private String langCode; 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 1604a27b..2528ca2c 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 @@ -79,6 +79,10 @@ public class AgentTemplateEntity implements Serializable { */ private String systemPrompt; + /** + * 总结记忆 + */ + private String summaryMemory; /** * 语言编码 */ diff --git a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java index 6ce70ba7..592b3c1d 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java @@ -65,6 +65,7 @@ public class ConfigServiceImpl implements ConfigService { null, null, null, + null, agent.getVadModelId(), agent.getAsrModelId(), null, @@ -134,6 +135,7 @@ public class ConfigServiceImpl implements ConfigService { buildModuleConfig( agent.getAgentName(), agent.getSystemPrompt(), + agent.getSummaryMemory(), voice, agent.getVadModelId(), agent.getAsrModelId(), @@ -234,6 +236,7 @@ public class ConfigServiceImpl implements ConfigService { private void buildModuleConfig( String assistantName, String prompt, + String summaryMemory, String voice, String vadModelId, String asrModelId, @@ -294,5 +297,6 @@ public class ConfigServiceImpl implements ConfigService { prompt = prompt.replace("{{assistant_name}}", StringUtils.isBlank(assistantName) ? "小智" : assistantName); } result.put("prompt", prompt); + result.put("summaryMemory", summaryMemory); } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java b/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java index 5252336f..9780744e 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java @@ -86,6 +86,7 @@ public class ShiroConfig { // 将config路径使用server服务过滤器 filterMap.put("/config/**", "server"); filterMap.put("/agent/chat-history/report", "server"); + filterMap.put("/agent/device/**", "server"); filterMap.put("/agent/play/**", "anon"); filterMap.put("/**", "oauth2"); shiroFilter.setFilterChainDefinitionMap(filterMap); diff --git a/main/manager-api/src/main/resources/db/changelog/202505122348.sql b/main/manager-api/src/main/resources/db/changelog/202505122348.sql new file mode 100644 index 00000000..05bbeb84 --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202505122348.sql @@ -0,0 +1,6 @@ +-- 添加总结记忆字段 +ALTER TABLE `ai_agent` +ADD COLUMN `summary_memory` text COMMENT '总结记忆' AFTER `system_prompt`; + +ALTER TABLE `ai_agent_template` +ADD COLUMN `summary_memory` text COMMENT '总结记忆' AFTER `system_prompt`; diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml index 65ec8972..459a056b 100755 --- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml @@ -120,4 +120,11 @@ databaseChangeLog: changes: - sqlFile: encoding: utf8 - path: classpath:db/changelog/202505111914.sql \ No newline at end of file + path: classpath:db/changelog/202505111914.sql + - changeSet: + id: 202505122348 + author: ljwwd2 + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202505122348.sql \ No newline at end of file diff --git a/main/manager-web/src/views/roleConfig.vue b/main/manager-web/src/views/roleConfig.vue index 00148b7d..51f4955b 100644 --- a/main/manager-web/src/views/roleConfig.vue +++ b/main/manager-web/src/views/roleConfig.vue @@ -40,6 +40,11 @@ + + + + @@ -133,6 +138,7 @@ export default { ttsVoiceId: "", chatHistoryConf: 0, systemPrompt: "", + summaryMemory: "", langCode: "", language: "", sort: "", @@ -188,6 +194,7 @@ export default { memModelId: this.form.model.memModelId, intentModelId: this.form.model.intentModelId, systemPrompt: this.form.systemPrompt, + summaryMemory: this.form.summaryMemory, langCode: this.form.langCode, language: this.form.language, sort: this.form.sort, @@ -219,6 +226,7 @@ export default { ttsVoiceId: "", chatHistoryConf: 0, systemPrompt: "", + summaryMemory: "", langCode: "", language: "", sort: "", @@ -273,6 +281,7 @@ export default { ttsVoiceId: templateData.ttsVoiceId || this.form.ttsVoiceId, chatHistoryConf: templateData.chatHistoryConf || this.form.chatHistoryConf, systemPrompt: templateData.systemPrompt || this.form.systemPrompt, + summaryMemory: templateData.summaryMemory || this.form.summaryMemory, langCode: templateData.langCode || this.form.langCode, model: { ttsModelId: templateData.ttsModelId || this.form.model.ttsModelId, diff --git a/main/xiaozhi-server/config/manage_api_client.py b/main/xiaozhi-server/config/manage_api_client.py index fe3da63c..a42cf5e2 100644 --- a/main/xiaozhi-server/config/manage_api_client.py +++ b/main/xiaozhi-server/config/manage_api_client.py @@ -144,6 +144,21 @@ def get_agent_models( }, ) +def save_mem_local_short( + mac_address: str, short_momery: str +) -> Optional[Dict]: + try: + return ManageApiClient._instance._execute_request( + "PUT", + f"/agent/device/" + mac_address, + json={ + "summaryMemory": short_momery, + }, + ) + except Exception as e: + print(f"存储短期记忆到服务器失败: {e}") + return None + def report( mac_address: str, session_id: str, chat_type: int, content: str, audio diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index 5f2286db..6d1df053 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -388,6 +388,8 @@ class ConnectionHandler: ]["Intent"] if private_config.get("prompt", None) is not None: self.config["prompt"] = private_config["prompt"] + if private_config.get("summaryMemory", None) is not None: + self.config["summaryMemory"] = private_config["summaryMemory"] if private_config.get("device_max_output_size", None) is not None: self.max_output_size = int(private_config["device_max_output_size"]) if private_config.get("chat_history_conf", None) is not None: @@ -421,7 +423,11 @@ class ConnectionHandler: def _initialize_memory(self): """初始化记忆模块""" - self.memory.init_memory(self.device_id, self.llm) + self.memory.init_memory( + self.device_id, + self.llm, + self.config["summaryMemory"] + ) def _initialize_intent(self): self.intent_type = self.config["Intent"][ diff --git a/main/xiaozhi-server/core/providers/memory/mem_local_short/mem_local_short.py b/main/xiaozhi-server/core/providers/memory/mem_local_short/mem_local_short.py index fca7c228..478bc036 100644 --- a/main/xiaozhi-server/core/providers/memory/mem_local_short/mem_local_short.py +++ b/main/xiaozhi-server/core/providers/memory/mem_local_short/mem_local_short.py @@ -4,6 +4,7 @@ import json import os import yaml from config.config_loader import get_project_dir +from config.manage_api_client import save_mem_local_short short_term_memory_prompt = """ @@ -93,17 +94,22 @@ TAG = __name__ class MemoryProvider(MemoryProviderBase): - def __init__(self, config): + def __init__(self, config, summary_memory): super().__init__(config) self.short_momery = "" self.memory_path = get_project_dir() + "data/.memory.yaml" - self.load_memory() + self.load_memory(summary_memory) - def init_memory(self, role_id, llm): + def init_memory(self, role_id, llm, summary_memory=None): super().init_memory(role_id, llm) - self.load_memory() + self.load_memory(summary_memory) + + def load_memory(self, summary_memory): + # api获取到总结记忆后直接返回 + if summary_memory: + self.short_momery = summary_memory + return - def load_memory(self): all_memory = {} if os.path.exists(self.memory_path): with open(self.memory_path, "r", encoding="utf-8") as f: @@ -152,6 +158,7 @@ class MemoryProvider(MemoryProviderBase): print("Error:", e) self.save_memory_to_file() + save_mem_local_short(self.role_id, self.short_momery) logger.bind(tag=TAG).info(f"Save memory successful - Role: {self.role_id}") return self.short_momery diff --git a/main/xiaozhi-server/core/utils/util.py b/main/xiaozhi-server/core/utils/util.py index effbf38e..5ba8d904 100644 --- a/main/xiaozhi-server/core/utils/util.py +++ b/main/xiaozhi-server/core/utils/util.py @@ -319,6 +319,7 @@ def initialize_modules( modules["memory"] = memory.create_instance( memory_type, config["Memory"][select_memory_module], + config['summaryMemory'], ) logger.bind(tag=TAG).info(f"初始化组件: memory成功 {select_memory_module}")