资料
讯飞官网:星火认知大模型Web文档 | 讯飞开放平台文档中心 (xfyun.cn)
说明
- 对接讯飞的大模型采用的websockt 我们这边采用webflux来实现
测试代码
- 测试代码如下
@Test
public void testFlux() throws Exception {
String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
String url = authUrl.replace("http://", "ws://").replace("https://", "wss://");
ReactorNettyWebSocketClient client = new ReactorNettyWebSocketClient();
Flux.create(fluxSink -> {
new Thread(()-> client.execute(URI.create(url), session ->session.send(Flux.just(session.textMessage("""
{
"header": {
"app_id": "81d533e9",
"uid": "1111111"
},
"parameter": {
"chat": {
"domain": "general",
"temperature": 0.5,
"max_tokens": 1024
}
},
"payload": {
"message": {
"text": [
{"role": "user", "content": "你是谁"}
]
}
}
}
"""))).thenMany(session.receive().map(WebSocketMessage::getPayloadAsText).doOnNext(fluxSink::next)).then()).block(Duration.ofSeconds(60L))).start();
}).subscribe(System.out::println);
Thread.sleep(60000);
}
public 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();
// System.err.println(httpUrl.toString());
return httpUrl.toString();
}
- 注意将 hostUrl, apiKey, apiSecret都换成自己的
实战代码
- 由于无法直接返回其流式数据 我这里采用线程池的方式来实现返回流式数据 再交由上级进行处理 方便抽像
public Flux<String> send(List<MessageContentDto> messages) {
String authUrl = getAuthUrl("https://spark-api.xf-yun.com/v1.1/chat", chatProperties.getFLy().getApiKey(), chatProperties.getFLy().getApiSecret());
String url = authUrl.replace("http://", "ws://").replace("https://", "wss://");
ReactorNettyWebSocketClient client = new ReactorNettyWebSocketClient();
return Flux.create(fluxSink ->
makePool.execute(()-> client.execute(URI.create(url), session -> session
.send(Flux.just(session.textMessage(
Objects.requireNonNull(JsonUtils.writeToJson(createFlySendDto(messages, chatProperties.getFLy().getAppId())))
)))
.thenMany(session.receive()
.map(WebSocketMessage::getPayloadAsText)
.doOnNext(fluxSink::next)).then()).block(Duration.ofSeconds(120))));
}
项目成果
网址地址:欢迎来到我的ChatGPT (error.cool)
目前已经对接了ChptGPT和讯飞(实现上下文共享无缝切换) 后续将扩展更多功能