Compare commits

...
161 Commits
Author SHA1 Message Date
欣南科技andGitHub d721270bed Merge pull request #2915 from xinnan-tech/test-arm64-docker
update:兼容arm架构字体
2026-01-28 11:40:26 +08:00
hrz fe2e178b19 update:兼容arm架构字体 2026-01-28 11:39:50 +08:00
欣南科技andGitHub 21337e5046 Merge pull request #2914 from xinnan-tech/test-arm64-docker
update:兼容arm架构字体
2026-01-28 11:34:54 +08:00
hrz 1c8b271e20 update:兼容arm架构字体 2026-01-28 11:34:16 +08:00
欣南科技andGitHub 3d1160b6bb Merge pull request #2913 from xinnan-tech/test-arm64-docker
update:调试编译arm镜像
2026-01-28 11:13:40 +08:00
hrz 086c4a55e6 update:调试编译arm镜像 2026-01-28 11:12:58 +08:00
欣南科技andGitHub 889f2f9a75 Merge pull request #2912 from xinnan-tech/test-arm64-docker
update:兼容arm架构字体
2026-01-28 11:03:04 +08:00
hrz 07b686be14 update:兼容arm架构字体 2026-01-28 11:02:17 +08:00
欣南科技andGitHub 4d6b453485 Merge pull request #2910 from xinnan-tech/test-arm64-docker
add:增加linux/arm64docker镜像编译
2026-01-28 09:16:25 +08:00
hrz 9909045f9d add:增加linux/arm64docker镜像编译 2026-01-28 09:15:40 +08:00
hrzandGitHub b0dc4d88db Merge pull request #2908 from xinnan-tech/py_fix_text
fix: 保存音频数据文件时文本不记录
2026-01-27 17:53:51 +08:00
Sakura-RanChen bbf3858735 fix: 保存音频数据文件时文本不记录 2026-01-27 16:22:35 +08:00
欣南科技andGitHub 73573e2f12 Merge pull request #2907 from xinnan-tech/live2d-actions
update:增加版本号,解决html引用文件缓存问题
2026-01-27 16:13:31 +08:00
hrz 99e136786e update:增加版本号,解决html引用文件缓存问题 2026-01-27 16:12:55 +08:00
欣南科技andGitHub 205be0e4ec Merge pull request #2906 from xinnan-tech/live2d-actions
add:麦克风权限的判断
2026-01-27 16:03:49 +08:00
hrz 2e64f45a31 update:优化代码排版 2026-01-27 15:59:46 +08:00
hrz 818b4f2f6d update:增加版本号,解决html引用文件缓存问题 2026-01-27 15:52:34 +08:00
hrz 5d72f9f79d update:由于现在的模型本身动作有限,使用起来体验不佳,暂时移除动作控制的代码 2026-01-27 15:45:53 +08:00
hrzandGitHub 0ee349df2d Merge pull request #2905 from xinnan-tech/py_fix_minimaxLog
补充minimax接口错误信息
2026-01-27 11:28:17 +08:00
Sakura-RanChen 4dde66339b 补充minimax接口错误信息 2026-01-27 11:22:32 +08:00
hrzandGitHub 0064f975c2 Merge pull request #2903 from spider-yamet/feature/issue-2896-clean
feat: implement Issue 2896 - Live2D Actions and Microphone Detection
2026-01-27 11:17:31 +08:00
rainv123andGitHub 43234f4798 Merge pull request #2836 from xinnan-tech/py_audio_rate
update: 自定义配置输出音频采样率
2026-01-27 10:58:32 +08:00
spider-yamet 48034fc000 Translate log messages to Chinese in recorder.js 2026-01-26 15:03:23 -08:00
spider-yamet 3fc33e9095 Optimize code density: simplify changed files while keeping comments (reduce 364 lines) 2026-01-26 14:48:08 -08:00
spider-yamet da71dce860 Optimize code : minify test files 2026-01-26 14:37:07 -08:00
spider-yamet b7e4408a0f Add browser-based unit tests for xiaozhi test modules
- Add browser-compatible test files (no npm required)

  - recorder.test.browser.js: 8 tests for microphone and HTTP detection

  - tools.test.browser.js: 5 tests for Live2D actions and error handling

- Add test runner (test-runner.html) with built-in test framework

- Add null safety checks in tools.js for DOM element access

- Add documentation (English and Chinese versions)

  - README_TESTS.md / README_TESTS_CN.md: Complete test guide

  - QUICK_START_TEST.md / QUICK_START_TEST_CN.md: Quick start guides

- Total: 13 unit tests covering microphone detection, HTTP detection, Live2D actions, and error handling
2026-01-26 10:18:40 -08:00
spider-yamet 4f4f8ca54e docs: add testing guide and fix Chinese text in controller.js 2026-01-26 08:30:39 -08:00
spider-yamet 99c12a0fed fix: translate corrupted Chinese text to proper Chinese in controller.js 2026-01-26 08:05:02 -08:00
spider-yamet dcd0ef3f40 fix: translate corrupted Chinese text to proper Chinese in controller.js
- Fix corrupted Chinese characters in addMCPTool function
- Translate placeholder and button text to proper Chinese
2026-01-26 07:57:13 -08:00
spider-yamet 2f53b921fe feat: implement Issue 2896 - Live2D Actions and Microphone Detection
- Add Live2D action tools (smile, wave, generic actions) as MCP tools
- Implement microphone availability detection
- Handle HTTP non-localhost access scenarios
- Update UI to reflect microphone availability state
- Translate all comments and messages to proper Chinese/English
- Add test files for new functionality
2026-01-26 07:44:33 -08:00
Sakura-RanChen 3051dc8327 更改默认输出采样率与设备端适配 2026-01-26 17:35:45 +08:00
Sakura-RanChen c313997a61 去除调试输出 2026-01-26 16:33:09 +08:00
欣南科技andGitHub 07c0c764d3 Merge pull request #2898 from xinnan-tech/fix-ChatHistoryConf-value
set ChatHistoryConf default value
2026-01-26 15:11:46 +08:00
hrz e339a501aa set ChatHistoryConf default value 2026-01-26 15:11:11 +08:00
hrzandGitHub f2c541b4ab Merge pull request #2897 from xinnan-tech/fix-path
fix: 修复项目访问地址
2026-01-26 15:07:47 +08:00
zhuoqinglian 206af1c074 fix: 修复项目访问地址 2026-01-26 15:06:05 +08:00
欣南科技andGitHub 344729c9a6 Merge pull request #2895 from xinnan-tech/fix-digital-human-initialize
add:响应mcp初始化请求
2026-01-26 12:51:09 +08:00
hrz 3b1c2d3b1b add:响应mcp初始化请求 2026-01-26 12:42:11 +08:00
wengzhandGitHub 3660af9619 Merge pull request #2881 from xinnan-tech/generator
feat: 添加语音盒子在线烧录功能
2026-01-26 09:41:42 +08:00
zhuoqinglian 4905ba836c fix: 修复语音盒子自定义主题表情无法跟随语气变化问题 2026-01-26 09:33:58 +08:00
Sakura-RanChen ce00c862fe HuoshanDoubleStreamTTS增加自定义配置 2026-01-23 17:16:46 +08:00
zhuoqinglian a50229431b fix: 修复https协议导致无法上传表情的问题 2026-01-23 17:07:23 +08:00
wengzhandGitHub 275102f5b7 Merge pull request #2882 from xinnan-tech/fix-devices-loading
fix: 修复获取设备状态接口报错时, 没有执行失败回调导致loading一直存在
2026-01-23 15:36:46 +08:00
lww155 ff6286ffcc fix: 修复获取设备状态接口报错时, 没有执行失败回调导致loading一直存在 2026-01-23 15:33:44 +08:00
zhuoqinglian 974fe6c3b7 feat: 添加语音盒子在线烧录功能 2026-01-23 15:29:43 +08:00
wengzhandGitHub b78292b270 Merge pull request #2880 from xinnan-tech/perf-manager-api-business
pred:优化MCP工具名称列表顺序问题
2026-01-23 14:13:23 +08:00
DaGou12138 3559a7018c 优化MCP工具名称列表顺序问题 2026-01-23 14:03:00 +08:00
wengzhandGitHub 3222d6175d Merge pull request #2879 from xinnan-tech/fix-digital-human
update: 拨号成功后自动开启录音
2026-01-23 09:22:03 +08:00
lww155 28f9f23449 update: 拨号成功后自动开启录音 2026-01-23 09:13:19 +08:00
wengzhandGitHub 5e7d192ebc Merge pull request #2877 from xinnan-tech/fix-digital-human
update: 调整配置获取
2026-01-22 17:55:46 +08:00
lww155 d6a32416d7 update: 调整配置获取 2026-01-22 17:48:40 +08:00
wengzhandGitHub 6a2c01763e Merge pull request #2876 from xinnan-tech/fix-digital-human
Fix digital human
2026-01-22 17:27:36 +08:00
lww155 e1dd272708 update: 关闭设置框时保存配置, 阻止按钮事件冒泡, 调整配置获取方式 2026-01-22 17:23:27 +08:00
lww155 3e7bc0606a update: 优化背景加载代码 2026-01-22 16:16:09 +08:00
lww155 9d9ca1475d fix: 修复重复请求ota与重复建立连接问题 2026-01-22 15:54:26 +08:00
lww155 43ddc0135c update: 去除未使用代码 2026-01-22 15:39:40 +08:00
欣南科技andGitHub 98f907a97b Merge pull request #2874 from xinnan-tech/manager-mcp-api
update:增加mcp调用后数据类型的判断
2026-01-22 14:46:23 +08:00
hrz b2ddf060c9 update:增加mcp调用后数据类型的判断 2026-01-22 14:42:43 +08:00
欣南科技andGitHub 5e612276db Merge pull request #2873 from xinnan-tech/manager-mcp-api
自定义表情固件接口
2026-01-22 14:02:48 +08:00
hrz cbb293e7fa add:上传自定义表情固件接口 2026-01-22 13:27:10 +08:00
hrz fdb050f6ed add:获取设备的mcp工具列表 2026-01-21 22:58:58 +08:00
wengzhandGitHub f83ddf79fa Merge pull request #2868 from xinnan-tech/fix-digital-human
fix: 修复未绑定设备时状态处理
2026-01-20 17:48:35 +08:00
lww155 95b340a7a3 fix: 修复未绑定设备时状态处理 2026-01-20 17:39:06 +08:00
milieyoandGitHub d46ac89e58 Merge pull request #2867 from xinnan-tech/update-style
style: 优化部分样式,保持一致性
2026-01-20 15:45:00 +08:00
zhuoqinglian 80b0912f84 Merge branch 'main' into update-style 2026-01-20 15:36:22 +08:00
zhuoqinglian e0b4431064 style: 优化部分样式,保持一致性 2026-01-20 15:35:41 +08:00
milieyoandGitHub e3f16f91cf Merge pull request #2863 from xinnan-tech/fix-digital-human
update: 新增聊天输入框
2026-01-20 09:32:23 +08:00
milieyoandGitHub 5f39e5c308 Merge pull request #2860 from xinnan-tech/perf-manager-api-business
perf:优化字典接口、模型接口、音色资源部分业务逻辑
2026-01-20 09:17:24 +08:00
lww155 83304c9ff4 update: 新增聊天输入框 2026-01-20 09:16:45 +08:00
DaGou12138 863cfb575c 优化音色资源相关业务逻辑 2026-01-19 17:55:38 +08:00
DaGou12138 2944040648 优化音色资源相关业务逻辑 2026-01-19 17:19:45 +08:00
DaGou12138 5f19b9b0d0 优化字典接口、模型接口部分业务逻辑 2026-01-19 15:19:48 +08:00
milieyoandGitHub 2948ed091c Merge pull request #2858 from xinnan-tech/perf-manager-api-device
perf:优化知识库相关业务逻辑
2026-01-19 14:24:27 +08:00
DaGou12138 97ee397b54 Merge branch 'refs/heads/main' into perf-manager-api-device 2026-01-19 12:00:07 +08:00
DaGou12138 f7fbe7efbe 优化修改知识库接口部分业务逻辑 2026-01-19 11:59:25 +08:00
hrzandGitHub ce6b0bd099 Merge pull request #2857 from xinnan-tech/build-generator
fix: 修复项目部署二级目录自定义语音盒子主题文件资源异常问题
2026-01-19 11:45:08 +08:00
zhuoqinglian 8643960104 Merge branch 'main' into build-generator 2026-01-19 11:33:11 +08:00
zhuoqinglian b4549ebc59 fix: 修复项目部署二级目录自定义语音盒子主题文件资源异常问题 2026-01-19 11:30:28 +08:00
hrzandGitHub a602cddd05 Merge pull request #2850 from xinnan-tech/build-generator
feat: 添加语音盒子自定义主题功能
2026-01-17 14:04:12 +08:00
hrzandGitHub c4278864d1 Merge pull request #2852 from xinnan-tech/fix_device-mcp
fix: 修复开机立刻唤醒导致客户端 MCP 工具列表为空的问题
2026-01-16 19:02:58 +08:00
3030332422 7094548ecf fix: 修复开机立刻唤醒导致客户端 MCP 工具列表为空的问题 2026-01-16 18:04:04 +08:00
milieyoandGitHub 363fffada8 Merge pull request #2849 from xinnan-tech/fix-multilingual-bug
fix: 语音合成-音色管理,克隆音频路径、克隆音频文本多语言异常处理
2026-01-16 17:14:28 +08:00
milieyoandGitHub c2c3eb7106 Merge pull request #2848 from xinnan-tech/perf-manager-api-device
perf:优化设备在线状态接口相关逻辑
2026-01-16 17:13:30 +08:00
zhuoqinglian 8e19a64f15 fix: 语音合成-音色管理,克隆音频路径、克隆音频文本多语言异常处理 2026-01-16 17:05:46 +08:00
linjiaqin 9042b7e6d7 优化智能体模块相关逻辑 2026-01-16 16:43:04 +08:00
linjiaqin ad1855cfb5 优化设备在线接口相关逻辑 2026-01-16 15:45:42 +08:00
zhuoqinglian efa0d1095d feat: 添加语音盒子自定义主题功能 2026-01-16 14:52:40 +08:00
hrzandGitHub a8c13d740b Merge pull request #2842 from hlleng/fix/model-remark
fix: 修复智控台模型配置中备注不能保存的问题
2026-01-15 20:49:50 +08:00
Honglin Leng 7475e9829f fix: persist model remark on update 2026-01-15 20:15:25 +08:00
milieyoandGitHub b7dde1dae2 Merge pull request #2839 from xinnan-tech/fix-digital-human
修复背景404、通话接通后自动录音、模型加载Loading
2026-01-15 14:26:50 +08:00
lww155 778c4560fd update: 新增模型加载 2026-01-15 09:20:22 +08:00
lww155 fa31096cd8 update: 拨号成功后开启自动录音 2026-01-15 09:19:25 +08:00
Sakura-RanChen fd1dd39463 update: 自定义配置输出音频采样率 2026-01-14 17:54:50 +08:00
lww9029 ecd3e12a41 fix: 切换背景404问题 2026-01-14 11:18:41 +08:00
欣南科技andGitHub 0a8121e849 Merge pull request #2831 from xinnan-tech/test_page_fix
update:修复live2d模型加在路径bug
2026-01-12 18:06:41 +08:00
hrz e93f9d7111 update:修复live2d模型加在路径bug 2026-01-12 18:05:39 +08:00
hrzandGitHub fdf98985a1 Merge pull request #2826 from xinnan-tech/test_page_fix
update:增加live2d模型,修改测试页面样式
2026-01-12 17:44:30 +08:00
hrz 6c3609e79e update:优化图片大小 2026-01-12 17:43:30 +08:00
rainv123 a9aa709502 update:增加live2d模型,修改测试页面样式 2026-01-12 11:00:50 +08:00
milieyoandGitHub 1f6a89ada5 Merge pull request #2823 from xinnan-tech/20260109
调整智能体管理list接口排序,根据创建时间倒序返回
2026-01-09 14:32:22 +08:00
LJH-rgsze 31a1180b79 还原 2026-01-09 14:30:27 +08:00
LJH-rgsze 77b4a416a9 调整智能体管理list接口排序,根据创建时间倒序返回 2026-01-09 14:28:01 +08:00
milieyoandGitHub da7a6933f5 Merge pull request #2818 from xinnan-tech/fix_wakeup_audioRate
修复设备播放音频时打断后使用唤醒词时流控器未重置造成的死锁
2026-01-08 17:27:53 +08:00
Sakura-RanChen 54cac0d2fd fix: 修复当手动设备上个会话正常结束后,使用唤醒词唤醒音频播放不完整 2026-01-08 16:17:48 +08:00
hrzandGitHub 7fe718c887 Merge pull request #2817 from xinnan-tech/py_TTS_text
TTS文本过滤
2026-01-08 14:21:17 +08:00
hrzandGitHub 36eaefb8b0 Merge pull request #2816 from xinnan-tech/20260105
修复音色播放按钮显示错误
2026-01-08 12:39:33 +08:00
hrzandGitHub 3a61ec84b3 移除console打印 2026-01-08 12:39:07 +08:00
Sakura-RanChen c1bf92d243 修复设备播放音频时打断后使用唤醒词时流控器未重置造成的死锁 2026-01-08 11:39:04 +08:00
LJH-rgsze c1959e0795 优化代码逻辑 2026-01-08 10:10:39 +08:00
LJH-rgsze 40a6b7434b 调整判断逻辑 2026-01-07 18:08:43 +08:00
Sakura-RanChen 24519a2732 TTS文本过滤 2026-01-07 17:38:38 +08:00
LJH-rgsze c190abe4b1 用国际化重写硬编码提示 2026-01-07 17:03:56 +08:00
LJH-rgsze 07d5b3cd2a 补充-上个修改上传少了 2026-01-07 16:54:08 +08:00
LJH-rgsze 81e923b4f7 补充音色管理页面缺失的国际化 2026-01-07 16:52:36 +08:00
LJH-rgsze bcb51729a5 修复播放按钮的显示错误 2026-01-07 16:00:35 +08:00
hrzandGitHub a731c1d01f Merge pull request #2811 from xinnan-tech/py_fix_llm_text
修复独立LLM调用时文本未记录
2026-01-06 17:34:07 +08:00
Sakura-RanChen 0bb5a37ace 修复独立LLM调用时文本未记录 2026-01-06 10:29:56 +08:00
hrzandGitHub a711827996 Merge pull request #2810 from xinnan-tech/fix_report_connection
fix: 禁用httpx连接池并显式关闭响应防止连接泄漏,进程文件描述符耗尽
2026-01-05 18:00:41 +08:00
hrzandGitHub 8f854e6f74 Merge pull request #2809 from xinnan-tech/20260105
补充国际化
2026-01-05 17:59:12 +08:00
Sakura-RanChen f1b5afbf5c fix: 禁用httpx连接池并显式关闭响应防止连接泄漏 2026-01-05 17:50:23 +08:00
LJH-rgsze 84f6930389 补充国际化 2026-01-05 17:46:35 +08:00
hrzandGitHub f415dd4482 Merge pull request #2808 from xinnan-tech/20260105
修复音色克隆,ota管理,语音资源管理的分页错误
2026-01-05 17:30:46 +08:00
LJH-rgsze 927f65e106 修复参数名不匹配导致的翻页错误 2026-01-05 17:21:38 +08:00
hrzandGitHub 4b6b3082c7 Merge pull request #2794 from xinnan-tech/20260104SSL
拓展首页的搜索栏-支持同时搜索设备mac和智能体名字
2026-01-05 16:54:20 +08:00
LJH-rgsze 4c550245db 调整判断逻辑 2026-01-05 16:51:09 +08:00
LJH-rgsze 341ed22370 简化代码 2026-01-05 15:27:47 +08:00
LJH-rgsze 6851ccacf3 提取重复代码合并 2026-01-05 15:05:29 +08:00
hrzandGitHub 815af687ea Merge pull request #2798 from xinnan-tech/py_asr_emotion_language
Py asr emotion language
2026-01-05 15:03:50 +08:00
LJH-rgsze e9373b59c8 优化代码 2026-01-05 14:50:23 +08:00
Sakura-RanChen 3f3f3fcd57 更改Funserver使用模型 2026-01-05 14:46:34 +08:00
LJH-rgsze d003e66310 还原部分代码 2026-01-05 11:31:28 +08:00
Sakura-RanChen e6108ccbbd 增加ASR情绪和语种返回 2026-01-05 11:17:04 +08:00
LJH-rgsze a01f01198c 补全参数的返回 2026-01-05 11:13:01 +08:00
LJH-rgsze cc96eaeb8f 修复设备列表显示问题 2026-01-05 10:13:11 +08:00
LJH-rgsze e25ca3d1d3 调整搜索实现-从前端过滤改为后端查询 2026-01-05 10:10:17 +08:00
LJH-rgsze 9c111b2d5e 更新国际化提示 2026-01-04 18:04:26 +08:00
LJH-rgsze 436a01fb6e 删除依赖更新部分(还原) 2026-01-04 17:14:25 +08:00
LJH-rgsze 9b6620dd4a 搜索拓展 2026-01-04 16:53:38 +08:00
Sakura-RanChenandGitHub 85919e800e Merge pull request #2552 from Packeting1/multi_lang_tts
feat: 为阿里百炼流式TTS支持多语言音色
2026-01-04 15:02:24 +08:00
欣南科技andGitHub a2023a65c0 Merge pull request #2789 from xinnan-tech/test_page_token
Bump to 0.8.11
2026-01-02 22:46:55 +08:00
hrz 619370f36c Bump to 0.8.11 2026-01-02 22:45:53 +08:00
欣南科技andGitHub ea6c0e691f Merge pull request #2788 from xinnan-tech/test_page_token
update:删除认证令牌输入框,从ota接口获取令牌
2026-01-02 22:42:48 +08:00
hrz de0d82f1e8 update:删除认证令牌输入框,从ota接口获取令牌 2026-01-02 22:41:37 +08:00
hrzandGitHub c8a26d9c5e Merge pull request #2623 from xinnan-tech/dependabot/pip/main/xiaozhi-server/psutil-7.1.3
build(deps): bump psutil from 7.0.0 to 7.1.3 in /main/xiaozhi-server
2026-01-02 21:50:21 +08:00
hrz d89b842586 update:保留适配本项目python3.10的版本 2026-01-02 21:48:34 +08:00
hrzandGitHub 6dd3ceea7e Merge pull request #2627 from xinnan-tech/dependabot/pip/main/xiaozhi-server/mcp-1.22.0
build(deps): bump mcp from 1.20.0 to 1.22.0 in /main/xiaozhi-server
2026-01-02 21:39:03 +08:00
hrzandGitHub 5fe68030b0 Merge pull request #2626 from xinnan-tech/dependabot/pip/main/xiaozhi-server/torchaudio-2.9.1
build(deps): bump torchaudio from 2.2.2 to 2.9.1 in /main/xiaozhi-server
2026-01-02 21:38:45 +08:00
hrzandGitHub 5215105440 Merge pull request #2625 from xinnan-tech/dependabot/pip/main/xiaozhi-server/websockets-15.0.1
build(deps): bump websockets from 14.2 to 15.0.1 in /main/xiaozhi-server
2026-01-02 21:38:17 +08:00
hrzandGitHub fb69eb751a Merge pull request #2624 from xinnan-tech/dependabot/pip/main/xiaozhi-server/modelscope-1.32.0
build(deps): bump modelscope from 1.23.2 to 1.32.0 in /main/xiaozhi-server
2026-01-02 21:37:33 +08:00
hrzandGitHub b903d51592 Merge pull request #2777 from xinnan-tech/update_blasr_paraformer
Update blasr paraformer
2026-01-02 20:39:43 +08:00
Sakura-RanChen d1f6774e58 update: 增加火山流式情感字段支持 2025-12-30 16:46:04 +08:00
CGDandGitHub 9e55df4141 Merge pull request #2778 from xinnan-tech/fix_mcp_rag
fix:serch_from_ragflow调用失败返回详细错误信息
2025-12-30 11:06:50 +08:00
rainv123 b169e9413f fix:serch_from_ragflow调用失败返回详细错误信息 2025-12-30 11:02:56 +08:00
Sakura-RanChen c511766e9d update: 增加豆包流式多语种识别 2025-12-29 16:38:23 +08:00
FAN-yeB 46abb1009a update:初始化阿里云百炼asr供应器 手动模式待更改 2025-12-26 16:13:14 +08:00
Packeting1 6cdbe45313 feat: 为阿里百炼流式TTS添加多语言音色支持、相关 音色配置; 2025-12-16 11:35:58 +08:00
dependabot[bot]andGitHub 80d10cf4b5 build(deps): bump mcp from 1.20.0 to 1.22.0 in /main/xiaozhi-server
Bumps [mcp](https://github.com/modelcontextprotocol/python-sdk) from 1.20.0 to 1.22.0.
- [Release notes](https://github.com/modelcontextprotocol/python-sdk/releases)
- [Changelog](https://github.com/modelcontextprotocol/python-sdk/blob/main/RELEASE.md)
- [Commits](https://github.com/modelcontextprotocol/python-sdk/compare/v1.20.0...v1.22.0)

---
updated-dependencies:
- dependency-name: mcp
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 10:28:38 +00:00
dependabot[bot]andGitHub ba1fb16f2d build(deps): bump torchaudio from 2.2.2 to 2.9.1 in /main/xiaozhi-server
Bumps [torchaudio](https://github.com/pytorch/audio) from 2.2.2 to 2.9.1.
- [Release notes](https://github.com/pytorch/audio/releases)
- [Commits](https://github.com/pytorch/audio/compare/v2.2.2...v2.9.1)

---
updated-dependencies:
- dependency-name: torchaudio
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 10:28:33 +00:00
dependabot[bot]andGitHub 5f574667d3 build(deps): bump websockets from 14.2 to 15.0.1 in /main/xiaozhi-server
Bumps [websockets](https://github.com/python-websockets/websockets) from 14.2 to 15.0.1.
- [Release notes](https://github.com/python-websockets/websockets/releases)
- [Commits](https://github.com/python-websockets/websockets/compare/14.2...15.0.1)

---
updated-dependencies:
- dependency-name: websockets
  dependency-version: 15.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 10:28:26 +00:00
dependabot[bot]andGitHub c470bb1db1 build(deps): bump modelscope in /main/xiaozhi-server
Bumps [modelscope](https://github.com/modelscope/modelscope) from 1.23.2 to 1.32.0.
- [Release notes](https://github.com/modelscope/modelscope/releases)
- [Commits](https://github.com/modelscope/modelscope/compare/v1.23.2...v1.32.0)

---
updated-dependencies:
- dependency-name: modelscope
  dependency-version: 1.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 10:28:21 +00:00
dependabot[bot]andGitHub 26ed8ca33f build(deps): bump psutil from 7.0.0 to 7.1.3 in /main/xiaozhi-server
Bumps [psutil](https://github.com/giampaolo/psutil) from 7.0.0 to 7.1.3.
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-7.0.0...release-7.1.3)

---
updated-dependencies:
- dependency-name: psutil
  dependency-version: 7.1.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 10:28:16 +00:00
412 changed files with 72903 additions and 2603 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
file: Dockerfile-server-base
push: true
tags: ghcr.io/${{ github.repository }}:server-base
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
cache-from: type=gha,scope=server-base
cache-to: type=gha,mode=max,scope=server-base
build-args: |
+2 -2
View File
@@ -66,7 +66,7 @@ jobs:
push: true
tags: |
${{ env.IS_VERSION == 'true' && format('ghcr.io/{0}:server_{1},ghcr.io/{0}:server_latest', github.repository, env.VERSION) || format('ghcr.io/{0}:server_latest', github.repository) }}
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
@@ -81,7 +81,7 @@ jobs:
push: true
tags: |
${{ env.IS_VERSION == 'true' && format('ghcr.io/{0}:web_{1},ghcr.io/{0}:web_latest', github.repository, env.VERSION) || format('ghcr.io/{0}:web_latest', github.repository) }}
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
+7 -7
View File
@@ -1,5 +1,5 @@
# 第一阶段:构建Vue前端
FROM node:18 as web-builder
FROM node:18 AS web-builder
WORKDIR /app
COPY main/manager-web/package*.json ./
RUN npm install
@@ -7,7 +7,7 @@ COPY main/manager-web .
RUN npm run build
# 第二阶段:构建Java后端
FROM maven:3.9.4-eclipse-temurin-21 as api-builder
FROM maven:3.9.4-eclipse-temurin-21 AS api-builder
WORKDIR /app
COPY main/manager-api/pom.xml .
COPY main/manager-api/src ./src
@@ -18,18 +18,18 @@ FROM bellsoft/liberica-runtime-container:jre-21-glibc
# 安装Nginx和字体库
RUN apk update && \
apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing/ \
apk add --no-cache --no-scripts \
nginx \
bash \
fontconfig \
ttf-dejavu \
msttcorefonts-installer \
&& ACCEPT_EULA=Y apk add --no-cache msttcorefonts-installer \
&& fc-cache -f -v \
&& rm -rf /var/cache/apk/*
# 复制项目自带的中文字体
COPY main/manager-web/public/generator/static/fonts/*.ttf /usr/share/fonts/
# 更新字体缓存
RUN (printf 'YES\n' | update-ms-fonts || true) && fc-cache -f -v
RUN fc-cache -f -v
# 配置Nginx
COPY docs/docker/nginx.conf /etc/nginx/nginx.conf
@@ -43,7 +43,7 @@ public class SwaggerConfig {
public GroupedOpenApi oatApi() {
return GroupedOpenApi.builder()
.group("ota")
.pathsToMatch("/ota/**")
.pathsToMatch("/ota/**", "/otaMag/**")
.build();
}
@@ -304,7 +304,7 @@ public interface Constant {
/**
* 版本号
*/
public static final String VERSION = "0.8.10";
public static final String VERSION = "0.9.1";
/**
* 无效固件URL
@@ -240,4 +240,9 @@ public interface ErrorCode {
int RAG_ADAPTER_CACHE_ERROR = 10191; // 适配器缓存错误
int RAG_ADAPTER_TYPE_NOT_FOUND = 10192; // 适配器类型未找到
// 设备工具相关错误码
int DEVICE_ID_NOT_NULL = 10193; // 设备ID不能为空
int DEVICE_NOT_EXIST = 10194; // 设备不存在
int OTA_UPLOAD_COUNT_EXCEED = 10195; // OTA上传次数超过限制
}
@@ -166,4 +166,25 @@ public class RedisKeys {
public static String getTmpRegisterMacKey(String deviceId) {
return "tmp_register_mac:" + deviceId;
}
/**
* OTA绑定设备
*/
public static String getOtaActivationCode(String activationCode) {
return "ota:activation:code:" + activationCode;
}
/**
* OTA获取设备mac相关信息
*/
public static String getOtaDeviceActivationInfo(String deviceId) {
return "ota:activation:data:" + deviceId;
}
/**
* OTA上传次数
*/
public static String getOtaUploadCountKey(Long username) {
return "ota:upload:count:" + username;
}
}
@@ -0,0 +1,89 @@
package xiaozhi.common.utils;
import cn.hutool.core.util.ReUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 通用工具类
*/
public class ToolUtil {
private static final Logger logger = LoggerFactory.getLogger(ToolUtil.class);
/**
* 对象是否不为空(新增)
*/
public static boolean isNotEmpty(Object o) {
return !isEmpty(o);
}
/**
* 对象是否为空
*/
public static boolean isEmpty(Object o) {
if (o == null) {
return true;
}
if (o instanceof String) {
if (o.toString().trim().equals("")) {
return true;
}
} else if (o instanceof List) {
if (((List) o).size() == 0) {
return true;
}
} else if (o instanceof Map) {
if (((Map) o).size() == 0) {
return true;
}
} else if (o instanceof Set) {
if (((Set) o).size() == 0) {
return true;
}
} else if (o instanceof Object[]) {
if (((Object[]) o).length == 0) {
return true;
}
} else if (o instanceof int[]) {
if (((int[]) o).length == 0) {
return true;
}
} else if (o instanceof long[]) {
if (((long[]) o).length == 0) {
return true;
}
}
return false;
}
/**
* 对象组中是否存在空对象
*/
public static boolean isOneEmpty(Object... os) {
for (Object o : os) {
if (isEmpty(o)) {
return true;
}
}
return false;
}
/**
* 对象组中是否全是空对象
*/
public static boolean isAllEmpty(Object... os) {
for (Object o : os) {
if (!isEmpty(o)) {
return false;
}
}
return true;
}
}
@@ -73,9 +73,13 @@ public class AgentController {
@GetMapping("/list")
@Operation(summary = "获取用户智能体列表")
@RequiresPermissions("sys:role:normal")
public Result<List<AgentDTO>> getUserAgents() {
public Result<List<AgentDTO>> getUserAgents(
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "searchType", defaultValue = "name") String searchType) {
UserDetail user = SecurityUser.getUser();
List<AgentDTO> agents = agentService.getUserAgents(user.getId());
// 直接调用整合后的getUserAgents方法,无需再区分搜索和普通查询
List<AgentDTO> agents = agentService.getUserAgents(user.getId(), keyword, searchType);
return new Result<List<AgentDTO>>().ok(agents);
}
@@ -271,4 +275,6 @@ public class AgentController {
.body(audioData);
}
}
@@ -28,7 +28,7 @@ public class AgentMcpAccessPointController {
/**
* 获取智能体的Mcp接入点地址
*
* @param audioId 智能体id
* @param agentId 智能体id
* @return 返回错误提醒或者Mcp接入点地址
*/
@Operation(summary = "获取智能体的Mcp接入点地址")
@@ -1,6 +1,7 @@
package xiaozhi.modules.agent.dto;
import java.util.Date;
import java.util.List;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -54,9 +54,11 @@ public interface AgentService extends BaseService<AgentEntity> {
* 获取用户智能体列表
*
* @param userId 用户ID
* @param keyword 搜索关键词
* @param searchType 搜索类型(name - 按名称搜索,mac - 按MAC地址搜索)
* @return 智能体列表
*/
List<AgentDTO> getUserAgents(Long userId);
List<AgentDTO> getUserAgents(Long userId, String keyword, String searchType);
/**
* 根据智能体ID获取设备数量
@@ -98,4 +100,6 @@ public interface AgentService extends BaseService<AgentEntity> {
* @return 创建的智能体ID
*/
String createAgent(AgentCreateDTO dto);
}
@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import cn.hutool.core.collection.ListUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -18,6 +19,7 @@ import xiaozhi.common.constant.Constant;
import xiaozhi.common.page.PageData;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.JsonUtils;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.agent.Enums.AgentChatHistoryType;
import xiaozhi.modules.agent.dao.AiAgentChatHistoryDao;
import xiaozhi.modules.agent.dto.AgentChatHistoryDTO;
@@ -86,13 +88,12 @@ public class AgentChatHistoryServiceImpl extends ServiceImpl<AiAgentChatHistoryD
if (deleteAudio) {
// 分批删除音频,避免超时
List<String> audioIds = baseMapper.getAudioIdsByAgentId(agentId);
if (audioIds != null && !audioIds.isEmpty()) {
int batchSize = 1000; // 每批删除1000条
for (int i = 0; i < audioIds.size(); i += batchSize) {
int end = Math.min(i + batchSize, audioIds.size());
List<String> batch = audioIds.subList(i, end);
baseMapper.deleteAudioByIds(batch);
}
if (ToolUtil.isNotEmpty(audioIds)) {
// 每批删除1000条
List<List<String>> batch = ListUtil.split(audioIds, 1000);
batch.forEach(dataList->{
baseMapper.deleteAudioByIds(dataList);
});
}
}
if (deleteAudio && !deleteText) {
@@ -78,11 +78,11 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
// 4. 生成总结(generateSummaryFromMessages方法已包含长度限制逻辑)
String summary = generateSummaryFromMessages(meaningfulMessages, agentId);
System.out.println("成功生成会话 " + sessionId + " 的聊天记录总结,长度: " + summary.length() + " 字符");
log.info("成功生成会话 {} 的聊天记录总结,长度: {} 字符", sessionId, summary.length());
return new AgentChatSummaryDTO(sessionId, agentId, summary);
} catch (Exception e) {
System.err.println("生成会话 " + sessionId + " 的聊天记录总结时发生错误: " + e.getMessage());
log.error("生成会话 {} 的聊天记录总结时发生错误: {}", sessionId, e.getMessage());
return new AgentChatSummaryDTO(sessionId, "生成总结时发生错误: " + e.getMessage());
}
}
@@ -93,14 +93,14 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
// 1. 生成总结
AgentChatSummaryDTO summaryDTO = generateChatSummary(sessionId);
if (!summaryDTO.isSuccess()) {
System.err.println("生成总结失败: " + summaryDTO.getErrorMessage());
log.info("生成总结失败: {}", summaryDTO.getErrorMessage());
return false;
}
// 2. 获取设备信息(通过会话关联的设备)
DeviceEntity device = getDeviceBySessionId(sessionId);
if (device == null) {
System.err.println("未找到与会话 " + sessionId + " 关联的设备");
log.info("未找到与会话 {} 关联的设备", sessionId);
return false;
}
@@ -116,11 +116,11 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
}
});
System.out.println("成功保存会话 " + sessionId + " 的聊天记录总结到智能体 " + device.getAgentId());
log.info("成功保存会话 {} 的聊天记录总结到智能体 {}", sessionId, device.getAgentId());
return true;
} catch (Exception e) {
System.err.println("保存会话 " + sessionId + " 的聊天记录总结时发生错误: " + e.getMessage());
log.error("保存会话 {} 的聊天记录总结时发生错误: {}", sessionId, e.getMessage());
return false;
}
}
@@ -138,7 +138,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
}
return agentChatHistoryService.getChatHistoryBySessionId(agentId, sessionId);
} catch (Exception e) {
System.err.println("获取会话 " + sessionId + " 的聊天记录失败: " + e.getMessage());
log.error("获取会话 {} 的聊天记录失败: {}", sessionId, e.getMessage());
return null;
}
}
@@ -157,7 +157,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
AgentChatHistoryEntity entity = agentChatHistoryService.getOne(wrapper);
return entity != null ? entity.getAgentId() : null;
} catch (Exception e) {
System.err.println("根据会话ID " + sessionId + " 查找智能体ID失败: " + e.getMessage());
log.error("根据会话ID {} 查找智能体ID失败: {}", sessionId, e.getMessage());
return null;
}
}
@@ -272,7 +272,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
return summary;
} catch (Exception e) {
System.err.println("调用Java端LLM服务失败: " + e.getMessage());
log.error("调用Java端LLM服务失败: {}", e.getMessage());
throw new RuntimeException("LLM服务不可用,无法生成聊天总结");
}
}
@@ -295,7 +295,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
// 返回智能体的当前总结记忆
return agentInfo.getSummaryMemory();
} catch (Exception e) {
System.err.println("获取智能体历史记忆失败,agentId: " + agentId + ", 错误: " + e.getMessage());
log.error("获取智能体历史记忆失败,agentId: {}, 错误: {}", agentId, e.getMessage());
return null;
}
}
@@ -309,7 +309,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
String modelId = getMemorySummaryModelId(agentId);
if (StringUtils.isBlank(modelId)) {
System.out.println("未找到记忆总结的LLM模型配置,使用默认LLM服务");
log.info("未找到记忆总结的LLM模型配置,使用默认LLM服务");
return llmService.generateSummaryWithHistory(conversation, historyMemory, null, null);
}
@@ -323,7 +323,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
throw new RuntimeException("Java端LLM服务返回异常: " + summary);
} catch (Exception e) {
System.err.println("调用Java端LLM服务异常,agentId: " + agentId + ", 错误: " + e.getMessage());
log.error("调用Java端LLM服务异常,agentId: {}, 错误: {}", agentId, e.getMessage());
throw e;
}
}
@@ -337,7 +337,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
String modelId = getMemorySummaryModelId(agentId);
if (StringUtils.isBlank(modelId)) {
System.out.println("未找到记忆总结的LLM模型配置,使用默认LLM服务");
log.info("未找到记忆总结的LLM模型配置,使用默认LLM服务");
return llmService.generateSummary(conversation);
}
@@ -351,7 +351,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
throw new RuntimeException("Java端LLM服务返回异常: " + summary);
} catch (Exception e) {
System.err.println("调用Java端LLM服务异常,agentId: " + agentId + ", 错误: " + e.getMessage());
log.error("调用Java端LLM服务异常,agentId: {}, 错误: {}", agentId, e.getMessage());
throw e;
}
}
@@ -394,7 +394,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
return llmModelId;
} catch (Exception e) {
System.err.println("获取记忆总结LLM模型ID失败,agentId: " + agentId + ", 错误: " + e.getMessage());
log.error("获取记忆总结LLM模型ID失败,agentId: {}, 错误: {}", agentId, e.getMessage());
return null;
}
}
@@ -416,7 +416,7 @@ public class AgentChatSummaryServiceImpl implements AgentChatSummaryService {
}
return null;
} catch (Exception e) {
System.err.println("根据会话ID " + sessionId + " 查找设备信息失败: " + e.getMessage());
log.error("根据会话ID {} 查找设备信息失败: {}", sessionId, e.getMessage());
return null;
}
}
@@ -147,6 +147,7 @@ public class AgentMcpAccessPointServiceImpl implements AgentMcpAccessPointServic
List<String> result = toolsList.stream()
.map(tool -> (String) tool.get("name"))
.filter(name -> name != null)
.sorted()
.collect(Collectors.toList());
log.info("成功获取MCP工具列表,智能体ID: {}, 工具数量: {}", id, result.size());
return result;
@@ -5,6 +5,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -28,6 +29,7 @@ import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.JsonUtils;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.agent.dao.AgentDao;
import xiaozhi.modules.agent.dto.AgentCreateDTO;
import xiaozhi.modules.agent.dto.AgentDTO;
@@ -42,6 +44,7 @@ import xiaozhi.modules.agent.service.AgentPluginMappingService;
import xiaozhi.modules.agent.service.AgentService;
import xiaozhi.modules.agent.service.AgentTemplateService;
import xiaozhi.modules.agent.vo.AgentInfoVO;
import xiaozhi.modules.device.entity.DeviceEntity;
import xiaozhi.modules.device.service.DeviceService;
import xiaozhi.modules.model.dto.ModelProviderDTO;
import xiaozhi.modules.model.dto.VoiceDTO;
@@ -84,17 +87,17 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
if (agent.getMemModelId() != null && agent.getMemModelId().equals(Constant.MEMORY_NO_MEM)) {
agent.setChatHistoryConf(Constant.ChatHistoryConfEnum.IGNORE.getCode());
if (agent.getChatHistoryConf() == null) {
agent.setChatHistoryConf(Constant.ChatHistoryConfEnum.RECORD_TEXT_AUDIO.getCode());
}
}
if (agent.getChatHistoryConf() == null) {
agent.setChatHistoryConf(Constant.ChatHistoryConfEnum.RECORD_TEXT_AUDIO.getCode());
}
// 查询上下文源配置
AgentContextProviderEntity contextProviderEntity = agentContextProviderService.getByAgentId(id);
if (contextProviderEntity != null) {
agent.setContextProviders(contextProviderEntity.getContextProviders());
}
// 无需额外查询插件列表,已通过SQL查询出来
return agent;
}
@@ -127,38 +130,70 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
}
@Override
public List<AgentDTO> getUserAgents(Long userId) {
QueryWrapper<AgentEntity> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", userId);
List<AgentEntity> agents = agentDao.selectList(wrapper);
return agents.stream().map(agent -> {
AgentDTO dto = new AgentDTO();
dto.setId(agent.getId());
dto.setAgentName(agent.getAgentName());
dto.setSystemPrompt(agent.getSystemPrompt());
public List<AgentDTO> getUserAgents(Long userId, String keyword, String searchType) {
QueryWrapper<AgentEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId).orderByDesc("created_at");
// 获取 TTS 模型名称
dto.setTtsModelName(modelConfigService.getModelNameById(agent.getTtsModelId()));
// 如果有搜索关键词,根据搜索类型添加相应的查询条件
if (StringUtils.isNotBlank(keyword)) {
if ("mac".equals(searchType)) {
// 按MAC地址搜索:先搜索设备,再获取对应的智能体
List<DeviceEntity> devices = Optional
.ofNullable(deviceService.searchDevicesByMacAddress(keyword, userId)).orElseGet(ArrayList::new);
// 获取设备对应的智能体ID列表
List<String> agentIds = devices.stream()
.map(DeviceEntity::getAgentId)
.distinct()
.collect(Collectors.toList());
if (ToolUtil.isNotEmpty(agentIds)) {
queryWrapper.in("id", agentIds);
} else {
return new ArrayList<>();
}
} else {
// 按名称搜索
queryWrapper.like("agent_name", keyword);
}
}
// 获取 LLM 模型名称
dto.setLlmModelName(modelConfigService.getModelNameById(agent.getLlmModelId()));
// 执行查询
List<AgentEntity> agentEntities = baseDao.selectList(queryWrapper);
// 获取 VLLM 模型名称
dto.setVllmModelName(modelConfigService.getModelNameById(agent.getVllmModelId()));
// 转换为DTO并设置所有必要字段
return agentEntities.stream().map(this::buildAgentDTO).collect(Collectors.toList());
}
// 获取记忆模型名称
dto.setMemModelId(agent.getMemModelId());
/**
* 将AgentEntity转换为AgentDTO
*/
private AgentDTO buildAgentDTO(AgentEntity agent) {
AgentDTO dto = new AgentDTO();
dto.setId(agent.getId());
dto.setAgentName(agent.getAgentName());
dto.setSystemPrompt(agent.getSystemPrompt());
// 获取 TTS 音色名称
dto.setTtsVoiceName(timbreModelService.getTimbreNameById(agent.getTtsVoiceId()));
// 获取 TTS 模型名称
dto.setTtsModelName(modelConfigService.getModelNameById(agent.getTtsModelId()));
// 获取智能体最近的最后连接时长
dto.setLastConnectedAt(deviceService.getLatestLastConnectionTime(agent.getId()));
// 获取 LLM 模型名称
dto.setLlmModelName(modelConfigService.getModelNameById(agent.getLlmModelId()));
// 获取设备数量
dto.setDeviceCount(getDeviceCountByAgentId(agent.getId()));
return dto;
}).collect(Collectors.toList());
// 获取 VLLM 模型名称
dto.setVllmModelName(modelConfigService.getModelNameById(agent.getVllmModelId()));
// 获取记忆模型名称
dto.setMemModelId(agent.getMemModelId());
// 获取 TTS 音色名称
dto.setTtsVoiceName(timbreModelService.getTimbreNameById(agent.getTtsVoiceId()));
// 获取智能体最近的最后连接时长
dto.setLastConnectedAt(deviceService.getLatestLastConnectionTime(agent.getId()));
// 获取设备数量
dto.setDeviceCount(getDeviceCountByAgentId(agent.getId()));
return dto;
}
@Override
@@ -468,4 +503,5 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
agentPluginMappingService.saveBatch(toInsert);
return entity.getId();
}
}
}
@@ -163,11 +163,11 @@ public class ConfigServiceImpl implements ConfigService {
}
result.put("chat_history_conf", chatHistoryConf);
// 如果客户端已实例化模型,则不返回
String alreadySelectedVadModelId = (String) selectedModule.get("VAD");
String alreadySelectedVadModelId = selectedModule.get("VAD");
if (alreadySelectedVadModelId != null && alreadySelectedVadModelId.equals(agent.getVadModelId())) {
agent.setVadModelId(null);
}
String alreadySelectedAsrModelId = (String) selectedModule.get("ASR");
String alreadySelectedAsrModelId = selectedModule.get("ASR");
if (alreadySelectedAsrModelId != null && alreadySelectedAsrModelId.equals(agent.getAsrModelId())) {
agent.setAsrModelId(null);
}
@@ -302,7 +302,7 @@ public class ConfigServiceImpl implements ConfigService {
private void buildVoiceprintConfig(String agentId, Map<String, Object> result) {
try {
// 获取声纹接口地址
String voiceprintUrl = sysParamsService.getValue("server.voice_print", true);
String voiceprintUrl = sysParamsService.getValue(Constant.SERVER_VOICE_PRINT, true);
if (StringUtils.isBlank(voiceprintUrl) || "null".equals(voiceprintUrl)) {
return;
}
@@ -1,14 +1,11 @@
package xiaozhi.modules.device.controller;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@@ -16,9 +13,6 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -30,6 +24,7 @@ import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.Result;
import xiaozhi.modules.device.dto.DeviceManualAddDTO;
import xiaozhi.modules.device.dto.DeviceRegisterDTO;
import xiaozhi.modules.device.dto.DeviceToolsCallReqDTO;
import xiaozhi.modules.device.dto.DeviceUnBindDTO;
import xiaozhi.modules.device.dto.DeviceUpdateDTO;
import xiaozhi.modules.device.entity.DeviceEntity;
@@ -44,16 +39,11 @@ public class DeviceController {
private final DeviceService deviceService;
private final RedisUtils redisUtils;
private final SysParamsService sysParamsService;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
public DeviceController(DeviceService deviceService, RedisUtils redisUtils, SysParamsService sysParamsService,
RestTemplate restTemplate, ObjectMapper objectMapper) {
public DeviceController(DeviceService deviceService, RedisUtils redisUtils, SysParamsService sysParamsService) {
this.deviceService = deviceService;
this.redisUtils = redisUtils;
this.sysParamsService = sysParamsService;
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
}
@PostMapping("/bind/{agentId}/{deviceCode}")
@@ -99,83 +89,12 @@ public class DeviceController {
@RequiresPermissions("sys:role:normal")
public Result<String> forwardToMqttGateway(@PathVariable String agentId, @RequestBody String requestBody) {
try {
// 从系统参数中获取MQTT网关地址
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) {
return new Result<>();
}
// 获取当前用户的设备列表
UserDetail user = SecurityUser.getUser();
List<DeviceEntity> devices = deviceService.getUserDevices(user.getId(), agentId);
// 构建deviceIds数组
java.util.List<String> deviceIds = new java.util.ArrayList<>();
for (DeviceEntity device : devices) {
String macAddress = device.getMacAddress() != null ? device.getMacAddress() : "unknown";
String groupId = device.getBoard() != null ? device.getBoard() : "GID_default";
// 替换冒号为下划线
groupId = groupId.replace(":", "_");
macAddress = macAddress.replace(":", "_");
// 构建mqtt客户端ID格式:groupId@@@macAddress@@@macAddress
String mqttClientId = groupId + "@@@" + macAddress + "@@@" + macAddress;
deviceIds.add(mqttClientId);
}
// 构建完整的URL
String url = "http://" + mqttGatewayUrl + "/api/devices/status";
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
// 生成Bearer令牌
String token = generateBearerToken();
if (token == null) {
return new Result<String>().error("令牌生成失败");
}
headers.set("Authorization", "Bearer " + token);
// 构建请求体JSON
String jsonBody = "{\"clientIds\":" + objectMapper.writeValueAsString(deviceIds) + "}";
HttpEntity<String> requestEntity = new HttpEntity<>(jsonBody, headers);
// 发送POST请求
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
// 返回响应
return new Result<String>().ok(response.getBody());
return new Result<String>().ok(deviceService.getDeviceOnlineData(agentId));
} catch (Exception e) {
return new Result<String>().error("转发请求失败: " + e.getMessage());
}
}
private String generateBearerToken() {
try {
// 获取当前日期,格式为yyyy-MM-dd
String dateStr = java.time.LocalDate.now()
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 获取MQTT签名密钥
String signatureKey = sysParamsService.getValue("server.mqtt_signature_key", false);
if (StringUtils.isBlank(signatureKey)) {
return null;
}
// 将日期字符串与MQTT_SIGNATURE_KEY连接
String tokenContent = dateStr + signatureKey;
// 对连接后的字符串进行SHA256哈希计算
String token = org.apache.commons.codec.digest.DigestUtils.sha256Hex(tokenContent);
return token;
} catch (Exception e) {
return null;
}
}
@PostMapping("/unbind")
@Operation(summary = "解绑设备")
@RequiresPermissions("sys:role:normal")
@@ -210,4 +129,34 @@ public class DeviceController {
deviceService.manualAddDevice(user.getId(), dto);
return new Result<>();
}
@PostMapping("/tools/list/{deviceId}")
@Operation(summary = "获取设备工具列表")
@RequiresPermissions("sys:role:normal")
public Result<Object> getDeviceTools(@PathVariable String deviceId) {
Object toolsData = deviceService.getDeviceTools(deviceId);
if (toolsData == null) {
return new Result<Object>().error(ErrorCode.DEVICE_NOT_EXIST);
}
return new Result<Object>().ok(toolsData);
}
@PostMapping("/tools/call/{deviceId}")
@Operation(summary = "调用设备工具")
@RequiresPermissions("sys:role:normal")
public Result<Object> callDeviceTool(@PathVariable String deviceId,
@Valid @RequestBody DeviceToolsCallReqDTO request) {
String toolName = request.getName();
Map<String, Object> arguments = request.getArguments();
Object result = deviceService.callDeviceTool(deviceId, toolName, arguments);
if (result == null) {
return new Result<Object>().error(ErrorCode.DEVICE_NOT_EXIST);
}
Result<Object> response = new Result<Object>();
response.setMsg("Tools called successfully");
return response.ok(result);
}
}
@@ -7,7 +7,9 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
@@ -36,6 +38,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import xiaozhi.common.constant.Constant;
import xiaozhi.common.exception.ErrorCode;
import xiaozhi.common.page.PageData;
import xiaozhi.common.redis.RedisKeys;
import xiaozhi.common.redis.RedisUtils;
@@ -43,8 +46,11 @@ import xiaozhi.common.utils.Result;
import xiaozhi.common.validator.ValidatorUtils;
import xiaozhi.modules.device.entity.OtaEntity;
import xiaozhi.modules.device.service.OtaService;
import xiaozhi.modules.security.user.SecurityUser;
import xiaozhi.modules.sys.enums.SuperAdminEnum;
import xiaozhi.modules.sys.service.SysParamsService;
@Tag(name = "设备管理", description = "OTA 相关接口")
@Tag(name = "固件升级管理", description = "OTA 相关接口")
@Slf4j
@RestController
@RequiredArgsConstructor
@@ -53,6 +59,7 @@ public class OTAMagController {
private static final Logger logger = LoggerFactory.getLogger(OTAController.class);
private final OtaService otaService;
private final RedisUtils redisUtils;
private final SysParamsService sysParamsService;
@GetMapping
@Operation(summary = "分页查询 OTA 固件信息")
@@ -145,15 +152,11 @@ public class OTAMagController {
// 检查下载次数
String downloadCountKey = RedisKeys.getOtaDownloadCountKey(uuid);
Integer downloadCount = (Integer) redisUtils.get(downloadCountKey);
if (downloadCount == null) {
downloadCount = 0;
}
Integer downloadCount = (Integer) Optional.ofNullable(redisUtils.get(downloadCountKey)).orElse(0);
// 如果下载次数超过3次,返回404
if (downloadCount >= 3) {
redisUtils.delete(downloadCountKey);
redisUtils.delete(RedisKeys.getOtaIdKey(uuid));
redisUtils.delete(List.of(downloadCountKey, RedisKeys.getOtaIdKey(uuid)));
logger.warn("Download limit exceeded for UUID: {}", uuid);
return ResponseEntity.notFound().build();
}
@@ -162,7 +165,17 @@ public class OTAMagController {
try {
// 获取固件信息
OtaEntity otaEntity = otaService.selectById(id);
OtaEntity otaEntity = null;
if (id.indexOf("file:") == 0) {
id = id.substring(5);
otaEntity = new OtaEntity();
otaEntity.setFirmwarePath(id);
otaEntity.setType("assets");
otaEntity.setVersion("1.0.0");
} else {
otaEntity = otaService.selectById(id);
}
if (otaEntity == null || StringUtils.isBlank(otaEntity.getFirmwarePath())) {
logger.warn("Firmware not found or path is empty for ID: {}", id);
return ResponseEntity.notFound().build();
@@ -170,6 +183,7 @@ public class OTAMagController {
// 获取文件路径 - 确保路径是绝对路径或正确的相对路径
String firmwarePath = otaEntity.getFirmwarePath();
String originalFilename = otaEntity.getType() + "_" + otaEntity.getVersion();
Path path;
// 检查是否是绝对路径
@@ -203,7 +217,7 @@ public class OTAMagController {
byte[] fileContent = Files.readAllBytes(path);
// 设置响应头
String originalFilename = otaEntity.getType() + "_" + otaEntity.getVersion();
if (firmwarePath.contains(".")) {
String extension = firmwarePath.substring(firmwarePath.lastIndexOf("."));
originalFilename += extension;
@@ -279,6 +293,42 @@ public class OTAMagController {
}
}
@PostMapping("/uploadAssetsBin")
@Operation(summary = "上传资源固件文件")
@RequiresPermissions("sys:role:normal")
public Result<String> uploadAssetsBin(@RequestParam("file") MultipartFile file) {
String otaUrl = sysParamsService.getValue(Constant.SERVER_OTA, true);
if (StringUtils.isBlank(otaUrl) || otaUrl.equals("null")) {
return new Result<String>().error(ErrorCode.OTA_URL_EMPTY);
}
logger.info("username:{},uploadAssetsBin size: {}", SecurityUser.getUser().getUsername(), file.getSize());
// 验证文件大小 (资源固件最大20MB)
if (file.getSize() > 20 * 1024 * 1024) {
return new Result<String>().error(ErrorCode.VOICE_CLONE_AUDIO_TOO_LARGE);
}
// 普通用户只能每天上传50次
if (SecurityUser.getUser().getSuperAdmin() == SuperAdminEnum.NO.value()) {
String uploadCountKey = RedisKeys.getOtaUploadCountKey(SecurityUser.getUser().getId());
Integer uploadCount = (Integer) Optional.ofNullable(redisUtils.get(uploadCountKey)).orElse(0);
if (uploadCount >= 50) {
return new Result<String>().error(ErrorCode.OTA_UPLOAD_COUNT_EXCEED);
}
// 增加上传次数
redisUtils.increment(RedisKeys.getOtaUploadCountKey(SecurityUser.getUser().getId()),
RedisUtils.DEFAULT_EXPIRE);
}
Result<String> result = uploadFirmware(file);
// 生成资源文件路径
if (StringUtils.isNotBlank(result.getData())) {
String uuid = UUID.randomUUID().toString();
redisUtils.set(RedisKeys.getOtaIdKey(uuid), "file:" + result.getData());
String downloadUrl = otaUrl.replace("/ota/", "/otaMag/download/") + uuid;
result.setData(downloadUrl);
}
return result;
}
private String calculateMD5(MultipartFile file) throws IOException, NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(file.getBytes());
@@ -0,0 +1,15 @@
package xiaozhi.modules.device.dto;
import java.util.Map;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class DeviceToolsCallReqDTO {
@NotBlank(message = "工具名称不能为空")
private String name;
private Map<String, Object> arguments;
}
@@ -2,17 +2,22 @@ package xiaozhi.modules.device.service;
import java.util.Date;
import java.util.List;
import java.util.Map;
import xiaozhi.common.page.PageData;
import xiaozhi.common.service.BaseService;
import xiaozhi.modules.device.dto.DeviceManualAddDTO;
import xiaozhi.modules.device.dto.DevicePageUserDTO;
import xiaozhi.modules.device.dto.DeviceReportReqDTO;
import xiaozhi.modules.device.dto.DeviceReportRespDTO;
import xiaozhi.modules.device.dto.DeviceManualAddDTO;
import xiaozhi.modules.device.entity.DeviceEntity;
import xiaozhi.modules.device.vo.UserShowDeviceListVO;
public interface DeviceService extends BaseService<DeviceEntity> {
/**
* 获取设备在线数据
*/
String getDeviceOnlineData(String agentId);
/**
* 检查设备是否激活
@@ -83,6 +88,7 @@ public interface DeviceService extends BaseService<DeviceEntity> {
/**
* 获取这个智能体设备理的最近的最后连接时间
*
* @param agentId 智能体id
* @return 返回设备最近的最后连接时间
*/
@@ -108,4 +114,23 @@ public interface DeviceService extends BaseService<DeviceEntity> {
*/
String generateWebSocketToken(String clientId, String username) throws Exception;
/**
* 根据MAC地址搜索设备
*
* @param macAddress MAC地址关键词
* @param userId 用户ID
* @return 设备列表
*/
List<DeviceEntity> searchDevicesByMacAddress(String macAddress, Long userId);
/**
* 获取设备工具列表
*/
Object getDeviceTools(String deviceId);
/**
* 调用设备工具
*/
Object callDeviceTool(String deviceId, String toolName, Map<String, Object> arguments);
}
@@ -9,8 +9,11 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@@ -26,7 +29,16 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -40,6 +52,7 @@ import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.DateUtils;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.device.dao.DeviceDao;
import xiaozhi.modules.device.dto.DeviceManualAddDTO;
import xiaozhi.modules.device.dto.DevicePageUserDTO;
@@ -88,16 +101,16 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
if (StringUtils.isBlank(activationCode)) {
throw new RenException(ErrorCode.ACTIVATION_CODE_EMPTY);
}
String deviceKey = "ota:activation:code:" + activationCode;
String deviceKey = RedisKeys.getOtaActivationCode(activationCode);
Object cacheDeviceId = redisUtils.get(deviceKey);
if (cacheDeviceId == null) {
if (ToolUtil.isEmpty(cacheDeviceId)) {
throw new RenException(ErrorCode.ACTIVATION_CODE_ERROR);
}
String deviceId = (String) cacheDeviceId;
String safeDeviceId = deviceId.replace(":", "_").toLowerCase();
String cacheDeviceKey = String.format("ota:activation:data:%s", safeDeviceId);
String cacheDeviceKey = RedisKeys.getOtaDeviceActivationInfo(safeDeviceId);
Map<String, Object> cacheMap = (Map<String, Object>) redisUtils.get(cacheDeviceKey);
if (cacheMap == null) {
if (ToolUtil.isEmpty(cacheMap)) {
throw new RenException(ErrorCode.ACTIVATION_CODE_ERROR);
}
String cachedCode = (String) cacheMap.get("activation_code");
@@ -133,19 +146,56 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
deviceEntity.setLastConnectedAt(currentTime);
deviceDao.insert(deviceEntity);
// 清理redis缓存
redisUtils.delete(cacheDeviceKey);
redisUtils.delete(deviceKey);
// 添加:清除智能体设备数量缓存
redisUtils.delete(RedisKeys.getAgentDeviceCountById(agentId));
// 清理redis缓存、清除智能体设备数量缓存
redisUtils.delete(List.of(cacheDeviceKey, deviceKey, RedisKeys.getAgentDeviceCountById(agentId)));
return true;
}
/**
* 获取设备在线数据
*/
@Override
public DeviceReportRespDTO checkDeviceActive(String macAddress, String clientId,
DeviceReportReqDTO deviceReport) {
public String getDeviceOnlineData(String agentId) {
// 从系统参数中获取MQTT网关地址
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) {
return "";
}
// 构建完整的URL
String url = StrUtil.format("http://{}/api/devices/status", mqttGatewayUrl);
// 获取当前用户的设备列表
UserDetail user = SecurityUser.getUser();
List<DeviceEntity> devices = getUserDevices(user.getId(), agentId);
// 构建deviceIds数组
Set<String> deviceIds = devices.stream().map(o -> {
String macAddress = Optional.ofNullable(o.getMacAddress()).orElse("unknown").replace(":", "_");
String groupId = Optional.ofNullable(o.getBoard()).orElse("GID_default").replace(":", "_");
return StrUtil.format("{}@@@{}@@@{}", groupId, macAddress, macAddress);
}).collect(Collectors.toSet());
// 构建请求入参
Map<String, Set<String>> params = MapUtil
.builder(new HashMap<String, Set<String>>())
.put("clientIds", deviceIds).build();
if (ToolUtil.isNotEmpty(deviceIds)) {
// 发送请求
String resultMessage = HttpRequest.post(url)
.header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
.header(Header.AUTHORIZATION, "Bearer " + generateBearerToken())
.body(JSONUtil.toJsonStr(params))
.timeout(10000) // 超时,毫秒
.execute().body();
return resultMessage;
}
// 返回响应
return "";
}
@Override
public DeviceReportRespDTO checkDeviceActive(String macAddress, String clientId, DeviceReportReqDTO deviceReport) {
DeviceReportRespDTO response = new DeviceReportRespDTO();
response.setServer_time(buildServerTime());
@@ -356,8 +406,7 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
private String getDeviceCacheKey(String deviceId) {
String safeDeviceId = deviceId.replace(":", "_").toLowerCase();
String dataKey = String.format("ota:activation:data:%s", safeDeviceId);
return dataKey;
return RedisKeys.getOtaDeviceActivationInfo(safeDeviceId);
}
public DeviceReportRespDTO.Activation buildActivation(String deviceId, DeviceReportReqDTO deviceReport) {
@@ -396,7 +445,7 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
redisUtils.set(dataKey, dataMap);
// 写入反查激活码 key
String codeKey = "ota:activation:code:" + newCode;
String codeKey = RedisKeys.getOtaActivationCode(newCode);
redisUtils.set(codeKey, deviceId);
}
return code;
@@ -496,6 +545,14 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
redisUtils.delete(RedisKeys.getAgentDeviceCountById(dto.getAgentId()));
}
@Override
public List<DeviceEntity> searchDevicesByMacAddress(String macAddress, Long userId) {
QueryWrapper<DeviceEntity> wrapper = new QueryWrapper<>();
wrapper.like("mac_address", macAddress);
wrapper.eq("user_id", userId);
return deviceDao.selectList(wrapper);
}
/**
* 生成MQTT密码签名
*
@@ -598,4 +655,176 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
return mqtt;
}
/**
* 生成BearerToken
*/
private String generateBearerToken() {
try {
String dateStr = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
String signatureKey = sysParamsService.getValue(Constant.SERVER_MQTT_SECRET, false);
if (ToolUtil.isEmpty(signatureKey)) {
return null;
}
return DigestUtil.sha256Hex(dateStr + signatureKey);
} catch (Exception e) {
return null;
}
}
@Override
public Object getDeviceTools(String deviceId) {
// 从系统参数中获取MQTT网关地址
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) {
return null;
}
// 获取设备信息
DeviceEntity device = baseDao.selectById(deviceId);
if (device == null) {
return null;
}
// 检查设备是否属于当前用户
UserDetail user = SecurityUser.getUser();
if (!device.getUserId().equals(user.getId())) {
return null;
}
// 构建clientId
String macAddress = Optional.ofNullable(device.getMacAddress()).orElse("unknown").replace(":", "_");
String groupId = Optional.ofNullable(device.getBoard()).orElse("GID_default").replace(":", "_");
String clientId = StrUtil.format("{}@@@{}@@@{}", groupId, macAddress, macAddress);
// 构建完整的URL
String url = StrUtil.format("http://{}/api/commands/{}", mqttGatewayUrl, clientId);
// 构建请求体
Map<String, Object> payload = MapUtil
.builder(new HashMap<String, Object>())
.put("jsonrpc", "2.0")
.put("id", 2)
.put("method", "tools/list")
.put("params", MapUtil.builder(new HashMap<String, Object>())
.put("withUserTools", true)
.build())
.build();
Map<String, Object> requestBody = MapUtil
.builder(new HashMap<String, Object>())
.put("type", "mcp")
.put("payload", payload)
.build();
// 发送请求
String resultMessage = HttpRequest.post(url)
.header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
.header(Header.AUTHORIZATION, "Bearer " + generateBearerToken())
.body(JSONUtil.toJsonStr(requestBody))
.timeout(10000) // 超时,毫秒
.execute().body();
// 解析响应
if (StringUtils.isNotBlank(resultMessage)) {
cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(resultMessage);
if (jsonObject.getBool("success", false)) {
return jsonObject.get("data");
}
}
return null;
}
@Override
public Object callDeviceTool(String deviceId, String toolName, Map<String, Object> arguments) {
// 从系统参数中获取MQTT网关地址
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) {
return null;
}
// 获取设备信息
DeviceEntity device = baseDao.selectById(deviceId);
if (device == null) {
return null;
}
// 检查设备是否属于当前用户
UserDetail user = SecurityUser.getUser();
if (!device.getUserId().equals(user.getId())) {
return null;
}
// 构建clientId
String macAddress = Optional.ofNullable(device.getMacAddress()).orElse("unknown").replace(":", "_");
String groupId = Optional.ofNullable(device.getBoard()).orElse("GID_default").replace(":", "_");
String clientId = StrUtil.format("{}@@@{}@@@{}", groupId, macAddress, macAddress);
// 构建完整的URL
String url = StrUtil.format("http://{}/api/commands/{}", mqttGatewayUrl, clientId);
// 构建请求体
Map<String, Object> params = MapUtil
.builder(new HashMap<String, Object>())
.put("name", toolName)
.put("arguments", arguments)
.build();
Map<String, Object> payload = MapUtil
.builder(new HashMap<String, Object>())
.put("jsonrpc", "2.0")
.put("id", 2)
.put("method", "tools/call")
.put("params", params)
.build();
Map<String, Object> requestBody = MapUtil
.builder(new HashMap<String, Object>())
.put("type", "mcp")
.put("payload", payload)
.build();
// 发送请求
String resultMessage = HttpRequest.post(url)
.header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
.header(Header.AUTHORIZATION, "Bearer " + generateBearerToken())
.body(JSONUtil.toJsonStr(requestBody))
.timeout(10000) // 超时,毫秒
.execute().body();
// 解析响应
if (StringUtils.isNotBlank(resultMessage)) {
cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(resultMessage);
if (jsonObject.getBool("success", false)) {
cn.hutool.json.JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
cn.hutool.json.JSONArray content = data.getJSONArray("content");
if (content != null && content.size() > 0) {
cn.hutool.json.JSONObject firstContent = content.getJSONObject(0);
if (firstContent != null && "text".equals(firstContent.getStr("type"))) {
String text = firstContent.getStr("text");
if (StringUtils.isNotBlank(text)) {
String trimmedText = text.trim();
if (trimmedText.startsWith("{") || trimmedText.startsWith("[")) {
try {
return JSONUtil.parseObj(trimmedText);
} catch (Exception e) {
return trimmedText;
}
} else if ("true".equals(trimmedText)) {
return true;
} else if ("false".equals(trimmedText)) {
return false;
} else {
return trimmedText;
}
}
}
}
}
}
}
return null;
}
}
@@ -1,7 +1,6 @@
package xiaozhi.modules.knowledge.controller;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -24,8 +23,10 @@ import xiaozhi.common.exception.ErrorCode;
import xiaozhi.common.exception.RenException;
import xiaozhi.common.page.PageData;
import xiaozhi.common.utils.Result;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.knowledge.dto.KnowledgeBaseDTO;
import xiaozhi.modules.knowledge.service.KnowledgeBaseService;
import xiaozhi.modules.model.entity.ModelConfigEntity;
import xiaozhi.modules.security.user.SecurityUser;
@AllArgsConstructor
@@ -131,20 +132,17 @@ public class KnowledgeBaseController {
// 获取当前登录用户ID
Long currentUserId = SecurityUser.getUserId();
String[] idArray = ids.split(",");
for (String datasetId : idArray) {
if (StringUtils.isNotBlank(datasetId)) {
// 先获取现有知识库信息以检查权限
KnowledgeBaseDTO existingKnowledgeBase = knowledgeBaseService.getByDatasetId(datasetId.trim());
List<String> idList = Arrays.asList(ids.split(","));
List<KnowledgeBaseDTO> knowledgeBaseDTOs = Optional.ofNullable(knowledgeBaseService.getByDatasetIdList(idList)).orElseGet(ArrayList::new);
if (ToolUtil.isNotEmpty(knowledgeBaseDTOs)) {
knowledgeBaseDTOs.forEach(item->{
// 检查权限:用户只能删除自己创建的知识库
if (existingKnowledgeBase.getCreator() == null
|| !existingKnowledgeBase.getCreator().equals(currentUserId)) {
if (item.getCreator() == null || !item.getCreator().equals(currentUserId)) {
throw new RenException(ErrorCode.NO_PERMISSION);
}
knowledgeBaseService.deleteByDatasetId(datasetId.trim());
}
//删除
knowledgeBaseService.deleteByDatasetId(item.getDatasetId());
});
}
return new Result<>();
}
@@ -152,8 +150,8 @@ public class KnowledgeBaseController {
@GetMapping("/rag-models")
@Operation(summary = "获取RAG模型列表")
@RequiresPermissions("sys:role:normal")
public Result<List<Map<String, Object>>> getRAGModels() {
List<Map<String, Object>> result = knowledgeBaseService.getRAGModels();
return new Result<List<Map<String, Object>>>().ok(result);
public Result<List<ModelConfigEntity>> getRAGModels() {
List<ModelConfigEntity> result = knowledgeBaseService.getRAGModels();
return new Result<List<ModelConfigEntity>>().ok(result);
}
}
@@ -63,16 +63,11 @@ public class KnowledgeFilesController {
// 验证知识库权限
validateKnowledgeBasePermission(datasetId);
// 如果指定了状态参数,使用状态查询接口
if (status != null) {
PageData<KnowledgeFilesDTO> pageData = knowledgeFilesService.getPageListByStatus(datasetId, status, page, page_size);
return new Result<PageData<KnowledgeFilesDTO>>().ok(pageData);
}
// 否则使用通用查询接口
//组装参数
KnowledgeFilesDTO knowledgeFilesDTO = new KnowledgeFilesDTO();
knowledgeFilesDTO.setDatasetId(datasetId);
knowledgeFilesDTO.setName(name);
knowledgeFilesDTO.setStatus(status);
PageData<KnowledgeFilesDTO> pageData = knowledgeFilesService.getPageList(knowledgeFilesDTO, page, page_size);
return new Result<PageData<KnowledgeFilesDTO>>().ok(pageData);
}
@@ -87,8 +82,11 @@ public class KnowledgeFilesController {
@RequestParam(required = false, defaultValue = "10") Integer page_size) {
// 验证知识库权限
validateKnowledgeBasePermission(datasetId);
PageData<KnowledgeFilesDTO> pageData = knowledgeFilesService.getPageListByStatus(datasetId, status, page, page_size);
//组装参数
KnowledgeFilesDTO knowledgeFilesDTO = new KnowledgeFilesDTO();
knowledgeFilesDTO.setDatasetId(datasetId);
knowledgeFilesDTO.setStatus(status);
PageData<KnowledgeFilesDTO> pageData = knowledgeFilesService.getPageList(knowledgeFilesDTO, page, page_size);
return new Result<PageData<KnowledgeFilesDTO>>().ok(pageData);
}
@@ -159,8 +157,7 @@ public class KnowledgeFilesController {
// 验证知识库权限
validateKnowledgeBasePermission(datasetId);
Map<String, Object> result = knowledgeFilesService.listChunks(datasetId, documentId, keywords, page, page_size,
id);
Map<String, Object> result = knowledgeFilesService.listChunks(datasetId, documentId, keywords, page, page_size, id);
return new Result<Map<String, Object>>().ok(result);
}
@@ -7,6 +7,7 @@ import xiaozhi.common.page.PageData;
import xiaozhi.common.service.BaseService;
import xiaozhi.modules.knowledge.dto.KnowledgeBaseDTO;
import xiaozhi.modules.knowledge.entity.KnowledgeBaseEntity;
import xiaozhi.modules.model.entity.ModelConfigEntity;
/**
* 知识库知识库服务接口
@@ -55,6 +56,14 @@ public interface KnowledgeBaseService extends BaseService<KnowledgeBaseEntity> {
*/
KnowledgeBaseDTO getByDatasetId(String datasetId);
/**
* 根据知识库ID集合查询知识库
*
* @param datasetIdList 知识库ID集合
* @return 知识库详情
*/
List<KnowledgeBaseDTO> getByDatasetIdList(List<String> datasetIdList);
/**
* 根据知识库ID删除知识库
*
@@ -83,5 +92,5 @@ public interface KnowledgeBaseService extends BaseService<KnowledgeBaseEntity> {
*
* @return RAG模型列表
*/
List<Map<String, Object>> getRAGModels();
List<ModelConfigEntity> getRAGModels();
}
@@ -47,17 +47,6 @@ public interface KnowledgeFilesService {
Map<String, Object> metaFields, String chunkMethod,
Map<String, Object> parserConfig);
/**
* 根据状态分页查询文档列表
*
* @param datasetId 知识库ID
* @param status 文档解析状态(0-未开始,1-进行中,2-已取消,3-已完成,4-失败)
* @param page 页码
* @param limit 每页数量
* @return 分页数据
*/
PageData<KnowledgeFilesDTO> getPageListByStatus(String datasetId, Integer status, Integer page, Integer limit);
/**
* 根据文档ID和知识库ID删除文档
*
@@ -1,21 +1,12 @@
package xiaozhi.modules.knowledge.service.impl;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -32,6 +23,7 @@ import xiaozhi.common.redis.RedisUtils;
import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.MessageUtils;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.knowledge.dao.KnowledgeBaseDao;
import xiaozhi.modules.knowledge.dto.KnowledgeBaseDTO;
import xiaozhi.modules.knowledge.entity.KnowledgeBaseEntity;
@@ -53,8 +45,6 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
private final ModelConfigService modelConfigService;
private final ModelConfigDao modelConfigDao;
private final RedisUtils redisUtils;
private RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public KnowledgeBaseEntity selectById(Serializable datasetId) {
@@ -269,6 +259,26 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
return ConvertUtils.sourceToTarget(entity, KnowledgeBaseDTO.class);
}
/**
* 根据知识库ID集合查询知识库
* @param datasetIdList 知识库ID集合
* @return
*/
@Override
public List<KnowledgeBaseDTO> getByDatasetIdList(List<String> datasetIdList) {
//判断参数
if (ToolUtil.isEmpty(datasetIdList)) {
throw new RenException(ErrorCode.PARAMS_GET_ERROR);
}
//批量查询
List<KnowledgeBaseEntity> entityList = knowledgeBaseDao.selectList(
new QueryWrapper<KnowledgeBaseEntity>().in("dataset_id", datasetIdList));
if (ToolUtil.isEmpty(entityList)) {
throw new RenException(ErrorCode.Knowledge_Base_RECORD_NOT_EXISTS);
}
return ConvertUtils.sourceToTarget(entityList, KnowledgeBaseDTO.class);
}
@Override
public void deleteByDatasetId(String datasetId) {
if (StringUtils.isBlank(datasetId)) {
@@ -380,24 +390,17 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
}
@Override
public List<Map<String, Object>> getRAGModels() {
public List<ModelConfigEntity> getRAGModels() {
// 查询RAG类型的模型配置
QueryWrapper<ModelConfigEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("model_type", Constant.RAG_CONFIG_TYPE)
QueryWrapper<ModelConfigEntity> queryWrapper = new QueryWrapper<ModelConfigEntity>()
.select("id", "model_name")
.eq("model_type", Constant.RAG_CONFIG_TYPE)
.eq("is_enabled", 1)
.orderByDesc("is_default")
.orderByDesc("create_date");
List<ModelConfigEntity> modelConfigs = modelConfigDao.selectList(queryWrapper);
List<Map<String, Object>> modelList = new ArrayList<>();
for (ModelConfigEntity modelConfig : modelConfigs) {
Map<String, Object> modelInfo = new HashMap<>();
modelInfo.put("id", modelConfig.getId());
modelInfo.put("modelName", modelConfig.getModelName());
modelList.add(modelInfo);
}
return modelList;
return modelConfigs;
}
/**
@@ -3,24 +3,10 @@ package xiaozhi.modules.knowledge.service.impl;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.AbstractResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
@@ -31,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
import xiaozhi.common.exception.ErrorCode;
import xiaozhi.common.exception.RenException;
import xiaozhi.common.page.PageData;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.knowledge.dto.KnowledgeFilesDTO;
import xiaozhi.modules.knowledge.rag.KnowledgeBaseAdapter;
import xiaozhi.modules.knowledge.rag.KnowledgeBaseAdapterFactory;
@@ -43,8 +30,6 @@ import xiaozhi.modules.knowledge.service.KnowledgeFilesService;
public class KnowledgeFilesServiceImpl implements KnowledgeFilesService {
private final KnowledgeBaseService knowledgeBaseService;
private RestTemplate restTemplate = new RestTemplate();
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public Map<String, Object> getRAGConfig(String ragModelId) {
@@ -55,32 +40,29 @@ public class KnowledgeFilesServiceImpl implements KnowledgeFilesService {
public PageData<KnowledgeFilesDTO> getPageList(KnowledgeFilesDTO knowledgeFilesDTO, Integer page, Integer limit) {
try {
log.info("=== 开始获取文档列表 ===");
log.info("查询条件: datasetId={}, name={}, status={}, page={}, limit={}",
knowledgeFilesDTO != null ? knowledgeFilesDTO.getDatasetId() : null,
knowledgeFilesDTO != null ? knowledgeFilesDTO.getName() : null,
knowledgeFilesDTO != null ? knowledgeFilesDTO.getStatus() : null,
page, limit);
log.info("查询条件: datasetId={}, name={}, status={}, page={}, limit={}", knowledgeFilesDTO.getDatasetId(), knowledgeFilesDTO.getName(), knowledgeFilesDTO.getStatus(), page, limit);
// 获取数据集ID
String datasetId = knowledgeFilesDTO != null ? knowledgeFilesDTO.getDatasetId() : null;
if (StringUtils.isBlank(datasetId)) {
String datasetId = knowledgeFilesDTO.getDatasetId();
if (ToolUtil.isEmpty(datasetId)) {
throw new RenException(ErrorCode.RAG_DATASET_ID_NOT_NULL);
}
// 获取RAG配置
Map<String, Object> ragConfig = knowledgeBaseService.getRAGConfigByDatasetId(datasetId);
// 提取适配器类型
String adapterType = extractAdapterType(ragConfig);
// 使用适配器工厂获取适配器实例
KnowledgeBaseAdapter adapter = KnowledgeBaseAdapterFactory.getAdapter(adapterType, ragConfig);
// 构建查询参数
Map<String, Object> queryParams = new HashMap<>();
if (knowledgeFilesDTO != null && StringUtils.isNotBlank(knowledgeFilesDTO.getName())) {
if (ToolUtil.isNotEmpty(knowledgeFilesDTO.getName())) {
queryParams.put("keywords", knowledgeFilesDTO.getName());
}
if (ToolUtil.isNotEmpty(knowledgeFilesDTO.getStatus())) {
queryParams.put("status", knowledgeFilesDTO.getStatus());
}
if (page > 0) {
queryParams.put("page", page);
}
@@ -90,10 +72,8 @@ public class KnowledgeFilesServiceImpl implements KnowledgeFilesService {
// 调用适配器获取文档列表
PageData<KnowledgeFilesDTO> result = adapter.getDocumentList(datasetId, queryParams, page, limit);
log.info("获取文档列表成功,共{}个文档,总数: {}", result.getList().size(), result.getTotal());
return result;
} catch (Exception e) {
log.error("获取文档列表失败: {}", e.getMessage(), e);
if (e instanceof RenException) {
@@ -424,57 +404,6 @@ public class KnowledgeFilesServiceImpl implements KnowledgeFilesService {
}
}
@Override
public PageData<KnowledgeFilesDTO> getPageListByStatus(String datasetId, Integer status, Integer page,
Integer limit) {
if (StringUtils.isBlank(datasetId)) {
throw new RenException(ErrorCode.RAG_DATASET_ID_NOT_NULL);
}
log.info("=== 开始根据状态查询文档列表 ===");
log.info("datasetId: {}, status: {}, page: {}, limit: {}", datasetId, status, page, limit);
try {
// 获取RAG配置
Map<String, Object> ragConfig = knowledgeBaseService.getRAGConfigByDatasetId(datasetId);
// 提取适配器类型
String adapterType = extractAdapterType(ragConfig);
// 使用适配器工厂获取适配器实例
KnowledgeBaseAdapter adapter = KnowledgeBaseAdapterFactory.getAdapter(adapterType, ragConfig);
// 构建查询参数
Map<String, Object> queryParams = new HashMap<>();
if (page != null && page > 0) {
queryParams.put("page", page);
}
if (limit != null && limit > 0) {
queryParams.put("page_size", limit);
}
if (status != null) {
queryParams.put("status", status);
}
// 使用适配器获取文档列表
PageData<KnowledgeFilesDTO> pageData = adapter.getDocumentList(datasetId, queryParams, page, limit);
if (pageData != null) {
log.info("根据状态查询文档列表成功,datasetId: {}, 状态: {}, 文档数量: {}",
datasetId, status, pageData.getList().size());
return pageData;
} else {
throw new RenException(ErrorCode.Knowledge_Base_RECORD_NOT_EXISTS);
}
} catch (Exception e) {
log.error("根据状态查询文档列表失败: {}", e.getMessage(), e);
throw new RenException(ErrorCode.RAG_API_ERROR, e.getMessage());
} finally {
log.info("=== 根据状态查询文档列表操作结束 ===");
}
}
@Override
public KnowledgeFilesDTO uploadDocument(String datasetId, MultipartFile file, String name,
Map<String, Object> metaFields, String chunkMethod,
@@ -22,12 +22,24 @@ public class VoiceDTO implements Serializable {
@Schema(description = "音频播放地址")
private String voiceDemo;
@Schema(description = "是否为克隆音色")
private Boolean isClone;
// 添加双参数构造函数,保持向后兼容
public VoiceDTO(String id, String name) {
this.id = id;
this.name = name;
this.voiceDemo = null;
this.isClone = false; // 默认不是克隆音色
}
// 添加三参数构造函数,用于普通音色
public VoiceDTO(String id, String name, String voiceDemo) {
this.id = id;
this.name = name;
this.voiceDemo = voiceDemo;
this.isClone = false;
}
}
@@ -56,7 +56,7 @@ public class ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, Mode
new QueryWrapper<ModelConfigEntity>()
.eq("model_type", modelType)
.eq("is_enabled", 1)
.like(StringUtils.isNotBlank(modelName), "model_name", "%" + modelName + "%")
.like(StringUtils.isNotBlank(modelName), "model_name", modelName)
.select("id", "model_name"));
return ConvertUtils.sourceToTarget(entities, ModelBasicInfoDTO.class);
}
@@ -67,14 +67,14 @@ public class ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, Mode
new QueryWrapper<ModelConfigEntity>()
.eq("model_type", "llm")
.eq("is_enabled", 1)
.like(StringUtils.isNotBlank(modelName), "model_name", "%" + modelName + "%")
.like(StringUtils.isNotBlank(modelName), "model_name", modelName)
.select("id", "model_name", "config_json"));
return entities.stream().map(item -> {
LlmModelBasicInfoDTO dto = new LlmModelBasicInfoDTO();
dto.setId(item.getId());
dto.setModelName(item.getModelName());
String type = item.getConfigJson().get("type").toString();
String type = item.getConfigJson().getOrDefault("type", "").toString();
dto.setType(type);
return dto;
}).toList();
@@ -91,14 +91,13 @@ public class ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, Mode
Page<ModelConfigEntity> pageInfo = new Page<>(curPage, pageSize);
// 添加排序规则:先按is_enabled降序,再按sort升序
pageInfo.addOrder(OrderItem.desc("is_enabled"));
pageInfo.addOrder(OrderItem.asc("sort"));
pageInfo.addOrder(OrderItem.desc("is_enabled"), OrderItem.asc("sort"));
IPage<ModelConfigEntity> modelConfigEntityIPage = modelConfigDao.selectPage(
pageInfo,
new QueryWrapper<ModelConfigEntity>()
.eq("model_type", modelType)
.like(StringUtils.isNotBlank(modelName), "model_name", "%" + modelName + "%"));
.like(StringUtils.isNotBlank(modelName), "model_name", modelName));
return getPageData(modelConfigEntityIPage, ModelConfigDTO.class);
}
@@ -346,6 +345,7 @@ public class ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, Mode
modelConfigEntity.setModelName(modelConfigBodyDTO.getModelName());
modelConfigEntity.setSort(modelConfigBodyDTO.getSort());
modelConfigEntity.setIsEnabled(modelConfigBodyDTO.getIsEnabled());
modelConfigEntity.setRemark(modelConfigBodyDTO.getRemark());
// 3. 处理配置JSON,仅更新非敏感字段和明确修改的敏感字段
if (modelConfigBodyDTO.getConfigJson() != null && originalEntity.getConfigJson() != null) {
JSONObject originalJson = originalEntity.getConfigJson();
@@ -488,7 +488,7 @@ public class ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, Mode
List<ModelConfigEntity> intentConfigs = modelConfigDao.selectList(
new QueryWrapper<ModelConfigEntity>()
.eq("model_type", "Intent")
.like("config_json", "%" + modelId + "%"));
.like("config_json", modelId));
if (!intentConfigs.isEmpty()) {
throw new RenException(ErrorCode.LLM_REFERENCED_BY_INTENT);
}
@@ -124,12 +124,6 @@ public class ModelProviderServiceImpl extends BaseServiceImpl<ModelProviderDao,
return getPageData(modelProviderDao.selectPage(pageParam, wrapper), ModelProviderDTO.class);
}
public static void main(String[] args) {
String jsonString = "\"[]\"";
JSONArray jsonArray = new JSONArray(jsonString);
System.out.println("字符串转 JSONArray: " + jsonArray.toString());
}
@Override
public ModelProviderDTO add(ModelProviderDTO modelProviderDTO) {
UserDetail user = SecurityUser.getUser();
@@ -153,8 +147,7 @@ public class ModelProviderServiceImpl extends BaseServiceImpl<ModelProviderDao,
UserDetail user = SecurityUser.getUser();
modelProviderDTO.setUpdater(user.getId());
modelProviderDTO.setUpdateDate(new Date());
if (modelProviderDao
.updateById(ConvertUtils.sourceToTarget(modelProviderDTO, ModelProviderEntity.class)) == 0) {
if (modelProviderDao.updateById(ConvertUtils.sourceToTarget(modelProviderDTO, ModelProviderEntity.class)) == 0) {
throw new RenException(ErrorCode.UPDATE_DATA_FAILED);
}
return ConvertUtils.sourceToTarget(modelProviderDTO, ModelProviderDTO.class);
@@ -4,6 +4,7 @@ import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import xiaozhi.common.dao.BaseDao;
import xiaozhi.modules.sys.entity.SysDictDataEntity;
import xiaozhi.modules.sys.vo.SysDictDataItem;
@@ -23,4 +24,9 @@ public interface SysDictDataDao extends BaseDao<SysDictDataEntity> {
* @return 字典类型编码
*/
String getTypeByTypeId(Long dictTypeId);
/**
* 根据字典数据ID集合获取字典类型编码集合
*/
List<String> getDictTypesByIdList(@Param("dictDataIdList") List<Long> dictDataIdList);
}
@@ -1,9 +1,6 @@
package xiaozhi.modules.sys.service.impl;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -23,6 +20,7 @@ import xiaozhi.common.redis.RedisKeys;
import xiaozhi.common.redis.RedisUtils;
import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.sys.dao.SysDictDataDao;
import xiaozhi.modules.sys.dao.SysUserDao;
import xiaozhi.modules.sys.dto.SysDictDataDTO;
@@ -104,13 +102,19 @@ public class SysDictDataServiceImpl extends BaseServiceImpl<SysDictDataDao, SysD
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Long[] ids) {
for (Long id : ids) {
SysDictDataEntity entity = baseDao.selectById(id);
// 删除Redis缓存
String dictType = baseDao.getTypeByTypeId(entity.getDictTypeId());
redisUtils.delete(RedisKeys.getDictDataByTypeKey(dictType));
// 删除
deleteById(id);
List<Long> idList = Arrays.asList(ids);
if (ToolUtil.isNotEmpty(idList)) {
//批量删除redis字典
List<String> redisKeyList = new ArrayList<>();
//批量获取字典类型
List<String> dictTypeList = Optional.ofNullable(baseDao.getDictTypesByIdList(idList)).orElseGet(ArrayList::new);
dictTypeList.forEach(dictType -> redisKeyList.add(RedisKeys.getDictDataByTypeKey(dictType)));
if (ToolUtil.isNotEmpty(redisKeyList)) {
//清除缓存
redisUtils.delete(redisKeyList);
}
//批量删除字典数据
deleteBatchIds(Arrays.asList(ids));
}
}
@@ -1,10 +1,6 @@
package xiaozhi.modules.timbre.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
@@ -128,14 +124,12 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
if (StringUtils.isNotBlank(voiceName)) {
queryWrapper.like("name", voiceName);
}
List<TimbreEntity> timbreEntities = timbreDao.selectList(queryWrapper);
if (timbreEntities == null) {
timbreEntities = new ArrayList<>();
}
List<TimbreEntity> timbreEntities = Optional.ofNullable(timbreDao.selectList(queryWrapper)).orElseGet(ArrayList::new);
List<VoiceDTO> voiceDTOs = timbreEntities.stream()
.map(entity -> {
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
dto.setVoiceDemo(entity.getVoiceDemo());
dto.setIsClone(false); // 设置为普通音色
return dto;
})
.collect(Collectors.toList());
@@ -152,6 +146,7 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
voiceDTO.setName(MessageUtils.getMessage(ErrorCode.VOICE_CLONE_PREFIX) + entity.getName());
// 保留从数据库查询到的voiceDemo字段
voiceDTO.setVoiceDemo(entity.getVoiceDemo());
voiceDTO.setIsClone(true); // 设置为克隆音色
redisUtils.set(RedisKeys.getTimbreNameById(voiceDTO.getId()), voiceDTO.getName(),
RedisUtils.NOT_EXPIRE);
voiceDTOs.add(0, voiceDTO);
@@ -214,6 +209,7 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
TimbreEntity entity = list.get(0);
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
dto.setVoiceDemo(entity.getVoiceDemo());
dto.setIsClone(false); // 设置为普通音色
return dto;
}
}
@@ -83,6 +83,13 @@ public class VoiceCloneController {
return new Result<String>().error(ErrorCode.VOICE_CLONE_NOT_AUDIO_FILE);
}
// 加强验证文件扩展名
String originalFilename = voiceFile.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
if (!extension.equals(".mp3") && !extension.equals(".wav")) {
return new Result<String>().error("只允许上传.mp3和.wav格式的文件");
}
// 验证文件大小 (最大10MB)
if (voiceFile.getSize() > 10 * 1024 * 1024) {
return new Result<String>().error(ErrorCode.VOICE_CLONE_AUDIO_TOO_LARGE);
@@ -4,12 +4,8 @@ import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@@ -30,8 +26,11 @@ import xiaozhi.common.page.PageData;
import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.DateUtils;
import xiaozhi.common.utils.ToolUtil;
import xiaozhi.modules.model.entity.ModelConfigEntity;
import xiaozhi.modules.model.service.ModelConfigService;
import xiaozhi.modules.sys.dao.SysUserDao;
import xiaozhi.modules.sys.entity.SysUserEntity;
import xiaozhi.modules.sys.service.SysUserService;
import xiaozhi.modules.voiceclone.dao.VoiceCloneDao;
import xiaozhi.modules.voiceclone.dto.VoiceCloneDTO;
@@ -47,6 +46,7 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
private final ModelConfigService modelConfigService;
private final SysUserService sysUserService;
private final SysUserDao sysUserDao;
private final ObjectMapper objectMapper;
@Override
@@ -104,9 +104,11 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
}
}
// 批量保存
List<VoiceCloneEntity> batchInsertList = new ArrayList<>();
// 遍历选择的音色ID,为每个音色ID创建一条记录
int index = 0;
String namePrefix = DateUtils.format(new java.util.Date(), "MMddHHmm");
String namePrefix = DateUtils.format(new Date(), "MMddHHmm");
for (String voiceId : dto.getVoiceIds()) {
index++;
VoiceCloneEntity entity = new VoiceCloneEntity();
@@ -115,8 +117,10 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
entity.setName(namePrefix + "_" + index);
entity.setUserId(dto.getUserId());
entity.setTrainStatus(0); // 默认训练中
baseDao.insert(entity);
batchInsertList.add(entity);
}
if (ToolUtil.isNotEmpty(batchInsertList)) {
insertBatch(batchInsertList);
}
}
@@ -187,6 +191,11 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
List<VoiceCloneResponseDTO> dtoList = new ArrayList<>(entityList.size());
// 获取用户名称ID集合
Set<Long> userIdList = entityList.stream().map(VoiceCloneEntity::getUserId).collect(Collectors.toSet());
List<SysUserEntity> userList = sysUserDao.selectList(new QueryWrapper<SysUserEntity>().in("id", userIdList));
Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(SysUserEntity::getId, SysUserEntity::getUsername));
// 转换每个实体为DTO
for (VoiceCloneEntity entity : entityList) {
VoiceCloneResponseDTO dto = ConvertUtils.sourceToTarget(entity, VoiceCloneResponseDTO.class);
@@ -198,7 +207,7 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
// 设置用户名称
if (entity.getUserId() != null) {
dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername());
dto.setUserName(userMap.get(entity.getUserId()));
}
// 确保trainStatus字段被正确设置,前端需要这个字段来判断是否为克隆音频
@@ -0,0 +1,94 @@
-- 添加阿里百炼Paraformer实时语音识别服务配置
delete from `ai_model_provider` where id = 'SYSTEM_ASR_AliyunBLStream';
INSERT INTO `ai_model_provider` (`id`, `model_type`, `provider_code`, `name`, `fields`, `sort`, `creator`, `create_date`, `updater`, `update_date`) VALUES
('SYSTEM_ASR_AliyunBLStream', 'ASR', 'aliyunbl_stream', '阿里百炼Paraformer实时语音识别', '[{"key":"api_key","label":"API密钥","type":"password"},{"key":"model","label":"模型名称","type":"string"},{"key":"format","label":"音频格式","type":"string"},{"key":"sample_rate","label":"采样率","type":"number"},{"key":"output_dir","label":"输出目录","type":"string"}]', 18, 1, NOW(), 1, NOW());
delete from `ai_model_config` where id = 'ASR_AliyunBLStream';
INSERT INTO `ai_model_config` VALUES ('ASR_AliyunBLStream', 'ASR', 'AliyunBLStream', '阿里百炼Paraformer实时语音识别', 0, 1, '{"type": "aliyunbl_stream", "api_key": "", "model": "paraformer-realtime-v2", "format": "pcm", "sample_rate": 16000, "disfluency_removal_enabled": false, "semantic_punctuation_enabled": false, "max_sentence_silence": 200, "multi_threshold_mode_enabled": false, "punctuation_prediction_enabled": true, "inverse_text_normalization_enabled": true, "output_dir": "tmp/"}', 'https://help.aliyun.com/zh/model-studio/websocket-for-paraformer-real-time-service', '支持多语言、热词定制、语义断句等高级功能', 21, NULL, NULL, NULL, NULL);
-- 更新阿里百炼Paraformer模型配置的说明文档
UPDATE `ai_model_config` SET
`doc_link` = 'https://help.aliyun.com/zh/model-studio/websocket-for-paraformer-real-time-service',
`remark` = '阿里百炼Paraformer实时语音识别配置说明:
1. 登录阿里云百炼平台 https://bailian.console.aliyun.com/
2. 创建API-KEY https://bailian.console.aliyun.com/#/api-key
3. 支持模型:paraformer-realtime-v2(推荐)、paraformer-realtime-8k-v2、paraformer-realtime-v1、paraformer-realtime-8k-v1
4. 功能特性:
- 多语言支持(中文含方言、英文、日语、韩语、德语、法语、俄语)
- 热词定制(vocabulary_id参数),详细说明请参考:https://help.aliyun.com/zh/model-studio/custom-hot-words?
- 语义断句/VAD断句(semantic_punctuation_enabled参数)
- 自动标点符号、ITN、过滤语气词等
5. 参数说明:
- model: 模型名称,推荐paraformer-realtime-v2
- sample_rate: 采样率(Hz)v2支持任意采样率,v1仅支持16000,8k版本仅支持8000
- semantic_punctuation_enabled: false为VAD断句(低延迟)true为语义断句(高准确)
- max_sentence_silence: VAD断句静音时长阈值(200-6000ms)
' WHERE `id` = 'ASR_AliyunBLStream';
-- 更新豆包流式ASR供应器,增加配置
delete from `ai_model_provider` where id = 'SYSTEM_ASR_DoubaoStreamASR';
INSERT INTO `ai_model_provider` (`id`, `model_type`, `provider_code`, `name`, `fields`, `sort`, `creator`, `create_date`, `updater`, `update_date`) VALUES
('SYSTEM_ASR_DoubaoStreamASR', 'ASR', 'doubao_stream', '火山引擎语音识别(流式)', '[{"key":"appid","label":"应用ID","type":"string"},{"key":"access_token","label":"访问令牌","type":"string"},{"key":"cluster","label":"集群","type":"string"},{"key":"boosting_table_name","label":"热词文件名称","type":"string"},{"key":"correct_table_name","label":"替换词文件名称","type":"string"},{"key":"output_dir","label":"输出目录","type":"string"},{"key":"end_window_size","label":"静音判定时长(ms)","type":"number"},{"key":"enable_multilingual","label":"是否开启多语种识别模式","type":"boolean"},{"key":"language","label":"指定语言编码","type":"string"}]', 3, 1, NOW(), 1, NOW());
UPDATE `ai_model_config` SET
`remark` = '豆包ASR配置说明:
1. 豆包ASR和豆包(流式)ASR的区别是:豆包ASR是按次收费,豆包(流式)ASR是按时收费
2. 一般来说按次收费的更便宜,但是豆包(流式)ASR使用了大模型技术,效果更好
3. 需要在火山引擎控制台创建应用并获取appid和access_token
4. 支持中文语音识别
5. 需要网络连接
6. 输出文件保存在tmp/目录
申请步骤:
1. 访问 https://console.volcengine.com/speech/app
2. 创建新应用
3. 获取appid和access_token
4. 填入配置文件中
如需设置热词,请参考:https://www.volcengine.com/docs/6561/155738
如开启多语种识别模式,请设置language当该键为空时,该模型支持中英文、上海话、闽南语,四川、陕西、粤语识别。其他语种请参考:https://www.volcengine.com/docs/6561/1354869
' WHERE `id` = 'ASR_DoubaoStreamASR';
-- 更新豆包流式ASR模型配置,增加enable_multilingual默认值
UPDATE `ai_model_config` SET
`config_json` = JSON_SET(
`config_json`,
'$.enable_multilingual', false,
'$.language', 'zh-CN'
)
WHERE `id` = 'ASR_DoubaoStreamASR'
AND JSON_EXTRACT(`config_json`, '$.enable_multilingual') IS NULL
AND JSON_EXTRACT(`config_json`, '$.language') IS NULL;
-- 更新HuoshanDoubleStreamTTS供应器配置,增加多情感音色参数
UPDATE `ai_model_provider`
SET `fields` = '[{"key": "ws_url", "type": "string", "label": "WebSocket地址"}, {"key": "appid", "type": "string", "label": "应用ID"}, {"key": "access_token", "type": "string", "label": "访问令牌"}, {"key": "resource_id", "type": "string", "label": "资源ID"}, {"key": "speaker", "type": "string", "label": "默认音色"}, {"key": "enable_ws_reuse", "type": "boolean", "label": "是否开启链接复用", "default": true}, {"key": "speech_rate", "type": "number", "label": "语速(-50~100)"}, {"key": "loudness_rate", "type": "number", "label": "音量(-50~100)"}, {"key": "pitch", "type": "number", "label": "音高(-12~12)"}, {"key": "emotion_scale", "type": "number", "label": "情感强度(1-5)"}, {"key": "emotion", "type": "string", "label": "情感类型"}]'
WHERE `id` = 'SYSTEM_TTS_HSDSTTS';
-- 更新默认值
UPDATE `ai_model_config` SET
`config_json` = JSON_SET(
`config_json`,
'$.emotion', 'neutral',
'$.emotion_scale', 4
)
WHERE `id` = 'TTS_HuoshanDoubleStreamTTS'
AND JSON_EXTRACT(`config_json`, '$.emotion') IS NULL
AND JSON_EXTRACT(`config_json`, '$.emotion_scale') IS NULL;
-- 增加文档链接和备注
UPDATE `ai_model_config` SET
`doc_link` = 'https://console.volcengine.com/speech/service/10007',
`remark` = '火山引擎语音合成服务配置说明:
1. 访问 https://www.volcengine.com/ 注册并开通火山引擎账号
2. 访问 https://console.volcengine.com/speech/service/10007 开通语音合成大模型,购买音色
3. 在页面底部获取appid和access_token
5. 资源ID固定为:volc.service_type.10029(大模型语音合成及混音)
6. 链接复用:开启WebSocket连接复用,默认true减少链接损耗(注意:复用后设备处于聆听状态时空闲链接会占并发数)
7. 语速:-50~100,可不填,正常默认值0,可填-50~100
8. 音量:-50~100,可不填,正常默认值0,可填-50~100
9. 音高:-12~12,可不填,正常默认值0,可填-12~12
10. 多情感参数(当前仅部分音色支持设置情感):
相关音色列表:https://www.volcengine.com/docs/6561/1257544
- emotion_scale:情感强度,可选值为:1~5,默认值为4
- emotion:情感类型,可选值为:neutral、happy、sad、angry、fearful、disgusted、surprised
' WHERE `id` = 'TTS_HuoshanDoubleStreamTTS';
@@ -0,0 +1,11 @@
-- 更改FunASRServer说明文档模型为SenseVoiceSmall
UPDATE `ai_model_config` SET
`doc_link` = 'https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_online_zh.md',
`remark` = '独立部署FunASR,使用FunASR的API服务,只需要五句话
第一句:mkdir -p ./funasr-runtime-resources/models
第二句:sudo docker run -d -p 10096:10095 --privileged=true -v $PWD/funasr-runtime-resources/models:/workspace/models registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.12
上一句话执行后会进入到容器,继续第三句:cd FunASR/runtime
不要退出容器,继续在容器中执行第四句:nohup bash run_server_2pass.sh --download-model-dir /workspace/models --vad-dir damo/speech_fsmn_vad_zh-cn-16k-common-onnx --model-dir iic/SenseVoiceSmall-onnx --online-model-dir damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online-onnx --punc-dir damo/punc_ct-transformer_zh-cn-common-vad_realtime-vocab272727-onnx --lm-dir damo/speech_ngram_lm_zh-cn-ai-wesp-fst --itn-dir thuduj12/fst_itn_zh --hotword /workspace/models/hotwords.txt > log.txt 2>&1 &
上一句话执行后会进入到容器,继续第五句:tail -f log.txt
第五句话执行完后,会看到模型下载日志,下载完后就可以连接使用了
以上是使用CPU推理,如果有GPU,详细参考:https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_online_zh.md' WHERE `id` = 'ASR_FunASRServer';
@@ -0,0 +1,31 @@
-- 批量清理 ai_model_provider 中的 sample_rate 字段定义
UPDATE `ai_model_provider` ap
JOIN (
SELECT
id,
JSON_ARRAYAGG(
JSON_OBJECT('key', jt.k, 'label', jt.l, 'type', jt.t)
) AS new_fields
FROM `ai_model_provider`,
JSON_TABLE(`fields`, '$[*]' COLUMNS (
k VARCHAR(50) PATH '$.key',
l VARCHAR(100) PATH '$.label',
t VARCHAR(20) PATH '$.type'
)) AS jt
WHERE `model_type` = 'TTS'
AND jt.k != 'sample_rate'
GROUP BY id
) filtered ON ap.id = filtered.id
SET ap.fields = filtered.new_fields;
-- 清理 config_json 顶层的 sample_rate
UPDATE `ai_model_config`
SET `config_json` = JSON_REMOVE(`config_json`, '$.sample_rate')
WHERE `model_type` = 'TTS'
AND JSON_EXTRACT(`config_json`, '$.sample_rate') IS NOT NULL;
-- 清理Minimax流式TTS的sample_rate参数(位于audio_setting内部)
UPDATE `ai_model_config` SET
`config_json` = JSON_SET(`config_json`, '$.audio_setting', JSON_REMOVE(JSON_EXTRACT(`config_json`, '$.audio_setting'), '$.sample_rate'))
WHERE `id` = 'TTS_MinimaxStreamTTS'
AND JSON_EXTRACT(`config_json`, '$.audio_setting.sample_rate') IS NOT NULL;
@@ -0,0 +1,87 @@
-- 更新HuoshanDoubleStreamTTS供应器配置,将分散的参数改为JSON字典配置
-- 将 speech_rate, loudness_rate, pitch, emotion, emotion_scale 等参数整合为 audio_params, additions, mix_speaker 三个JSON字典
UPDATE `ai_model_provider`
SET `fields` = '[
{"key": "ws_url", "type": "string", "label": "WebSocket地址"},
{"key": "appid", "type": "string", "label": "应用ID"},
{"key": "access_token", "type": "string", "label": "访问令牌"},
{"key": "resource_id", "type": "string", "label": "资源ID"},
{"key": "speaker", "type": "string", "label": "默认音色"},
{"key": "enable_ws_reuse", "type": "boolean", "label": "是否开启链接复用", "default": true},
{"key": "audio_params", "type": "dict", "label": "音频输出配置"},
{"key": "additions", "type": "dict", "label": "高级文本处理配置"},
{"key": "mix_speaker", "type": "dict", "label": "混音控制配置"}
]'
WHERE `id` = 'SYSTEM_TTS_HSDSTTS';
-- 更新现有配置,将旧的分散参数迁移到新的JSON字典结构
UPDATE `ai_model_config`
SET `config_json` = JSON_SET(
`config_json`,
'$.audio_params', JSON_OBJECT(
'speech_rate', CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.speech_rate')), ''), '0') AS SIGNED),
'loudness_rate', CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.loudness_rate')), ''), '0') AS SIGNED)
),
'$.additions', JSON_OBJECT(
'aigc_metadata', JSON_OBJECT(),
'cache_config', JSON_OBJECT(),
'post_process', JSON_OBJECT(
'pitch', CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.pitch')), ''), '0') AS SIGNED)
)
),
'$.mix_speaker', JSON_OBJECT()
)
WHERE `id` = 'TTS_HuoshanDoubleStreamTTS';
-- 删除旧的分散参数字段
UPDATE `ai_model_config`
SET `config_json` = JSON_REMOVE(
`config_json`,
'$.speech_rate',
'$.loudness_rate',
'$.pitch',
'$.emotion',
'$.emotion_scale'
)
WHERE `id` = 'TTS_HuoshanDoubleStreamTTS';
-- 更新文档链接和备注说明
UPDATE `ai_model_config` SET
`doc_link` = 'https://www.volcengine.com/docs/6561/1329505',
`remark` = '火山引擎双向流式TTS配置说明:
1. 访问 https://www.volcengine.com/ 注册并开通火山引擎账号
2. 访问 https://console.volcengine.com/speech/service/10007 开通语音合成大模型,购买音色
3. 在页面底部获取appid和access_token
4. 资源ID固定为:volc.service_type.10029(大模型语音合成及混音)
5. 链接复用:开启WebSocket连接复用,默认true减少链接损耗(注意:复用后设备处于聆听状态时空闲链接会占并发数)
详细参数文档:https://www.volcengine.com/docs/6561/1329505
【audio_params】音频输出配置 - 用户可自定义添加火山引擎支持的任何音频参数
- speech_rate: 语速(-50~100),默认0
- loudness_rate: 音量(-50~100),默认0
- emotion: 情感类型(仅部分音色支持),可选值:neutral、happy、sad、angry、fearful、disgusted、surprised
- emotion_scale: 情感强度(1~5),默认4
示例:{"speech_rate": 10, "loudness_rate": 5, "emotion": "happy", "emotion_scale": 4}
【additions】高级文本处理配置 - 用户可自定义添加火山引擎支持的任何高级参数
- post_process.pitch: 音高(-12~12),默认0
- aigc_metadata: AIGC元数据配置
- cache_config: 缓存配置
示例:{"post_process": {"pitch": 2}, "aigc_metadata": {}, "cache_config": {}}
【mix_speaker】混音控制配置 - 多音色混合(仅 TTS 1.0)
示例:
{"speakers": [
{"source_speaker": "zh_male_bvlazysheep","mix_factor": 0.3},
{"source_speaker": "BV120_streaming","mix_factor": 0.3},
{"source_speaker": "zh_male_ahu_conversation_wvae_bigtts","mix_factor": 0.4}
]}
注意:
- 多情感音色参数(emotion、emotion_scale)仅部分音色支持
- 相关音色列表:https://www.volcengine.com/docs/6561/1257544
- 用户可根据火山引擎API文档自行添加更多参数
- 混音功能主要适用于豆包语音合成模型1.0的音色,使用时需要将req_params.speaker设置为custom_mix_bigtts
'
WHERE `id` = 'TTS_HuoshanDoubleStreamTTS';
@@ -0,0 +1,14 @@
-- 更新小智参数中的默认采样率从 16000 改为 24000
UPDATE `sys_params`
SET `param_value` = '{
"type": "hello",
"version": 1,
"transport": "websocket",
"audio_params": {
"format": "opus",
"sample_rate": 24000,
"channels": 1,
"frame_duration": 60
}
}'
WHERE `id` = 309 AND `param_code` = 'xiaozhi';
@@ -472,4 +472,39 @@ databaseChangeLog:
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202512221117.sql
path: classpath:db/changelog/202512221117.sql
- changeSet:
id: 202512301430
author: RanChen
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202512301430.sql
- changeSet:
id: 202601051433
author: RanChen
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202601051433.sql
- changeSet:
id: 202601141645
author: RanChen
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202601141645.sql
- changeSet:
id: 202601231530
author: RanChen
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202601231530.sql
- changeSet:
id: 202601261730
author: RanChen
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202601261730.sql
@@ -198,4 +198,7 @@
10189=\u9002\u914D\u5668\u64CD\u4F5C\u5931\u8D25
10190=\u9002\u914D\u5668\u672A\u627E\u5230
10191=\u9002\u914D\u5668\u7F13\u5B58\u9519\u8BEF
10192=\u9002\u914D\u5668\u7C7B\u578B\u672A\u627E\u5230
10192=\u9002\u914D\u5668\u7C7B\u578B\u672A\u627E\u5230
10193=\u8BBE\u5907ID\u4E0D\u80FD\u4E3A\u7A7A
10194=\u8BBE\u5907\u4E0D\u5B58\u5728\u6216\u4E0D\u5728\u7EBF
10195=OTA\u4E0A\u4F20\u6B21\u6570\u8D85\u8FC7\u9650\u5236
@@ -8,23 +8,23 @@
10004=Die Kontonummer oder das Passwort ist falsch
10005=Konto wurde deaktiviert
10006=Eindeutige ID darf nicht leer sein
10007=Der Bestätigungscode ist falsch
10008=Zuerst Untermenü oder Schaltfläche löschen
10009=Das ursprüngliche Passwort ist falsch
10010=Das Konto oder Passwort ist falsch, Sie können es noch {0} Mal versuchen
10007=Der Best\u00E4tigungscode ist falsch
10008=Zuerst Untermen\u00FC oder Schaltfl\u00E4che l\u00F6schen
10009=Das urspr\u00FCngliche Passwort ist falsch
10010=Das Konto oder Passwort ist falsch, Sie k\u00F6nnen es noch {0} Mal versuchen
10011=Die übergeordnete Abteilung hat eine falsche Wahl getroffen
10012=Oberes Menü kann nicht sich selbst sein
10011=Die \u00FCbergeordnete Abteilung hat eine falsche Wahl getroffen
10012=Oberes Men\u00FC kann nicht sich selbst sein
10013=Datenberechtigungsschnittstelle, die nur ein Map-Typ-Parameter sein kann
10014=Bitte löschen Sie zuerst die untergeordnete Abteilung
10015=Bitte löschen Sie zuerst den Benutzer unter der Abteilung
10014=Bitte l\u00F6schen Sie zuerst die untergeordnete Abteilung
10015=Bitte l\u00F6schen Sie zuerst den Benutzer unter der Abteilung
10016=Bereitstellung fehlgeschlagen, kein Prozess
10017=Das ModellDiagramm ist falsch, bitte überprüfen
10017=Das ModellDiagramm ist falsch, bitte \u00FCberpr\u00FCfen
10018=Export fehlgeschlagen, Modell-ID ist {0}
10019=Bitte laden Sie eine Datei hoch
10020=Token darf nicht leer sein
10021=Token ist ungültig, bitte melden Sie sich erneut an
10021=Token ist ung\u00FCltig, bitte melden Sie sich erneut an
10022=Das Konto wurde gesperrt
10023=Bitte laden Sie Dateien im Format zip, bar, bpmn, bpmn20.xml hoch
@@ -37,25 +37,25 @@
10029=Darf keine illegalen Zeichen enthalten
10030=Das Passwort hat weniger als {0} Ziffern
10031=Das Passwort muss gleichzeitig aus Zahlen, Groß- und Kleinbuchstaben sowie Sonderzeichen bestehen
10032=Ausnahme beim Löschen dieser Daten
10033=Gerätebestätigungscode Fehler
10031=Das Passwort muss gleichzeitig aus Zahlen, Gro\u00DF- und Kleinbuchstaben sowie Sonderzeichen bestehen
10032=Ausnahme beim L\u00F6schen dieser Daten
10033=Ger\u00E4tebest\u00E4tigungscode Fehler
10034=Parameterwert darf nicht leer sein
10035=Parametertyp darf nicht leer sein
10036=Nicht unterstützter Parametertyp
10037=Parameterwert muss eine gültige Zahl sein
10036=Nicht unterst\u00FCtzter Parametertyp
10037=Parameterwert muss eine g\u00FCltige Zahl sein
10038=Parameterwert muss true oder false sein
10039=Parameterwert muss ein gültiges JSON-Array-Format sein
10040=Parameterwert muss ein gültiges JSON-Format sein
10039=Parameterwert muss ein g\u00FCltiges JSON-Array-Format sein
10040=Parameterwert muss ein g\u00FCltiges JSON-Format sein
10041=Gerät nicht gefunden
10041=Ger\u00E4t nicht gefunden
10042={0}
10043=Löschen der Daten fehlgeschlagen
10043=L\u00F6schen der Daten fehlgeschlagen
10044=Benutzer nicht angemeldet
10045=WebSocket-Verbindung fehlgeschlagen oder Zeitüberschreitung
10045=WebSocket-Verbindung fehlgeschlagen oder Zeit\u00FCberschreitung
10046=Stimmabdruck speichern fehlgeschlagen, bitte Administrator kontaktieren
10047=Tägliches SendeLimit erreicht
10047=T\u00E4gliches SendeLimit erreicht
10048=Altes Passwort ist falsch
10049=Das eingestellte LLM ist nicht openai oder ollama
10050=Token-Generierung fehlgeschlagen
@@ -65,45 +65,45 @@
10054=Stimmabdruck-Schnittstelle nicht konfiguriert, bitte konfigurieren Sie zuerst die Stimmabdruck-Schnittstellenadresse (server.voice_print) in der Parameterkonfiguration
10055=SMS-Sendung fehlgeschlagen
10056=SMS-Verbindung konnte nicht hergestellt werden
10057=Stimmabdruck für Agent konnte nicht erstellt werden
10058=Stimmabdruck für Agent konnte nicht aktualisiert werden
10059=Stimmabdruck für Agent konnte nicht gelöscht werden
10060=Sendung zu häufig, bitte versuchen Sie es nach {0} Sekunden erneut
10057=Stimmabdruck f\u00FCr Agent konnte nicht erstellt werden
10058=Stimmabdruck f\u00FCr Agent konnte nicht aktualisiert werden
10059=Stimmabdruck f\u00FCr Agent konnte nicht gel\u00F6scht werden
10060=Sendung zu h\u00E4ufig, bitte versuchen Sie es nach {0} Sekunden erneut
10061=Aktivierungscode darf nicht leer sein
10062=Aktivierungscode Fehler
10063=Gerät bereits aktiviert
10063=Ger\u00E4t bereits aktiviert
10064=Dieses Modell ist das Standardmodell, bitte setzen Sie zuerst ein anderes Modell als Standard
10065=Hinzufügen der Daten fehlgeschlagen
10065=Hinzuf\u00FCgen der Daten fehlgeschlagen
10066=Aktualisieren der Daten fehlgeschlagen
10067=Grafischer Bestätigungscode Fehler
10068=Mobilregistrierung nicht aktiviert, SMS-Bestätigungscode-Funktion kann nicht verwendet werden
10067=Grafischer Best\u00E4tigungscode Fehler
10068=Mobilregistrierung nicht aktiviert, SMS-Best\u00E4tigungscode-Funktion kann nicht verwendet werden
10069=Benutzername ist keine Handynummer, bitte erneut eingeben
10070=Diese Handynummer wurde bereits registriert
10071=Die eingegebene Handynummer ist nicht registriert
10072=Normale Benutzerregistrierung derzeit nicht erlaubt
10073=Mobilregistrierung nicht aktiviert, Passwort-Wiederherstellungsfunktion kann nicht verwendet werden
10074=Das Format der eingegebenen Handynummer ist falsch
10075=Der eingegebene SMS-Bestätigungscode ist falsch
10076=Wörterbuchtyp existiert nicht
10077=Wörterbuchtypcode ist dupliziert
10075=Der eingegebene SMS-Best\u00E4tigungscode ist falsch
10076=W\u00F6rterbuchtyp existiert nicht
10077=W\u00F6rterbuchtypcode ist dupliziert
10078=Lesen der Ressource fehlgeschlagen
10079=LLM-Modell und Absichtserkennung, Parameterauswahl stimmt nicht überein
10080=Dieser Stimmabdruck gehört zu {0}, der bereits registriert ist, bitte wählen Sie eine andere Stimme
10081=Fehler beim Löschen des Stimmabdrucks aufgetreten
10082=Änderung nicht erlaubt, diese Stimme wurde bereits als Stimmabdruck registriert ({0})
10083=Fehler beim Ändern des Stimmabdrucks, bitte Administrator kontaktieren
10084=Stimmabdruck-Schnittstellenadresse Fehler, bitte gehen Sie zur Parameterverwaltung, um die Stimmabdruck-Schnittstellenadresse zu ändern
10085=Audiodaten gehören nicht zu diesem Agent
10086=Audiodaten sind leer, bitte überprüfen Sie hochgeladene Daten
10079=LLM-Modell und Absichtserkennung, Parameterauswahl stimmt nicht \u00FCberein
10080=Dieser Stimmabdruck geh\u00F6rt zu {0}, der bereits registriert ist, bitte w\u00E4hlen Sie eine andere Stimme
10081=Fehler beim L\u00F6schen des Stimmabdrucks aufgetreten
10082=\u00C4nderung nicht erlaubt, diese Stimme wurde bereits als Stimmabdruck registriert ({0})
10083=Fehler beim \u00C4ndern des Stimmabdrucks, bitte Administrator kontaktieren
10084=Stimmabdruck-Schnittstellenadresse Fehler, bitte gehen Sie zur Parameterverwaltung, um die Stimmabdruck-Schnittstellenadresse zu \u00E4ndern
10085=Audiodaten geh\u00F6ren nicht zu diesem Agent
10086=Audiodaten sind leer, bitte \u00FCberpr\u00FCfen Sie hochgeladene Daten
10087=Stimmabdruck-Registrierung fehlgeschlagen, Anfrage nicht erfolgreich
10088=Stimmabdruck-Registrierung fehlgeschlagen, Anfrageverarbeitung fehlgeschlagen
10089=Stimmabdruck-Stornierung fehlgeschlagen, Anfrage nicht erfolgreich
10090=Stimmabdruck-Stornierung fehlgeschlagen, Anfrageverarbeitung fehlgeschlagen
10091=Modellanbieter existiert nicht
10092=Das konfigurierte LLM existiert nicht
10093=Diese Modellkonfiguration wird von Agent {0} referenziert und kann nicht gelöscht werden
10094=Dieses LLM-Modell wird von der Absichtserkennungskonfiguration referenziert und kann nicht gelöscht werden
10095=Ungültige Serveroperation
10093=Diese Modellkonfiguration wird von Agent {0} referenziert und kann nicht gel\u00F6scht werden
10094=Dieses LLM-Modell wird von der Absichtserkennungskonfiguration referenziert und kann nicht gel\u00F6scht werden
10095=Ung\u00FCltige Serveroperation
10096=Server WebSocket-Adresse nicht konfiguriert
10097=Ziel-WebSocket-Adresse existiert nicht
10098=WebSocket-Adressliste darf nicht leer sein
@@ -115,47 +115,47 @@
10104=OTA-Adresse muss mit http oder https beginnen
10105=OTA-Adresse muss mit /ota/ enden
10106=OTA-Schnittstellenzugriff fehlgeschlagen
10107=OTA-Schnittstelle Rückgabeinhaltformat ist falsch
10107=OTA-Schnittstelle R\u00FCckgabeinhaltformat ist falsch
10108=OTA-Schnittstellenvalidierung fehlgeschlagen
10109=MCP-Adresse darf nicht leer sein
10110=MCP-Adresse darf nicht localhost oder 127.0.0.1 verwenden
10111=Keine gültige MCP-Adresse
10111=Keine g\u00FCltige MCP-Adresse
10112=MCP-Schnittstellenzugriff fehlgeschlagen
10113=MCP-Schnittstelle Rückgabeinhaltformat ist falsch
10113=MCP-Schnittstelle R\u00FCckgabeinhaltformat ist falsch
10114=MCP-Schnittstellenvalidierung fehlgeschlagen
10115=Stimmabdruck-Schnittstellenadresse darf nicht leer sein
10116=Stimmabdruck-Schnittstellenadresse darf nicht localhost oder 127.0.0.1 verwenden
10117=Keine gültige Stimmabdruck-Schnittstellenadresse
10117=Keine g\u00FCltige Stimmabdruck-Schnittstellenadresse
10118=Stimmabdruck-Schnittstellenadresse muss mit http oder https beginnen
10119=Stimmabdruck-Schnittstellenzugriff fehlgeschlagen
10120=Stimmabdruck-Schnittstelle Rückgabeinhaltformat ist falsch
10120=Stimmabdruck-Schnittstelle R\u00FCckgabeinhaltformat ist falsch
10121=Stimmabdruck-Schnittstellenvalidierung fehlgeschlagen
10122=MQTT-Geheimnis darf nicht leer sein
10123=Ihr MQTT-Geheimnis ist nicht sicher, es muss mindestens 8 Zeichen lang sein und muss sowohl Groß- als auch Kleinbuchstaben enthalten
10124=Ihr MQTT-Geheimnis ist nicht sicher, MQTT-Geheimnis muss sowohl Groß- als auch Kleinbuchstaben enthalten
10125=Ihr MQTT-Geheimnis enthält schwaches Passwort
10128=Wörterbuchlabel ist dupliziert
10129=SM2-Schlüssel nicht konfiguriert
10130=SM2-Entschlüsselung fehlgeschlagen
10131=modelType und provideCode dürfen nicht leer sein
10123=Ihr MQTT-Geheimnis ist nicht sicher, es muss mindestens 8 Zeichen lang sein und muss sowohl Gro\u00DF- als auch Kleinbuchstaben enthalten
10124=Ihr MQTT-Geheimnis ist nicht sicher, MQTT-Geheimnis muss sowohl Gro\u00DF- als auch Kleinbuchstaben enthalten
10125=Ihr MQTT-Geheimnis enth\u00E4lt schwaches Passwort
10128=W\u00F6rterbuchlabel ist dupliziert
10129=SM2-Schl\u00FCssel nicht konfiguriert
10130=SM2-Entschl\u00FCsselung fehlgeschlagen
10131=modelType und provideCode d\u00FCrfen nicht leer sein
10132=Keine Berechtigung, den Chat-Verlauf dieses Agents anzuzeigen
10133=Sitzungs-ID darf nicht leer sein
10134=Agent-ID darf nicht leer sein
10135=Chat-Verlauf-Download fehlgeschlagen
10136=Download-Link abgelaufen oder ungültig
10137=Download-Link ungültig
10136=Download-Link abgelaufen oder ung\u00FCltig
10137=Download-Link ung\u00FCltig
10138=Benutzer
10139=Agent
10140=Audio-Datei darf nicht leer sein
10141=Nur Audio-Dateien werden unterstützt
10142=Audio-Dateigröße darf 10MB nicht überschreiten
10141=Nur Audio-Dateien werden unterst\u00FCtzt
10142=Audio-Dateigr\u00F6\u00DFe darf 10MB nicht \u00FCberschreiten
10143=Upload fehlgeschlagen
10144=Stimmenklon-Datensatz existiert nicht
10145=Stimmressourceninformationen dürfen nicht leer sein
10145=Stimmressourceninformationen d\u00FCrfen nicht leer sein
10146=TTS-Plattformname darf nicht leer sein
10147=Stimmen-ID darf nicht leer sein
10148=Kontoinhaber darf nicht leer sein
10149=Zu löschende Stimmressourcen-ID darf nicht leer sein
10149=Zu l\u00F6schende Stimmressourcen-ID darf nicht leer sein
10150=Sie haben keine Berechtigung, diesen Datensatz zu bearbeiten
10151=Bitte laden Sie zuerst eine Audio-Datei hoch
10152=Modellkonfiguration nicht gefunden
@@ -179,18 +179,18 @@
10170=Wissensbasis-Name existiert bereits
10171=RAG-Konfiguration base_url darf nicht leer sein
10172=RAG-Konfiguration api_key darf nicht leer sein
10173=RAG-Konfiguration api_key darf keinen Platzhalter enthalten, bitte ersetzen Sie mit tatsächlichem API-Schlüssel
10173=RAG-Konfiguration api_key darf keinen Platzhalter enthalten, bitte ersetzen Sie mit tats\u00E4chlichem API-Schl\u00FCssel
10174=RAG-Konfiguration base_url-Formatfehler, muss mit http oder https beginnen
10175=Mac-Adresse darf nicht leer sein
10176=RAG-Konfiguration dataset_id darf nicht leer sein
10177=RAG-Konfiguration model_id darf nicht leer sein
10178=RAG-Konfiguration dataset_id und model_id dürfen nicht leer sein
10178=RAG-Konfiguration dataset_id und model_id d\u00FCrfen nicht leer sein
10179=Dateiname darf nicht leer sein
10180=Dateiinhalt darf nicht leer sein
10181=Stimmenklon-Name darf nicht leer sein
10182=Stimmenklon-Audio nicht gefunden
10183=Standard-Agent-Vorlage nicht gefunden
10184=Nicht unterstützter Adaptertyp
10184=Nicht unterst\u00FCtzter Adaptertyp
10185=RAG-Konfigurationsvalidierung fehlgeschlagen
10186=Adapter-Erstellung fehlgeschlagen
10187=Adapter-Initialisierung fehlgeschlagen
@@ -198,4 +198,7 @@
10189=Adapter-Operation fehlgeschlagen
10190=Adapter nicht gefunden
10191=Adapter-Cache-Fehler
10192=Adaptertyp nicht gefunden
10192=Adaptertyp nicht gefunden
10193=Adapter-ID darf nicht leer sein
10194=Adapter nicht gefunden oder nicht online
10195=OTA-Upload-Anzahl \u00FCberschreitet das Limit
@@ -198,4 +198,7 @@
10189=Adapter operation failed
10190=Adapter not found
10191=Adapter cache error
10192=Adapter type not found
10192=Adapter type not found
10193=Device ID cannot be empty
10194=Device not found or not online
10195=OTA upload times exceed the limit
@@ -1,201 +1,204 @@
#Tiếng Việt
500=Ngoại lệ nội bộ máy chủ
401=Không được ủy quyền
403=Truy cập bị từ chối, không có quyền
10001={0} không thể để trống
10002=Bản ghi đã tồn tại trong cơ sở dữ liệu
10003=Không thể lấy tham s
10004=Số tài khoản hoặc mật khẩu không chính xác
10005=Tài khoản đã bị vô hiệu hóa
10006=ID duy nhất không thể để trống
10007=Mã xác minh không chính xác
10008=Trước tiên hãy xóa menu con hoặc nút
10009=Mật khẩu gốc không chính xác
10010=Tài khoản hoặc mật khẩu không chính xác, bạn có thể thử thêm {0} lần nữa
#Ti\u1EBFng Vi\u1EC7t
500=Ngo\u1EA1i l\u1EC7 n\u1ED9i b\u1ED9 m\u00E1y ch\u1EE7
401=Kh\u00F4ng \u0111\u01B0\u1EE3c \u1EE7y quy\u1EC1n
403=Truy c\u1EADp b\u1ECB t\u1EEB ch\u1ED1i, kh\u00F4ng c\u00F3 quy\u1EC1n
10001={0} kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10002=B\u1EA3n ghi \u0111\u00E3 t\u1ED3n t\u1EA1i trong c\u01A1 s\u1EDF d\u1EEF li\u1EC7u
10003=Kh\u00F4ng th\u1EC3 l\u1EA5y tham s\u1ED1
10004=S\u1ED1 t\u00E0i kho\u1EA3n ho\u1EB7c m\u1EADt kh\u1EA9u kh\u00F4ng ch\u00EDnh x\u00E1c
10005=T\u00E0i kho\u1EA3n \u0111\u00E3 b\u1ECB v\u00F4 hi\u1EC7u h\u00F3a
10006=ID duy nh\u1EA5t kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10007=M\u00E3 x\u00E1c minh kh\u00F4ng ch\u00EDnh x\u00E1c
10008=Tr\u01B0\u1EDBc ti\u00EAn h\u00E3y x\u00F3a menu con ho\u1EB7c n\u00FAt
10009=M\u1EADt kh\u1EA9u g\u1ED1c kh\u00F4ng ch\u00EDnh x\u00E1c
10010=T\u00E0i kho\u1EA3n ho\u1EB7c m\u1EADt kh\u1EA9u kh\u00F4ng ch\u00EDnh x\u00E1c, b\u1EA1n c\u00F3 th\u1EC3 th\u1EED th\u00EAm {0} l\u1EA7n n\u1EEFa
10011=Phòng ban cấp trên đã lựa chọn sai
10012=Menu trên không thể là chính nó
10013=Giao diện quyền dữ liệu, chỉ có thể là tham số kiểu Map
10014=Vui lòng xóa phòng ban cấp dưới trước
10015=Vui lòng xóa người dùng thuộc phòng ban trước
10016=Trin khai thất bại, không có quy trình
10017=Biểu đồ mô hình không chính xác, vui lòng kiểm tra
10018=Xuất thất bại, ID mô hình là {0}
10011=Ph\u00F2ng ban c\u1EA5p tr\u00EAn \u0111\u00E3 l\u1EF1a ch\u1ECDn sai
10012=Menu tr\u00EAn kh\u00F4ng th\u1EC3 l\u00E0 ch\u00EDnh n\u00F3
10013=Giao di\u1EC7n quy\u1EC1n d\u1EEF li\u1EC7u, ch\u1EC9 c\u00F3 th\u1EC3 l\u00E0 tham s\u1ED1 ki\u1EC3u Map
10014=Vui l\u00F2ng x\u00F3a ph\u00F2ng ban c\u1EA5p d\u01B0\u1EDBi tr\u01B0\u1EDBc
10015=Vui l\u00F2ng x\u00F3a ng\u01B0\u1EDDi d\u00F9ng thu\u1ED9c ph\u00F2ng ban tr\u01B0\u1EDBc
10016=Tri\u1EC3n khai th\u1EA5t b\u1EA1i, kh\u00F4ng c\u00F3 quy tr\u00ECnh
10017=Bi\u1EC3u \u0111\u1ED3 m\u00F4 h\u00ECnh kh\u00F4ng ch\u00EDnh x\u00E1c, vui l\u00F2ng ki\u1EC3m tra
10018=Xu\u1EA5t th\u1EA5t b\u1EA1i, ID m\u00F4 h\u00ECnh l\u00E0 {0}
10019=Vui lòng tải lên tệp
10020=Token không thể để trống
10021=Token không hợp lệ, vui lòng đăng nhập lại
10022=Tài khoản đã bị khóa
10023=Vui lòng tải lên tệp ở định dạng zip, bar, bpmn, bpmn20.xml
10019=Vui l\u00F2ng t\u1EA3i l\u00EAn t\u1EC7p
10020=Token kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10021=Token kh\u00F4ng h\u1EE3p l\u1EC7, vui l\u00F2ng \u0111\u0103ng nh\u1EADp l\u1EA1i
10022=T\u00E0i kho\u1EA3n \u0111\u00E3 b\u1ECB kh\u00F3a
10023=Vui l\u00F2ng t\u1EA3i l\u00EAn t\u1EC7p \u1EDF \u0111\u1ECBnh d\u1EA1ng zip, bar, bpmn, bpmn20.xml
10024=Tải lên tệp {0} thất bại
10025=Gi SMS {0} thất bại
10026=Mu email không tồn tại
10024=T\u1EA3i l\u00EAn t\u1EC7p {0} th\u1EA5t b\u1EA1i
10025=G\u1EEDi SMS {0} th\u1EA5t b\u1EA1i
10026=M\u1EABu email kh\u00F4ng t\u1ED3n t\u1EA1i
10027=Ngoại lệ dịch vụ Redis
10028=Tác vụ hẹn giờ thất bại
10029=Không thể chứa ký tự không hợp lệ
10027=Ngo\u1EA1i l\u1EC7 d\u1ECBch v\u1EE5 Redis
10028=T\u00E1c v\u1EE5 h\u1EB9n gi\u1EDD th\u1EA5t b\u1EA1i
10029=Kh\u00F4ng th\u1EC3 ch\u1EE9a k\u00FD t\u1EF1 kh\u00F4ng h\u1EE3p l\u1EC7
10030=Mật khẩu ít hơn {0} chữ số
10031=Mật khẩu phải bao gồm số, chữ hoa, chữ thường và ký tự đặc biệt cùng một lúc
10032=Ngoại lệ khi xóa dữ liệu này
10033=Lỗi mã xác minh thiết bị
10030=M\u1EADt kh\u1EA9u \u00EDt h\u01A1n {0} ch\u1EEF s\u1ED1
10031=M\u1EADt kh\u1EA9u ph\u1EA3i bao g\u1ED3m s\u1ED1, ch\u1EEF hoa, ch\u1EEF th\u01B0\u1EDDng v\u00E0 k\u00FD t\u1EF1 \u0111\u1EB7c bi\u1EC7t c\u00F9ng m\u1ED9t l\u00FAc
10032=Ngo\u1EA1i l\u1EC7 khi x\u00F3a d\u1EEF li\u1EC7u n\u00E0y
10033=L\u1ED7i m\u00E3 x\u00E1c minh thi\u1EBFt b\u1ECB
10034=Giá trị tham số không thể để trống
10035=Loi tham số không thể để trống
10036=Loi tham số không được hỗ trợ
10037=Giá trị tham số phải là số hợp lệ
10038=Giá trị tham số phải là true hoc false
10039=Giá trị tham số phải là định dạng mảng JSON hợp lệ
10040=Giá trị tham số phải là định dạng JSON hợp lệ
10034=Gi\u00E1 tr\u1ECB tham s\u1ED1 kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10035=Lo\u1EA1i tham s\u1ED1 kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10036=Lo\u1EA1i tham s\u1ED1 kh\u00F4ng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3
10037=Gi\u00E1 tr\u1ECB tham s\u1ED1 ph\u1EA3i l\u00E0 s\u1ED1 h\u1EE3p l\u1EC7
10038=Gi\u00E1 tr\u1ECB tham s\u1ED1 ph\u1EA3i l\u00E0 true ho\u1EB7c false
10039=Gi\u00E1 tr\u1ECB tham s\u1ED1 ph\u1EA3i l\u00E0 \u0111\u1ECBnh d\u1EA1ng m\u1EA3ng JSON h\u1EE3p l\u1EC7
10040=Gi\u00E1 tr\u1ECB tham s\u1ED1 ph\u1EA3i l\u00E0 \u0111\u1ECBnh d\u1EA1ng JSON h\u1EE3p l\u1EC7
10041=Không tìm thấy thiết bị
10041=Kh\u00F4ng t\u00ECm th\u1EA5y thi\u1EBFt b\u1ECB
10042={0}
10043=Xóa dữ liệu thất bại
10044=Người dùng chưa đăng nhập
10045=Kết nối WebSocket thất bại hoặc hết thời gian ch
10046=Không thể lưu dấu giọng nói, vui lòng liên hệ quản trị viên
10047=Đạt đến giới hạn gửi hàng ngày
10048=Mật khẩu cũ không chính xác
10049=LLM được đặt không phải là openai hoc ollama
10050=Không thể tạo token
10051=Không tìm thấy tài nguyên
10052=Không tìm thấy agent mặc định
10053=Không tìm thấy agent
10054=Giao diện dấu giọng nói chưa được cấu hình, vui lòng cấu hình địa chỉ giao diện dấu giọng nói (server.voice_print) trong cấu hình tham số trước
10055=Gi SMS thất bại
10056=Không thể thiết lập kết nối SMS
10057=Không thể tạo dấu giọng nói cho agent
10058=Không thể cập nhật dấu giọng nói cho agent
10059=Không thể xóa dấu giọng nói cho agent
10060=Gửi quá thường xuyên, vui lòng thử lại sau {0} giây
10061=Mã kích hoạt không thể để trống
10062=Lỗi mã kích hoạt
10063=Thiết bị đã được kích hoạt
10064=Mô hình này là mô hình mặc định, vui lòng đặt mô hình khác làm mặc định trước
10065=Thêm dữ liệu thất bại
10066=Cập nhật dữ liệu thất bại
10067=Lỗi mã xác minh đồ họa
10068=Đăng ký di động không được bật, không thể sử dụng chức năng mã xác minh SMS
10069=Tên người dùng không phải là số điện thoại di động, vui lòng nhập lại
10070=Số điện thoại di động này đã được đăng ký
10071=Số điện thoại di động đã nhập không được đăng ký
10072=Hiện không cho phép đăng ký người dùng thông thường
10073=Đăng ký di động không được bật, không thể sử dụng chức năng truy xuất mật khẩu
10074=Định dạng số điện thoại di động đã nhập không chính xác
10075=Mã xác minh SMS đã nhập không chính xác
10076=Loại từ điển không tồn tại
10077=Mã loại từ điển bị trùng lặp
10078=Đọc tài nguyên thất bại
10079=Mô hình LLM và nhận dạng ý định, lựa chọn tham số không khớp
10080=Dấu giọng nói này thuộc về {0} đã đăng ký, vui lòng chọn giọng nói khác
10081=Đã xảy ra lỗi khi xóa dấu giọng nói
10082=Không cho phép sửa đổi, giọng nói này đã được đăng ký làm dấu giọng nói ({0})
10083=Lỗi sửa đổi dấu giọng nói, vui lòng liên hệ quản trị viên
10084=Lỗi địa chỉ giao diện dấu giọng nói, vui lòng vào quản lý tham số để sửa đổi địa chỉ giao diện dấu giọng nói
10085=Dữ liệu âm thanh không thuộc về agent này
10086=Dữ liệu âm thanh trng, vui lòng kiểm tra dữ liệu đã tải lên
10087=Đăng ký dấu giọng nói thất bại, yêu cầu không thành công
10088=Đăng ký dấu giọng nói thất bại, xử lý yêu cầu thất bại
10089=Hủy dấu giọng nói thất bại, yêu cầu không thành công
10090=Hủy dấu giọng nói thất bại, xử lý yêu cầu thất bại
10091=Nhà cung cấp mô hình không tồn tại
10092=LLM được cấu hình không tồn tại
10093=Cấu hình mô hình này được tham chiếu bởi agent {0} và không thể xóa
10094=Mô hình LLM này được tham chiếu bởi cấu hình nhận dạng ý định và không thể xóa
10095=Thao tác máy chủ không hợp lệ
10096=Địa chỉ WebSocket máy chủ chưa được cấu hình
10097=Địa chỉ WebSocket mục tiêu không tồn tại
10098=Danh sách địa chỉ WebSocket không thể để trống
10099=Địa chỉ WebSocket không thể sử dụng localhost hoc 127.0.0.1
10100=Định dạng địa chỉ WebSocket không chính xác
10101=Kim tra kết nối WebSocket thất bại
10102=Địa chỉ OTA không thể để trống
10103=Địa chỉ OTA không thể sử dụng localhost hoc 127.0.0.1
10104=Địa chỉ OTA phải bắt đầu bằng http hoc https
10105=Địa chỉ OTA phải kết thúc bằng /ota/
10106=Truy cp giao din OTA thất bại
10107=Định dạng nội dung trả về giao din OTA không chính xác
10108=Xác thực giao din OTA thất bại
10109=Địa chỉ MCP không thể để trống
10110=Địa chỉ MCP không thể sử dụng localhost hoc 127.0.0.1
10111=Không phải địa chỉ MCP hợp lệ
10112=Truy cp giao din MCP thất bại
10113=Định dạng nội dung trả về giao din MCP không chính xác
10114=Xác thực giao din MCP thất bại
10115=Địa chỉ giao diện dấu giọng nói không thể để trống
10116=Địa chỉ giao diện dấu giọng nói không thể sử dụng localhost hoc 127.0.0.1
10117=Không phải địa chỉ giao diện dấu giọng nói hợp lệ
10118=Địa chỉ giao diện dấu giọng nói phải bắt đầu bằng http hoc https
10119=Truy cp giao diện dấu giọng nói thất bại
10120=Định dạng nội dung trả về giao diện dấu giọng nói không chính xác
10121=Xác thực giao diện dấu giọng nói thất bại
10122=Bí mật MQTT không thể để trống
10123=Bí mật MQTT của bạn không an toàn, cần ít nhất 8 ký tự và phải chứa cả chữ hoa và chữ thường
10124=Bí mật MQTT của bạn không an toàn, bí mật MQTT phải chứa cả chữ hoa và chữ thường
10125=Bí mật MQTT của bạn chứa mật khẩu yếu
10128=Nhãn từ điển bị trùng lặp
10129=Khóa SM2 chưa được cấu hình
10130=Giải mã SM2 thất bại
10131=modelType và provideCode không thể để trống
10132=Không có quyền xem lịch sử trò chuyện của agent này
10133=ID phiên không thể để trống
10134=ID agent không thể để trống
10135=Tải xuống lịch sử trò chuyện thất bại
10136=Liên kết tải xuống đã hết hạn hoặc không hợp lệ
10137=Liên kết tải xuống không hợp lệ
10138=Người dùng
10043=X\u00F3a d\u1EEF li\u1EC7u th\u1EA5t b\u1EA1i
10044=Ng\u01B0\u1EDDi d\u00F9ng ch\u01B0a \u0111\u0103ng nh\u1EADp
10045=K\u1EBFt n\u1ED1i WebSocket th\u1EA5t b\u1EA1i ho\u1EB7c h\u1EBFt th\u1EDDi gian ch\u1EDD
10046=Kh\u00F4ng th\u1EC3 l\u01B0u d\u1EA5u gi\u1ECDng n\u00F3i, vui l\u00F2ng li\u00EAn h\u1EC7 qu\u1EA3n tr\u1ECB vi\u00EAn
10047=\u0110\u1EA1t \u0111\u1EBFn gi\u1EDBi h\u1EA1n g\u1EEDi h\u00E0ng ng\u00E0y
10048=M\u1EADt kh\u1EA9u c\u0169 kh\u00F4ng ch\u00EDnh x\u00E1c
10049=LLM \u0111\u01B0\u1EE3c \u0111\u1EB7t kh\u00F4ng ph\u1EA3i l\u00E0 openai ho\u1EB7c ollama
10050=Kh\u00F4ng th\u1EC3 t\u1EA1o token
10051=Kh\u00F4ng t\u00ECm th\u1EA5y t\u00E0i nguy\u00EAn
10052=Kh\u00F4ng t\u00ECm th\u1EA5y agent m\u1EB7c \u0111\u1ECBnh
10053=Kh\u00F4ng t\u00ECm th\u1EA5y agent
10054=Giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5u h\u00ECnh, vui l\u00F2ng c\u1EA5u h\u00ECnh \u0111\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i (server.voice_print) trong c\u1EA5u h\u00ECnh tham s\u1ED1 tr\u01B0\u1EDBc
10055=G\u1EEDi SMS th\u1EA5t b\u1EA1i
10056=Kh\u00F4ng th\u1EC3 thi\u1EBFt l\u1EADp k\u1EBFt n\u1ED1i SMS
10057=Kh\u00F4ng th\u1EC3 t\u1EA1o d\u1EA5u gi\u1ECDng n\u00F3i cho agent
10058=Kh\u00F4ng th\u1EC3 c\u1EADp nh\u1EADt d\u1EA5u gi\u1ECDng n\u00F3i cho agent
10059=Kh\u00F4ng th\u1EC3 x\u00F3a d\u1EA5u gi\u1ECDng n\u00F3i cho agent
10060=G\u1EEDi qu\u00E1 th\u01B0\u1EDDng xuy\u00EAn, vui l\u00F2ng th\u1EED l\u1EA1i sau {0} gi\u00E2y
10061=M\u00E3 k\u00EDch ho\u1EA1t kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10062=L\u1ED7i m\u00E3 k\u00EDch ho\u1EA1t
10063=Thi\u1EBFt b\u1ECB \u0111\u00E3 \u0111\u01B0\u1EE3c k\u00EDch ho\u1EA1t
10064=M\u00F4 h\u00ECnh n\u00E0y l\u00E0 m\u00F4 h\u00ECnh m\u1EB7c \u0111\u1ECBnh, vui l\u00F2ng \u0111\u1EB7t m\u00F4 h\u00ECnh kh\u00E1c l\u00E0m m\u1EB7c \u0111\u1ECBnh tr\u01B0\u1EDBc
10065=Th\u00EAm d\u1EEF li\u1EC7u th\u1EA5t b\u1EA1i
10066=C\u1EADp nh\u1EADt d\u1EEF li\u1EC7u th\u1EA5t b\u1EA1i
10067=L\u1ED7i m\u00E3 x\u00E1c minh \u0111\u1ED3 h\u1ECDa
10068=\u0110\u0103ng k\u00FD di \u0111\u1ED9ng kh\u00F4ng \u0111\u01B0\u1EE3c b\u1EADt, kh\u00F4ng th\u1EC3 s\u1EED d\u1EE5ng ch\u1EE9c n\u0103ng m\u00E3 x\u00E1c minh SMS
10069=T\u00EAn ng\u01B0\u1EDDi d\u00F9ng kh\u00F4ng ph\u1EA3i l\u00E0 s\u1ED1 \u0111i\u1EC7n tho\u1EA1i di \u0111\u1ED9ng, vui l\u00F2ng nh\u1EADp l\u1EA1i
10070=S\u1ED1 \u0111i\u1EC7n tho\u1EA1i di \u0111\u1ED9ng n\u00E0y \u0111\u00E3 \u0111\u01B0\u1EE3c \u0111\u0103ng k\u00FD
10071=S\u1ED1 \u0111i\u1EC7n tho\u1EA1i di \u0111\u1ED9ng \u0111\u00E3 nh\u1EADp kh\u00F4ng \u0111\u01B0\u1EE3c \u0111\u0103ng k\u00FD
10072=Hi\u1EC7n kh\u00F4ng cho ph\u00E9p \u0111\u0103ng k\u00FD ng\u01B0\u1EDDi d\u00F9ng th\u00F4ng th\u01B0\u1EDDng
10073=\u0110\u0103ng k\u00FD di \u0111\u1ED9ng kh\u00F4ng \u0111\u01B0\u1EE3c b\u1EADt, kh\u00F4ng th\u1EC3 s\u1EED d\u1EE5ng ch\u1EE9c n\u0103ng truy xu\u1EA5t m\u1EADt kh\u1EA9u
10074=\u0110\u1ECBnh d\u1EA1ng s\u1ED1 \u0111i\u1EC7n tho\u1EA1i di \u0111\u1ED9ng \u0111\u00E3 nh\u1EADp kh\u00F4ng ch\u00EDnh x\u00E1c
10075=M\u00E3 x\u00E1c minh SMS \u0111\u00E3 nh\u1EADp kh\u00F4ng ch\u00EDnh x\u00E1c
10076=Lo\u1EA1i t\u1EEB \u0111i\u1EC3n kh\u00F4ng t\u1ED3n t\u1EA1i
10077=M\u00E3 lo\u1EA1i t\u1EEB \u0111i\u1EC3n b\u1ECB tr\u00F9ng l\u1EB7p
10078=\u0110\u1ECDc t\u00E0i nguy\u00EAn th\u1EA5t b\u1EA1i
10079=M\u00F4 h\u00ECnh LLM v\u00E0 nh\u1EADn d\u1EA1ng \u00FD \u0111\u1ECBnh, l\u1EF1a ch\u1ECDn tham s\u1ED1 kh\u00F4ng kh\u1EDBp
10080=D\u1EA5u gi\u1ECDng n\u00F3i n\u00E0y thu\u1ED9c v\u1EC1 {0} \u0111\u00E3 \u0111\u0103ng k\u00FD, vui l\u00F2ng ch\u1ECDn gi\u1ECDng n\u00F3i kh\u00E1c
10081=\u0110\u00E3 x\u1EA3y ra l\u1ED7i khi x\u00F3a d\u1EA5u gi\u1ECDng n\u00F3i
10082=Kh\u00F4ng cho ph\u00E9p s\u1EEDa \u0111\u1ED5i, gi\u1ECDng n\u00F3i n\u00E0y \u0111\u00E3 \u0111\u01B0\u1EE3c \u0111\u0103ng k\u00FD l\u00E0m d\u1EA5u gi\u1ECDng n\u00F3i ({0})
10083=L\u1ED7i s\u1EEDa \u0111\u1ED5i d\u1EA5u gi\u1ECDng n\u00F3i, vui l\u00F2ng li\u00EAn h\u1EC7 qu\u1EA3n tr\u1ECB vi\u00EAn
10084=L\u1ED7i \u0111\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i, vui l\u00F2ng v\u00E0o qu\u1EA3n l\u00FD tham s\u1ED1 \u0111\u1EC3 s\u1EEDa \u0111\u1ED5i \u0111\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i
10085=D\u1EEF li\u1EC7u \u00E2m thanh kh\u00F4ng thu\u1ED9c v\u1EC1 agent n\u00E0y
10086=D\u1EEF li\u1EC7u \u00E2m thanh tr\u1ED1ng, vui l\u00F2ng ki\u1EC3m tra d\u1EEF li\u1EC7u \u0111\u00E3 t\u1EA3i l\u00EAn
10087=\u0110\u0103ng k\u00FD d\u1EA5u gi\u1ECDng n\u00F3i th\u1EA5t b\u1EA1i, y\u00EAu c\u1EA7u kh\u00F4ng th\u00E0nh c\u00F4ng
10088=\u0110\u0103ng k\u00FD d\u1EA5u gi\u1ECDng n\u00F3i th\u1EA5t b\u1EA1i, x\u1EED l\u00FD y\u00EAu c\u1EA7u th\u1EA5t b\u1EA1i
10089=H\u1EE7y d\u1EA5u gi\u1ECDng n\u00F3i th\u1EA5t b\u1EA1i, y\u00EAu c\u1EA7u kh\u00F4ng th\u00E0nh c\u00F4ng
10090=H\u1EE7y d\u1EA5u gi\u1ECDng n\u00F3i th\u1EA5t b\u1EA1i, x\u1EED l\u00FD y\u00EAu c\u1EA7u th\u1EA5t b\u1EA1i
10091=Nh\u00E0 cung c\u1EA5p m\u00F4 h\u00ECnh kh\u00F4ng t\u1ED3n t\u1EA1i
10092=LLM \u0111\u01B0\u1EE3c c\u1EA5u h\u00ECnh kh\u00F4ng t\u1ED3n t\u1EA1i
10093=C\u1EA5u h\u00ECnh m\u00F4 h\u00ECnh n\u00E0y \u0111\u01B0\u1EE3c tham chi\u1EBFu b\u1EDFi agent {0} v\u00E0 kh\u00F4ng th\u1EC3 x\u00F3a
10094=M\u00F4 h\u00ECnh LLM n\u00E0y \u0111\u01B0\u1EE3c tham chi\u1EBFu b\u1EDFi c\u1EA5u h\u00ECnh nh\u1EADn d\u1EA1ng \u00FD \u0111\u1ECBnh v\u00E0 kh\u00F4ng th\u1EC3 x\u00F3a
10095=Thao t\u00E1c m\u00E1y ch\u1EE7 kh\u00F4ng h\u1EE3p l\u1EC7
10096=\u0110\u1ECBa ch\u1EC9 WebSocket m\u00E1y ch\u1EE7 ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5u h\u00ECnh
10097=\u0110\u1ECBa ch\u1EC9 WebSocket m\u1EE5c ti\u00EAu kh\u00F4ng t\u1ED3n t\u1EA1i
10098=Danh s\u00E1ch \u0111\u1ECBa ch\u1EC9 WebSocket kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10099=\u0110\u1ECBa ch\u1EC9 WebSocket kh\u00F4ng th\u1EC3 s\u1EED d\u1EE5ng localhost ho\u1EB7c 127.0.0.1
10100=\u0110\u1ECBnh d\u1EA1ng \u0111\u1ECBa ch\u1EC9 WebSocket kh\u00F4ng ch\u00EDnh x\u00E1c
10101=Ki\u1EC3m tra k\u1EBFt n\u1ED1i WebSocket th\u1EA5t b\u1EA1i
10102=\u0110\u1ECBa ch\u1EC9 OTA kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10103=\u0110\u1ECBa ch\u1EC9 OTA kh\u00F4ng th\u1EC3 s\u1EED d\u1EE5ng localhost ho\u1EB7c 127.0.0.1
10104=\u0110\u1ECBa ch\u1EC9 OTA ph\u1EA3i b\u1EAFt \u0111\u1EA7u b\u1EB1ng http ho\u1EB7c https
10105=\u0110\u1ECBa ch\u1EC9 OTA ph\u1EA3i k\u1EBFt th\u00FAc b\u1EB1ng /ota/
10106=Truy c\u1EADp giao di\u1EC7n OTA th\u1EA5t b\u1EA1i
10107=\u0110\u1ECBnh d\u1EA1ng n\u1ED9i dung tr\u1EA3 v\u1EC1 giao di\u1EC7n OTA kh\u00F4ng ch\u00EDnh x\u00E1c
10108=X\u00E1c th\u1EF1c giao di\u1EC7n OTA th\u1EA5t b\u1EA1i
10109=\u0110\u1ECBa ch\u1EC9 MCP kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10110=\u0110\u1ECBa ch\u1EC9 MCP kh\u00F4ng th\u1EC3 s\u1EED d\u1EE5ng localhost ho\u1EB7c 127.0.0.1
10111=Kh\u00F4ng ph\u1EA3i \u0111\u1ECBa ch\u1EC9 MCP h\u1EE3p l\u1EC7
10112=Truy c\u1EADp giao di\u1EC7n MCP th\u1EA5t b\u1EA1i
10113=\u0110\u1ECBnh d\u1EA1ng n\u1ED9i dung tr\u1EA3 v\u1EC1 giao di\u1EC7n MCP kh\u00F4ng ch\u00EDnh x\u00E1c
10114=X\u00E1c th\u1EF1c giao di\u1EC7n MCP th\u1EA5t b\u1EA1i
10115=\u0110\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10116=\u0110\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i kh\u00F4ng th\u1EC3 s\u1EED d\u1EE5ng localhost ho\u1EB7c 127.0.0.1
10117=Kh\u00F4ng ph\u1EA3i \u0111\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i h\u1EE3p l\u1EC7
10118=\u0110\u1ECBa ch\u1EC9 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i ph\u1EA3i b\u1EAFt \u0111\u1EA7u b\u1EB1ng http ho\u1EB7c https
10119=Truy c\u1EADp giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i th\u1EA5t b\u1EA1i
10120=\u0110\u1ECBnh d\u1EA1ng n\u1ED9i dung tr\u1EA3 v\u1EC1 giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i kh\u00F4ng ch\u00EDnh x\u00E1c
10121=X\u00E1c th\u1EF1c giao di\u1EC7n d\u1EA5u gi\u1ECDng n\u00F3i th\u1EA5t b\u1EA1i
10122=B\u00ED m\u1EADt MQTT kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10123=B\u00ED m\u1EADt MQTT c\u1EE7a b\u1EA1n kh\u00F4ng an to\u00E0n, c\u1EA7n \u00EDt nh\u1EA5t 8 k\u00FD t\u1EF1 v\u00E0 ph\u1EA3i ch\u1EE9a c\u1EA3 ch\u1EEF hoa v\u00E0 ch\u1EEF th\u01B0\u1EDDng
10124=B\u00ED m\u1EADt MQTT c\u1EE7a b\u1EA1n kh\u00F4ng an to\u00E0n, b\u00ED m\u1EADt MQTT ph\u1EA3i ch\u1EE9a c\u1EA3 ch\u1EEF hoa v\u00E0 ch\u1EEF th\u01B0\u1EDDng
10125=B\u00ED m\u1EADt MQTT c\u1EE7a b\u1EA1n ch\u1EE9a m\u1EADt kh\u1EA9u y\u1EBFu
10128=Nh\u00E3n t\u1EEB \u0111i\u1EC3n b\u1ECB tr\u00F9ng l\u1EB7p
10129=Kh\u00F3a SM2 ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5u h\u00ECnh
10130=Gi\u1EA3i m\u00E3 SM2 th\u1EA5t b\u1EA1i
10131=modelType v\u00E0 provideCode kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10132=Kh\u00F4ng c\u00F3 quy\u1EC1n xem l\u1ECBch s\u1EED tr\u00F2 chuy\u1EC7n c\u1EE7a agent n\u00E0y
10133=ID phi\u00EAn kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10134=ID agent kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10135=T\u1EA3i xu\u1ED1ng l\u1ECBch s\u1EED tr\u00F2 chuy\u1EC7n th\u1EA5t b\u1EA1i
10136=Li\u00EAn k\u1EBFt t\u1EA3i xu\u1ED1ng \u0111\u00E3 h\u1EBFt h\u1EA1n ho\u1EB7c kh\u00F4ng h\u1EE3p l\u1EC7
10137=Li\u00EAn k\u1EBFt t\u1EA3i xu\u1ED1ng kh\u00F4ng h\u1EE3p l\u1EC7
10138=Ng\u01B0\u1EDDi d\u00F9ng
10139=Agent
10140=Tệp âm thanh không thể để trống
10141=Chỉ hỗ trợ tệp âm thanh
10142=Kích thước tệp âm thanh không thể vượt quá 10MB
10143=Tải lên thất bại
10144=Bn ghi nhân bản giọng nói không tồn tại
10145=Thông tin tài nguyên giọng nói không thể để trống
10146=Tên nền tảng TTS không thể để trống
10147=ID giọng nói không thể để trống
10148=Tài khoản chủ sở hữu không thể để trống
10149=ID tài nguyên giọng nói cần xóa không thể để trống
10150=Bạn không có quyền thao tác bản ghi này
10151=Vui lòng tải lên tệp âm thanh trước
10152=Không tìm thấy cấu hình mô hình
10153=Không tìm thấy loại mô hình
10154=Đào tạo thất bại: {0}
10155=Thiếu cấu hình Huoshan Engine
10156=Lỗi định dạng phản hồi, thiếu trường BaseResp
10157=Yêu cầu thất bại
10158=Nhân bản âm sắc:
10159=ID giọng nói đã tồn tại
10160=Lỗi định dạng ID giọng nói Huoshan Engine, phải bắt đầu bằng S_
10161=Địa chỉ Mac đã tồn tại
10162=Nhà cung cấp mô hình không tồn tại
10163=Bn ghi cơ sở kiến thức không tồn tại
10164=Không tìm thấy cấu hình RAG
10165=Lỗi loại cấu hình RAG
10166=Không tìm thấy cấu hình RAG mặc định
10167=Gi API RAG thất bại: {0}
10168=Tải lên tệp thất bại
10169=Không có quyền thao tác cơ sở kiến thức này
10170=Tên cơ sở kiến thức đã tồn tại
10171=Cấu hình RAG base_url không thể để trống
10172=Cấu hình RAG api_key không thể để trống
10173=Cấu hình RAG api_key không thể chứa trình giữ chỗ, vui lòng thay thế bằng khóa API thực tế
10174=Lỗi định dạng cấu hình RAG base_url, phải bắt đầu bằng http hoc https
10175=Địa chỉ Mac không thể để trống
10176=Cấu hình RAG dataset_id không thể để trống
10177=Cấu hình RAG model_id không thể để trống
10178=Cấu hình RAG dataset_id và model_id không thể để trống
10179=Tên tệp không thể để trống
10180=Ni dung tệp không thể để trống
10181=Tên nhân bản giọng nói không thể để trống
10182=Không tìm thấy âm thanh nhân bản giọng nói
10183=Không tìm thấy mẫu agent mặc định
10184=Loại bộ chuyển đổi không được hỗ trợ
10185=Kim tra cấu hình RAG thất bại
10186=Tạo bộ chuyển đổi thất bại
10187=Khởi tạo bộ chuyển đổi thất bại
10188=Kim tra kết nối bộ chuyển đổi thất bại
10189=Thao tác bộ chuyển đổi thất bại
10190=Không tìm thấy bộ chuyển đổi
10191=Lỗi bộ nhớ đệm bộ chuyển đổi
10192=Không tìm thấy loại bộ chuyển đổi
10140=T\u1EC7p \u00E2m thanh kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10141=Ch\u1EC9 h\u1ED7 tr\u1EE3 t\u1EC7p \u00E2m thanh
10142=K\u00EDch th\u01B0\u1EDBc t\u1EC7p \u00E2m thanh kh\u00F4ng th\u1EC3 v\u01B0\u1EE3t qu\u00E1 10MB
10143=T\u1EA3i l\u00EAn th\u1EA5t b\u1EA1i
10144=B\u1EA3n ghi nh\u00E2n b\u1EA3n gi\u1ECDng n\u00F3i kh\u00F4ng t\u1ED3n t\u1EA1i
10145=Th\u00F4ng tin t\u00E0i nguy\u00EAn gi\u1ECDng n\u00F3i kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10146=T\u00EAn n\u1EC1n t\u1EA3ng TTS kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10147=ID gi\u1ECDng n\u00F3i kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10148=T\u00E0i kho\u1EA3n ch\u1EE7 s\u1EDF h\u1EEFu kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10149=ID t\u00E0i nguy\u00EAn gi\u1ECDng n\u00F3i c\u1EA7n x\u00F3a kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10150=B\u1EA1n kh\u00F4ng c\u00F3 quy\u1EC1n thao t\u00E1c b\u1EA3n ghi n\u00E0y
10151=Vui l\u00F2ng t\u1EA3i l\u00EAn t\u1EC7p \u00E2m thanh tr\u01B0\u1EDBc
10152=Kh\u00F4ng t\u00ECm th\u1EA5y c\u1EA5u h\u00ECnh m\u00F4 h\u00ECnh
10153=Kh\u00F4ng t\u00ECm th\u1EA5y lo\u1EA1i m\u00F4 h\u00ECnh
10154=\u0110\u00E0o t\u1EA1o th\u1EA5t b\u1EA1i: {0}
10155=Thi\u1EBFu c\u1EA5u h\u00ECnh Huoshan Engine
10156=L\u1ED7i \u0111\u1ECBnh d\u1EA1ng ph\u1EA3n h\u1ED3i, thi\u1EBFu tr\u01B0\u1EDDng BaseResp
10157=Y\u00EAu c\u1EA7u th\u1EA5t b\u1EA1i
10158=Nh\u00E2n b\u1EA3n \u00E2m s\u1EAFc:
10159=ID gi\u1ECDng n\u00F3i \u0111\u00E3 t\u1ED3n t\u1EA1i
10160=L\u1ED7i \u0111\u1ECBnh d\u1EA1ng ID gi\u1ECDng n\u00F3i Huoshan Engine, ph\u1EA3i b\u1EAFt \u0111\u1EA7u b\u1EB1ng S_
10161=\u0110\u1ECBa ch\u1EC9 Mac \u0111\u00E3 t\u1ED3n t\u1EA1i
10162=Nh\u00E0 cung c\u1EA5p m\u00F4 h\u00ECnh kh\u00F4ng t\u1ED3n t\u1EA1i
10163=B\u1EA3n ghi c\u01A1 s\u1EDF ki\u1EBFn th\u1EE9c kh\u00F4ng t\u1ED3n t\u1EA1i
10164=Kh\u00F4ng t\u00ECm th\u1EA5y c\u1EA5u h\u00ECnh RAG
10165=L\u1ED7i lo\u1EA1i c\u1EA5u h\u00ECnh RAG
10166=Kh\u00F4ng t\u00ECm th\u1EA5y c\u1EA5u h\u00ECnh RAG m\u1EB7c \u0111\u1ECBnh
10167=G\u1ECDi API RAG th\u1EA5t b\u1EA1i: {0}
10168=T\u1EA3i l\u00EAn t\u1EC7p th\u1EA5t b\u1EA1i
10169=Kh\u00F4ng c\u00F3 quy\u1EC1n thao t\u00E1c c\u01A1 s\u1EDF ki\u1EBFn th\u1EE9c n\u00E0y
10170=T\u00EAn c\u01A1 s\u1EDF ki\u1EBFn th\u1EE9c \u0111\u00E3 t\u1ED3n t\u1EA1i
10171=C\u1EA5u h\u00ECnh RAG base_url kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10172=C\u1EA5u h\u00ECnh RAG api_key kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10173=C\u1EA5u h\u00ECnh RAG api_key kh\u00F4ng th\u1EC3 ch\u1EE9a tr\u00ECnh gi\u1EEF ch\u1ED7, vui l\u00F2ng thay th\u1EBF b\u1EB1ng kh\u00F3a API th\u1EF1c t\u1EBF
10174=L\u1ED7i \u0111\u1ECBnh d\u1EA1ng c\u1EA5u h\u00ECnh RAG base_url, ph\u1EA3i b\u1EAFt \u0111\u1EA7u b\u1EB1ng http ho\u1EB7c https
10175=\u0110\u1ECBa ch\u1EC9 Mac kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10176=C\u1EA5u h\u00ECnh RAG dataset_id kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10177=C\u1EA5u h\u00ECnh RAG model_id kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10178=C\u1EA5u h\u00ECnh RAG dataset_id v\u00E0 model_id kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10179=T\u00EAn t\u1EC7p kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10180=N\u1ED9i dung t\u1EC7p kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10181=T\u00EAn nh\u00E2n b\u1EA3n gi\u1ECDng n\u00F3i kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng
10182=Kh\u00F4ng t\u00ECm th\u1EA5y \u00E2m thanh nh\u00E2n b\u1EA3n gi\u1ECDng n\u00F3i
10183=Kh\u00F4ng t\u00ECm th\u1EA5y m\u1EABu agent m\u1EB7c \u0111\u1ECBnh
10184=Lo\u1EA1i b\u1ED9 chuy\u1EC3n \u0111\u1ED5i kh\u00F4ng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3
10185=Ki\u1EC3m tra c\u1EA5u h\u00ECnh RAG th\u1EA5t b\u1EA1i
10186=T\u1EA1o b\u1ED9 chuy\u1EC3n \u0111\u1ED5i th\u1EA5t b\u1EA1i
10187=Kh\u1EDFi t\u1EA1o b\u1ED9 chuy\u1EC3n \u0111\u1ED5i th\u1EA5t b\u1EA1i
10188=Ki\u1EC3m tra k\u1EBFt n\u1ED1i b\u1ED9 chuy\u1EC3n \u0111\u1ED5i th\u1EA5t b\u1EA1i
10189=Thao t\u00E1c b\u1ED9 chuy\u1EC3n \u0111\u1ED5i th\u1EA5t b\u1EA1i
10190=Kh\u00F4ng t\u00ECm th\u1EA5y b\u1ED9 chuy\u1EC3n \u0111\u1ED5i
10191=L\u1ED7i b\u1ED9 nh\u1EDB \u0111\u1EC7m b\u1ED9 chuy\u1EC3n \u0111\u1ED5i
10192=Kh\u00F4ng t\u00ECm th\u1EA5y lo\u1EA1i b\u1ED9 chuy\u1EC3n \u0111\u1ED5i
10193=ID thi\u1EBFt b\u1ECB kh\u00F4ng th\u1EC3 tr\u1ED1ng
10194=Kh\u00F4ng t\u00ECm th\u1EA5y thi\u1EBFt b\u1ECB ho\u1EB7c thi\u1EBFt b\u1ECB kh\u00F4ng tr\u1EF1c tuy\u1EBFn
10195=S\u1ED1 l\u1EA7n t\u1EA3i l\u00EAn OTA v\u01B0\u1EE3t qu\u00E1 gi\u1EDBi h\u1EA1n
@@ -198,4 +198,7 @@
10189=\u9002\u914D\u5668\u64CD\u4F5C\u5931\u8D25
10190=\u9002\u914D\u5668\u672A\u627E\u5230
10191=\u9002\u914D\u5668\u7F13\u5B58\u9519\u8BEF
10192=\u9002\u914D\u5668\u7C7B\u578B\u672A\u627E\u5230
10192=\u9002\u914D\u5668\u7C7B\u578B\u672A\u627E\u5230
10193=\u8BBE\u5907ID\u4E0D\u80FD\u4E3A\u7A7A
10194=\u8BBE\u5907\u4E0D\u5B58\u5728\u6216\u4E0D\u5728\u7EBF
10195=OTA\u4E0A\u4F20\u6B21\u6570\u8D85\u8FC7\u9650\u5236
@@ -164,7 +164,7 @@
10155=\u706B\u5C71\u5F15\u64CE\u7F3A\u5C11appid\u6216access_token
10156=\u97FF\u61C9\u683C\u5F0F\u932F\u8AA4\uFF0C\u7F3A\u5C11BaseResp\u5B57\u6BB5
10157=\u8ACB\u6C42\u5931\u6557
10158=\u514b\u9686\u97f3\u8272:
10158=\u514B\u9686\u97F3\u8272:
10159=\u97F3\u8272ID\u5DF2\u5B58\u5728
10160=\u706B\u5C71\u5F15\u64CE\u97F3\u8272ID\u683C\u5F0F\u932F\u8AA4\uFF0C\u5FC5\u9808\u4EE5S_\u958B\u982D
10161=Mac\u5730\u5740\u5DF2\u5B58\u5728
@@ -173,23 +173,23 @@
10164=RAG\u914D\u7F6E\u672A\u627E\u5230
10165=RAG\u914D\u7F6E\u985E\u578B\u932F\u8AA4
10166=\u9810\u8A2DRAG\u914D\u7F6E\u672A\u627E\u5230
10167=\u0052\u0041\u0047\u8abf\u7528\u5931\u6557\uFF0C{0}
10167=RAG\u8ABF\u7528\u5931\u6557\uFF0C{0}
10168=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557
10169=\u60A8\u6C92\u6709\u6B0A\u9650\u64CD\u4F5C\u8A72\u8A18\u9304
10170=\u77E5\u8B58\u5EAB\u540D\u7A31\u91CD\u8907
10171=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684base_url\u4E0D\u80FD\u4E3A\u7A7A
10172=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A
10173=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u66F4\u6362\u4E3A\u5728\u53D6\u7684API\u53C2\u6570
10174=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684base_url\u683C\u5F0F\u9519\u8BEF\uFF0C\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934
10171=RAG\u914D\u7F6E\u4F53\u7684base_url\u4E0D\u80FD\u4E3A\u7A7A
10172=RAG\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A
10173=RAG\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u66F4\u6362\u4E3A\u5728\u53D6\u7684API\u53C2\u6570
10174=RAG\u914D\u7F6E\u4F53\u7684base_url\u683C\u5F0F\u9519\u8BEF\uFF0C\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934
10175=mac\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A
10176=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684dataset_id\u4E0D\u80FD\u4E3A\u7A7A
10177=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684model_id\u4E0D\u80FD\u4E3A\u7A7A
10178=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684dataset_id\u548Cmodel_id\u4E0D\u80FD\u4E3A\u7A7A
10179=\u6587\u4ef6\u540d\u7a31\u4e0d\u80fd\u70ba\u7a7a
10180=\u6587\u4ef6\u5185\u5bb9\u4e0d\u80fd\u70ba\u7a7a
10181=\u97f3\u8272\u514b\u9686\u540d\u7a31\u4e0d\u80fd\u70ba\u7a7a
10182=\u97f3\u8272\u514b\u9686\u97f3\u983b\u4e0d\u5b58\u5728
10183=\u9ed8\u8ba4\u667a\u80fd\u4f53\u672a\u627e\u5230
10176=RAG\u914D\u7F6E\u4F53\u7684dataset_id\u4E0D\u80FD\u4E3A\u7A7A
10177=RAG\u914D\u7F6E\u4F53\u7684model_id\u4E0D\u80FD\u4E3A\u7A7A
10178=RAG\u914D\u7F6E\u4F53\u7684dataset_id\u548Cmodel_id\u4E0D\u80FD\u4E3A\u7A7A
10179=\u6587\u4EF6\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
10180=\u6587\u4EF6\u5185\u5BB9\u4E0D\u80FD\u70BA\u7A7A
10181=\u97F3\u8272\u514B\u9686\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
10182=\u97F3\u8272\u514B\u9686\u97F3\u983B\u4E0D\u5B58\u5728
10183=\u9ED8\u8BA4\u667A\u80FD\u4F53\u672A\u627E\u5230
10184=\u4E0D\u652F\u6301\u7684\u9002\u914D\u5668\u985E\u578B
10185=RAG\u914D\u7F6E\u9A57\u8B49\u5931\u6557
10186=\u9002\u914D\u5668\u5275\u5EFA\u5931\u6557
@@ -198,4 +198,7 @@
10189=\u9002\u914D\u5668\u64CD\u4F5C\u5931\u6557
10190=\u9002\u914D\u5668\u672A\u627E\u5230
10191=\u9002\u914D\u5668\u7F13\u5B58\u932F\u8AA4
10192=\u9002\u914D\u5668\u985E\u578B\u672A\u627E\u5230
10192=\u9002\u914D\u5668\u985E\u578B\u672A\u627E\u5230
10193=\u8A2D\u5099ID\u4E0D\u80FD\u4E3A\u7A7A
10194=\u8A2D\u5099\u4E0D\u5B58\u5728\u6216\u672A\u5728\u7DDA
10195=OTA\u4E0A\u4F20\u6B21\u6578\u8D85\u904E\u9650\u5236
@@ -15,4 +15,23 @@
FROM sys_dict_type
WHERE id = #{dictTypeId}
</select>
<select id="getDictTypesByIdList" resultType="java.lang.String">
SELECT
dict_type
FROM
sys_dict_type
WHERE
id IN (
SELECT
dict_type_id
FROM
sys_dict_data
WHERE
id IN
<foreach collection="dictDataIdList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
)
</select>
</mapper>
@@ -235,7 +235,7 @@ function showAbout() {
title: t('settings.aboutApp', { appName: import.meta.env.VITE_APP_TITLE }),
content: t('settings.aboutContent', {
appName: import.meta.env.VITE_APP_TITLE,
version: '0.8.10'
version: '0.9.1'
}),
showCancel: false,
confirmText: t('common.confirm'),
@@ -0,0 +1,89 @@
# 语音盒子主题自定义
## 项目概述
本目录包含从 [xiaozhi-assets-generator](https://github.com/xinnan-tech/xiaozhi-assets-generator) 项目打包的静态文件,用于语音盒子主题的在线自定义与生成。用户可以通过此工具配置唤醒词、字体、表情和聊天背景等元素,并导出为 `assets.bin` 文件。
## 目录结构
```
generator/
├── assets/ # 构建生成的资源文件
│ ├── ft_render-ByO_jG18.js
│ ├── index-CYcyz9xb.js
│ └── index-NXxBVrod.css
├── static/ # 静态资源目录
│ ├── charsets/ # 字符集文件
│ │ ├── deepseek.txt
│ │ ├── gb2312.txt
│ │ ├── latin1.txt
│ │ └── qwen18409.txt
│ ├── fonts/ # 字体资源
│ │ ├── font_noto_qwen_14_1.bin
│ │ ├── font_noto_qwen_16_4.bin
│ │ ├── font_noto_qwen_20_4.bin
│ │ ├── font_noto_qwen_30_4.bin
│ │ ├── font_puhui_deepseek_14_1.bin
│ │ ├── font_puhui_deepseek_16_4.bin
│ │ ├── font_puhui_deepseek_20_4.bin
│ │ ├── font_puhui_deepseek_30_4.bin
│ │ ├── noto_qwen.ttf
│ │ └── puhui_deepseek.ttf
│ ├── multinet_model/ # 自定义唤醒词模型
│ │ ├── fst/
│ │ ├── mn6_cn/
│ │ ├── mn6_en/
│ │ ├── mn7_cn/
│ │ └── mn7_en/
│ ├── twemoji32/ # 32x32 表情图片
│ ├── twemoji64/ # 64x64 表情图片
│ ├── wakenet_model/ # 预设唤醒词模型
│ └── README.md # 静态资源说明
├── index.html # 主页面
└── README.md # 项目说明文档
```
## 主要功能
### 1. 芯片与屏幕配置
- 支持多种芯片型号:ESP32-S3、ESP32-C3、ESP32-P4、ESP32-C6
- 灵活的屏幕分辨率设置
- 支持 RGB565 颜色格式
### 2. 唤醒词配置
- **预设唤醒词**:基于不同芯片支持的 WakeNet 模型
- **自定义唤醒词**:支持中文和英文命令词,可配置阈值和超时时间
### 3. 字体配置
- 预设多种字体:阿里巴巴普惠体、Noto Qwen 等
- 支持上传自定义 TTF/WOFF 字体文件
- 可配置字号和颜色深度(bpp
### 4. 表情集合
- 提供 21 种基础表情的预设方案(32x32 和 64x64 两种尺寸)
- 支持自定义表情上传
### 5. 聊天背景
- 支持浅色/深色模式切换
- 可配置纯色背景或图片背景
- 自动适配屏幕分辨率
## 使用方法
1. 以服务方式启动 `index.html` 文件
2. 选择芯片型号和屏幕配置
3. 通过不同标签页配置主题元素
4. 点击生成按钮查看资源清单
5. 确认后生成并下载 `assets.bin` 文件
## 技术说明
- 构建后的静态资源位于 `assets/` 目录
- 原始模型和资源文件位于 `static/` 目录
- 支持离线使用,无需额外依赖
## 注意事项
- 本工具为离线使用设计,所有资源已包含在目录中
- 生成的 `assets.bin` 文件需要与语音盒子硬件配合使用
- 自定义资源需注意文件格式和大小限制,以确保兼容
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="./favicon.ico">
<title>Xiaozhi AI Customization</title>
<script type="module" crossorigin src="./assets/index-B8r0c7xg.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CrIJdTCK.css">
</head>
<body>
<div id="app"></div>
</body>
@@ -0,0 +1,20 @@
### Alibaba Puhui Fonts
https://www.alibabafonts.com/
### twemoji32 / twemoji64
https://github.com/twitter/twemoji
### Wakenet models
The wakenet model weights are copied from the ESP-SR repo.
https://github.com/espressif/esp-sr/tree/master/model/wakenet_model
### Multinet models
The multinet model weights are copied from the ESP-SR repo.
https://github.com/espressif/esp-sr/tree/master/model/multinet_model
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,190 @@
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
¡
¢
£
¤
¥
¦
§
¨
©
ª
«
¬
­
®
¯
°
±
²
³
´
µ
·
¸
¹
º
»
¼
½
¾
¿
À
Á
Â
Ã
Ä
Å
Æ
Ç
È
É
Ê
Ë
Ì
Í
Î
Ï
Ð
Ñ
Ò
Ó
Ô
Õ
Ö
×
Ø
Ù
Ú
Û
Ü
Ý
Þ
ß
à
á
â
ã
ä
å
æ
ç
è
é
ê
ë
ì
í
î
ï
ð
ñ
ò
ó
ô
õ
ö
÷
ø
ù
ú
û
ü
ý
þ
ÿ
@@ -0,0 +1,313 @@
1,ba xiao shi hou guan ji
2,ba xiao shi hou kai ji
3,bi kai wo chui
4,chao qiang feng su
5,chao zhe wo chui
6,chou shi mo shi
7,chu shi mo shi
8,da kai bai feng
9,da kai bing xiang
10,da kai chou shi mo shi
11,da kai chu jun
12,da kai chu shi mo shi
13,da kai dian fu re
14,da kai ding chu feng
15,da kai ding xiang chu wu
16,da kai er tong fang leng feng
17,da kai fang zhi chui
18,da kai feng ji
19,da kai fu re
20,da kai gan zao
21,da kai huan ji tiao wen
22,da kai jia shi
23,da kai jing hua
24,da kai jun yun feng
25,da kai kong tiao
26,da kai kong tiao deng guang
27,da kai mu ying feng
28,da kai mu qing feng
29,da kai pai feng mo shi
30,da kai pai qi
31,da kai pai qi mo shi
32,da kai qiang jing
33,da kai quan wu feng gan
34,da kai rou feng gan
35,da kai shang wu feng gan
36,da kai shang xia bai feng
37,da kai shang xia sao feng
38,da kai sen ba
39,da kai shu sheng
40,da kai shu shi feng
41,da kai shui mian
42,da kai si ji chu shi
43,da kai si ji chu shi mo shi
44,da kai song feng
45,da kai song feng mo shi
46,da kai wu feng gan
47,da kai xia wu feng gan
48,da kai xin feng
49,da kai xiu xian mo shi
50,da kai xuan zhuan song feng
51,da kai yi jian chu wu
52,da kai zhi leng
53,da kai zhi leng mo shi
54,da kai zhi re
55,da kai zhi re mo shi
56,da kai zhi kong wen
57,da kai zhi neng guan jia
58,da kai zhi neng sha jun
59,da kai zhi neng sheng dian
60,da kai zhi qing jie
61,da kai zhi wen gan
62,da kai zhuan shu wen du
63,da kai zi dong mo shi
64,da kai zuo you bai feng
65,da kai zuo you sao feng
66,di feng su
67,di su feng
68,di yi dian
69,dian fu re
70,tiao cheng zui leng
71,tiao cheng zui nuan
72,tiao da feng su
73,tiao da xin feng
74,tiao dao er shi ba du
75,tiao dao er shi du
76,tiao dao er shi er du
77,tiao dao er shi jiu du
78,tiao dao er shi liu du
79,tiao dao er shi qi du
80,tiao dao er shi san du
81,tiao dao er shi si du
82,tiao dao er shi wu du
83,tiao dao er shi yi du
84,tiao dao san shi du
85,tiao dao shi ba du
86,tiao dao shi jiu du
87,tiao dao shi liu du
88,tiao dao shi qi du
89,tiao dao zui leng
90,tiao dao zui nuan
91,tiao di ling dian wu du
92,tiao di wen du
93,tiao di yi du
94,tiao gao er shi du
95,tiao gao ling dian wu du
96,tiao gao wen du
97,tiao gao wu du
98,tiao gao yi du
99,tiao leng yi dian
100,tiao nuan
101,tiao nuan yi dian
102,tiao xiao feng su
103,tiao xiao xin feng
104,ding chu feng
105,ding shi wu rao
106,ding xiang chu wu
107,er tong fang leng feng
108,er dang xin feng
109,feng da yi dian
110,feng su da dian
111,feng su er dang
112,feng su san dang
113,feng su xiao dian
114,feng su yi dang
115,feng wang shang chui
116,feng wang xia chui
117,feng wang you chui
118,feng wang zhong jian chui
119,feng wang zuo chui
120,feng xiang shang chui
121,feng xiang xia chui
122,feng xiang you chui
123,feng xiang zhong jian chui
124,feng xiang zuo chui
125,feng xiao yi dian
126,gao feng su
127,gao su feng
128,guan bi bai feng
129,fang zhi chui
130,guan bi dian fu re
131,guan bi ding chu feng
132,guan bi ding xiang chu wu
133,guan bi er tong fang leng feng
134,guan bi fang zhi chui
135,guan bi feng ji
136,guan bi fu re
137,guan bi huan qi
138,guan bi huan qi mo shi
139,guan bi jia shi
140,guan bi jie neng
141,guan bi jun yun feng
142,guan bi kong tiao
143,guan bi kong tiao deng guang
144,guan bi mu ying feng
145,guan bi mu qing feng
146,guan bi qiang jing
147,guan bi quan wu feng gan
148,guan bi rou feng gan
149,guan bi sen ba
150,guan bi shang wu feng gan
151,guan bi shang xia bai feng
152,guan bi shang xia sao feng
153,guan bi shu sheng
154,guan bi shui mian
155,guan bi si ji chu shi
156,guan bi si ji chu shi mo shi
157,guan bi wu feng gan
158,guan bi xia wu feng gan
159,guan bi xin feng
160,guan bi xuan zhuan song feng
161,guan bi yi jian chu wu
162,guan bi zhi kong wen
163,guan bi zhi qing jie
164,guan bi zhong wen bao wen
165,guan bi zhuan xiang wen du er
166,guan bi zhuan xiang wen du san
167,guan bi zhuan xiang wen du yi
168,guan bi zuo you bai feng
169,guan bi zuo you sao feng
170,guan bi zhuan shu wen du
171,guan diao bai feng
172,guan diao dian fu re
173,guan diao ding chu feng
174,guan diao ding xiang chu wu
175,guan diao er tong fang leng feng
176,guan diao fang zhi chui
177,guan diao gan zao
178,guan diao huan qi
179,guan diao huan qi mo shi
180,guan diao jia shi
181,guan diao jing hua
182,guan diao jun yun feng
183,guan diao kong tiao
184,guan diao kong tiao deng guang
185,guan diao qiang jing
186,guan diao quan wu feng gan
187,guan diao rou feng gan
188,guan diao shang wu feng gan
189,guan diao shang xia bai feng
190,guan diao shu sheng
191,guan diao shui mian
192,guan diao si ji chu shi
193,guan diao si ji chu shi mo shi
194,guan diao wu feng gan
195,guan diao xia wu feng gan
196,guan diao xin feng
197,guan diao xuan zhuan song feng
198,guan diao yi jian chu wu
199,guan diao zhi kong wen
200,guan diao zhi qing jie
201,guan diao zuo you bai feng
202,guan kong tiao
203,guan shang xia bai feng
204,guan shang xia feng
205,guan xin feng
206,guan zuo you bai feng
207,guan zuo you feng
208,guan bi zhi neng sheng dian
209,jian xiao feng su
210,jian xiao pu tong xin feng
211,jian xiao xin feng
212,jiang di wen du
213,jing yin feng
214,jing yin feng su
215,jun yun feng
216,kai kong tiao
217,kai qi bai feng
218,kai qi chu shi
219,kai qi chu shi mo shi
220,kai qi kong tiao
221,kai qi pai feng mo shi
222,kai qi shang xia sao feng
223,kai qi tong feng
224,kai qi zhi leng
225,kai qi zhi leng mo shi
226,kai qi zhi re
227,kai qi zhi re mo shi
228,kai qi zuo you sao feng
229,kai shi chu wei
230,kong tiao da kai
231,kong tiao guan bi
232,kong tiao guan diao
233,kong tiao guan ji
234,kong tiao kai ji
235,kong tiao kai shi pei wang
236,kong tiao lian wang
237,kong tiao chong xin pei wang
238,kai xin feng
239,leng yi dian
240,nuan yi dian
241,pu tong xin feng
242,qi dong kong tiao
243,qiang jing xin feng
244,qiang li feng
245,qiang li feng su
246,qu shi mo shi
247,quan wu feng gan
248,rou feng gan
249,san dang xin feng
250,shang wu feng gan
251,shang xia bai feng
252,shang xia feng
253,sheng gao wen du
254,sheng dao zui gao
255,sheng dao zui gao wei zhi
256,si dang xin feng
257,si ji chu shi
258,si ji chu shi mo shi
259,song feng mo shi
260,tai leng le
261,tai re le
262,ting zhi shang xia bai feng
263,ting zhi shang xia sao feng
264,ting zhi bai feng
265,ting zhi zhuan shu wen du
266,ting zhi zuo you bai feng
267,ting zhi zuo you sao feng
268,xia wu feng gan
269,xin feng da dian
270,xin feng er dang
271,xin feng qiang jing
272,xin feng qiang jing dang
273,xin feng san dang
274,xin feng si dang
275,xin feng xiao dian
276,xin feng yi dang
277,xin feng zui da
278,xin feng zui da dang
279,xin feng zui xiao
280,xin feng zui xiao dang
281,xuan zhuan song feng
282,yi dang xin feng
283,you dian leng
284,you dian re
285,zai gao yi dian
286,zeng da feng su
287,zeng da xin feng
288,zhi leng mo shi
289,zhi re mo shi
290,zhi kong wen
291,zhi neng wu rao
292,zhi qing jie
293,zhong deng feng
294,zhong feng su
295,zhong su feng
296,zi dong
297,zi dong feng
298,zi dong feng su
299,zi dong mo shi
300,zui da feng
301,zui da feng su
302,zui da xin feng
303,zui xiao feng
304,zui xiao feng su
305,zui xiao xin feng
306,zuo you bai feng
307,zuo you feng
308,bang wo guan deng
309,bang wo kai deng
310,da kai dian deng
311,guan bi dian deng
312,xiao le xiao le
313,xiao xin xiao xin
@@ -0,0 +1,49 @@
1,TELL ME A JOKE,TfL Mm c qbK
2,SING A SONG,Sgl c Sel
3,PLAY NEWS CHANNEL,PLd NoZ paNcL
4,TURN ON MY SOUNDBOX,TkN nN Mi StNDBnKS
5,TURN OFF MY SOUNDBOX,TkN eF Mi StNDBnKS
5,TURN OF MY SOUNDBOX,TkN cV Mi StNDBnKS
6,HIGHEST VOLUME,hicST VnLYoM
7,LOWEST VOLUME,LbcST VnLYoM
8,INCREASE THE VOLUME,gNKRmS jc VnLYoM
9,DECREASE THE VOLUME,DgKRmS jc VnLYoM
10,TURN ON THE TV,TkN nN jc TmVm
11,TURN OFF THE TV,TkN eF jc TmVm
11,TURN OF THE TV,TkN cV jc TmVm
12,MAKE ME A TEA,MdK Mm c Tm
13,MAKE ME A COFFEE,MdK Mm c KnFm
14,TURN ON THE LIGHT,TkN nN jc LiT
15,TURN OFF THE LIGHT,TkN eF jc LiT
15,TURN OF THE LIGHT,TkN cV jc LiT
16,CHANGE THE COLOR TO RED,pdNq jc KcLk To RfD
17,CHANGE THE COLOR TO GREEN,pdNq jc KcLk To GRmN
18,TURN ON ALL THE LIGHTS,TkN nN eL jc LiTS
19,TURN OFF ALL THE LIGHTS,TkN eF eL jc LiTS
19,TURN OF ALL THE LIGHTS,TkN cV eL jc LiTS
20,TURN ON THE AIR CONDITIONER,TkN nN jc fR KcNDgscNk
21,TURN OFF THE AIR CONDITIONER,TkN eF jc fR KcNDgscNk
21,TURN OF THE AIR CONDITIONER,TkN cV jc fR KcNDgscNk
22,SET THE TEMPERATURE TO SIXTEEN DEGREES,SfT jc TfMPRcpk To SgKSTmN DgGRmZ
23,SET THE TEMPERATURE TO SEVENTEEN DEGREES,SfT jc TfMPRcpk To SfVcNTmN DgGRmZ
24,SET THE TEMPERATURE TO EIGHTEEN DEGREES,SfT jc TfMPRcpk To dTmN DgGRmZ
25,SET THE TEMPERATURE TO NINETEEN DEGREES,SfT jc TfMPRcpk To NiNTmN DgGRmZ
26,SET THE TEMPERATURE TO TWENTY DEGREES,SfT jc TfMPRcpk To TWfNTm DgGRmZ
27,SET THE TEMPERATURE TO TWENTY ONE DEGREES,SfT jc TfMPRcpk To TWfNTm WcN DgGRmZ
28,SET THE TEMPERATURE TO TWENTY TWO DEGREES,SfT jc TfMPRcpk To TWfNTm To DgGRmZ
29,SET THE TEMPERATURE TO TWENTY THREE DEGREES,SfT jc TfMPRcpk To TWfNTm vRm DgGRmZ
30,SET THE TEMPERATURE TO TWENTY FOUR DEGREES,SfT jc TfMPRcpk To TWfNTm FeR DgGRmZ
31,SET THE TEMPERATURE TO TWENTY FIVE DEGREES,SfT jc TfMPRcpk To TWfNTm FiV DgGRmZ
32,SET THE TEMPERATURE TO TWENTY SIX DEGREES,SfT jc TfMPRcpk To TWfNTm SgKS DgGRmZ
33,LOWEST FAN SPEED,LbcST FaN SPmD
34,MEDIUM FAN SPEED,MmDmcM FaN SPmD
35,HIGHEST FAN SPEED,hicST FaN SPmD
36,AUTO ADJUST THE FAN SPEED,eTb cqcST jc FaN SPmD
37,DECREASE THE FAN SPEED,DgKRmS jc FaN SPmD
38,INCREASE THE FAN SPEED,gNKRmS jc FaN SPmD
39,INCREASE THE TEMPERATURE,gNKRmS jc TfMPRcpk
40,DECREASE THE TEMPERATURE,DgKRmS jc TfMPRcpk
41,COOLING MODE,KoLgl MbD
42,HEATING MODE,hmTgl MbD
43,VENTILATION MODE,VfNTcLdscN MbD
44,DEHUMIDIFY MODE,DmhYoMgDcFi MbD
@@ -0,0 +1,2 @@
# (neural network type)_(model data version)_(lable1_detection windown length_threshold for 90%_threshold for 95%)_(lable2 ...)_...
MN6_v3_chinese_8_0.9_0.90
@@ -0,0 +1,408 @@
<blk> 0
<sos/eos> 0
<unk> 0
▁a -6.00389
▁ai -6.00389
▁an -6.00389
▁ang -6.00389
▁ao -6.00389
▁ba -6.00389
▁bai -6.00389
▁ban -6.00389
▁bang -6.00389
▁bao -6.00389
▁bei -6.00389
▁ben -6.00389
▁beng -6.00389
▁bi -6.00389
▁bian -6.00389
▁biao -6.00389
▁bie -6.00389
▁bin -6.00389
▁bing -6.00389
▁bo -6.00389
▁bu -6.00389
▁ca -6.00389
▁cai -6.00389
▁can -6.00389
▁cang -6.00389
▁cao -6.00389
▁ce -6.00389
▁cen -6.00389
▁ceng -6.00389
▁cha -6.00389
▁chai -6.00389
▁chan -6.00389
▁chang -6.00389
▁chao -6.00389
▁che -6.00389
▁chen -6.00389
▁cheng -6.00389
▁chi -6.00389
▁chong -6.00389
▁chou -6.00389
▁chu -6.00389
▁chuai -6.00389
▁chuan -6.00389
▁chuang -6.00389
▁chui -6.00389
▁chun -6.00389
▁chuo -6.00389
▁ci -6.00389
▁cong -6.00389
▁cou -6.00389
▁cu -6.00389
▁cuan -6.00389
▁cui -6.00389
▁cun -6.00389
▁cuo -6.00389
▁da -6.00389
▁dai -6.00389
▁dan -6.00389
▁dang -6.00389
▁dao -6.00389
▁de -6.00389
▁dei -6.00389
▁deng -6.00389
▁di -6.00389
▁dia -6.00389
▁dian -6.00389
▁diao -6.00389
▁die -6.00389
▁ding -6.00389
▁diu -6.00389
▁dong -6.00389
▁dou -6.00389
▁du -6.00389
▁duan -6.00389
▁dui -6.00389
▁dun -6.00389
▁duo -6.00389
▁e -6.00389
▁ei -6.00389
▁en -6.00389
▁eng -6.00389
▁er -6.00389
▁fa -6.00389
▁fan -6.00389
▁fang -6.00389
▁fei -6.00389
▁fen -6.00389
▁feng -6.00389
▁fo -6.00389
▁fou -6.00389
▁fu -6.00389
▁ga -6.00389
▁gai -6.00389
▁gan -6.00389
▁gang -6.00389
▁gao -6.00389
▁ge -6.00389
▁gei -6.00389
▁gen -6.00389
▁geng -6.00389
▁gong -6.00389
▁gou -6.00389
▁gu -6.00389
▁gua -6.00389
▁guai -6.00389
▁guan -6.00389
▁guang -6.00389
▁gui -6.00389
▁gun -6.00389
▁guo -6.00389
▁ha -6.00389
▁hai -6.00389
▁han -6.00389
▁hang -6.00389
▁hao -6.00389
▁he -6.00389
▁hei -6.00389
▁hen -6.00389
▁heng -6.00389
▁hong -6.00389
▁hou -6.00389
▁hu -6.00389
▁hua -6.00389
▁huai -6.00389
▁huan -6.00389
▁huang -6.00389
▁hui -6.00389
▁hun -6.00389
▁huo -6.00389
▁ji -6.00389
▁jia -6.00389
▁jian -6.00389
▁jiang -6.00389
▁jiao -6.00389
▁jie -6.00389
▁jin -6.00389
▁jing -6.00389
▁jiong -6.00389
▁jiu -6.00389
▁ju -6.00389
▁juan -6.00389
▁jue -6.00389
▁jun -6.00389
▁ka -6.00389
▁kai -6.00389
▁kan -6.00389
▁kang -6.00389
▁kao -6.00389
▁ke -6.00389
▁ken -6.00389
▁keng -6.00389
▁kong -6.00389
▁kou -6.00389
▁ku -6.00389
▁kua -6.00389
▁kuai -6.00389
▁kuan -6.00389
▁kuang -6.00389
▁kui -6.00389
▁kun -6.00389
▁kuo -6.00389
▁la -6.00389
▁lai -6.00389
▁lan -6.00389
▁lang -6.00389
▁lao -6.00389
▁le -6.00389
▁lei -6.00389
▁leng -6.00389
▁li -6.00389
▁lia -6.00389
▁lian -6.00389
▁liang -6.00389
▁liao -6.00389
▁lie -6.00389
▁lin -6.00389
▁ling -6.00389
▁liu -6.00389
▁long -6.00389
▁lou -6.00389
▁lu -6.00389
▁luan -6.00389
▁lun -6.00389
▁luo -6.00389
▁lv -6.00389
▁lve -6.00389
▁ma -6.00389
▁mai -6.00389
▁man -6.00389
▁mang -6.00389
▁mao -6.00389
▁me -6.00389
▁mei -6.00389
▁men -6.00389
▁meng -6.00389
▁mi -6.00389
▁mian -6.00389
▁miao -6.00389
▁mie -6.00389
▁min -6.00389
▁ming -6.00389
▁miu -6.00389
▁mo -6.00389
▁mou -6.00389
▁mu -6.00389
▁n -6.00389
▁na -6.00389
▁nai -6.00389
▁nan -6.00389
▁nang -6.00389
▁nao -6.00389
▁ne -6.00389
▁nei -6.00389
▁nen -6.00389
▁neng -6.00389
▁ni -6.00389
▁nian -6.00389
▁niang -6.00389
▁niao -6.00389
▁nie -6.00389
▁nin -6.00389
▁ning -6.00389
▁niu -6.00389
▁nong -6.00389
▁nou -6.00389
▁nu -6.00389
▁nuan -6.00389
▁nuo -6.00389
▁nv -6.00389
▁nve -6.00389
▁o -6.00389
▁ou -6.00389
▁pa -6.00389
▁pai -6.00389
▁pan -6.00389
▁pang -6.00389
▁pao -6.00389
▁pei -6.00389
▁pen -6.00389
▁peng -6.00389
▁pi -6.00389
▁pian -6.00389
▁piao -6.00389
▁pie -6.00389
▁pin -6.00389
▁ping -6.00389
▁po -6.00389
▁pou -6.00389
▁pu -6.00389
▁qi -6.00389
▁qia -6.00389
▁qian -6.00389
▁qiang -6.00389
▁qiao -6.00389
▁qie -6.00389
▁qin -6.00389
▁qing -6.00389
▁qiong -6.00389
▁qiu -6.00389
▁qu -6.00389
▁quan -6.00389
▁que -6.00389
▁qun -6.00389
▁ran -6.00389
▁rang -6.00389
▁rao -6.00389
▁re -6.00389
▁ren -6.00389
▁reng -6.00389
▁ri -6.00389
▁rong -6.00389
▁rou -6.00389
▁ru -6.00389
▁ruan -6.00389
▁rui -6.00389
▁run -6.00389
▁ruo -6.00389
▁sa -6.00389
▁sai -6.00389
▁san -6.00389
▁sang -6.00389
▁sao -6.00389
▁se -6.00389
▁sen -6.00389
▁seng -6.00389
▁sha -6.00389
▁shai -6.00389
▁shan -6.00389
▁shang -6.00389
▁shao -6.00389
▁she -6.00389
▁shei -6.00389
▁shen -6.00389
▁sheng -6.00389
▁shi -6.00389
▁shou -6.00389
▁shu -6.00389
▁shua -6.00389
▁shuai -6.00389
▁shuan -6.00389
▁shuang -6.00389
▁shui -6.00389
▁shun -6.00389
▁shuo -6.00389
▁si -6.00389
▁song -6.00389
▁sou -6.00389
▁su -6.00389
▁suan -6.00389
▁sui -6.00389
▁sun -6.00389
▁suo -6.00389
▁ta -6.00389
▁tai -6.00389
▁tan -6.00389
▁tang -6.00389
▁tao -6.00389
▁te -6.00389
▁teng -6.00389
▁ti -6.00389
▁tian -6.00389
▁tiao -6.00389
▁tie -6.00389
▁ting -6.00389
▁tong -6.00389
▁tou -6.00389
▁tu -6.00389
▁tuan -6.00389
▁tui -6.00389
▁tun -6.00389
▁tuo -6.00389
▁wa -6.00389
▁wai -6.00389
▁wan -6.00389
▁wang -6.00389
▁wei -6.00389
▁wen -6.00389
▁weng -6.00389
▁wo -6.00389
▁wu -6.00389
▁xi -6.00389
▁xia -6.00389
▁xian -6.00389
▁xiang -6.00389
▁xiao -6.00389
▁xie -6.00389
▁xin -6.00389
▁xing -6.00389
▁xiong -6.00389
▁xiu -6.00389
▁xu -6.00389
▁xuan -6.00389
▁xue -6.00389
▁xun -6.00389
▁ya -6.00389
▁yan -6.00389
▁yang -6.00389
▁yao -6.00389
▁ye -6.00389
▁yi -6.00389
▁yin -6.00389
▁ying -6.00389
▁yo -6.00389
▁yong -6.00389
▁you -6.00389
▁yu -6.00389
▁yuan -6.00389
▁yue -6.00389
▁yun -6.00389
▁za -6.00389
▁zai -6.00389
▁zan -6.00389
▁zang -6.00389
▁zao -6.00389
▁ze -6.00389
▁zei -6.00389
▁zen -6.00389
▁zeng -6.00389
▁zha -6.00389
▁zhai -6.00389
▁zhan -6.00389
▁zhang -6.00389
▁zhao -6.00389
▁zhe -6.00389
▁zhen -6.00389
▁zheng -6.00389
▁zhi -6.00389
▁zhong -6.00389
▁zhou -6.00389
▁zhu -6.00389
▁zhua -6.00389
▁zhuai -6.00389
▁zhuan -6.00389
▁zhuang -6.00389
▁zhui -6.00389
▁zhun -6.00389
▁zhuo -6.00389
▁zi -6.00389
▁zong -6.00389
▁zou -6.00389
▁zu -6.00389
▁zuan -6.00389
▁zui -6.00389
▁zun -6.00389
▁zuo -6.00389
@@ -0,0 +1,2 @@
# (neural network type)_(model data version)_(lable1_detection windown length_threshold for 90%_threshold for 95%)_(lable2 ...)_...
MN6_v11_english_8_0.9_0.90
@@ -0,0 +1,496 @@
<blk> 0
<sos/eos> 0
<unk> 0
S -3.07889
▁THE -3.40423
T -3.88725
▁A -3.92112
N -4.09564
D -4.11012
ED -4.1357
E -4.14799
▁OF -4.26336
Y -4.29626
▁AND -4.33585
▁S -4.3654
▁IN -4.3757
R -4.40673
▁TO -4.4224
▁ -4.44313
A -4.53295
ING -4.609
P -4.6255
O -4.64585
M -4.70827
▁HE -4.88611
ER -4.8978
C -4.91954
G -4.92569
I -4.94376
L -4.99607
▁WAS -5.03879
RE -5.04049
▁IS -5.04139
B -5.05608
U -5.0919
IN -5.09797
AL -5.11326
F -5.14736
▁RE -5.17026
▁C -5.18734
W -5.20708
LE -5.2265
AR -5.22738
LY -5.25158
K -5.26829
▁E -5.28591
▁IT -5.29688
▁I -5.30127
▁FOR -5.32154
▁BE -5.32403
OR -5.34223
▁F -5.37851
RI -5.43106
UR -5.45431
TER -5.45866
ES -5.45872
LL -5.48135
TH -5.52073
▁HIS -5.55833
CE -5.56702
▁THAT -5.57592
AN -5.59288
▁W -5.6041
VE -5.60931
ST -5.62437
ENT -5.65017
H -5.65339
▁WITH -5.6706
▁DE -5.68992
▁AS -5.69156
ON -5.72969
▁G -5.74921
EN -5.78306
▁ON -5.78979
SE -5.79199
▁T -5.79727
CH -5.81344
IT -5.81754
▁ME -5.82634
ND -5.8311
IC -5.85196
IL -5.90067
LI -5.93408
▁ARE -5.93654
▁AT -5.9387
LA -5.94726
NE -5.95697
TE -5.96039
▁BY -5.96685
▁SO -5.9722
ATION -5.98634
▁YOU -5.9876
NG -5.99006
ME -5.99601
RO -6.02152
▁CON -6.02394
▁HER -6.0293
▁LA -6.03015
▁THIS -6.04492
▁DO -6.07943
▁B -6.08512
▁NOT -6.08671
▁SHE -6.09068
EL -6.1097
▁HO -6.11901
▁AN -6.12235
▁MA -6.12322
▁LE -6.12454
CK -6.1247
' -6.12699
▁HAD -6.13045
RA -6.13689
AD -6.14076
▁O -6.14214
▁P -6.20087
IR -6.21724
LO -6.22267
▁MO -6.22307
ION -6.22672
▁CO -6.23029
▁CA -6.23812
▁SU -6.26152
▁SE -6.26695
▁BUT -6.27228
▁FROM -6.27467
▁EX -6.28074
▁HA -6.28098
VER -6.28125
▁PO -6.28914
▁SA -6.2916
▁WERE -6.30425
▁NO -6.30776
ET -6.31275
▁BO -6.31689
▁PRO -6.32041
CI -6.32454
▁FA -6.32788
▁RO -6.32906
V -6.34332
▁OR -6.36826
GE -6.37052
▁LI -6.37484
▁WE -6.37675
MENT -6.37907
VI -6.38565
▁HAVE -6.39316
US -6.40326
▁BA -6.42561
▁LO -6.42993
THER -6.43168
▁ALSO -6.47489
▁ALL -6.50533
X -6.50653
▁K -6.52042
Z -6.52984
PE -6.53095
IVE -6.53508
▁ONE -6.53996
▁WA -6.54638
KE -6.55093
▁RA -6.55191
UL -6.55216
ECT -6.55335
▁UN -6.56427
PP -6.56492
ANT -6.56898
CO -6.57329
TED -6.57444
▁GO -6.58303
▁THEY -6.59422
▁HIM -6.59522
TI -6.60893
HO -6.61054
ITY -6.61409
▁PA -6.61551
▁TE -6.6184
IS -6.62109
▁HAS -6.63168
AT -6.6365
TA -6.63933
LU -6.64536
▁COM -6.64737
MP -6.64779
IES -6.64855
▁NE -6.6488
RY -6.65295
▁SP -6.66979
▁THERE -6.68432
▁MY -6.68952
▁US -6.69133
AM -6.70139
UN -6.71227
LD -6.71897
DE -6.72339
ATE -6.72648
IST -6.72921
IGHT -6.73344
▁WHICH -6.73445
UT -6.74595
TION -6.7483
▁PRE -6.75246
▁STA -6.75454
MO -6.77175
QU -6.77352
EST -6.77941
▁WHO -6.78426
OM -6.79011
▁EN -6.79139
RU -6.7931
UND -6.8019
▁DI -6.80283
▁MI -6.80652
▁CAN -6.8222
▁DA -6.83626
▁THEIR -6.83991
▁MAN -6.85115
FF -6.85206
IG -6.85213
ERS -6.85821
▁SOME -6.86373
J -6.87215
▁SAID -6.8771
IDE -6.88655
ENCE -6.88893
▁BEEN -6.88897
UGH -6.89375
▁CHA -6.89704
OL -6.90369
AS -6.90373
▁FE -6.90451
ALLY -6.90772
▁PER -6.91705
▁TRA -6.91809
▁DIS -6.92071
ISH -6.92646
▁OUT -6.93475
TU -6.94591
▁TWO -6.95006
TEN -6.95389
ANCE -6.95667
ABLE -6.95742
▁FI -6.95763
ATED -6.96277
MAN -6.96672
ARD -6.97351
IM -6.97412
▁COMP -6.97531
TO -6.97737
▁UP -6.98066
▁DR -6.98419
▁WHEN -6.99258
ID -6.99533
▁VI -6.99727
▁MAR -7.0055
MI -7.00807
▁OTHER -7.00956
UM -7.01895
ACH -7.02126
▁TIME -7.02406
VO -7.03375
AGE -7.03636
▁WILL -7.03689
LES -7.0385
SON -7.04028
▁WOULD -7.04116
▁AFTER -7.04746
DI -7.05154
HE -7.05471
CTION -7.06388
DER -7.07653
▁SEE -7.08034
TOR -7.08927
TING -7.09141
IA -7.09335
IAN -7.09403
▁RI -7.10291
▁KNOW -7.10479
▁GA -7.1099
▁WI -7.11445
MA -7.11769
NO -7.12181
LOW -7.12665
▁HU -7.13031
▁WHAT -7.13396
▁AL -7.13463
LAND -7.14441
TURE -7.15932
CA -7.17135
INE -7.17506
▁PRI -7.17772
SH -7.20164
▁INTO -7.20364
▁BU -7.21223
▁MORE -7.21481
▁VA -7.21647
PORT -7.2194
▁PART -7.23217
▁FIRST -7.23582
OUS -7.23769
TRA -7.24264
▁ITS -7.2429
HA -7.24538
ITE -7.25177
▁IF -7.25488
▁NEW -7.25627
ICAL -7.26377
TIC -7.26381
PER -7.26693
▁CAR -7.26944
▁RU -7.27772
ITION -7.28408
FUL -7.29445
BO -7.29669
▁NAME -7.30452
TON -7.30697
▁OVER -7.31507
TRO -7.32087
▁GRA -7.3217
▁BRO -7.32641
ACT -7.33136
▁NOW -7.34355
AST -7.35111
CU -7.35545
▁SHA -7.35997
▁WORK -7.36627
▁YEAR -7.36661
VEN -7.36903
▁NA -7.37128
WAY -7.38026
▁ONLY -7.38736
BER -7.38879
LF -7.4099
ARY -7.41035
▁LIKE -7.42306
▁COULD -7.42436
▁VERY -7.42967
▁ANY -7.43986
▁THESE -7.44827
▁PLAY -7.45178
▁MOST -7.45687
WARD -7.45972
▁TA -7.46343
▁THAN -7.46455
BA -7.4685
▁PAR -7.47386
▁COUNT -7.47686
▁EVEN -7.48424
VA -7.4928
▁DID -7.4948
▁DAY -7.49797
▁PU -7.51069
▁MU -7.51234
ROW -7.5153
▁ABOUT -7.516
▁MANY -7.51664
▁WELL -7.53807
▁JO -7.54001
▁UNDER -7.54177
▁ACC -7.55773
▁PE -7.56034
▁AGAIN -7.5605
▁SCHOOL -7.56228
▁MAY -7.5694
▁PI -7.57678
▁MADE -7.57897
▁DU -7.59393
RESS -7.59781
▁THREE -7.60489
▁GREAT -7.60498
▁YOUR -7.60601
▁MIN -7.60861
VING -7.61683
IOUS -7.61753
▁BI -7.62307
▁LITTLE -7.62497
▁COL -7.62618
▁CHI -7.63267
▁THOUGH -7.63364
▁LONG -7.63534
▁JA -7.63895
▁THROUGH -7.64648
▁HIGH -7.64926
▁LOOK -7.6521
FORM -7.65936
▁FIN -7.66407
▁KI -7.6669
▁HI -7.67024
NESS -7.68112
▁HAND -7.68612
▁IMP -7.68653
▁OLD -7.7006
SHIP -7.70413
▁DOWN -7.71157
▁BRI -7.71511
▁BEFORE -7.71936
▁SUCH -7.72039
▁HOWEVER -7.728
▁OWN -7.75294
▁TAKE -7.76308
▁GOOD -7.76874
▁MON -7.76942
▁FOUND -7.77054
▁GU -7.78223
▁EVERY -7.78939
▁STATE -7.7907
▁WHERE -7.79278
CTOR -7.79962
▁NEVER -7.80492
IZE -7.80764
▁TOWN -7.81842
▁BACK -7.82046
▁SHOULD -7.8246
▁UPON -7.83734
▁HOUSE -7.84511
IV -7.85541
▁PH -7.86099
▁PLACE -7.87672
▁MISS -7.88612
▁CAME -7.8866
▁JU -7.88931
▁QUI -7.90935
▁MUCH -7.91921
IBLE -7.93599
▁JUST -7.93659
▁FOUR -7.94758
▁PEOPLE -7.94857
▁FOLLOW -7.94871
▁MUST -7.95395
▁LIFE -7.96048
▁LARGE -7.96278
▁MAKE -7.9675
▁INCLUDE -7.96818
▁NORTH -7.97504
▁DURING -7.98067
▁SOUTH -7.99293
▁STILL -7.9973
▁TI -7.99869
▁SEVERAL -8.00559
ATIVE -8.0089
▁PASS -8.03179
▁JE -8.0351
▁CALLED -8.04403
▁THING -8.05018
▁SHOW -8.05214
▁THI -8.0527
▁WHILE -8.07217
▁NI -8.08629
▁WORLD -8.08951
▁THINK -8.09877
QUI -8.11332
▁BECAME -8.11496
▁MISTER -8.11977
▁HIMSELF -8.13559
▁BORN -8.13768
▁APPEAR -8.14342
▁ANOTHER -8.15291
TTLE -8.1567
▁TURN -8.1729
▁OPEN -8.18109
▁SMALL -8.19434
▁WITHOUT -8.21613
▁THOSE -8.24015
▁MUSIC -8.24442
▁SECOND -8.25535
▁GENERAL -8.25552
▁WORD -8.25754
▁BETWEEN -8.26687
▁RIGHT -8.27526
▁REMAIN -8.27935
▁TOOK -8.28184
▁DIRECT -8.28644
▁MIGHT -8.30341
▁NIGHT -8.31281
▁RETURN -8.315
▁BOOK -8.32654
▁MEMBER -8.32963
WOOD -8.33563
▁FRIEND -8.33879
▁LOCATED -8.3518
▁CHILDREN -8.38972
▁FILM -8.39793
▁OPERA -8.40359
▁CONSIDER -8.40997
▁SIX -8.41371
▁NUMBER -8.42239
▁QUA -8.42348
▁GROUP -8.45124
▁CLOSE -8.45242
▁FAMILY -8.45315
▁PUBLIC -8.46476
▁POWER -8.46486
▁BLACK -8.46615
▁NOTHING -8.46827
▁UNIVERSITY -8.48681
▁JOHN -8.49126
Q -10.4251
@@ -0,0 +1,2 @@
# (neural network type)_(model data version)_(lable1_detection windown length_threshold for 90%_threshold for 95%)_(lable2 ...)_...
MN7_v1_chinese_8_0.9_0.90
@@ -0,0 +1,408 @@
<blk> 0
<sos/eos> 0
<unk> 0
▁a -6.00389
▁ai -6.00389
▁an -6.00389
▁ang -6.00389
▁ao -6.00389
▁ba -6.00389
▁bai -6.00389
▁ban -6.00389
▁bang -6.00389
▁bao -6.00389
▁bei -6.00389
▁ben -6.00389
▁beng -6.00389
▁bi -6.00389
▁bian -6.00389
▁biao -6.00389
▁bie -6.00389
▁bin -6.00389
▁bing -6.00389
▁bo -6.00389
▁bu -6.00389
▁ca -6.00389
▁cai -6.00389
▁can -6.00389
▁cang -6.00389
▁cao -6.00389
▁ce -6.00389
▁cen -6.00389
▁ceng -6.00389
▁cha -6.00389
▁chai -6.00389
▁chan -6.00389
▁chang -6.00389
▁chao -6.00389
▁che -6.00389
▁chen -6.00389
▁cheng -6.00389
▁chi -6.00389
▁chong -6.00389
▁chou -6.00389
▁chu -6.00389
▁chuai -6.00389
▁chuan -6.00389
▁chuang -6.00389
▁chui -6.00389
▁chun -6.00389
▁chuo -6.00389
▁ci -6.00389
▁cong -6.00389
▁cou -6.00389
▁cu -6.00389
▁cuan -6.00389
▁cui -6.00389
▁cun -6.00389
▁cuo -6.00389
▁da -6.00389
▁dai -6.00389
▁dan -6.00389
▁dang -6.00389
▁dao -6.00389
▁de -6.00389
▁dei -6.00389
▁deng -6.00389
▁di -6.00389
▁dia -6.00389
▁dian -6.00389
▁diao -6.00389
▁die -6.00389
▁ding -6.00389
▁diu -6.00389
▁dong -6.00389
▁dou -6.00389
▁du -6.00389
▁duan -6.00389
▁dui -6.00389
▁dun -6.00389
▁duo -6.00389
▁e -6.00389
▁ei -6.00389
▁en -6.00389
▁eng -6.00389
▁er -6.00389
▁fa -6.00389
▁fan -6.00389
▁fang -6.00389
▁fei -6.00389
▁fen -6.00389
▁feng -6.00389
▁fo -6.00389
▁fou -6.00389
▁fu -6.00389
▁ga -6.00389
▁gai -6.00389
▁gan -6.00389
▁gang -6.00389
▁gao -6.00389
▁ge -6.00389
▁gei -6.00389
▁gen -6.00389
▁geng -6.00389
▁gong -6.00389
▁gou -6.00389
▁gu -6.00389
▁gua -6.00389
▁guai -6.00389
▁guan -6.00389
▁guang -6.00389
▁gui -6.00389
▁gun -6.00389
▁guo -6.00389
▁ha -6.00389
▁hai -6.00389
▁han -6.00389
▁hang -6.00389
▁hao -6.00389
▁he -6.00389
▁hei -6.00389
▁hen -6.00389
▁heng -6.00389
▁hong -6.00389
▁hou -6.00389
▁hu -6.00389
▁hua -6.00389
▁huai -6.00389
▁huan -6.00389
▁huang -6.00389
▁hui -6.00389
▁hun -6.00389
▁huo -6.00389
▁ji -6.00389
▁jia -6.00389
▁jian -6.00389
▁jiang -6.00389
▁jiao -6.00389
▁jie -6.00389
▁jin -6.00389
▁jing -6.00389
▁jiong -6.00389
▁jiu -6.00389
▁ju -6.00389
▁juan -6.00389
▁jue -6.00389
▁jun -6.00389
▁ka -6.00389
▁kai -6.00389
▁kan -6.00389
▁kang -6.00389
▁kao -6.00389
▁ke -6.00389
▁ken -6.00389
▁keng -6.00389
▁kong -6.00389
▁kou -6.00389
▁ku -6.00389
▁kua -6.00389
▁kuai -6.00389
▁kuan -6.00389
▁kuang -6.00389
▁kui -6.00389
▁kun -6.00389
▁kuo -6.00389
▁la -6.00389
▁lai -6.00389
▁lan -6.00389
▁lang -6.00389
▁lao -6.00389
▁le -6.00389
▁lei -6.00389
▁leng -6.00389
▁li -6.00389
▁lia -6.00389
▁lian -6.00389
▁liang -6.00389
▁liao -6.00389
▁lie -6.00389
▁lin -6.00389
▁ling -6.00389
▁liu -6.00389
▁long -6.00389
▁lou -6.00389
▁lu -6.00389
▁luan -6.00389
▁lun -6.00389
▁luo -6.00389
▁lv -6.00389
▁lve -6.00389
▁ma -6.00389
▁mai -6.00389
▁man -6.00389
▁mang -6.00389
▁mao -6.00389
▁me -6.00389
▁mei -6.00389
▁men -6.00389
▁meng -6.00389
▁mi -6.00389
▁mian -6.00389
▁miao -6.00389
▁mie -6.00389
▁min -6.00389
▁ming -6.00389
▁miu -6.00389
▁mo -6.00389
▁mou -6.00389
▁mu -6.00389
▁n -6.00389
▁na -6.00389
▁nai -6.00389
▁nan -6.00389
▁nang -6.00389
▁nao -6.00389
▁ne -6.00389
▁nei -6.00389
▁nen -6.00389
▁neng -6.00389
▁ni -6.00389
▁nian -6.00389
▁niang -6.00389
▁niao -6.00389
▁nie -6.00389
▁nin -6.00389
▁ning -6.00389
▁niu -6.00389
▁nong -6.00389
▁nou -6.00389
▁nu -6.00389
▁nuan -6.00389
▁nuo -6.00389
▁nv -6.00389
▁nve -6.00389
▁o -6.00389
▁ou -6.00389
▁pa -6.00389
▁pai -6.00389
▁pan -6.00389
▁pang -6.00389
▁pao -6.00389
▁pei -6.00389
▁pen -6.00389
▁peng -6.00389
▁pi -6.00389
▁pian -6.00389
▁piao -6.00389
▁pie -6.00389
▁pin -6.00389
▁ping -6.00389
▁po -6.00389
▁pou -6.00389
▁pu -6.00389
▁qi -6.00389
▁qia -6.00389
▁qian -6.00389
▁qiang -6.00389
▁qiao -6.00389
▁qie -6.00389
▁qin -6.00389
▁qing -6.00389
▁qiong -6.00389
▁qiu -6.00389
▁qu -6.00389
▁quan -6.00389
▁que -6.00389
▁qun -6.00389
▁ran -6.00389
▁rang -6.00389
▁rao -6.00389
▁re -6.00389
▁ren -6.00389
▁reng -6.00389
▁ri -6.00389
▁rong -6.00389
▁rou -6.00389
▁ru -6.00389
▁ruan -6.00389
▁rui -6.00389
▁run -6.00389
▁ruo -6.00389
▁sa -6.00389
▁sai -6.00389
▁san -6.00389
▁sang -6.00389
▁sao -6.00389
▁se -6.00389
▁sen -6.00389
▁seng -6.00389
▁sha -6.00389
▁shai -6.00389
▁shan -6.00389
▁shang -6.00389
▁shao -6.00389
▁she -6.00389
▁shei -6.00389
▁shen -6.00389
▁sheng -6.00389
▁shi -6.00389
▁shou -6.00389
▁shu -6.00389
▁shua -6.00389
▁shuai -6.00389
▁shuan -6.00389
▁shuang -6.00389
▁shui -6.00389
▁shun -6.00389
▁shuo -6.00389
▁si -6.00389
▁song -6.00389
▁sou -6.00389
▁su -6.00389
▁suan -6.00389
▁sui -6.00389
▁sun -6.00389
▁suo -6.00389
▁ta -6.00389
▁tai -6.00389
▁tan -6.00389
▁tang -6.00389
▁tao -6.00389
▁te -6.00389
▁teng -6.00389
▁ti -6.00389
▁tian -6.00389
▁tiao -6.00389
▁tie -6.00389
▁ting -6.00389
▁tong -6.00389
▁tou -6.00389
▁tu -6.00389
▁tuan -6.00389
▁tui -6.00389
▁tun -6.00389
▁tuo -6.00389
▁wa -6.00389
▁wai -6.00389
▁wan -6.00389
▁wang -6.00389
▁wei -6.00389
▁wen -6.00389
▁weng -6.00389
▁wo -6.00389
▁wu -6.00389
▁xi -6.00389
▁xia -6.00389
▁xian -6.00389
▁xiang -6.00389
▁xiao -6.00389
▁xie -6.00389
▁xin -6.00389
▁xing -6.00389
▁xiong -6.00389
▁xiu -6.00389
▁xu -6.00389
▁xuan -6.00389
▁xue -6.00389
▁xun -6.00389
▁ya -6.00389
▁yan -6.00389
▁yang -6.00389
▁yao -6.00389
▁ye -6.00389
▁yi -6.00389
▁yin -6.00389
▁ying -6.00389
▁yo -6.00389
▁yong -6.00389
▁you -6.00389
▁yu -6.00389
▁yuan -6.00389
▁yue -6.00389
▁yun -6.00389
▁za -6.00389
▁zai -6.00389
▁zan -6.00389
▁zang -6.00389
▁zao -6.00389
▁ze -6.00389
▁zei -6.00389
▁zen -6.00389
▁zeng -6.00389
▁zha -6.00389
▁zhai -6.00389
▁zhan -6.00389
▁zhang -6.00389
▁zhao -6.00389
▁zhe -6.00389
▁zhen -6.00389
▁zheng -6.00389
▁zhi -6.00389
▁zhong -6.00389
▁zhou -6.00389
▁zhu -6.00389
▁zhua -6.00389
▁zhuai -6.00389
▁zhuan -6.00389
▁zhuang -6.00389
▁zhui -6.00389
▁zhun -6.00389
▁zhuo -6.00389
▁zi -6.00389
▁zong -6.00389
▁zou -6.00389
▁zu -6.00389
▁zuan -6.00389
▁zui -6.00389
▁zun -6.00389
▁zuo -6.00389
@@ -0,0 +1,2 @@
# (neural network type)_(model data version)_(lable1_detection windown length_threshold for 90%_threshold for 95%)_(lable2 ...)_...
MN7_v2_english_8_0.9_0.90
@@ -0,0 +1,496 @@
<blk> 0
<sos/eos> 0
<unk> 0
▁jc -3.50373
D -3.5684
Z -3.78123
▁ -3.79998
S -3.83618
T -3.87046
L -4.10747
k -4.11347
m -4.19593
N -4.22335
▁c -4.22589
▁cND -4.27701
▁To -4.29056
▁cV -4.31859
gl -4.33672
▁gN -4.37203
▁S -4.4714
cN -4.49621
M -4.54434
K -4.63236
cL -4.67913
▁K -4.71478
▁F -4.74325
d -4.82918
▁i -4.85698
R -4.86703
P -4.92216
▁WnZ -5.00484
V -5.02262
b -5.03227
▁gZ -5.05364
Lm -5.10135
F -5.12035
▁P -5.12086
▁hm -5.12715
c -5.13687
▁h -5.15949
▁gT -5.18356
ST -5.19187
q -5.21425
▁Yo -5.22842
cS -5.22968
▁FeR -5.23966
o -5.26657
▁T -5.27106
i -5.2919
▁jaT -5.31665
B -5.3544
a -5.35965
eR -5.38129
▁B -5.38271
cT -5.43331
G -5.47756
gK -5.5056
cD -5.50664
▁hgZ -5.53485
nR -5.53996
W -5.5877
▁Wgj -5.60166
p -5.60441
cM -5.61738
cNT -5.62181
▁G -5.63642
▁aZ -5.71277
fR -5.71746
▁nR -5.71804
▁ST -5.72643
▁TnM -5.74877
v -5.77125
Tk -5.77647
▁Bm -5.78607
▁nN -5.81834
▁jfR -5.85378
f -5.85578
▁hk -5.90336
e -5.9078
▁Nb -5.90836
Rm -5.91096
gL -5.91741
▁jgS -5.91979
▁Dg -5.9272
▁Bi -5.93789
▁Rg -5.95634
▁haD -5.96296
▁aT -5.96296
▁s -5.97546
n -5.98883
▁NnT -6.00763
gN -6.01002
▁Wk -6.01178
dscN -6.01329
▁V -6.01564
fL -6.02194
▁Mi -6.02826
cZ -6.04709
Yo -6.04782
▁haV -6.05726
s -6.07188
▁a -6.07615
▁sm -6.08078
cK -6.09
▁aN -6.09715
▁WcN -6.10703
gT -6.11357
▁BcT -6.15304
aN -6.16532
▁Mm -6.16782
▁fS -6.1714
gR -6.18534
scN -6.18622
▁jd -6.1994
▁Wm -6.24759
u -6.25542
t -6.25927
▁FRcM -6.27249
kZ -6.27958
dT -6.28288
▁eL -6.29125
▁Rm -6.29208
gD -6.29997
▁cP -6.3241
▁Tm -6.32699
g -6.34756
gV -6.35953
gZ -6.36227
▁eR -6.37034
McN -6.3715
dN -6.37315
kD -6.37589
▁KcM -6.38682
▁Sm -6.38905
▁Do -6.3974
▁hgM -6.40994
▁BR -6.42479
▁Rf -6.42856
cNS -6.43498
▁SP -6.44143
iN -6.44191
▁GR -6.45766
cB -6.46027
▁p -6.46846
gS -6.47832
cST -6.48588
▁Sb -6.49067
gST -6.49181
fNT -6.49573
iT -6.49735
▁Wi -6.50855
▁WfN -6.52316
Vk -6.52443
gs -6.52706
▁PR -6.52774
▁v -6.53108
▁f -6.56235
▁KaN -6.5666
▁Li -6.57229
iD -6.58316
▁Kn -6.5832
TcD -6.58484
w -6.59819
▁haZ -6.60379
cP -6.60889
▁WcT -6.61385
▁KR -6.62303
fN -6.62737
aND -6.63035
▁Wgp -6.63954
▁WwD -6.65084
▁DgS -6.65373
cF -6.65712
mZ -6.66699
▁SfD -6.67477
pk -6.69479
TS -6.695
fKT -6.70052
McNT -6.70319
Dm -6.71245
▁eLSb -6.71705
eL -6.71759
▁BgN -6.72228
▁tT -6.73979
▁MeR -6.74077
aL -6.7427
▁ho -6.75134
jk -6.76713
▁WgL -6.77334
cBcL -6.77345
▁Rc -6.77421
aK -6.77939
cTm -6.78357
nL -6.78623
▁KcN -6.79348
fT -6.79532
▁ScM -6.80766
SP -6.8082
cq -6.80856
fRm -6.81043
nN -6.81225
▁DR -6.81469
▁Md -6.81943
▁gK -6.82419
▁Sd -6.83334
▁MaN -6.83827
▁Ld -6.84033
h -6.84414
▁Gb -6.84487
▁Lf -6.8514
fND -6.85243
▁PLd -6.85302
▁gF -6.85796
▁TiM -6.86458
▁Rd -6.86507
▁Mg -6.87118
▁Wg -6.87192
fS -6.87345
aM -6.87513
▁ht -6.87937
▁Dd -6.88576
▁Mc -6.89067
▁No -6.90141
TcN -6.90439
▁DgD -6.9107
▁Pk -6.91445
nT -6.91539
l -6.91848
mN -6.91959
▁VfRm -6.92163
▁Ma -6.92804
bN -6.94291
nP -6.94333
cG -6.96256
KS -6.96275
fST -6.96416
tND -6.96664
▁Df -6.9701
▁jfM -6.97647
▁LiK -6.99176
▁Wd -6.9979
tN -7.00168
▁Y -7.00423
▁m -7.00454
gM -7.00971
▁fN -7.01195
cV -7.01324
▁gTS -7.01639
aT -7.02274
▁eF -7.02734
▁cjk -7.03753
gscN -7.04204
bLD -7.0527
Pk -7.0586
▁PRn -7.06185
▁jfN -7.0651
▁Mf -7.07005
aKT -7.07351
▁SK -7.08235
▁YeR -7.08512
▁STR -7.08684
▁aFTk -7.08805
bZ -7.0882
Rf -7.09352
▁Nt -7.10726
Bk -7.10801
cLm -7.10932
aP -7.12006
iZ -7.12318
▁gNTo -7.12848
▁KnN -7.13285
Yc -7.13939
Tm -7.13985
Fk -7.1449
▁Pa -7.1512
▁KW -7.15296
BcL -7.16211
▁Bf -7.16276
▁Rb -7.1675
▁KwD -7.17276
▁cBtT -7.17381
▁MfRm -7.17527
Y -7.17661
Li -7.184
gq -7.18822
TRc -7.19102
Rd -7.21693
▁BL -7.21734
▁Sk -7.21835
▁bVk -7.22379
▁PnRT -7.23661
wR -7.23753
▁fM -7.2383
▁Dc -7.2417
fP -7.2455
gP -7.25885
Rb -7.2592
Lb -7.26108
fK -7.26502
▁k -7.27224
▁fNm -7.27675
▁LwK -7.28554
▁jmZ -7.29014
▁bNLm -7.29574
▁tk -7.29717
▁FkST -7.29888
▁WfL -7.29891
fM -7.30488
▁Bn -7.30592
KW -7.3139
Sm -7.32676
gF -7.33304
mc -7.34274
▁WnNT -7.34378
▁FR -7.34529
▁WkK -7.34753
▁n -7.34886
bK -7.35356
nK -7.35381
▁WfR -7.36005
j -7.37283
▁hmR -7.37391
qk -7.39067
▁Lm -7.39275
PeRT -7.39586
▁Ro -7.39659
▁TdK -7.40401
▁Le -7.4074
YcL -7.41016
▁jaN -7.41385
▁Ra -7.41443
▁cGfN -7.41565
▁vglK -7.42018
▁Se -7.42935
▁YgR -7.43003
▁NdM -7.43696
▁Si -7.44106
▁hi -7.44334
▁GwD -7.44411
▁LgTcL -7.44823
LcND -7.45773
▁MdD -7.46048
▁KeR -7.46645
▁GRdT -7.47876
▁Ba -7.48457
▁NfVk -7.50238
VcL -7.50301
▁Lel -7.50448
rcN -7.50475
dTcD -7.50866
▁qcST -7.51138
▁La -7.51687
FcL -7.51989
▁Pn -7.52134
lK -7.53701
▁MbST -7.54063
▁Wf -7.54358
▁MdK -7.54487
▁SkV -7.54717
▁BgG -7.55028
▁Dn -7.55184
▁cN -7.55296
▁MfNm -7.5575
▁DtN -7.55772
▁MnR -7.56086
▁cS -7.56592
▁swD -7.57011
▁RiT -7.57032
▁BgL -7.57481
▁BaK -7.57536
▁jb -7.57705
fNS -7.57997
▁NeR -7.58034
▁GfT -7.58184
▁gM -7.58286
▁BgFeR -7.58361
▁PRf -7.58469
▁vRo -7.58732
▁vRm -7.58886
▁Dm -7.5917
▁TRa -7.59345
▁haND -7.59921
▁MfN -7.6038
▁PRc -7.60597
▁MgS -7.61131
▁Lb -7.61746
▁Mn -7.63249
▁bLD -7.63333
▁Mcp -7.63656
▁Scp -7.64435
gKcL -7.64576
▁Di -7.64679
gG -7.65583
alK -7.661
▁DnN -7.67024
▁TfL -7.67744
▁GgV -7.68746
YwR -7.70829
▁SKoL -7.71139
▁Mb -7.71499
▁cPnN -7.72335
▁WeR -7.72428
▁LfT -7.72701
▁bN -7.76208
▁KdM -7.77118
▁McST -7.7726
▁hbM -7.78221
▁FtND -7.79333
▁gMP -7.80415
▁veT -7.81381
▁gGZ -7.81882
▁STgL -7.82014
fKscN -7.82577
▁Wn -7.83255
▁Rn -7.83329
▁PmPcL -7.85228
r -7.85566
lG -7.86083
▁Nd -7.8709
▁htfVk -7.88052
▁TRi -7.88154
▁LcV -7.88601
▁hgMSfLF -7.90396
▁LaST -7.9066
▁cWd -7.9196
▁Bbv -7.93391
▁hbL -7.93782
▁MgSTk -7.9585
▁Nn -7.9685
▁FmL -7.97302
▁NmD -7.97977
▁fKS -7.9861
▁Nf -7.9904
▁TkN -7.99385
sgP -7.99594
▁FnLb -7.99942
▁hfLP -8.00141
▁NgR -8.02016
▁mVgN -8.02157
▁gNKLoD -8.02707
▁Ycl -8.04963
▁SgTm -8.05047
▁MoV -8.06119
▁qf -8.06562
▁WgvtT -8.06755
▁fVkm -8.07061
▁Ln -8.07269
▁Lo -8.08834
▁KtNT -8.09315
▁cNcjk -8.09509
▁LnRq -8.09678
▁bPcN -8.09941
▁Fnjk -8.09952
▁FRfND -8.1047
▁KeLD -8.11978
▁WkLD -8.12246
▁WeTk -8.13249
▁LfFT -8.14443
▁TwK -8.15221
▁TRo -8.17328
▁ScMvgl -8.17768
▁PRg -8.17899
▁DwRgl -8.18843
▁SfVRcL -8.20676
▁Ncvgl -8.21837
▁Ri -8.22799
▁SMeL -8.2586
▁BgKdM -8.26814
▁PLaN -8.27884
▁eLWdZ -8.28205
▁TeK -8.29486
▁BwK -8.30129
▁PwT -8.31272
▁BgTWmN -8.31697
▁RgTkN -8.33086
▁aSKT -8.33259
▁BeRN -8.33271
▁Da -8.3384
▁SfKcND -8.3531
▁RgMdN -8.36742
▁qfNkcL -8.37399
▁PRgNS -8.3743
▁KcNTgNYo -8.38148
▁pgLDRcN -8.38604
▁pdNq -8.3899
▁FaMcLm -8.41463
▁KcNSgDk -8.43512
▁BgKeZ -8.44313
▁haPcN -8.46647
STRcK -8.46792
▁qnN -8.46846
▁Stv -8.47119
▁NfKST -8.48221
▁BgLmV -8.48721
▁fNmvgl -8.49723
▁WwMcN -8.50511
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Some files were not shown because too many files have changed in this diff Show More