feat(service): 新增 WebSocket 实时语音转写与流式 TTS 全流程
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -39,3 +39,10 @@ build/
|
|||||||
/.dockerignore
|
/.dockerignore
|
||||||
/Dockerfile
|
/Dockerfile
|
||||||
/.claude/ralph-loop.local.md
|
/.claude/ralph-loop.local.md
|
||||||
|
/deepgramAPI.md
|
||||||
|
/elevenLabs-websocketAPI.md
|
||||||
|
/elevenlabsAPI.md
|
||||||
|
/Getting Started with Flux.md
|
||||||
|
/voice-optimization-plan.md
|
||||||
|
/docs/websocket-api.md
|
||||||
|
/src/main/resources/static/ws-test.html
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
"/user/bindInviteCode",
|
"/user/bindInviteCode",
|
||||||
"/themes/listAllStyles",
|
"/themes/listAllStyles",
|
||||||
"/wallet/transactions",
|
"/wallet/transactions",
|
||||||
"/themes/restore"
|
"/themes/restore",
|
||||||
|
"/chat/message"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -45,6 +45,20 @@ public class ChatController {
|
|||||||
private ChatService chatService;
|
private ChatService chatService;
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/message")
|
||||||
|
@Operation(summary = "同步对话", description = "发送消息给大模型,同步返回回复")
|
||||||
|
public BaseResponse<String> message(@RequestParam("content") String content) {
|
||||||
|
if (StrUtil.isBlank(content)) {
|
||||||
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "消息内容不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
String userId = StpUtil.getLoginIdAsString();
|
||||||
|
String response = chatService.message(content, userId);
|
||||||
|
|
||||||
|
return ResultUtils.success(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/talk")
|
@PostMapping("/talk")
|
||||||
@Operation(summary = "聊天润色接口", description = "聊天润色接口")
|
@Operation(summary = "聊天润色接口", description = "聊天润色接口")
|
||||||
public Flux<ServerSentEvent<ChatStreamMessage>> talk(@RequestBody ChatReq chatReq){
|
public Flux<ServerSentEvent<ChatStreamMessage>> talk(@RequestBody ChatReq chatReq){
|
||||||
|
|||||||
@@ -11,4 +11,13 @@ import reactor.core.publisher.Flux;
|
|||||||
*/
|
*/
|
||||||
public interface ChatService {
|
public interface ChatService {
|
||||||
Flux<ServerSentEvent<ChatStreamMessage>> talk(ChatReq chatReq);
|
Flux<ServerSentEvent<ChatStreamMessage>> talk(ChatReq chatReq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步对话
|
||||||
|
*
|
||||||
|
* @param content 用户消息内容
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return AI 响应
|
||||||
|
*/
|
||||||
|
String message(String content, String userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,4 +321,42 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步对话
|
||||||
|
*
|
||||||
|
* @param content 用户消息内容
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return AI 响应
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String message(String content, String userId) {
|
||||||
|
log.info("同步对话请求, userId: {}, content: {}", userId, content);
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
String systemPrompt = """
|
||||||
|
ROLE: You are "Tiffany", a 17-year-old popular high school student from Beverly Hills.
|
||||||
|
You are sassy, judgmental, impatient, but secretly caring.
|
||||||
|
|
||||||
|
TASK: Generate dialogue scripts optimized for ElevenLabs TTS.
|
||||||
|
Use emotional cues in brackets like [sighs], [giggles], [scoffs], [whispers], [yells].
|
||||||
|
Use punctuation for tone: ... for hesitation, ! for energy.
|
||||||
|
Use fillers naturally: "like", "literally", "omg".
|
||||||
|
|
||||||
|
Keep responses concise (2-3 sentences max) for real-time conversation.
|
||||||
|
""";
|
||||||
|
|
||||||
|
String response = client
|
||||||
|
.prompt()
|
||||||
|
.system(systemPrompt)
|
||||||
|
.user(content)
|
||||||
|
.call()
|
||||||
|
.content();
|
||||||
|
|
||||||
|
long duration = System.currentTimeMillis() - startTime;
|
||||||
|
log.info("同步对话完成, userId: {}, 耗时: {}ms, 响应长度: {}", userId, duration, response.length());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,15 @@ dromara:
|
|||||||
bucket-name: keyborad-resource #桶名称
|
bucket-name: keyborad-resource #桶名称
|
||||||
domain: https://resource.loveamorkey.com/ # 访问域名,注意末尾的'/',例如:https://abcd.s3.ap-east-1.amazonaws.com/
|
domain: https://resource.loveamorkey.com/ # 访问域名,注意末尾的'/',例如:https://abcd.s3.ap-east-1.amazonaws.com/
|
||||||
base-path: avatar/ # 基础路径
|
base-path: avatar/ # 基础路径
|
||||||
|
- platform: cloudflare-r2-apac # 存储平台标识
|
||||||
|
enable-storage: true # 启用存储
|
||||||
|
access-key: 550b33cc4d53e05c2e438601f8a0e209
|
||||||
|
secret-key: df4d529cdae44e6f614ca04f4dc0f1f9a299e57367181243e8abdc7f7c28e99a
|
||||||
|
region: APAC # 区域
|
||||||
|
end-point: https://b632a61caa85401f63c9b32eef3a74c8.r2.cloudflarestorage.com/keyboardtest # 端点
|
||||||
|
bucket-name: keyboardtest #桶名称
|
||||||
|
domain: https://cdn.loveamorkey.com/ # 访问域名,注意末尾的'/',例如:https://abcd.s3.ap-east-1.amazonaws.com/
|
||||||
|
base-path: / # 基础路径
|
||||||
|
|
||||||
############## Sa-Token 配置 (参考文档: https://sa-token.cc) ##############
|
############## Sa-Token 配置 (参考文档: https://sa-token.cc) ##############
|
||||||
sa-token:
|
sa-token:
|
||||||
|
|||||||
Reference in New Issue
Block a user