SpringBoot接入星火认知大模型

文章目录

  • 准备工作
  • 整体思路
  • 接入大模型
    • 服务端和大模型连接
    • 客户端和服务端的连接
    • 测试

准备工作

  1. 到讯飞星火大模型上根据官方的提示申请tokens
    申请成功后可以获得对应的secret,key还有之前创建的应用的appId,这些就是我们要用到的信息

    在这里插入图片描述

  2. 搭建项目

整体思路

考虑到敏感信息等安全性问题,这里和大模型的交互都放到后端去做。
在这里插入图片描述

客户端,服务端,星火大模型均通过Websocket的方式建立连接,用户询问问题时向SpringBoot服务端发送消息,服务端接收到后,创建与星火大模型的连接,并访问大模型,获取到请求结果后发送给客户端

如果想实现根据上下文问答,就要把历史问题和历史回答结果全部传回大模型服务端

请求参数的构建和响应参数解析参照官方文档Web API文档

接入大模型

服务端和大模型连接

/*** 与大模型建立Socket连接** @author gwj*/
@Slf4j
public class BigModelNew extends WebSocketListener {public static final String appid = "appid";// 对话历史存储集合public static Map<Long,List<RoleContent>> hisMap = new ConcurrentHashMap<>();public static String totalAnswer = ""; // 大模型的答案汇总private static String newAsk = "";public static synchronized void ask(String question) {newAsk = question;}public static final Gson gson = new Gson();// 项目中需要用到的参数private Long userId;private Boolean wsCloseFlag;// 构造函数public BigModelNew(Long userId, Boolean wsCloseFlag) {this.userId = userId;this.wsCloseFlag = wsCloseFlag;}// 由于历史记录最大上线1.2W左右,需要判断是能能加入历史public boolean canAddHistory() {int len = 0;List<RoleContent> list = hisMap.get(userId);for (RoleContent temp : list) {len = len + temp.getContent().length();}if (len > 12000) {list.remove(0);list.remove(1);list.remove(2);list.remove(3);list.remove(4);return false;} else {return true;}}// 线程来发送参数class ModelThread extends Thread {private WebSocket webSocket;private Long userId;public ModelThread(WebSocket webSocket, Long userId) {this.webSocket = webSocket;this.userId = userId;}public void run() {try {JSONObject requestJson = new JSONObject();JSONObject header = new JSONObject();  // header参数header.put("app_id", appid);header.put("uid", userId+UUID.randomUUID().toString().substring(0,16));JSONObject parameter = new JSONObject(); // parameter参数JSONObject chat = new JSONObject();chat.put("domain", "4.0Ultra");chat.put("temperature", 0.5);chat.put("max_tokens", 4096);parameter.put("chat", chat);JSONObject payload = new JSONObject(); // payload参数JSONObject message = new JSONObject();JSONArray text = new JSONArray();// 历史问题获取List<RoleContent> list = hisMap.get(userId);if (list != null && !list.isEmpty()) {//log.info("his:{}",list);for (RoleContent tempRoleContent : list) {text.add(JSON.toJSON(tempRoleContent));}}// 最新问题RoleContent roleContent = new RoleContent();roleContent.setRole("user");roleContent.setContent(newAsk);text.add(JSON.toJSON(roleContent));hisMap.computeIfAbsent(userId, k -> new ArrayList<>());hisMap.get(userId).add(roleContent);message.put("text", text);payload.put("message", message);requestJson.put("header", header);requestJson.put("parameter", parameter);requestJson.put("payload", payload);// System.out.println(requestJson);webSocket.send(requestJson.toString());// 等待服务端返回完毕后关闭while (true) {// System.err.println(wsCloseFlag + "---");Thread.sleep(200);if (wsCloseFlag) {break;}}webSocket.close(1000, "");} catch (Exception e) {log.error("【大模型】发送消息错误,{}",e.getMessage());}}}@Overridepublic void onOpen(WebSocket webSocket, Response response) {super.onOpen(webSocket, response);log.info("上线");ModelThread modelThread = new ModelThread(webSocket,userId);modelThread.start();}@Overridepublic void onMessage(WebSocket webSocket, String text) {JsonParse json = gson.fromJson(text, JsonParse.class);if (json.getHeader().getCode() != 0) {log.error("发生错误,错误码为:{} sid为:{}", json.getHeader().getCode(),json.getHeader().getSid());//System.out.println(json);webSocket.close(1000, "");}List<Text> textList = json.getPayload().getChoices().getText();for (Text temp : textList) {// 向客户端发送回答信息,如有存储问答需求,在此处存储ModelChatEndpoint.sendMsgByUserId(userId,temp.getContent());totalAnswer = totalAnswer + temp.getContent();}if (json.getHeader().getStatus() == 2) {// 可以关闭连接,释放资源if (canAddHistory()) {RoleContent roleContent = new RoleContent();roleContent.setRole("assistant");roleContent.setContent(totalAnswer);hisMap.get(userId).add(roleContent);} else {hisMap.get(userId).remove(0);RoleContent roleContent = new RoleContent();roleContent.setRole("assistant");roleContent.setContent(totalAnswer);hisMap.get(userId).add(roleContent);}//收到响应后让等待的线程停止等待wsCloseFlag = true;}}@Overridepublic void onFailure(WebSocket webSocket, Throwable t, Response response) {super.onFailure(webSocket, t, response);try {if (null != response) {int code = response.code();System.out.println("onFailure code:" + code);System.out.println("onFailure body:" + response.body().string());if (101 != code) {System.out.println("connection failed");System.exit(0);}}} catch (IOException e) {e.printStackTrace();}}// 鉴权方法public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {URL url = new URL(hostUrl);// 时间SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);format.setTimeZone(TimeZone.getTimeZone("GMT"));String date = format.format(new Date());// 拼接String preStr = "host: " + url.getHost() + "\n" + "date: " + date + "\n" + "GET " + url.getPath() + " HTTP/1.1";// System.err.println(preStr);// SHA256加密Mac mac = Mac.getInstance("hmacsha256");SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");mac.init(spec);byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));// Base64加密String sha = Base64.getEncoder().encodeToString(hexDigits);// System.err.println(sha);// 拼接String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);// 拼接地址HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//addQueryParameter("date", date).//addQueryParameter("host", url.getHost()).//build();return httpUrl.toString();}
}

其中用来接收响应参数相关实体类

@Data
public class JsonParse {Header header;Payload payload;
}
@Data
public class Header {int code;int status;String sid;
}
@Data
public class Payload {Choices choices;
}
@Data
public class Choices {List<Text> text;
}
@Data
public class Text {String role;String content;
}
@Data
public class RoleContent {String role;String content;
}

客户端和服务端的连接

/*** 接收客户端请求** @author gwj* @date 2024/10/29 16:51*/
@ServerEndpoint(value = "/ws/model", configurator = GetUserConfigurator.class)
@Component
@Slf4j
public class ModelChatEndpoint {private static AtomicInteger online = new AtomicInteger(0);private static final ConcurrentHashMap<Long,ModelChatEndpoint> wsMap = new ConcurrentHashMap<>();private static BigModelConfig config;@Resourceprivate BigModelConfig modelConfig;@PostConstructpublic void init() {config = modelConfig;}private Session session;private Long userId;@OnOpenpublic void onOpen(EndpointConfig config, Session session) {String s = config.getUserProperties().get("id").toString();userId = Long.parseLong(s);this.session = session;wsMap.put(userId,this);online.incrementAndGet();log.info("用户{},连接成功,在线人数:{}",userId,online);}@OnClosepublic void onClose() {wsMap.remove(userId);online.incrementAndGet();log.info("{},退出,在线人数:{}",userId,online);}@OnErrorpublic void onError(Session session, Throwable error) {log.error("连接出错,{}", error.getMessage());}@OnMessagepublic void onMessage(String message,Session session) throws Exception {BigModelNew.ask(message);//构建鉴权urlString authUrl = BigModelNew.getAuthUrl(config.getHostUrl(), config.getApiKey(), config.getApiSecret());OkHttpClient client = new OkHttpClient.Builder().build();String url = authUrl.replace("http://", "ws://").replace("https://", "wss://");Request request = new Request.Builder().url(url).build();WebSocket webSocket = client.newWebSocket(request,new BigModelNew(this.userId, false));log.info("收到客户端{}的消息:{}", userId, message);}private void sendMsg(String message) {try {this.session.getBasicRemote().sendText(message);} catch (IOException e) {log.error("客户端{}发送{}失败",userId,message);}}/*** 根据userId向用户发送消息** @param userId 用户id* @param message 消息*/public static void sendMsgByUserId(Long userId,String message) {if (userId != null && wsMap.containsKey(userId)) {wsMap.get(userId).sendMsg(message);}}}

测试

在这里插入图片描述
在这里插入图片描述

这样就简单实现了一个ai问答功能

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

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

相关文章

ssm056基于Java语言校园快递代取系统的设计与实现+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;校园快递代取系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递代取系统…

简单语音信号识别的MATLAB仿真

简单语音信号识别的MATLAB仿真 摘要&#xff1a; 隐马尔可夫模型&#xff08;HMM&#xff09;作为描述语音信号的一种统计模型&#xff0c;在现代语音处理中获得了广泛应用。本文概述了基于HMM的语音识别技术&#xff0c;阐述了预处理&#xff0c;特征提取以及训练&#xff0c…

童年玩具:两款线绳陀螺

1,2图是过去用来安装明线电线的瓷夹。现在应该找不到了。过去安装电线后&#xff0c;家里留下了一些&#xff0c;拿来做线陀螺非常好。 因为它非常重&#xff0c;旋转起来很有力&#xff0c;那声音呼呼响。 3,4图是现在都能看到的一个圆木片&#xff0c;两个孔&#xff0c;穿绳…

AntFlow一款开源免费且自主可控的仿钉钉工作流引擎

在现代企业管理中&#xff0c;流程审批的高效性直接影响到工作的流畅度与生产力。最近&#xff0c;我发现了一个非常有趣的项目——AntFlow。这个项目不仅提供了一个灵活且可定制的工作流平台&#xff0c;还能让用户以可视化的方式创建和管理审批流程。 如果你寻找一个快速集成…

光纤资源APP开发及二次开发说明

光纤资源APP主要由以下几部分组成&#xff1a; 登录界面选择项目界面地图创建节点界面填写详细信息界面成端及端口表界面接续及接续表界面 其中1、2、4界面不需要涉及到ht&#xff0c;故用原生界面即可实现&#xff0c;但是3、5、6涉及到ht&#xff0c;而ht在app中是不兼容的…

鉴源实验室·如何通过雷达攻击自动驾驶汽车-针对点云识别模型的对抗性攻击的科普

01 引 言 随着自动驾驶技术的迅速发展&#xff0c;雷达和激光雷达等传感器在自动驾驶汽车中的作用愈发重要。它们能够生成3D点云数据&#xff0c;帮助车辆实时感知周围环境并做出安全决策。然而&#xff0c;尽管这些传感器对驾驶环境的检测非常精确&#xff0c;它们也面临一种…

Stable Diffusion(2024)Ai绘画AIGC最新安装包资源下载+自学教程

以下内容为整理的Stable Diffusion保姆级教学内容&#xff0c;请购买的资料的同学务必认真学习&#xff01;按以下步骤操作快速掌握Stable Diffusion这个工具&#xff01; Stable Diffusion&#xff08;简称SD&#xff09;是一款地表最强AI绘图工具(AIGC)之一&#xff0c;Stab…

基于单片机的宠物自动喂食系统的设计

本设计以STM32单片机为核心控制器&#xff0c;搭载了OLED显示屏作为显示交互模块&#xff0c;HX711称重模块获取食物重量&#xff0c;ESP8266与手机APP通信从而远程控制&#xff0c;PWM输出控制舵机模拟投喂食物开关打开&#xff0c;驱动继电器控制水泵打开加水&#xff0c;HC-…

vue+websocket实现即时聊天平台

目录 1 什么是websocket 2 实现步骤 2.1 导入依赖 2.2 编写代码 1 什么是websocket WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它主要用于在客户端和服务器之间建立持久的连接&#xff0c;允许实时数据交换。WebSocket 的设计目的是为了提高 Web 应用程序的…

Spring Boot框架:大学城水电管理自动化

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

关于三色标记算法的理解

三色标记算法是一种垃圾标记的算法&#xff0c;用于cms和g1。 它将对象分为3种颜色&#xff1a; 1.白色对象&#xff1a;未被标记的对象 2.灰色对象&#xff1a;自身被标记&#xff0c;引用的其它对象还没被标记 3.黑色对象&#xff1a;自身以及所引用的对象都被标记完 标记过…

Python Matplotlib:基本图表绘制指南

Python Matplotlib&#xff1a;基本图表绘制指南 Matplotlib 是 Python 中一个非常流行的绘图库&#xff0c;它以简单易用和功能丰富而闻名&#xff0c;适合各种场景的数据可视化需求。在数据分析和数据科学领域&#xff0c;Matplotlib 是我们展示数据的有力工具。本文将详细讲…

深入探讨SEO分析技巧助力网站流量提升

内容概要 在当前的数字化时代&#xff0c;SEO分析的重要性不言而喻。它是提升网站流量的关键工具&#xff0c;帮助站长有效地优化网站内容和结构。通过系统的SEO分析&#xff0c;站长可以掌握用户搜索行为和需求&#xff0c;从而制定出更具针对性的内容策略。例如&#xff0c;…

配置QINQ

1. 配置公司A和公司B的私有网络&#xff0c;创建对应的VLAN&#xff0c;并且接口的链路类型 S3的配置: 系统视图进入&#xff1a; <Huawei>system-view 设置设备名称为s3&#xff1a; [huawei]sysname s3 创建VLAN 10和20&#xff1a; [s3]vlan batch 10 20 配置Gigabit…

react 中配置@寻找文件

安装插件craco npm i -D craco/craco 创建 craco.config.js文件放在根目录和package.json同级 const path require(path)module.exports {webpack: {alias: {"": path.resolve(__dirname, "src")}} }创建 jsconfig.config.js文件放在根目录和package.js…

基于Qt的独立线程创建与多线程执行实验Demo

一、多线程与线程池的应用目的[1][4] &#xff08;一&#xff09;多线程 一个进程内多个线程并发执行的情况就叫多线程&#xff0c;每一个线程是一个独立的执行流。多线程是一种编程模型&#xff0c;它与处理器无关&#xff0c;与设计机制有关。 需要多线程的原因包括&#xf…

电能质量治理产品在分布式光伏电站的应用

1.概述 随着全球对可再生能源需求的不断增长&#xff0c;分布式光伏电站的建设与扩张正迅速发展。然而&#xff0c;在其运行过程中&#xff0c;分布式光伏电站遭遇了一系列挑战&#xff0c;包括企业关口计量点功率因数降低和谐波污染等问题。这些问题不仅影响了光伏电站的运行…

如何解决导入aioredis报错TypeError: duplicate base class TimeoutError的问题(轻松解决,亲测有效)

下面是根据你的要求撰写的文章: 文章目录 📖 介绍 📖🏡 演示环境 🏡📒 aioredis导包报错 📒📝 解决方案📝 小贴士⚓️ 相关链接 ⚓️📖 介绍 📖 最近在使用Python异步redis模块aioredis的时候遇到了一个错误,导包报错提示 TypeError: duplicate base cla…

@Excel若依导出异常/解决BusinessBaseEntity里面的字段不支持导出

今天发现所有实体类继承BusinessBaseEntity里面的这些通用字段不支持导出&#xff0c;debug时发现是这样&#xff1a; 导出效果 这里我把能查到的方法都汇总了&#xff0c;如果你也遇到这个异常&#xff0c;可以去逐步排查 1.先看库里有没有数据 2.看字段名是否对齐 3.所需要…