首页 > 编程语言 >Java对接科大讯飞星火大模型实战

Java对接科大讯飞星火大模型实战

时间:2023-10-20 15:11:40浏览次数:39  
标签:Java String request static 星火 科大 import new com

Java对接讯飞认知大模型教程,先注册账号领取免费测试额度

获取个人免费额度

个人免费 购买 星火认知大模型V2.0

获取秘钥

平台地址: 讯飞开放平台

image

pom.xml 文件

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.java-websocket</groupId>
        <artifactId>Java-WebSocket</artifactId>
        <version>1.3.8</version>
    </dependency>

    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.16</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.67</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

核心调用类


package com.xunfei;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.HMac;
import com.alibaba.fastjson.JSONObject;
import com.xunfei.domain.RoleContent;
import com.xunfei.domain.request.Request;
import com.xunfei.domain.request.header.Header;
import com.xunfei.domain.request.parameter.Chat;
import com.xunfei.domain.request.parameter.Parameter;
import com.xunfei.domain.request.payload.Message;
import com.xunfei.domain.request.payload.Payload;
import com.xunfei.domain.response.payload.Text;
import com.xunfei.domain.response.Result;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.util.UriComponentsBuilder;


import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 讯飞大模型测试类
 *
 * @author Linzj
 * @date 2023/10/19/019 16:25
 */
public class XunFeiBigModelMain {

    private static final Logger log = LoggerFactory.getLogger(XunFeiBigModelMain.class);

    /**
     * 请求地址
     */
    private static final String HOST_URL = "https://spark-api.xf-yun.com/v2.1/chat";

    /**
     * v2版本
     */
    private static final String DOMAIN_2 = "generalv2";

    /**
     * APPID
     */
    private static final String APPID = "109ed2a8";

    /**
     * APISecret
     */
    private static final String API_SECRET = "YTUxNmQ4ZDQyZWQ3N2UzYTE4YTlhYTUz";

    /**
     * APIKey
     */
    private static final String API_KEY = "803e4a5f8354e52a5ddd5258059847ba";

    /**
     * user表示是用户的问题
     */
    private static final String ROLE_USER = "user";

    /**
     * assistant表示AI的回复
     */
    private static final String ROLE_ASSISTANT = "assistant";

    /**
     * 接口响应内容集合
     */
    private static final LinkedList<Result> RESULT_LINKED_LIST = new LinkedList<>();

    /**
     * 对话历史存储集合
     */
    public static List<RoleContent> historyList = new LinkedList<>();

    public static void main(String[] args) throws MalformedURLException, URISyntaxException {
        System.out.println("您好,这里是星火认知大模型,请问有什么可以帮您的吗?");
        while (true) {
            Scanner scanner = new Scanner(System.in);
            String content = scanner.nextLine();
            // 如果键入“结束对话”,则跳出循环,终止程序
            if (Objects.equals(content, "结束对话")) {
                System.out.println("好的,再见!");
                break;
            }
            System.out.println("我:" + content);
            websocketClient(getAuthUrl(), createReqParams(content));
        }
    }


    /**
     * websocket 连接
     *
     * @param authUrl   鉴权地址
     * @param reqParams 请求参数
     * @throws URISyntaxException 异常
     */
    private static void websocketClient(String authUrl, String reqParams) throws URISyntaxException {
        String url = authUrl.replace("http://", "ws://").replace("https://", "wss://");
        URI uri = new URI(url);
        WebSocketClient webSocketClient = new WebSocketClient(uri) {
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
                RESULT_LINKED_LIST.clear();
                send(reqParams);
            }

            @Override
            public void onMessage(String s) {
                // 错误码,0表示正常
                final int successCode = 0;
                // 会话状态,2代表最后一个结果
                final int lastStatus = 2;

                Result result = JSONObject.parseObject(s, Result.class);
                com.xunfei.domain.response.header.Header header = result.getHeader();
                if (Objects.equals(successCode, header.getCode())) {
                    RESULT_LINKED_LIST.add(result);
                } else {
                    log.error("大模型接口响应异常,错误码:{},sid:{}", header.getCode(), header.getSid());
                }

                // 如果是最后的结果,整合答复数据打印出来
                if (Objects.equals(lastStatus, header.getStatus())) {
                    printReply();
                }
            }

            @Override
            public void onClose(int i, String s, boolean b) {
                // log.info("WebSocket连接已关闭,原因:{},状态码:{},是否远程关闭:{}", i, s, b);
            }

            @Override
            public void one rror(Exception e) {
                log.error("大模型接口调用发生异常,异常原因:{},异常位置:{}", e.getMessage(), e.getStackTrace()[0]);
            }
        };
        webSocketClient.connect();
    }

    /**
     * 生成请求参数
     *
     * @param content 对话内容
     * @return 请求参数
     */
    public static String createReqParams(String content) {
        // 组装接口请求参数
        Header header = new Header();
        header.setAppId(APPID);

        Chat chat = new Chat();
        chat.setDomain(DOMAIN_2);
        Parameter parameter = new Parameter();
        parameter.setChat(chat);

        Message message = new Message();
        if (historyList.isEmpty()) {
            com.xunfei.domain.request.payload.Text text = new com.xunfei.domain.request.payload.Text();
            text.setRole(ROLE_USER);
            text.setContent(content);
            message.setText(Collections.singletonList(text));

            // 添加历史对话集合
            RoleContent roleContent = new RoleContent();
            roleContent.setRole(ROLE_USER);
            roleContent.setContent(content);
            historyList.add(roleContent);
        } else {
            // 添加历史对话集合
            RoleContent roleContent = new RoleContent();
            roleContent.setRole(ROLE_USER);
            roleContent.setContent(content);
            historyList.add(roleContent);
            delHistory();

            List<com.xunfei.domain.request.payload.Text> textList = historyList.stream()
                    .map(item -> {
                        com.xunfei.domain.request.payload.Text text = new com.xunfei.domain.request.payload.Text();
                        text.setContent(item.getContent());
                        text.setRole(item.getRole());
                        return text;
                    })
                    .collect(Collectors.toList());
            message.setText(textList);
        }

        Payload payload = new Payload();
        payload.setMessage(message);

        Request request = new Request();
        request.setHeader(header);
        request.setParameter(parameter);
        request.setPayload(payload);
        return JSONObject.toJSONString(request);
    }


    /**
     * URL鉴权
     *
     * @return 请求url
     * @throws MalformedURLException 异常
     */
    private static String getAuthUrl() throws MalformedURLException {
        String date = DateUtil.format(new Date(), DatePattern.HTTP_DATETIME_FORMAT);
        URL url = new URL(HOST_URL);
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";

        HMac hMac = SecureUtil.hmacSha256(API_SECRET.getBytes(StandardCharsets.UTF_8));
        byte[] digest = hMac.digest(preStr);
        String signature = Base64.encode(digest);
        String authorizationOrigin = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
                API_KEY, "hmac-sha256", "host date request-line", signature);
        String authorization = Base64.encode(authorizationOrigin);
        return UriComponentsBuilder.fromUriString(HOST_URL)
                .queryParam("authorization", authorization)
                .queryParam("date", date)
                .queryParam("host", url.getHost()).toUriString();
    }

    /**
     * 如果历史数据太大,将前面的历史数据清除一些
     */
    public static void delHistory() {
        // 由于历史记录最大上线1.2W左右,如果最大值,删除前面的数据
        final int maxLength = 12000;
        Iterator<RoleContent> iterator = historyList.iterator();
        while (iterator.hasNext()) {
            iterator.next();
            int historyLength = historyList.stream()
                    .map(RoleContent::getContent)
                    .collect(Collectors.joining()).length();
            if (historyLength > maxLength) {
                iterator.remove();
            } else {
                break;
            }
        }
    }

    /**
     * 打印星火认知大模型回复内容
     */
    private static void printReply() {
        String content = RESULT_LINKED_LIST.stream()
                .map(item -> item.getPayload().getChoices().getText())
                .flatMap(Collection::stream)
                .map(Text::getContent)
                .collect(Collectors.joining());
        RoleContent roleContent = new RoleContent();
        roleContent.setRole(ROLE_ASSISTANT);
        roleContent.setContent(content);
        historyList.add(roleContent);
        System.out.println("星火认知大模型:" + content);
    }
}

相关文档

通用鉴权URL生成说明

其他一些实体类就不详细写了,文末有项目地址,可以自行获取,或者照着官方文档自己写一下

最终效果

image

对接完成,全部代码已提交至Gitee 讯飞大模型

标签:Java,String,request,static,星火,科大,import,new,com
From: https://www.cnblogs.com/Linzj5950/p/17777153.html

相关文章

  • 在Java中,可以使用`java.nio.file`包中的`Files`类来进行文件搜索。以下是一种模糊搜索
    在Java中,可以使用`java.nio.file`包中的`Files`类来进行文件搜索。以下是一种模糊搜索文件的方法:```javaimportjava.io.IOException;importjava.nio.file.*;importjava.nio.file.attribute.BasicFileAttributes;publicclassFileSearch{publicstaticvoidmain(String......
  • Java拾贝第七天——包装类、BigInteger、BigDecimal
    Java拾贝不建议作为0基础学习,都是本人想到什么写什么基本数据类型怎么变化引用数据类型(对象)Java为每种基本类型都提供了对应的包装类型:基本数据类型包装类intIntegercharCharactershortShortlongLongfloatFloatdoubleDoublebooleanBoolean......
  • Java基础的转义符、数据类型和标识符
    1.转义符把字符转义成特殊含义或原来意思,这就是转义符的作用例如:1publicclassDemo{2publicstaticvoidmain(String[]args){3//\":因为在Java中双引号(")是有特殊含义的双引号是成双成对出现的4//当你想打印一个双引号时,就需要运用转义......
  • java如何导入导出excel
     在Java中,可以使用多种方式导入和导出Excel文件。下面将详细介绍几种常见的方法及其实现步骤:1.ApachePOI库:  ApachePOI是一个开源的Java库,提供了许多类和方法用于处理MicrosoftOffice格式的文档,包括Excel文件。  -导入Excel文件:   1.导入POI库:首先需要在......
  • Java 多线程例子1 小例子
    学习的张孝祥的《Java就业培训教程》觉得讲的不错,是比较好的入门教程吧。下面是最简单的例子。publicclassThreadDemo{ publicstaticvoidmain(String[]args){ newTestThread().start(); while(true){ System.out.println("main():"+Thread.currentThread().getN......
  • Java的文件路径
    1,访问该类所在目录下的文件:如结构: 现在Tst.java中想要访问note.txt文件,这样就行:getClass().getResource("note.txt")得到java.net.URL或:getClass().getResourceAsStream("note.txt")得到InputStream。或:Tst.class.getResource("note.txt")2,访问同一项目下的文件:如结构: 现在AAA.ja......
  • Java中四种XML解析技术(DOM、SAX、Jdom、DOM4j)
    在平时工作中,难免会遇到把XML作为数据存储格式。面对目前种类繁多的解决方案,哪个最适合我们呢?在这篇文章中,我对这四种主流方案做一个不完全评测,仅仅针对遍历XML这块来测试,因为遍历XML是工作中使用最多的(至少我认为)。预备测试环境:AMD毒龙1.4GOC1.5G、256M......
  • Java的引用传替
    publicclassSample{ publicstaticvoidmain(String[]args){ AobjectA=newA(); System.out.println(objectA.a); add(objectA); System.out.println(objectA.a); } privatestaticvoidadd(AobjectA){ objectA.a=1; }}classA{ inta=......
  • Java中运行音频文件
    publicclassMp3Player{publicstaticvoidmain(Stringargs[]){try{ FileInputStreamfileau=newFileInputStream(newFile("f:/tmp/ss.wav")); AudioStreamas=newAudioStream(fileau); ......
  • Java 多线程例子2 前台线程(用户线程) 后台线程(守护线程 ) setDaemon
    1,setDaemon(true)后就是后台线程(守护线程),反之就是前台线程(用户线程)2,后台线程和前台线程的区别:在java程序中如果所以的前台线程都已经退出,所有的后台线程自动退出。TestThread为后台线程:publicclassThreadDemo{ publicstaticvoidmain(String[]args){ Threadt=newTes......