Agent 业务逻辑完善
This commit is contained in:
@@ -29,8 +29,8 @@ public class MyWebSocketClient {
|
|||||||
try {
|
try {
|
||||||
// 发送消息到服务端
|
// 发送消息到服务端
|
||||||
Map<String,String> map = new HashMap<>();
|
Map<String,String> map = new HashMap<>();
|
||||||
map.put("type", "contextual_update");
|
map.put("type", "transcript");
|
||||||
map.put("user_id", session.getId());
|
map.put("role", "user");
|
||||||
map.put("text", "你好,只回复一句话");
|
map.put("text", "你好,只回复一句话");
|
||||||
String s = JSONUtil.toJsonStr(map);
|
String s = JSONUtil.toJsonStr(map);
|
||||||
session.getBasicRemote().sendText(s);
|
session.getBasicRemote().sendText(s);
|
||||||
@@ -44,8 +44,8 @@ public class MyWebSocketClient {
|
|||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
// 发送消息到服务端
|
// 发送消息到服务端
|
||||||
Map<String,String> map = new HashMap<>();
|
Map<String,String> map = new HashMap<>();
|
||||||
map.put("type", "contextual_update");
|
map.put("type", "transcript");
|
||||||
map.put("user_id", session.getId());
|
map.put("role", "user");
|
||||||
map.put("text", "你能回答我其他的嘛");
|
map.put("text", "你能回答我其他的嘛");
|
||||||
String s = JSONUtil.toJsonStr(map);
|
String s = JSONUtil.toJsonStr(map);
|
||||||
session.getBasicRemote().sendText(s);
|
session.getBasicRemote().sendText(s);
|
||||||
@@ -78,7 +78,7 @@ public class MyWebSocketClient {
|
|||||||
// WebSocket服务端地址(示例)
|
// WebSocket服务端地址(示例)
|
||||||
String serverUri = "ws://vetti.hotake.cn/prod-api/voice-websocket/elevenLabsAgent/104";
|
String serverUri = "ws://vetti.hotake.cn/prod-api/voice-websocket/elevenLabsAgent/104";
|
||||||
try {
|
try {
|
||||||
// 获取WebSocket容器
|
// 获取WebSocket容器c
|
||||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||||
// 连接服务端(传入客户端端点实例和服务端URI)
|
// 连接服务端(传入客户端端点实例和服务端URI)
|
||||||
container.connectToServer(new MyWebSocketClient(), new URI(serverUri));
|
container.connectToServer(new MyWebSocketClient(), new URI(serverUri));
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.vetti.web.controller.ai;
|
||||||
|
|
||||||
|
import com.vetti.common.core.controller.BaseController;
|
||||||
|
import com.vetti.common.core.domain.R;
|
||||||
|
import com.vetti.hotake.domain.dto.HotakeJobDescriptionGeneratorDto;
|
||||||
|
import com.vetti.hotake.domain.vo.HotakeJobDescriptionGeneratorVo;
|
||||||
|
import com.vetti.hotake.service.IHotakeAiCommonToolsService;
|
||||||
|
import com.vetti.web.entity.dto.ConvAiTokenDto;
|
||||||
|
import com.vetti.web.service.IElevenLabsConvAiTokenClientService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI ElevemLabs Agent 信息Controller
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-12-14
|
||||||
|
*/
|
||||||
|
@Api(tags ="AI ElevemLabs Agent")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/hotake/elevenLabsConvAi")
|
||||||
|
public class HotakeElevenLabsConvAiTokenClientController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IElevenLabsConvAiTokenClientService convAiTokenClientService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ElevemLabs Agent令牌
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取ElevemLabs Agent令牌")
|
||||||
|
@PostMapping(value = "/getToken")
|
||||||
|
public R<ConvAiTokenDto> handleElevemLabsAgentToken()
|
||||||
|
{
|
||||||
|
return R.ok(convAiTokenClientService.getConvAiToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.vetti.web.entity.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ElevenLabs Agent token 信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ConvAiTokenDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("核心对话Token")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@ApiModelProperty("会话ID")
|
||||||
|
private String conversation_id;
|
||||||
|
|
||||||
|
@ApiModelProperty("Token过期时间(时间戳,秒)")
|
||||||
|
private long expires_at;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.vetti.web.entity.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ElevenLabs Agent token 请求体 信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ConvAiTokenRequestVo {
|
||||||
|
|
||||||
|
@ApiModelProperty("Agent ID(必填)")
|
||||||
|
private String agent_id;
|
||||||
|
|
||||||
|
@ApiModelProperty("会话ID(可选)")
|
||||||
|
private String conversation_id;
|
||||||
|
|
||||||
|
@ApiModelProperty("用户ID(可选)")
|
||||||
|
private String user_id;
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
package com.vetti.web.service;
|
|
||||||
|
|
||||||
public interface ElevenLabsConvAiTokenClientService {
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.vetti.web.service;
|
||||||
|
|
||||||
|
import com.vetti.web.entity.dto.ConvAiTokenDto;
|
||||||
|
/**
|
||||||
|
* ElevenLabs Agent 信息 服务类
|
||||||
|
*
|
||||||
|
* @author WangXiangShun
|
||||||
|
* @since 2025-08-27
|
||||||
|
*/
|
||||||
|
public interface IElevenLabsConvAiTokenClientService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ConvAI对话Token
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ConvAiTokenDto getConvAiToken();
|
||||||
|
}
|
||||||
@@ -1,111 +1,93 @@
|
|||||||
package com.vetti.web.service.impl;
|
package com.vetti.web.service.impl;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.vetti.common.exception.ServiceException;
|
||||||
|
import com.vetti.common.utils.SecurityUtils;
|
||||||
|
import com.vetti.web.entity.dto.ConvAiTokenDto;
|
||||||
|
import com.vetti.web.entity.vo.ConvAiTokenRequestVo;
|
||||||
|
import com.vetti.web.service.IElevenLabsConvAiTokenClientService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class ElevenLabsConvAiTokenClientServiceImpl {
|
/**
|
||||||
|
* ElevenLabs Agent 信息 服务实现类
|
||||||
|
*
|
||||||
|
* @author WangXiangShun
|
||||||
|
* @since 2025-08-27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ElevenLabsConvAiTokenClientServiceImpl implements IElevenLabsConvAiTokenClientService {
|
||||||
// ========== 配置项(替换为你的实际值) ==========
|
// ========== 配置项(替换为你的实际值) ==========
|
||||||
private static final String XI_API_KEY = "sk_dfe2b45e19bf8ad93a71d3a0faa61619a91e817df549d116"; // 从ElevenLabs控制台获取
|
// 从ElevenLabs控制台获取
|
||||||
private static final String AGENT_ID = "agent_9401kd09yfjnes2vddz1n29wev2t"; // 如:agent_9401kd09yfjnes2vddz1n29wev2t
|
private static final String XI_API_KEY = "sk_dfe2b45e19bf8ad93a71d3a0faa61619a91e817df549d116";
|
||||||
private static final String TOKEN_API_URL = "https://api.elevenlabs.io/v1/convai/conversation/token";
|
// 如:agent_9401kd09yfjnes2vddz1n29wev2t
|
||||||
|
private static final String AGENT_ID = "agent_9401kd09yfjnes2vddz1n29wev2t";
|
||||||
|
//请求地址
|
||||||
|
private static final String TOKEN_API_URL = "https://api.elevenlabs.io/v1/convai/conversation/token?agent_id=agent_9401kd09yfjnes2vddz1n29wev2t";
|
||||||
// JSON媒体类型
|
// JSON媒体类型
|
||||||
private static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
private static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
||||||
private final OkHttpClient client;
|
|
||||||
private final Gson gson;
|
|
||||||
|
|
||||||
// 构造方法:初始化客户端
|
|
||||||
public ElevenLabsConvAiTokenClientServiceImpl() {
|
|
||||||
// 初始化OkHttp客户端(设置超时)
|
|
||||||
this.client = new OkHttpClient.Builder()
|
|
||||||
.connectTimeout(10, TimeUnit.SECONDS)
|
|
||||||
.readTimeout(10, TimeUnit.SECONDS)
|
|
||||||
.writeTimeout(10, TimeUnit.SECONDS)
|
|
||||||
.build();
|
|
||||||
this.gson = new Gson();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================== 核心:获取ConvAI Token =====================
|
// ===================== 核心:获取ConvAI Token =====================
|
||||||
/**
|
/**
|
||||||
* 获取ConvAI对话Token
|
* 获取ConvAI对话Token
|
||||||
* @param conversationId 会话ID(可选,不传则自动生成)
|
|
||||||
* @param userId 用户ID(可选,用于区分用户)
|
|
||||||
* @return Token响应对象
|
* @return Token响应对象
|
||||||
* @throws IOException 网络/接口异常
|
* @throws IOException 网络/接口异常
|
||||||
*/
|
*/
|
||||||
public ConvAiTokenResponse getConvAiToken(String conversationId, String userId) throws IOException {
|
public ConvAiTokenDto getConvAiToken() {
|
||||||
// 1. 构造请求体
|
try {
|
||||||
ConvAiTokenRequest requestBody = new ConvAiTokenRequest();
|
// 用户ID(可选,用于区分用户)
|
||||||
requestBody.setAgent_id(AGENT_ID);
|
Long userId = SecurityUtils.getUserId();
|
||||||
// 会话ID:不传则生成随机ID
|
// 1. 构造请求体
|
||||||
requestBody.setConversation_id(conversationId == null ? UUID.randomUUID().toString() : conversationId);
|
ConvAiTokenRequestVo requestBody = new ConvAiTokenRequestVo();
|
||||||
requestBody.setUser_id(userId); // 用户ID(可选)
|
requestBody.setAgent_id(AGENT_ID);
|
||||||
|
// 会话ID:不传则生成随机ID
|
||||||
// 2. 构建HTTP请求
|
requestBody.setConversation_id(UUID.randomUUID().toString());
|
||||||
Request request = new Request.Builder()
|
// 用户ID(可选)
|
||||||
.url(TOKEN_API_URL)
|
requestBody.setUser_id(userId.toString());
|
||||||
// 核心鉴权:添加XI-API-KEY头
|
// 2. 构建HTTP请求
|
||||||
.addHeader("xi-api-key", XI_API_KEY)
|
Request request = new Request.Builder()
|
||||||
.addHeader("Content-Type", "application/json")
|
.url(TOKEN_API_URL)
|
||||||
// 发送JSON请求体
|
// 核心鉴权:添加XI-API-KEY头
|
||||||
.post(RequestBody.create(gson.toJson(requestBody), JSON_MEDIA_TYPE))
|
.addHeader("xi-api-key", XI_API_KEY)
|
||||||
.build();
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.build();
|
||||||
// 3. 执行请求并解析响应
|
// 初始化OkHttp客户端(设置超时)
|
||||||
try (Response response = client.newCall(request).execute()) {
|
OkHttpClient client = new OkHttpClient.Builder()
|
||||||
// 检查响应状态
|
.connectTimeout(10, TimeUnit.SECONDS)
|
||||||
if (!response.isSuccessful()) {
|
.readTimeout(10, TimeUnit.SECONDS)
|
||||||
String errorBody = response.body() != null ? response.body().string() : "无错误信息";
|
.writeTimeout(10, TimeUnit.SECONDS)
|
||||||
throw new IOException("获取Token失败:HTTP码=" + response.code() + ",错误信息=" + errorBody);
|
.build();
|
||||||
|
// 3. 执行请求并解析响应
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
log.info("1-错误信息为:{}",JSONUtil.toJsonStr(response));
|
||||||
|
// 检查响应状态
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
String errorBody = response.body() != null ? response.body().string() : "无错误信息";
|
||||||
|
log.info("2-错误信息为:{}",errorBody);
|
||||||
|
throw new IOException("Failed to obtain Token");
|
||||||
|
}
|
||||||
|
// 解析JSON响应为实体类
|
||||||
|
String responseBody = response.body().string();
|
||||||
|
log.info("3-获取令牌数据:{}", responseBody);
|
||||||
|
return JSONUtil.toBean(responseBody, ConvAiTokenDto.class);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
// 解析JSON响应为实体类
|
e.printStackTrace();
|
||||||
String responseBody = response.body().string();
|
throw new ServiceException("Failed to obtain Token");
|
||||||
return gson.fromJson(responseBody, ConvAiTokenResponse.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================== 数据模型(匹配接口格式) =====================
|
|
||||||
/**
|
|
||||||
* Token请求体(对应接口入参)
|
|
||||||
*/
|
|
||||||
static class ConvAiTokenRequest {
|
|
||||||
private String agent_id; // Agent ID(必填)
|
|
||||||
private String conversation_id; // 会话ID(可选)
|
|
||||||
private String user_id; // 用户ID(可选)
|
|
||||||
|
|
||||||
// Getter & Setter
|
|
||||||
public String getAgent_id() { return agent_id; }
|
|
||||||
public void setAgent_id(String agent_id) { this.agent_id = agent_id; }
|
|
||||||
public String getConversation_id() { return conversation_id; }
|
|
||||||
public void setConversation_id(String conversation_id) { this.conversation_id = conversation_id; }
|
|
||||||
public String getUser_id() { return user_id; }
|
|
||||||
public void setUser_id(String user_id) { this.user_id = user_id; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Token响应体(对应接口返回)
|
|
||||||
*/
|
|
||||||
static class ConvAiTokenResponse {
|
|
||||||
private String token; // 核心对话Token
|
|
||||||
private String conversation_id; // 会话ID
|
|
||||||
private long expires_at; // Token过期时间(时间戳,秒)
|
|
||||||
|
|
||||||
// Getter & Setter
|
|
||||||
public String getToken() { return token; }
|
|
||||||
public void setToken(String token) { this.token = token; }
|
|
||||||
public String getConversation_id() { return conversation_id; }
|
|
||||||
public void setConversation_id(String conversation_id) { this.conversation_id = conversation_id; }
|
|
||||||
public long getExpires_at() { return expires_at; }
|
|
||||||
public void setExpires_at(long expires_at) { this.expires_at = expires_at; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================== 测试主方法 =====================
|
// ===================== 测试主方法 =====================
|
||||||
// public static void main(String[] args) {
|
// public static void main(String[] args) {
|
||||||
@@ -120,10 +102,10 @@ public class ElevenLabsConvAiTokenClientServiceImpl {
|
|||||||
// System.out.println("会话ID:" + response.getConversation_id());
|
// System.out.println("会话ID:" + response.getConversation_id());
|
||||||
// System.out.println("过期时间(时间戳):" + response.getExpires_at());
|
// System.out.println("过期时间(时间戳):" + response.getExpires_at());
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// // 后续使用:拼接WebSocket地址
|
// // 后续使用:拼接WebSocket地址
|
||||||
// String wsUrl = "wss://api.elevenlabs.io/v1/convai/ws?token=" + response.getToken();
|
// String wsUrl = "wss://api.elevenlabs.io/v1/convai/ws?token=" + response.getToken();
|
||||||
// System.out.println("WebSocket连接地址:" + wsUrl);
|
// System.out.println("WebSocket连接地址:" + wsUrl);
|
||||||
//
|
|
||||||
// } catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
// System.err.println("❌ 获取Token失败:" + e.getMessage());
|
// System.err.println("❌ 获取Token失败:" + e.getMessage());
|
||||||
// e.printStackTrace();
|
// e.printStackTrace();
|
||||||
|
|||||||
Reference in New Issue
Block a user