对接讯飞火星大模型

447 阅读1分钟

资料

讯飞官网:星火认知大模型Web文档 | 讯飞开放平台文档中心 (xfyun.cn)

说明

  1. 对接讯飞的大模型采用的websockt 我们这边采用webflux来实现

测试代码

  1. 测试代码如下

@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();
}

  1. 注意将 hostUrl, apiKey, apiSecret都换成自己的

image.png

实战代码

  1. 由于无法直接返回其流式数据 我这里采用线程池的方式来实现返回流式数据 再交由上级进行处理 方便抽像
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和讯飞(实现上下文共享无缝切换) 后续将扩展更多功能