mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-23 23:53:55 +08:00
Compare commits
21
Commits
v0.8.8
...
fix-chat-depth
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c07ecbf6d1 | ||
|
|
920e24b4ff | ||
|
|
43d82343a3 | ||
|
|
faea50f99d | ||
|
|
ef59798d70 | ||
|
|
c1f0853271 | ||
|
|
f9bd5bb995 | ||
|
|
f1c2b5cb3f | ||
|
|
579af29a73 | ||
|
|
9e20a53ca0 | ||
|
|
8768240efe | ||
|
|
b429760bd5 | ||
|
|
218cd35c3d | ||
|
|
146a039c19 | ||
|
|
9a3e1fa9c8 | ||
|
|
fa194af9bb | ||
|
|
46b3757c13 | ||
|
|
5050ea7ac1 | ||
|
|
d121b4d0e1 | ||
|
|
d45bf5f60a | ||
|
|
94a43432fc |
@@ -19,4 +19,15 @@ public class VoiceDTO implements Serializable {
|
|||||||
|
|
||||||
@Schema(description = "音色名称")
|
@Schema(description = "音色名称")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "音频播放地址")
|
||||||
|
private String voiceDemo;
|
||||||
|
|
||||||
|
// 添加双参数构造函数,保持向后兼容
|
||||||
|
public VoiceDTO(String id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.voiceDemo = null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+11
-2
@@ -133,7 +133,11 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
|
|||||||
timbreEntities = new ArrayList<>();
|
timbreEntities = new ArrayList<>();
|
||||||
}
|
}
|
||||||
List<VoiceDTO> voiceDTOs = timbreEntities.stream()
|
List<VoiceDTO> voiceDTOs = timbreEntities.stream()
|
||||||
.map(entity -> new VoiceDTO(entity.getId(), entity.getName()))
|
.map(entity -> {
|
||||||
|
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
|
||||||
|
dto.setVoiceDemo(entity.getVoiceDemo());
|
||||||
|
return dto;
|
||||||
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 获取当前登录用户ID
|
// 获取当前登录用户ID
|
||||||
@@ -146,6 +150,8 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
|
|||||||
VoiceDTO voiceDTO = new VoiceDTO();
|
VoiceDTO voiceDTO = new VoiceDTO();
|
||||||
voiceDTO.setId(entity.getId());
|
voiceDTO.setId(entity.getId());
|
||||||
voiceDTO.setName(MessageUtils.getMessage(ErrorCode.VOICE_CLONE_PREFIX) + entity.getName());
|
voiceDTO.setName(MessageUtils.getMessage(ErrorCode.VOICE_CLONE_PREFIX) + entity.getName());
|
||||||
|
// 保留从数据库查询到的voiceDemo字段
|
||||||
|
voiceDTO.setVoiceDemo(entity.getVoiceDemo());
|
||||||
redisUtils.set(RedisKeys.getTimbreNameById(voiceDTO.getId()), voiceDTO.getName(),
|
redisUtils.set(RedisKeys.getTimbreNameById(voiceDTO.getId()), voiceDTO.getName(),
|
||||||
RedisUtils.NOT_EXPIRE);
|
RedisUtils.NOT_EXPIRE);
|
||||||
voiceDTOs.add(0, voiceDTO);
|
voiceDTOs.add(0, voiceDTO);
|
||||||
@@ -205,6 +211,9 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
|
|||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new VoiceDTO(list.get(0).getId(), list.get(0).getName());
|
TimbreEntity entity = list.get(0);
|
||||||
|
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
|
||||||
|
dto.setVoiceDemo(entity.getVoiceDemo());
|
||||||
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
@@ -165,6 +165,9 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
|
|||||||
dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername());
|
dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保trainStatus字段被正确设置,前端需要这个字段来判断是否为克隆音频
|
||||||
|
dto.setTrainStatus(entity.getTrainStatus());
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +201,9 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
|
|||||||
dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername());
|
dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保trainStatus字段被正确设置,前端需要这个字段来判断是否为克隆音频
|
||||||
|
dto.setTrainStatus(entity.getTrainStatus());
|
||||||
|
|
||||||
// 设置是否有音频数据
|
// 设置是否有音频数据
|
||||||
dto.setHasVoice(entity.getVoice() != null);
|
dto.setHasVoice(entity.getVoice() != null);
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@
|
|||||||
10155=Thiếu cấu hình Huoshan Engine
|
10155=Thiếu cấu hình Huoshan Engine
|
||||||
10156=Lỗi định dạng phản hồi, thiếu trường BaseResp
|
10156=Lỗi định dạng phản hồi, thiếu trường BaseResp
|
||||||
10157=Yêu cầu thất bại
|
10157=Yêu cầu thất bại
|
||||||
10158=Nhân bản giọng nói:
|
10158=Nhân bản âm sắc:
|
||||||
10159=ID giọng nói đã tồn tại
|
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_
|
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
|
10161=Địa chỉ Mac đã tồn tại
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<mapper namespace="xiaozhi.modules.voiceclone.dao.VoiceCloneDao">
|
<mapper namespace="xiaozhi.modules.voiceclone.dao.VoiceCloneDao">
|
||||||
<select id="getTrainSuccess" resultType="xiaozhi.modules.model.dto.VoiceDTO">
|
<select id="getTrainSuccess" resultType="xiaozhi.modules.model.dto.VoiceDTO">
|
||||||
select id, name
|
select id, name, voice_id as voiceDemo
|
||||||
from ai_voice_clone
|
from ai_voice_clone
|
||||||
where model_id = #{modelId} and user_id = #{userId} and train_status = 2
|
where model_id = #{modelId} and user_id = #{userId} and train_status = 2
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ export default {
|
|||||||
'dictManagement.pageTitle': 'Wörterbuchverwaltung',
|
'dictManagement.pageTitle': 'Wörterbuchverwaltung',
|
||||||
'dictManagement.searchPlaceholder': 'Bitte Wörterbuchwert-Label zur Suche eingeben',
|
'dictManagement.searchPlaceholder': 'Bitte Wörterbuchwert-Label zur Suche eingeben',
|
||||||
'dictManagement.search': 'Suchen',
|
'dictManagement.search': 'Suchen',
|
||||||
'dictManagement.dictTypeName': 'Wörterbuchtyp-Name',
|
'dictManagement.dictTypeName': 'WDT-Name',
|
||||||
'dictManagement.operation': 'Operation',
|
'dictManagement.operation': 'Operation',
|
||||||
'dictManagement.edit': 'Bearbeiten',
|
'dictManagement.edit': 'Bearbeiten',
|
||||||
'dictManagement.dictLabel': 'Wörterbuch-Label',
|
'dictManagement.dictLabel': 'Wörterbuch-Label',
|
||||||
@@ -532,10 +532,10 @@ export default {
|
|||||||
'dictManagement.delete': 'Löschen',
|
'dictManagement.delete': 'Löschen',
|
||||||
'dictManagement.selectAll': 'Alle auswählen',
|
'dictManagement.selectAll': 'Alle auswählen',
|
||||||
'dictManagement.deselectAll': 'Alle abwählen',
|
'dictManagement.deselectAll': 'Alle abwählen',
|
||||||
'dictManagement.addDictType': 'Wörterbuchtyp hinzufügen',
|
'dictManagement.addDictType': 'WDT hinzufügen',
|
||||||
'dictManagement.batchDeleteDictType': 'Wörterbuchtypen massenhaft löschen',
|
'dictManagement.batchDeleteDictType': 'WDT massenhaft löschen',
|
||||||
'dictManagement.addDictData': 'Wörterbuchdaten hinzufügen',
|
'dictManagement.addDictData': 'WDT hinzufügen',
|
||||||
'dictManagement.batchDeleteDictData': 'Wörterbuchdaten massenhaft löschen',
|
'dictManagement.batchDeleteDictData': 'WDT massenhaft löschen',
|
||||||
'dictManagement.itemsPerPage': '{items} Einträge/Seite',
|
'dictManagement.itemsPerPage': '{items} Einträge/Seite',
|
||||||
'dictManagement.firstPage': 'Erste Seite',
|
'dictManagement.firstPage': 'Erste Seite',
|
||||||
'dictManagement.prevPage': 'Vorherige Seite',
|
'dictManagement.prevPage': 'Vorherige Seite',
|
||||||
@@ -810,7 +810,7 @@ export default {
|
|||||||
'modelConfig.duplicate': 'Duplizieren',
|
'modelConfig.duplicate': 'Duplizieren',
|
||||||
'modelConfig.delete': 'Löschen',
|
'modelConfig.delete': 'Löschen',
|
||||||
'modelConfig.deselectAll': 'Alle abwählen',
|
'modelConfig.deselectAll': 'Alle abwählen',
|
||||||
'modelConfig.select': 'Auswählen',
|
'modelConfig.select': 'ausw.',
|
||||||
'modelConfig.selectAll': 'Alle auswählen',
|
'modelConfig.selectAll': 'Alle auswählen',
|
||||||
'modelConfig.add': 'Neu hinzufügen',
|
'modelConfig.add': 'Neu hinzufügen',
|
||||||
'modelConfig.selectModelsFirst': 'Bitte wählen Sie zuerst Modelle zum Löschen aus',
|
'modelConfig.selectModelsFirst': 'Bitte wählen Sie zuerst Modelle zum Löschen aus',
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default {
|
|||||||
'header.smartManagement': 'Tác nhân AI',
|
'header.smartManagement': 'Tác nhân AI',
|
||||||
'header.modelConfig': 'Mô hình',
|
'header.modelConfig': 'Mô hình',
|
||||||
'header.knowledgeBase': 'Kiến thức',
|
'header.knowledgeBase': 'Kiến thức',
|
||||||
'header.voiceCloneManagement': 'Nhân bản giọng',
|
'header.voiceCloneManagement': 'NBAS',
|
||||||
'header.voiceResourceManagement': 'Tài nguyên giọng nói',
|
'header.voiceResourceManagement': 'Tài nguyên giọng nói',
|
||||||
'header.userManagement': 'Người dùng',
|
'header.userManagement': 'Người dùng',
|
||||||
'header.otaManagement': 'Quản lý OTA',
|
'header.otaManagement': 'Quản lý OTA',
|
||||||
@@ -1043,7 +1043,7 @@ export default {
|
|||||||
'sm2.publicKeyRetryFailed': 'Thử lấy lại khóa công khai thất bại',
|
'sm2.publicKeyRetryFailed': 'Thử lấy lại khóa công khai thất bại',
|
||||||
|
|
||||||
// Voice Clone and Resource Management
|
// Voice Clone and Resource Management
|
||||||
'voiceClone.title': 'Nhân bản giọng nói',
|
'voiceClone.title': 'Nhân bản âm sắc',
|
||||||
'voiceResource.title': 'Tài nguyên giọng nói',
|
'voiceResource.title': 'Tài nguyên giọng nói',
|
||||||
'voiceClone.platformName': 'Tên nền tảng',
|
'voiceClone.platformName': 'Tên nền tảng',
|
||||||
'voiceClone.voiceId': 'ID giọng nói',
|
'voiceClone.voiceId': 'ID giọng nói',
|
||||||
@@ -1095,7 +1095,7 @@ export default {
|
|||||||
'voiceClone.totalRecords': 'Tổng cộng {total} bản ghi',
|
'voiceClone.totalRecords': 'Tổng cộng {total} bản ghi',
|
||||||
'voiceClone.noVoiceCloneAssigned': 'Tài khoản của bạn không được chỉ định tài nguyên giọng nói',
|
'voiceClone.noVoiceCloneAssigned': 'Tài khoản của bạn không được chỉ định tài nguyên giọng nói',
|
||||||
'voiceClone.contactAdmin': 'Vui lòng liên hệ quản trị viên để được chỉ định tài nguyên giọng nói',
|
'voiceClone.contactAdmin': 'Vui lòng liên hệ quản trị viên để được chỉ định tài nguyên giọng nói',
|
||||||
'voiceClone.dialogTitle': 'Nhân bản giọng nói',
|
'voiceClone.dialogTitle': 'Nhân bản âm sắc',
|
||||||
'voiceClone.stepUpload': 'Chuẩn bị âm thanh',
|
'voiceClone.stepUpload': 'Chuẩn bị âm thanh',
|
||||||
'voiceClone.stepEdit': 'Chỉnh sửa âm thanh',
|
'voiceClone.stepEdit': 'Chỉnh sửa âm thanh',
|
||||||
'voiceClone.dragOrClick': 'Kéo tệp âm thanh vào đây hoặc nhấp để tải lên',
|
'voiceClone.dragOrClick': 'Kéo tệp âm thanh vào đây hoặc nhấp để tải lên',
|
||||||
|
|||||||
@@ -16,3 +16,7 @@ select:-webkit-autofill:focus {
|
|||||||
.el-footer {
|
.el-footer {
|
||||||
height: 35px !important; /* 使用 !important 确保覆盖默认样式 */
|
height: 35px !important; /* 使用 !important 确保覆盖默认样式 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-icon-video-play, .el-icon-video-pause {
|
||||||
|
font-size: 18px !important;
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column :label="$t('voiceClone.Details')" align="center" width="80">
|
<el-table-column :label="$t('voiceClone.Details')" align="center" width="120">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tooltip :content="getTooltipContent(scope.row)" placement="top">
|
<el-tooltip :content="getTooltipContent(scope.row)" placement="top">
|
||||||
<el-button size="mini" type="text" icon="el-icon-info"
|
<el-button size="mini" type="text" icon="el-icon-info"
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #3d4566;
|
color: #3d4566;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-welcome {
|
.login-welcome {
|
||||||
@@ -36,11 +38,11 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
right: 18%;
|
right: 15%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 35px 0;
|
padding: 35px 0;
|
||||||
width: 450px;
|
width: 550px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -726,10 +726,11 @@ class ConnectionHandler:
|
|||||||
self.logger.bind(tag=TAG).info(f"大模型收到用户消息: {query}")
|
self.logger.bind(tag=TAG).info(f"大模型收到用户消息: {query}")
|
||||||
self.llm_finish_task = False
|
self.llm_finish_task = False
|
||||||
|
|
||||||
# 为最顶层时新建会话ID和发送FIRST请求
|
# depth!=0目前只能表示是非用户发起的请求,与对话逻辑无关,这里所有tts对话都应该发送FIRST和LAST,没有例外
|
||||||
if depth == 0:
|
if depth == 0:
|
||||||
self.sentence_id = str(uuid.uuid4().hex)
|
|
||||||
self.dialogue.put(Message(role="user", content=query))
|
self.dialogue.put(Message(role="user", content=query))
|
||||||
|
# 发送开始标记
|
||||||
|
self.sentence_id = str(uuid.uuid4().hex)
|
||||||
self.tts.tts_text_queue.put(
|
self.tts.tts_text_queue.put(
|
||||||
TTSMessageDTO(
|
TTSMessageDTO(
|
||||||
sentence_id=self.sentence_id,
|
sentence_id=self.sentence_id,
|
||||||
@@ -826,6 +827,14 @@ class ConnectionHandler:
|
|||||||
content_detail=content,
|
content_detail=content,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# 发送结束标记
|
||||||
|
self.tts.tts_text_queue.put(
|
||||||
|
TTSMessageDTO(
|
||||||
|
sentence_id=self.sentence_id,
|
||||||
|
sentence_type=SentenceType.LAST,
|
||||||
|
content_type=ContentType.ACTION,
|
||||||
|
)
|
||||||
|
)
|
||||||
# 处理function call
|
# 处理function call
|
||||||
if tool_call_flag:
|
if tool_call_flag:
|
||||||
bHasError = False
|
bHasError = False
|
||||||
@@ -879,14 +888,7 @@ class ConnectionHandler:
|
|||||||
text_buff = "".join(response_message)
|
text_buff = "".join(response_message)
|
||||||
self.tts_MessageText = text_buff
|
self.tts_MessageText = text_buff
|
||||||
self.dialogue.put(Message(role="assistant", content=text_buff))
|
self.dialogue.put(Message(role="assistant", content=text_buff))
|
||||||
if depth == 0:
|
|
||||||
self.tts.tts_text_queue.put(
|
|
||||||
TTSMessageDTO(
|
|
||||||
sentence_id=self.sentence_id,
|
|
||||||
sentence_type=SentenceType.LAST,
|
|
||||||
content_type=ContentType.ACTION,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.llm_finish_task = True
|
self.llm_finish_task = True
|
||||||
# 使用lambda延迟计算,只有在DEBUG级别时才执行get_llm_dialogue()
|
# 使用lambda延迟计算,只有在DEBUG级别时才执行get_llm_dialogue()
|
||||||
self.logger.bind(tag=TAG).debug(
|
self.logger.bind(tag=TAG).debug(
|
||||||
|
|||||||
Reference in New Issue
Block a user