星火大模型AI接口Spring中项目中使用【星火、AIGC】

2023-10-06 23:01

本文主要是介绍星火大模型AI接口Spring中项目中使用【星火、AIGC】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

星火大模型AI接口使用

讯飞的星火大模型是有免费版本赠送200万个Token,就个人学习来说完全够用了。

请添加图片描述

免费申请过后,到控制台,两个红色方框是最要紧的。

请添加图片描述

星火认知大模型Web文档 | 讯飞开放平台文档中心 (xfyun.cn)这是官方文档对于接口的详细使用,里面有对各种请求的详细描述。接下来我们将在Spring项目中使用星火的AIGC能力。

首先是星火给的APPID、APISecret、APIKey是连接到大模型的关键,通过这三个参数按照通用鉴权URL生成说明 | 讯飞开放平台文档中心 (xfyun.cn)生成通用鉴权URL就可以就行html请求,发送请求参数,接受返回信息。

https://xfyun-doc.cn-bj.ufileos.com/static%2F16933832521697972%2Fbig_model.zip 这是官方给出的Java例子。

通用鉴权URL的生成

官方给的,直接拿来用。

/ 获得鉴权地址public static String getAuthUrl(String hostUrl, String apiSecret, String apiKey) 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();// System.err.println(httpUrl.toString());return httpUrl.toString();}

项目中实现

在项目中使用我们需要一个Config进行全局配置,一个WebListener发送接受请求,还有与星火交互的DTO。

请添加图片描述

1. XfunConfig
/***   星火大模型AI接口配置*/
@Configuration
@Data
@ConfigurationProperties(prefix = "xfun.open")
public class XfunConfig {private String appid;private String apiSecret;private String hostUrl;private String apiKey;
}

在application.yml中的配置

#星火
xfun:open:appid: XXXXXXXXXXXXXXXXXXXXXXXapiSecret: XXXXXXXXXXXXXXXXXXXXXXXhostUrl: https://spark-api.xf-yun.com/v2.1/chatapiKey: XXXXXXXXXXXXXXXXXXXXXXX
3. DTO – Xfun

看官方文档中对请求参数以及对各个字段的解释。

# 参数构造示例如下
{"header": {"app_id": "12345","uid": "12345"},"parameter": {"chat": {"domain": "general","temperature": 0.5,"max_tokens": 1024, }},"payload": {"message": {# 如果想获取结合上下文的回答,需要开发者每次将历史问答信息一起传给服务端,如下示例# 注意:text里面的所有content内容加一起的tokens需要控制在8192以内,开发者如有较长对话需求,需要适当裁剪历史信息"text": [{"role": "user", "content": "你是谁"} # 用户的历史问题{"role": "assistant", "content": "....."}  # AI的历史回答结果# ....... 省略的历史对话{"role": "user", "content": "你会做什么"}  # 最新的一条问题,如无需上下文,可只传最新一条问题]}}
}

请添加图片描述

其中Message单独为一个类

/*** 消息对象**/
@Data
public class MsgDTO {/*** 角色*/private String role;/*** 消息内容*/private String content;private Integer index;@Getterpublic static enum Role {SYSTEM("system"),USER("user"),ASSISTANT("assistant");private String name;private Role(String name) {this.name = name;}}}

这样一个请求构成的数据对象类如下:

@Data
public class XfunSendRequest {@JsonProperty("header")private Header header;@JsonProperty("parameter")private ParameterDTO parameterDTO;@JsonProperty("payload")private PayloadDTO payload;@Datapublic static class Header{@JSONField(name = "app_id")private String appId;@JSONField(name = "uid")private String uid;}@ Datapublic static class ParameterDTO{@JsonProperty("chat")private ChatDTO chat;@Datapublic static class ChatDTO {@JsonProperty("domain")private String domain = "generalv2";@JsonProperty("temperature")private Double temperature = 0.5;@JSONField(name = "max_tokens")private Integer maxTokens = 2048;}}@Datapublic static class PayloadDTO {@JsonProperty("message")private MessageDTO message;@Datapublic static class MessageDTO {@JsonProperty("text")private List<MsgDTO> text;}}}

接下来是构造接口响应对象:

# 接口为流式返回,此示例为最后一次返回结果,开发者需要将接口多次返回的结果进行拼接展示
{"header":{"code":0,"message":"Success","sid":"cht000cb087@dx18793cd421fb894542","status":2},"payload":{"choices":{"status":2,"seq":0,"text":[{"content":"我可以帮助你的吗?","role":"assistant","index":0}]},"usage":{"text":{"question_tokens":4,"prompt_tokens":5,"completion_tokens":9,"total_tokens":14}}}
}

请添加图片描述

由官方描述可见,其中 payload.choice.text中的内容就是构造的MsgDto, 根据官方文档给出的接口响应构造XfunReceieveRequest;

@Data
public class XfunReceieveRequest {@JsonProperty("header")private HeaderDTO header;@JsonProperty("payload")private PayloadDTO payload;@NoArgsConstructor@Datapublic static class HeaderDTO {@JsonProperty("code")private Integer code;@JsonProperty("message")private String message;@JsonProperty("sid")private String sid;@JsonProperty("status")private Integer status;}@NoArgsConstructor@Datapublic static class PayloadDTO {@JsonProperty("choices")private ChoicesDTO choices;@JsonProperty("usage")private UsageDTO usage;@NoArgsConstructor@Datapublic static class ChoicesDTO {@JsonProperty("status")private Integer status;@JsonProperty("seq")private Integer seq;@JsonProperty("text")private List<MsgDTO> text;}@NoArgsConstructor@Datapublic static class UsageDTO {@JsonProperty("text")private TextDTO text;@NoArgsConstructor@Datapublic static class TextDTO {@JsonProperty("question_tokens")private Integer questionTokens;@JsonProperty("prompt_tokens")private Integer promptTokens;@JsonProperty("completion_tokens")private Integer completionTokens;@JsonProperty("total_tokens")private Integer totalTokens;}}}}

这样发送和接受请求都构造完成可以尝试与星火进行交互。

使用WebSocket将XfunSendRequest发出即可;以下是XfunListener中发送消息代码:

    public XfunListener sendMsg(String uid, List<MsgDTO> msgs, XfunListener webSocketListener) throws Exception {// 获取鉴权urlString url = getAuthUrl(hostUrl,apiSecret,apiKey);//建立请求OkHttpClient okHttpClient = new OkHttpClient.Builder().build();Request request = new Request.Builder().url(url).build();WebSocket webSocket = okHttpClient.newWebSocket(request, webSocketListener);XfunSendRequest xfunSendRequest = this.getSendRequest(uid, msgs);System.out.println("params:" + JSONObject.toJSONString(xfunSendRequest));//发送消息webSocket.send(JSONObject.toJSONString(xfunSendRequest));return webSocketListener;}

可以看到整个发送消息的过程:

  1. 建立请求,根据请求创建WebSoeckt
  2. 利用WebSocket发出XfunSendRequest

接受消息写在XfunListener的OnMessage重载函数中,根据XfunReceiveRequest来处理数据;

3. XfunListener

具体代码如下:

最关键的就是两个函数:

  • OnMessage: 接受消息,处理消息
  • SendMsg: 发送消息
@Builder
public class XfunListener extends WebSocketListener {private String hostUrl;private String appid;private String apiSecret;private String apiKey;@Builder.Defaultpublic boolean is_finished = false;@Builder.Defaultprivate String answer = "";public String getAnswer() {return answer;}public boolean isFinished() {return is_finished;}public List<MsgDTO> getHistoryList() {return historyList;}@Builder.Defaultpublic List<MsgDTO> historyList = new ArrayList<>();@Overridepublic void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {super.onOpen(webSocket, response);}public  void deleteHistory(){historyList = new ArrayList<>();}public void init_chat(){is_finished = false;}// 接收到消息如何处理@Overridepublic void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {super.onMessage(webSocket, text);// System.out.println("接收到消息:" + text);// 消息格式处理XfunReceieveRequest xfunReceieveRequest = JSONObject.parseObject(text, XfunReceieveRequest.class);//状态判断if(xfunReceieveRequest.getHeader().getCode() == 0) {// 0的话 ,获取状态成功XfunReceieveRequest.PayloadDTO payload = xfunReceieveRequest.getPayload();XfunReceieveRequest.PayloadDTO.ChoicesDTO choices = payload.getChoices();//处理得到的答案List<MsgDTO> msgs = choices.getText();//打上indexfor(int i = 0; i < msgs.size(); i++){MsgDTO msg =msgs.get(i);msg.setIndex(historyList.size()+i);historyList.add(msg);}if(xfunReceieveRequest.getHeader().getStatus() == 2){//表示会话来到最后一个结果XfunReceieveRequest.PayloadDTO.UsageDTO.TextDTO text1 = payload.getUsage().getText();System.out.println("PromptTokecn:" + text1.getPromptTokens());System.out.println("QuestionToken:" + text1.getQuestionTokens());System.out.println("CompletionToken:" + text1.getCompletionTokens());System.out.println("TotalToken"+text1.getTotalTokens());is_finished = true;// 消息整合StringBuilder message = new StringBuilder();for(MsgDTO msg: historyList){message.append(msg.getContent());}deleteHistory();answer = message.toString();//断开连接// webSocket.close(3,"客户端断开连接");}}}// 获得鉴权地址public static String getAuthUrl(String hostUrl, String apiSecret, String apiKey) 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();// System.err.println(httpUrl.toString());return httpUrl.toString();}// msgs和uid 转成 XfunSendRequestpublic XfunSendRequest getSendRequest(String uid, List<MsgDTO> msgs) {XfunSendRequest xfunSendRequest = new XfunSendRequest();XfunSendRequest.Header header = new XfunSendRequest.Header();header.setAppId(appid);header.setUid(uid);xfunSendRequest.setHeader(header);XfunSendRequest.ParameterDTO parameterDTO = new XfunSendRequest.ParameterDTO();XfunSendRequest.ParameterDTO.ChatDTO chatDTO = new XfunSendRequest.ParameterDTO.ChatDTO();parameterDTO.setChat(chatDTO);xfunSendRequest.setParameterDTO(parameterDTO);XfunSendRequest.PayloadDTO payloadDTO = new XfunSendRequest.PayloadDTO();XfunSendRequest.PayloadDTO.MessageDTO messageDTO = new XfunSendRequest.PayloadDTO.MessageDTO();messageDTO.setText(msgs);payloadDTO.setMessage(messageDTO);xfunSendRequest.setPayload(payloadDTO);return xfunSendRequest;}/***  发送信息*/public XfunListener sendMsg(String uid, List<MsgDTO> msgs, XfunListener webSocketListener) throws Exception {// 获取鉴权urlString url = getAuthUrl(hostUrl,apiSecret,apiKey);//建立请求OkHttpClient okHttpClient = new OkHttpClient.Builder().build();Request request = new Request.Builder().url(url).build();WebSocket webSocket = okHttpClient.newWebSocket(request, webSocketListener);XfunSendRequest xfunSendRequest = this.getSendRequest(uid, msgs);System.out.println("params:" + JSONObject.toJSONString(xfunSendRequest));//发送消息webSocket.send(JSONObject.toJSONString(xfunSendRequest));return webSocketListener;}
}

可以看到这个XfunListener不是一个Bean,所以在MainApplication中创建了这个Bean。

@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
@MapperScan("com.yupi.springbootinit.mapper")
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class MainApplication {@Autowiredprivate XfunConfig xfunConfig;public static void main(String[] args) {SpringApplication.run(MainApplication.class, args);}@Beanpublic XfunListener getXfunListener() {return XfunListener.builder().apiKey(xfunConfig.getApiKey()).apiSecret(xfunConfig.getApiSecret()).hostUrl(xfunConfig.getHostUrl()).appid(xfunConfig.getAppid()).build();}
}

这样整个星火的AIGC就设计完成,可以随意复用在任意的项目之中,利用XfunListener即可发送消息或获取消息。

详细的数据处理,发送消息,另外写一个AI的Service做具体的处理即可。例如以下一个简单的实例:

@Service
public class AiManager {@Resourceprivate XfunListener xfunListener;  // 实现发送接受消息的websockectpublic String testChat(String question){//8位随机数String random = String.valueOf((int)((Math.random()*9+1)*10000000));List<MsgDTO> msgs = new ArrayList<>();MsgDTO msgDTO = new MsgDTO( );msgDTO.setRole("user");msgDTO.setContent(question);msgDTO.setIndex(0);msgs.add(msgDTO);xfunListener.init_chat();try {// 获取接受消息的webSoecktXfunListener webSocket = xfunListener.sendMsg(random, msgs, xfunListener);//等待weSocked返回消息 , 这是一个笨笨的处理方法。int cnt = 30;//最长等待30Swhile (!webSocket.isFinished() && cnt > 0){Thread.sleep(1000);  //休息1Scnt--;}if(cnt == 0){return null;}String answer = webSocket.getAnswer();//返回答案return answer;} catch (Exception e) {throw new RuntimeException(e);}}public static void main(String[] args) {AiManager ai = new AiManager();ai.xfunListener =  XfunListener.builder().apiKey("xxxxxxx").apiSecret("xxxxxxx").appid("xxxxxxx").hostUrl("https://spark-api.xf-yun.com/v2.1/chat").build();System.out.println(ai.testChat("你好啊!"));}}

AiManager运行结果

请添加图片描述

这篇关于星火大模型AI接口Spring中项目中使用【星火、AIGC】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/154455

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取