Application address
https://xinghuo.xfyun.cn/sparkapi?scr=price
Apply for 2 million Tokens for free
Development documentation
https://www.xfyun.cn/doc/spark/Web.html#_1-Interface Description
There are related demos at the bottom of the page for reference.
introduce
The interface is returned in segments in the form of sockets, and non-http requests are relatively cumbersome. The official only provides a relatively simple demo.
Dependencies
<!--okhttp3-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<!-- AliJSONparser -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
Configuration file
xunfei:
ai:
hostUrl: https://spark-api.xf-yun.com/v3.5/chat
appId: xxx
apiSecret: xxx
apiKey: xxx
You can view the API authentication string on the console
Read configuration file
@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;
Permission verification
What you get is a url, you need to replace http with ws
/**
* Permission verification
* @return String
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws MalformedURLException
*/
private String getAuthUrl() throws NoSuchAlgorithmException, InvalidKeyException, MalformedURLException {
URL url = new URL(hostUrl);
// time
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());
// Splicing
String preStr = "host: " + url.getHost() + "\n" +
"date: " + date + "\n" +
"GET " + url.getPath() + " HTTP/1.1";
// System.err.println(preStr);
// SHA256encryption
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));
// Base64encryption
String sha = Base64.getEncoder().encodeToString(hexDigits);
// System.err.println(sha);
// Splicing
String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
// splicing address
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();
}
Build request parameters
The request parameters are sent in json format. If you need to combine previous information to continue answering, you need to bring the history record. You can also view it in the official api documentation
#Parameter construction example is as follows
{
"header": {
"app_id": "12345",
"uid": "12345"
},
"parameter": {
"chat": {
"domain": "generalv3.5",
"temperature": 0.5,
"max_tokens": 1024,
}
},
"payload": {
"message": {
# If you want a contextual answer,The developer needs to transmit the historical question and answer information to the server every time.,Example as below
# Notice:textall insidecontentcontent added togethertokensneed to be controlled8192within,If developers need longer conversations,Historical information needs to be appropriately tailored
"text": [
{"role":"system","content":"You are now playing Li Bai,You are so proud,Unruly;Next, please use Li Bai’s tone to talk to the user.。"} #Set dialogue background or model character
{"role": "user", "content": "Who are you"} # User history issues
{"role": "assistant", "content": "....."} # AIHistorical answer results for
# ....... omitted historical dialogue
{"role": "user", "content": "what will you do"} # The latest question,without context,You can only upload the latest question
]
}
}
}
JAVA BUILD
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","Please answer me about some production safety content");
//Define session context
history.getJSONObject("message").getJSONArray("text").add(0,back);
return body.toJSONString();
}
Reply message
Based on OKHTTP3 request library, connect websocket
/**
* Reply message
* @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() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
webSocket.send(body);
//Send a message
}
@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); // Pass the received message to CompletableFuture
}
}
} );
String result = messageReceived.get(30, TimeUnit.SECONDS);; // Block waiting for message return
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));
}
Complete code
Controller layer
@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;
/**
* Reply message
* @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() {
@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); // Pass the received message to CompletableFuture
}
}
} );
String result = messageReceived.get(30, TimeUnit.SECONDS);; // Block waiting for message return
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","please answer me about somexxxContent");
history.getJSONObject("message").getJSONArray("text").add(0,back);
return body.toJSONString();
}
/**
* Permission verification
* @return String
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws MalformedURLException
*/
private String getAuthUrl() throws NoSuchAlgorithmException, InvalidKeyException, MalformedURLException {
URL url = new URL(hostUrl);
// time
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());
// Splicing
String preStr = "host: " + url.getHost() + "\n" +
"date: " + date + "\n" +
"GET " + url.getPath() + " HTTP/1.1";
// System.err.println(preStr);
// SHA256encryption
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));
// Base64encryption
String sha = Base64.getEncoder().encodeToString(hexDigits);
// System.err.println(sha);
// Splicing
String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
// splicing address
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();
}
}