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

打印 上一主题 下一主题

主题 549|帖子 549|积分 1657

如题,第一次用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
    1. @Configuration
    2. public class WebSocketConfig {
    3.      
    4.     @Bean
    5.     public ServerEndpointExporter serverEndpointExporter() {
    6.      
    7.         return new ServerEndpointExporter();
    8.     }
    9. }
    复制代码
    1.2 实现一个WebSocket的服务(别看这么长,其实参考了若依插件-集成websocket实现简朴通信,但没涉及信号量之类以是没什么用,除了onMessage外,其他如onOpen打印一条消息就行了,更多如WebSocketUsers可以去链接那下载)
    1. @CrossOrigin
    2. @Component
    3. @ServerEndpoint("/websocket/message")
    4. public class WebSocketServer {
    5.      
    6.    private ChatRecordMapper chatRecordMapper = SpringUtils.getBean(ChatRecordMapper.class);
    7.    /**
    8.     * WebSocketServer 日志控制器
    9.     */
    10.    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
    11.    /**
    12.     * 默认最多允许同时在线人数100
    13.     */
    14.    public static int socketMaxOnlineCount = 100;
    15.    private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
    16.    /**
    17.     * 连接建立成功调用的方法
    18.     */
    19.    @OnOpen
    20.    public void onOpen(Session session) throws Exception {
    21.      
    22.        boolean semaphoreFlag = false;
    23.        // 尝试获取信号量
    24.        semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
    25.        if (!semaphoreFlag) {
    26.      
    27.            // 未获取到信号量
    28.            LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
    29.            WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount);
    30.            session.close();
    31.        } else {
    32.      
    33.            // 添加用户
    34.            WebSocketUsers.put(session.getId(), session);
    35.            LOGGER.info("\n 建立连接 - {}", session);
    36.            LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
    37.            WebSocketUsers.sendMessageToUserByText(session, "连接成功");
    38.        }
    39.    }
    40.    /**
    41.     * 连接关闭时处理
    42.     */
    43.    @OnClose
    44.    public void onClose(Session session) {
    45.      
    46.        LOGGER.info("\n 关闭连接 - {}", session);
    47.        // 移除用户
    48.        WebSocketUsers.remove(session.getId());
    49.        // 获取到信号量则需释放
    50.        SemaphoreUtils.release(socketSemaphore);
    51.    }
    52.    /**
    53.     * 抛出异常时处理
    54.     */
    55.    @OnError
    56.    public void onError(Session session, Throwable exception) throws Exception {
    57.      
    58.        if (session.isOpen()) {
    59.      
    60.            // 关闭连接
    61.            session.close();
    62.        }
    63.        String sessionId = session.getId();
    64.        LOGGER.info("\n 连接异常 - {}", sessionId);
    65.        LOGGER.info("\n 异常信息 - {}", exception);
    66.        // 移出用户
    67.        WebSocketUsers.remove(sessionId);
    68.        // 获取到信号量则需释放
    69.        SemaphoreUtils.release(socketSemaphore);
    70.    }
    71.    /**
    72.     * 服务器接收到客户端消息时调用的方法
    73.     */
    74.    @OnMessage
    75.    public void onMessage(String message, Session session) {
    76.      
    77.        // 首先,接收到一条消息
    78.        LOGGER.info("\n 收到消息 - {}", message);
    79.        // 1. 调用大模型API,把上下文和这次问题传入,得到回复
    80.        BigModelService bigModelService = new BigModelService();
    81.        TurboResponse response = bigModelService.callModelAPI(session.getId(),message);
    82.        if (response == null) {
    83.      
    84.            WebSocketUsers.sendMessageToUserByText(session, "抱歉,似乎出了点问题,请联系管理员");
    85.            return;
    86.        }
    87.        WebSocketUsers.sendMessageToUserByText(session, response.getResult());
    88.    }
    89. }
    复制代码

  • 实现哀求接口相关
    2.1 先写实体类,包括BaiduChatMessage(最基本的谈天消息)、ErnieBotTurboParam(ErnieBot-Turbo的哀求参数,包括了List<BaiduChatMessage>)TurboResponse(哀求返回结果对应的实体类)
    1. @Data
    2. @SuperBuilder
    3. @NoArgsConstructor
    4. @AllArgsC
    复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表