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 9c591c35..0e237b8f 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 @@ -9,20 +9,27 @@ import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; + import lombok.AllArgsConstructor; import xiaozhi.common.constant.Constant; import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; +import xiaozhi.common.utils.ConvertUtils; import xiaozhi.common.utils.JsonUtils; +import xiaozhi.modules.agent.dao.AgentVoicePrintDao; import xiaozhi.modules.agent.entity.AgentEntity; import xiaozhi.modules.agent.entity.AgentPluginMapping; import xiaozhi.modules.agent.entity.AgentTemplateEntity; +import xiaozhi.modules.agent.entity.AgentVoicePrintEntity; import xiaozhi.modules.agent.service.AgentMcpAccessPointService; import xiaozhi.modules.agent.service.AgentPluginMappingService; import xiaozhi.modules.agent.service.AgentService; import xiaozhi.modules.agent.service.AgentTemplateService; +import xiaozhi.modules.agent.service.AgentVoicePrintService; +import xiaozhi.modules.agent.vo.AgentVoicePrintVO; import xiaozhi.modules.config.service.ConfigService; import xiaozhi.modules.device.entity.DeviceEntity; import xiaozhi.modules.device.service.DeviceService; @@ -45,6 +52,8 @@ public class ConfigServiceImpl implements ConfigService { private final TimbreService timbreService; private final AgentPluginMappingService agentPluginMappingService; private final AgentMcpAccessPointService agentMcpAccessPointService; + private final AgentVoicePrintService agentVoicePrintService; + private final AgentVoicePrintDao agentVoicePrintDao; @Override public Object getConfig(Boolean isCache) { @@ -162,6 +171,8 @@ public class ConfigServiceImpl implements ConfigService { mcpEndpoint = mcpEndpoint.replace("/mcp/", "/call/"); result.put("mcp_endpoint", mcpEndpoint); } + // 获取声纹信息 + buildVoiceprintConfig(agent.getId(), result); // 构建模块配置 buildModuleConfig( @@ -255,6 +266,62 @@ public class ConfigServiceImpl implements ConfigService { return config; } + /** + * 构建声纹配置信息 + * + * @param agentId 智能体ID + * @param result 结果Map + */ + private void buildVoiceprintConfig(String agentId, Map result) { + try { + // 获取声纹接口地址 + String voiceprintUrl = sysParamsService.getValue("server.voice_print", true); + if (StringUtils.isBlank(voiceprintUrl) || "null".equals(voiceprintUrl)) { + return; + } + + // 获取智能体关联的声纹信息(不需要用户权限验证) + List voiceprints = getVoiceprintsByAgentId(agentId); + if (voiceprints == null || voiceprints.isEmpty()) { + return; + } + + // 构建speakers列表 + List speakers = new ArrayList<>(); + for (AgentVoicePrintVO voiceprint : voiceprints) { + String speakerStr = String.format("%s,%s,%s", + voiceprint.getId(), + voiceprint.getSourceName(), + voiceprint.getIntroduce() != null ? voiceprint.getIntroduce() : ""); + speakers.add(speakerStr); + } + + // 构建声纹配置 + Map voiceprintConfig = new HashMap<>(); + voiceprintConfig.put("url", voiceprintUrl); + voiceprintConfig.put("speakers", speakers); + + result.put("voiceprint", voiceprintConfig); + } catch (Exception e) { + // 声纹配置获取失败时不影响其他功能 + System.err.println("获取声纹配置失败: " + e.getMessage()); + } + } + + /** + * 获取智能体关联的声纹信息 + * + * @param agentId 智能体ID + * @return 声纹信息列表 + */ + private List getVoiceprintsByAgentId(String agentId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(AgentVoicePrintEntity::getAgentId, agentId); + queryWrapper.orderByAsc(AgentVoicePrintEntity::getCreateDate); + List entities = agentVoicePrintDao.selectList(queryWrapper); + return ConvertUtils.sourceToTarget(entities, AgentVoicePrintVO.class); + } + /** * 构建模块配置 * diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index 5c740aa8..bcabe617 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -496,6 +496,9 @@ class ConnectionHandler: ] = plugin_from_server.keys() if private_config.get("prompt", None) is not None: self.config["prompt"] = private_config["prompt"] + # 获取声纹信息 + if private_config.get("voiceprint", None) is not None: + self.config["voiceprint"] = private_config["voiceprint"] 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: @@ -634,25 +637,29 @@ class ConnectionHandler: # 检查是否是JSON格式的消息(包含说话人信息) enhanced_query = query try: - if query.strip().startswith('{') and query.strip().endswith('}'): + if query.strip().startswith("{") and query.strip().endswith("}"): data = json.loads(query) - if 'speaker' in data and 'content' in data: + if "speaker" in data and "content" in data: # 直接使用JSON格式,不重新格式化 enhanced_query = query self.logger.bind(tag=TAG).info(f"识别到说话人: {data['speaker']}") else: # 如果有说话人信息但不是JSON格式,按原逻辑处理 - if hasattr(self, 'current_speaker') and self.current_speaker: + if hasattr(self, "current_speaker") and self.current_speaker: enhanced_query = f"[说话人: {self.current_speaker}] {query}" - self.logger.bind(tag=TAG).info(f"识别到说话人: {self.current_speaker}") + self.logger.bind(tag=TAG).info( + f"识别到说话人: {self.current_speaker}" + ) else: # 如果有说话人信息但不是JSON格式,按原逻辑处理 - if hasattr(self, 'current_speaker') and self.current_speaker: + if hasattr(self, "current_speaker") and self.current_speaker: enhanced_query = f"[说话人: {self.current_speaker}] {query}" - self.logger.bind(tag=TAG).info(f"识别到说话人: {self.current_speaker}") + self.logger.bind(tag=TAG).info( + f"识别到说话人: {self.current_speaker}" + ) except json.JSONDecodeError: # JSON解析失败,按原逻辑处理 - if hasattr(self, 'current_speaker') and self.current_speaker: + if hasattr(self, "current_speaker") and self.current_speaker: enhanced_query = f"[说话人: {self.current_speaker}] {query}" self.logger.bind(tag=TAG).info(f"识别到说话人: {self.current_speaker}")