mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-25 08:33:53 +08:00
Merge pull request #1320 from xinnan-tech/manager-icp-num
可自定义智控台底部的系统名称、ICP备案号、公安备案号
This commit is contained in:
@@ -40,5 +40,5 @@
|
|||||||
|
|
||||||
2、开启允许非管理员用户可注册,将参数`server.allow_user_register`设置成`true`
|
2、开启允许非管理员用户可注册,将参数`server.allow_user_register`设置成`true`
|
||||||
|
|
||||||
3、开启手机注册功能,将参数`system.enable_mobile_register`设置成`true`
|
3、开启手机注册功能,将参数`server.enable_mobile_register`设置成`true`
|
||||||

|

|
||||||
@@ -118,29 +118,17 @@ public interface Constant {
|
|||||||
|
|
||||||
enum SysBaseParam {
|
enum SysBaseParam {
|
||||||
/**
|
/**
|
||||||
* 系统全称
|
* ICP备案号
|
||||||
*/
|
*/
|
||||||
SYS_NAME("SYS_NAME"),
|
BEIAN_ICP_NUM("server.beian_icp_num"),
|
||||||
/**
|
/**
|
||||||
* 系统简称
|
* GA备案号
|
||||||
*/
|
*/
|
||||||
SYS_SHORT_NAME("SYS_SHORT_NAME"),
|
BEIAN_GA_NUM("server.beian_ga_num"),
|
||||||
/**
|
/**
|
||||||
* 系统描述
|
* 系统名称
|
||||||
*/
|
*/
|
||||||
SYS_DES("SYS_DES"),
|
SERVER_NAME("server.name");
|
||||||
/**
|
|
||||||
* 登录失败几次锁定
|
|
||||||
*/
|
|
||||||
LOGIN_LOCK_COUNT("LOGIN_LOCK_COUNT"),
|
|
||||||
/**
|
|
||||||
* 账号失败锁定分钟数
|
|
||||||
*/
|
|
||||||
LOGIN_LOCK_TIME("LOGIN_LOCK_TIME"),
|
|
||||||
/**
|
|
||||||
* TOKEN强验证
|
|
||||||
*/
|
|
||||||
SYS_TOKEN_SECURITY("SYS_TOKEN_SECURITY");
|
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
@@ -176,11 +164,11 @@ public interface Constant {
|
|||||||
/**
|
/**
|
||||||
* 单号码最大短信发送条数
|
* 单号码最大短信发送条数
|
||||||
*/
|
*/
|
||||||
SYSTEM_SMS_MAX_SEND_COUNT("system.sms.max_send_count"),
|
SERVER_SMS_MAX_SEND_COUNT("server.sms_max_send_count"),
|
||||||
/**
|
/**
|
||||||
* 是否开启手机注册
|
* 是否开启手机注册
|
||||||
*/
|
*/
|
||||||
SYSTEM_ENABLE_MOBILE_REGISTER("system.enable_mobile_register");
|
SERVER_ENABLE_MOBILE_REGISTER("server.enable_mobile_register");
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
@@ -245,4 +233,24 @@ public interface Constant {
|
|||||||
* 无效固件URL
|
* 无效固件URL
|
||||||
*/
|
*/
|
||||||
String INVALID_FIRMWARE_URL = "http://xiaozhi.server.com:8002/xiaozhi/otaMag/download/NOT_ACTIVATED_FIRMWARE_THIS_IS_A_INVALID_URL";
|
String INVALID_FIRMWARE_URL = "http://xiaozhi.server.com:8002/xiaozhi/otaMag/download/NOT_ACTIVATED_FIRMWARE_THIS_IS_A_INVALID_URL";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典类型
|
||||||
|
*/
|
||||||
|
enum DictType {
|
||||||
|
/**
|
||||||
|
* 手机区号
|
||||||
|
*/
|
||||||
|
MOBILE_AREA("MOBILE_AREA");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
DictType(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+10
-5
@@ -1,6 +1,7 @@
|
|||||||
package xiaozhi.modules.security.controller;
|
package xiaozhi.modules.security.controller;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -70,7 +71,7 @@ public class LoginController {
|
|||||||
throw new RenException("图形验证码错误");
|
throw new RenException("图形验证码错误");
|
||||||
}
|
}
|
||||||
Boolean isMobileRegister = sysParamsService
|
Boolean isMobileRegister = sysParamsService
|
||||||
.getValueObject(Constant.SysMSMParam.SYSTEM_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
.getValueObject(Constant.SysMSMParam.SERVER_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
||||||
if (!isMobileRegister) {
|
if (!isMobileRegister) {
|
||||||
throw new RenException("没有开启手机注册,没法使用短信验证码功能");
|
throw new RenException("没有开启手机注册,没法使用短信验证码功能");
|
||||||
}
|
}
|
||||||
@@ -108,7 +109,7 @@ public class LoginController {
|
|||||||
}
|
}
|
||||||
// 是否开启手机注册
|
// 是否开启手机注册
|
||||||
Boolean isMobileRegister = sysParamsService
|
Boolean isMobileRegister = sysParamsService
|
||||||
.getValueObject(Constant.SysMSMParam.SYSTEM_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
.getValueObject(Constant.SysMSMParam.SERVER_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
||||||
boolean validate;
|
boolean validate;
|
||||||
if (isMobileRegister) {
|
if (isMobileRegister) {
|
||||||
// 验证用户是否是手机号码
|
// 验证用户是否是手机号码
|
||||||
@@ -165,7 +166,7 @@ public class LoginController {
|
|||||||
public Result<?> retrievePassword(@RequestBody RetrievePasswordDTO dto) {
|
public Result<?> retrievePassword(@RequestBody RetrievePasswordDTO dto) {
|
||||||
// 是否开启手机注册
|
// 是否开启手机注册
|
||||||
Boolean isMobileRegister = sysParamsService
|
Boolean isMobileRegister = sysParamsService
|
||||||
.getValueObject(Constant.SysMSMParam.SYSTEM_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
.getValueObject(Constant.SysMSMParam.SERVER_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
||||||
if (!isMobileRegister) {
|
if (!isMobileRegister) {
|
||||||
throw new RenException("没有开启手机注册,没法使用找回密码功能");
|
throw new RenException("没有开启手机注册,没法使用找回密码功能");
|
||||||
}
|
}
|
||||||
@@ -198,11 +199,15 @@ public class LoginController {
|
|||||||
public Result<Map<String, Object>> pubConfig() {
|
public Result<Map<String, Object>> pubConfig() {
|
||||||
Map<String, Object> config = new HashMap<>();
|
Map<String, Object> config = new HashMap<>();
|
||||||
config.put("enableMobileRegister", sysParamsService
|
config.put("enableMobileRegister", sysParamsService
|
||||||
.getValueObject(Constant.SysMSMParam.SYSTEM_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class));
|
.getValueObject(Constant.SysMSMParam.SERVER_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class));
|
||||||
config.put("version", Constant.VERSION);
|
config.put("version", Constant.VERSION);
|
||||||
|
config.put("year", "©" + Calendar.getInstance().get(Calendar.YEAR));
|
||||||
config.put("allowUserRegister", sysUserService.getAllowUserRegister());
|
config.put("allowUserRegister", sysUserService.getAllowUserRegister());
|
||||||
List<SysDictDataItem> list = sysDictDataService.getDictDataByType("MOBILE_AREA");
|
List<SysDictDataItem> list = sysDictDataService.getDictDataByType(Constant.DictType.MOBILE_AREA.getValue());
|
||||||
config.put("mobileAreaList", list);
|
config.put("mobileAreaList", list);
|
||||||
|
config.put("beianIcpNum", sysParamsService.getValue(Constant.SysBaseParam.BEIAN_ICP_NUM.getValue(), true));
|
||||||
|
config.put("beianGaNum", sysParamsService.getValue(Constant.SysBaseParam.BEIAN_GA_NUM.getValue(), true));
|
||||||
|
config.put("name", sysParamsService.getValue(Constant.SysBaseParam.SERVER_NAME.getValue(), true));
|
||||||
|
|
||||||
return new Result<Map<String, Object>>().ok(config);
|
return new Result<Map<String, Object>>().ok(config);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -101,7 +101,7 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
|
|
||||||
// 获取最大发送次数限制
|
// 获取最大发送次数限制
|
||||||
Integer maxSendCount = sysParamsService.getValueObject(
|
Integer maxSendCount = sysParamsService.getValueObject(
|
||||||
Constant.SysMSMParam.SYSTEM_SMS_MAX_SEND_COUNT.getValue(),
|
Constant.SysMSMParam.SERVER_SMS_MAX_SEND_COUNT.getValue(),
|
||||||
Integer.class);
|
Integer.class);
|
||||||
if (maxSendCount == null) {
|
if (maxSendCount == null) {
|
||||||
maxSendCount = 5; // 默认值
|
maxSendCount = 5; // 默认值
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ public class SysParamsController {
|
|||||||
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"),
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"),
|
||||||
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"),
|
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"),
|
||||||
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"),
|
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"),
|
||||||
@Parameter(name = "paramCode", description = "参数编码", in = ParameterIn.QUERY, ref = "String")
|
@Parameter(name = "paramCode", description = "参数编码或参数备注", in = ParameterIn.QUERY, ref = "String")
|
||||||
})
|
})
|
||||||
@RequiresPermissions("sys:role:superAdmin")
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
public Result<PageData<SysParamsDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
public Result<PageData<SysParamsDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
|||||||
+3
-1
@@ -52,7 +52,9 @@ public class SysParamsServiceImpl extends BaseServiceImpl<SysParamsDao, SysParam
|
|||||||
|
|
||||||
QueryWrapper<SysParamsEntity> wrapper = new QueryWrapper<>();
|
QueryWrapper<SysParamsEntity> wrapper = new QueryWrapper<>();
|
||||||
wrapper.eq("param_type", 1);
|
wrapper.eq("param_type", 1);
|
||||||
wrapper.like(StringUtils.isNotBlank(paramCode), "param_code", paramCode);
|
wrapper.nested(StringUtils.isNotBlank(paramCode),i->i.like("param_code", paramCode)
|
||||||
|
.or()
|
||||||
|
.like("remark", paramCode));
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-3
@@ -1,15 +1,21 @@
|
|||||||
-- 添加手机短信注册功能的需要的参数
|
-- 添加手机短信注册功能的需要的参数
|
||||||
delete from sys_params where id in (601, 602, 610, 611, 612, 613);
|
delete from sys_params where id in (108, 109, 110, 111, 112, 113, 114, 115);
|
||||||
|
delete from sys_params where id in (610, 611, 612, 613);
|
||||||
INSERT INTO sys_params
|
INSERT INTO sys_params
|
||||||
(id, param_code, param_value, value_type, param_type, remark, creator, create_date, updater, update_date)
|
(id, param_code, param_value, value_type, param_type, remark, creator, create_date, updater, update_date)
|
||||||
VALUES
|
VALUES
|
||||||
(601, 'system.enable_mobile_register', 'false', 'boolean', 1, '是否开启手机注册', NULL, NULL, NULL, NULL),
|
(108, 'server.name', 'xiaozhi-esp32-server', 'string', 1, '系统名称', NULL, NULL, NULL, NULL),
|
||||||
(602, 'system.sms.max_send_count', '10', 'number', 1, '单号码单日最大短信发送条数', NULL, NULL, NULL, NULL),
|
(109, 'server.beian_icp_num', 'null', 'string', 1, 'icp备案号,填写null则不设置', NULL, NULL, NULL, NULL),
|
||||||
|
(110, 'server.beian_ga_num', 'null', 'string', 1, '公安备案号,填写null则不设置', NULL, NULL, NULL, NULL),
|
||||||
|
(111, 'server.enable_mobile_register', 'false', 'boolean', 1, '是否开启手机注册', NULL, NULL, NULL, NULL),
|
||||||
|
(112, 'server.sms_max_send_count', '10', 'number', 1, '单号码单日最大短信发送条数', NULL, NULL, NULL, NULL),
|
||||||
(610, 'aliyun.sms.access_key_id', '', 'string', 1, '阿里云平台access_key', NULL, NULL, NULL, NULL),
|
(610, 'aliyun.sms.access_key_id', '', 'string', 1, '阿里云平台access_key', NULL, NULL, NULL, NULL),
|
||||||
(611, 'aliyun.sms.access_key_secret', '', 'string', 1, '阿里云平台access_key_secret', NULL, NULL, NULL, NULL),
|
(611, 'aliyun.sms.access_key_secret', '', 'string', 1, '阿里云平台access_key_secret', NULL, NULL, NULL, NULL),
|
||||||
(612, 'aliyun.sms.sign_name', '', 'string', 1, '阿里云短信签名', NULL, NULL, NULL, NULL),
|
(612, 'aliyun.sms.sign_name', '', 'string', 1, '阿里云短信签名', NULL, NULL, NULL, NULL),
|
||||||
(613, 'aliyun.sms.sms_code_template_code', '', 'string', 1, '阿里云短信模板', NULL, NULL, NULL, NULL);
|
(613, 'aliyun.sms.sms_code_template_code', '', 'string', 1, '阿里云短信模板', NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
update sys_params set remark = '是否允许管理员以外的人注册' where param_code = 'server.allow_user_register';
|
||||||
|
|
||||||
-- 增加手机区域字典
|
-- 增加手机区域字典
|
||||||
-- 插入固件类型字典类型
|
-- 插入固件类型字典类型
|
||||||
delete from `sys_dict_type` where `id` = 102;
|
delete from `sys_dict_type` where `id` = 102;
|
||||||
@@ -114,13 +114,6 @@ databaseChangeLog:
|
|||||||
- sqlFile:
|
- sqlFile:
|
||||||
encoding: utf8
|
encoding: utf8
|
||||||
path: classpath:db/changelog/202505091409.sql
|
path: classpath:db/changelog/202505091409.sql
|
||||||
- changeSet:
|
|
||||||
id: 202505141132
|
|
||||||
author: zjy
|
|
||||||
changes:
|
|
||||||
- sqlFile:
|
|
||||||
encoding: utf8
|
|
||||||
path: classpath:db/changelog/202505141132.sql
|
|
||||||
- changeSet:
|
- changeSet:
|
||||||
id: 202505091555
|
id: 202505091555
|
||||||
author: whosmyqueen
|
author: whosmyqueen
|
||||||
@@ -149,3 +142,10 @@ databaseChangeLog:
|
|||||||
- sqlFile:
|
- sqlFile:
|
||||||
encoding: utf8
|
encoding: utf8
|
||||||
path: classpath:db/changelog/202505142037.sql
|
path: classpath:db/changelog/202505142037.sql
|
||||||
|
- changeSet:
|
||||||
|
id: 202505182234
|
||||||
|
author: amen
|
||||||
|
changes:
|
||||||
|
- sqlFile:
|
||||||
|
encoding: utf8
|
||||||
|
path: classpath:db/changelog/202505182234.sql
|
||||||
@@ -1,23 +1,74 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
©2025 xiaozhi-esp32-server v{{ version }}
|
<div class="footer-content">
|
||||||
|
<span>{{ year }} {{ name }} {{ version }}</span>
|
||||||
|
<template v-if="beianGaNum !== 'null'">
|
||||||
|
<span v-if="beianIcpNum !== 'null' || name">|</span>
|
||||||
|
<a :href="'http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=' + beianGaNum" target="_blank"
|
||||||
|
rel="noopener" class="beian-link">
|
||||||
|
<img
|
||||||
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAACXlBMVEUAAADax4rGxqP556zmsVD/6KXu5JvwvFPglEFnY3nnpEjosU1+XFTmuVfu13Hrv1jpsFa1k3mne2HlvnPdqmPqz3fu3YrJoWv04J/mz5z246aSi3i2p2/0zGj82WDrtFjar1O7klO4dkfimUJcWnbho0rgr1vntFfmvFflvGOZdFKXZkOUemnmv2XkuWWVe2ziqlXnt1Tr0HDpwl6ObmCkbEKqhVyOc2jdoVHmuljfrmDq0nPapWDUnErqy3XjtWXesXLrzHjz34rqzYfmw3fy4YrqyYDevW/dzoTIhkndsXLRsIneuHjlyIzQroTjuXjlyYfktWvw2prhvoHTmGfx45j3773TuYT/25LdijyKf321oXU+Nm3cumXfuWLtwlzpwVz40FvpvlvqvFfouFXjrlHipEjcmEfknEXPbzfbZyzZQR/YMBrWKBrhJhLdHxDTGg5HV4xBT4YYKYaWk4SDgYIWIYBybH0qLn1KS3tlZHpNS3WGfHIcHXEwLHAnF28rKW07NGuzn2pNQ2ruzWnDrGnuy2jryGjAnGgoH2j1x2RCNGPcrmIsEGGQdl/pu17YtV7FoV3muVxoRVzWqFvSmVp2SVbyw1XbkVTuvFPfo1PgmVPpt1LcnFLWkVLlp1F7W1HpsU92QE5oMUtFAUrpqUjnjUFOAEHUgz+DUj14FzvbczieMTdhATfodjXWcDXcbjXVcTS/Xi/hay7WXS3cWS3vYyvaVSrUVymnJSjXSyeKDSbNSiWfHCPMTyLFQiHkSR/lPxvVLRrPLBnUJRfUHhbaJxXVGxTZJxPNFhBdOhm/AAAAWXRSTlMABQIU/hIJ/v79/Pj29PPx4cC6s7CNfmxZWRv+/v7+/v7+/v78/Pr6+fPz8vHq6ujl5eTj4ODe2NTQzMW6ubKsnJeQkJCJiIOBgX9ubGpoW1lMREM0JR8dDgvYx1gAAAE7SURBVBjTYgADJmZJQUFJZiYGOGD2EzLV1jIT8paCibCJ86zctGPD1D4ecUaICKuPyYLMYznZOfNqzP0jwEJBOt1KB4/mHjqZ3dGsHwxW5M4Zk5l/PPdIQcGMShUPVqBlgQLlMSvyDq+P3HVidjWnkQQTA5MXV1SFYtb+jZGrl02si2J3Y2JgFMmILl68efueLVvXLSqLXirCCBgDow1HT+GS/AP7srblLS+K5bIHCjmodpXUr929d+eaVb3SsuouQCHhufPjShsbJk/rrK2KW8hiBxRyVkvnkI9tnaDQJDNFOU1DDOjRMEfe9Mjpiewz5RIzZmmKMoPcKqGbkJqSkBSfnDqpXS+ACeRpJ76W/uSUpDlpLPFtfK5soLAKFbU05Odm4eblN7YWk4KEGWOIp62FgYCVsG84SAAAL7BaooX965sAAAAASUVORK5CYII="
|
||||||
|
class="beian-icon" alt="备案图标">
|
||||||
|
<span class="beian-text">{{ beianGaNum }}</span>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<template v-if="beianIcpNum !== 'null'">
|
||||||
|
<span v-if="name">|</span>
|
||||||
|
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener" class="beian-link">
|
||||||
|
<span class="beian-text">{{ beianIcpNum }}</span>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex';
|
import { mapState } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'VersionFooter',
|
name: 'VersionFooter',
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
version: state => state.pubConfig.version
|
version: state => state.pubConfig.version,
|
||||||
})
|
name: state => state.pubConfig.name,
|
||||||
},
|
beianIcpNum: state => state.pubConfig.beianIcpNum,
|
||||||
mounted() {
|
beianGaNum: state => state.pubConfig.beianGaNum,
|
||||||
this.$store.dispatch('fetchPubConfig');
|
year: state => state.pubConfig.year
|
||||||
}
|
})
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$store.dispatch('fetchPubConfig')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beian-link {
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beian-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beian-text {
|
||||||
|
color: #000;
|
||||||
|
font-size: 12px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,6 +13,8 @@ export default new Vuex.Store({
|
|||||||
isSuperAdmin: false, // 添加superAdmin状态
|
isSuperAdmin: false, // 添加superAdmin状态
|
||||||
pubConfig: { // 添加公共配置存储
|
pubConfig: { // 添加公共配置存储
|
||||||
version: '',
|
version: '',
|
||||||
|
beianIcpNum: 'null',
|
||||||
|
beianGaNum: 'null',
|
||||||
allowUserRegister: false
|
allowUserRegister: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="operation-bar">
|
<div class="operation-bar">
|
||||||
<h2 class="page-title">参数管理</h2>
|
<h2 class="page-title">参数管理</h2>
|
||||||
<div class="right-operations">
|
<div class="right-operations">
|
||||||
<el-input placeholder="请输入参数编码查询" v-model="searchCode" class="search-input"
|
<el-input placeholder="请输入参数编码或备注查询" v-model="searchCode" class="search-input"
|
||||||
@keyup.enter.native="handleSearch" clearable />
|
@keyup.enter.native="handleSearch" clearable />
|
||||||
<el-button class="btn-search" @click="handleSearch">搜索</el-button>
|
<el-button class="btn-search" @click="handleSearch">搜索</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ LLM:
|
|||||||
base_url: https://host/api/v1
|
base_url: https://host/api/v1
|
||||||
# 你可以在这里找到你的api_key
|
# 你可以在这里找到你的api_key
|
||||||
# https://cloud.tryfastgpt.ai/account/apikey
|
# https://cloud.tryfastgpt.ai/account/apikey
|
||||||
api_key: fastgpt-xxx
|
api_key: 你的fastgpt密钥
|
||||||
variables:
|
variables:
|
||||||
k: "v"
|
k: "v"
|
||||||
k2: "v2"
|
k2: "v2"
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ def ensure_directories(config):
|
|||||||
|
|
||||||
# ASR/TTS模块输出目录
|
# ASR/TTS模块输出目录
|
||||||
for module in ["ASR", "TTS"]:
|
for module in ["ASR", "TTS"]:
|
||||||
|
if config.get(module) is None:
|
||||||
|
continue
|
||||||
for provider in config.get(module, {}).values():
|
for provider in config.get(module, {}).values():
|
||||||
output_dir = provider.get("output_dir", "")
|
output_dir = provider.get("output_dir", "")
|
||||||
if output_dir:
|
if output_dir:
|
||||||
@@ -93,6 +95,10 @@ def ensure_directories(config):
|
|||||||
selected_provider = selected_modules.get(module_type)
|
selected_provider = selected_modules.get(module_type)
|
||||||
if not selected_provider:
|
if not selected_provider:
|
||||||
continue
|
continue
|
||||||
|
if config.get(module) is None:
|
||||||
|
continue
|
||||||
|
if config.get(selected_provider) is None:
|
||||||
|
continue
|
||||||
provider_config = config.get(module_type, {}).get(selected_provider, {})
|
provider_config = config.get(module_type, {}).get(selected_provider, {})
|
||||||
output_dir = provider_config.get("output_dir")
|
output_dir = provider_config.get("output_dir")
|
||||||
if output_dir:
|
if output_dir:
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import time
|
|
||||||
import aiohttp
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import statistics
|
||||||
|
import time
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
from typing import Dict, List
|
|
||||||
|
from config.settings import load_config
|
||||||
|
from core.utils.asr import create_instance as create_stt_instance
|
||||||
from core.utils.llm import create_instance as create_llm_instance
|
from core.utils.llm import create_instance as create_llm_instance
|
||||||
from core.utils.tts import create_instance as create_tts_instance
|
from core.utils.tts import create_instance as create_tts_instance
|
||||||
import statistics
|
|
||||||
from config.settings import load_config
|
|
||||||
import inspect
|
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
|
|
||||||
# 设置全局日志级别为WARNING,抑制INFO级别日志
|
# 设置全局日志级别为WARNING,抑制INFO级别日志
|
||||||
logging.basicConfig(level=logging.WARNING)
|
logging.basicConfig(level=logging.WARNING)
|
||||||
@@ -26,7 +28,17 @@ class AsyncPerformanceTester:
|
|||||||
"请用100字概括量子计算的基本原理和应用前景",
|
"请用100字概括量子计算的基本原理和应用前景",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.results = {"llm": {}, "tts": {}, "combinations": []}
|
|
||||||
|
self.test_wav_list = []
|
||||||
|
self.wav_root = r"config/assets"
|
||||||
|
for file_name in os.listdir(self.wav_root):
|
||||||
|
file_path = os.path.join(self.wav_root, file_name)
|
||||||
|
# 检查文件大小是否大于300KB
|
||||||
|
if os.path.getsize(file_path) > 300 * 1024: # 300KB = 300 * 1024 bytes
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
self.test_wav_list.append(f.read())
|
||||||
|
|
||||||
|
self.results = {"llm": {}, "tts": {}, "stt": {}, "combinations": []}
|
||||||
|
|
||||||
async def _check_ollama_service(self, base_url: str, model_name: str) -> bool:
|
async def _check_ollama_service(self, base_url: str, model_name: str) -> bool:
|
||||||
"""异步检查Ollama服务状态"""
|
"""异步检查Ollama服务状态"""
|
||||||
@@ -109,6 +121,57 @@ class AsyncPerformanceTester:
|
|||||||
print(f"⚠️ {tts_name} 测试失败: {str(e)}")
|
print(f"⚠️ {tts_name} 测试失败: {str(e)}")
|
||||||
return {"name": tts_name, "type": "tts", "errors": 1}
|
return {"name": tts_name, "type": "tts", "errors": 1}
|
||||||
|
|
||||||
|
async def _test_stt(self, stt_name: str, config: Dict) -> Dict:
|
||||||
|
"""异步测试单个STT性能"""
|
||||||
|
try:
|
||||||
|
logging.getLogger("core.providers.asr.base").setLevel(logging.WARNING)
|
||||||
|
token_fields = ["access_token", "api_key", "token"]
|
||||||
|
if any(
|
||||||
|
field in config
|
||||||
|
and any(x in config[field] for x in ["你的", "placeholder"])
|
||||||
|
for field in token_fields
|
||||||
|
):
|
||||||
|
print(f"⏭️ STT {stt_name} 未配置access_token/api_key,已跳过")
|
||||||
|
return {"name": stt_name, "type": "stt", "errors": 1}
|
||||||
|
|
||||||
|
module_type = config.get("type", stt_name)
|
||||||
|
stt = create_stt_instance(module_type, config, delete_audio_file=True)
|
||||||
|
stt.audio_format = "pcm"
|
||||||
|
|
||||||
|
print(f"🎵 测试 STT: {stt_name}")
|
||||||
|
|
||||||
|
text, _ = await stt.speech_to_text([self.test_wav_list[0]], "1")
|
||||||
|
|
||||||
|
if text is None:
|
||||||
|
print(f"❌ {stt_name} 连接失败")
|
||||||
|
return {"name": stt_name, "type": "stt", "errors": 1}
|
||||||
|
|
||||||
|
total_time = 0
|
||||||
|
test_count = len(self.test_wav_list)
|
||||||
|
|
||||||
|
for i, sentence in enumerate(self.test_wav_list, 1):
|
||||||
|
start = time.time()
|
||||||
|
text, _ = await stt.speech_to_text([sentence], "1")
|
||||||
|
duration = time.time() - start
|
||||||
|
total_time += duration
|
||||||
|
|
||||||
|
if text:
|
||||||
|
print(f"✓ {stt_name} [{i}/{test_count}]")
|
||||||
|
else:
|
||||||
|
print(f"✗ {stt_name} [{i}/{test_count}]")
|
||||||
|
return {"name": stt_name, "type": "stt", "errors": 1}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"name": stt_name,
|
||||||
|
"type": "stt",
|
||||||
|
"avg_time": total_time / test_count,
|
||||||
|
"errors": 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ {stt_name} 测试失败: {str(e)}")
|
||||||
|
return {"name": stt_name, "type": "stt", "errors": 1}
|
||||||
|
|
||||||
async def _test_llm(self, llm_name: str, config: Dict) -> Dict:
|
async def _test_llm(self, llm_name: str, config: Dict) -> Dict:
|
||||||
"""异步测试单个LLM性能"""
|
"""异步测试单个LLM性能"""
|
||||||
try:
|
try:
|
||||||
@@ -234,6 +297,7 @@ class AsyncPerformanceTester:
|
|||||||
if v["errors"] == 0 and v["avg_first_token"] >= 0.05
|
if v["errors"] == 0 and v["avg_first_token"] >= 0.05
|
||||||
]
|
]
|
||||||
valid_tts = [k for k, v in self.results["tts"].items() if v["errors"] == 0]
|
valid_tts = [k for k, v in self.results["tts"].items() if v["errors"] == 0]
|
||||||
|
valid_stt = [k for k, v in self.results["stt"].items() if v["errors"] == 0]
|
||||||
|
|
||||||
# 找出基准值
|
# 找出基准值
|
||||||
min_first_token = (
|
min_first_token = (
|
||||||
@@ -246,42 +310,53 @@ class AsyncPerformanceTester:
|
|||||||
if valid_tts
|
if valid_tts
|
||||||
else 1
|
else 1
|
||||||
)
|
)
|
||||||
|
min_stt_time = (
|
||||||
|
min([self.results["stt"][stt]["avg_time"] for stt in valid_stt])
|
||||||
|
if valid_stt
|
||||||
|
else 1
|
||||||
|
)
|
||||||
|
|
||||||
for llm in valid_llms:
|
for llm in valid_llms:
|
||||||
for tts in valid_tts:
|
for tts in valid_tts:
|
||||||
# 计算相对性能分数(越小越好)
|
for stt in valid_stt:
|
||||||
llm_score = (
|
# 计算相对性能分数(越小越好)
|
||||||
self.results["llm"][llm]["avg_first_token"] / min_first_token
|
llm_score = (
|
||||||
)
|
self.results["llm"][llm]["avg_first_token"] / min_first_token
|
||||||
tts_score = self.results["tts"][tts]["avg_time"] / min_tts_time
|
)
|
||||||
|
tts_score = self.results["tts"][tts]["avg_time"] / min_tts_time
|
||||||
|
stt_score = self.results["stt"][stt]["avg_time"] / min_stt_time
|
||||||
|
|
||||||
# 计算稳定性分数(标准差/平均值,越小越稳定)
|
# 计算稳定性分数(标准差/平均值,越小越稳定)
|
||||||
llm_stability = (
|
llm_stability = (
|
||||||
self.results["llm"][llm]["std_first_token"]
|
self.results["llm"][llm]["std_first_token"]
|
||||||
/ self.results["llm"][llm]["avg_first_token"]
|
/ self.results["llm"][llm]["avg_first_token"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# 综合得分(考虑性能和稳定性)
|
# 综合得分(考虑性能和稳定性)
|
||||||
# 性能权重0.7,稳定性权重0.3
|
# LLM得分: 性能权重(70%) + 稳定性权重(30%)
|
||||||
llm_final_score = llm_score * 0.7 + llm_stability * 0.3
|
llm_final_score = llm_score * 0.7 + llm_stability * 0.3
|
||||||
|
|
||||||
# 总分 = LLM得分(70%) + TTS得分(30%)
|
# 总分 = LLM得分(70%) + TTS得分(30%) + STT得分(30%)
|
||||||
total_score = llm_final_score * 0.7 + tts_score * 0.3
|
total_score = (
|
||||||
|
llm_final_score * 0.7 + tts_score * 0.3 + stt_score * 0.3
|
||||||
|
)
|
||||||
|
|
||||||
self.results["combinations"].append(
|
self.results["combinations"].append(
|
||||||
{
|
{
|
||||||
"llm": llm,
|
"llm": llm,
|
||||||
"tts": tts,
|
"tts": tts,
|
||||||
"score": total_score,
|
"stt": stt,
|
||||||
"details": {
|
"score": total_score,
|
||||||
"llm_first_token": self.results["llm"][llm][
|
"details": {
|
||||||
"avg_first_token"
|
"llm_first_token": self.results["llm"][llm][
|
||||||
],
|
"avg_first_token"
|
||||||
"llm_stability": llm_stability,
|
],
|
||||||
"tts_time": self.results["tts"][tts]["avg_time"],
|
"llm_stability": llm_stability,
|
||||||
},
|
"tts_time": self.results["tts"][tts]["avg_time"],
|
||||||
}
|
"stt_time": self.results["stt"][stt]["avg_time"],
|
||||||
)
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# 分数越小越好
|
# 分数越小越好
|
||||||
self.results["combinations"].sort(key=lambda x: x["score"])
|
self.results["combinations"].sort(key=lambda x: x["score"])
|
||||||
@@ -302,7 +377,7 @@ class AsyncPerformanceTester:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if llm_table:
|
if llm_table:
|
||||||
print("\nLLM 性能排行:")
|
print("\nLLM 性能排行:\n")
|
||||||
print(
|
print(
|
||||||
tabulate(
|
tabulate(
|
||||||
llm_table,
|
llm_table,
|
||||||
@@ -321,7 +396,7 @@ class AsyncPerformanceTester:
|
|||||||
tts_table.append([name, f"{data['avg_time']:.3f}秒"]) # 不需要固定宽度
|
tts_table.append([name, f"{data['avg_time']:.3f}秒"]) # 不需要固定宽度
|
||||||
|
|
||||||
if tts_table:
|
if tts_table:
|
||||||
print("\nTTS 性能排行:")
|
print("\nTTS 性能排行:\n")
|
||||||
print(
|
print(
|
||||||
tabulate(
|
tabulate(
|
||||||
tts_table,
|
tts_table,
|
||||||
@@ -334,17 +409,37 @@ class AsyncPerformanceTester:
|
|||||||
else:
|
else:
|
||||||
print("\n⚠️ 没有可用的TTS模块进行测试。")
|
print("\n⚠️ 没有可用的TTS模块进行测试。")
|
||||||
|
|
||||||
|
stt_table = []
|
||||||
|
for name, data in self.results["stt"].items():
|
||||||
|
if data["errors"] == 0:
|
||||||
|
stt_table.append([name, f"{data['avg_time']:.3f}秒"]) # 不需要固定宽度
|
||||||
|
|
||||||
|
if stt_table:
|
||||||
|
print("\nSTT 性能排行:\n")
|
||||||
|
print(
|
||||||
|
tabulate(
|
||||||
|
stt_table,
|
||||||
|
headers=["模型名称", "合成耗时"],
|
||||||
|
tablefmt="github",
|
||||||
|
colalign=("left", "right"),
|
||||||
|
disable_numparse=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print("\n⚠️ 没有可用的STT模块进行测试。")
|
||||||
|
|
||||||
if self.results["combinations"]:
|
if self.results["combinations"]:
|
||||||
print("\n推荐配置组合 (得分越小越好):")
|
print("\n推荐配置组合 (得分越小越好):\n")
|
||||||
combo_table = []
|
combo_table = []
|
||||||
for combo in self.results["combinations"][:5]:
|
for combo in self.results["combinations"][:]:
|
||||||
combo_table.append(
|
combo_table.append(
|
||||||
[
|
[
|
||||||
f"{combo['llm']} + {combo['tts']}", # 不需要固定宽度
|
f"{combo['llm']} + {combo['tts']} + {combo['stt']}", # 不需要固定宽度
|
||||||
f"{combo['score']:.3f}",
|
f"{combo['score']:.3f}",
|
||||||
f"{combo['details']['llm_first_token']:.3f}秒",
|
f"{combo['details']['llm_first_token']:.3f}秒",
|
||||||
f"{combo['details']['llm_stability']:.3f}",
|
f"{combo['details']['llm_stability']:.3f}",
|
||||||
f"{combo['details']['tts_time']:.3f}秒",
|
f"{combo['details']['tts_time']:.3f}秒",
|
||||||
|
f"{combo['details']['stt_time']:.3f}秒",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -357,9 +452,10 @@ class AsyncPerformanceTester:
|
|||||||
"LLM首字耗时",
|
"LLM首字耗时",
|
||||||
"稳定性",
|
"稳定性",
|
||||||
"TTS合成耗时",
|
"TTS合成耗时",
|
||||||
|
"STT合成耗时",
|
||||||
],
|
],
|
||||||
tablefmt="github",
|
tablefmt="github",
|
||||||
colalign=("left", "right", "right", "right", "right"),
|
colalign=("left", "right", "right", "right", "right", "right"),
|
||||||
disable_numparse=True,
|
disable_numparse=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -372,8 +468,12 @@ class AsyncPerformanceTester:
|
|||||||
if result["errors"] == 0:
|
if result["errors"] == 0:
|
||||||
if result["type"] == "llm":
|
if result["type"] == "llm":
|
||||||
self.results["llm"][result["name"]] = result
|
self.results["llm"][result["name"]] = result
|
||||||
else:
|
elif result["type"] == "tts":
|
||||||
self.results["tts"][result["name"]] = result
|
self.results["tts"][result["name"]] = result
|
||||||
|
elif result["type"] == "stt":
|
||||||
|
self.results["stt"][result["name"]] = result
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
"""执行全量异步测试"""
|
"""执行全量异步测试"""
|
||||||
@@ -383,52 +483,73 @@ class AsyncPerformanceTester:
|
|||||||
all_tasks = []
|
all_tasks = []
|
||||||
|
|
||||||
# LLM测试任务
|
# LLM测试任务
|
||||||
for llm_name, config in self.config.get("LLM", {}).items():
|
if self.config.get("LLM") is not None:
|
||||||
# 检查配置有效性
|
for llm_name, config in self.config.get("LLM", {}).items():
|
||||||
if llm_name == "CozeLLM":
|
# 检查配置有效性
|
||||||
if any(x in config.get("bot_id", "") for x in ["你的"]) or any(
|
if llm_name == "CozeLLM":
|
||||||
x in config.get("user_id", "") for x in ["你的"]
|
if any(x in config.get("bot_id", "") for x in ["你的"]) or any(
|
||||||
|
x in config.get("user_id", "") for x in ["你的"]
|
||||||
|
):
|
||||||
|
print(f"⏭️ LLM {llm_name} 未配置bot_id/user_id,已跳过")
|
||||||
|
continue
|
||||||
|
elif "api_key" in config and any(
|
||||||
|
x in config["api_key"] for x in ["你的", "placeholder", "sk-xxx"]
|
||||||
):
|
):
|
||||||
print(f"⏭️ LLM {llm_name} 未配置bot_id/user_id,已跳过")
|
print(f"⏭️ LLM {llm_name} 未配置api_key,已跳过")
|
||||||
continue
|
|
||||||
elif "api_key" in config and any(
|
|
||||||
x in config["api_key"] for x in ["你的", "placeholder", "sk-xxx"]
|
|
||||||
):
|
|
||||||
print(f"⏭️ LLM {llm_name} 未配置api_key,已跳过")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 对于Ollama,先检查服务状态
|
|
||||||
if llm_name == "Ollama":
|
|
||||||
base_url = config.get("base_url", "http://localhost:11434")
|
|
||||||
model_name = config.get("model_name")
|
|
||||||
if not model_name:
|
|
||||||
print(f"🚫 Ollama未配置model_name")
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not await self._check_ollama_service(base_url, model_name):
|
# 对于Ollama,先检查服务状态
|
||||||
continue
|
if llm_name == "Ollama":
|
||||||
|
base_url = config.get("base_url", "http://localhost:11434")
|
||||||
|
model_name = config.get("model_name")
|
||||||
|
if not model_name:
|
||||||
|
print(f"🚫 Ollama未配置model_name")
|
||||||
|
continue
|
||||||
|
|
||||||
print(f"📋 添加LLM测试任务: {llm_name}")
|
if not await self._check_ollama_service(base_url, model_name):
|
||||||
module_type = config.get("type", llm_name)
|
continue
|
||||||
llm = create_llm_instance(module_type, config)
|
|
||||||
|
|
||||||
# 为每个句子创建独立任务
|
print(f"📋 添加LLM测试任务: {llm_name}")
|
||||||
for sentence in self.test_sentences:
|
module_type = config.get("type", llm_name)
|
||||||
sentence = sentence.encode("utf-8").decode("utf-8")
|
llm = create_llm_instance(module_type, config)
|
||||||
all_tasks.append(self._test_single_sentence(llm_name, llm, sentence))
|
|
||||||
|
# 为每个句子创建独立任务
|
||||||
|
for sentence in self.test_sentences:
|
||||||
|
sentence = sentence.encode("utf-8").decode("utf-8")
|
||||||
|
all_tasks.append(
|
||||||
|
self._test_single_sentence(llm_name, llm, sentence)
|
||||||
|
)
|
||||||
|
|
||||||
# TTS测试任务
|
# TTS测试任务
|
||||||
for tts_name, config in self.config.get("TTS", {}).items():
|
if self.config.get("TTS") is not None:
|
||||||
token_fields = ["access_token", "api_key", "token"]
|
for tts_name, config in self.config.get("TTS", {}).items():
|
||||||
if any(
|
token_fields = ["access_token", "api_key", "token"]
|
||||||
field in config
|
if any(
|
||||||
and any(x in config[field] for x in ["你的", "placeholder"])
|
field in config
|
||||||
for field in token_fields
|
and any(x in config[field] for x in ["你的", "placeholder"])
|
||||||
):
|
for field in token_fields
|
||||||
print(f"⏭️ TTS {tts_name} 未配置access_token/api_key,已跳过")
|
):
|
||||||
continue
|
print(f"⏭️ TTS {tts_name} 未配置access_token/api_key,已跳过")
|
||||||
print(f"🎵 添加TTS测试任务: {tts_name}")
|
continue
|
||||||
all_tasks.append(self._test_tts(tts_name, config))
|
print(f"🎵 添加TTS测试任务: {tts_name}")
|
||||||
|
all_tasks.append(self._test_tts(tts_name, config))
|
||||||
|
|
||||||
|
# STT测试任务
|
||||||
|
if len(self.test_wav_list) >= 1:
|
||||||
|
if self.config.get("ASR") is not None:
|
||||||
|
for stt_name, config in self.config.get("ASR", {}).items():
|
||||||
|
token_fields = ["access_token", "api_key", "token"]
|
||||||
|
if any(
|
||||||
|
field in config
|
||||||
|
and any(x in config[field] for x in ["你的", "placeholder"])
|
||||||
|
for field in token_fields
|
||||||
|
):
|
||||||
|
print(f"⏭️ ASR {stt_name} 未配置access_token/api_key,已跳过")
|
||||||
|
continue
|
||||||
|
print(f"🎵 添加ASR测试任务: {stt_name}")
|
||||||
|
all_tasks.append(self._test_stt(stt_name, config))
|
||||||
|
else:
|
||||||
|
print(f"\n⚠️ {self.wav_root} 路径下没有音频文件,已跳过STT测试任务")
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"\n✅ 找到 {len([t for t in all_tasks if 'test_single_sentence' in str(t)]) / len(self.test_sentences):.0f} 个可用LLM模块"
|
f"\n✅ 找到 {len([t for t in all_tasks if 'test_single_sentence' in str(t)]) / len(self.test_sentences):.0f} 个可用LLM模块"
|
||||||
@@ -436,6 +557,9 @@ class AsyncPerformanceTester:
|
|||||||
print(
|
print(
|
||||||
f"✅ 找到 {len([t for t in all_tasks if '_test_tts' in str(t)])} 个可用TTS模块"
|
f"✅ 找到 {len([t for t in all_tasks if '_test_tts' in str(t)])} 个可用TTS模块"
|
||||||
)
|
)
|
||||||
|
print(
|
||||||
|
f"✅ 找到 {len([t for t in all_tasks if '_test_stt' in str(t)])} 个可用STT模块"
|
||||||
|
)
|
||||||
print("\n⏳ 开始并发测试所有模块...\n")
|
print("\n⏳ 开始并发测试所有模块...\n")
|
||||||
|
|
||||||
# 并发执行所有测试任务
|
# 并发执行所有测试任务
|
||||||
@@ -494,6 +618,15 @@ class AsyncPerformanceTester:
|
|||||||
if result["errors"] == 0:
|
if result["errors"] == 0:
|
||||||
self.results["tts"][result["name"]] = result
|
self.results["tts"][result["name"]] = result
|
||||||
|
|
||||||
|
# 处理STT结果
|
||||||
|
for result in [
|
||||||
|
r
|
||||||
|
for r in all_results
|
||||||
|
if r and isinstance(r, dict) and r.get("type") == "stt"
|
||||||
|
]:
|
||||||
|
if result["errors"] == 0:
|
||||||
|
self.results["stt"][result["name"]] = result
|
||||||
|
|
||||||
# 生成组合建议并打印结果
|
# 生成组合建议并打印结果
|
||||||
print("\n📊 生成测试报告...")
|
print("\n📊 生成测试报告...")
|
||||||
self._generate_combinations()
|
self._generate_combinations()
|
||||||
|
|||||||
Reference in New Issue
Block a user