• 2.5k的ChatGPT-Java版SDK升级1.1.2-beta0支持GPT-4V、Dall-e-3模型、ToolCalls、微调Job、TTS...


    1、项目简介

    Chatgpt-Java是OpenAI官方Api的Java SDK,可以快速接入项目使用。支持OpenAI官方全部接口。
    目前收获将2500+star🌟。

    • 开源地址:https://github.com/Grt1228/chatgpt-java
    • 官方文档:https://chatgpt-java.unfbx.com/
    • 最新版本:1.1.2-beta0
    <dependency>
        <groupId>com.unfbxgroupId>
        <artifactId>chatgpt-javaartifactId>
        <version>1.1.2-beta0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    目前支持的功能:

    Dall-e-3FineTuneJobTTSChatCompletionWithPicture
    AI生成图片微调job文本转语音附加图片的ChatCompletion
    TikTokenChatCompletionsImagesSpeech To Text余额查询
    Token计算GPT-3.5、4.0对话模型GPT-3.0对话图片模型语音转文字,语音翻译余额查询
    EmbeddingsFilesModerationsFine-tuneModels
    嵌入自定义训练模型文本审核,敏感词鉴别微调模型检索相关

    OpenAi在上周更新了新的版本,发布了很多新的功能,包括GPT-4V、附加图片的ChatCompletion、指定返回数据格式、Tool Call、Dall-e-3生成图片、FineTuneJob、文本转语音TTS等等功能。

    本周Chatgpt-Java同步更新,支持最新的Api。

    2、新版本更新

    所以的新版本Api更新基于原有的OpenAiClient和OpenAiStreamClient,所以构建客户端的当时是没有变化的。

    创建Client如下:

    @Slf4j
    public class OpenAiClientTest {
    
        private OpenAiClient client;
        private OpenAiStreamClient streamClient;
        
        @Before
        public void before() {
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
            //!!!!千万别再生产或者测试环境打开BODY级别日志!!!!
            //!!!生产或者测试环境建议设置为这三种级别:NONE,BASIC,HEADERS,!!!
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
            OkHttpClient okHttpClient = new OkHttpClient
                    .Builder()
                    .addInterceptor(httpLoggingInterceptor)
                    .addInterceptor(new OpenAiResponseInterceptor())
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .build();
            client = OpenAiClient.builder()
                    .apiKey(Arrays.asList("*********************"))
                    .okHttpClient(okHttpClient)
                    //自己做了代理就传代理地址,没有可不不传,(关注公众号回复:openai ,获取免费的测试代理地址)
                    .apiHost("https://*******/")
                    .build();
    
            streamClient = OpenAiStreamClient.builder()
                    //支持多key传入,请求时候随机选择
                    .apiKey(Arrays.asList("*********************"))
                    .okHttpClient(okHttpClient)
                    //自己做了代理就传代理地址,没有可不不传,(关注公众号回复:openai ,获取免费的测试代理地址)
                    .apiHost("https://*******/")
                    .build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    2.1、附加图片的chatCompletion示例

    2.1.1、阻塞请求

    /**
     * 聊天模型支持图片流式示例
     */
    @Test
    public void pictureChat() {
        Content textContent = Content.builder().text("What’s in this image?").type(Content.Type.TEXT.getName()).build();
        ImageUrl imageUrl = ImageUrl.builder().url("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg").build();
        Content imageContent = Content.builder().imageUrl(imageUrl).type(Content.Type.IMAGE_URL.getName()).build();
        List<Content> contentList = new ArrayList<>();
        contentList.add(textContent);
        contentList.add(imageContent);
        MessagePicture message = MessagePicture.builder().role(Message.Role.USER).content(contentList).build();
        //#####请求参数使用ChatCompletionWithPicture类
        ChatCompletionWithPicture chatCompletion = ChatCompletionWithPicture
                .builder()
                .messages(Collections.singletonList(message))
                .model(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName())
                .build();
        ChatCompletionResponse chatCompletionResponse = client.chatCompletion(chatCompletion);
        chatCompletionResponse.getChoices().forEach(e -> System.out.println(e.getMessage()));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2.1.2、流式请求

    /**
     * 聊天模型支持图片流式示例
     */
    @Test
    public void pictureChatV2() {
        Content textContent = Content.builder().text("What’s in this image?").type(Content.Type.TEXT.getName()).build();
        ImageUrl imageUrl = ImageUrl.builder().url("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg").build();
        Content imageContent = Content.builder().imageUrl(imageUrl).type(Content.Type.IMAGE_URL.getName()).build();
        List<Content> contentList = new ArrayList<>();
        contentList.add(textContent);
        contentList.add(imageContent);
        MessagePicture message = MessagePicture.builder().role(Message.Role.USER).content(contentList).build();
        ChatCompletionWithPicture chatCompletion = ChatCompletionWithPicture
                .builder()
                .messages(Collections.singletonList(message))
                .model(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName())
                .build();
        ChatCompletionResponse chatCompletionResponse = client.chatCompletion(chatCompletion);
        chatCompletionResponse.getChoices().forEach(e -> System.out.println(e.getMessage()));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.1.3、注意事项

    附加图片的chatCompletion暂时不支持以下简易接口请求

    • public void streamChatCompletion(List messages, EventSourceListener el)
    • public ChatCompletionResponse chatCompletion(List messages)

    2.2、ChatGPT指定返回Json格式

    最新版的OpenAi接口支持执行数据返回格式。以下仅举例阻塞输出的方案,流式输出一样的使用方法不再举例。

    指定数据格式目前支持:

    • json_object
    • text

    参考源码:com/unfbx/chatgpt/entity/chat/ResponseFormat.java

    2.2.1、请求

    /**
     * 自定义返回数据格式
     */
    @Test
    public void diyReturnDataModelChat() {
        Message message = Message.builder().role(Message.Role.USER).content("随机输出10个单词,使用json输出").build();
        ChatCompletion chatCompletion = ChatCompletion
            .builder()
            .messages(Collections.singletonList(message))
            .responseFormat(ResponseFormat.builder().type(ResponseFormat.Type.JSON_OBJECT.getName()).build())
            .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName())
            .build();
        ChatCompletionResponse chatCompletionResponse = client.chatCompletion(chatCompletion);
        chatCompletionResponse.getChoices().forEach(e -> System.out.println(e.getMessage()));
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    {
      "words": [
        "aberration",
        "nostalgia",
        "quintessential",
        "harmony",
        "serendipity",
        "benevolent",
        "ephemeral",
        "labyrinth",
        "zenith",
        "vivacious"
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.3、Dall-e-3生成图片(AI绘画)

    最新版的OpenAi接口支持Dall-e-3模型生成图片,功能更加强大。

    2.3.1、请求

    /**
     * 新版图片生成模型使用示例
     */
    @Test
    public void generateImageByDall_e_3() {
        Image image = Image.builder()
            .responseFormat(com.unfbx.chatgpt.entity.images.ResponseFormat.URL.getName())
            .model(Image.Model.DALL_E_3.getName())
            .prompt("一个咖啡杯,上面印刷Unfbx四个字母。")
            .n(1)
            .quality(Image.Quality.HD.getName())
            .size(SizeEnum.size_1024_1792.getName())
            .style(Image.Style.NATURAL.getName())
            .build();
        ImageResponse imageResponse = client.genImages(image);
    //        ImageResponse imageResponse = client.genImages("一个咖啡杯,上面印刷Unfbx四个字母。");
        System.out.println(imageResponse.getData().get(0).getUrl());
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.4、FineTuneJob微调job

    OpenAi支持自定义训练专属模型,通过FineTuneJob进行模型微调训练。
    FineTuneJob支持的模型有:

    • gpt-3.5-turbo-1106
    • gpt-3.5-turbo-0613
    • babbage-002
    • gpt-4-0613
    • davinci-002

    更多详细参考源码:com/unfbx/chatgpt/entity/fineTune/job/FineTuneJob.java

    2.4.1、创建训练数据文件

    创建文件格式为json1下面是一个示例文件:fine_tune_test_file.json1
    文件在github源码根目录,文件内容;

    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "chagpt-java好用么?"}, {"role": "assistant", "content": "还行吧。"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "chagpt-java最新版本是什么?"}, {"role": "assistant", "content": "1.1.2版本"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "chagpt-java支持流式输出么?"}, {"role": "assistant", "content": "最新版支持流式输出"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "chagpt-java的作者是谁?"}, {"role": "assistant", "content": "作者是Unfbx,个人网站:https://www.unfbx.com"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "Unfbx是chagpt-java的作者,微信公众号是什么?"}, {"role": "assistant", "content": "程序员的黑洞。"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "Unfbx是chagpt-java的作者,个人博客地址是什么?"}, {"role": "assistant", "content": "https://www.unfbx.com"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "Unfbx是chagpt-java的作者,chagpt-java官方地址是什么?"}, {"role": "assistant", "content": "https://chatgpt-java.unfbx.com"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "Unfbx是chagpt-java的作者,chagpt-java的github地址是什么?"}, {"role": "assistant", "content": "https://github.com/Grt1228/chatgpt-java"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "Unfbx是chagpt-java的作者,chagpt-java的简单介绍。"}, {"role": "assistant", "content": "OpenAI官方Api的Java SDK,可以快速接入项目使用。目前支持OpenAI官方全部接口,**同时支持Tokens计算。参考文档:[Tokens_README.md](https://github.com/Grt1228/chatgpt-java/blob/main/Tokens_README.md)**"}]}
    {"messages": [{"role": "system", "content": "OnBot是一个聊天机器人。"}, {"role": "user", "content": "OpenAi的官方Java Sdk 是什么?"}, {"role": "assistant", "content": "chagpt-java,github地址:https://github.com/Grt1228/chatgpt-java"}]}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.4.2、上传文件

    /**
     * fineTuneJob使用示例
     */
    @Test
    public void uploadFile() {
        UploadFileResponse uploadFileResponse = client.uploadFile(new java.io.File("fine_tune_test_file.json1"));
        //返回文件的id:file-6KaBdtVlaassk9Y2P5ZjTqIC
        System.out.println(uploadFileResponse.getId());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.4.3、创建微调job

    @Test
    public void fineTuneJob() {
        //file-KaNQn5V9YHlLqVQzo8CUMdIr是文件上传返回的文件id
        FineTuneJobResponse fineTuneJobResponse = client.fineTuneJob("file-KaNQn5V9YHlLqVQzo8CUMdIr");
        //返回job id = ftjob-5WQr0bZ7grvjnY3Or2sqiixl
        System.out.println(fineTuneJobResponse.toString());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.4.4、查看微调job

    2.4.4.1、详细信息
    • FineTuneJobResponse的fineTunedModel属性就是微调的模型id,也是后续使用的模型id

    需要主义只有FineTuneJob执行完成fineTunedModel属性才会有值,job失败或者未执行完成此属性为null。

    结合第4.0章节可以看到job的执行信息。

    @Test
    public void retrieveFineTuneJob() {
        //传入job id
        FineTuneJobResponse fineTuneJobResponse = client.retrieveFineTuneJob("ftjob-5WQr0bZ7grvjnY3Or2sqiixl");
        System.out.println(fineTuneJobResponse);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2.4.4.2、job列表

    支持分页查询

    @Test
    public void retrieveFineTuneJob() {
    
    //        FineTuneJobListResponse jobListResponse = client.fineTuneJobs("ftjob-cG7zIraBhAkq5Ybs7311lH7t", 5);
        FineTuneJobListResponse<FineTuneJobResponse> jobListResponse = client.fineTuneJobs(null, 20);
        System.out.println(jobListResponse);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.4.5、微调job执行进度查询

    支持分页查询,支持分页

    @Test
    public void fineTuneJobEvents() {
        FineTuneJobListResponse<FineTuneJobEvent> listResponse = client.fineTuneJobEvents("ftjob-5WQr0bZ7grvjnY3Or2sqiixl", null, 20);
    //        FineTuneJobListResponse listResponse = client.fineTuneJobEvents("ftjob-5WQr0bZ7grvjnY3Or2sqiixl", "ftevent-WwB8lpWxhjgUJX9DYdb47zJe", 20);
        listResponse.getData().forEach(e -> System.out.println(e.getMessage()));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出信息,输出信息会返回创建的模型id,这个就是后续使用的模型id。

        The job has successfully completed
        New fine-tuned model created: ft:gpt-3.5-turbo-1106:personal::8K5KwJTU
        Step 91/100: training loss=0.45
        Step 81/100: training loss=0.00
        Step 71/100: training loss=0.00
        Step 61/100: training loss=0.94
        Step 51/100: training loss=0.19
        Step 41/100: training loss=0.06
        Step 31/100: training loss=0.95
        Step 21/100: training loss=1.99
        Step 11/100: training loss=2.50
        Step 1/100: training loss=5.42
        Fine-tuning job started
        Files validated, moving job to queued state
        Validating training file: file-KaNQn5V9YHlLqVQzo8CUMdIr
        Created fine-tuning job: ftjob-5WQr0bZ7grvjnY3Or2sqiixl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.4.6、微调模型使用

    注意model参数为自定义的模型id。此id会在fineTuneJobEvents完成后返回。

    此id的获取有几种方式:

    • 1、fineTuneJobEvents接口完成后返回。
    • 2、通过3.1章节查询job详细信息可以获取模型id:fineTunedModel属性。
    • 3、models接口返回,参考第5章
    @Test
    public void fineTuneJobModelChat() {
        Message message1 = Message.builder().role(Message.Role.SYSTEM).content("OnBot是一个聊天机器人。").build();
        Message message2 = Message.builder().role(Message.Role.USER).content("OnBot请问:Chatgpt-java的作者是谁?").build();
        List<Message> messages = new ArrayList<>(2);
        messages.add(message1);
        messages.add(message2);
        ChatCompletion chatCompletion = ChatCompletion
                .builder()
                .messages(messages)
                .model("ft:gpt-3.5-turbo-1106:personal::8K5KwJTU")
                .build();
        ChatCompletionResponse chatCompletionResponse = client.chatCompletion(chatCompletion);
        chatCompletionResponse.getChoices().forEach(e -> {
            System.out.println(e.getMessage());
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    输出信息

    作者是Unfbx,个人网站:https://www.unfbx.com
    
    • 1

    2.5、文本转语音TTS

    OpenAi最新接口支持TTS,支持高清语音,支持六种人声。

    2.5.1、文本转语音

    /**
     * tts使用示例
     */
    @Test
    public void textToSpeed() {
        TextToSpeech textToSpeech = TextToSpeech.builder()
                .model(TextToSpeech.Model.TTS_1_HD.getName())
                .input("OpenAI官方Api的Java SDK,可以快速接入项目使用。目前支持OpenAI官方全部接口,同时支持Tokens计算。官方github地址:https://github.com/Grt1228/chatgpt-java。欢迎star。")
                .voice(TtsVoice.NOVA.getName())
                .responseFormat(TtsFormat.MP3.getName())
                .build();
        File file = new File("C:\\Users\\***\\Desktop\\test.mp3");
        client.textToSpeech(textToSpeech, new Callback<ResponseBody>() {
            @SneakyThrows
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                InputStream inputStream = response.body().byteStream();
                //创建文件
                if (!file.exists()) {
                    if (!file.getParentFile().exists())
                        file.getParentFile().mkdir();
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                        log.error("createNewFile IOException");
                    }
                }
    
                OutputStream os = null;
                try {
                    os = new BufferedOutputStream(new FileOutputStream(file));
                    byte data[] = new byte[8192];
                    int len;
                    while ((len = inputStream.read(data, 0, 8192)) != -1) {
                        os.write(data, 0, len);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        if (os != null) {
                            os.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
    
            }
        });
        CountDownLatch countDownLatch = new CountDownLatch(1);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    3、更多

    访问项目开源地址:https://github.com/Grt1228/chatgpt-java
    点一点免费的star
    获取更多SDK功能

  • 相关阅读:
    C++ pair的介绍和使用输出
    python LeetCode 刷题记录 27
    leetcode做题笔记145. 二叉树的后序遍历
    MFC C++ 数据结构及相互转化 CString char * char[] byte PCSTR DWORE unsigned
    Zynq中断与AMP~双核串口环回之PS与PL通信
    Dubbo——初识RPC、Dubbo框架、使用直连方式实现Dubbo
    Hive 视图和索引
    Python语言这么火热,其实具有以下特点
    微信小程序使用阿里巴巴iconfont,报错Failed to load font http://at.alicdn.com/t/..........
    基于Spring boot框架开发的电商网站系统
  • 原文地址:https://blog.csdn.net/tsgjcnyn/article/details/134380659