使用websocket后端接入文心一言

news2024/11/16 1:17:17

最近再写项目练手,想着最近大模型那么火,也想接入项目来玩一玩,于是去了解了一下相关的api和通信协议,最后选择了文心一言进行集成,国内的相对稳定。ERNIE-Bot-turbo - 千帆大模型平台 | 百度智能云文档 (baidu.com)

使用websocket进行双向通信,因为http是单向协议显然不适合这样的场景。简单介绍一下websocket它是一个双向的通信协议,一旦通信双方建立联系,就可以互相发送消息。

 

http和websocket通信过程图

现在就开始进行配置吧,首先我们需要配置好websocket的的相关依赖已经配置serverEndpoint的扫描。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
@Configuration
public class WebSocketConfig
{
    @Bean
    public ServerEndpointExporter serverEndpointExporter()
    {
        return new ServerEndpointExporter();
    }
}

如此就将准备工作做好了,现在配置一下访问处理的server

@Component
@ServerEndpoint("/websocket/message")
public class WebSocketServer
{
    /**
     * 实现日志打印
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);

    public static int socketMaxOnlineCount = 100;

    private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);

    private List<BaiduChatMessage> userMessage[]=new List[2000];

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) throws Exception
    {
        SemaphoreUtils.tryAcquire(socketSemaphore);
        LOGGER.info("\n 成功连接 - {}", session);
    }

    /**
     * 连接关闭时处理
     */
    @OnClose
    public void onClose(Session session)
    {
        LOGGER.info("\n 关闭连接 - {}", session);
        // 获取到信号量则需释放
        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);
        // 获取到信号量则需释放
        SemaphoreUtils.release(socketSemaphore);
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        // 首先,接收到一条消息
        LOGGER.info("\n 收到消息 - {}", message);
        // 1. 调用大模型API,把上下文和这次问题传入,得到回复
        BigModelService bigModelService = new BigModelService();
        boolean f = bigModelService.callModelAPI(session,message,userMessage);
        if (!f) {
            session.getBasicRemote().sendText("抱歉,似乎出了点问题,请联系管理员");
            return;
        }
    }
}

都使用注解进行控制,其中这里最重要的就是 OnMessage,这个是得到websocket消息进行的处理,是最核心的方法,本次主要的业务实现焦距于本方法。

接下来就是将问题发送给文心一言的接口然后得到回应了

下面粘贴一下主代码

public boolean callModelAPI(Session session, String message, Map<String,List<BaiduChatMessage>> userMassage) {
        String records = "{}";
        ErnieBotTurboParam param = JSONObject.parseObject(records, ErnieBotTurboParam.class);
        //未将信息存入数据库,使用会话做一个简单的持久化
        if(userMassage.get(session.getId()) == null)
            userMassage.put(session.getId(),new ArrayList<>());
        //存入最新消息
        userMassage.get(session.getId()).add(BaiduChatMessage.builder().role("user").content(message).build());
        // 1.2.2 把messages重新设置到param中
        param.setMessages(userMassage.get(session.getId()));
        try {
            // 2. 发出请求,调用大模型API
            RequestBody body = RequestBody.create(MediaType.parse("application/json"), JSONObject.toJSONString(param));
            Request request = new Request.Builder()
                    .url("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=" + getAccessToken())
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json")
                    .build();
            Response response = HTTP_CLIENT.newCall(request).execute();

            if (response.isSuccessful()) {
                //对返回信息进行处理
                try (ResponseBody responseBody = response.body()) {
                    if (responseBody != null) {
                        InputStream inputStream = responseBody.byteStream();
                        // 以流的方式处理响应内容
                        byte[] buffer = new byte[2048];
                        int bytesRead;
                        String ss="";
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            // 在控制台输出每个数据块
                            String s[] = new String(buffer, 0, bytesRead).split("data: ");
                            int n=1;
                            while (n<s.length) {
                                System.out.println(s[n]);
                                TurboResponse turboResponse = JSONObject.parseObject(s[n++], TurboResponse.class);
                                ss+=turboResponse.getResult();
                                session.getBasicRemote().sendText(turboResponse.getResult());
                            }
                        }
                        userMassage.get(session.getId()).add(BaiduChatMessage.builder().role("assistant").content(ss).build());
                    }
                }
                return true;
            } else {
                LOGGER.error("调用大模型API失败: {}", response.message());
            }
        } catch (IOException e) {
            LOGGER.error("调用大模型API发生异常:", e);
        }
        return false;
    }

如此便实现了基本的通信服务,下面来看看效果

 

效果只能说够用 ,也还不错吧。

期待这篇文章可以帮助到大家

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1423920.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

elementUI实现selecttree自定义下拉框树形组件支持多选和搜索

elementUI实现selecttree自定义下拉框树形组件支持多选和搜索 效果图定义子组件父组件应用 效果图 定义子组件 主要结合el-select和el-tree两个组件改造的。 <template><div class"selectTree"><el-select filterable :filter-method"filterMe…

AI学习(4): PyTorch实战-手写数字识别

1.介绍 在之前的文章中介绍了PyTorch的环境安装&#xff0c;和张量(tensor)的基本使用&#xff0c;为防止陷入枯燥的理论学习中&#xff0c;在这篇文章&#xff0c;我们将进行项目实战学习&#xff0c;项目主要内容: 基于MNIST数据集&#xff0c;实现一个手写数字识别的神经网…

基于OpenCV的高压电力检测项目案例

一、项目背景与目标 随着高压电力设施的日益增多&#xff0c;传统的巡检方式已无法满足现代电力系统的需求。为此&#xff0c;我们决定利用计算机视觉技术&#xff0c;特别是OpenCV库&#xff0c;开发一个高压电力检测系统。目标是实现自动化、高精度的电力设备检测&#xff0c…

《动手学深度学习(PyTorch版)》笔记4.8

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

get out of black background

文章目录 基础 Sequence settings (after selected a Sequence) 看见 ( 让Pr表示透明 ) Effects-> Color Key, drag into your Sequence >.如果看不到 Effects 面板, 可以在 Window 菜单中打开 在Effect Controls 你可以调整 Color Key 的效果了先吸取黑色 还可以使用ma…

Python笔记(二)—— Python判断语句

2.1 布尔类型和比较运算符 布尔类型用于表示&#xff1a;真和假 比较运算符用于计算&#xff1a;真和假 1. 布尔&#xff08;bool&#xff09;表示现实生活中的逻辑&#xff0c;即真和假 True表示真False表示假 True本质上是一个数字记作1&#xff0c;False记作0 定义变…

17.Golang channel的基本定义及使用

目录 概述实践无缓冲 channel代码结果 缓冲 channel代码结果 channel的关闭特点代码结果range代码结果 select channel代码结果 结束 概述 此篇文章介绍 channel 的用法 无缓冲 channel缓冲 channelchannel的关闭特点range channelselect channel 每一种&#xff0c;配上完整…

Flutter 和 Android原生(Activity、Fragment)相互跳转、传参

前言 本文主要讲解 Flutter 和 Android原生之间&#xff0c;页面相互跳转、传参&#xff0c; 但其中用到了两端相互通信的知识&#xff0c;非常建议先看完这篇 讲解通信的文章&#xff1a; Flutter 与 Android原生 相互通信&#xff1a;BasicMessageChannel、MethodChannel、…

075:vue+mapbox 利用高德地址逆转换,点击地图,弹出地址信息

第075个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中利用高德逆地理编码,点击地图,弹出某点坐标和地址信息。这里要仔细阅读高德地图的逆编码API,同时要注意的是,这种转换在中国很好用,到了欧美国家就不好使了。同时这个底图是天地图的图像和标记。 直接…

如何在Raspberry Pi上启用SSH并结合cpolar内网穿透实现公网远程访问本地树莓派

文章目录 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地址4.5 ssh公网…

React16源码: React中处理hydrate的核心流程源码实现

hydrate 1 &#xff09;概述 hydrate 在react当中不算特别重要, 但是很多时候会用到的一个API这个 API 它主要作用就是在进入第一次渲染的时候&#xff0c;如果本身 dom 树上面已经有一个dom结构存在是否可以去利用这一部分已经存在的dom&#xff0c;然后去避免掉在第一次渲染…

全国疫情实时监测系统(附源码)

目录 一.项目背景 1.有力支持疫情防控知识传播 2.迅速锁定“涉疫”人员流动轨迹 3.开展疫情发展态势预测与溯源 4.一图胜过千言万语&#xff01;&#xff01;&#xff01; 二.研究过程&#xff08;项目技术的利用&#xff09; 1.总述 2.所用技术介绍 2.1Python 2.2Pyt…

免费的ChatGPT网站(7个)

还在为找免费的chatGPT网站或者应用而烦恼吗&#xff1f;博主归纳总结了7个国内非常好用&#xff0c;而且免费的chatGPT网站&#xff0c;AI语言大模型&#xff0c;我们都来接触一下吧。 免费&#xff01;免费&#xff01;免费&#xff01;...&#xff0c;建议收藏保存。 1&…

TPH-YOLOv5:基于Transformer预测头改进的YOLOv5开发构建麦穗检测计数分析系统

关于小麦麦穗或者是麦粒相关的开发实践不多&#xff0c;但前文也有所涉及&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《基于轻量级yolov5nCBAM开发构建全球小麦麦穗智能检测计数系统》 《基于YOLOv5[n/s/m/l/x]全系列参数模型开发构建小麦麦穗颗粒智能化精准检…

常见序列化的优劣:pb、avro、json、hessian

概念 &#xff08;1&#xff09;基础概念和用途 序列化和反序列本质上就是对象和字节数组的转换&#xff1a; 序列化时&#xff0c;将Java对象编码为byte数组 反序列化&#xff0c;则是将byte数组转换为Java对象 序列化用途&#xff1a; 1、在网络上传送对象的字节序列 2、…

Flink实战五_状态机制

接上文&#xff1a;Flink实战四_TableAPI&SQL 在学习Flink的状态机制之前&#xff0c;我们需要理解什么是状态。回顾我们之前介绍的很多流计算的计算过程&#xff0c;有些计算方法&#xff0c;比如说我们之前多次使用的将stock.txt中的一行文本数据转换成Stock股票对象的ma…

LTC5548 具宽带 DC 至 6GHz IF 的 2GHz 至 14GHz 微波混频器

优势和特点 上变频或下变频高 IIP3&#xff1a;在 5.8GHz 为 24.4dBm在 9GHz 为 21.4dBm7.1dB 转换损耗 (在 5.8GHz)15.2dBm 输入 P1dB (在 5.8GHz)集成型 LO 缓冲器&#xff1a;0dBm LO 驱动可选的集成型 LO 倍频器低 LO-RF 泄漏&#xff1a;< –30dBm50Ω 宽带匹配 RF 和…

Hadoop3.x基础(2)- HDFS

来源&#xff1a;B站尚硅谷 目录 HDFS概述HDFS产出背景及定义HDFS优缺点HDFS组成架构HDFS文件块大小&#xff08;面试重点&#xff09; HDFS的Shell操作&#xff08;开发重点&#xff09;基本语法命令大全常用命令实操准备工作上传下载HDFS直接操作 HDFS的API操作HDFS的API案例…

01神经网络的理论及实现

感知机的缺点就是需要设置合适的权重&#xff0c;而权重的设置都是人工操作的。 1、从感知机到神经网络 重新画出感知机的模型&#xff0c;在图上加上偏置&#xff0c;由于偏置始终为1&#xff0c;所以颜色加深。 图1-1 感知机模型 引入新函数(激活函数&#xff09;&#xff…

Zookeeper分布式命名服务实战

目录 分布式命名服务 分布式API目录 分布式节点的命名 分布式的ID生成器 分布式的ID生成器方案&#xff1a; 基于Zookeeper实现分布式ID生成器 基于Zookeeper实现SnowFlakeID算法 分布式命名服务 命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用Z…