diff --git a/docs/Deployment.md b/docs/Deployment.md index f020b417..55fef3c3 100644 --- a/docs/Deployment.md +++ b/docs/Deployment.md @@ -139,6 +139,9 @@ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/ conda install libopus -y conda install ffmpeg -y + +# 在 Linux 环境下进行部署时,如出现类似缺失 libiconv.so.2 动态库的报错 请通过以下命令进行安装 +conda install libiconv -y ``` 请注意,以上命令,不是一股脑执行就成功的,你需要一步步执行,每一步执行完后,都检查一下输出的日志,查看是否成功。 @@ -267,7 +270,8 @@ LLM: 6、[我说话很慢,停顿时小智老是抢话](./FAQ.md)
## 部署相关教程 1、[如何自动拉取本项目最新代码自动编译和启动](./dev-ops-integration.md)
-2、[如何与Nginx集成](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791)
+2、[如何部署MQTT网关开启MQTT+UDP协议](./mqtt-gateway-integration.md)
+3、[如何与Nginx集成](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791)
## 拓展相关教程 1、[如何开启手机号码注册智控台](./ali-sms-integration.md)
2、[如何集成HomeAssistant实现智能家居控制](./homeassistant-integration.md)
@@ -275,11 +279,13 @@ LLM: 4、[如何部署MCP接入点](./mcp-endpoint-enable.md)
5、[如何接入MCP接入点](./mcp-endpoint-integration.md)
6、[如何开启声纹识别](./voiceprint-integration.md)
-10、[新闻插件源配置指南](./newsnow_plugin_config.md)
+7、[新闻插件源配置指南](./newsnow_plugin_config.md)
+8、[天气插件使用指南](./weather-integration.md)
## 语音克隆、本地语音部署相关教程 -1、[如何部署集成index-tts本地语音](./index-stream-integration.md)
-2、[如何部署集成fish-speech本地语音](./fish-speech-integration.md)
-3、[如何部署集成PaddleSpeech本地语音](./paddlespeech-deploy.md)
+1、[如何在智控台克隆音色](./huoshan-streamTTS-voice-cloning.md)
+2、[如何部署集成index-tts本地语音](./index-stream-integration.md)
+3、[如何部署集成fish-speech本地语音](./fish-speech-integration.md)
+4、[如何部署集成PaddleSpeech本地语音](./paddlespeech-deploy.md)
## 性能测试教程 1、[各组件速度测试指南](./performance_tester.md)
2、[定期公开测试结果](https://github.com/xinnan-tech/xiaozhi-performance-research)
diff --git a/docs/Deployment_all.md b/docs/Deployment_all.md index c63941dc..f7d87cc3 100644 --- a/docs/Deployment_all.md +++ b/docs/Deployment_all.md @@ -357,7 +357,7 @@ conda install libopus -y conda install ffmpeg -y # 在 Linux 环境下进行部署时,如出现类似缺失 libiconv.so.2 动态库的报错 请通过以下命令进行安装 -conda install libiconv +conda install libiconv -y ``` 请注意,以上命令,不是一股脑执行就成功的,你需要一步步执行,每一步执行完后,都检查一下输出的日志,查看是否成功。 @@ -471,7 +471,8 @@ ws://你电脑局域网的ip:8000/xiaozhi/v1/ 6、[我说话很慢,停顿时小智老是抢话](./FAQ.md)
## 部署相关教程 1、[如何自动拉取本项目最新代码自动编译和启动](./dev-ops-integration.md)
-2、[如何与Nginx集成](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791)
+2、[如何部署MQTT网关开启MQTT+UDP协议](./mqtt-gateway-integration.md)
+3、[如何与Nginx集成](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791)
## 拓展相关教程 1、[如何开启手机号码注册智控台](./ali-sms-integration.md)
2、[如何集成HomeAssistant实现智能家居控制](./homeassistant-integration.md)
@@ -482,9 +483,10 @@ ws://你电脑局域网的ip:8000/xiaozhi/v1/ 7、[新闻插件源配置指南](./newsnow_plugin_config.md)
8、[天气插件使用指南](./weather-integration.md)
## 语音克隆、本地语音部署相关教程 -1、[如何部署集成index-tts本地语音](./index-stream-integration.md)
-2、[如何部署集成fish-speech本地语音](./fish-speech-integration.md)
-3、[如何部署集成PaddleSpeech本地语音](./paddlespeech-deploy.md)
+1、[如何在智控台克隆音色](./huoshan-streamTTS-voice-cloning.md)
+2、[如何部署集成index-tts本地语音](./index-stream-integration.md)
+3、[如何部署集成fish-speech本地语音](./fish-speech-integration.md)
+4、[如何部署集成PaddleSpeech本地语音](./paddlespeech-deploy.md)
## 性能测试教程 1、[各组件速度测试指南](./performance_tester.md)
2、[定期公开测试结果](https://github.com/xinnan-tech/xiaozhi-performance-research)
diff --git a/docs/FAQ.md b/docs/FAQ.md index 0904a17c..844ee3d4 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -62,15 +62,15 @@ VAD: ### 7、部署相关教程 1、[如何进行最简化部署](./Deployment.md)
2、[如何进行全模块部署](./Deployment_all.md)
-2、[如何部署MQTT网关开启MQTT+UDP协议](./mqtt-gateway-integration.md)
-3、[如何自动拉取本项目最新代码自动编译和启动](./dev-ops-integration.md)
-4、[如何与Nginx集成](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791)
+3、[如何部署MQTT网关开启MQTT+UDP协议](./mqtt-gateway-integration.md)
+4、[如何自动拉取本项目最新代码自动编译和启动](./dev-ops-integration.md)
+5、[如何与Nginx集成](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791)
-### 8、编译固件相关教程 +### 9、编译固件相关教程 1、[如何自己编译小智固件](./firmware-build.md)
2、[如何基于虾哥编译好的固件修改OTA地址](./firmware-setting.md)
-### 8、拓展相关教程 +### 10、拓展相关教程 1、[如何开启手机号码注册智控台](./ali-sms-integration.md)
2、[如何集成HomeAssistant实现智能家居控制](./homeassistant-integration.md)
3、[如何开启视觉模型实现拍照识物](./mcp-vision-integration.md)
@@ -79,13 +79,13 @@ VAD: 6、[如何开启声纹识别](./voiceprint-integration.md)
10、[新闻插件源配置指南](./newsnow_plugin_config.md)
-### 9、语音克隆、本地语音部署相关教程 +### 11、语音克隆、本地语音部署相关教程 1、[如何在智控台克隆音色](./huoshan-streamTTS-voice-cloning.md)
2、[如何部署集成index-tts本地语音](./index-stream-integration.md)
3、[如何部署集成fish-speech本地语音](./fish-speech-integration.md)
4、[如何部署集成PaddleSpeech本地语音](./paddlespeech-deploy.md)
-### 10、性能测试教程 +### 12、性能测试教程 1、[各组件速度测试指南](./performance_tester.md)
2、[定期公开测试结果](https://github.com/xinnan-tech/xiaozhi-performance-research)
diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java index e476dc32..a3f9d236 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java @@ -93,7 +93,7 @@ public class DeviceController { } @PostMapping("/bind/{agentId}") - @Operation(summary = "转发POST请求到MQTT网关") + @Operation(summary = "设备在线接口") @RequiresPermissions("sys:role:normal") public Result forwardToMqttGateway(@PathVariable String agentId, @RequestBody String requestBody) { try { @@ -208,63 +208,4 @@ public class DeviceController { deviceService.manualAddDevice(user.getId(), dto); return new Result<>(); } - - @PostMapping("/commands/{deviceId}") - @Operation(summary = "发送设备指令") - @RequiresPermissions("sys:role:normal") - public Result sendDeviceCommand(@PathVariable String deviceId, @RequestBody String command) { - try { - // 从系统参数中获取MQTT网关地址 - String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true); - if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) { - return new Result().error("MQTT网关地址未配置"); - } - - // 构建完整的URL - // 获取设备信息以构建mqttClientId - DeviceEntity deviceById = deviceService.selectById(deviceId); - - if (!deviceById.getUserId().equals(SecurityUser.getUser().getId())) { - return new Result().error("设备不存在"); - } - String macAddress = deviceById != null ? deviceById.getMacAddress() : "unknown"; - String groupId = deviceById != null ? deviceById.getBoard() : null; - if (groupId == null) { - groupId = "GID_default"; - } - groupId = groupId.replace(":", "_"); - macAddress = macAddress.replace(":", "_"); - - // 拼接为groupId@@@macAddress@@@deviceId格式 - String mqttClientId = groupId + "@@@" + macAddress + "@@@" + macAddress; - - String url = "http://" + mqttGatewayUrl + "/api/commands/" + mqttClientId; - - // 设置请求头 - HttpHeaders headers = new HttpHeaders(); - headers.set("Content-Type", "application/json"); - - // 生成Bearer令牌 - String dateStr = java.time.LocalDate.now() - .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")); - String signatureKey = sysParamsService.getValue("server.mqtt_signature_key", false); - if (StringUtils.isBlank(signatureKey)) { - return new Result().error("MQTT签名密钥未配置"); - } - String tokenContent = dateStr + signatureKey; - String token = org.apache.commons.codec.digest.DigestUtils.sha256Hex(tokenContent); - headers.set("Authorization", "Bearer " + token); - - // 构建请求体 - HttpEntity requestEntity = new HttpEntity<>(command, headers); - - // 发送POST请求 - ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); - - // 返回响应 - return new Result().ok(response.getBody()); - } catch (Exception e) { - return new Result().error("发送指令失败: " + e.getMessage()); - } - } } \ No newline at end of file diff --git a/main/manager-web/src/apis/module/device.js b/main/manager-web/src/apis/module/device.js index 03ed3519..bd1697b7 100644 --- a/main/manager-web/src/apis/module/device.js +++ b/main/manager-web/src/apis/module/device.js @@ -102,21 +102,4 @@ export default { }); }).send(); }, - // 发送设备指令 - sendDeviceCommand(deviceId, mcpData, callback) { - RequestService.sendRequest() - .url(`${getServiceUrl()}/device/commands/${deviceId}`) - .method('POST') - .data(mcpData) - .success((res) => { - RequestService.clearRequestTime(); - callback(res); - }) - .networkFail((err) => { - console.error('发送设备指令失败:', err); - RequestService.reAjaxFun(() => { - this.sendDeviceCommand(deviceId, mcpData, callback); - }); - }).send(); - }, } \ No newline at end of file diff --git a/main/manager-web/src/components/McpToolCallDialog.vue b/main/manager-web/src/components/McpToolCallDialog.vue deleted file mode 100644 index d271c3ff..00000000 --- a/main/manager-web/src/components/McpToolCallDialog.vue +++ /dev/null @@ -1,1604 +0,0 @@ - - - - - diff --git a/main/manager-web/src/views/DeviceManagement.vue b/main/manager-web/src/views/DeviceManagement.vue index 053fcbc6..faac1305 100644 --- a/main/manager-web/src/views/DeviceManagement.vue +++ b/main/manager-web/src/views/DeviceManagement.vue @@ -64,9 +64,6 @@ {{ $t('device.unbind') }} - - {{ $t('device.toolCall') }} - @@ -82,9 +79,9 @@ {{ $t('device.manualAdd') }} - {{ - $t('device.unbind') - }} + + {{ $t('device.unbind') }} +
@@ -92,20 +89,22 @@ :label="$t('dictManagement.itemsPerPage').replace('{items}', item)" :value="item"> - - + + - - {{ $t('dictManagement.totalRecords').replace('{total}', deviceList.length) - }} + + + {{ $t('dictManagement.totalRecords').replace('{total}', deviceList.length) }} +
@@ -117,7 +116,6 @@ @refresh="fetchBindDevices(currentAgentId)" /> - @@ -127,20 +125,17 @@ import Api from '@/apis/api'; import AddDeviceDialog from "@/components/AddDeviceDialog.vue"; import HeaderBar from "@/components/HeaderBar.vue"; import ManualAddDeviceDialog from "@/components/ManualAddDeviceDialog.vue"; -import McpToolCallDialog from "@/components/McpToolCallDialog.vue"; export default { components: { HeaderBar, AddDeviceDialog, - ManualAddDeviceDialog, - McpToolCallDialog + ManualAddDeviceDialog }, data() { return { addDeviceDialogVisible: false, manualAddDeviceDialogVisible: false, - mcpToolCallDialogVisible: false, selectedDeviceId: '', searchKeyword: "", activeSearchKeyword: "", @@ -280,11 +275,6 @@ export default { handleManualAddDevice() { this.manualAddDeviceDialogVisible = true; }, - - handleMcpToolCall(deviceId) { - this.selectedDeviceId = deviceId; - this.mcpToolCallDialogVisible = true; - }, submitRemark(row) { if (row._submitting) return; @@ -383,7 +373,7 @@ export default { .sort((a, b) => a.rawBindTime - b.rawBindTime); this.activeSearchKeyword = ""; this.searchKeyword = ""; - + // 获取设备列表后,立即获取设备状态 this.fetchDeviceStatus(agentId); } else { @@ -391,7 +381,7 @@ export default { } }); }, - + // 获取设备状态 fetchDeviceStatus(agentId) { Api.device.getDeviceStatus(agentId, ({ data }) => { @@ -399,7 +389,7 @@ export default { try { // 解析后端返回的设备状态JSON const statusData = JSON.parse(data.data); - + // 直接使用解析后的数据作为设备状态映射(不需要devices字段包装) if (statusData && typeof statusData === 'object') { // 更新设备状态 @@ -411,7 +401,7 @@ export default { } }); }, - + // 根据API响应更新设备状态 updateDeviceStatusFromResponse(deviceStatusMap) { this.deviceList.forEach(device => { @@ -419,11 +409,11 @@ export default { const macAddress = device.macAddress ? device.macAddress.replace(/:/g, '_') : 'unknown'; const groupId = device.model ? device.model.replace(/:/g, '_') : 'GID_default'; const mqttClientId = `${groupId}@@@${macAddress}@@@${macAddress}`; - + // 从状态映射中获取设备状态 if (deviceStatusMap[mqttClientId]) { const statusInfo = deviceStatusMap[mqttClientId]; - + let isOnline = false; if (statusInfo.isAlive === true) { isOnline = true; @@ -434,7 +424,7 @@ export default { } else { isOnline = false; } - + device.deviceStatus = isOnline ? 'online' : 'offline'; } else { // 如果没有找到对应的状态信息,默认为离线 diff --git a/main/xiaozhi-server/config.yaml b/main/xiaozhi-server/config.yaml index 1fca578c..248be252 100644 --- a/main/xiaozhi-server/config.yaml +++ b/main/xiaozhi-server/config.yaml @@ -179,6 +179,9 @@ prompt: | - 长篇大论,叽叽歪歪 - 长时间严肃对话 +# 默认系统提示词模板文件 +prompt_template: agent-base-prompt.txt + # 结束语prompt end_prompt: enable: true # 是否开启结束语 diff --git a/main/xiaozhi-server/core/utils/prompt_manager.py b/main/xiaozhi-server/core/utils/prompt_manager.py index 4cbeefcb..0223f965 100644 --- a/main/xiaozhi-server/core/utils/prompt_manager.py +++ b/main/xiaozhi-server/core/utils/prompt_manager.py @@ -66,7 +66,7 @@ class PromptManager: def _load_base_template(self): """加载基础提示词模板""" try: - template_path = "agent-base-prompt.txt" + template_path = self.config.get("prompt_template", "agent-base-prompt.txt") cache_key = f"prompt_template:{template_path}" # 先从缓存获取 @@ -88,7 +88,7 @@ class PromptManager: self.base_prompt_template = template_content self.logger.bind(tag=TAG).debug("成功加载基础提示词模板并缓存") else: - self.logger.bind(tag=TAG).warning("未找到agent-base-prompt.txt文件") + self.logger.bind(tag=TAG).warning(f"未找到{template_path}文件") except Exception as e: self.logger.bind(tag=TAG).error(f"加载提示词模板失败: {e}") diff --git a/main/xiaozhi-server/performance_tester/performance_tester_llm.py b/main/xiaozhi-server/performance_tester/performance_tester_llm.py index 33430637..769cad6b 100644 --- a/main/xiaozhi-server/performance_tester/performance_tester_llm.py +++ b/main/xiaozhi-server/performance_tester/performance_tester_llm.py @@ -38,7 +38,7 @@ class LLMPerformanceTester: """加载系统提示词""" try: prompt_file = os.path.join( - os.path.dirname(os.path.dirname(__file__)), "agent-base-prompt.txt" + os.path.dirname(os.path.dirname(__file__)), self.config.get("prompt_template", "agent-base-prompt.txt") ) with open(prompt_file, "r", encoding="utf-8") as f: content = f.read()