Skip to content

Commit 0d8cd39

Browse files
committed
update:更新coze和dify模型大小写名称导致查询错误问题
update:阿里云语音识别高并发处理
1 parent 7d200c8 commit 0d8cd39

File tree

7 files changed

+86
-21
lines changed

7 files changed

+86
-21
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ Xiaozhi ESP32 Server Java 是基于 [Xiaozhi ESP32](https://github.com/78/xiaozh
8080
| **实时打断** || 支持实时打断功能,提高对话流畅度 |
8181
| **本地离线识别** || 支持Vosk本地离线语音识别,无需联网即可使用 |
8282
| **WebSocket通信** || 高性能WebSocket通信,支持设备实时状态更新和控制 |
83-
| **MQTT通信** || 支持MQTT通信协议,实现设备间的消息传递 |
84-
| **自动语音唤醒** || 支持自定义唤醒词,无需按键即可激活设备 |
83+
| **MQTT通信** || 支持MQTT通信协议,长连接、服务端主动唤醒 |
84+
| **自动语音唤醒** || 支持自定义唤醒词唤醒,无需按键即可激活设备 |
8585
| **多设备同时接入** || 支持多设备同时接入,实现全屋语音覆盖 |
8686
| **TTS多引擎支持** || 支持微软、阿里、火山等多种TTS引擎 |
8787
| **多用户支持** || 支持多用户配置,满足家庭多成员使用需求 |

docs/images/wechat_group.jpg

-159 KB
Binary file not shown.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@
225225
<dependency>
226226
<groupId>com.alibaba</groupId>
227227
<artifactId>dashscope-sdk-java</artifactId>
228-
<version>2.19.1</version>
228+
<version>2.20.2</version>
229229
</dependency>
230230
<!-- COZE -->
231231
<dependency>

src/main/java/com/xiaozhi/dialogue/llm/providers/CozeChatModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class CozeChatModel implements ChatModel {
3838
private final String appId;
3939
private final String apiSecret;
4040
private final Logger logger = LoggerFactory.getLogger(getClass());
41-
public static final String PROVIDER_NAME = "Coze";
41+
public static final String PROVIDER_NAME = "coze";
4242

4343
/**
4444
* 构造函数

src/main/java/com/xiaozhi/dialogue/stt/providers/AliyunSttService.java

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,37 @@ public class AliyunSttService implements SttService {
2828
private static final int QUEUE_CAPACITY = 1000; // 队列容量限制
2929
private static final String DEFAULT_MODEL = "paraformer-realtime-v2"; // 默认模型
3030

31-
// 复用识别器实例,避免频繁创建
32-
private final Recognition recognizer;
31+
// 识别器实例
32+
private Recognition recognizer;
3333
private String apiKey;
34+
private final Object recognizerLock = new Object(); // 用于同步访问recognizer
3435

3536
public AliyunSttService(SysConfig config) {
3637
this.apiKey = config.getApiKey();
37-
this.recognizer = new Recognition();
38+
// 初始化recognizer
39+
createNewRecognizer();
40+
}
41+
42+
/**
43+
* 创建新的Recognition实例
44+
*/
45+
private void createNewRecognizer() {
46+
synchronized (recognizerLock) {
47+
// 如果存在旧的实例,尝试关闭它
48+
if (recognizer != null) {
49+
try {
50+
if (recognizer.getDuplexApi() != null) {
51+
recognizer.getDuplexApi().close(1000, "创建新实例");
52+
}
53+
} catch (Exception e) {
54+
logger.warn("关闭旧的Recognition实例时出错", e);
55+
}
56+
}
57+
58+
// 创建新实例
59+
recognizer = new Recognition();
60+
logger.info("创建了新的Recognition实例");
61+
}
3862
}
3963

4064
@Override
@@ -61,6 +85,13 @@ public String streamRecognition(Sinks.Many<byte[]> audioSink) {
6185
AtomicBoolean isCompleted = new AtomicBoolean(false);
6286
AtomicReference<String> finalResult = new AtomicReference<>("");
6387
AtomicBoolean isProcessing = new AtomicBoolean(true);
88+
AtomicBoolean recognizerFailed = new AtomicBoolean(false);
89+
90+
// 获取当前的recognizer实例
91+
Recognition currentRecognizer;
92+
synchronized (recognizerLock) {
93+
currentRecognizer = this.recognizer;
94+
}
6495

6596
// 订阅Sink并将数据放入队列
6697
var subscription = audioSink.asFlux().subscribe(
@@ -126,7 +157,7 @@ public String streamRecognition(Sinks.Many<byte[]> audioSink) {
126157
// 保存中间结果,用于跟踪识别进度
127158
StringBuilder fullText = new StringBuilder();
128159

129-
recognizer.streamCall(param, rxAudioStream)
160+
currentRecognizer.streamCall(param, rxAudioStream)
130161
.blockingForEach(result -> {
131162
if (result != null && result.getSentence() != null) {
132163
String text = result.getSentence().getText();
@@ -138,7 +169,7 @@ public String streamRecognition(Sinks.Many<byte[]> audioSink) {
138169

139170
// 记录中间结果,便于调试
140171
if (logger.isDebugEnabled()) {
141-
logger.info("语音识别中间结果: {}", text);
172+
logger.debug("语音识别中间结果: {}", text);
142173
}
143174
}
144175
}
@@ -147,9 +178,26 @@ public String streamRecognition(Sinks.Many<byte[]> audioSink) {
147178
logger.info("语音识别完成,最终结果: {}", finalResult.get());
148179
} catch (Exception e) {
149180
logger.error("阿里云流式语音识别失败", e);
181+
recognizerFailed.set(true); // 标记识别器失败
150182
} finally {
151183
isProcessing.set(false);
152184
subscription.dispose(); // 清理资源
185+
186+
// 如果识别过程中出现异常,需要重置recognizer
187+
if (recognizerFailed.get()) {
188+
try {
189+
// 关闭WebSocket连接
190+
if (currentRecognizer.getDuplexApi() != null) {
191+
currentRecognizer.getDuplexApi().close(1000, "bye");
192+
logger.info("已关闭失败的WebSocket连接");
193+
}
194+
195+
// 创建新的实例替代当前实例
196+
createNewRecognizer();
197+
} catch (Exception ex) {
198+
logger.error("处理失败的Recognition实例时出错", ex);
199+
}
200+
}
153201
}
154202
});
155203

@@ -160,11 +208,28 @@ public String streamRecognition(Sinks.Many<byte[]> audioSink) {
160208
if (isProcessing.get()) {
161209
logger.warn("语音识别超时,强制结束");
162210
isProcessing.set(false);
211+
recognizerFailed.set(true); // 超时也视为失败,需要重置
163212
}
164213

165214
} catch (Exception e) {
166215
logger.error("启动虚拟线程失败", e);
167216
subscription.dispose(); // 确保资源被释放
217+
218+
// 线程启动失败也视为识别器失败
219+
recognizerFailed.set(true);
220+
221+
// 处理失败的识别器
222+
try {
223+
// 关闭WebSocket连接
224+
if (currentRecognizer.getDuplexApi() != null) {
225+
currentRecognizer.getDuplexApi().close(1000, "bye");
226+
}
227+
228+
// 创建新的实例替代
229+
createNewRecognizer();
230+
} catch (Exception ex) {
231+
logger.error("处理失败的Recognition实例时出错", ex);
232+
}
168233
}
169234

170235
return finalResult.get();

web/src/components/ConfigManager.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export default {
202202
{ label: 'Ollama', value: 'ollama', key: '1' },
203203
{ label: 'Spark', value: 'spark', key: '2' },
204204
{ label: 'Zhipu', value: 'zhipu', key: '3' },
205-
{ label: 'Ali', value: 'ali', key: '4'},
205+
{ label: 'AliYun', value: 'aliyun', key: '4'},
206206
{ label: 'Doubao', value: 'doubao', key: '5'},
207207
{ label: 'DeepSeek', value: 'deepseek', key: '6'},
208208
{ label: 'ChatGLM', value: 'chatglm', key: '7'},

web/src/views/page/config/Agent.vue

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ export default {
122122
},
123123
// 平台选项
124124
providerOptions: [
125-
{ label: 'Coze', value: 'Coze' },
126-
{ label: 'Dify', value: 'Dify' }
125+
{ label: 'Coze', value: 'coze' },
126+
{ label: 'Dify', value: 'dify' }
127127
],
128128
// 表格列定义
129129
tableColumns: [
@@ -162,34 +162,34 @@ export default {
162162
type: 'select',
163163
placeholder: '请选择平台类型',
164164
options: [
165-
{ label: 'Coze', value: 'Coze' },
166-
{ label: 'Dify', value: 'Dify' }
165+
{ label: 'Coze', value: 'coze' },
166+
{ label: 'Dify', value: 'dify' }
167167
]
168168
},
169169
{
170170
field: 'appId',
171171
label: 'Space ID',
172172
placeholder: '请输入Coze Space ID',
173-
condition: { field: 'provider', value: 'Coze' }
173+
condition: { field: 'provider', value: 'coze' }
174174
},
175175
{
176176
field: 'apiSecret',
177177
label: 'Secret token',
178178
placeholder: '请输入Secret token',
179-
condition: { field: 'provider', value: 'Coze' }
179+
condition: { field: 'provider', value: 'coze' }
180180
},
181181
{
182182
field: 'apiUrl',
183183
label: 'apiUrl',
184184
placeholder: '请输入apiUrl',
185-
condition: { field: 'provider', value: 'Dify' },
185+
condition: { field: 'provider', value: 'dify' },
186186
suffix: '/chat_message'
187187
},
188188
{
189189
field: 'apiKey',
190190
label: 'apiKey',
191191
placeholder: '请输入apiKey',
192-
condition: { field: 'provider', value: 'Dify' }
192+
condition: { field: 'provider', value: 'dify' }
193193
},
194194
],
195195
@@ -211,7 +211,7 @@ export default {
211211
const columns = [...this.tableColumns];
212212
213213
// 如果当前选择的是Coze平台,则插入智能体ID列
214-
if (this.query.provider === 'Coze') {
214+
if (this.query.provider === 'coze') {
215215
const botIdColumn = {
216216
title: '智能体ID',
217217
dataIndex: 'botId',
@@ -232,7 +232,7 @@ export default {
232232
watch: {
233233
// 监听平台类型变化,根据不同平台设置不同的默认值
234234
'platformForm.provider': function(newVal) {
235-
if (newVal === 'Dify') {
235+
if (newVal === 'dify') {
236236
// 如果切换到Dify平台,设置默认的apiUrl
237237
this.platformForm.apiUrl = 'https://api.dify.ai/v1';
238238
}
@@ -292,7 +292,7 @@ export default {
292292
this.platformModalLoading = true;
293293
294294
// 如果是Dify平台,确保apiUrl有正确的后缀
295-
if (this.platformForm.provider === 'Dify' && this.platformForm.apiUrl) {
295+
if (this.platformForm.provider === 'dify' && this.platformForm.apiUrl) {
296296
// 确保URL末尾没有斜杠
297297
let baseUrl = this.platformForm.apiUrl;
298298
if (baseUrl.endsWith('/')) {

0 commit comments

Comments
 (0)