由于现在网上的相关教程并不多外加没有使用代理的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;
}
}
}
}
如果没有代理的话,可以去购买一个香港的服务器,将服务部署在香港服务器中