Springboot接入OpenAi/Chat GPT的三种方式

由于现在网上的相关教程并不多外加没有使用代理的demo,所以抛砖引玉,写了三种调用方式,分别是直接访问、非官方SDK访问、官方开源的SDK访问

准备工作

1、导入pom文件(2023.3.30最新版本)

		<dependency>
            <groupId>com.unfbx</groupId>
            <artifactId>chatgpt-java</artifactId>
            <version>1.0.8</version>
        </dependency>
        <dependency>
            <groupId>com.theokanning.openai-gpt3-java</groupId>
            <artifactId>service</artifactId>
            <version>0.11.1</version>
        </dependency>

2、入参
这里的TalkDto 还可以入参maxToken,用于返回最大量的数据,官方计算token大小的方式:中文1字=3token 英文4字=1token。例如: 哈 = 3;ha=1;哈ha=4;哈ha哈h=8
官方计算token地址:https://platform.openai.com/tokenizer

/**
 * @author panx
 * @date 2023/3/29 13:52
 */
public class TalkDto {
    @ApiModelProperty("内容")
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

正文

1、直接访问

  • 优点

    自定义且简便,具有高度的可玩性,所有openAi新增的入参都可以直接用。

  • 缺点

    过于硬核,官方文档为纯英文。已经有轮子了为什么还要自行造车轮呢?

  • 正文

由于我自行封装了请求方式,所以不展示代理怎么进行插入,主要展示Body层,这里是最简单的Body入参。

		Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("model", "gpt-3.5-turbo");
        bodyMap.put("max_tokens", "4096");
        {
            List<Map<String, String>> maps = new ArrayList<>();
            //        Map systemMap = new HashMap<>();
            //        systemMap.put("role", "system");
            //        systemMap.put("content", "你是一个分析师");
            //        maps.add(systemMap);
            Map<String, String> contentMap = new HashMap<>();
            contentMap.put("role", "user");
            contentMap.put("content", talkDto.getContent());
            maps.add(contentMap);
            bodyMap.put("messages", maps);
        }
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Authorization", "Bearer 123456789");

出参可以参考官方文档(https://platform.openai.com/docs/api-reference/chat)或下面的TalkResultDto

2、使用com.unfbx.chatgpt-java

  • 项目地址

https://github.com/Grt1228/chatgpt-java

  • 优点

纯中文文档,网上的demo也很多,更新速度也快,针对中国玩家的使用更便捷。

  • 缺点

不支持别的类型的请求?粗略的找了一下没有找到。
有一些默认值无法去除,而不去除某一些值在长段入参中可能会报错,如果需要去除可能要等更新或自行去https://platform.openai.com/playground调试模型。

  • 正文
       
    @ApiOperation("非官方聊天api捏")
    @PostMapping("/talkByService")
    public ReTurnDto<String> talkByService(@RequestBody TalkDto talkDto) {
        //国内访问需要做代理,国外服务器不需要
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("192.168.45.56", 1080));
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient okHttpClient = new OkHttpClient.Builder().proxy(proxy)//自定义代理
                .addInterceptor(httpLoggingInterceptor)//自定义日志输出
                .addInterceptor(new OpenAiResponseInterceptor())//自定义返回值拦截
                .connectTimeout(10, TimeUnit.SECONDS)//自定义超时时间
                .writeTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .readTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .build();
        //构建客户端
        OpenAiClient openAiClient = OpenAiClient.builder()//构建
                .apiKey(Collections.singletonList("1234577987645"))//token
                .okHttpClient(okHttpClient)//注入okhttp
                .build();
        Message message = Message.builder().role(Message.Role.USER).content(talkDto.getContent()).build();
        ChatCompletion.ChatCompletionBuilder builder = ChatCompletion.builder();
        //聊天模型:gpt-3.5
        builder.model("gpt-3.5-turbo");
        builder.messages(Arrays.asList(message));
        ChatCompletion chatCompletion = builder.build();

        ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
        return new ReTurnDto<>(chatCompletionResponse.getChoices().get(0).getMessage().getContent());
    }

3、使用com.theokanning.openai-gpt3-java.service

  • 项目地址

https://github.com/TheoKanning/openai-java

  • 优点

官方SDK。各种类型的请求都有单独的实体类,使用起来非常便捷。

  • 缺点

更新速度没有上面的快,官方文档不太清晰。由于使用了 Retrofit+OkHttp 中国玩家需要进行繁琐的配置才能使用。

  • 正文
    @ApiOperation("官方api聊天捏")
    @PostMapping("/talkByOpen")
    public ReTurnDto<String> talkByOpen(@RequestBody TalkDto talkDto) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

        //国内访问需要做代理,国外服务器不需要
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 1549));
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().proxy(proxy)//自定义代理
                .addInterceptor(new HttpLoggingInterceptor()).addInterceptor(httpLoggingInterceptor)//自定义日志输出
                .addInterceptor(new AuthOpenAiInterceptor("123456789000"))//token
                .connectTimeout(10, TimeUnit.SECONDS)//自定义超时时间
                .writeTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .readTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .build();

        Retrofit retrofit = new Retrofit.Builder()//构建者
                .client(client).baseUrl("https://api.openai.com/")//url
                .addConverterFactory(JacksonConverterFactory.create(mapper))//jackson
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//
                .build();

        OpenAiApi api = retrofit.create(OpenAiApi.class);
        OpenAiService service = new OpenAiService(api);
        //text-davinci-003
       /* CompletionRequest completionRequest = CompletionRequest.builder()
                .prompt(talkDto.getContent())
                .model("text-davinci-003")
                .maxTokens(2060)
                .build();
        CompletionResult completion = service.createCompletion(completionRequest);
        return new ResponseVo<>(completion.getChoices().get(0).getText());*/
        //gpt-3.5-turbo
        ChatCompletionRequest chatCompletionRequest = new ChatCompletionRequest();
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setRole(ChatMessageRole.USER.value());
        chatMessage.setContent(talkDto.getContent());
        chatCompletionRequest.setModel("gpt-3.5-turbo");
        chatCompletionRequest.setMessages(Collections.singletonList(chatMessage));
        ChatCompletionResult chatCompletion = service.createChatCompletion(chatCompletionRequest);
        return new ReTurnDto<>(chatCompletion.getChoices().get(0).getMessage().getContent());
    }

后期工作

TalkResultDto 如下

/**
 * @author panx
 * @date 2023/3/29 14:35
 */
public class TalkResultDto {

    private String id;
    private String object;
    private Integer created;
    private String model;
    private UsageDto usage;
    private List<ChoicesDto> choices;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getObject() {
        return object;
    }

    public void setObject(String object) {
        this.object = object;
    }

    public Integer getCreated() {
        return created;
    }

    public void setCreated(Integer created) {
        this.created = created;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public UsageDto getUsage() {
        return usage;
    }

    public void setUsage(UsageDto usage) {
        this.usage = usage;
    }

    public List<ChoicesDto> getChoices() {
        return choices;
    }

    public void setChoices(List<ChoicesDto> choices) {
        this.choices = choices;
    }

    public static class UsageDto {
        private Integer prompt_tokens;
        private Integer completion_tokens;
        private Integer total_tokens;

        public Integer getPrompt_tokens() {
            return prompt_tokens;
        }

        public void setPrompt_tokens(Integer prompt_tokens) {
            this.prompt_tokens = prompt_tokens;
        }

        public Integer getCompletion_tokens() {
            return completion_tokens;
        }

        public void setCompletion_tokens(Integer completion_tokens) {
            this.completion_tokens = completion_tokens;
        }

        public Integer getTotal_tokens() {
            return total_tokens;
        }

        public void setTotal_tokens(Integer total_tokens) {
            this.total_tokens = total_tokens;
        }
    }

    public static class ChoicesDto {
        private MessageDto message;
        private String finish_reason;
        private Integer index;

        public MessageDto getMessage() {
            return message;
        }

        public void setMessage(MessageDto message) {
            this.message = message;
        }

        public String getFinish_reason() {
            return finish_reason;
        }

        public void setFinish_reason(String finish_reason) {
            this.finish_reason = finish_reason;
        }

        public Integer getIndex() {
            return index;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }

        public static class MessageDto {
            private String role;
            private String content;

            public String getRole() {
                return role;
            }

            public void setRole(String role) {
                this.role = role;
            }

            public String getContent() {
                return content;
            }

            public void setContent(String content) {
                this.content = content;
            }
        }
    }
}

如果没有代理的话,可以去购买一个香港的服务器,将服务部署在香港服务器中

畅爽使用~

你可能感兴趣的:(java,spring,boot,java,后端)