Loading... # ChatGPT API 的 Java 简单使用 > 引言:想着openai送的额度不能浪费,就使用OKHTTP框架做了一个简单的控制台对话实现 ## 请求部分 ```java /** * 发送消息请求 * @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; } } } ``` 根据 [官方文档](https://platform.openai.com/docs/api-reference/authentication),需要在请求头中加入 `Authorization: Bearer OPENAI_API_KEY` 来鉴权,其中 `OPENAI_API_KEY` 需要自己创建,发文时新注册赠送 5$ 4个月。 请求部分参考这部分 [官方文档](https://platform.openai.com/docs/api-reference/chat) 可以看到方法的入参有一个集合,其中存储历史对话记录 官方提供的返回Json示例如下,我们重点关注 message 部分 ```json { "id": "chatcmpl-123", "object": "chat.completion", "created": 1677652288, "choices": [{ "index": 0, "message": { "role": "assistant", "content": "\n\nHello there, how may I assist you today?", }, "finish_reason": "stop" }], "usage": { "prompt_tokens": 9, "completion_tokens": 12, "total_tokens": 21 } } ``` 可以看到,api 采用 `role` 字段表名消息发送者的身份,一共有三种身份 [文档](https://platform.openai.com/docs/guides/chat/introduction) ```json [ {"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` 之间,用于设定生成回复的 "创造力",较高的值生成的内容会更加随机。 ## 对话交互部分 ```java /** * 负责对话交互部分 */ 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 最后修改:2023 年 04 月 03 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 2 本作品采用 CC BY-NC-SA 4.0 International License 进行许可。