Skip to content

Commit ccd5aad

Browse files
committed
feat:update tts module
1 parent b608537 commit ccd5aad

File tree

20 files changed

+540
-185
lines changed

20 files changed

+540
-185
lines changed

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ mysql,redis,emqx和influxdb环境。
8888
欢迎加入群聊一起交流讨论有关Aiot相关的话题,免费获取智控台的前端源码,链接过期了可以issue或email提醒一下作者。
8989

9090
<div style="width: 250px;margin: 0 auto;">
91-
<img src="./images/c2cfd1c5bbbe84e9d5892823f7dc6789.jpg" width="250px"/>
91+
<img src="./images/f1d07cf6a241ec0ac1601643364be3df.jpg" width="250px"/>
9292
</div>
9393

9494

-167 KB
Binary file not shown.
164 KB
Loading

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@
263263
<artifactId>websdk-java-speech</artifactId>
264264
<version>2.0.3</version>
265265
</dependency>
266+
<dependency>
267+
<groupId>io.github.whitemagic2014</groupId>
268+
<artifactId>tts-edge-java</artifactId>
269+
<version>1.2.6</version>
270+
</dependency>
266271
<dependency>
267272
<groupId>dev.langchain4j</groupId>
268273
<artifactId>langchain4j</artifactId>

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ mysql,redis,emqx和influxdb环境,安装详情请看官方文档。
116116
欢迎加入群聊一起交流讨论有关Aiot相关的话题,免费获取智控台的前端源码,链接过期了可以issue或email提醒一下作者。
117117

118118
<div style="width: 250px;margin: 0 auto;">
119-
<img src="./docs/images/c2cfd1c5bbbe84e9d5892823f7dc6789.jpg" width="250px"/>
119+
<img src="./docs/images/f1d07cf6a241ec0ac1601643364be3df.jpg" width="250px"/>
120120
</div>
121121

122122
## 致谢

src/main/java/top/rslly/iot/services/agent/AiServiceImpl.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,17 @@
2828
import org.springframework.web.multipart.MultipartFile;
2929
import top.rslly.iot.param.request.AiControl;
3030
import top.rslly.iot.services.SafetyServiceImpl;
31-
import top.rslly.iot.services.agent.AiService;
3231
import top.rslly.iot.services.thingsModel.ProductServiceImpl;
3332
import top.rslly.iot.utility.JwtTokenUtil;
3433
import top.rslly.iot.utility.MyFileUtil;
3534
import top.rslly.iot.utility.RedisUtil;
3635
import top.rslly.iot.utility.ai.chain.Router;
3736
import top.rslly.iot.utility.ai.llm.LLMFactory;
38-
import top.rslly.iot.utility.ai.mcp.McpProtocolSend;
3937
import top.rslly.iot.utility.ai.mcp.McpWebsocket;
40-
import top.rslly.iot.utility.ai.mcp.McpWebsocketEndpoint;
4138
import top.rslly.iot.utility.ai.voice.Audio2Text;
42-
import top.rslly.iot.utility.ai.voice.Text2audio;
39+
import top.rslly.iot.utility.ai.voice.AudioUtils;
40+
import top.rslly.iot.utility.ai.voice.TTS.Text2audio;
41+
import top.rslly.iot.utility.ai.voice.TTS.TtsService;
4342
import top.rslly.iot.utility.result.JsonResult;
4443
import top.rslly.iot.utility.result.ResultCode;
4544
import top.rslly.iot.utility.result.ResultTool;
@@ -66,7 +65,7 @@ public class AiServiceImpl implements AiService {
6665
@Autowired
6766
private Router router;
6867
@Autowired
69-
private Text2audio text2audio;
68+
private TtsService text2audio;
7069
@Autowired
7170
private Audio2Text audio2Text;
7271
@Autowired
@@ -126,7 +125,7 @@ public JsonResult<?> getAiResponse(boolean tts, boolean stream, int productId,
126125
aiResponse.put("text", answer);
127126
if (tts) {
128127
var audio = Text2audio.synthesizeAndSaveAudio(answer).array();
129-
audio = Text2audio.VoiceBitChange(audio);
128+
audio = AudioUtils.VoiceBitChange(audio);
130129
if (!stream)
131130
aiResponse.put("audio", Base64.getEncoder().encodeToString(audio));
132131
else

src/main/java/top/rslly/iot/utility/ai/llm/LLMFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ else if (llmName.contains("think")) {
104104
return new DeepSeek("https://dashscope.aliyuncs.com/compatible-mode",
105105
"qwen3-next-80b-a3b-instruct",
106106
dashScopeApiKey);
107+
} else if (llmName.equals("dashscope-Qwen3-max")) {
108+
return new DeepSeek("https://dashscope.aliyuncs.com/compatible-mode",
109+
"qwen3-max",
110+
dashScopeApiKey);
107111
} else if (llmName.startsWith("silicon-Qwen3-30B-A3B")) {
108112
return new Qwen3(siliconFlowApiKey, "Qwen/Qwen3-30B-A3B", enableThinking, thinkingBudget);
109113
} else if (llmName.startsWith("silicon-Qwen3-235B-A22B")) {

src/main/java/top/rslly/iot/utility/ai/mcp/McpAgent.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,18 @@ public String run(String question, Map<String, Object> globalMessage) {
260260
client.close();
261261
}
262262
clientMap.clear();
263+
// 超出迭代轮次,调用模型进行总结
264+
String summaryPrompt = "请根据以上对话历史和最终观察结果,用中文总结回答最初的问题: " + question;
265+
messages.clear();
266+
messages.add(new ModelMessage(ModelMessageRole.SYSTEM.value(), summaryPrompt));
267+
messages.add(new ModelMessage(ModelMessageRole.USER.value(), conversationPrompt.toString()));
268+
269+
try {
270+
toolResult = LLMFactory.getLLM(llmName).commonChat(summaryPrompt, messages, false);
271+
} catch (Exception e) {
272+
log.error("Error generating summary after max iterations: ", e);
273+
toolResult = "经过多次尝试仍未找到完整答案,请重新提问或提供更多细节。";
274+
}
263275
if (queue != null) {
264276
queue.add(toolResult);
265277
if (!mcpIsTool)

src/main/java/top/rslly/iot/utility/ai/toolAgent/Agent.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ public String run(String question, Map<String, Object> globalMessage) {
109109
}
110110
iteration += 1;
111111
}
112+
// 超出迭代轮次,调用模型进行总结
113+
String summaryPrompt = "请根据以上对话历史和最终观察结果,用中文总结回答最初的问题: " + question;
114+
messages.clear();
115+
messages.add(new ModelMessage(ModelMessageRole.SYSTEM.value(), summaryPrompt));
116+
messages.add(new ModelMessage(ModelMessageRole.USER.value(), conversationPrompt.toString()));
117+
118+
try {
119+
toolResult = LLMFactory.getLLM(llmName).commonChat(summaryPrompt, messages, false);
120+
} catch (Exception e) {
121+
log.error("Error generating summary after max iterations: ", e);
122+
toolResult = "经过多次尝试仍未找到完整答案,请重新提问或提供更多细节。";
123+
}
112124
if (queue != null) {
113125
queue.add(toolResult);
114126
queue.add("[DONE]");

src/main/java/top/rslly/iot/utility/ai/tools/GoodByeTool.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
import lombok.extern.slf4j.Slf4j;
2424
import org.springframework.beans.factory.annotation.Autowired;
2525
import org.springframework.stereotype.Component;
26-
import top.rslly.iot.utility.ai.voice.Text2audio;
26+
import top.rslly.iot.utility.ai.voice.TTS.Text2audio;
27+
import top.rslly.iot.utility.ai.voice.TTS.TtsServiceFactory;
2728
import top.rslly.iot.utility.smartVoice.XiaoZhiWebsocket;
2829

2930
import java.io.IOException;
@@ -34,7 +35,7 @@
3435
@Slf4j
3536
public class GoodByeTool implements BaseTool<String> {
3637
@Autowired
37-
private Text2audio text2audio;
38+
private TtsServiceFactory ttsServiceFactory;
3839

3940
private String name = "goodByeTool";
4041
private String description = """
@@ -91,7 +92,7 @@ public String run(String question, Map<String, Object> globalMessage) {
9192
session.getBasicRemote()
9293
.sendText("{\"type\": \"tts\", \"state\": \"sentence_start\", \"text\": \""
9394
+ message + "\"}");
94-
text2audio.websocketAudioSync(message, session, chatId, productId);
95+
ttsServiceFactory.websocketAudioSync(message, session, chatId, productId);
9596
session.close();
9697
} catch (IOException e) {
9798
e.printStackTrace();

0 commit comments

Comments
 (0)