Merge branch 'main' into py_test_Memory_powermem

This commit is contained in:
Sakura-RanChen
2026-02-04 16:02:50 +08:00
415 changed files with 72660 additions and 3336 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: |
+9 -8
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,19 @@ 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/*
&& rm -rf /var/cache/apk/* \
&& mkdir -p /run/nginx /var/log/nginx /var/tmp/nginx /etc/nginx/conf.d
# 复制项目自带的中文字体
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.11";
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;
}
}
@@ -28,7 +28,7 @@ public class AgentMcpAccessPointController {
/**
* 获取智能体的Mcp接入点地址
*
* @param audioId 智能体id
* @param agentId 智能体id
* @return 返回错误提醒或者Mcp接入点地址
*/
@Operation(summary = "获取智能体的Mcp接入点地址")
@@ -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;
@@ -85,9 +87,9 @@ 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());
}
// 查询上下文源配置
@@ -130,26 +132,21 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
@Override
public List<AgentDTO> getUserAgents(Long userId, String keyword, String searchType) {
QueryWrapper<AgentEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId);
queryWrapper.eq("user_id", userId).orderByDesc("created_at");
// 如果有搜索关键词,根据搜索类型添加相应的查询条件
if (StringUtils.isNotBlank(keyword)) {
if ("mac".equals(searchType)) {
// 按MAC地址搜索:先搜索设备,再获取对应的智能体
List<DeviceEntity> devices = deviceService.searchDevicesByMacAddress(keyword, userId);
if (!devices.isEmpty()) {
// 获取设备对应的智能体ID列表
List<String> agentIds = devices.stream()
.map(DeviceEntity::getAgentId)
.distinct()
.collect(Collectors.toList());
if (!agentIds.isEmpty()) {
queryWrapper.in("id", agentIds);
} else {
return new ArrayList<>();
}
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<>();
}
@@ -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 返回设备最近的最后连接时间
*/
@@ -112,9 +118,19 @@ public interface DeviceService extends BaseService<DeviceEntity> {
* 根据MAC地址搜索设备
*
* @param macAddress MAC地址关键词
* @param userId 用户ID
* @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;
@@ -606,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,
@@ -129,6 +129,10 @@ public class ModelController {
if (entity == null) {
return new Result<Void>().error("模型配置不存在");
}
// 不能关闭默认模型
if (status == 0 && entity.getIsDefault() > 0) {
return new Result<Void>().error("默认模型配置不允许关闭");
}
// 不更新ConfigJson字段
entity.setConfigJson(null);
entity.setIsEnabled(status);
@@ -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,10 +124,7 @@ 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());
@@ -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,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';
@@ -0,0 +1 @@
INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (502, 'system_error_response', '主人,小智现在有点忙,我们稍后再试吧。', 'string', 1, '系统错误时的回复');
@@ -487,3 +487,31 @@ databaseChangeLog:
- 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
- changeSet:
id: 202602021555
author: shengzhou1216
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202602021555.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.11'
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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