ChatGPT API 的 Java 简单使用
> 引言:想着openai送的额度不能浪费,就使用OKHTTP框架做了一个简单的控制台对话实现
请求部分
代码语言:javascript复制/**
* 发送消息请求
* @param msgList 消息列表,包含历史对话
* @param delay 等待回复延迟
* @return ChatGPT回复消息
* @throws IOException Json格式化异常, 返回包execute()异常
*/
private static String sendReq(List<Map<String, String>> msgList, int delay) throws IOException {
assert Main.CONFIG != null;
var httpClient = new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(Main.CONFIG.getProxyUrl(), Main.CONFIG.getPort())))
.callTimeout(60, TimeUnit.SECONDS)
.connectTimeout(delay, TimeUnit.SECONDS)
.readTimeout(delay, TimeUnit.SECONDS)
.build();
var reqBody = Map.of("model", "gpt-3.5-turbo"
, "messages", msgList
, "temperature", 0.7);
var req = new Request.Builder()
.url(Main.CONFIG.getChatGptApi())
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer " Main.CONFIG.getChatGptToken())
.post(RequestBody.create(FileUtil.OBJECT_MAPPER.writeValueAsString(reqBody).getBytes(StandardCharsets.UTF_8)))
.build();
try (var resp = httpClient.newCall(req).execute()) {
if (resp.isSuccessful()) {
assert resp.body() != null;
return resp.body().string();
} else {
return null;
}
}
}
根据 官方文档,需要在请求头中加入 Authorization: Bearer OPENAI_API_KEY
来鉴权,其中 OPENAI_API_KEY
需要自己创建,发文时新注册赠送 5$ 4个月。
请求部分参考这部分 官方文档 可以看到方法的入参有一个集合,其中存储历史对话记录
官方提供的返回Json示例如下,我们重点关注 message 部分
代码语言:javascript复制{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "nnHello there, how may I assist you today?",
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 12,
"total_tokens": 21
}
}
可以看到,api 采用 role
字段表名消息发送者的身份,一共有三种身份 文档
[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}
]
官方的描述是: The main input is the messages parameter. Messages must be an array of message objects, where each object has a role (either "system", "user", or "assistant") and content (the content of the message). Conversations can be as short as 1 message or fill many pages.
通常使用 System
喂给 ChatGPT 一些背景设定,而后交替使用 user
和 assistant
来进行对话。
temperature
的范围在 0 - 2
之间,用于设定生成回复的 "创造力",较高的值生成的内容会更加随机。
对话交互部分
代码语言:javascript复制/**
* 负责对话交互部分
*/
public void chat() {
try {
List<Map<String, String>> msgList = new ArrayList<>();
while (true) {
Main.LOGGER.info("n你:");
String input = Main.SCANNER.nextLine();
if ("exit".equals(input)) {
return;
}
Main.LOGGER.info("请输入本次回复的等待时间(s):");
var delay = Integer.parseInt(Main.SCANNER.nextLine());
msgList.add(Map.of("role", "user", "content", input));
String resp = sendReq(msgList, delay);
if (resp == null) {
Main.LOGGER.warn("请求错误");
return;
}
String chatgptReply = resp.substring(resp.indexOf(""message":") 10, resp.indexOf(","finish_reason"));
Message message = FileUtil.OBJECT_MAPPER.readValue(chatgptReply, Message.class);
msgList.add(Map.of("role", message.getRole(), "content", message.getContent()));
Main.LOGGER.info("Chatgpt:");
Main.LOGGER.info(message.getContent());
}
} catch (NumberFormatException e) {
Main.LOGGER.warn("输入格式有误, 请输入数字");
} catch (InterruptedIOException e) {
Main.LOGGER.warn("等待回复超时, 请确认代理状态或增加等待时间");
} catch (IOException e) {
Main.LOGGER.warn("回复数据格式化失败");
}
}
通过将 问题 和 回复 添加进 msgList
集合,来实现持续对话
GitHub仓库:https://github.com/mashirot/MashiroChat