泉缘泉 发表于 2024-8-11 08:35:10

springboot + websocket对接文心一言接口实现简朴上下文谈天(贴代码)

如题,第一次用websocket,做了个这玩意,只做了上下文的谈天,没做流式。
中心另有个低级报错但卡了好久,具体可以看【错误记载】websocket连接失败,但后端毫无反应,另有【错误记载】ruoyi-vue@Autowired注入自定义mapper时为null解决
,感兴趣可前往观看。
实际上我后端用的是ruoyi-vue,前端用的ruoyi-app,但不重要。由于功能就是基于websocket和文心一言千帆大模型的接口,完全可以独立出来。
每个新建的账号会送一张20元的代金券,限期一个月内。而谈天服务接口单价约1分/千token,总之用来练手肯定够用了。
参考

文档中心-ERNIE-Bot-turbo
百度文心一言接入教程
若依插件-集成websocket实现简朴通信
先看看效果

大抵这样。
https://i-blog.csdnimg.cn/blog_migrate/6d4c3a6fdb309ba94c924da6f67f1ad9.png
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企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: springboot + websocket对接文心一言接口实现简朴上下文谈天(贴代码)