diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java b/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java index f83e49db..b4bacd42 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java @@ -121,7 +121,7 @@ public class LoginController { @Operation(summary = "公共配置") public Result> pubConfig() { Map config = new HashMap<>(); - config.put("version", "0.3.3"); + config.put("version", "0.3.4"); config.put("allowUserRegister", sysUserService.getAllowUserRegister()); return new Result>().ok(config); } diff --git a/main/manager-api/src/main/resources/db/changelog/202504151205.sql b/main/manager-api/src/main/resources/db/changelog/202504151206.sql similarity index 80% rename from main/manager-api/src/main/resources/db/changelog/202504151205.sql rename to main/manager-api/src/main/resources/db/changelog/202504151206.sql index 0b72121e..cb51cef9 100644 --- a/main/manager-api/src/main/resources/db/changelog/202504151205.sql +++ b/main/manager-api/src/main/resources/db/changelog/202504151206.sql @@ -21,3 +21,8 @@ INSERT INTO `ai_tts_voice` VALUES delete from `sys_params` where id in (103,104); INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (103, 'server.allow_user_register', 'false', 'boolean', 1, '是否运行管理员以外的人注册'); INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (104, 'server.fronted_url', 'http://xiaozhi.server.com', 'string', 1, '下发六位验证码时显示的控制面板地址'); + +-- 修正CosyVoiceSiliconflow音色 +delete from `ai_tts_voice` where tts_model_id = 'TTS_CosyVoiceSiliconflow'; +INSERT INTO `ai_tts_voice` VALUES ('TTS_CosyVoiceSiliconflow0001', 'TTS_CosyVoiceSiliconflow', 'CosyVoice男声', 'FunAudioLLM/CosyVoice2-0.5B:alex', '中文', 'https://example.com/cosyvoice/alex.mp3', NULL, 6, NULL, NULL, NULL, NULL); +INSERT INTO `ai_tts_voice` VALUES ('TTS_CosyVoiceSiliconflow0002', 'TTS_CosyVoiceSiliconflow', 'CosyVoice女声', 'FunAudioLLM/CosyVoice2-0.5B:bella', '中文', 'https://example.com/cosyvoice/bella.mp3', NULL, 6, NULL, NULL, NULL, NULL); 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 7060e32c..178f9ebe 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 @@ -52,9 +52,9 @@ databaseChangeLog: encoding: utf8 path: classpath:db/changelog/202504112058.sql - changeSet: - id: 202504151205 + id: 202504151206 author: John changes: - sqlFile: encoding: utf8 - path: classpath:db/changelog/202504151205.sql + path: classpath:db/changelog/202504151206.sql diff --git a/main/xiaozhi-server/config/logger.py b/main/xiaozhi-server/config/logger.py index 96d1fe65..025be960 100644 --- a/main/xiaozhi-server/config/logger.py +++ b/main/xiaozhi-server/config/logger.py @@ -3,7 +3,7 @@ import sys from loguru import logger from config.config_loader import load_config -SERVER_VERSION = "0.3.3" +SERVER_VERSION = "0.3.4" def get_module_abbreviation(module_name, module_dict): diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index f2cb9499..283fe3f6 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -269,8 +269,6 @@ class ConnectionHandler: self.config["selected_module"]["Intent"] = private_config[ "selected_module" ]["Intent"] - if private_config.get("prompt", None) is not None: - self.config["prompt"] = private_config["prompt"] try: modules = initialize_modules( self.logger, @@ -285,6 +283,10 @@ class ConnectionHandler: except Exception as e: self.logger.bind(tag=TAG).error(f"初始化组件失败: {e}") modules = {} + if modules.get("vad", None) is not None: + self.vad = modules["vad"] + if modules.get("asr", None) is not None: + self.asr = modules["asr"] if modules.get("tts", None) is not None: self.tts = modules["tts"] if modules.get("llm", None) is not None: @@ -293,6 +295,8 @@ class ConnectionHandler: self.intent = modules["intent"] if modules.get("memory", None) is not None: self.memory = modules["memory"] + if modules.get("prompt", None) is not None: + self.change_system_prompt(modules["prompt"]) def _initialize_memory(self): """初始化记忆模块""" diff --git a/main/xiaozhi-server/core/utils/util.py b/main/xiaozhi-server/core/utils/util.py index dd56f5ae..238bf5cb 100644 --- a/main/xiaozhi-server/core/utils/util.py +++ b/main/xiaozhi-server/core/utils/util.py @@ -222,80 +222,93 @@ def initialize_modules( # 初始化TTS模块 if init_tts: + select_tts_module = config["selected_module"]["TTS"] tts_type = ( - config["selected_module"]["TTS"] - if "type" not in config["TTS"][config["selected_module"]["TTS"]] - else config["TTS"][config["selected_module"]["TTS"]]["type"] + select_tts_module + if "type" not in config["TTS"][select_tts_module] + else config["TTS"][select_tts_module]["type"] ) modules["tts"] = tts.create_instance( tts_type, - config["TTS"][config["selected_module"]["TTS"]], + config["TTS"][select_tts_module], bool(config.get("delete_audio", True)), ) - logger.bind(tag=TAG).info(f"初始化组件: tts成功") + logger.bind(tag=TAG).info(f"初始化组件: tts成功 {select_tts_module}") # 初始化LLM模块 if init_llm: + select_llm_module = config["selected_module"]["LLM"] llm_type = ( - config["selected_module"]["LLM"] - if "type" not in config["LLM"][config["selected_module"]["LLM"]] - else config["LLM"][config["selected_module"]["LLM"]]["type"] + select_llm_module + if "type" not in config["LLM"][select_llm_module] + else config["LLM"][select_llm_module]["type"] ) modules["llm"] = llm.create_instance( llm_type, - config["LLM"][config["selected_module"]["LLM"]], + config["LLM"][select_llm_module], ) - logger.bind(tag=TAG).info(f"初始化组件: llm成功") + logger.bind(tag=TAG).info(f"初始化组件: llm成功 {select_llm_module}") # 初始化Intent模块 if init_intent: + select_intent_module = config["selected_module"]["Intent"] intent_type = ( - config["selected_module"]["Intent"] - if "type" not in config["Intent"][config["selected_module"]["Intent"]] - else config["Intent"][config["selected_module"]["Intent"]]["type"] + select_intent_module + if "type" not in config["Intent"][select_intent_module] + else config["Intent"][select_intent_module]["type"] ) modules["intent"] = intent.create_instance( intent_type, - config["Intent"][config["selected_module"]["Intent"]], + config["Intent"][select_intent_module], ) - logger.bind(tag=TAG).info(f"初始化组件: intent成功") + logger.bind(tag=TAG).info(f"初始化组件: intent成功 {select_intent_module}") + # 初始化Memory模块 if init_memory: + select_memory_module = config["selected_module"]["Memory"] memory_type = ( - config["selected_module"]["Memory"] - if "type" not in config["Memory"][config["selected_module"]["Memory"]] - else config["Memory"][config["selected_module"]["Memory"]]["type"] + select_memory_module + if "type" not in config["Memory"][select_memory_module] + else config["Memory"][select_memory_module]["type"] ) modules["memory"] = memory.create_instance( memory_type, - config["Memory"][config["selected_module"]["Memory"]], + config["Memory"][select_memory_module], ) - logger.bind(tag=TAG).info(f"初始化组件: memory成功") + logger.bind(tag=TAG).info(f"初始化组件: memory成功 {select_memory_module}") # 初始化VAD模块 if init_vad: + select_vad_module = config["selected_module"]["VAD"] vad_type = ( - config["selected_module"]["VAD"] - if "type" not in config["VAD"][config["selected_module"]["VAD"]] - else config["VAD"][config["selected_module"]["VAD"]]["type"] + select_vad_module + if "type" not in config["VAD"][select_vad_module] + else config["VAD"][select_vad_module]["type"] ) modules["vad"] = vad.create_instance( vad_type, - config["VAD"][config["selected_module"]["VAD"]], + config["VAD"][select_vad_module], ) - logger.bind(tag=TAG).info(f"初始化组件: vad成功") + logger.bind(tag=TAG).info(f"初始化组件: vad成功 {select_vad_module}") + # 初始化ASR模块 if init_asr: + select_asr_module = config["selected_module"]["ASR"] asr_type = ( - config["selected_module"]["ASR"] - if "type" not in config["ASR"][config["selected_module"]["ASR"]] - else config["ASR"][config["selected_module"]["ASR"]]["type"] + select_asr_module + if "type" not in config["ASR"][select_asr_module] + else config["ASR"][select_asr_module]["type"] ) modules["asr"] = asr.create_instance( asr_type, - config["ASR"][config["selected_module"]["ASR"]], + config["ASR"][select_asr_module], bool(config.get("delete_audio", True)), ) - logger.bind(tag=TAG).info(f"初始化组件: asr成功") + logger.bind(tag=TAG).info(f"初始化组件: asr成功 {select_asr_module}") + + # 初始化自定义prompt + if config.get("prompt", None) is not None: + modules["prompt"] = config["prompt"] + logger.bind(tag=TAG).info(f"初始化组件: prompt成功 {modules['prompt'][:50]}...") return modules diff --git a/main/xiaozhi-server/test/abbreviated_version/app.js b/main/xiaozhi-server/test/abbreviated_version/app.js index 59b75625..b2286524 100644 --- a/main/xiaozhi-server/test/abbreviated_version/app.js +++ b/main/xiaozhi-server/test/abbreviated_version/app.js @@ -992,7 +992,9 @@ function connectToServer() { if(connectButton.id === "connectButton") { connectButton.textContent = '断开'; - connectButton.onclick = disconnectFromServer; + // connectButton.onclick = disconnectFromServer; + connectButton.removeEventListener("click", connectToServer); + connectButton.addEventListener("click", disconnectFromServer); } if(messageInput.id === "messageInput") { @@ -1011,7 +1013,9 @@ function connectToServer() { if(connectButton.id === "connectButton") { connectButton.textContent = '连接'; - connectButton.onclick = connectToServer; + // connectButton.onclick = connectToServer; + connectButton.removeEventListener("click", disconnectFromServer); + connectButton.addEventListener("click", connectToServer); } if(messageInput.id === "messageInput") { @@ -1175,7 +1179,7 @@ function updateStatus(message, type = 'info') { // 处理文本消息 function handleTextMessage(message) { if (message.type === 'hello') { - console.log(`服务器回应:${message.message}`); + console.log(`服务器回应:${JSON.stringify(message, null, 2)}`); } else if (message.type === 'tts') { // TTS状态消息 if (message.state === 'start') { diff --git a/main/xiaozhi-server/test/test_page.html b/main/xiaozhi-server/test/test_page.html index 2735fb5a..35dd57ef 100644 --- a/main/xiaozhi-server/test/test_page.html +++ b/main/xiaozhi-server/test/test_page.html @@ -475,22 +475,36 @@ // 日志函数 function log(message, type = 'info') { - const logEntry = document.createElement('div'); - logEntry.className = `log-entry log-${type}`; - logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; - if (type === 'error') { - logEntry.style.color = 'red'; - } else if (type === 'debug') { - logEntry.style.color = 'gray'; - return; - } else if (type === 'warning') { - logEntry.style.color = 'orange'; - } else if (type === 'success') { - logEntry.style.color = 'green'; - } else { - logEntry.style.color = 'black'; - } - logContainer.appendChild(logEntry); + // 将消息按换行符分割成多行 + const lines = message.split('\n'); + const now = new Date(); + // const timestamp = `[${now.toLocaleTimeString()}] `; + const timestamp = `[${now.toLocaleTimeString()}.${now.getMilliseconds().toString().padStart(3, '0')}] `; + // 为每一行创建日志条目 + lines.forEach((line, index) => { + const logEntry = document.createElement('div'); + logEntry.className = `log-entry log-${type}`; + // 如果是第一条日志,显示时间戳 + const prefix = index === 0 ? timestamp : ' '.repeat(timestamp.length); + logEntry.textContent = `${prefix}${line}`; + // logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; + // logEntry.style 保留起始的空格 + logEntry.style.whiteSpace = 'pre'; + if (type === 'error') { + logEntry.style.color = 'red'; + } else if (type === 'debug') { + logEntry.style.color = 'gray'; + return; + } else if (type === 'warning') { + logEntry.style.color = 'orange'; + } else if (type === 'success') { + logEntry.style.color = 'green'; + } else { + logEntry.style.color = 'black'; + } + logContainer.appendChild(logEntry); + }); + logContainer.scrollTop = logContainer.scrollHeight; } @@ -1153,7 +1167,9 @@ await sendHelloMessage(); connectButton.textContent = '断开'; - connectButton.onclick = disconnectFromServer; + connectButton.removeEventListener('click', connectToServer); + connectButton.addEventListener('click', disconnectFromServer); + // connectButton.onclick = disconnectFromServer; messageInput.disabled = false; sendTextButton.disabled = false; @@ -1169,7 +1185,9 @@ connectionStatus.style.color = 'red'; connectButton.textContent = '连接'; - connectButton.onclick = connectToServer; + connectButton.removeEventListener('click', disconnectFromServer); + connectButton.addEventListener('click', connectToServer); + // connectButton.onclick = connectToServer; messageInput.disabled = true; sendTextButton.disabled = true; recordButton.disabled = true; @@ -1189,7 +1207,7 @@ const message = JSON.parse(event.data); if (message.type === 'hello') { - log(`服务器回应:${message.message}`, 'info'); + log(`服务器回应:${JSON.stringify(message, null, 2)}`, 'success'); } else if (message.type === 'tts') { // TTS状态消息 if (message.state === 'start') {