SpringBoot 接入讯飞星火大模型实现对话

申请地址

https://xinghuo.xfyun.cn/sparkapi?scr=price
免费申请200万Token

开发文档

https://www.xfyun.cn/doc/spark/Web.html#_1-接口说明

页面最下面有相关demo可以参考

在这里插入图片描述

介绍

接口是以套接字的形式分段返回,而且非http请求,比较繁琐,官方也只给了比较简单的deom。

依赖项

  <!--okhttp3--><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></dependency><!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId></dependency>

配置文件

xunfei:ai:hostUrl: https://spark-api.xf-yun.com/v3.5/chatappId: xxxapiSecret: xxxapiKey: xxx

控制台上可以查看 API认证字符串

在这里插入图片描述

读取配置文件

@Value("${xunfei.ai.hostUrl}")
private  String  hostUrl;@Value("${xunfei.ai.appId}")
private  String appId;@Value("${xunfei.ai.apiSecret}")
private  String apiSecret;@Value("${xunfei.ai.apiKey}")
private  String apiKey;

权限校验

得到的是一个url,需要将http替换成ws

/*** 权限校验* @return String* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws MalformedURLException*/private String getAuthUrl() throws NoSuchAlgorithmException, InvalidKeyException, MalformedURLException {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();}

构建请求参数

请求参数是与json格式进行发送,如果需要结合之前的信息继续回答需要携带历史记录。在官方的api文档也可以查看

#参数构造示例如下

{"header": {"app_id": "12345","uid": "12345"},"parameter": {"chat": {"domain": "generalv3.5","temperature": 0.5,"max_tokens": 1024, }},"payload": {"message": {# 如果想获取结合上下文的回答,需要开发者每次将历史问答信息一起传给服务端,如下示例# 注意:text里面的所有content内容加一起的tokens需要控制在8192以内,开发者如有较长对话需求,需要适当裁剪历史信息"text": [{"role":"system","content":"你现在扮演李白,你豪情万丈,狂放不羁;接下来请用李白的口吻和用户对话。"} #设置对话背景或者模型角色{"role": "user", "content": "你是谁"} # 用户的历史问题{"role": "assistant", "content": "....."}  # AI的历史回答结果# ....... 省略的历史对话{"role": "user", "content": "你会做什么"}  # 最新的一条问题,如无需上下文,可只传最新一条问题]}}
}

JAVA构建

private    String buildBody(String text,String uid){JSONObject body =new JSONObject();JSONObject header =new JSONObject();header.put("app_id",appId);header.put("uid",uid);body.put("header",header);JSONObject parameter =new JSONObject();JSONObject chat =new JSONObject();chat.put("domain","generalv3.5");parameter.put("chat",chat);body.put("parameter",parameter);JSONObject history =JSONObject.parseObject(text);body.put("payload",history);JSONObject back =new JSONObject();back.put("role","system");back.put("content","请回答我关于一些生产安全的内容");//定义会话背景history.getJSONObject("message").getJSONArray("text").add(0,back);return body.toJSONString();}

回复消息

基于OKHTTP3的请求库,连接websocket

 /*** 回复消息* @param text* @return* @throws MalformedURLException* @throws NoSuchAlgorithmException* @throws InvalidKeyException*/public String answer(String text,String uid) throws MalformedURLException, NoSuchAlgorithmException, InvalidKeyException, ExecutionException, InterruptedException, TimeoutException {String authUrl =getAuthUrl().replace("http://", "ws://").replace("https://", "wss://");Request request = new Request.Builder().url(authUrl).build();OkHttpClient client = new OkHttpClient.Builder().build();StringBuilder sb =new StringBuilder();CompletableFuture<String> messageReceived = new CompletableFuture<>();String body = buildBody(text,uid);WebSocket webSocket =client.newWebSocket(request, new WebSocketListener() {@Overridepublic void onOpen(WebSocket webSocket, Response response) {webSocket.send(body);//发送消息}@Overridepublic void onMessage(WebSocket webSocket, String text) {JSONObject obj = JSON.parseObject(text);String str= obj.getJSONObject("payload").getJSONObject("choices").getJSONArray("text").getJSONObject(0).getString("content");sb.append(str);if(obj.getJSONObject("header").getLong("status")==2){webSocket.close(1000, "Closing WebSocket connection");messageReceived.complete(text); // 将收到的消息传递给 CompletableFuture}}} );String result = messageReceived.get(30, TimeUnit.SECONDS);; // 阻塞等待消息返回webSocket.close(1000, "Closing WebSocket connection");return sb.toString();}

Controller

   @PostMapping("/chat")public AjaxResult chat(String text,String uid) throws MalformedURLException, NoSuchAlgorithmException, InvalidKeyException, ExecutionException, InterruptedException, TimeoutException {return  success( model.answer(text,uid));}

运行效果

在这里插入图片描述

完整代码

Controller层

@RestController
@RequestMapping("/course")
public class QueryController extends BaseController {@Autowiredprivate CognitiveMode model;@PostMapping("/chat")public AjaxResult chat(String text,String uid) throws MalformedURLException, NoSuchAlgorithmException, InvalidKeyException, ExecutionException, InterruptedException, TimeoutException {return  success( model.answer(text,uid));}}
package com.ruoyi.framework.ai;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;@Component
public class CognitiveMode {@Value("${xunfei.ai.hostUrl}")private  String  hostUrl;@Value("${xunfei.ai.appId}")private  String appId;@Value("${xunfei.ai.apiSecret}")private  String apiSecret;@Value("${xunfei.ai.apiKey}")private  String apiKey;/*** 回复消息* @param text* @return* @throws MalformedURLException* @throws NoSuchAlgorithmException* @throws InvalidKeyException*/public String answer(String text,String uid) throws MalformedURLException, NoSuchAlgorithmException, InvalidKeyException, ExecutionException, InterruptedException, TimeoutException {String authUrl =getAuthUrl().replace("http://", "ws://").replace("https://", "wss://");Request request = new Request.Builder().url(authUrl).build();OkHttpClient client = new OkHttpClient.Builder().build();StringBuilder sb =new StringBuilder();CompletableFuture<String> messageReceived = new CompletableFuture<>();String body = buildBody(text,uid);WebSocket webSocket =client.newWebSocket(request, new WebSocketListener() {@Overridepublic void onOpen(WebSocket webSocket, Response response) {webSocket.send(body);}@Overridepublic void onMessage(WebSocket webSocket, String text) {JSONObject obj = JSON.parseObject(text);String str= obj.getJSONObject("payload").getJSONObject("choices").getJSONArray("text").getJSONObject(0).getString("content");sb.append(str);if(obj.getJSONObject("header").getLong("status")==2){webSocket.close(1000, "Closing WebSocket connection");messageReceived.complete(text); // 将收到的消息传递给 CompletableFuture}}} );String result = messageReceived.get(30, TimeUnit.SECONDS);; // 阻塞等待消息返回webSocket.close(1000, "Closing WebSocket connection");return sb.toString();}private    String buildBody(String text,String uid){JSONObject body =new JSONObject();JSONObject header =new JSONObject();header.put("app_id",appId);header.put("uid",uid);body.put("header",header);JSONObject parameter =new JSONObject();JSONObject chat =new JSONObject();chat.put("domain","generalv3.5");parameter.put("chat",chat);body.put("parameter",parameter);JSONObject history =JSONObject.parseObject(text);body.put("payload",history);JSONObject back =new JSONObject();back.put("role","system");back.put("content","请回答我关于一些xxx的内容");history.getJSONObject("message").getJSONArray("text").add(0,back);return body.toJSONString();}/*** 权限校验* @return String* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws MalformedURLException*/private String getAuthUrl() throws NoSuchAlgorithmException, InvalidKeyException, MalformedURLException {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();}}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】yum软件包管理器

目录 Linux 软件包管理器 yum 什么是软件包 Linux安装软件 查看软件包 关于rzsz Linux卸载软件 查看yum源 扩展yum源下载 Linux开发工具 vim编辑器 上述vim三种模式之间的切换总结&#xff1a; 命令模式下&#xff0c;一些命令&#xff1a; vim配置 Linux 软件包管理…

微服务—ES数据同步

目录 数据同步 问题分析 方案1. 同步调用 方案2. 异步通知 方案3. 监听binlog​编辑 各方案对比 案例——利用MQ实现数据同步 步骤1. 导入hotel-admin项目 步骤2. 声明交换机、队列 步骤3. 发送MQ消息 步骤4. 接收MQ消息 步骤5. 测试同步功能 数据同步 elasticsea…

统一数据格式返回,统一异常处理

目录 1.统一数据格式返回 2.统一异常处理 3.接口返回String类型问题 1.统一数据格式返回 添加ControllerAdvice注解实现ResponseBodyAdvice接口重写supports方法&#xff0c;beforeBodyWrite方法 /*** 统一数据格式返回的保底类 对于一些非对象的数据的再统一 即非对象的封…

typescript中的Omit排除类型及Pick取想要的属性

Omit 的使用:排除类型 type OmitUser {name: string,age: number,sex:string } type newOmit Omit<OmitUser, sex>// 定义一个对象并将其类型设置为 newOmit const example: newOmit {name: "John",age: 30 };console.log( Omit 的使用:排除类型 , example…

AJAXJSON入门篇

AJAX&JSON 概念&#xff1a;AJAX(Asynchronous JavaScript And XML):异步的JavaScript和XML AJAX作用&#xff1a; 与服务器进行数据交换&#xff1a;通过AJAX可以给服务器发送请求&#xff0c;并获取服务器响应的数据 使用了AJAX和服务器进行通信&#xff0c;就可以使用H…

lv15 平台总线驱动开发——ID匹配 3

一、ID匹配之框架代码 id匹配&#xff08;可想象成八字匹配&#xff09;&#xff1a;一个驱动可以对应多个设备 ------优先级次低&#xff08;上一章名称匹配只能1对1&#xff09; 注意事项&#xff1a; device模块中&#xff0c;id的name成员必须与struct platform_device中…

MySQL主从环境,主库改端口后,从库如何操作?

主库&#xff1a;mysql-111 从库&#xff1a;mysql-112 主库由3306端口修改成3307后&#xff0c; 从库执行如下命令 mysql> stop slave; mysql> change master to master_port3307; mysql> CHANGE MASTER TO MASTER_HOST192.168.10.111,MASTER_USERbeifen,MASTER_PA…

npm install 安装依赖如何加速

在使用npm安装依赖时&#xff0c;有几种方法可以加速这一过程&#xff0c;尤其是在面临网络限制或npm官方源速度慢的情况下。以下是一些常用的加速技巧&#xff1a; 1. 使用国内镜像源 国内有几个镜像源可以提供更快的下载速度&#xff0c;例如淘宝npm镜像。你可以通过以下命…

如何用一根网线和51单片机做简单门禁[带破解器]

仓库:https://github.com/MartinxMax/Simple_Door 支持原创是您给我的最大动力… 原理 -基础设备代码程序- -Arduino爆破器程序 or 51爆破器程序- 任意选一个都可以用… —Arduino带TFT屏幕——— —51带LCD1602——— 基础设备的最大密码长度是0x7F&#xff0c;因为有一位…

Excel模板1:彩色甘特图

Excel模板1&#xff1a;彩色甘特图 分享地址 当前效果&#xff1a;只需要填写进度&#xff0c; 其余效果都是自动完成的 。 阿里网盘永久分享&#xff1a;https://www.alipan.com/s/cXhq1PNJfdm ​省心。能用公式的绝不使用手动输入。 ​​ 这个区域以及标题可以手动输入…

Python爬虫——解析库安装(1)

目录 1.lxml安装2.Beautiful Soup安装3.pyquery 的安装 我创建了一个社区&#xff0c;欢迎大家一起学习交流。社区名称&#xff1a;Spider学习交流 注&#xff1a;该系列教程已经默认用户安装了Pycharm和Anaconda&#xff0c;未安装的可以参考我之前的博客有将如何安装。同时默…

机器学习之局部最优和全局最优

(1)局部最优&#xff0c;就是在函数值空间的一个有限区域内寻找最小值;而全局最优&#xff0c;是在函数值空间整个区域寻找最小值问题。 (2)函数局部最小点是它的函数值小于或等于附近点的点&#xff0c;但是有可能大于较远距离的点。 (3)全局最小点是那种它的函数值小于或等于…

二叉树-------前,中,后序遍历 + 前,中,后序查找+删除节点 (java详解)

目录 提要&#xff1a; 创建一个简单的二叉树&#xff1a; 二叉树的前中后序遍历&#xff1a; 二叉树的前序遍历&#xff1a; 二叉树的中序遍历&#xff1a; 二叉树的后续遍历&#xff1a; 小结&#xff1a; 二叉树的前中后续查找&#xff1a; 二叉树的前序查找&#…

Python 数据可视化之山脊线图 Ridgeline Plots

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 JoyPy 是一个基于 matplotlib pandas 的单功能 Python 包&#xff0c;它的唯一目的是绘制山脊线图 Joyplots&#xff08;也称为 Ridgeline Plots&…

SpringMVC原理(设计原理+启动原理+工作原理)

文章目录 前言正文一、设计原理1.1 servlet生命周期简述1.2 设计原理小结 二、启动原理2.1 AbstractHandlerMethodMapping 初始化 --RequestMapping注解解析2.2 DispatcherServlet 的初始化2.3 DispatcherServlet#initHandlerMappings(...) 初始化示例说明 三、工作原理 前言 …

python - OSError:错误没有名为 [‘pytorch_model.bin‘

python - OSError&#xff1a;错误没有名为 [‘pytorch_model.bin’] 自己训练的模型存储好了以后 model MT5ForConditionalGeneration.from_pretrained(“ner/best”) 之前还可以跑 现在报错 错误没有名为 [‘pytorch_model.bin’] 还原了一下conda env 把四版变成三版了 …

面试前的准备

面试前的准备 Java程序员校招与社招的区别 校招和社招都是企业招聘形式的一种&#xff0c;只是面向的对象不同。校招 只允许在校生参加&#xff0c;社招理论上是任何人都能参加的(包括在校生)。 但是&#xff0c;无论是社招还是校招&#xff0c;它的难度都取决于你的水平高低。…

Unity SRP 管线【第十讲:SRP/URP 图形API】

Unity 封装的图形API 文章目录 Unity 封装的图形API一、 CommandBuffer 要执行的图形命令列表1. CommandBuffer 属性2. CommandBuffer 常用图形API&#xff08;方法&#xff09;(1)设置(2)获取临时纹理 GetTemporaryRT以及释放(3)设置纹理为渲染目标 SetRenderTarget(4)Command…

每日OJ题_递归①_力扣面试题 08.06. 汉诺塔问题

目录 递归算法原理 力扣面试题 08.06. 汉诺塔问题 解析代码 递归算法原理 递归算法个人经验&#xff1a;给定一个任务&#xff0c;相信递归函数一定能解决这个任务&#xff0c;根据任务所需的东西&#xff0c;给出函数参数&#xff0c;然后实现函数内容&#xff0c;最后找出…

Shell 学习笔记(三)-shell变量

Shell 语言是一种动态类型和弱类型语言, 因此,在Shell中无需显示地声明变量, 且变量的类型会根据不同的操作符而发生变化. 静态类型语言: 在程序编译期间就确定变量类型的语言, 如java, C等 动态类型语言: 在程序运行期间才确定变量类型的语言, 如PHP, Python等. 一 shell变量…