Agent 业务逻辑完善
This commit is contained in:
@@ -29,8 +29,8 @@ public class MyWebSocketClient {
|
||||
try {
|
||||
// 发送消息到服务端
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("type", "contextual_update");
|
||||
map.put("user_id", session.getId());
|
||||
map.put("type", "transcript");
|
||||
map.put("role", "user");
|
||||
map.put("text", "你好,只回复一句话");
|
||||
String s = JSONUtil.toJsonStr(map);
|
||||
session.getBasicRemote().sendText(s);
|
||||
@@ -44,8 +44,8 @@ public class MyWebSocketClient {
|
||||
Thread.sleep(2000);
|
||||
// 发送消息到服务端
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("type", "contextual_update");
|
||||
map.put("user_id", session.getId());
|
||||
map.put("type", "transcript");
|
||||
map.put("role", "user");
|
||||
map.put("text", "你能回答我其他的嘛");
|
||||
String s = JSONUtil.toJsonStr(map);
|
||||
session.getBasicRemote().sendText(s);
|
||||
@@ -78,7 +78,7 @@ public class MyWebSocketClient {
|
||||
// WebSocket服务端地址(示例)
|
||||
String serverUri = "ws://vetti.hotake.cn/prod-api/voice-websocket/elevenLabsAgent/104";
|
||||
try {
|
||||
// 获取WebSocket容器
|
||||
// 获取WebSocket容器c
|
||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
// 连接服务端(传入客户端端点实例和服务端URI)
|
||||
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;
|
||||
|
||||
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.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
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控制台获取
|
||||
private static final String AGENT_ID = "agent_9401kd09yfjnes2vddz1n29wev2t"; // 如:agent_9401kd09yfjnes2vddz1n29wev2t
|
||||
private static final String TOKEN_API_URL = "https://api.elevenlabs.io/v1/convai/conversation/token";
|
||||
|
||||
// 从ElevenLabs控制台获取
|
||||
private static final String XI_API_KEY = "sk_dfe2b45e19bf8ad93a71d3a0faa61619a91e817df549d116";
|
||||
// 如: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媒体类型
|
||||
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
|
||||
* @param conversationId 会话ID(可选,不传则自动生成)
|
||||
* @param userId 用户ID(可选,用于区分用户)
|
||||
* @return Token响应对象
|
||||
* @throws IOException 网络/接口异常
|
||||
*/
|
||||
public ConvAiTokenResponse getConvAiToken(String conversationId, String userId) throws IOException {
|
||||
public ConvAiTokenDto getConvAiToken() {
|
||||
try {
|
||||
// 用户ID(可选,用于区分用户)
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
// 1. 构造请求体
|
||||
ConvAiTokenRequest requestBody = new ConvAiTokenRequest();
|
||||
ConvAiTokenRequestVo requestBody = new ConvAiTokenRequestVo();
|
||||
requestBody.setAgent_id(AGENT_ID);
|
||||
// 会话ID:不传则生成随机ID
|
||||
requestBody.setConversation_id(conversationId == null ? UUID.randomUUID().toString() : conversationId);
|
||||
requestBody.setUser_id(userId); // 用户ID(可选)
|
||||
|
||||
requestBody.setConversation_id(UUID.randomUUID().toString());
|
||||
// 用户ID(可选)
|
||||
requestBody.setUser_id(userId.toString());
|
||||
// 2. 构建HTTP请求
|
||||
Request request = new Request.Builder()
|
||||
.url(TOKEN_API_URL)
|
||||
// 核心鉴权:添加XI-API-KEY头
|
||||
.addHeader("xi-api-key", XI_API_KEY)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
// 发送JSON请求体
|
||||
.post(RequestBody.create(gson.toJson(requestBody), JSON_MEDIA_TYPE))
|
||||
.build();
|
||||
|
||||
// 初始化OkHttp客户端(设置超时)
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.readTimeout(10, TimeUnit.SECONDS)
|
||||
.writeTimeout(10, TimeUnit.SECONDS)
|
||||
.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() : "无错误信息";
|
||||
throw new IOException("获取Token失败:HTTP码=" + response.code() + ",错误信息=" + errorBody);
|
||||
log.info("2-错误信息为:{}",errorBody);
|
||||
throw new IOException("Failed to obtain Token");
|
||||
}
|
||||
|
||||
// 解析JSON响应为实体类
|
||||
String responseBody = response.body().string();
|
||||
return gson.fromJson(responseBody, ConvAiTokenResponse.class);
|
||||
log.info("3-获取令牌数据:{}", responseBody);
|
||||
return JSONUtil.toBean(responseBody, ConvAiTokenDto.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new ServiceException("Failed to obtain Token");
|
||||
}
|
||||
|
||||
// ===================== 数据模型(匹配接口格式) =====================
|
||||
/**
|
||||
* 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) {
|
||||
@@ -120,10 +102,10 @@ public class ElevenLabsConvAiTokenClientServiceImpl {
|
||||
// System.out.println("会话ID:" + response.getConversation_id());
|
||||
// System.out.println("过期时间(时间戳):" + response.getExpires_at());
|
||||
//
|
||||
//
|
||||
// // 后续使用:拼接WebSocket地址
|
||||
// String wsUrl = "wss://api.elevenlabs.io/v1/convai/ws?token=" + response.getToken();
|
||||
// System.out.println("WebSocket连接地址:" + wsUrl);
|
||||
//
|
||||
// } catch (IOException e) {
|
||||
// System.err.println("❌ 获取Token失败:" + e.getMessage());
|
||||
// e.printStackTrace();
|
||||
|
||||
Reference in New Issue
Block a user