申请地址

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

开发文档

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

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

介绍

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

依赖项

com.squareup.okhttp3

okhttp

com.alibaba.fastjson2

fastjson2

配置文件

xunfei:

ai:

hostUrl: https://spark-api.xf-yun.com/v3.5/chat

appId: xxx

apiSecret: xxx

apiKey: 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 messageReceived = new CompletableFuture<>();

String body = buildBody(text,uid);

WebSocket webSocket =client.newWebSocket(request, new WebSocketListener() {

@Override

public void onOpen(WebSocket webSocket, Response response) {

webSocket.send(body);

//发送消息

}

@Override

public 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 {

@Autowired

private 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 messageReceived = new CompletableFuture<>();

String body = buildBody(text,uid);

WebSocket webSocket =client.newWebSocket(request, new WebSocketListener() {

@Override

public void onOpen(WebSocket webSocket, Response response) {

webSocket.send(body);

}

@Override

public 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();

}

}

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: