如题,第一次用websocket,做了个这玩意,只做了上下文的谈天,没做流式。
中心另有个低级报错但卡了好久,具体可以看【错误记载】websocket连接失败,但后端毫无反应,另有【错误记载】ruoyi-vue@Autowired注入自定义mapper时为null解决
,感兴趣可前往观看。
实际上我后端用的是ruoyi-vue,前端用的ruoyi-app,但不重要。由于功能就是基于websocket和文心一言千帆大模型的接口,完全可以独立出来。
每个新建的账号会送一张20元的代金券,限期一个月内。而谈天服务接口单价约1分/千token,总之用来练手肯定够用了。
参考
文档中心-ERNIE-Bot-turbo
百度文心一言接入教程
若依插件-集成websocket实现简朴通信
先看看效果
大抵这样。
2023.10.13更新:昨天和朋侪聊了一下,发现他的想法和我的差别——根本不用实体类去保存解析复杂的json,直接保存消息内容。有一说一,在这个小demo这里,确实可以更快更简朴的实现,由于这个demo最耗时的就是看又臭又长的参数,然后写哀求体和返回值的实体类,至少哀求体实体类是可以不写的。
下面进入正题。
文心千帆创建应用
- 文心一言,大概是这里,先创建个账号,进控制台创建一个应用(有一个apikey和secretkey,有用),开通一个谈天服务(我开通的是ErnieBot-turbo),就可以了。具体有点忘了,大家可以参考其他博客。
- 其次官方有给一些参考,API调用指南、在线测试平台,第二个链接可以对自己开通的谈天服务进行测试。其中也有一个分类是“技能文档”和“示例代码”,技能文档里边有普通/流式的哀求/响应的参数和示例(如果比力小不容易看,文档中心-ERNIE-Bot-turbo也有),示例代码就是哀求的各个语言的示例代码。
思路
有三个角色,大模型 ←→ 后端 ←→ 前端。
大模型:接受后端发过来的消息,返反响应消息
后端:接受前端发过来的消息,封装发给大模型;接收大模型返回的消息,回给后端;发送的消息和返回的消息都要保存到数据库
前端:发送消息,接受后端返回的响应消息,及时回显在谈天页面。
显然,websocket用在前后端之间进行交互,后端类似一个中心人,前端是一个用户,大模型是ai服务。
步调与代码
- 实现websocket相关
1.1 注册到spring- @Configuration
- public class WebSocketConfig {
-
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
-
- return new ServerEndpointExporter();
- }
- }
复制代码 1.2 实现一个WebSocket的服务(别看这么长,其实参考了若依插件-集成websocket实现简朴通信,但没涉及信号量之类以是没什么用,除了onMessage外,其他如onOpen打印一条消息就行了,更多如WebSocketUsers可以去链接那下载)- @CrossOrigin
- @Component
- @ServerEndpoint("/websocket/message")
- public class WebSocketServer {
-
- private ChatRecordMapper chatRecordMapper = SpringUtils.getBean(ChatRecordMapper.class);
- /**
- * WebSocketServer 日志控制器
- */
- private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
- /**
- * 默认最多允许同时在线人数100
- */
- public static int socketMaxOnlineCount = 100;
- private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
- /**
- * 连接建立成功调用的方法
- */
- @OnOpen
- public void onOpen(Session session) throws Exception {
-
- boolean semaphoreFlag = false;
- // 尝试获取信号量
- semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
- if (!semaphoreFlag) {
-
- // 未获取到信号量
- LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
- WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount);
- session.close();
- } else {
-
- // 添加用户
- WebSocketUsers.put(session.getId(), session);
- LOGGER.info("\n 建立连接 - {}", session);
- LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
- WebSocketUsers.sendMessageToUserByText(session, "连接成功");
- }
- }
- /**
- * 连接关闭时处理
- */
- @OnClose
- public void onClose(Session session) {
-
- LOGGER.info("\n 关闭连接 - {}", session);
- // 移除用户
- WebSocketUsers.remove(session.getId());
- // 获取到信号量则需释放
- SemaphoreUtils.release(socketSemaphore);
- }
- /**
- * 抛出异常时处理
- */
- @OnError
- public void onError(Session session, Throwable exception) throws Exception {
-
- if (session.isOpen()) {
-
- // 关闭连接
- session.close();
- }
- String sessionId = session.getId();
- LOGGER.info("\n 连接异常 - {}", sessionId);
- LOGGER.info("\n 异常信息 - {}", exception);
- // 移出用户
- WebSocketUsers.remove(sessionId);
- // 获取到信号量则需释放
- SemaphoreUtils.release(socketSemaphore);
- }
- /**
- * 服务器接收到客户端消息时调用的方法
- */
- @OnMessage
- public void onMessage(String message, Session session) {
-
- // 首先,接收到一条消息
- LOGGER.info("\n 收到消息 - {}", message);
- // 1. 调用大模型API,把上下文和这次问题传入,得到回复
- BigModelService bigModelService = new BigModelService();
- TurboResponse response = bigModelService.callModelAPI(session.getId(),message);
- if (response == null) {
-
- WebSocketUsers.sendMessageToUserByText(session, "抱歉,似乎出了点问题,请联系管理员");
- return;
- }
- WebSocketUsers.sendMessageToUserByText(session, response.getResult());
- }
- }
复制代码
- 实现哀求接口相关
2.1 先写实体类,包括BaiduChatMessage(最基本的谈天消息)、ErnieBotTurboParam(ErnieBot-Turbo的哀求参数,包括了List<BaiduChatMessage>)TurboResponse(哀求返回结果对应的实体类)- @Data
- @SuperBuilder
- @NoArgsConstructor
- @AllArgsC
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |