├── README.md ├── README_en.md ├── pom.xml ├── sample_code.png ├── sample_code_1.png └── src ├── main ├── java │ └── cn │ │ └── jianwoo │ │ └── openai │ │ └── chatgptapi │ │ ├── auth │ │ └── OpenAiAuth.java │ │ ├── bo │ │ ├── AudioReq.java │ │ ├── AudioRes.java │ │ ├── BillingUsage.java │ │ ├── Choices.java │ │ ├── CompletionReq.java │ │ ├── CompletionRes.java │ │ ├── CreditGrantsRes.java │ │ ├── EmbeddingsReq.java │ │ ├── EmbeddingsRes.java │ │ ├── EnginesDataRes.java │ │ ├── EnginesListRes.java │ │ ├── ErrorRes.java │ │ ├── EventListRes.java │ │ ├── EventRes.java │ │ ├── FileDetRes.java │ │ ├── FileListRes.java │ │ ├── FileReq.java │ │ ├── FineTuneListRes.java │ │ ├── FineTunesReq.java │ │ ├── FineTunesRes.java │ │ ├── FunctionCall.java │ │ ├── FunctionsReq.java │ │ ├── HttpFailedBO.java │ │ ├── ImageReq.java │ │ ├── ImageRes.java │ │ ├── MessageReq.java │ │ ├── ModelDataRes.java │ │ ├── ModelRes.java │ │ ├── ModerationsReq.java │ │ ├── ModerationsRes.java │ │ ├── ObjDelRes.java │ │ ├── ParametersReq.java │ │ ├── PropertyReq.java │ │ ├── Subscription.java │ │ └── Usage.java │ │ ├── completions │ │ └── FastCompletion.java │ │ ├── constants │ │ ├── Model.java │ │ └── Role.java │ │ ├── exception │ │ └── ApiException.java │ │ ├── service │ │ ├── PostApiService.java │ │ └── impl │ │ │ └── ChatGptApiPost.java │ │ └── stream │ │ ├── Callback.java │ │ └── HttpAsyncClientUtil.java └── resources │ └── json_prepared.jsonl └── test └── java └── cn └── jianwoo └── openai └── DemoTest.java /README.md: -------------------------------------------------------------------------------- 1 | # ChatGpt 官方API封装,支持 GPT3.5!开箱即用! 2 | 3 | 4 | 这个 SDK 已经对接了官方的所有 SDK,包括了事件流式(text/event-stream)异步读取数据, 5 | 已经支持最新的GPT3.5模型和whisper-1模型,支持语音功能! 6 | 关于如何使用自己的文本进行微调,已经上传的相关的 demo 文件和 demo 示例,参照[DemoTest.fineTuneCreate和DemoTest.completionsAfterFineTunes](src%2Ftest%2Fjava%2Fcn%2Fjianwoo%2Fopenai%2FDemoTest.java) 7 | 8 | 9 | [English Doc](README_en.md). 10 | 11 | ## 基于此项目的微信小程序和 H5 端已经上线,扫码体验! 12 |

13 | 微信小程序 14 |

15 | 16 | 官网H5地址:[https://chat.uyojo.com](https://chat.uyojo.com) 17 | 18 | 微AI聊天v1.0开源(最基础的聊天功能,github地址:https://github.com/gulihua10010/wxmini-chatgpt),v2.0不开源,功能详见1.0文档,有需要的可以联系官网客服 19 | 20 | 21 | ## 版本日志 22 | - 1.0.0 支持所有的OpenAI官方接口,支持代理,支持流式传输; 23 | - 1.0.2 支持最新的GPT-3.5-Turbo模型和Whisper-1模型; 24 | - 1.0.3 修复一些已知问题; 25 | - 1.0.4 修复一些已知问题 [issues #5](https://github.com/gulihua10010/chatGptApiSdk/issues/5); 26 | - 1.0.5 流式调用新增是否传输完成字段; 27 | - 1.0.6 支持gpt-4,查询账单明细,支持自定义Api端点; 28 | - 1.0.7 支持设置超时时间,以及超时后是否自动重试(仅支持completions/completionsStream/completionsChat/completionsChatStream 这 4 个 API),流式响应的返回增加是否成功的字段,如果是失败,则返回失败信息和异常详情,取代之前直接抛出运行时异常; 29 | - 1.0.8 修复一些已知问题; 30 | - 1.0.9 官方已经修复账单明细的 bug,版本1.0.6中的查询账单明细的接口已经不可用,已经移除 31 | - 1.0.10 再次新增账单查询功能,优化流式请求(okHttpClient设置为单例),代理新增设置用户名密码功能 32 | - 1.0.11 修复一些已知问题 [issues #17](https://github.com/gulihua10010/chatGptApiSdk/issues/17); 33 | - 1.0.12 修复[EmbeddingsReq.java](src%2Fmain%2Fjava%2Fcn%2Fjianwoo%2Fopenai%2Fchatgptapi%2Fbo%2FEmbeddingsReq.java)参数类型问题 [issues #23](https://github.com/gulihua10010/chatGptApiSdk/issues/23); 34 | - 1.0.13 新增模型,新增函数调用 35 | 36 | ## 用法 37 | 38 | ### 导入依赖 39 | 40 | ```xml 41 | 42 | 43 | cn.jianwoo.openai 44 | ChatGpt-API-SDK 45 | 1.0.13 46 | 47 | 48 | 49 | 50 | 51 | nexues 52 | snapshots 53 | https://s01.oss.sonatype.org/content/groups/public/ 54 | 55 | true 56 | 57 | 58 | true 59 | always 60 | 61 | 62 | 63 | ``` 64 | ### 调用 65 | ```java 66 | // 初始化服务 67 | PostApiService service = new ChatGptApiPost(new OpenAiAuth("")); 68 | // 请求服务 69 | CompletionRes res = service.completions(CompletionReq.builder().model("text-davinci-003").prompt("<问题>").build()); 70 | 71 | ``` 72 | ### GPT-3.5 73 | ```java 74 | // 初始化服务 75 | PostApiService service = new ChatGptApiPost(new OpenAiAuth("")); 76 | // 请求服务 77 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 78 | .messages( 79 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 80 | .build(); 81 | CompletionRes res = service.completionsChat(req); 82 | System.out.println(JSONObject.toJSONString(res)) 83 | ``` 84 | ### 使用代理 85 | 86 | ```java 87 | // 初始化服务 88 | // 不带 http或者https前缀! 89 | Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("","")); 90 | PostApiService service = new ChatGptApiPost(new OpenAiAuth("", proxy)); 91 | // 请求服务 92 | CompletionRes res = service.completions(CompletionReq.builder().model("text-davinci-003").prompt("<问题>").build()); 93 | 94 | ``` 95 | ### 异步流式读取响应 96 | 97 | ```java 98 | @Test 99 | public void completionsStream() throws Exception { 100 | CompletionReq req = CompletionReq.builder().model("text-ada-001").prompt("介绍下《水浒传》这本书").build(); 101 | service.completionsStream(req, res -> { 102 | // 回调方法 103 | System.out.println(JSONObject.toJSONString(res)); 104 | }); 105 | } 106 | ``` 107 | ### 快速使用 108 | ```java 109 | System.out.println(FastCompletion.ask("","介绍一下《三国演义》这本书")); 110 | System.out.println(FastCompletion.chat("","介绍一下《三国演义》这本书")); 111 | ``` 112 | 113 | ### 根据描述生成图片 114 | ```java 115 | // 返回一个 url 地址 116 | ImageRes res = OpenAiAuth.builder().apiKey(apiKey).post() 117 | .imageCreate(ImageReq.builder().prompt(prompt).build()); 118 | return res.getData().get(0).getUrl(); 119 | ``` 120 | ### 音频转录 121 | ```java 122 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 123 | AudioReq req = AudioReq.builder().file(audio).build(); 124 | AudioRes res = service.audioTranscribes(req); 125 | System.out.println(JSONObject.toJSONString(res)); 126 | ``` 127 | 128 | ## 已完成接口列表: 129 | - [x] Models 130 | - [x] Completions 131 | - [x] Chat 132 | - [x] Edits 133 | - [x] Images 134 | - [x] Embeddings 135 | - [x] Audio 136 | - [x] Files 137 | - [x] Fine-tunes 138 | - [x] Moderations 139 | - [x] Engines 140 | 141 | 142 | ## 常用的模型枚举 143 | ```java 144 | cn.jianwoo.openai.chatgptapi.constants.Model 145 | ``` 146 | ## 如何连续对话/记住上下文 147 | 把之前的对话传进去就行了,可以参考下面的测试用例 148 | 149 | ## 其他ChatGpt相关项目 150 | - 基于uni-app构建的微信小程序:https://github.com/gulihua10010/wxmini-chatgpt 151 | - 微信小程序服务端API程序:https://github.com/gulihua10010/chatGptApi 152 | - openAi授权SDK:https://github.com/gulihua10010/openAiAuth 153 | - chatGpt API SDK:https://github.com/gulihua10010/chatGptApiSdk 154 | - chatGpt命令行客户端:https://github.com/gulihua10010/ChatGpt 155 | 156 | ## 示例 157 | ![sample_code_1.png](sample_code_1.png) 158 | ```java 159 | 160 | import cn.jianwoo.openai.chatgptapi.completions.FastCompletion; 161 | import org.junit.jupiter.api.Test; 162 | 163 | import com.alibaba.fastjson2.JSONObject; 164 | import cn.jianwoo.openai.chatgptapi.exception.ApiException; 165 | 166 | @Test 167 | public void fastCompletionAsk() throws ApiException { 168 | System.out.println(FastCompletion.ask(apiKey,"介绍一下《三国演义》这本书")); 169 | } 170 | 171 | ``` 172 | ### 输出 173 | ``` 174 | 《三国演义》是中国古典小说的代表作,作者是元末明初的名家罗贯中。书中描写了从西晋末年到东汉初年之间的历史,以三国时期为背景,描写了诸葛亮、曹操、刘备、孙权等历史人物的故事,以及他们之间的爱恨情仇,展现了当时社会的种种矛盾,反映了中国古代政治、军事、经济、文化等方面的历史。 175 | ``` 176 | 177 | ## 测试用例 178 | 179 | ```java 180 | String apiKey = "sk-N*************************************goY"; 181 | PostApiService service = new ChatGptApiPost(new OpenAiAuth(apiKey)); 182 | 183 | /** 184 | * 185 | * 列出模型 186 | * 187 | * @author gulihua 188 | */ 189 | @Test 190 | public void models() throws ApiException 191 | { 192 | ModelRes res = service.models(); 193 | System.out.println(JSONObject.toJSONString(res)); 194 | } 195 | 196 | 197 | /** 198 | * 199 | * 检索模型 200 | * 201 | * @author gulihua 202 | */ 203 | @Test 204 | public void model() throws ApiException 205 | { 206 | ModelDataRes res = service.model("text-davinci-001"); 207 | System.out.println(JSONObject.toJSONString(res)); 208 | } 209 | 210 | 211 | /** 212 | * 213 | * 创建AI对话 214 | * 215 | * @author gulihua 216 | */ 217 | @Test 218 | public void completions() throws ApiException 219 | { 220 | CompletionReq req = CompletionReq.builder().model("text-ada-001").prompt("你好").build(); 221 | CompletionRes res = service.completions(req); 222 | System.out.println(JSONObject.toJSONString(res)); 223 | } 224 | /** 225 | * 226 | * 连续对话 227 | * 228 | * @author gulihua 229 | */ 230 | @Test 231 | public void completionsContext() throws ApiException 232 | { 233 | CompletionReq req = CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()) 234 | .stop("[\" Human:\", \" Bot:\"]").prompt("Human: 你好").build(); 235 | CompletionRes res = service.completions(req); 236 | System.out.println(JSONObject.toJSONString(res)); 237 | req.setPrompt(res.getAnswer() + "\n" + "Human: 你叫什么"); 238 | res = service.completions(req); 239 | System.out.println(JSONObject.toJSONString(res)); 240 | } 241 | 242 | /** 243 | * 244 | * 创建异步对话(流式) 245 | * 246 | * @author gulihua 247 | */ 248 | public static void completionsStream() throws Exception 249 | { 250 | CompletionReq req = CompletionReq.builder().model("text-davinci-003").prompt("你是什么模型").build(); 251 | service.completionsStream(req, res -> { 252 | // 回调方法 253 | if (res != null) 254 | { 255 | System.out.println(res.getAnswer()); 256 | } 257 | }); 258 | } 259 | 260 | 261 | /** 262 | * 263 | * 使用gpt-3.5-turbo模型聊天 264 | * 265 | * @author gulihua 266 | */ 267 | @Test 268 | public void completionsChat() throws ApiException 269 | { 270 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 271 | .messages( 272 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 273 | .build(); 274 | CompletionRes res = service.completionsChat(req); 275 | System.out.println(JSONObject.toJSONString(res)); 276 | } 277 | 278 | 279 | /** 280 | * 281 | * 使用gpt-3.5-turbo模型聊天 282 | * 283 | * @author gulihua 284 | */ 285 | @Test 286 | public void completionsChatContext() throws ApiException 287 | { 288 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 289 | .messages( 290 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("请重复我的话").build())) 291 | .build(); 292 | CompletionRes res = service.completionsChat(req); 293 | System.out.println(JSONObject.toJSONString(res)); 294 | List messages = new ArrayList<>(); 295 | messages.add(res.getChoices().get(0).getMessage()); 296 | messages.add(MessageReq.builder().role(Role.USER.getName()).content("我是中国人").build()); 297 | req.setMessages(messages); 298 | res = service.completionsChat(req); 299 | System.out.println(JSONObject.toJSONString(res)); 300 | } 301 | 302 | /** 303 | * 304 | * 使用gpt-3.5-turbo模型聊天(流式) 305 | * 306 | * @author gulihua 307 | */ 308 | public static void completionsChatStream() throws Exception 309 | { 310 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 311 | .messages( 312 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 313 | .build(); 314 | service.completionsChatStream(req, res -> { 315 | // 回调方法 316 | if (res != null) 317 | { 318 | System.out.println(res.getChatContent()); 319 | } 320 | }); 321 | } 322 | 323 | 324 | /** 325 | * 326 | * 使用gpt-3.5-turbo模型聊天(使用函数) 327 | * 328 | * @author gulihua 329 | */ 330 | @Test 331 | public void completionsChatFunctions() throws ApiException 332 | { 333 | PropertyReq location = PropertyReq.builder().name("location").type("string").description("城市,比如:上海").build(); 334 | PropertyReq format = PropertyReq.builder().name("format").type("string").description("温度单位") 335 | .enums(Arrays.asList("摄氏度", "华氏度")).build(); 336 | JSONObject properties = new JSONObject(); 337 | properties.putAll(location.toJSON()); 338 | properties.putAll(format.toJSON()); 339 | ParametersReq parametersReq = ParametersReq.builder().required(Arrays.asList("properties", "format")) 340 | .properties(properties).build(); 341 | FunctionsReq functions = FunctionsReq.builder().name("getCurrentWeather").description("查询天气") 342 | .parameters(parametersReq).build(); 343 | MessageReq messageReq = MessageReq.builder().role(Role.USER.getName()).content("南京天气怎么样,并给出穿衣建议").build(); 344 | 345 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 346 | .messages(Collections.singletonList(messageReq)).functions(Collections.singletonList(functions)) 347 | .build(); 348 | CompletionRes res = service.completionsChat(req); 349 | // System.out.println(JSONObject.toJSONString(res)); 350 | // System.out.println(res.getFunctionArgs()); 351 | MessageReq messageReq1 = MessageReq.builder().role(Role.ASSISTANT.getName()) 352 | .content(queryWeather(res.getFunctionArgs().getString("location"))).build(); 353 | 354 | req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 355 | .messages(Arrays.asList(messageReq, messageReq1)).build(); 356 | res = service.completionsChat(req); 357 | System.out.println(JSONObject.toJSONString(res)); 358 | } 359 | 360 | 361 | /** 362 | * 363 | * 使用gpt-3.5-turbo模型聊天(流式, 使用函数) 364 | * 365 | * @author gulihua 366 | */ 367 | public static void completionsChatStreamFunctions() throws Exception 368 | { 369 | PropertyReq location = PropertyReq.builder().name("location").type("string").description("城市,比如:上海").build(); 370 | PropertyReq format = PropertyReq.builder().name("format").type("string").description("温度单位") 371 | .enums(Arrays.asList("摄氏度", "华氏度")).build(); 372 | JSONObject properties = new JSONObject(); 373 | properties.putAll(location.toJSON()); 374 | properties.putAll(format.toJSON()); 375 | ParametersReq parametersReq = ParametersReq.builder().required(Arrays.asList("properties", "format")) 376 | .properties(properties).build(); 377 | FunctionsReq functions = FunctionsReq.builder().name("getCurrentWeather").description("查询天气") 378 | .parameters(parametersReq).build(); 379 | MessageReq messageReq = MessageReq.builder().role(Role.USER.getName()).content("南京天气怎么样,并给出穿衣建议").build(); 380 | 381 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 382 | .messages(Collections.singletonList(messageReq)).functions(Collections.singletonList(functions)) 383 | .build(); 384 | StringBuilder sb = new StringBuilder(); 385 | service.completionsChatStream(req, res -> { 386 | // 回调方法 387 | if (res != null) 388 | { 389 | sb.append(res.getChatContent()); 390 | // 接收结束 391 | if (res.getDone()) 392 | { 393 | JSONObject args = JSONObject.parseObject(sb.toString()); 394 | MessageReq messageReq1 = MessageReq.builder().role(Role.ASSISTANT.getName()) 395 | .content(queryWeather(args.getString("location"))).build(); 396 | CompletionReq req1 = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 397 | .messages(Arrays.asList(messageReq, messageReq1)).build(); 398 | StringBuilder sb1 = new StringBuilder(); 399 | service.completionsChatStream(req1, res1 -> { 400 | // 回调方法 401 | if (res1 != null) 402 | { 403 | System.out.println("isSuccess:" + res1.getIsSuccess() + ", Done:" + res1.getDone() 404 | + ", 接收到的数据: " + res1.getChatContent()); 405 | sb1.append(res1.getChatContent()); 406 | if (res1.getDone()) 407 | { 408 | System.out.println(sb1); 409 | } 410 | 411 | } 412 | }); 413 | } 414 | } 415 | }); 416 | 417 | } 418 | 419 | 420 | public static void main(String[] args) throws Exception 421 | { 422 | // completionsStream(); 423 | // completionsChatStream(); 424 | completionsChatStreamFunctions(); 425 | } 426 | 427 | /** 428 | * 429 | * 编辑会话文本 430 | * 431 | * @author gulihua 432 | */ 433 | @Test 434 | public void completionsEdit() throws ApiException 435 | { 436 | CompletionReq req = CompletionReq.builder().model("text-davinci-edit-001").input("What day of the wek is it?") 437 | .instruction("Fix the spelling mistakes").build(); 438 | CompletionRes res = service.completionsEdit(req); 439 | System.out.println(JSONObject.toJSONString(res)); 440 | } 441 | 442 | 443 | /** 444 | * 445 | * 根据描述生成图片 446 | * 447 | * @author gulihua 448 | */ 449 | @Test 450 | public void imageCreate() throws ApiException 451 | { 452 | ImageReq req = ImageReq.builder().prompt("cat").build(); 453 | ImageRes res = service.imageCreate(req); 454 | System.out.println(JSONObject.toJSONString(res)); 455 | } 456 | 457 | 458 | /** 459 | * 460 | * 编辑图片 461 | * 462 | * @author gulihua 463 | */ 464 | @Test 465 | public void imageEdit() throws ApiException 466 | { 467 | File cat = new File("/Users/gulihua/Downloads/cat.png"); 468 | ImageReq req = ImageReq.builder().prompt("cat").image(cat).build(); 469 | ImageRes res = service.imageEdit(req); 470 | System.out.println(JSONObject.toJSONString(res)); 471 | } 472 | 473 | 474 | /** 475 | * 476 | * 图像修正 477 | * 478 | * @author gulihua 479 | */ 480 | @Test 481 | public void imageVariate() throws ApiException 482 | { 483 | File cat = new File("/Users/gulihua/Downloads/cat.png"); 484 | ImageReq req = ImageReq.builder().prompt("cat").image(cat).build(); 485 | ImageRes res = service.imageVariate(req); 486 | System.out.println(JSONObject.toJSONString(res)); 487 | } 488 | 489 | 490 | /** 491 | * 492 | * 创建embeddings 493 | * 494 | * @author gulihua 495 | */ 496 | @Test 497 | public void embeddingsCreate() throws ApiException 498 | { 499 | EmbeddingsReq req = EmbeddingsReq.builder().model("text-embedding-ada-002") 500 | .input("he food was delicious and the waiter...").build(); 501 | EmbeddingsRes res = service.embeddingsCreate(req); 502 | System.out.println(JSONObject.toJSONString(res)); 503 | } 504 | 505 | 506 | 507 | /** 508 | * 509 | * 语音转录 510 | * 511 | * @author gulihua 512 | */ 513 | @Test 514 | public void audioTranscribes() throws ApiException 515 | { 516 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 517 | AudioReq req = AudioReq.builder().file(audio).build(); 518 | AudioRes res = service.audioTranscribes(req); 519 | System.out.println(JSONObject.toJSONString(res)); 520 | } 521 | 522 | 523 | /** 524 | * 525 | * 语音翻译 526 | * 527 | * @author gulihua 528 | */ 529 | @Test 530 | public void audioTranslates() throws ApiException 531 | { 532 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 533 | AudioReq req = AudioReq.builder().file(audio).build(); 534 | AudioRes res = service.audioTranslates(req); 535 | System.out.println(JSONObject.toJSONString(res)); 536 | } 537 | 538 | 539 | /** 540 | * 541 | * 列出所有用户上传的文件 542 | * 543 | * @author gulihua 544 | */ 545 | @Test 546 | public void fileList() throws ApiException 547 | { 548 | FileListRes res = service.fileList(); 549 | System.out.println(JSONObject.toJSONString(res)); 550 | } 551 | 552 | 553 | /** 554 | * 555 | * 文件上传 556 | * 557 | * @author gulihua 558 | */ 559 | @Test 560 | public void fileUpload() throws ApiException 561 | { 562 | File cat = new File("/Users/gulihua/Downloads/ChatGPT-Proxy-main-1/1.jsonl"); 563 | FileReq req = FileReq.builder().purpose("fine-tune").file(cat).build(); 564 | FileDetRes res = service.fileUpload(req); 565 | System.out.println(JSONObject.toJSONString(res)); 566 | } 567 | 568 | 569 | /** 570 | * 571 | * 文件删除 572 | * 573 | * @author gulihua 574 | */ 575 | @Test 576 | public void fileDelete() throws ApiException 577 | { 578 | ObjDelRes res = service.fileDelete("file-jPU5wZkSxqkWJr32HlvnEou0"); 579 | System.out.println(JSONObject.toJSONString(res)); 580 | } 581 | 582 | 583 | /** 584 | * 585 | * 文件检索 586 | * 587 | * @author gulihua 588 | */ 589 | @Test 590 | public void fileRetrieve() throws ApiException 591 | { 592 | FileDetRes res = service.fileRetrieve("file-2HvmtSTWMTatG5mvRTPerMkn"); 593 | System.out.println(JSONObject.toJSONString(res)); 594 | } 595 | 596 | 597 | /** 598 | * 599 | * 文件检索内容 600 | * 601 | * @author gulihua 602 | */ 603 | @Test 604 | public void fileRetrieveContent() throws ApiException 605 | { 606 | String res = service.fileRetrieveContent("file-2HvmtSTWMTatG5mvRTPerMkn"); 607 | System.out.println(JSONObject.toJSONString(res)); 608 | } 609 | 610 | 611 | /** 612 | * 613 | * 创建Fine-tunes 614 | * 615 | * @author gulihua 616 | */ 617 | @Test 618 | public void fineTuneCreate() throws ApiException 619 | { 620 | FineTunesReq req = FineTunesReq.builder().trainingFile("file-2HvmtSTWMTatG5mvRTPerMkn").build(); 621 | FineTunesRes res = service.fineTuneCreate(req); 622 | System.out.println(JSONObject.toJSONString(res)); 623 | } 624 | 625 | 626 | /** 627 | * 628 | * 列出Fine-tunes 629 | * 630 | * @author gulihua 631 | */ 632 | @Test 633 | public void fineTuneList() throws ApiException 634 | { 635 | FineTuneListRes res = service.fineTuneList(); 636 | System.out.println(JSONObject.toJSONString(res)); 637 | } 638 | 639 | 640 | /** 641 | * 642 | * 检索Fine-tunes 643 | * 644 | * @author gulihua 645 | */ 646 | @Test 647 | public void fineTuneRetrieve() throws ApiException 648 | { 649 | FineTunesRes res = service.fineTuneRetrieve("ft-XyXOimCsBXnRc2Djpf52ghwl"); 650 | System.out.println(JSONObject.toJSONString(res)); 651 | } 652 | 653 | 654 | /** 655 | * 656 | * 取消Fine-tunes 657 | * 658 | * @author gulihua 659 | */ 660 | @Test 661 | public void fineTuneCancel() throws ApiException 662 | { 663 | FineTunesRes res = service.fineTuneCancel("ft-XyXOimCsBXnRc2Djpf52ghwl"); 664 | System.out.println(JSONObject.toJSONString(res)); 665 | } 666 | 667 | 668 | /** 669 | * 670 | * 列出Fine-tunes 事件 671 | * 672 | * @author gulihua 673 | */ 674 | @Test 675 | public void fineTuneEventList() throws ApiException 676 | { 677 | EventListRes res = service.fineTuneEventList("ft-XyXOimCsBXnRc2Djpf52ghwl"); 678 | System.out.println(JSONObject.toJSONString(res)); 679 | } 680 | 681 | 682 | /** 683 | * 684 | * 删除Fine-tunes 685 | * 686 | * @author gulihua 687 | */ 688 | @Test 689 | public void fineTuneDelete() throws ApiException 690 | { 691 | ObjDelRes res = service.fineTuneDelete("curie:ft-acmeco-2021-03-03-21-44-20"); 692 | System.out.println(JSONObject.toJSONString(res)); 693 | } 694 | 695 | 696 | /** 697 | * 698 | * 创建moderations 699 | * 700 | * @author gulihua 701 | */ 702 | @Test 703 | public void moderationsCreate() throws ApiException 704 | { 705 | ModerationsReq req = ModerationsReq.builder().input("I want to kill them.").build(); 706 | ModerationsRes res = service.moderationsCreate(req); 707 | System.out.println(JSONObject.toJSONString(res)); 708 | } 709 | 710 | 711 | /** 712 | * 713 | * 列出所有引擎 714 | * 715 | * @author gulihua 716 | */ 717 | @Test 718 | public void enginesList() throws ApiException 719 | { 720 | EnginesListRes res = service.enginesList(); 721 | System.out.println(JSONObject.toJSONString(res)); 722 | } 723 | 724 | 725 | /** 726 | * 727 | * 检索引擎 728 | * 729 | * @author gulihua 730 | */ 731 | 732 | @Test 733 | public void enginesRetrieve() throws ApiException 734 | { 735 | EnginesDataRes res = service.enginesRetrieve("text-davinci-003"); 736 | System.out.println(JSONObject.toJSONString(res)); 737 | } 738 | 739 | 740 | 741 | /** 742 | * 743 | * 账户信息查询:里面包含总金额等信息 744 | * 745 | * @author gulihua 746 | */ 747 | 748 | @Test 749 | public void subscription() throws ApiException 750 | { 751 | Subscription res = service.subscription(); 752 | System.out.println(JSONObject.toJSONString(res)); 753 | } 754 | 755 | 756 | /** 757 | * 758 | * 账户调用接口消耗金额信息查询, 最多查询100天 759 | * 760 | * @author gulihua 761 | */ 762 | 763 | @Test 764 | public void billingUsage() throws ApiException 765 | { 766 | Date startDate = DateUtil.parse("2023-03-01"); 767 | Date endDate = DateUtil.parse("2023-04-01"); 768 | BillingUsage res = service.billingUsage(startDate, endDate); 769 | System.out.println(JSONObject.toJSONString(res)); 770 | } 771 | /** 772 | * 773 | * 快速创建会话 774 | * 775 | * @author gulihua 776 | */ 777 | @Test 778 | public void fastCompletionAsk() throws ApiException 779 | { 780 | System.out.println(FastCompletion.ask(apiKey, "介绍一下《三国演义》这本书")); 781 | } 782 | 783 | /** 784 | * 785 | * 快速创建聊天 786 | * 787 | * @author gulihua 788 | */ 789 | @Test 790 | public void fastCompletionChat() throws ApiException 791 | { 792 | System.out.println(FastCompletion.chat(apiKey, "介绍一下《三国演义》这本书")); 793 | } 794 | 795 | /** 796 | * 797 | * 快速生成图像 798 | * 799 | * @author gulihua 800 | */ 801 | @Test 802 | public void fastCompletionAsk4Image() throws ApiException 803 | { 804 | System.out.println(FastCompletion.ask4Image(apiKey, "猫")); 805 | } 806 | ``` -------------------------------------------------------------------------------- /README_en.md: -------------------------------------------------------------------------------- 1 | # ChatGpt official API package, GPT3.5 support! out of the box! 2 | 3 | This SDK has been connected to all official SDKS, including text/event-stream asynchronously read data 4 | It already supports the latest GPT3.5 model and the whisper-1 model, which supports voice function! 5 | 6 | For details on how to use your own text for fine tuning, have uploaded relevant demo files and demo examples, see[DemoTest.fineTuneCreate和DemoTest.completionsAfterFineTunes](src%2Ftest%2Fjava%2Fcn%2Fjianwoo%2Fopenai%2FDemoTest.java) 7 | 8 | 9 | [中文文档](README.md). 10 | 11 | ## Version log 12 | - 1.0.0 Supports all OpenAI official interfaces, supports proxies, and supports streaming; 13 | - 1.0.2 Supports the latest GPT-3.5-Turbo models and Whis-1 models; 14 | - 1.0.3 Fixed some known problems; 15 | - 1.0.4 Fixed some known problems [issues #5](https://github.com/gulihua10010/chatGptApiSdk/issues/5); 16 | - 1.0.5 Stream Call added whether transfer complete field; 17 | - 1.0.6 Support gpt-4, query billing credit grants, and customize Api endpoints; 18 | - 1.0.7 Support to set the timeout, and whether timeout after the automatic retry (only support completions/completionsStream/completionsChat/completionsChatStream these four API), current response returned to increase the success of a field, If it is a failure, a failure message and exception details are returned, instead of throwing the runtime exception directly; 19 | - 1.0.8 Fixed some known problems; 20 | - 1.0.9 The official has fixed the bug in the billing details. The interface is unavailable and has been removed; 21 | - 1.0.10 Added bill query function again, optimized stream request (okHttpClient set to singleton), added function of proxy set username and password 22 | - 1.0.11 Fixed bug [issues #17](https://github.com/gulihua10010/chatGptApiSdk/issues/17); 23 | - 1.0.12 Fixed the [EmbeddingsReq.java](src%2Fmain%2Fjava%2Fcn%2Fjianwoo%2Fopenai%2Fchatgptapi%2Fbo%2FEmbeddingsReq.java) parameter type problem [issues #23](https://github.com/gulihua10010/chatGptApiSdk/issues/23); 24 | - 1.0.13 Add new models, and add function call. 25 | 26 | 27 | ## Usage 28 | 29 | ### Import dependency 30 | 31 | ```xml 32 | 33 | 34 | cn.jianwoo.openai 35 | ChatGpt-API-SDK 36 | 1.0.13 37 | 38 | 39 | 40 | 41 | 42 | nexues 43 | snapshots 44 | https://s01.oss.sonatype.org/content/groups/public/ 45 | 46 | true 47 | 48 | 49 | true 50 | always 51 | 52 | 53 | 54 | ``` 55 | ### Call 56 | ```java 57 | // Init 58 | PostApiService service = new ChatGptApiPost(new OpenAiAuth("")); 59 | // Call 60 | CompletionRes res = service.completions(CompletionReq.builder().model("text-davinci-003").prompt("<问题>").build()); 61 | 62 | ``` 63 | ### GPT-3.5 64 | ```java 65 | // 初始化服务 66 | PostApiService service = new ChatGptApiPost(new OpenAiAuth("")); 67 | // 请求服务 68 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 69 | .messages( 70 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 71 | .build(); 72 | CompletionRes res = service.completionsChat(req); 73 | System.out.println(JSONObject.toJSONString(res)) 74 | ``` 75 | 76 | ### Use Proxy 77 | 78 | ```java 79 | // Init 80 | // < host> No http or https prefix! 81 | Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("","")) 82 | PostApiService service = new ChatGptApiPost(new OpenAiAuth("", proxy)); 83 | // Call 84 | CompletionRes res = service.completions(CompletionReq.builder().model("text-davinci-003").prompt("<问题>").build()); 85 | 86 | ``` 87 | ### Asynchronous streaming reads the response 88 | 89 | 90 | ```java 91 | @Test 92 | public void completionsStream() throws Exception { 93 | CompletionReq req = CompletionReq.builder().model("text-ada-001").prompt("介绍下《水浒传》这本书").build(); 94 | service.completionsStream(req, res -> { 95 | // Callback 96 | System.out.println(JSONObject.toJSONString(res)); 97 | }); 98 | } 99 | ``` 100 | ### Quick Start 101 | ```java 102 | System.out.println(FastCompletion.ask("","介绍一下《三国演义》这本书")); 103 | System.out.println(FastCompletion.chat("","介绍一下《三国演义》这本书")); 104 | 105 | ``` 106 | 107 | ### Generate a picture from the description 108 | ```java 109 | // Returns a url address 110 | ImageRes res = OpenAiAuth.builder().apiKey(apiKey).post() 111 | .imageCreate(ImageReq.builder().prompt(prompt).build()); 112 | return res.getData().get(0).getUrl(); 113 | ``` 114 | 115 | ### Audio transcription 116 | ```java 117 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 118 | AudioReq req = AudioReq.builder().file(audio).build(); 119 | AudioRes res = service.audioTranscribes(req); 120 | System.out.println(JSONObject.toJSONString(res)); 121 | ``` 122 | ## List of completed interfaces: 123 | - [x] Models 124 | - [x] Completions 125 | - [x] Chat 126 | - [x] Edits 127 | - [x] Images 128 | - [x] Embeddings 129 | - [x] Audio 130 | - [x] Files 131 | - [x] Fine-tunes 132 | - [x] Moderations 133 | - [x] Engines 134 | 135 | 136 | ## Common model enumeration 137 | ```java 138 | cn.jianwoo.openai.chatgptapi.constants.Model 139 | ``` 140 | 141 | ## How to keep a conversation going/remember context 142 | Just pass in the previous dialog, see the test case below 143 | 144 | ## Other ChatGPt-related items 145 | - Wechat mini-program based on uni-app:https://github.com/gulihua10010/wxmini-chatgpt 146 | - Wechat mini-program server API program:https://github.com/gulihua10010/chatGptApi 147 | - OpenAi authorized SDK:https://github.com/gulihua10010/openAiAuth 148 | - ChatGpt API SDK:https://github.com/gulihua10010/chatGptApiSdk 149 | - ChatGpt Command line client:https://github.com/gulihua10010/ChatGpt 150 | 151 | ## Example 152 | ![sample_code_1.png](sample_code_1.png) 153 | ```java 154 | 155 | import cn.jianwoo.openai.chatgptapi.completions.FastCompletion; 156 | import org.junit.jupiter.api.Test; 157 | 158 | import com.alibaba.fastjson2.JSONObject; 159 | import cn.jianwoo.openai.chatgptapi.exception.ApiException; 160 | 161 | @Test 162 | public void fastCompletionAsk() throws ApiException { 163 | System.out.println(FastCompletion.ask(apiKey,"介绍一下《三国演义》这本书")); 164 | } 165 | 166 | ``` 167 | ### Output 168 | ``` 169 | The Romance of The Three Kingdoms is a representative work of Chinese classical novels written by Luo Guanzhong, a famous writer in the late Yuan Dynasty and early Ming Dynasty. The book describes the history from the late Western Jin Dynasty to the early Eastern Han Dynasty. With The Three Kingdoms period as the background, it describes the stories of Zhuge Liang, Cao Cao, Liu Bei, Sun Quan and other historical figures, as well as the love and hate between them. It shows the contradictions of the society at that time and reflects the history of ancient China's politics, military, economy and culture.``` 170 | ``` 171 | ## Test case 172 | 173 | ```java 174 | String apiKey = "sk-N*************************************goY"; 175 | PostApiService service = new ChatGptApiPost(new OpenAiAuth(apiKey)); 176 | 177 | /** 178 | * 179 | * List models 180 | * 181 | * @author gulihua 182 | */ 183 | @Test 184 | public void models() throws ApiException 185 | { 186 | ModelRes res = service.models(); 187 | System.out.println(JSONObject.toJSONString(res)); 188 | } 189 | 190 | 191 | /** 192 | * 193 | * Retrieve model 194 | * 195 | * @author gulihua 196 | */ 197 | @Test 198 | public void model() throws ApiException 199 | { 200 | ModelDataRes res = service.model("text-davinci-001"); 201 | System.out.println(JSONObject.toJSONString(res)); 202 | } 203 | 204 | 205 | /** 206 | * 207 | * Create completion 208 | * 209 | * @author gulihua 210 | */ 211 | @Test 212 | public void completions() throws ApiException 213 | { 214 | CompletionReq req = CompletionReq.builder().model("text-ada-001").prompt("你好").build(); 215 | CompletionRes res = service.completions(req); 216 | System.out.println(JSONObject.toJSONString(res)); 217 | } 218 | 219 | /** 220 | * 221 | * Continuous dialogue 222 | * 223 | * @author gulihua 224 | */ 225 | @Test 226 | public void completionsContext() throws ApiException 227 | { 228 | CompletionReq req = CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()) 229 | .stop("[\" Human:\", \" Bot:\"]").prompt("Human: 你好").build(); 230 | CompletionRes res = service.completions(req); 231 | System.out.println(JSONObject.toJSONString(res)); 232 | req.setPrompt(res.getAnswer() + "\n" + "Human: 你叫什么"); 233 | res = service.completions(req); 234 | System.out.println(JSONObject.toJSONString(res)); 235 | } 236 | 237 | 238 | /** 239 | * 240 | * Create completion (text/event-stream) 241 | * 242 | * @author gulihua 243 | */ 244 | public static void completionsStream() throws Exception 245 | { 246 | CompletionReq req = CompletionReq.builder().model("text-davinci-003").prompt("你是什么模型").build(); 247 | service.completionsStream(req, res -> { 248 | // Callback 249 | if (res != null) 250 | { 251 | System.out.println(res.getAnswer()); 252 | } 253 | }); 254 | } 255 | 256 | 257 | 258 | /** 259 | * 260 | * Chat(Model 3.5) 261 | * 262 | * @author gulihua 263 | */ 264 | @Test 265 | public void completionsChat() throws ApiException 266 | { 267 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 268 | .messages( 269 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 270 | .build(); 271 | CompletionRes res = service.completionsChat(req); 272 | System.out.println(JSONObject.toJSONString(res)); 273 | } 274 | 275 | 276 | /** 277 | * 278 | * Continuous dialogue(Model 3.5) 279 | * 280 | * @author gulihua 281 | */ 282 | @Test 283 | public void completionsChatContext() throws ApiException 284 | { 285 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 286 | .messages( 287 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("请重复我的话").build())) 288 | .build(); 289 | CompletionRes res = service.completionsChat(req); 290 | System.out.println(JSONObject.toJSONString(res)); 291 | List messages = new ArrayList<>(); 292 | messages.add(res.getChoices().get(0).getMessage()); 293 | messages.add(MessageReq.builder().role(Role.USER.getName()).content("我是中国人").build()); 294 | req.setMessages(messages); 295 | res = service.completionsChat(req); 296 | System.out.println(JSONObject.toJSONString(res)); 297 | } 298 | /** 299 | * 300 | * Create chat completion(text/event-stream)(Model 3.5) 301 | * 302 | * @author gulihua 303 | */ 304 | public static void completionsChatStream() throws Exception 305 | { 306 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 307 | .messages( 308 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 309 | .build(); 310 | service.completionsChatStream(req, res -> { 311 | // 回调方法 312 | if (res != null) 313 | { 314 | System.out.println(res.getChatContent()); 315 | } 316 | }); 317 | } 318 | 319 | 320 | 321 | /** 322 | * 323 | * Use Functions 324 | * 325 | * @author gulihua 326 | */ 327 | @Test 328 | public void completionsChatFunctions() throws ApiException 329 | { 330 | PropertyReq location = PropertyReq.builder().name("location").type("string").description("城市,比如:上海").build(); 331 | PropertyReq format = PropertyReq.builder().name("format").type("string").description("温度单位") 332 | .enums(Arrays.asList("摄氏度", "华氏度")).build(); 333 | JSONObject properties = new JSONObject(); 334 | properties.putAll(location.toJSON()); 335 | properties.putAll(format.toJSON()); 336 | ParametersReq parametersReq = ParametersReq.builder().required(Arrays.asList("properties", "format")) 337 | .properties(properties).build(); 338 | FunctionsReq functions = FunctionsReq.builder().name("getCurrentWeather").description("查询天气") 339 | .parameters(parametersReq).build(); 340 | MessageReq messageReq = MessageReq.builder().role(Role.USER.getName()).content("南京天气怎么样,并给出穿衣建议").build(); 341 | 342 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 343 | .messages(Collections.singletonList(messageReq)).functions(Collections.singletonList(functions)) 344 | .build(); 345 | CompletionRes res = service.completionsChat(req); 346 | // System.out.println(JSONObject.toJSONString(res)); 347 | // System.out.println(res.getFunctionArgs()); 348 | MessageReq messageReq1 = MessageReq.builder().role(Role.ASSISTANT.getName()) 349 | .content(queryWeather(res.getFunctionArgs().getString("location"))).build(); 350 | 351 | req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 352 | .messages(Arrays.asList(messageReq, messageReq1)).build(); 353 | res = service.completionsChat(req); 354 | System.out.println(JSONObject.toJSONString(res)); 355 | } 356 | 357 | 358 | /** 359 | * 360 | * Use Functions(text/event-stream) 361 | * 362 | * @author gulihua 363 | */ 364 | public static void completionsChatStreamFunctions() throws Exception 365 | { 366 | PropertyReq location = PropertyReq.builder().name("location").type("string").description("城市,比如:上海").build(); 367 | PropertyReq format = PropertyReq.builder().name("format").type("string").description("温度单位") 368 | .enums(Arrays.asList("摄氏度", "华氏度")).build(); 369 | JSONObject properties = new JSONObject(); 370 | properties.putAll(location.toJSON()); 371 | properties.putAll(format.toJSON()); 372 | ParametersReq parametersReq = ParametersReq.builder().required(Arrays.asList("properties", "format")) 373 | .properties(properties).build(); 374 | FunctionsReq functions = FunctionsReq.builder().name("getCurrentWeather").description("查询天气") 375 | .parameters(parametersReq).build(); 376 | MessageReq messageReq = MessageReq.builder().role(Role.USER.getName()).content("南京天气怎么样,并给出穿衣建议").build(); 377 | 378 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 379 | .messages(Collections.singletonList(messageReq)).functions(Collections.singletonList(functions)) 380 | .build(); 381 | StringBuilder sb = new StringBuilder(); 382 | service.completionsChatStream(req, res -> { 383 | // 回调方法 384 | if (res != null) 385 | { 386 | sb.append(res.getChatContent()); 387 | // 接收结束 388 | if (res.getDone()) 389 | { 390 | JSONObject args = JSONObject.parseObject(sb.toString()); 391 | MessageReq messageReq1 = MessageReq.builder().role(Role.ASSISTANT.getName()) 392 | .content(queryWeather(args.getString("location"))).build(); 393 | CompletionReq req1 = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 394 | .messages(Arrays.asList(messageReq, messageReq1)).build(); 395 | StringBuilder sb1 = new StringBuilder(); 396 | service.completionsChatStream(req1, res1 -> { 397 | // 回调方法 398 | if (res1 != null) 399 | { 400 | System.out.println("isSuccess:" + res1.getIsSuccess() + ", Done:" + res1.getDone() 401 | + ", 接收到的数据: " + res1.getChatContent()); 402 | sb1.append(res1.getChatContent()); 403 | if (res1.getDone()) 404 | { 405 | System.out.println(sb1); 406 | } 407 | 408 | } 409 | }); 410 | } 411 | } 412 | }); 413 | 414 | } 415 | 416 | public static void main(String[] args) throws Exception 417 | { 418 | // completionsStream(); 419 | completionsChatStream(); 420 | } 421 | 422 | /** 423 | * 424 | * Create edit 425 | * 426 | * @author gulihua 427 | */ 428 | @Test 429 | public void completionsEdit() throws ApiException 430 | { 431 | CompletionReq req = CompletionReq.builder().model("text-davinci-edit-001").input("What day of the wek is it?") 432 | .instruction("Fix the spelling mistakes").build(); 433 | CompletionRes res = service.completionsEdit(req); 434 | System.out.println(JSONObject.toJSONString(res)); 435 | } 436 | 437 | 438 | /** 439 | * 440 | * Create image 441 | * 442 | * @author gulihua 443 | */ 444 | @Test 445 | public void imageCreate() throws ApiException 446 | { 447 | ImageReq req = ImageReq.builder().prompt("cat").build(); 448 | ImageRes res = service.imageCreate(req); 449 | System.out.println(JSONObject.toJSONString(res)); 450 | } 451 | 452 | 453 | /** 454 | * 455 | * Create image edit 456 | * 457 | * @author gulihua 458 | */ 459 | @Test 460 | public void imageEdit() throws ApiException 461 | { 462 | File cat = new File("/Users/gulihua/Downloads/cat.png"); 463 | ImageReq req = ImageReq.builder().prompt("cat").image(cat).build(); 464 | ImageRes res = service.imageEdit(req); 465 | System.out.println(JSONObject.toJSONString(res)); 466 | } 467 | 468 | 469 | /** 470 | * 471 | * Create image variation 472 | * 473 | * @author gulihua 474 | */ 475 | @Test 476 | public void imageVariate() throws ApiException 477 | { 478 | File cat = new File("/Users/gulihua/Downloads/cat.png"); 479 | ImageReq req = ImageReq.builder().prompt("cat").image(cat).build(); 480 | ImageRes res = service.imageVariate(req); 481 | System.out.println(JSONObject.toJSONString(res)); 482 | } 483 | 484 | 485 | /** 486 | * 487 | * Create embeddings 488 | * 489 | * @author gulihua 490 | */ 491 | @Test 492 | public void embeddingsCreate() throws ApiException 493 | { 494 | EmbeddingsReq req = EmbeddingsReq.builder().model("text-embedding-ada-002") 495 | .input("he food was delicious and the waiter...").build(); 496 | EmbeddingsRes res = service.embeddingsCreate(req); 497 | System.out.println(JSONObject.toJSONString(res)); 498 | } 499 | 500 | 501 | /** 502 | * 503 | * Create transcription 504 | * 505 | * @author gulihua 506 | */ 507 | @Test 508 | public void audioTranscribes() throws ApiException 509 | { 510 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 511 | AudioReq req = AudioReq.builder().file(audio).build(); 512 | AudioRes res = service.audioTranscribes(req); 513 | System.out.println(JSONObject.toJSONString(res)); 514 | } 515 | 516 | 517 | /** 518 | * 519 | * Create translation 520 | * 521 | * @author gulihua 522 | */ 523 | @Test 524 | public void audioTranslates() throws ApiException 525 | { 526 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 527 | AudioReq req = AudioReq.builder().file(audio).build(); 528 | AudioRes res = service.audioTranslates(req); 529 | System.out.println(JSONObject.toJSONString(res)); 530 | } 531 | 532 | /** 533 | * 534 | * List files 535 | * 536 | * @author gulihua 537 | */ 538 | @Test 539 | public void fileList() throws ApiException 540 | { 541 | FileListRes res = service.fileList(); 542 | System.out.println(JSONObject.toJSONString(res)); 543 | } 544 | 545 | 546 | /** 547 | * 548 | * Upload file 549 | * 550 | * @author gulihua 551 | */ 552 | @Test 553 | public void fileUpload() throws ApiException 554 | { 555 | File cat = new File("/Users/gulihua/Downloads/ChatGPT-Proxy-main-1/1.jsonl"); 556 | FileReq req = FileReq.builder().purpose("fine-tune").file(cat).build(); 557 | FileDetRes res = service.fileUpload(req); 558 | System.out.println(JSONObject.toJSONString(res)); 559 | } 560 | 561 | 562 | /** 563 | * 564 | * Delete file 565 | * 566 | * @author gulihua 567 | */ 568 | @Test 569 | public void fileDelete() throws ApiException 570 | { 571 | ObjDelRes res = service.fileDelete("file-jPU5wZkSxqkWJr32HlvnEou0"); 572 | System.out.println(JSONObject.toJSONString(res)); 573 | } 574 | 575 | 576 | /** 577 | * 578 | * Retrieve file 579 | * 580 | * @author gulihua 581 | */ 582 | @Test 583 | public void fileRetrieve() throws ApiException 584 | { 585 | FileDetRes res = service.fileRetrieve("file-2HvmtSTWMTatG5mvRTPerMkn"); 586 | System.out.println(JSONObject.toJSONString(res)); 587 | } 588 | 589 | 590 | /** 591 | * 592 | * Retrieve file content 593 | * 594 | * @author gulihua 595 | */ 596 | @Test 597 | public void fileRetrieveContent() throws ApiException 598 | { 599 | String res = service.fileRetrieveContent("file-2HvmtSTWMTatG5mvRTPerMkn"); 600 | System.out.println(JSONObject.toJSONString(res)); 601 | } 602 | 603 | 604 | /** 605 | * 606 | * Create fine-tune 607 | * 608 | * @author gulihua 609 | */ 610 | @Test 611 | public void fineTuneCreate() throws ApiException 612 | { 613 | FineTunesReq req = FineTunesReq.builder().trainingFile("file-2HvmtSTWMTatG5mvRTPerMkn").build(); 614 | FineTunesRes res = service.fineTuneCreate(req); 615 | System.out.println(JSONObject.toJSONString(res)); 616 | } 617 | 618 | 619 | /** 620 | * 621 | * List fine-tunes 622 | * 623 | * @author gulihua 624 | */ 625 | @Test 626 | public void fineTuneList() throws ApiException 627 | { 628 | FineTuneListRes res = service.fineTuneList(); 629 | System.out.println(JSONObject.toJSONString(res)); 630 | } 631 | 632 | 633 | /** 634 | * 635 | * Retrieve fine-tune 636 | * 637 | * @author gulihua 638 | */ 639 | @Test 640 | public void fineTuneRetrieve() throws ApiException 641 | { 642 | FineTunesRes res = service.fineTuneRetrieve("ft-XyXOimCsBXnRc2Djpf52ghwl"); 643 | System.out.println(JSONObject.toJSONString(res)); 644 | } 645 | 646 | 647 | /** 648 | * 649 | * Cancel fine-tune 650 | * 651 | * @author gulihua 652 | */ 653 | @Test 654 | public void fineTuneCancel() throws ApiException 655 | { 656 | FineTunesRes res = service.fineTuneCancel("ft-XyXOimCsBXnRc2Djpf52ghwl"); 657 | System.out.println(JSONObject.toJSONString(res)); 658 | } 659 | 660 | 661 | /** 662 | * 663 | * List fine-tune events 664 | * 665 | * @author gulihua 666 | */ 667 | @Test 668 | public void fineTuneEventList() throws ApiException 669 | { 670 | EventListRes res = service.fineTuneEventList("ft-XyXOimCsBXnRc2Djpf52ghwl"); 671 | System.out.println(JSONObject.toJSONString(res)); 672 | } 673 | 674 | 675 | /** 676 | * 677 | * Delete fine-tune model 678 | * 679 | * @author gulihua 680 | */ 681 | @Test 682 | public void fineTuneDelete() throws ApiException 683 | { 684 | ObjDelRes res = service.fineTuneDelete("curie:ft-acmeco-2021-03-03-21-44-20"); 685 | System.out.println(JSONObject.toJSONString(res)); 686 | } 687 | 688 | 689 | /** 690 | * 691 | * Create moderation 692 | * 693 | * @author gulihua 694 | */ 695 | @Test 696 | public void moderationsCreate() throws ApiException 697 | { 698 | ModerationsReq req = ModerationsReq.builder().input("I want to kill them.").build(); 699 | ModerationsRes res = service.moderationsCreate(req); 700 | System.out.println(JSONObject.toJSONString(res)); 701 | } 702 | 703 | 704 | /** 705 | * 706 | * List enginesDeprecated 707 | * 708 | * @author gulihua 709 | */ 710 | @Test 711 | public void enginesList() throws ApiException 712 | { 713 | EnginesListRes res = service.enginesList(); 714 | System.out.println(JSONObject.toJSONString(res)); 715 | } 716 | 717 | 718 | /** 719 | * 720 | * Retrieve engine 721 | * 722 | * @author gulihua 723 | */ 724 | 725 | @Test 726 | public void enginesRetrieve() throws ApiException 727 | { 728 | EnginesDataRes res = service.enginesRetrieve("text-davinci-003"); 729 | System.out.println(JSONObject.toJSONString(res)); 730 | } 731 | 732 | 733 | 734 | /** 735 | * 736 | * Account information query: contains the total amount of information 737 | * 738 | * @author gulihua 739 | */ 740 | 741 | @Test 742 | public void subscription() throws ApiException 743 | { 744 | Subscription res = service.subscription(); 745 | System.out.println(JSONObject.toJSONString(res)); 746 | } 747 | 748 | 749 | /** 750 | * 751 | * The account invocation interface can be used to query the consumption amount for a maximum of 100 days 752 | * 753 | * @author gulihua 754 | */ 755 | 756 | @Test 757 | public void billingUsage() throws ApiException 758 | { 759 | Date startDate = DateUtil.parse("2023-03-01"); 760 | Date endDate = DateUtil.parse("2023-04-01"); 761 | BillingUsage res = service.billingUsage(startDate, endDate); 762 | System.out.println(JSONObject.toJSONString(res)); 763 | } 764 | 765 | /** 766 | * 767 | * Completion Fastly 768 | * 769 | * @author gulihua 770 | */ 771 | @Test 772 | public void fastCompletionAsk() throws ApiException 773 | { 774 | System.out.println(FastCompletion.ask(apiKey, "介绍一下《三国演义》这本书")); 775 | } 776 | 777 | /** 778 | * 779 | * Chat Fastly 780 | * 781 | * @author gulihua 782 | */ 783 | @Test 784 | public void fastCompletionChat() throws ApiException 785 | { 786 | System.out.println(FastCompletion.chat(apiKey, "介绍一下《三国演义》这本书")); 787 | } 788 | 789 | /** 790 | * 791 | * Generate images Fastly 792 | * 793 | * @author gulihua 794 | */ 795 | @Test 796 | public void fastCompletionAsk4Image() throws ApiException 797 | { 798 | System.out.println(FastCompletion.ask4Image(apiKey, "猫")); 799 | } 800 | ``` -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | cn.jianwoo.openai 5 | ChatGpt-API-SDK 6 | 1.0.13 7 | fundebug-java-notifier 8 | https://github.com/gulihua10010/openAiAuth 9 | openAI/chatGpt User name and password Authorized login The jar package is encapsulated 10 | 11 | 12 | com.alibaba 13 | fastjson 14 | 2.0.23 15 | 16 | 17 | cn.hutool 18 | hutool-all 19 | 5.4.3 20 | 21 | 22 | ch.qos.logback 23 | logback-classic 24 | 1.2.3 25 | compile 26 | 27 | 28 | org.apache.logging.log4j 29 | log4j-to-slf4j 30 | 2.13.3 31 | compile 32 | 33 | 34 | 35 | org.projectlombok 36 | lombok 37 | 1.18.26 38 | 39 | 40 | 41 | com.squareup.okhttp3 42 | okhttp-sse 43 | 3.14.9 44 | 45 | 46 | org.junit.jupiter 47 | junit-jupiter-engine 48 | 5.6.2 49 | 50 | 51 | 52 | 53 | 54 | Server Side Public License 55 | https://www.mongodb.com/licensing/server-side-public-license 56 | repo 57 | A not business-friendly OSS license 58 | 59 | 60 | 61 | https://github.com/gulihua10010/openAiAuth 62 | https://github.com/gulihua10010/openAiAuth.git 63 | 64 | 65 | 1.8 66 | 1.8 67 | true 68 | 69 | 70 | 71 | gu 72 | gu 73 | 1729846470@qq.com 74 | 75 | Developer 76 | 77 | +8 78 | 79 | 80 | 81 | 82 | default 83 | 84 | true 85 | 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-source-plugin 91 | 2.2.1 92 | 93 | 94 | package 95 | 96 | jar-no-fork 97 | 98 | 99 | 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-gpg-plugin 104 | 1.6 105 | 106 | 107 | verify 108 | 109 | sign 110 | 111 | 112 | 113 | 114 | 115 | org.sonatype.plugins 116 | nexus-staging-maven-plugin 117 | 1.6.7 118 | true 119 | 120 | ossrh 121 | https://s01.oss.sonatype.org/ 122 | true 123 | 124 | 125 | 126 | 127 | org.apache.maven.plugins 128 | maven-source-plugin 129 | 2.2.1 130 | 131 | 132 | attach-sources 133 | 134 | jar-no-fork 135 | 136 | 137 | 138 | 139 | 140 | org.apache.maven.plugins 141 | maven-gpg-plugin 142 | 1.5 143 | 144 | 145 | sign-artifacts 146 | verify 147 | 148 | sign 149 | 150 | 151 | 152 | 153 | 154 | org.apache.maven.plugins 155 | maven-javadoc-plugin 156 | 3.0.1 157 | 158 | UTF-8 159 | true 160 | UTF-8 161 | UTF-8 162 | 163 | 164 | 165 | attach-javadocs 166 | package 167 | 168 | jar 169 | 170 | 171 | 172 | -Xdoclint:none 173 | 174 | 175 | 176 | 177 | 178 | 179 | org.apache.maven.plugins 180 | maven-surefire-plugin 181 | 2.5 182 | 183 | true 184 | 185 | 186 | 187 | 188 | 189 | 190 | ossrh 191 | https://oss.sonatype.org/content/repositories/snapshots/ 192 | 193 | 194 | ossrh 195 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /sample_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gulihua10010/chatGptApiSdk/67278f420b70b1c8afad60a3ca398f3320469155/sample_code.png -------------------------------------------------------------------------------- /sample_code_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gulihua10010/chatGptApiSdk/67278f420b70b1c8afad60a3ca398f3320469155/sample_code_1.png -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/auth/OpenAiAuth.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.auth; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import cn.jianwoo.openai.chatgptapi.service.PostApiService; 5 | import cn.jianwoo.openai.chatgptapi.service.impl.ChatGptApiPost; 6 | 7 | import java.net.Proxy; 8 | 9 | /** 10 | * OpenAiAuth授权实体类 11 | * 12 | * @blog https://jianwoo.cn 13 | * @author gulihua 14 | * @github https://github.com/gulihua10010/ 15 | * @bilibili 顾咕咕了 16 | * @date 2023-02-10 22:10 17 | */ 18 | public class OpenAiAuth 19 | { 20 | public static final String BASE_URL = "https://api.openai.com/v1"; 21 | 22 | /** apiKey,获取地址:https://platform.openai.com/account/api-keys */ 23 | private String apiKey; 24 | /** 代理 */ 25 | private Proxy proxy; 26 | 27 | /** 自定义端点 */ 28 | private String baseUrl; 29 | 30 | /** 超时时间(单位:秒) */ 31 | private int timeout; 32 | 33 | /** 连接超时(单位:秒) */ 34 | private int connectionTimeout; 35 | 36 | /** 读取超时(单位:秒) */ 37 | private int readTimeout; 38 | /** 是否重试,只对completions/completionsStream/completionsChat/completionsChatStream有效 */ 39 | private boolean isReTry; 40 | /** 单个主机最大请求数 */ 41 | private int maxRequestsPerHost; 42 | /** 最大请求数 */ 43 | private int maxRequests; 44 | /** 代理用户名 */ 45 | private String username; 46 | /** 代理密码 */ 47 | private String password; 48 | 49 | private OpenAiAuth() 50 | { 51 | } 52 | 53 | 54 | public OpenAiAuth(String apiKey) 55 | { 56 | this.apiKey = apiKey; 57 | } 58 | 59 | 60 | public OpenAiAuth(String apiKey, Proxy proxy) 61 | { 62 | this.apiKey = apiKey; 63 | this.proxy = proxy; 64 | } 65 | 66 | 67 | public OpenAiAuth(String apiKey, Proxy proxy, String baseUrl) 68 | { 69 | this.apiKey = apiKey; 70 | this.proxy = proxy; 71 | this.baseUrl = baseUrl; 72 | } 73 | 74 | 75 | public static OpenAiAuth builder() 76 | { 77 | return new OpenAiAuth(); 78 | } 79 | 80 | 81 | public OpenAiAuth apiKey(String apiKey) 82 | { 83 | this.apiKey = apiKey; 84 | return this; 85 | } 86 | 87 | 88 | public OpenAiAuth proxy(Proxy proxy) 89 | { 90 | this.proxy = proxy; 91 | return this; 92 | } 93 | 94 | 95 | public OpenAiAuth baseUrl(String baseUrl) 96 | { 97 | this.baseUrl = baseUrl; 98 | return this; 99 | } 100 | 101 | 102 | public OpenAiAuth timeout(int timeout) 103 | { 104 | this.timeout = timeout; 105 | this.connectionTimeout = timeout; 106 | this.readTimeout = timeout; 107 | return this; 108 | } 109 | 110 | 111 | public OpenAiAuth connectionTimeout(int connectionTimeout) 112 | { 113 | this.connectionTimeout = connectionTimeout; 114 | return this; 115 | } 116 | 117 | 118 | public OpenAiAuth readTimeout(int readTimeout) 119 | { 120 | this.readTimeout = readTimeout; 121 | return this; 122 | } 123 | 124 | 125 | public OpenAiAuth maxRequestsPerHost(int maxRequestsPerHost) 126 | { 127 | this.maxRequestsPerHost = maxRequestsPerHost; 128 | return this; 129 | } 130 | 131 | 132 | public OpenAiAuth maxRequests(int maxRequests) 133 | { 134 | this.maxRequests = maxRequests; 135 | return this; 136 | } 137 | 138 | 139 | public OpenAiAuth username(String username) 140 | { 141 | this.username = username; 142 | return this; 143 | } 144 | 145 | 146 | public OpenAiAuth password(String password) 147 | { 148 | this.password = password; 149 | return this; 150 | } 151 | 152 | 153 | public String getBaseUrl() 154 | { 155 | if (StrUtil.isBlank(baseUrl)) 156 | { 157 | this.baseUrl = BASE_URL; 158 | } 159 | return this.baseUrl; 160 | } 161 | 162 | 163 | public int getTimeout() 164 | { 165 | if (this.timeout == 0) 166 | { 167 | this.timeout = 60; 168 | } 169 | return this.timeout * 1000; 170 | } 171 | 172 | 173 | public int getConnectionTimeout() 174 | { 175 | if (this.connectionTimeout == 0) 176 | { 177 | this.connectionTimeout = 60; 178 | } 179 | return this.connectionTimeout * 1000; 180 | } 181 | 182 | 183 | public int getReadTimeout() 184 | { 185 | if (this.readTimeout == 0) 186 | { 187 | this.readTimeout = 60; 188 | } 189 | return this.readTimeout * 1000; 190 | } 191 | 192 | 193 | public String getUsername() 194 | { 195 | return this.username; 196 | } 197 | 198 | 199 | public String getPassword() 200 | { 201 | return this.password; 202 | } 203 | 204 | 205 | public int getMaxRequestsPerHost() 206 | { 207 | if (this.maxRequestsPerHost == 0) 208 | { 209 | this.maxRequestsPerHost = 64; 210 | } 211 | return this.maxRequestsPerHost; 212 | } 213 | 214 | 215 | public int getMaxRequests() 216 | { 217 | if (this.maxRequests == 0) 218 | { 219 | this.maxRequests = 60; 220 | } 221 | return this.maxRequests; 222 | } 223 | 224 | 225 | public OpenAiAuth isReTry(boolean isReTry) 226 | { 227 | this.isReTry = isReTry; 228 | return this; 229 | } 230 | 231 | 232 | public boolean getIsReTry() 233 | { 234 | return this.isReTry; 235 | } 236 | 237 | 238 | public String getApiKey() 239 | { 240 | return "Bearer " + this.apiKey; 241 | } 242 | 243 | 244 | public Proxy getProxy() 245 | { 246 | return this.proxy; 247 | } 248 | 249 | 250 | public PostApiService post() 251 | { 252 | return new ChatGptApiPost(this); 253 | } 254 | 255 | } 256 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/AudioReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.File; 4 | import java.io.Serializable; 5 | import java.math.BigDecimal; 6 | 7 | import cn.jianwoo.openai.chatgptapi.constants.Model; 8 | import com.alibaba.fastjson2.annotation.JSONField; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.ToString; 12 | 13 | /** 14 | * @author gulihua 15 | * @Description 16 | * @date 2023-02-28 23:42 17 | */ 18 | @Data 19 | @ToString 20 | @Builder 21 | public class AudioReq implements Serializable 22 | { 23 | private static final long serialVersionUID = 3056811090283551797L; 24 | /** (Required) ID of the model to use. Only whisper-1 is currently available. */ 25 | private String model; 26 | 27 | /** (Required) The audio file to transcribe, in one of these formats: mp3, mp4, mpeg, mpga, m4a, wav, or webm. */ 28 | private File file; 29 | 30 | /** 31 | * An optional text to guide the model's style or continue a previous audio segment. The prompt should match the 32 | * audio language. 33 | */ 34 | private String prompt; 35 | /** The format of the transcript output, in one of these options: json, text, srt, verbose_json, or vtt. */ 36 | @JSONField(name = "response_format") 37 | private String responseFormat; 38 | /** 39 | * The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower 40 | * values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to 41 | * automatically increase the temperature until certain thresholds are hit. 42 | */ 43 | private BigDecimal temperature; 44 | /** 45 | * The language of the input audio. Supplying the input language in ISO-639-1 format will improve accuracy and 46 | * latency. 47 | */ 48 | private String language; 49 | 50 | public String getModel() 51 | { 52 | if (model == null) 53 | { 54 | return Model.WHISPER_1.getName(); 55 | } 56 | return this.model; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/AudioRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | /** 10 | * @author gulihua 11 | * @Description 12 | * @date 2023-02-28 23:42 13 | */ 14 | @Data 15 | @ToString 16 | @Builder 17 | public class AudioRes implements Serializable 18 | { 19 | private static final long serialVersionUID = 3056811090283551797L; 20 | private String text; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/BillingUsage.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | 8 | import java.math.BigDecimal; 9 | import java.util.List; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-04-13 16:48 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class BillingUsage 20 | { 21 | 22 | @JSONField(name = "object") 23 | private String object; 24 | /** 25 | * 账号金额消耗明细 26 | */ 27 | @JSONField(name = "daily_costs") 28 | private List dailyCosts; 29 | /** 30 | * 总使用金额:美分 31 | */ 32 | @JSONField(name = "total_usage") 33 | private BigDecimal totalUsage; 34 | 35 | @Data 36 | @ToString 37 | @Builder 38 | public static class DailyCost 39 | { 40 | /** 41 | * 时间戳 42 | */ 43 | @JSONField(name = "timestamp") 44 | private long timestamp; 45 | /** 46 | * 模型消耗金额详情 47 | */ 48 | @JSONField(name = "line_items") 49 | private List lineItems; 50 | } 51 | 52 | @Data 53 | @ToString 54 | @Builder 55 | public static class LineItem 56 | { 57 | /** 58 | * 模型名称 59 | */ 60 | private String name; 61 | /** 62 | * 消耗金额 63 | */ 64 | private BigDecimal cost; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/Choices.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.alibaba.fastjson2.annotation.JSONField; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-02-28 19:13 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class Choices implements Serializable 20 | { 21 | private static final long serialVersionUID = 1203020411876310328L; 22 | private String text; 23 | 24 | private Integer index; 25 | 26 | private String logprobs; 27 | 28 | private MessageReq message; 29 | // stream 式返回为这个字段 30 | private MessageReq delta; 31 | 32 | @JSONField(name = "finish_reason") 33 | private String finishReason; 34 | 35 | public String getText() 36 | { 37 | if (null == text) 38 | { 39 | return ""; 40 | } 41 | return this.text; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/CompletionReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import com.alibaba.fastjson2.annotation.JSONField; 9 | 10 | import lombok.Builder; 11 | import lombok.Data; 12 | import lombok.ToString; 13 | 14 | /** 15 | * @author gulihua 16 | * @Description 17 | * @date 2023-02-28 18:57 18 | */ 19 | @Data 20 | @ToString 21 | @Builder 22 | public class CompletionReq implements Serializable 23 | { 24 | private static final long serialVersionUID = 881176059503224136L; 25 | /** 26 | * (Required) ID of the model to use. You can use the List models API to see all of your available models, or see 27 | * our ModelRes overview for descriptions of them. 28 | */ 29 | private String model; 30 | 31 | /** The messages to generate chat completions for, in the chat format. */ 32 | private List messages; 33 | 34 | /** 35 | * The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of 36 | * token arrays. 37 | * 38 | */ 39 | private String prompt; 40 | 41 | /** The maximum number of tokens to generate in the completion. */ 42 | @JSONField(name = "max_tokens") 43 | @Builder.Default 44 | private Integer maxTokens = 2048; 45 | 46 | /** 47 | * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while 48 | * lower values like 0.2 will make it more focused and deterministic. 49 | */ 50 | @Builder.Default 51 | private BigDecimal temperature = BigDecimal.ZERO; 52 | 53 | /** 54 | * An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of 55 | * the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are 56 | * considered. 57 | */ 58 | @JSONField(name = "top_p") 59 | private BigDecimal topP; 60 | 61 | /** How many completions to generate for each prompt. */ 62 | private Integer n; 63 | 64 | /** 65 | * Whether to stream back partial progress. If set, tokens will be sent as data-only server-sent events as they 66 | * become available, with the stream terminated by a data: [DONE] message. 67 | */ 68 | private Boolean stream; 69 | 70 | /** 71 | * Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. For example, if 72 | * logprobs is 5, the API will return a list of the 5 most likely tokens. The API will always return the logprob of 73 | * the sampled token, so there may be up to logprobs+1 elements in the response 74 | */ 75 | private String logprobs; 76 | 77 | /** 78 | * Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop 79 | * sequence. 80 | */ 81 | private String stop; 82 | /** The suffix that comes after a completion of inserted text. */ 83 | private String suffix; 84 | 85 | /** Echo back the prompt in addition to the completion */ 86 | private String echo; 87 | /** 88 | * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, 89 | * increasing the model's likelihood to talk about new topics. 90 | */ 91 | @JSONField(name = "presence_penalty") 92 | private BigDecimal presencePenalty; 93 | /** 94 | * Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so 95 | * far, decreasing the model's likelihood to repeat the same line verbatim. 96 | */ 97 | @JSONField(name = "frequency_penalty") 98 | private BigDecimal frequencyPenalty; 99 | /** 100 | * Generates best_of completions server-side and returns the "best" (the one with the highest log probability per 101 | * token). Results cannot be streamed. 102 | */ 103 | @JSONField(name = "best_of") 104 | private String bestOf; 105 | /** Modify the likelihood of specified tokens appearing in the completion. */ 106 | @JSONField(name = "logit_bias") 107 | private Map logitBias; 108 | /** A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. */ 109 | private String user; 110 | 111 | /** 112 | * The input text to use as a starting point for the edit. 113 | * 114 | */ 115 | private String input; 116 | 117 | /** 118 | * (Required in Edit)The instruction that tells the model how to edit the prompt. 119 | * 120 | */ 121 | private String instruction; 122 | 123 | /** A list of functions the model may generate JSON inputs for. */ 124 | private List functions; 125 | 126 | /** 127 | * Controls how the model responds to function calls. "none" means the model does not call a function, and responds 128 | * to the end-user. "auto" means the model can pick between an end-user or calling a function. Specifying a 129 | * particular function via {"name":\ "my_function"} forces the model to call that function. "none" is the default 130 | * when no functions are present. "auto" is the default if functions are present. 131 | */ 132 | @JSONField(name = "function_call") 133 | private Object functionCall; 134 | 135 | private transient Boolean isReTry; 136 | 137 | public Boolean getIsReTry() 138 | { 139 | if (null == isReTry) 140 | { 141 | this.isReTry = false; 142 | } 143 | return this.isReTry; 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/CompletionRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | import com.alibaba.fastjson2.JSON; 8 | import com.alibaba.fastjson2.JSONObject; 9 | 10 | import cn.hutool.core.collection.CollUtil; 11 | import lombok.Builder; 12 | import lombok.Data; 13 | import lombok.ToString; 14 | 15 | /** 16 | * @author gulihua 17 | * @Description 18 | * @date 2023-02-28 18:57 19 | */ 20 | @Data 21 | @ToString 22 | @Builder 23 | public class CompletionRes implements Serializable 24 | { 25 | private static final long serialVersionUID = 2572934731450584760L; 26 | private String id; 27 | 28 | private String object; 29 | 30 | private Long created; 31 | 32 | private String model; 33 | 34 | private List choices; 35 | 36 | private Usage usage; 37 | /** 是否已经完成 */ 38 | private Boolean done; 39 | /** 是否成功 */ 40 | private Boolean isSuccess; 41 | /** 失败详情 */ 42 | private HttpFailedBO failed; 43 | 44 | public String getAnswer() 45 | { 46 | if (CollUtil.isEmpty(choices)) 47 | { 48 | return null; 49 | } 50 | return choices.stream().map(Choices::getText).collect(Collectors.joining()); 51 | 52 | } 53 | 54 | 55 | public String getChatContent() 56 | { 57 | if (CollUtil.isEmpty(choices)) 58 | { 59 | return ""; 60 | } 61 | StringBuilder sb = new StringBuilder(); 62 | for (Choices c : choices) 63 | { 64 | if (null != c.getMessage()) 65 | { 66 | sb.append(c.getMessage().getContent()); 67 | } 68 | else if (null != c.getDelta()) 69 | { 70 | sb.append(c.getDelta().getContent()); 71 | } 72 | 73 | } 74 | return sb.toString(); 75 | 76 | } 77 | 78 | public String getFunctionCall() 79 | { 80 | if (CollUtil.isEmpty(choices)) 81 | { 82 | return ""; 83 | } 84 | StringBuilder sb = new StringBuilder(); 85 | for (Choices c : choices) 86 | { 87 | if (null != c.getMessage()) 88 | { 89 | sb.append(c.getMessage().getContent()); 90 | } 91 | else if (null != c.getDelta()) 92 | { 93 | sb.append(c.getDelta().getContent()); 94 | } 95 | 96 | } 97 | return sb.toString(); 98 | 99 | } 100 | 101 | public JSONObject getFunctionArgs() 102 | { 103 | JSONObject args = new JSONObject(); 104 | if (CollUtil.isEmpty(choices)) 105 | { 106 | return args; 107 | } 108 | Choices c = choices.get(0); 109 | if (null == c.getMessage()) 110 | { 111 | return args; 112 | } 113 | MessageReq messageReq = c.getMessage(); 114 | if (null == messageReq || null == messageReq.getFunctionCall()) 115 | { 116 | return args; 117 | } 118 | return JSON.parseObject(messageReq.getFunctionCall().getArguments()); 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/CreditGrantsRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | import java.util.List; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-03-23 01:15 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class CreditGrantsRes implements Serializable { 21 | private static final long serialVersionUID = 2334542692107992629L; 22 | 23 | private String object; 24 | /** 25 | * 账户总金额(单位:美元) 26 | */ 27 | @JSONField(name = "total_granted") 28 | private BigDecimal totalGranted; 29 | /** 30 | * 账户使用金额(单位:美元) 31 | */ 32 | @JSONField(name = "total_used") 33 | private BigDecimal totalUsed; 34 | /** 35 | * 账户剩余金额(单位:美元) 36 | */ 37 | @JSONField(name = "total_available") 38 | private BigDecimal totalAvailable; 39 | /** 40 | * 账户余额明细 41 | */ 42 | private Grants grants; 43 | 44 | @Data 45 | @ToString 46 | @Builder 47 | public static class Grants { 48 | private String object; 49 | @JSONField(name = "data") 50 | private List data; 51 | } 52 | 53 | 54 | @Data 55 | @ToString 56 | @Builder 57 | public static class Datum { 58 | private String object; 59 | private String id; 60 | /** 61 | * 账户赠送金额(单位:美元) 62 | */ 63 | @JSONField(name = "grant_amount") 64 | private BigDecimal grantAmount; 65 | /** 66 | * 账户使用金额(单位:美元) 67 | */ 68 | @JSONField(name = "used_amount") 69 | private BigDecimal usedAmount; 70 | /** 71 | * 生效时间 72 | */ 73 | @JSONField(name = "effective_at") 74 | private Long effectiveAt; 75 | /** 76 | * 过期时间 77 | */ 78 | @JSONField(name = "expires_at") 79 | private Long expiresAt; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/EmbeddingsReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | import java.util.List; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-02-28 18:57 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class EmbeddingsReq implements Serializable 21 | { 22 | private static final long serialVersionUID = -4876536562204868695L; 23 | /** 24 | * ID of the model to use. You can use the List models API to see all of your available models, or see our ModelRes 25 | * overview for descriptions of them. 26 | */ 27 | private String model; 28 | 29 | /** A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. */ 30 | private String user; 31 | 32 | /** 33 | * Input text to get embeddings for, encoded as a string or array of tokens. To get embeddings for multiple inputs 34 | * in a single request, pass an array of strings or array of token arrays. Each input must not exceed 8192 tokens in 35 | * length. 36 | * 37 | */ 38 | private List input; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/EmbeddingsRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | import sun.nio.cs.ext.Big5; 7 | 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | import java.util.List; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-02-28 18:57 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class EmbeddingsRes implements Serializable 21 | { 22 | private static final long serialVersionUID = 7464674452424003392L; 23 | private String object; 24 | 25 | private List data; 26 | 27 | private String model; 28 | 29 | private Usage usage; 30 | 31 | @lombok.Data 32 | @ToString 33 | @Builder 34 | public static class Data implements Serializable 35 | { 36 | private static final long serialVersionUID = 4926704717764854168L; 37 | private String object; 38 | 39 | private Integer index; 40 | 41 | private List embedding; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/EnginesDataRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.ToString; 9 | 10 | @Data 11 | @ToString 12 | @Builder 13 | public class EnginesDataRes implements Serializable 14 | { 15 | private static final long serialVersionUID = 1228999036969758493L; 16 | private String id; 17 | 18 | private String object; 19 | 20 | private String owner; 21 | 22 | private Boolean ready; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/EnginesListRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.ToString; 9 | 10 | @Data 11 | @ToString 12 | @Builder 13 | public class EnginesListRes implements Serializable 14 | { 15 | private static final long serialVersionUID = 5696979122264771764L; 16 | private List data; 17 | 18 | private String object; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ErrorRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author gulihua 11 | * @Description 12 | * @date 2023-02-28 19:18 13 | */ 14 | @Data 15 | @ToString 16 | @Builder 17 | public class ErrorRes implements Serializable 18 | { 19 | private static final long serialVersionUID = 4949702843041546727L; 20 | private Error error; 21 | 22 | @Data 23 | @ToString 24 | public static class Error implements Serializable 25 | { 26 | private static final long serialVersionUID = -5581255954819882957L; 27 | private String message; 28 | private String type; 29 | private String param; 30 | private String code; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/EventListRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | import java.util.List; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-02-28 23:42 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class EventListRes implements Serializable 21 | { 22 | private static final long serialVersionUID = 6898615781807162470L; 23 | private String object; 24 | 25 | private List data; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/EventRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-02-28 23:42 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class EventRes implements Serializable 20 | { 21 | private static final long serialVersionUID = -2682859742737504203L; 22 | private String object; 23 | 24 | @JSONField(name = "created_at") 25 | private Long createdAt; 26 | 27 | private String level; 28 | 29 | private String message; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FileDetRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-02-28 19:13 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class FileDetRes implements Serializable 20 | { 21 | private static final long serialVersionUID = 2201393714953045971L; 22 | private String id; 23 | 24 | private String object; 25 | 26 | private Long bytes; 27 | 28 | @JSONField(name = "created_at") 29 | private Long createdAt; 30 | 31 | private String filename; 32 | 33 | private String purpose; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FileListRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | /** 11 | * @author gulihua 12 | * @Description 13 | * @date 2023-02-28 23:42 14 | */ 15 | @Data 16 | @ToString 17 | @Builder 18 | public class FileListRes implements Serializable 19 | { 20 | private static final long serialVersionUID = 8143210348945550075L; 21 | private List data; 22 | 23 | private String object; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FileReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.File; 4 | import java.io.Serializable; 5 | import java.util.List; 6 | 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.ToString; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-02-28 23:42 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class FileReq implements Serializable 20 | { 21 | private static final long serialVersionUID = 3056811090283551797L; 22 | /** (Required) The intended purpose of the uploaded documents. */ 23 | private String purpose; 24 | 25 | /** (Required) Name of the JSON Lines file to be uploaded. */ 26 | private File file; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FineTuneListRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.ToString; 9 | 10 | /** 11 | * @author gulihua 12 | * @Description 13 | * @date 2023-02-28 23:42 14 | */ 15 | @Data 16 | @ToString 17 | @Builder 18 | public class FineTuneListRes implements Serializable 19 | { 20 | private static final long serialVersionUID = 5059829239538390140L; 21 | private List data; 22 | 23 | private String object; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FineTunesReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | import java.util.List; 6 | 7 | import com.alibaba.fastjson2.annotation.JSONField; 8 | 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.ToString; 12 | 13 | /** 14 | * @author gulihua 15 | * @Description 16 | * @date 2023-02-28 19:13 17 | */ 18 | @Data 19 | @ToString 20 | @Builder 21 | public class FineTunesReq implements Serializable 22 | { 23 | private static final long serialVersionUID = 1782056672431751978L; 24 | /** (Required) The ID of an uploaded file that contains training data */ 25 | @JSONField(name = "training_file") 26 | private String trainingFile; 27 | /** The ID of an uploaded file that contains validation data. */ 28 | @JSONField(name = "validation_file") 29 | private String validationFile; 30 | /** 31 | * The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", "davinci", or a 32 | * fine-tuned model created after 2022-04-21. To learn more about these models, 33 | */ 34 | private String model; 35 | /** 36 | * The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. 37 | */ 38 | @JSONField(name = "n_epochs") 39 | private Integer nEpochs; 40 | /** 41 | * The batch size to use for training. The batch size is the number of training examples used to train a single 42 | * forward and backward pass. 43 | */ 44 | @JSONField(name = "batch_size") 45 | private Long batchSize; 46 | /** 47 | * The learning rate multiplier to use for training. The fine-tuning learning rate is the original learning rate 48 | * used for pretraining multiplied by this value. 49 | */ 50 | @JSONField(name = "learning_rate_multiplier") 51 | private BigDecimal learningRateMultiplier; 52 | /** 53 | * The weight to use for loss on the prompt tokens. This controls how much the model tries to learn to generate the 54 | * prompt (as compared to the completion which always has a weight of 1.0), and can add a stabilizing effect to 55 | * training when completions are short. 56 | * 57 | */ 58 | @JSONField(name = "prompt_loss_weight") 59 | private BigDecimal promptLossWeight; 60 | /** 61 | * If set, we calculate classification-specific metrics such as accuracy and F-1 score using the validation set at 62 | * the end of every epoch. These metrics can be viewed in the results file. 63 | */ 64 | @JSONField(name = "compute_classification_metrics") 65 | private Boolean computeClassificationMetrics; 66 | 67 | /** The number of classes in a classification task. */ 68 | @JSONField(name = "classification_n_classes") 69 | private Integer classificationNClasses; 70 | 71 | /** The positive class in binary classification. */ 72 | @JSONField(name = "classification_positive_class") 73 | private String classificationPositiveClass; 74 | /** 75 | * If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score is a 76 | * generalization of F-1 score. This is only used for binary classification. 77 | */ 78 | @JSONField(name = "classification_betas") 79 | private List classificationBetas; 80 | /** A string of up to 40 characters that will be added to your fine-tuned model name. */ 81 | private String suffix; 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FineTunesRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | import java.math.BigDecimal; 11 | import java.util.List; 12 | 13 | /** 14 | * @author gulihua 15 | * @Description 16 | * @date 2023-02-28 19:13 17 | */ 18 | @Data 19 | @ToString 20 | @Builder 21 | public class FineTunesRes implements Serializable 22 | { 23 | private static final long serialVersionUID = 3933030578633023126L; 24 | private String id; 25 | 26 | private String object; 27 | 28 | private String model; 29 | 30 | @JSONField(name = "created_at") 31 | private Long createdAt; 32 | 33 | private List events; 34 | 35 | @JSONField(name = "fine_tuned_model") 36 | private String fineTunedModel; 37 | 38 | private Hyperparams hyperparams; 39 | 40 | @JSONField(name = "organization_id") 41 | private String organizationId; 42 | 43 | @JSONField(name = "result_files") 44 | private List resultFiles; 45 | 46 | private String status; 47 | 48 | @JSONField(name = "validation_files") 49 | private List validationFiles; 50 | 51 | @JSONField(name = "training_files") 52 | private List trainingFiles; 53 | 54 | @JSONField(name = "updated_at") 55 | private int updatedAt; 56 | 57 | 58 | @Data 59 | @ToString 60 | @Builder 61 | public static class Hyperparams implements Serializable 62 | { 63 | private static final long serialVersionUID = -2038826683714854343L; 64 | @JSONField(name = "batch_size") 65 | private Long batchSize; 66 | 67 | @JSONField(name = "learning_rate_multiplier") 68 | private BigDecimal learningRateMultiplier; 69 | 70 | @JSONField(name = "n_epochs") 71 | private Integer nEpochs; 72 | 73 | @JSONField(name = "prompt_loss_weight") 74 | private BigDecimal promptLossWeight; 75 | } 76 | 77 | @Data 78 | @ToString 79 | @Builder 80 | public static class TrainingFiles implements Serializable 81 | { 82 | private static final long serialVersionUID = 5832195282203971823L; 83 | private String id; 84 | 85 | private String object; 86 | 87 | private Long bytes; 88 | 89 | @JSONField(name = "created_at") 90 | private Long createdAt; 91 | 92 | private String filename; 93 | 94 | private String purpose; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FunctionCall.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 函数调用返回值
10 | * 11 | *
12 |  *     "function_call": {
13 |  *                     "name": "getCurrentWeather",
14 |  *                     "arguments": "{\n\"location\": \"南京\",\n\"format\": \"摄氏度\"\n}"
15 |  *                 }
16 |  * 
17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Builder 22 | public class FunctionCall 23 | { 24 | /** 25 | * 方法名 26 | */ 27 | private String name; 28 | /** 29 | * 方法参数 30 | */ 31 | private String arguments; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/FunctionsReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | 8 | /** 9 | * 方法实体类 10 | * 11 | *
12 |  "functions": [
13 |  *         {
14 |  *             "name": "getCurrentWeather",
15 |  *             "description": "查询天气",
16 |  *             "parameters": {
17 |  *                 "type": "object",
18 |  *                 "properties": {
19 |  *                     "location": {
20 |  *                         "type": "string",
21 |  *                         "description": "城市,比如:上海"
22 |  *                     },
23 |  *                     "format": {
24 |  *                         "type": "string",
25 |  *                         "description": "温度单位",
26 |  *                         "enum": [
27 |  *                             "摄氏度",
28 |  *                             "华氏度"
29 |  *                         ]
30 |  *                     }
31 |  *                 },
32 |  *                 "required": [
33 |  *                     "location"
34 |  *                 ]
35 |  *             }
36 |  *         }
37 |  *     ]
38 |  * 
39 | */ 40 | @Data 41 | @Builder 42 | public class FunctionsReq implements Serializable 43 | { 44 | /** 45 | * 方法名称 46 | */ 47 | private String name; 48 | /** 49 | * 方法描述 50 | */ 51 | private String description; 52 | /** 53 | * 方法参数, 如需扩展可继承{@link ParametersReq} 54 | */ 55 | private ParametersReq parameters; 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/HttpFailedBO.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author gulihua 9 | * @Description 10 | * @date 2023-03-24 01:47 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class HttpFailedBO { 16 | private String msg; 17 | private Throwable e; 18 | 19 | public HttpFailedBO(String msg) { 20 | this.msg = msg; 21 | } 22 | 23 | public HttpFailedBO(Throwable e) { 24 | this.e = e; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ImageReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.ToString; 8 | 9 | import java.io.File; 10 | import java.io.Serializable; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-02-28 18:57 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class ImageReq implements Serializable 21 | { 22 | 23 | private static final long serialVersionUID = 2092072774983708273L; 24 | /** 25 | * (Required) A text description of the desired image(s). The maximum length is 1000 characters. 26 | * 27 | */ 28 | private String prompt; 29 | 30 | /** The number of images to generate. Must be between 1 and 10. */ 31 | private Integer n; 32 | 33 | /** The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024. */ 34 | private String size; 35 | 36 | /** The format in which the generated images are returned. Must be one of url or b64_json. */ 37 | @JSONField(name = "response_format") 38 | private String responseFormat; 39 | /** A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. */ 40 | private String user; 41 | 42 | /** 43 | * (Required in Edit) The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have 44 | * transparency, which will be used as the mask. 45 | * 46 | */ 47 | private File image; 48 | /** 49 | * 50 | * An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where image should be 51 | * edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. 52 | * 53 | */ 54 | private File mask; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ImageRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import com.alibaba.fastjson2.annotation.JSONField; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.ToString; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-02-28 18:57 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class ImageRes implements Serializable 20 | { 21 | 22 | private static final long serialVersionUID = -4375773431242699973L; 23 | private Integer created; 24 | 25 | private List data; 26 | 27 | @lombok.Data 28 | @ToString 29 | @Builder 30 | public static class Data implements Serializable 31 | { 32 | private static final long serialVersionUID = -8812438979978660848L; 33 | private String url; 34 | @JSONField(name = "b64_json") 35 | private String b64Json; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/MessageReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author gulihua 12 | * @Description 13 | * @date 2023-03-02 22:13 14 | */ 15 | @Data 16 | @ToString 17 | @Builder 18 | public class MessageReq implements Serializable 19 | { 20 | private static final long serialVersionUID = 7342715261030858658L; 21 | /** The role of the messages author. One of system, user, assistant, or function. */ 22 | private String role; 23 | /** 24 | * The contents of the message. content is required for all messages except assistant messages with function calls. 25 | */ 26 | private String content; 27 | /** 28 | * The name of the author of this message. name is required if role is function, and it should be the name of the 29 | * function whose response is in the content. May contain a-z, A-Z, 0-9, and underscores, with a maximum length of 30 | * 64 characters. 31 | */ 32 | private String name; 33 | 34 | /** The name and arguments of a function that should be called, as generated by the model. */ 35 | @JSONField(name = "function_call") 36 | private FunctionCall functionCall; 37 | 38 | public MessageReq(String role, String content, String name, FunctionCall functionCall) 39 | { 40 | this.role = role; 41 | this.content = content; 42 | this.name = name; 43 | this.functionCall = functionCall; 44 | } 45 | 46 | 47 | public MessageReq(String role, String content) 48 | { 49 | this.role = role; 50 | this.content = content; 51 | } 52 | 53 | 54 | public MessageReq(String role) 55 | { 56 | this.role = role; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ModelDataRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | /** 12 | * @author gulihua 13 | * @Description 14 | * @date 2023-02-28 18:25 15 | */ 16 | @Data 17 | @ToString 18 | @Builder 19 | public class ModelDataRes implements Serializable { 20 | private static final long serialVersionUID = -7315472038774372903L; 21 | private String id; 22 | 23 | private String object; 24 | 25 | private int created; 26 | 27 | @JSONField(name = "owned_by") 28 | private String ownedBy; 29 | 30 | private List permission; 31 | 32 | private String root; 33 | 34 | private String parent; 35 | 36 | 37 | @lombok.Data 38 | @ToString 39 | @Builder 40 | public static class Permission implements Serializable { 41 | private static final long serialVersionUID = 5829901289792852545L; 42 | private String id; 43 | 44 | private String object; 45 | 46 | private Integer created; 47 | 48 | @JSONField(name = "allow_create_engine") 49 | private Boolean allowCreateEngine; 50 | 51 | @JSONField(name = "allow_sampling") 52 | private Boolean allowSampling; 53 | 54 | @JSONField(name = "allow_logprobs") 55 | private Boolean allowLogprobs; 56 | 57 | @JSONField(name = "allow_search_indices") 58 | private Boolean allowSearchIndices; 59 | 60 | @JSONField(name = "allow_view") 61 | private Boolean allowView; 62 | 63 | @JSONField(name = "allow_fine_tuning") 64 | private Boolean allowFineTuning; 65 | 66 | private String organization; 67 | 68 | private String group; 69 | 70 | @JSONField(name = "is_blocking") 71 | private Boolean isBlocking; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ModelRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | @ToString 12 | @Builder 13 | public class ModelRes implements Serializable 14 | { 15 | private static final long serialVersionUID = 9172905867883603019L; 16 | private String object; 17 | 18 | private List data; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ModerationsReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.File; 4 | import java.io.Serializable; 5 | 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.ToString; 9 | 10 | /** 11 | * @author gulihua 12 | * @Description 13 | * @date 2023-02-28 23:42 14 | */ 15 | @Data 16 | @ToString 17 | @Builder 18 | public class ModerationsReq implements Serializable 19 | { 20 | private static final long serialVersionUID = 3620948657761062623L; 21 | /** (Required) The input text to classify. */ 22 | private String input; 23 | 24 | /** Two content moderations models are available: text-moderation-stable and text-moderation-latest. */ 25 | private String model; 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ModerationsRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | import java.util.List; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-02-28 23:42 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class ModerationsRes implements Serializable 21 | { 22 | 23 | private static final long serialVersionUID = -7626651671774441526L; 24 | private String id; 25 | 26 | private String model; 27 | 28 | private List results; 29 | 30 | @Data 31 | @ToString 32 | @Builder 33 | public static class Categories implements Serializable 34 | { 35 | private static final long serialVersionUID = -3594412612848243437L; 36 | private Boolean hate; 37 | 38 | @JSONField(name = "hate/threatening") 39 | private Boolean hateThreatening; 40 | 41 | @JSONField(name = "self-harm") 42 | private Boolean selfHarm; 43 | 44 | private Boolean sexual; 45 | 46 | @JSONField(name = "sexual/minors") 47 | private Boolean sexualMinors; 48 | 49 | private Boolean violence; 50 | 51 | @JSONField(name = "violence/graphic") 52 | private Boolean violenceGraphic; 53 | 54 | } 55 | 56 | @Data 57 | @ToString 58 | @Builder 59 | public static class CategoryScores implements Serializable 60 | { 61 | private static final long serialVersionUID = 4124486670170898185L; 62 | private BigDecimal hate; 63 | 64 | @JSONField(name = "hate/threatening") 65 | private BigDecimal hateThreatening; 66 | @JSONField(name = "self-harm") 67 | private BigDecimal selfHarm; 68 | 69 | private BigDecimal sexual; 70 | 71 | @JSONField(name = "sexual/minors") 72 | private BigDecimal sexualMinors; 73 | 74 | private BigDecimal violence; 75 | 76 | @JSONField(name = "violence/graphic") 77 | private BigDecimal violenceGraphic; 78 | 79 | } 80 | 81 | @Data 82 | @ToString 83 | @Builder 84 | public static class Results implements Serializable 85 | { 86 | private static final long serialVersionUID = -181955305218248039L; 87 | private Categories categories; 88 | 89 | @JSONField(name = "category_scores") 90 | private CategoryScores categoryScores; 91 | 92 | private Boolean flagged; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ObjDelRes.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author gulihua 11 | * @Description 12 | * @date 2023-02-28 19:13 13 | */ 14 | @Data 15 | @ToString 16 | @Builder 17 | public class ObjDelRes implements Serializable 18 | { 19 | private static final long serialVersionUID = 4158216211948315224L; 20 | private String id; 21 | 22 | private String object; 23 | 24 | private Boolean deleted; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/ParametersReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import lombok.Builder; 7 | import lombok.Data; 8 | 9 | /** 10 | * 函数参数类, 如需扩展可继承{@link ParametersReq}
11 | * 12 | *
13 |  * "parameters": {
14 |  *                 "type": "object",
15 |  *                 "properties": {
16 |  *                     "location": {
17 |  *                         "type": "string",
18 |  *                         "description": "城市,比如:上海"
19 |  *                     },
20 |  *                     "format": {
21 |  *                         "type": "string",
22 |  *                         "description": "温度单位",
23 |  *                         "enum": [
24 |  *                             "摄氏度",
25 |  *                             "华氏度"
26 |  *                         ]
27 |  *                     }
28 |  *                 },
29 |  *                 "required": [
30 |  *                     "location"
31 |  *                 ]
32 |  *             }
33 |  * 
34 | * 35 | * @author gulihua 36 | * @date 2023-06-17 23:42 37 | */ 38 | @Data 39 | @Builder 40 | public class ParametersReq implements Serializable 41 | { 42 | /** 43 | * 参数类型 44 | */ 45 | @Builder.Default 46 | private String type = "object"; 47 | /** 48 | * 参数属性、描述 49 | */ 50 | private Object properties; 51 | /** 52 | * 方法必输字段 53 | */ 54 | private List required; 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/PropertyReq.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import java.util.List; 4 | 5 | import com.alibaba.fastjson2.JSON; 6 | import com.alibaba.fastjson2.JSONObject; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | /** 14 | * 函数参数里的属性类, 如需扩展可继承{@link PropertyReq}
15 | * 16 | *
17 |  *                 "properties": {
18 |  *                     "location": {
19 |  *                         "type": "string",
20 |  *                         "description": "城市,比如:上海"
21 |  *                     },
22 |  *                     "format": {
23 |  *                         "type": "string",
24 |  *                         "description": "温度单位",
25 |  *                         "enum": [
26 |  *                             "摄氏度",
27 |  *                             "华氏度"
28 |  *                         ]
29 |  *                     }
30 |  *                 }
31 |  * 
32 | * 33 | * @author gulihua 34 | */ 35 | @Data 36 | @NoArgsConstructor 37 | @AllArgsConstructor 38 | @Builder 39 | public class PropertyReq 40 | { 41 | private String name; 42 | private String type; 43 | private String description; 44 | private List enums; 45 | 46 | public JSONObject toJSON() 47 | { 48 | JSONObject o = (JSONObject) JSON.toJSON(this); 49 | o.remove("name"); 50 | o.remove("enums"); 51 | o.put("enum", enums); 52 | JSONObject prop = new JSONObject(); 53 | prop.put(name, o); 54 | return prop; 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/Subscription.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.ToString; 9 | 10 | import java.io.Serializable; 11 | 12 | /** 13 | * @author gulihua 14 | * @Description 15 | * @date 2023-04-13 16:44 16 | */ 17 | @Data 18 | @ToString 19 | @Builder 20 | public class Subscription implements Serializable 21 | { 22 | private static final long serialVersionUID = -6850948420912930882L; 23 | 24 | @JSONField(name = "object") 25 | private String object; 26 | @JSONField(name = "has_payment_method") 27 | private boolean hasPaymentMethod; 28 | @JSONField(name = "canceled") 29 | private boolean canceled; 30 | @JSONField(name = "canceled_at") 31 | private Object canceledAt; 32 | @JSONField(name = "delinquent") 33 | private Object delinquent; 34 | @JSONField(name = "access_until") 35 | private long accessUntil; 36 | @JSONField(name = "soft_limit") 37 | private long softLimit; 38 | @JSONField(name = "hard_limit") 39 | private long hardLimit; 40 | @JSONField(name = "system_hard_limit") 41 | private long systemHardLimit; 42 | @JSONField(name = "soft_limit_usd") 43 | private double softLimitUsd; 44 | @JSONField(name = "hard_limit_usd") 45 | private double hardLimitUsd; 46 | @JSONField(name = "system_hard_limit_usd") 47 | private double systemHardLimitUsd; 48 | @JSONField(name = "plan") 49 | private Plan plan; 50 | @JSONField(name = "account_name") 51 | private String accountName; 52 | @JSONField(name = "po_number") 53 | private Object poNumber; 54 | @JSONField(name = "billing_email") 55 | private Object billingEmail; 56 | @JSONField(name = "tax_ids") 57 | private Object taxIds; 58 | @JSONField(name = "billing_address") 59 | private Object billingAddress; 60 | @JSONField(name = "business_address") 61 | private Object businessAddress; 62 | 63 | @Data 64 | @ToString 65 | @Builder 66 | public static class Plan 67 | { 68 | private String title; 69 | private String id; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/bo/Usage.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.bo; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author gulihua 12 | * @Description 13 | * @date 2023-02-28 19:14 14 | */ 15 | @Data 16 | @ToString 17 | @Builder 18 | public class Usage implements Serializable 19 | { 20 | 21 | private static final long serialVersionUID = 4102065520113901923L; 22 | @JSONField(name = "prompt_tokens") 23 | private Integer promptTokens; 24 | 25 | @JSONField(name = "completion_tokens") 26 | private Integer completionTokens; 27 | 28 | @JSONField(name = "total_tokens") 29 | private Integer totalTokens; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/completions/FastCompletion.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.completions; 2 | 3 | import cn.jianwoo.openai.chatgptapi.auth.OpenAiAuth; 4 | import cn.jianwoo.openai.chatgptapi.bo.Choices; 5 | import cn.jianwoo.openai.chatgptapi.bo.CompletionReq; 6 | import cn.jianwoo.openai.chatgptapi.bo.CompletionRes; 7 | import cn.jianwoo.openai.chatgptapi.bo.ImageReq; 8 | import cn.jianwoo.openai.chatgptapi.bo.ImageRes; 9 | import cn.jianwoo.openai.chatgptapi.bo.MessageReq; 10 | import cn.jianwoo.openai.chatgptapi.constants.Model; 11 | import cn.jianwoo.openai.chatgptapi.constants.Role; 12 | import cn.jianwoo.openai.chatgptapi.exception.ApiException; 13 | import com.alibaba.fastjson2.JSONObject; 14 | import sun.misc.resources.Messages; 15 | 16 | import java.net.Proxy; 17 | import java.util.Collections; 18 | import java.util.stream.Collectors; 19 | 20 | /** 21 | * Completion封装 22 | * 23 | * @blog https://jianwoo.cn 24 | * @author gulihua 25 | * @github https://github.com/gulihua10010/ 26 | * @bilibili 顾咕咕了 27 | */ 28 | public class FastCompletion 29 | { 30 | /*** 31 | * 快速提问 32 | * 33 | * @param apiKey API KEY 34 | * @param prompt 问题 35 | * @return 答案 36 | */ 37 | public static String ask(String apiKey, String prompt) throws ApiException 38 | { 39 | CompletionRes res = OpenAiAuth.builder().apiKey(apiKey).post() 40 | .completions(CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()).prompt(prompt).build()); 41 | return res.getAnswer(); 42 | } 43 | 44 | 45 | /*** 46 | * 快速提问 47 | * 48 | * @param apiKey API KEY 49 | * @param prompt 问题 50 | * @param proxy 代理 51 | * @return 答案 52 | */ 53 | public static String ask(String apiKey, Proxy proxy, String prompt) throws ApiException 54 | { 55 | CompletionRes res = OpenAiAuth.builder().apiKey(apiKey).proxy(proxy).post() 56 | .completions(CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()).prompt(prompt).build()); 57 | return res.getChoices().stream().map(Choices::getText).collect(Collectors.joining()); 58 | } 59 | 60 | 61 | /*** 62 | * 快速聊天 63 | * 64 | * @param apiKey API KEY 65 | * @param content 内容 66 | * @return 答案 67 | */ 68 | public static String chat(String apiKey, String content) throws ApiException 69 | { 70 | CompletionRes res = OpenAiAuth.builder().apiKey(apiKey).post() 71 | .completionsChat(CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 72 | .messages(Collections 73 | .singletonList(MessageReq.builder().role(Role.USER.getName()).content(content).build())) 74 | .build()); 75 | return res.getChatContent(); 76 | } 77 | 78 | 79 | /*** 80 | * 快速聊天 81 | * 82 | * @param apiKey API KEY 83 | * @param content 内容 84 | * @param proxy 代理 85 | * @return 答案 86 | */ 87 | public static String chat(String apiKey, Proxy proxy, String content) throws ApiException 88 | { 89 | CompletionRes res = OpenAiAuth.builder().apiKey(apiKey).proxy(proxy).post() 90 | .completionsChat(CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 91 | .messages(Collections 92 | .singletonList(MessageReq.builder().role(Role.USER.getName()).content(content).build())) 93 | .build()); 94 | return res.getChoices().stream().map(Choices::getText).collect(Collectors.joining()); 95 | } 96 | 97 | 98 | /*** 99 | * 请求图片 100 | * 101 | * @param apiKey API KEY 102 | * @param prompt 问题 103 | * @return 图片 url 104 | */ 105 | public static String ask4Image(String apiKey, String prompt) throws ApiException 106 | { 107 | ImageRes res = OpenAiAuth.builder().apiKey(apiKey).post() 108 | .imageCreate(ImageReq.builder().prompt(prompt).build()); 109 | return res.getData().get(0).getUrl(); 110 | } 111 | 112 | 113 | /*** 114 | * 请求图片 115 | * 116 | * @param apiKey API KEY 117 | * @param prompt 问题 118 | * @param proxy 代理 119 | * @return 答案 120 | */ 121 | public static String ask4Image(String apiKey, Proxy proxy, String prompt) throws ApiException 122 | { 123 | CompletionRes res = OpenAiAuth.builder().apiKey(apiKey).proxy(proxy).post() 124 | .completions(CompletionReq.builder().model("text-davinci-003").prompt(prompt).build()); 125 | return res.getChoices().stream().map(Choices::getText).collect(Collectors.joining()); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/constants/Model.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.constants; 2 | 3 | /** 4 | * 5 | * 常用的模型枚举
6 | * 虽然PostApiService.models 接口中返回了69 中模型,这里只列举 7 | * https://platform.openai.com/docs/models/ 中所常用的几个模型
8 | * 9 | * 10 | * @author gulihua 11 | * 12 | */ 13 | public enum Model { 14 | /** Most capable GPT-3 model. Can do any task the other models can do, often with higher quality. */ 15 | DAVINCI("davinci"), 16 | /** 17 | * Can do any language task with better quality, longer output, and consistent instruction-following than the curie, 18 | * babbage, or ada models. Also supports inserting completions within text. 19 | */ 20 | TEXT_DAVINCI_003("text-davinci-003"), 21 | /** text-davinci-001 */ 22 | TEXT_DAVINCI_001("text-davinci-001"), 23 | /** 24 | * Most capable Codex model. Particularly good at translating natural language to code. In addition to completing 25 | * code, also supports inserting completions within code. 26 | */ 27 | CODE_DAVINCI_002("code-davinci-002"), 28 | /** Very capable, faster and lower cost than Davinci. */ 29 | TEXT_CURIE_001("text-curie-001"), 30 | /** Very capable, but faster and lower cost than Davinci. */ 31 | CURIE("curie"), 32 | /** Capable of straightforward tasks, very fast, and lower cost. */ 33 | TEXT_BABBAGE_001("text-babbage-001"), 34 | /** Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost. */ 35 | TEXT_ADA_001("text-ada-001"), 36 | /** Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost. */ 37 | ADA("ada"), 38 | /** davinci-instruct-beta */ 39 | DAVINCI_INSTRUCT_BETA("davinci-instruct-beta"), 40 | /** curie-instruct-beta */ 41 | CURIE_INSTRUCT_BETA("curie-instruct-beta"), 42 | /** 43 | * Almost as capable as Davinci Codex, but slightly faster. This speed advantage may make it preferable for 44 | * real-time applications. 45 | */ 46 | CODE_CUSHMAN_001("code-cushman-001"), 47 | /** Capable of straightforward tasks, very fast, and lower cost. */ 48 | BABBAGE("babbage"), 49 | /** 50 | * Similar capabilities to text-davinci-003 but trained with supervised fine-tuning instead of reinforcement 51 | * learning 52 | */ 53 | TEXT_DAVINCI_002("text-davinci-002"), 54 | /** 55 | * Most capable GPT-3.5 model and optimized for chat at 1/10th the cost of text-davinci-003. Will be updated with 56 | * our latest model iteration.
57 | * MAX TOKENS: 4,096 tokens 58 | */ 59 | GPT_35_TURBO("gpt-3.5-turbo"), 60 | /** 61 | * Snapshot of gpt-3.5-turbo from March 1st 2023. Unlike gpt-3.5-turbo, this model will not receive updates, and 62 | * will only be supported for a three month period ending on June 1st 2023. 63 | */ 64 | GPT_35_TURBO_0301("gpt-3.5-turbo-0301"), 65 | /** 66 | * Same capabilities as the standard gpt-3.5-turbo model but with 4 times the context.
67 | * MAX TOKENS: 16,384 tokens 68 | */ 69 | GPT_35_TURBO_16K("gpt-3.5-turbo-16k"), 70 | 71 | /** 72 | * Snapshot of gpt-3.5-turbo from June 13th 2023 with function calling data. Unlike gpt-3.5-turbo, this model will 73 | * not receive updates, and will be deprecated 3 months after a new version is released.
74 | * MAX TOKENS: 4,096 tokens 75 | */ 76 | GPT_35_TURBO_0613("gpt-3.5-turbo-0613"), 77 | 78 | /** 79 | * Snapshot of gpt-3.5-turbo-16k from June 13th 2023. Unlike gpt-3.5-turbo-16k, this model will not receive updates, 80 | * and will be deprecated 3 months after a new version is released.
81 | * MAX TOKENS: 16,384 tokens 82 | */ 83 | GPT_35_TURBO_16K_0613("gpt-3.5-turbo-16k-0613"), 84 | 85 | /** Whisper is a general-purpose speech recognition model. */ 86 | WHISPER_1("whisper-1"), 87 | /** 88 | * Embeddings are a numerical representation of text that can be used to measure the relateness between two pieces 89 | * of text. 90 | */ 91 | TEXT_EMBEDDING_ADA_002("text-embedding-ada-002"), 92 | /** 93 | * More capable than any GPT-3.5 model, able to do more complex tasks, and optimized for chat. Will be updated with 94 | * our latest model iteration. 95 | */ 96 | GPT_4("gpt-4"), 97 | /** 98 | * Snapshot of gpt-4 from March 14th 2023. Unlike gpt-4, this model will not receive updates, and will only be 99 | * supported for a three month period ending on June 14th 2023.
100 | * MAX TOKENS: 8,192 tokens 101 | */ 102 | GPT_4_0314("gpt-4-0314"), 103 | /** 104 | * Same capabilities as the base gpt-4 mode but with 4x the context length. Will be updated with our latest model 105 | * iteration.
106 | * MAX TOKENS: 32,768 tokens 107 | */ 108 | GPT_4_32K("gpt-4-32k"), 109 | /** 110 | * Snapshot of gpt-4-32 from March 14th 2023. Unlike gpt-4-32k, this model will not receive updates, and will only 111 | * be supported for a three month period ending on June 14th 2023. 112 | */ 113 | GPT_4_32K_0314("gpt-4-32k-0314"), 114 | /** 115 | * Snapshot of gpt-4 from June 13th 2023 with function calling data. Unlike gpt-4, this model will not receive 116 | * updates, and will be deprecated 3 months after a new version is released.
117 | * MAX TOKENS: 8,192 tokens 118 | */ 119 | GPT_4_0613("gpt-4-0613"), 120 | 121 | /** 122 | * Snapshot of gpt-4-32 from June 13th 2023. Unlike gpt-4-32k, this model will not receive updates, and will be 123 | * deprecated 3 months after a new version is released.
124 | * MAX TOKENS: 32,768 tokens 125 | */ 126 | GPT_4_32K_0613("gpt-4-32k-0613"),; 127 | 128 | private String name; 129 | 130 | public String getName() 131 | { 132 | return this.name; 133 | } 134 | 135 | 136 | public void setName(String name) 137 | { 138 | this.name = name; 139 | } 140 | 141 | 142 | Model(String name) 143 | { 144 | this.name = name; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/constants/Role.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.constants; 2 | 3 | /** 4 | * 5 | * MessageReq.role 定义的枚举
6 | * https://platform.openai.com/docs/guides/chat/introduction 8 | * 9 | * @author gulihua 10 | * 11 | */ 12 | public enum Role { 13 | /** 系统消息 */ 14 | SYSTEM("system"), 15 | /** 用户消息 */ 16 | USER("user"), 17 | /** 助手消息 */ 18 | ASSISTANT("assistant"), 19 | 20 | /** 函数 */ 21 | FUNCTION("function"),; 22 | 23 | private String name; 24 | 25 | public String getName() 26 | { 27 | return this.name; 28 | } 29 | 30 | 31 | public void setName(String name) 32 | { 33 | this.name = name; 34 | } 35 | 36 | 37 | Role(String name) 38 | { 39 | this.name = name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/exception/ApiException.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.exception; 2 | 3 | /** 4 | * @author GuLihua 5 | * @Description 6 | * @date 2020-08-04 14:21 7 | */ 8 | public class ApiException extends Exception 9 | { 10 | public static final ApiException SYSTEM_ERROR = new ApiException("999999", "服务出错!"); 11 | private static final long serialVersionUID = -4668522971027224346L; 12 | protected String code; 13 | protected String msg; 14 | 15 | public ApiException() 16 | { 17 | } 18 | 19 | 20 | public ApiException(String code, String msg, Object... args) 21 | { 22 | super(args == null || args.length == 0 ? msg : String.format(msg, args)); 23 | this.code = code; 24 | this.msg = args == null || args.length == 0 ? msg : String.format(msg, args); 25 | } 26 | 27 | 28 | public ApiException(String message) 29 | { 30 | super(message); 31 | this.msg = message; 32 | } 33 | 34 | 35 | public ApiException(String message, Throwable cause) 36 | { 37 | super(message, cause); 38 | this.msg = message; 39 | 40 | } 41 | 42 | 43 | public ApiException(Throwable cause) 44 | { 45 | super(cause); 46 | } 47 | 48 | 49 | public ApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) 50 | { 51 | super(message, cause, enableSuppression, writableStackTrace); 52 | this.msg = message; 53 | 54 | } 55 | 56 | 57 | public ApiException getNewInstance(String code, String msg, Object... args) 58 | { 59 | return new ApiException(code, msg, args); 60 | } 61 | 62 | 63 | public ApiException formatMsg(String msg, Object... args) 64 | { 65 | return new ApiException(code, msg, args); 66 | } 67 | 68 | 69 | public String getCode() 70 | { 71 | return code; 72 | } 73 | 74 | 75 | public void setCode(String code) 76 | { 77 | this.code = code; 78 | } 79 | 80 | 81 | public String getMsg() 82 | { 83 | return msg; 84 | } 85 | 86 | 87 | public void setMsg(String msg) 88 | { 89 | this.msg = msg; 90 | } 91 | 92 | 93 | public ApiException format(Object... args) 94 | { 95 | return new ApiException(this.code, this.msg, args); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/service/PostApiService.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.service; 2 | 3 | import cn.jianwoo.openai.chatgptapi.bo.AudioReq; 4 | import cn.jianwoo.openai.chatgptapi.bo.AudioRes; 5 | import cn.jianwoo.openai.chatgptapi.bo.BillingUsage; 6 | import cn.jianwoo.openai.chatgptapi.bo.CompletionReq; 7 | import cn.jianwoo.openai.chatgptapi.bo.CompletionRes; 8 | import cn.jianwoo.openai.chatgptapi.bo.CreditGrantsRes; 9 | import cn.jianwoo.openai.chatgptapi.bo.EmbeddingsReq; 10 | import cn.jianwoo.openai.chatgptapi.bo.EmbeddingsRes; 11 | import cn.jianwoo.openai.chatgptapi.bo.EnginesDataRes; 12 | import cn.jianwoo.openai.chatgptapi.bo.EnginesListRes; 13 | import cn.jianwoo.openai.chatgptapi.bo.EventListRes; 14 | import cn.jianwoo.openai.chatgptapi.bo.ModerationsReq; 15 | import cn.jianwoo.openai.chatgptapi.bo.ModerationsRes; 16 | import cn.jianwoo.openai.chatgptapi.bo.ObjDelRes; 17 | import cn.jianwoo.openai.chatgptapi.bo.FileDetRes; 18 | import cn.jianwoo.openai.chatgptapi.bo.FileListRes; 19 | import cn.jianwoo.openai.chatgptapi.bo.FileReq; 20 | import cn.jianwoo.openai.chatgptapi.bo.FineTuneListRes; 21 | import cn.jianwoo.openai.chatgptapi.bo.FineTunesReq; 22 | import cn.jianwoo.openai.chatgptapi.bo.FineTunesRes; 23 | import cn.jianwoo.openai.chatgptapi.bo.ImageReq; 24 | import cn.jianwoo.openai.chatgptapi.bo.ImageRes; 25 | import cn.jianwoo.openai.chatgptapi.bo.ModelRes; 26 | import cn.jianwoo.openai.chatgptapi.bo.ModelDataRes; 27 | import cn.jianwoo.openai.chatgptapi.bo.Subscription; 28 | import cn.jianwoo.openai.chatgptapi.exception.ApiException; 29 | import cn.jianwoo.openai.chatgptapi.stream.Callback; 30 | 31 | import java.util.Date; 32 | 33 | /** 34 | * ChatGpt API服务 35 | * 36 | * @blog https://jianwoo.cn 37 | * @author gulihua 38 | * @github https://github.com/gulihua10010/ 39 | * @bilibili 顾咕咕了 40 | * @date 2023-02-22 14:32 41 | */ 42 | public interface PostApiService 43 | { 44 | 45 | /** 46 | * List models
47 | * Lists the currently available models, and provides basic information about each one such as the owner and 48 | * availability. 49 | * 50 | * @author gulihua 51 | * @return ModelRes 52 | * @throws ApiException
53 | * --400001 未授权
54 | * --500001 响应JSON错误
55 | * --800001 业务错误
56 | * --900001 其他错误
57 | **/ 58 | ModelRes models() throws ApiException; 59 | 60 | 61 | /** 62 | * Retrieve model
63 | * Retrieves a model instance, providing basic information about the model such as the owner and permissioning. 64 | * 65 | * @author gulihua 66 | * @param modelName model 67 | * @return ModelDataRes 68 | * @throws ApiException
69 | * --400001 未授权
70 | * --500001 响应JSON错误
71 | * --800001 业务错误
72 | * --900001 其他错误
73 | **/ 74 | ModelDataRes model(String modelName) throws ApiException; 75 | 76 | 77 | /** 78 | * Create completion
79 | * Creates a completion for the provided prompt and parameters
80 | * stream = false
81 | * 82 | * @author gulihua 83 | * @param req req 84 | * @return CompletionRes 85 | * @throws ApiException
86 | * --400001 未授权
87 | * --500001 响应JSON错误
88 | * --800001 业务错误
89 | * --900001 其他错误
90 | **/ 91 | CompletionRes completions(CompletionReq req) throws ApiException; 92 | 93 | 94 | /** 95 | * Create completion
96 | * Creates a completion for the provided prompt and parameters
97 | * stream = true
98 | * 99 | * @author gulihua 100 | * @param req req 101 | * @param callback callback funcation 102 | * @throws ApiException
103 | * --400001 未授权
104 | * --500001 响应JSON错误
105 | * --800001 业务错误
106 | * --900001 其他错误
107 | **/ 108 | void completionsStream(CompletionReq req, Callback callback); 109 | 110 | 111 | /** 112 | * Create chat completion
113 | * Creates a completion for the chat message
114 | * stream = false
115 | * 116 | * @author gulihua 117 | * @param req req 118 | * @return CompletionRes 119 | * @throws ApiException
120 | * --400001 未授权
121 | * --500001 响应JSON错误
122 | * --800001 业务错误
123 | * --900001 其他错误
124 | **/ 125 | CompletionRes completionsChat(CompletionReq req) throws ApiException; 126 | 127 | 128 | /** 129 | * Create chat completion
130 | * Creates a completion for the chat message
131 | * stream = true
132 | * 133 | * @author gulihua 134 | * @param req req 135 | * @param callback callback funcation 136 | * @throws ApiException
137 | * --400001 未授权
138 | * --500001 响应JSON错误
139 | * --800001 业务错误
140 | * --900001 其他错误
141 | **/ 142 | void completionsChatStream(CompletionReq req, Callback callback); 143 | 144 | 145 | /** 146 | * Create edit
147 | * Creates a new edit for the provided input, instruction, and parameters.
148 | * 149 | * @author gulihua 150 | * @param req req 151 | * @return CompletionRes 152 | * @throws ApiException
153 | * --400001 未授权
154 | * --500001 响应JSON错误
155 | * --800001 业务错误
156 | * --900001 其他错误
157 | **/ 158 | CompletionRes completionsEdit(CompletionReq req) throws ApiException; 159 | 160 | 161 | /** 162 | * Create image
163 | * Creates an image given a prompt.
164 | * 165 | * @author gulihua 166 | * @param req req 167 | * @return ImageRes 168 | * @throws ApiException
169 | * --400001 未授权
170 | * --500001 响应JSON错误
171 | * --800001 业务错误
172 | * --900001 其他错误
173 | **/ 174 | ImageRes imageCreate(ImageReq req) throws ApiException; 175 | 176 | 177 | /** 178 | * Create image edit
179 | * Creates an edited or extended image given an original image and a prompt.
180 | * 181 | * @author gulihua 182 | * @param req req 183 | * @return ImageRes 184 | * @throws ApiException
185 | * --400001 未授权
186 | * --500001 响应JSON错误
187 | * --800001 业务错误
188 | * --900001 其他错误
189 | **/ 190 | ImageRes imageEdit(ImageReq req) throws ApiException; 191 | 192 | 193 | /** 194 | * Create image variation
195 | * Creates a variation of a given image.
196 | * 197 | * @author gulihua 198 | * @param req req 199 | * @return ImageRes 200 | * @throws ApiException
201 | * --400001 未授权
202 | * --500001 响应JSON错误
203 | * --800001 业务错误
204 | * --900001 其他错误
205 | **/ 206 | ImageRes imageVariate(ImageReq req) throws ApiException; 207 | 208 | 209 | /** 210 | * Create embeddings
211 | * Creates an embedding vector representing the input text.
212 | * 213 | * @author gulihua 214 | * @param req req 215 | * @return EmbeddingsRes 216 | * @throws ApiException
217 | * --400001 未授权
218 | * --500001 响应JSON错误
219 | * --800001 业务错误
220 | * --900001 其他错误
221 | **/ 222 | EmbeddingsRes embeddingsCreate(EmbeddingsReq req) throws ApiException; 223 | 224 | 225 | /** 226 | * Create transcription
227 | * Transcribes audio into the input language.
228 | * 229 | * @author gulihua 230 | * @param req req 231 | * @return EmbeddingsRes 232 | * @throws ApiException
233 | * --400001 未授权
234 | * --500001 响应JSON错误
235 | * --800001 业务错误
236 | * --900001 其他错误
237 | **/ 238 | AudioRes audioTranscribes(AudioReq req) throws ApiException; 239 | 240 | 241 | /** 242 | * Create translation
243 | * Translates audio into into English.
244 | * 245 | * @author gulihua 246 | * @param req req 247 | * @return EmbeddingsRes 248 | * @throws ApiException
249 | * --400001 未授权
250 | * --500001 响应JSON错误
251 | * --800001 业务错误
252 | * --900001 其他错误
253 | **/ 254 | AudioRes audioTranslates(AudioReq req) throws ApiException; 255 | 256 | 257 | /** 258 | * List files
259 | * Returns a list of files that belong to the user's organization.
260 | * 261 | * @author gulihua 262 | * @return FileListRes 263 | * @throws ApiException
264 | * --400001 未授权
265 | * --500001 响应JSON错误
266 | * --800001 业务错误
267 | * --900001 其他错误
268 | **/ 269 | FileListRes fileList() throws ApiException; 270 | 271 | 272 | /** 273 | * Upload file
274 | * Upload a file that contains document(s) to be used across various endpoints/features. Currently, the size of all 275 | * the files uploaded by one organization can be up to 1 GB. Please contact us if you need to increase the storage 276 | * limit.
277 | * 278 | * @author gulihua 279 | * @param req req 280 | * @return FileDetRes 281 | * @throws ApiException
282 | * --400001 未授权
283 | * --500001 响应JSON错误
284 | * --800001 业务错误
285 | * --900001 其他错误
286 | **/ 287 | FileDetRes fileUpload(FileReq req) throws ApiException; 288 | 289 | 290 | /** 291 | * Delete file
292 | * Delete a file.
293 | * 294 | * @author gulihua 295 | * @param fileId The ID of the file to use for this request 296 | * @return ObjDelRes 297 | * @throws ApiException
298 | * --400001 未授权
299 | * --500001 响应JSON错误
300 | * --800001 业务错误
301 | * --900001 其他错误
302 | **/ 303 | ObjDelRes fileDelete(String fileId) throws ApiException; 304 | 305 | 306 | /** 307 | * Retrieve file
308 | * Returns information about a specific file.
309 | * 310 | * @author gulihua 311 | * @param fileId The ID of the file to use for this request 312 | * @return FileDetRes 313 | * @throws ApiException
314 | * --400001 未授权
315 | * --500001 响应JSON错误
316 | * --800001 业务错误
317 | * --900001 其他错误
318 | **/ 319 | FileDetRes fileRetrieve(String fileId) throws ApiException; 320 | 321 | 322 | /** 323 | * Retrieve file content
324 | * Returns the contents of the specified file.
325 | * 326 | * @author gulihua 327 | * @param fileId The ID of the file to use for this request 328 | * @return String 329 | * @throws ApiException
330 | * --400001 未授权
331 | * --500001 响应JSON错误
332 | * --800001 业务错误
333 | * --900001 其他错误
334 | **/ 335 | String fileRetrieveContent(String fileId) throws ApiException; 336 | 337 | 338 | /** 339 | * Create fine-tune
340 | * Creates a job that fine-tunes a specified model from a given dataset.
341 | * 342 | * @author gulihua 343 | * @param req req 344 | * @return FineTunesRes 345 | * @throws ApiException
346 | * --400001 未授权
347 | * --500001 响应JSON错误
348 | * --800001 业务错误
349 | * --900001 其他错误
350 | **/ 351 | FineTunesRes fineTuneCreate(FineTunesReq req) throws ApiException; 352 | 353 | 354 | /** 355 | * List fine-tunes
356 | * List your organization's fine-tuning jobs.
357 | * 358 | * @author gulihua 359 | * @return FineTuneListRes 360 | * @throws ApiException
361 | * --400001 未授权
362 | * --500001 响应JSON错误
363 | * --800001 业务错误
364 | * --900001 其他错误
365 | **/ 366 | FineTuneListRes fineTuneList() throws ApiException; 367 | 368 | 369 | /** 370 | * Retrieve fine-tune
371 | * Gets info about the fine-tune job.
372 | * 373 | * @author gulihua 374 | * @param fineTuneId The ID of the fine-tune job to get events for. 375 | * @return FineTunesRes 376 | * @throws ApiException
377 | * --400001 未授权
378 | * --500001 响应JSON错误
379 | * --800001 业务错误
380 | * --900001 其他错误
381 | **/ 382 | FineTunesRes fineTuneRetrieve(String fineTuneId) throws ApiException; 383 | 384 | 385 | /** 386 | * Cancel fine-tune
387 | * Immediately cancel a fine-tune job.
388 | * 389 | * @author gulihua 390 | * @param fineTuneId The ID of the fine-tune job to get events for. 391 | * @return FineTunesRes 392 | * @throws ApiException
393 | * --400001 未授权
394 | * --500001 响应JSON错误
395 | * --800001 业务错误
396 | * --900001 其他错误
397 | **/ 398 | FineTunesRes fineTuneCancel(String fineTuneId) throws ApiException; 399 | 400 | 401 | /** 402 | * List fine-tune events
403 | * Get fine-grained status updates for a fine-tune job.
404 | * 405 | * @author gulihua 406 | * @param fineTuneId The ID of the fine-tune job to get events for. 407 | * @return FineTunesRes 408 | * @throws ApiException
409 | * --400001 未授权
410 | * --500001 响应JSON错误
411 | * --800001 业务错误
412 | * --900001 其他错误
413 | **/ 414 | EventListRes fineTuneEventList(String fineTuneId) throws ApiException; 415 | 416 | 417 | /** 418 | * Delete fine-tune model
419 | * Delete a fine-tuned model. You must have the Owner role in your organization.
420 | * 421 | * @author gulihua 422 | * @param model The model to delete 423 | * @return FineTunesRes 424 | * @throws ApiException
425 | * --400001 未授权
426 | * --500001 响应JSON错误
427 | * --800001 业务错误
428 | * --900001 其他错误
429 | **/ 430 | ObjDelRes fineTuneDelete(String model) throws ApiException; 431 | 432 | 433 | /** 434 | * Create moderation
435 | * Classifies if text violates OpenAI's Content Policy
436 | * 437 | * @author gulihua 438 | * @param req req 439 | * @return ModerationsRes 440 | * @throws ApiException
441 | * --400001 未授权
442 | * --500001 响应JSON错误
443 | * --800001 业务错误
444 | * --900001 其他错误
445 | **/ 446 | ModerationsRes moderationsCreate(ModerationsReq req) throws ApiException; 447 | 448 | 449 | /** 450 | * List engines
451 | * Lists the currently available (non-finetuned) models, and provides basic information about each one such as the 452 | * owner and availability.
453 | * 454 | * @author gulihua 455 | * @return EnginesListRes 456 | * @throws ApiException
457 | * --400001 未授权
458 | * --500001 响应JSON错误
459 | * --800001 业务错误
460 | * --900001 其他错误
461 | **/ 462 | EnginesListRes enginesList() throws ApiException; 463 | 464 | 465 | /** 466 | * Retrieve engine
467 | * Retrieves a model instance, providing basic information about it such as the owner and availability.
468 | * 469 | * @author gulihua 470 | * @param engineId The ID of the engine to use for this request 471 | * @return FineTunesRes 472 | * @throws ApiException
473 | * --400001 未授权
474 | * --500001 响应JSON错误
475 | * --800001 业务错误
476 | * --900001 其他错误
477 | **/ 478 | EnginesDataRes enginesRetrieve(String engineId) throws ApiException; 479 | 480 | 481 | /** 482 | * 账户信息查询:里面包含总金额等信息
483 | * 单位:美元 484 | * 485 | * @author gulihua 486 | * @return Subscription 487 | * @throws ApiException
488 | * --400001 未授权
489 | * --500001 响应JSON错误
490 | * --800001 业务错误
491 | * --900001 其他错误
492 | **/ 493 | Subscription subscription() throws ApiException; 494 | 495 | 496 | /** 497 | * 账户调用接口消耗金额信息查询, 最多查询100天
498 | * totalUsage = 账户总使用金额
499 | * 单位:美分 500 | * 501 | * @author gulihua 502 | * @param startDate 起始时间 503 | * @param endDate 结束时间 504 | * @return BillingUsage 505 | * @throws ApiException
506 | * --400001 未授权
507 | * --500001 响应JSON错误
508 | * --800001 业务错误
509 | * --900001 其他错误
510 | **/ 511 | BillingUsage billingUsage(Date startDate, Date endDate) throws ApiException; 512 | } 513 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/stream/Callback.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.stream; 2 | 3 | /** 4 | * @author gulihua 5 | * @Description 6 | * @date 2023-01-03 00:16 7 | */ 8 | @FunctionalInterface 9 | public interface Callback 10 | { 11 | /** 12 | * 方法回调 13 | * 14 | * @param param 参数 15 | * @date 00:18 2023/1/3 16 | * @author gulihua 17 | **/ 18 | void call(T param); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cn/jianwoo/openai/chatgptapi/stream/HttpAsyncClientUtil.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai.chatgptapi.stream; 2 | 3 | import java.io.IOException; 4 | import java.net.Proxy; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import cn.hutool.core.util.StrUtil; 8 | import cn.jianwoo.openai.chatgptapi.auth.OpenAiAuth; 9 | import cn.jianwoo.openai.chatgptapi.bo.HttpFailedBO; 10 | import lombok.extern.log4j.Log4j2; 11 | import okhttp3.Authenticator; 12 | import okhttp3.Credentials; 13 | import okhttp3.OkHttpClient; 14 | import okhttp3.Request; 15 | import okhttp3.Response; 16 | import okhttp3.ResponseBody; 17 | import okhttp3.Route; 18 | import okhttp3.sse.EventSource; 19 | import okhttp3.sse.EventSourceListener; 20 | import okhttp3.sse.EventSources; 21 | 22 | /** 23 | * @author gulihua 24 | * @Description 25 | * @date 2023-02-23 12:12 26 | */ 27 | @Log4j2 28 | public class HttpAsyncClientUtil 29 | { 30 | private static OkHttpClient client; 31 | 32 | public static OkHttpClient initHttpClient(Proxy proxy, OpenAiAuth config) 33 | { 34 | if (client != null) 35 | { 36 | return client; 37 | } 38 | OkHttpClient.Builder builder = new OkHttpClient.Builder(); 39 | builder.connectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS); 40 | builder.writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS); 41 | builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS); 42 | if (null != proxy) 43 | { 44 | builder.proxy(proxy); 45 | } 46 | if (StrUtil.isNotBlank(config.getUsername())) 47 | { 48 | Authenticator proxyAuthenticator = new Authenticator() { 49 | 50 | public Request authenticate(Route route, Response response) throws IOException 51 | { 52 | String credential = Credentials.basic(config.getUsername(), config.getPassword()); 53 | return response.request().newBuilder().header("Proxy-Authorization", credential).build(); 54 | } 55 | }; 56 | builder.proxyAuthenticator(proxyAuthenticator); 57 | } 58 | 59 | client = builder.build(); 60 | client.dispatcher().setMaxRequestsPerHost(config.getMaxRequestsPerHost()); 61 | client.dispatcher().setMaxRequests(config.getMaxRequests()); 62 | return client; 63 | 64 | } 65 | 66 | 67 | public static void execute(Request request, Callback succCallback) 68 | { 69 | execute(request, succCallback, null); 70 | } 71 | 72 | 73 | public static void execute(Request request, Callback succCallback, Callback failCallback) 74 | { 75 | EventSource.Factory factory = EventSources.createFactory(client); 76 | factory.newEventSource(request, new EventSourceListener() { 77 | @Override 78 | public void onOpen(EventSource eventSource, Response response) 79 | { 80 | log.debug("AsyncClient opens connection."); 81 | } 82 | 83 | 84 | @Override 85 | public void onEvent(EventSource eventSource, String id, String type, String data) 86 | { 87 | log.debug("AsyncClient.onEvent, id={}, type={}, data= {}", id, type, data); 88 | if (null != succCallback) 89 | { 90 | succCallback.call(data); 91 | } 92 | 93 | } 94 | 95 | 96 | @Override 97 | public void onClosed(EventSource eventSource) 98 | { 99 | log.debug("AsyncClient closes connection. "); 100 | 101 | } 102 | 103 | 104 | @Override 105 | public void onFailure(EventSource eventSource, Throwable t, Response response) 106 | { 107 | if (null == response) 108 | { 109 | if (null != failCallback && null != t) 110 | { 111 | failCallback.call(new HttpFailedBO(t.getMessage(), t)); 112 | } 113 | log.error(" asyncClient.execute failed, e: ", t); 114 | return; 115 | } 116 | ResponseBody body = response.body(); 117 | if (body != null) 118 | { 119 | try 120 | { 121 | String content = body.string(); 122 | if (null != failCallback) 123 | { 124 | failCallback.call(new HttpFailedBO(content, t)); 125 | } 126 | log.error(" asyncClient.execute failed, body: {}, e: {}", content, t); 127 | } 128 | catch (IOException e) 129 | { 130 | log.error(">>>>onFailure.exec failed, e: ", e); 131 | } 132 | 133 | } 134 | else 135 | { 136 | if (null != failCallback && null != t) 137 | { 138 | failCallback.call(new HttpFailedBO(t.getMessage(), t)); 139 | } 140 | log.error(" asyncClient.execute failed, e: ", t); 141 | 142 | } 143 | eventSource.cancel(); 144 | 145 | } 146 | }); 147 | 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /src/main/resources/json_prepared.jsonl: -------------------------------------------------------------------------------- 1 | {"prompt":"冬瓜、黄瓜、西瓜、南瓜都能吃,什么瓜不能吃。->","completion":" 傻瓜\nENDEND"} 2 | {"prompt":"你能以最快速度,把冰变成水吗。->","completion":" \nENDEND"} 3 | {"prompt":"冬天,宝宝怕冷,到了屋里也不肯脱帽。可是他见了一个人乖乖地脱下帽,那人是谁。->","completion":" 理发师\nENDEND"} 4 | {"prompt":"有一个字,人人见了都会念错。这是什么字。->","completion":" 这是“错”字\nENDEND"} 5 | {"prompt":"鸡蛋壳有什么用处。->","completion":" 用来包蛋清和蛋黄。\nENDEND"} 6 | {"prompt":"你能做,我能做,大家都做;一个人能做,两个人不能一起做。这是做什么。->","completion":" 做梦\nENDEND"} 7 | {"prompt":"什么人始终不敢洗澡。->","completion":" 泥人\nENDEND"} 8 | {"prompt":"什么车子寸步难行。->","completion":" 风车\nENDEND"} 9 | {"prompt":"你知道上课睡觉有什么不好吗。->","completion":" 不如床上舒服嘛\nENDEND"} 10 | {"prompt":"什么蛋打不烂,煮不熟,更不能吃。->","completion":" 考试得的零蛋\nENDEND"} 11 | {"prompt":"火车由北京到上海需要6小时,行使3小时后,火车该在什么地方。->","completion":" 在车轨上\nENDEND"} 12 | {"prompt":"书店里买不到什么书。->","completion":" 遗书\nENDEND"} 13 | {"prompt":"什么东西不能吃。->","completion":" “东西”方向\nENDEND"} 14 | {"prompt":"一年四季都盛开的花是什么花。->","completion":" 塑料花\nENDEND"} 15 | {"prompt":"什么人生病从来不看医生。->","completion":" 盲人\nENDEND"} 16 | {"prompt":"用铁锤锤鸡蛋为什么锤不破。->","completion":" 铁锤当然不会破了\nENDEND"} 17 | {"prompt":"什么事天不知地知,你不知我知。->","completion":" 鞋底破了\nENDEND"} 18 | {"prompt":"一位卡车司机撞倒一个骑摩托车的人,卡车司机受重伤,摩托车骑士却没事,为什么。->","completion":" 卡车司机当时没开车\nENDEND"} 19 | {"prompt":"你能用蓝笔写出红字来吗。->","completion":" 写个“红”字有何难\nENDEND"} 20 | {"prompt":"孔子与孟子有什么区别。->","completion":" 孔子的子在左边,孟子的子在上边\nENDEND"} 21 | {"prompt":"一个人空肚子最多能吃几个鸡蛋。->","completion":" 一个。因为吃了一个后就不是空肚子了\nENDEND"} 22 | {"prompt":"毛毛虫回到家,对爸爸说了一句话,爸爸即场晕倒,毛毛虫说了什么话。->","completion":" 毛毛虫说:“我要买鞋。”\nENDEND"} 23 | {"prompt":"太平洋的中间是什么。->","completion":" 是平字\nENDEND"} 24 | {"prompt":"把一只鸡和一只鹅同时放在冰箱里,为什么鸡死了鹅没死。->","completion":" 企鹅嘛\nENDEND"} 25 | {"prompt":"万兽大王是谁。->","completion":" 动物园园长\nENDEND"} 26 | {"prompt":"什么样的人死后还会出现。->","completion":" 电影中的人\nENDEND"} 27 | {"prompt":"谁说话的声音传得最远。->","completion":" 打电话的人\nENDEND"} 28 | {"prompt":"小咪昨晚花了整整一个晚上在历史课本上,可第二天妈妈还是骂她不用功,为什么。->","completion":" 她用历史课本当枕头睡\nENDEND"} 29 | {"prompt":"一头牛,向北走10米,再向西走10米,再向南走10米,倒退右转,问牛的尾巴朝哪儿。->","completion":" 朝地\nENDEND"} 30 | {"prompt":"把8分成两半,是多少。->","completion":" 0\nENDEND"} 31 | {"prompt":"什么东西使人哭笑不得。->","completion":" 口罩\nENDEND"} 32 | {"prompt":"有个人走独木桥,前面来了一只老虎,后面来了只熊,这个人是怎么过去的。->","completion":" 晕过去了\nENDEND"} 33 | {"prompt":"小明的妈妈有三个儿子,大独生子叫大明,二儿子叫二明,三儿子叫什么。->","completion":" 当然叫小明\nENDEND"} 34 | {"prompt":"大象的左边耳朵象什么。->","completion":" 右边耳朵\nENDEND"} 35 | {"prompt":"有一个人走在沙滩上,回头却看不见自己的脚印,为什么。->","completion":" 因为他倒着走\nENDEND"} 36 | {"prompt":"李先生到16层楼去谈生意,但他只乘电梯到14层楼,然后再步行爬楼梯上去,为什么。->","completion":" 李先生个子太矮,按不到16楼的电梯按键\nENDEND"} 37 | {"prompt":"什么字全世界通用。->","completion":" 阿拉伯数字\nENDEND"} 38 | {"prompt":"人的长寿秘诀是什么。->","completion":" 保持呼吸,不要断气\nENDEND"} 39 | {"prompt":"什么人一年中只工作一天。->","completion":" 圣诞老人\nENDEND"} 40 | {"prompt":"为什么刚出生的小孩只有一只左眼睛。->","completion":" 人本来就只有一只左眼睛\nENDEND"} 41 | {"prompt":"房间里着火了,小明怎么也拉不开门,请问他后来是怎么出去的。->","completion":" 推开门\nENDEND"} 42 | {"prompt":"什么最会弄虚做假。->","completion":" 魔术师\nENDEND"} 43 | {"prompt":"铁放在屋外露天会生锈,那么金子呢。->","completion":" 会被偷走\nENDEND"} 44 | {"prompt":"“新华字典”有多少个字。->","completion":" 四个\nENDEND"} 45 | {"prompt":"什么人心肠最不好。->","completion":" 得胃肠炎的人.\nENDEND"} 46 | {"prompt":"2对父子去打猎,他们每人达了一只野鸭、,但是总共却只有3只,为什么。->","completion":" 祖孙3人\nENDEND"} 47 | {"prompt":"什么东西没吃的时候是绿的,吃的时候是红的,吐出来的是黑的。->","completion":" 西瓜\nENDEND"} 48 | {"prompt":"一只狼钻进羊圈,想吃羊,可是它为啥没吃又没吃羊。->","completion":" 因为:羊圈里没有羊!\nENDEND"} 49 | {"prompt":"什么船最安全。->","completion":" 停在海滩里的船\nENDEND"} 50 | {"prompt":"老詹养了一只狗,并且从来不帮狗洗澡,为什么狗不会生跳蚤呢?。->","completion":" 因不狗只会生小狗\nENDEND"} 51 | {"prompt":"什么书既没有作者也从来没有人看得懂?。->","completion":" 天书\nENDEND"} 52 | {"prompt":"放一支铅笔在地上,要使任何人都无法跨过,怎么做?。->","completion":" 放在墙边\nENDEND"} 53 | {"prompt":"环球旅行 打一人名。->","completion":" 周星驰\nENDEND"} 54 | {"prompt":"为什麽帽子脏了要翻面再戴?。->","completion":" 张冠李戴(脏冠里戴)\nENDEND"} 55 | {"prompt":"犯人最乐意选择的死法是什么?。->","completion":" 老死\nENDEND"} 56 | {"prompt":"狗过了独木桥就不叫了(打一成语)。->","completion":" 过目不忘(过木不汪)\nENDEND"} 57 | {"prompt":"小白加小白等于什么?。->","completion":" 小白兔(TWO)\nENDEND"} 58 | {"prompt":"小咪昨晚花了整整一个晚上在历史课本上,可第二天妈妈还是骂她不用功,为什么?。->","completion":" 她用历史课本当枕头睡\nENDEND"} 59 | {"prompt":"一只公鸡和一只母鸡(猜五个字)。->","completion":" 还是两只鸡\nENDEND"} 60 | {"prompt":"什么是附中?。->","completion":" 胎死腹中(附中)\nENDEND"} 61 | {"prompt":"经理不会做饭,可有一道菜特别拿手,是什么?。->","completion":" 炒鱿鱼\nENDEND"} 62 | {"prompt":"世界上什么蛋不能吃,煮不熟,却打得破?。->","completion":" 考试得的零蛋\nENDEND"} 63 | {"prompt":"偷什么东西不犯法?。->","completion":" 偷笑\nENDEND"} 64 | {"prompt":"为什麽老师从小就叮咛我们要珍惜四支箭。->","completion":" 光阴似箭(四箭)\nENDEND"} 65 | {"prompt":"什么船从来不下水?。->","completion":" 宇宙飞船\nENDEND"} 66 | {"prompt":"何时是离婚最好的日子?。->","completion":" 月日(自由日)\nENDEND"} 67 | {"prompt":"死前放屁又叫什么?。->","completion":" 绝响\nENDEND"} 68 | {"prompt":"一个瞎子射击一个帽子,怎么样一枪就中?。->","completion":" 把帽子挂在枪口上\nENDEND"} 69 | {"prompt":"什么东西生的不能吃,熟不能吃,边烤边吃?。->","completion":" 香烟\nENDEND"} 70 | {"prompt":"小明今年岁,为什么只过了三次生日?。->","completion":" 小明的生日是月日\nENDEND"} 71 | {"prompt":"点一横长,一撇飘南洋,南洋有个人,只有一寸长。(打一字)。->","completion":" 府\nENDEND"} 72 | {"prompt":"一只青蛙掉进三十公尺深的枯井,如果它每次能跳二公尺高,它需要跳几次才能跳出井口呢?。->","completion":" 那么深的枯井他早就摔死了\nENDEND"} 73 | {"prompt":"七分熟的牛肉遇到八分熟的牛肉,为什么他们不打招呼?。->","completion":" 因为它们不熟\nENDEND"} 74 | {"prompt":"什么东西要藏起来暗地里用,用完之后再暗地里交给别人?。->","completion":" 底片\nENDEND"} 75 | {"prompt":"在路上,它翻了一个跟斗,接着又翻了一次(猜字成语)。->","completion":" 三翻两次\nENDEND"} 76 | {"prompt":"山坡上有一群羊,来了一群羊。一共有几群羊?。->","completion":" 还是一群呀!\nENDEND"} 77 | {"prompt":"耶稣是哪一国人?。->","completion":" 天国\nENDEND"} 78 | {"prompt":"阿弟竟成功的用面线上吊自杀成功,为什么?。->","completion":" 摔死的...\nENDEND"} 79 | {"prompt":"9头牛10个秃子(打一成语)。->","completion":" 九牛一毛\nENDEND"} 80 | {"prompt":"情心渐逝泪婆娑,日月同辉不快活(打一节日)。->","completion":" 清明\nENDEND"} 81 | {"prompt":"平安无事医院坐,急病一来把人拖(打一交通工具)。->","completion":" 救护车\nENDEND"} 82 | {"prompt":"深夜沉沉(打一人名)。->","completion":" 墨子\nENDEND"} 83 | {"prompt":"此物最怕晒,越晒湿越快(打一自然物)。->","completion":" 冰\nENDEND"} 84 | {"prompt":"去年秋天撒下种,长出绿苗过一冬。开春它还接着长,等到夏天黄澄澄。(打一植物)。->","completion":" 冬小麦\nENDEND"} 85 | {"prompt":"女人的胸部(打一个现代流行语)。->","completion":" 二奶\nENDEND"} 86 | {"prompt":"三立注重品行(打一爱国名将)。->","completion":" 杨靖宇\nENDEND"} 87 | {"prompt":"烤肉的时侯最怕什么?。->","completion":" 肉跟你装熟\nENDEND"} 88 | {"prompt":"能吃又能洗,就是不能吞(打一娱乐物品)。->","completion":" 麻将\nENDEND"} 89 | {"prompt":"千里之行,寻太阳(打一节日)。->","completion":" 重阳节\nENDEND"} 90 | {"prompt":"张灯结彩龙狮闹,欢天喜地合家好(打一节日)。->","completion":" 元宵节\nENDEND"} 91 | {"prompt":"东方威尼斯(打一城市名)。->","completion":" 苏州\nENDEND"} 92 | {"prompt":"你在什么时候晴天见不到太阳?。->","completion":" 闭上眼的时候\nENDEND"} 93 | {"prompt":"地面上的森林霸王(打一歌手)。->","completion":" 陆虎(陆地上的老虎)\nENDEND"} 94 | {"prompt":"白床铺,黄帐子。(打一植物)。->","completion":" 桂圆\nENDEND"} 95 | {"prompt":"房产证(打一宗教用语)。->","completion":" 主持\nENDEND"} 96 | {"prompt":"总共四人,一同落水(打一地名)。->","completion":" 陈光标出生地:泗洪\nENDEND"} 97 | {"prompt":"奇花异草荟萃地,珍禽异兽安生所(打一国家)。->","completion":" 厄瓜多尔\nENDEND"} 98 | {"prompt":"林务大臣,猜一字。->","completion":" 棺\nENDEND"} 99 | {"prompt":"男女老少赏花灯,其乐融融庆佳节(打一节日)。->","completion":" 元宵节\nENDEND"} 100 | {"prompt":"四个晚上(打一个字)。->","completion":" 罗\nENDEND"} 101 | {"prompt":"一人自驾游(打一诗句)。->","completion":" 寂寞开无主\nENDEND"} 102 | {"prompt":"人人引壶觞自酌,九九佳节聚老友(打一节日习俗)。->","completion":" 重阳节之习俗:喝菊花酒\nENDEND"} 103 | {"prompt":"孔子携老友一同爬山(打一节日习俗)。->","completion":" 重阳节习俗:登高\nENDEND"} 104 | {"prompt":"人间喜庆团圆日,月宫饮尽相思泪(打一节日)。->","completion":" 中秋节\nENDEND"} 105 | {"prompt":"冬天幼苗夏成熟,滔滔海水是活土,根浮水面随浪晃,身潜水中漫起舞。(打一植物)。->","completion":" 海带\nENDEND"} 106 | {"prompt":"月月怀念祖国(打一中医用语)。->","completion":" 腮肿\nENDEND"} 107 | {"prompt":"皮肤白皙(打一食品)。->","completion":" 面粉\nENDEND"} 108 | {"prompt":"利剑穿腹(打一花类)。->","completion":" 刺红(蔷薇)\nENDEND"} 109 | {"prompt":"草本植物根肉质,特殊臭味多分枝,美名流传存于世,熏牙入药即可吃(打一植物)。->","completion":" 天仙子\nENDEND"} 110 | {"prompt":"明明是个近视眼,也是个出名的馋小子,在他面前放一堆书,书后放一个苹果,你说他会先看什么?。->","completion":" 什么都看不见\nENDEND"} 111 | {"prompt":"住在农家屋,浑身黑乎乎,遇水小变大,吃了有好处(打一菌类)。->","completion":" 木耳\nENDEND"} 112 | {"prompt":"双膝着地,祈求二星(打一七夕习俗)。->","completion":" 拜织女,拜魁星\nENDEND"} 113 | {"prompt":"文理分科(打一曹植诗句)。->","completion":" 本是同根生\nENDEND"} 114 | {"prompt":"苗头不对,猜一字。->","completion":" 笛\nENDEND"} 115 | {"prompt":"穿过树林的风(打一歌曲)。->","completion":" 《枫》。\nENDEND"} 116 | {"prompt":"一座亭子、一个人(猜一个字)。->","completion":" 停\nENDEND"} 117 | {"prompt":"词作家(打一成语)。->","completion":" 玩弄词藻\nENDEND"} 118 | {"prompt":"豪杰纷纷聚集(打一热门游戏)。->","completion":" 英雄联盟\nENDEND"} 119 | {"prompt":"医治晕车的最好办法是什么?。->","completion":" 不坐车\nENDEND"} 120 | {"prompt":"贞观之治路无豺,开元盛世粟米白(打一演员)。->","completion":" 唐国强\nENDEND"} 121 | {"prompt":"出租的士(打一军事名)。->","completion":" 雇佣军\nENDEND"} 122 | {"prompt":"你能做我能做大家都能做,一个人能做两个人不能一起做。这是做什么?(答案:做梦) 45.一个离过五十次婚的女人,应该怎么形容她?(答案:前公尽弃) 46.三个孩子吃三个饼要用分钟,九十个孩子九十个饼要用多少时间?(答案:也是三分钟,九十个孩子同时吃) 47.什么样的轮子只转不走?(答案:风车的轮子) 48.地球上什么东西每天要走的距离最远?(答案:地球) 49.中国人最早的姓氏是什么?(答案:姓善) 50.铁放到外面要生锈,那金子呢?(答案:会被偷走) 51.在什么时候+不等于?(答案:算错了的时候) 52.两个人住在一个胡同里,只隔几步路,他们同在一个工厂上班,但每天出门上班,却总一个向左,一个向右,为什么?(答案:他们住对门) 53.什么时候最好还是要高高举起你的双手好些?(答案:当有人用枪指着你的头的时候) 54.无风荷叶动,猜一字。->","completion":" 衡\nENDEND"} 123 | {"prompt":"仓库里面的木材(打一成语)。->","completion":" 枪\nENDEND"} 124 | {"prompt":"俺媳妇肥头大耳(打一离合字)。->","completion":" 内人肉\nENDEND"} 125 | {"prompt":"弱冠之年登基(打一离合字)。->","completion":" 二十王\nENDEND"} 126 | {"prompt":"关(打一成语)。->","completion":" 老天有眼\nENDEND"} 127 | {"prompt":"右侧青草于上飘,玉林美景点影飞(打一奥运明星)。->","completion":" 陈若琳\nENDEND"} 128 | {"prompt":"云间新月影如钩,十载一来复见君。(打一节日)。->","completion":" 万圣节\nENDEND"} 129 | {"prompt":"小明家住在五楼,可是电梯坏了,他自己也没有走楼梯,他却上了五楼回到家里,这可能吗?(答案:妈妈背着他上的楼) 62.天气越热,爬得越高。外面透明,里面有毒。(打一事物)。->","completion":" 温度计\nENDEND"} 130 | {"prompt":"欲言又止,猜一个字。->","completion":" 认\nENDEND"} 131 | {"prompt":"好兄弟们抱成团,穿着白衣真好看(打一植物)。->","completion":" 蒜\nENDEND"} 132 | {"prompt":"除了父母不能骂还有一个人不能骂他是谁?。->","completion":" 老板\nENDEND"} 133 | {"prompt":"空中而来(打一词牌名)。->","completion":" 八归\nENDEND"} 134 | {"prompt":"一根又黑又粗又硬的棍子插进洞里,感觉暖烘烘的,等到抽出来以后,客人就要付钱啦(一种行业)(答案:烤甘蔗) 68.舔也硬,不舔也硬,想舒服睡,先搓搓它(人身上的东西)(答案:牙齿) 69.一种东西,东方人的短,西方人的长,结婚后女的就可以用男的这东西,和尚有但是不用它(答案:人的,姓) 70.什么东西最硬?女孩子最喜欢,特别是结了婚的女人,更是爱死了。(答案:钻石) 71.一品大官的俸禄(打一复姓)。->","completion":" 高辛\nENDEND"} 135 | {"prompt":"婴儿当诱饵(打一俗语)。->","completion":" 舍不得孩子套不住狼\nENDEND"} 136 | {"prompt":"二小姐,猜一个字。->","completion":" 姿\nENDEND"} 137 | {"prompt":"十八罗汉立空中,整体赛过活神仙(打一热门人物)。->","completion":" 李天一\nENDEND"} 138 | {"prompt":"供认不讳(打一离合字)。->","completion":" 口不否\nENDEND"} 139 | {"prompt":"一横一横长,人字在一旁(打一个字)。->","completion":" 仁\nENDEND"} 140 | {"prompt":"阿明给蚊子咬了一大一小的包,请问较大的包,是公蚊子咬的,还是母蚊子咬的?(答案:公蚊是不咬人的) 78.为什么妈妈几个月都不给弟弟吃饭,但弟弟仍然健康成长。为什么?。->","completion":" 因为弟弟在妈妈的肚子里\nENDEND"} 141 | {"prompt":"长得像竹不是竹,周身有节不太粗,不是紫来就是绿,只吃生来不能熟。。->","completion":" 甘蔗\nENDEND"} 142 | {"prompt":"两棵树上挂饰品,不带金不带银(打一《红楼梦》人物)。->","completion":" 林黛玉(带玉)\nENDEND"} 143 | {"prompt":"日长月短左右战,一正一反两边排,猜一个字。->","completion":" 门\nENDEND"} 144 | {"prompt":"白白的,软软的,暖暖的(打一植物)。->","completion":" 棉花\nENDEND"} 145 | {"prompt":"在一间房子里,有油灯,暖炉及壁炉.现在,想要将三个器具点燃,可是你只有一根火柴.请问首先应该点哪一样?。->","completion":" 火柴)\nENDEND"} 146 | {"prompt":"一间牢房中关了两名犯人,其中一个因偷窃,要关一年,另一个是强盗杀人犯,却只关两个星期,为什么?。->","completion":" 因为杀人犯要拉去填命)\nENDEND"} 147 | {"prompt":"两个人分五个苹果,怎么分最公平?。->","completion":" 榨成果汁)\nENDEND"} 148 | {"prompt":"小张开车,不小心撞上电线杆发生车祸,警察到达时车上有个死人,小张说这与他无关,警察也相信了,为什么?。->","completion":" 小张开灵车)\nENDEND"} 149 | {"prompt":"一只凶猛的饿猫,看到老鼠,为何拔腿就跑?。->","completion":" 跑去追老鼠)\nENDEND"} 150 | {"prompt":"动物园中,大象鼻子最长,鼻子第二长的是什么?。->","completion":" 小象)\nENDEND"} 151 | {"prompt":"一个人在沙滩上行走,回头为什么看不见自己的脚印?。->","completion":" 倒着走)\nENDEND"} 152 | {"prompt":"什么动物你打死了它,却流了你的血?。->","completion":" 蚊子)\nENDEND"} 153 | {"prompt":"两对父子去买帽子,为什么只买了三顶?。->","completion":" 三代人)\nENDEND"} 154 | {"prompt":"小红和小丽是同学,也住在同一条街,她们总是一起上学,可是每天一出家门就一个向左走,一个向右走,这是怎么回事呢?。->","completion":" 他们的家门是相对着的)\nENDEND"} 155 | {"prompt":"在一次监察严密的考试中,有两个学生交了一模一样的考卷。主考官发现后,却并没有认为他们作弊,这是什么原因?。->","completion":" 二张考卷交得都是白卷)\nENDEND"} 156 | {"prompt":"张大妈整天说个不停,可有一个月她说话最少,那是哪个月?。->","completion":" 二月份)\nENDEND"} 157 | {"prompt":"有一种地方专门教坏人,但没有一个警察敢对它采取行动加以扫荡。这是什么地方。。->","completion":" 看守所)\nENDEND"} 158 | {"prompt":"报纸上登的消息不一定百分之百是真的,但什么消息绝对假不了?。->","completion":" 报纸上的年月日)\nENDEND"} 159 | {"prompt":"早晨醒来,每个人都会去做的第一件事是什么?。->","completion":" 睁眼)\nENDEND"} 160 | {"prompt":"如果你有一只下金蛋的母鸡,你该怎么办?。->","completion":" 不要再做梦了)\nENDEND"} 161 | {"prompt":"一架飞机坐满了人,从万米高空落下坠毁,为什么却一个伤者也没有?。->","completion":" 没有伤者,都摔死了)\nENDEND"} 162 | {"prompt":"红红果子棍上挂,外裹糖儿味道佳(打一食品)。->","completion":" 冰糖葫芦\nENDEND"} 163 | {"prompt":"二人来比赛,绳索围栏杆,挥舞皮手套,看谁当状元(打一体育比赛项目)。->","completion":" 拳击\nENDEND"} 164 | {"prompt":"别看是堆草,砂锅里面熬。每天喝两碗,疾病被撵跑。(打一种药)。->","completion":" 中草药\nENDEND"} 165 | {"prompt":"月下美人(打一植物)。->","completion":" 昙花(“月下美人”是“昙花”的别名)\nENDEND"} 166 | {"prompt":"瘦瘦身体黑心肠,外披彩色花衣裳。琴棋书画会两样,削尖脑袋帮你忙。(打一物)。->","completion":" 铅笔\nENDEND"} 167 | {"prompt":"脱了红袍有白衣,白衣下面黑胖子(打一水果)。->","completion":" 荔枝\nENDEND"} 168 | {"prompt":"一群小姑娘,围坐水中央,举着小绿伞,个个笑红脸(打一植物)。->","completion":" 荷花\nENDEND"} 169 | {"prompt":"唱歌比赛赢奖品,小朋友们真高兴(打一节日)。->","completion":" 儿童节\nENDEND"} 170 | {"prompt":"小小四方纸,散发出幽香,饭店最常见。饭后就用它。->","completion":" 餐巾纸\nENDEND"} 171 | {"prompt":"脚穿一双特制鞋,尺码大得没了边,冰天雪地向前跑,速度快得像射箭(打一体育运动)。->","completion":" 滑雪\nENDEND"} 172 | {"prompt":"天上飞着一只鸟,用线牵着到处跑(打一玩具)。->","completion":" 风筝\nENDEND"} 173 | {"prompt":"圆规画蛋(猜地名)。->","completion":" 太原\nENDEND"} 174 | {"prompt":"孔明定下空城计,苏秦能说六国平,六郎要斩亲生子,宗保不舍穆桂英,猜四个字。->","completion":" 巧言令色\nENDEND"} 175 | {"prompt":"坐的姿势不对,它就跟你作对,要想身体笔直恶习立即纠正(打一人体器官)。->","completion":" 脊柱\nENDEND"} 176 | {"prompt":"不能口头推荐淮阴侯探骊格。->","completion":" 应用文·介绍信\nENDEND"} 177 | {"prompt":"小小箱子真奇妙,里面装着各种药,走村串寒送温暖,乡村医生不能少(打一医疗器具)。->","completion":" 医药箱\nENDEND"} 178 | {"prompt":"远看像蛋糕,近看像蜂巢。全身小洞洞,吸水效果好(打一物)。->","completion":" 海绵\nENDEND"} 179 | {"prompt":"浑身毛绒绒,有水拧一拧,人人离不开,早晚都要用(打一日用品)。->","completion":" 毛巾\nENDEND"} 180 | {"prompt":"树弯弯藤弯弯,秋天结果一串串。紫的紫来绿的绿,造出好酒甜又甜(打一水果)。->","completion":" 葡萄\nENDEND"} 181 | {"prompt":"俊美无匹却为妖,贵气逼人毒华爪(打一动漫人物)。->","completion":" 杀生丸\nENDEND"} 182 | {"prompt":"高高树上结果实,插入吸管尽情饮(打一水果)。->","completion":" 椰子\nENDEND"} 183 | {"prompt":"母马打一个字。->","completion":" 妈(母就是女)\nENDEND"} 184 | {"prompt":"小小水池像战场,跳进水里手脚忙,你追我赶比谁快,分分秒秒不相让(打一体育比赛项目)。->","completion":" 游泳\nENDEND"} 185 | {"prompt":"一个有着两把大扇子的小朋友(打一动画片)。->","completion":" 《大耳朵图图》\nENDEND"} 186 | {"prompt":"一对姐妹花,身穿红褂褂,各把门一端,净说吉祥话(打一节日物品)。->","completion":" 春联\nENDEND"} 187 | {"prompt":"喵!汪!(打一动画片)。->","completion":" 《猫狗\/Catdog》\nENDEND"} 188 | {"prompt":"绿色叶子红色根,大力水手的最爱(打一植物)。->","completion":" 菠菜\nENDEND"} 189 | {"prompt":"一个很有破案头脑的小鬼(打一动漫)。->","completion":" 《名侦探柯南》\nENDEND"} 190 | {"prompt":"有话大家讲,猜一字。->","completion":" 讼\nENDEND"} 191 | {"prompt":"样子像小锅,不把饭菜热,扣在脑袋上,立刻冷变热(打一日用品)。->","completion":" 帽子\nENDEND"} 192 | {"prompt":"小小家伙本领大,数字再多都会算;答案瞬间就得出,人人爱把它来赞(打一物品)。->","completion":" 计算器\nENDEND"} 193 | {"prompt":"长长方方小年糕,香气扑鼻不能咬。搓搓柔柔变泡泡,清洗衣服个变小。(打一物)。->","completion":" 肥皂\nENDEND"} 194 | {"prompt":"赤珊瑚儿地下埋,片片绿叶头上栽;清甜爽口营养菜,男女老少把它爱(打一蔬菜)。->","completion":" 胡萝卜\nENDEND"} 195 | {"prompt":"远看一点火,近看一盏灯,无风它会动,白天不出来(打一动物)。->","completion":" 萤火虫\nENDEND"} 196 | {"prompt":"植物界的老寿星(打一植物)。->","completion":" 百岁兰\nENDEND"} 197 | {"prompt":"益母果儿青黄色,切片泡水解渴喝(打一水果)。->","completion":" 柠檬\nENDEND"} 198 | {"prompt":"桌上小书怪稀奇,没有故事有日期,日日月月写得清,寸寸光阴要爱惜(打一文化用品)。->","completion":" 台历\nENDEND"} 199 | {"prompt":"国外婴儿(打一玩具)。->","completion":" 洋娃娃\nENDEND"} 200 | {"prompt":"身披绿袍有柔毛,头上开有小黄包,细嫩肉质味道好,解毒调经价值高(打一蔬菜)。->","completion":" 丝瓜\nENDEND"} 201 | {"prompt":"脸蛋圆圆金灿灿,对着太阳哈哈笑(打一花卉)。->","completion":" 向日葵\nENDEND"} 202 | {"prompt":"大三角,可折叠,脖上挂,很神圣(打一物品)。->","completion":" 红领巾\nENDEND"} 203 | {"prompt":"花顶生伞房,花序呈紫色。(打一植物)。->","completion":" 红枫\nENDEND"} 204 | {"prompt":"小小矮瓜皮光滑,紫袍姑娘顶呱呱(打一蔬菜)。->","completion":" 茄子\nENDEND"} 205 | {"prompt":"圆圆小铁汉,肚里盛着电,不要随处仍,小心有污染(打一日用品)。->","completion":" 电池\nENDEND"} 206 | {"prompt":"方块形的黄色海绵(打一动画片)。->","completion":" 《海绵宝宝》\nENDEND"} 207 | {"prompt":"脸蛋发光桌上放,梳妆打扮它帮忙(打一物)。->","completion":" 镜子\nENDEND"} 208 | {"prompt":"身材圆又圆,穿着黑白衣,肚子装着气,一踢飞老高(打一运动用品)。->","completion":" 足球\nENDEND"} 209 | {"prompt":"星星礼物树上放,彩色灯儿好漂亮(打一国外节日)。->","completion":" 圣诞节\nENDEND"} 210 | {"prompt":"一个矮胖子,天天挨鞭子。鞭子抽一遍,胖子转圈圈。(打一玩具)。->","completion":" 陀螺\nENDEND"} 211 | {"prompt":"喜羊羊看见一片嫩草(打一水果)。->","completion":" 草莓(草没,被喜羊羊吃了)\nENDEND"} 212 | {"prompt":"生来包公面,圆头多心眼。不会唱大戏,黑红白变脸。(打一物)。->","completion":" 蜂窝煤\nENDEND"} 213 | {"prompt":"两管弯弯挂耳内,一个小鼓管下垂,又听心来又听肺,听听声音对不对(打一医疗器具)。->","completion":" 听诊器\nENDEND"} 214 | {"prompt":"小小丸子白又白,里面黑泥流出来(打一节日食品)。->","completion":" 汤圆\nENDEND"} 215 | {"prompt":"粉色绒球讨人爱,人若一碰它不开(打一花卉)。->","completion":" 含羞草\nENDEND"} 216 | {"prompt":"一只鸟儿没有毛,却在空中随风摇(打一玩具)。->","completion":" 风筝\nENDEND"} 217 | {"prompt":"个个生两角(打一物)。->","completion":" 毛笔\nENDEND"} 218 | {"prompt":"金黄坛子装饺子,红红饺子有珠子(打一水果)。->","completion":" 橘子\nENDEND"} 219 | {"prompt":"与其给我飞吻,何若让我依偎在你身旁。(六字口语)。->","completion":" 远亲不如近邻\nENDEND"} 220 | {"prompt":"土黄外皮包白果,岭南佳果易上火(打一水果)。->","completion":" 龙眼\nENDEND"} 221 | {"prompt":"五月节里粽儿香,小朋友们把它抢(打一节日)。->","completion":" 端午节\nENDEND"} 222 | {"prompt":"你能做、我能做、大家都能做,一个人能做、两个人不能一起做。这是做什么。->","completion":" 做梦\nENDEND"} 223 | {"prompt":"一个离过五十次婚的女人,应该怎么形容她。->","completion":" 前公尽弃\nENDEND"} 224 | {"prompt":"三个孩子吃三个饼要用3分钟,九十个孩子九十个饼要用多少时间。->","completion":" 也是三分钟,九十个孩子同时吃\nENDEND"} 225 | {"prompt":"什么样的轮子只转不走。->","completion":" 风车的轮子\nENDEND"} 226 | {"prompt":"地球上什么东西每天要走的距离最远。->","completion":" 地球(地球每天自转一周为四百万公里)\nENDEND"} 227 | {"prompt":"中国人最早的姓氏是什么。->","completion":" 姓善\nENDEND"} 228 | {"prompt":"铁放到外面要生锈,那金子呢。->","completion":" 会被偷走\nENDEND"} 229 | {"prompt":"在什么时候1+2不等于3。->","completion":" 算错了的时候\nENDEND"} 230 | {"prompt":"两个人住在一个胡同里,只隔几步路,他们同在一个工厂上班,但每天出门上班,却总一个向左,一个向右,为什么。->","completion":" 他们住对门\nENDEND"} 231 | {"prompt":"什么时候最好还是要高高举起你的双手好些。->","completion":" 当有人用枪指着你的头的时候\nENDEND"} 232 | {"prompt":"小明家住在五楼,可是电梯坏了,他自己也没有走楼梯,他却上了五楼回到家里,这可能吗。->","completion":" 妈妈背着他上的楼\nENDEND"} 233 | {"prompt":"一根又黑、又粗、又硬的棍子插进洞里,感觉暖烘烘的,等到抽出来以后,客人就要付钱啦(一种行业)。->","completion":" 烤甘蔗\nENDEND"} 234 | {"prompt":"舔也硬,不舔也硬,想舒服睡,先搓搓它(人身上的东西)。->","completion":" 牙齿\nENDEND"} 235 | {"prompt":"一种东西,东方人的短,西方人的长,结婚后女的就可以用男的这东西,和尚有但是不用它。->","completion":" 人的,姓\nENDEND"} 236 | {"prompt":"什么东西最硬?女孩子最喜欢,特别是结了婚的女人,更是爱死了。。->","completion":" 钻石\nENDEND"} 237 | {"prompt":"阿明给蚊子咬了一大一小的包,请问较大的包,是公蚊子咬的,还是母蚊子咬的。->","completion":" 公蚊是不咬人的\nENDEND"} 238 | {"prompt":"在一间房子里,有油灯,暖炉及壁炉.现在,想要将三个器具点燃,可是你只有一根火柴.请问首先应该点哪一样。->","completion":" 火柴\nENDEND"} 239 | {"prompt":"一间牢房中关了两名犯人,其中一个因偷窃,要关一年,另一个是强盗杀人犯,却只关两个星期,为什么。->","completion":" 因为杀人犯要拉去填命\nENDEND"} 240 | {"prompt":"两个人分五个苹果,怎么分最公平。->","completion":" 榨成果汁\nENDEND"} 241 | {"prompt":"小张开车,不小心撞上电线杆发生车祸,警察到达时车上有个死人,小张说这与他无关,警察也相信了,为什么。->","completion":" 小张开灵车\nENDEND"} 242 | {"prompt":"一只凶猛的饿猫,看到老鼠,为何拔腿就跑。->","completion":" 跑去追老鼠\nENDEND"} 243 | {"prompt":"动物园中,大象鼻子最长,鼻子第二长的是什么。->","completion":" 小象\nENDEND"} 244 | {"prompt":"一个人在沙滩上行走,回头为什么看不见自己的脚印。->","completion":" 倒着走\nENDEND"} 245 | {"prompt":"什么动物你打死了它,却流了你的血。->","completion":" 蚊子\nENDEND"} 246 | {"prompt":"两对父子去买帽子,为什么只买了三顶。->","completion":" 三代人\nENDEND"} 247 | {"prompt":"小红和小丽是同学,也住在同一条街,她们总是一起上学,可是每天一出家门就一个向左走,一个向右走,这是怎么回事呢。->","completion":" 他们的家门是相对着的\nENDEND"} 248 | {"prompt":"在一次监察严密的考试中,有两个学生交了一模一样的考卷。主考官发现后,却并没有认为他们作弊,这是什么原因。->","completion":" 二张考卷交得都是白卷\nENDEND"} 249 | {"prompt":"张大妈整天说个不停,可有一个月她说话最少,那是哪个月。->","completion":" 二月份\nENDEND"} 250 | {"prompt":"有一种地方专门教坏人,但没有一个警察敢对它采取行动加以扫荡。这是什么地方(答案:看守所) 报纸上登的消息不一定百分之百是真的,但什么消息绝对假不了。->","completion":" 报纸上的年、月、日\nENDEND"} 251 | {"prompt":"早晨醒来,每个人都会去做的第一件事是什么。->","completion":" 睁眼\nENDEND"} 252 | {"prompt":"如果你有一只下金蛋的母鸡,你该怎么办。->","completion":" 不要再做梦了\nENDEND"} 253 | {"prompt":"一架飞机坐满了人,从万米高空落下坠毁,为什么却一个伤者也没有。->","completion":" 没有伤者,都摔死了\nENDEND"} 254 | {"prompt":"要想使梦成为现实,我们干的第一件事会是什么。->","completion":" 醒来\nENDEND"} 255 | {"prompt":"什么东西人们都不喜欢吃。->","completion":" 吃亏\nENDEND"} 256 | {"prompt":"别人跟阿丹说她的衣服怎么没衣扣,她却不在乎,为什么。->","completion":" 因为他的衣服只有拉链没有扣子\nENDEND"} 257 | {"prompt":"裤裆里放鞭炮-----打一军事用品(答案:**) 避孕套----打一地名(答案:**) 小刘是个很普通的人,为什么竟然能一连十几个小时不眨眼。->","completion":" 睡觉的时候\nENDEND"} 258 | {"prompt":"情人卡、生日卡、大大小小的卡,到底要寄什么卡给女人,最能博得她的欢心呢。->","completion":" 信用卡\nENDEND"} 259 | {"prompt":"小王走路从来脚不沾地,这是为什么。->","completion":" 因为穿着鞋子\nENDEND"} 260 | {"prompt":"什么地方开口说话要付钱。->","completion":" 打电话\nENDEND"} 261 | {"prompt":"冬冬的爸爸牙齿非常好,可是他经常去口腔医院,为什么。->","completion":" 因为他是牙科医生\nENDEND"} 262 | {"prompt":"盖楼要从第几层开始盖。->","completion":" 是从地基开始的\nENDEND"} 263 | {"prompt":"为什么大雁秋天要飞到南方去。->","completion":" 如果走,哪太慢了\nENDEND"} 264 | {"prompt":"什么门永远关不上。->","completion":" 足球门\nENDEND"} 265 | {"prompt":"什么东西比乌鸦更讨厌。->","completion":" 乌鸦嘴\nENDEND"} 266 | {"prompt":"女人翻跟头。---打一外国城市名(答案:巴比伦) 有一块天然的黑色的大理石,在九月七号这一天,把它扔到钱塘江里会有什么现象发生。->","completion":" 沉到江底\nENDEND"} 267 | {"prompt":"有一个人,他是你父母生的,但他却不是你的兄弟姐妹,他是谁。->","completion":" 你自己\nENDEND"} 268 | {"prompt":"什么东西天气越热,它爬的越高。->","completion":" 温度计\nENDEND"} 269 | {"prompt":"有一位老太太上了公车,为什么没人让座。->","completion":" 车上有空位\nENDEND"} 270 | {"prompt":"小王一边刷牙,一边悠闲的吹着口哨,他是怎么做到的。->","completion":" 刷假牙\nENDEND"} 271 | {"prompt":"用椰子和西瓜打头哪一个比较痛。->","completion":" 头比较痛\nENDEND"} 272 | {"prompt":"制造日期与有效日期是同一天的产品是什么。->","completion":" 报纸\nENDEND"} 273 | {"prompt":"为什么有家医院从不给人看病。->","completion":" 兽医院\nENDEND"} 274 | {"prompt":"有一头头朝北的牛,它向右转原地转三圈,然后向后转原地转三圈,接着再往右转,这时候它的尾巴朝哪。->","completion":" 朝地\nENDEND"} 275 | {"prompt":"胖妞生病了,最怕别人来探病时说什么。->","completion":" 多多保重\nENDEND"} 276 | {"prompt":"如果明天就是世界末日,为什么今天就有人想自杀。->","completion":" 去天堂占位置\nENDEND"} 277 | {"prompt":"一对健康的夫妇,为什么会生出没有眼睛的婴儿。->","completion":" 鸡生蛋\nENDEND"} 278 | {"prompt":"狐狸精最擅长迷惑男人,那么什么“精”男女一起迷。->","completion":" 酒精\nENDEND"} 279 | {"prompt":"小张走路从来脚不沾地,这是为什么。->","completion":" 还隔着鞋和袜子\nENDEND"} 280 | {"prompt":"胖胖是个颇有名气的跳水运动员,可是有一天,他站在跳台上,却不敢往下跳。这是为什么。->","completion":" 下面没有水\nENDEND"} 281 | {"prompt":"哪一颗牙最后长出来。->","completion":" 假牙\nENDEND"} 282 | {"prompt":"为什么两只老虎打架,非要拼个你死我活绝不罢休。->","completion":" 没有人敢去劝架\nENDEND"} 283 | {"prompt":"小红与妈妈都在同一个班里上课,这是为什么。->","completion":" 一个是学生,一个是老师\nENDEND"} 284 | {"prompt":"为什么游泳比赛中青蛙输给了狗。->","completion":" 青蛙用蛙泳犯规\nENDEND"} 285 | {"prompt":"为读完北京大学需要多少时间。->","completion":" 一钞钟足够\nENDEND"} 286 | {"prompt":"小明总是喜欢把家里的闹钟整坏,妈妈为什么总是让不会修理钟表的爸爸代为修理。->","completion":" 修理小明\nENDEND"} 287 | {"prompt":"黑人和白人生下的婴儿,牙齿是什么颜色。->","completion":" 婴儿没有牙\nENDEND"} 288 | {"prompt":"有一根棍子,要使它变短,但不许锯断,折断或削短,该怎么办。->","completion":" 拿一根长得跟它比\nENDEND"} 289 | {"prompt":"在罗马数字中,零该怎么写。->","completion":" 罗马数字没有零\nENDEND"} 290 | {"prompt":"你能否用3跟筷子搭起一个比3大比4小的数。->","completion":" 搭成圆周率∏\nENDEND"} 291 | {"prompt":"沙沙声称自己是辨别母鸡年龄的专家,其绝招是用牙齿,为什么。->","completion":" 把鸡亲口吃了来辨别母鸡的老嫩\nENDEND"} 292 | {"prompt":"数字0到1之间加一个什么号,才能使这个数比0大,而比1小呢。->","completion":" 加个.成为0.1\nENDEND"} 293 | {"prompt":"什么东西说父亲是不会相碰,叫爸爸时却会碰到两次。->","completion":" 上嘴唇和下嘴唇\nENDEND"} 294 | {"prompt":"一张方桌据掉一个角,还有几个角。->","completion":" 5个角\nENDEND"} 295 | {"prompt":"金太太一向心直口快,可什么事竟让她突然变得吞吞吐吐了呢。->","completion":" 金太太在吃甘蔗的时候吞吞吐吐\nENDEND"} 296 | {"prompt":"请仔细想一想,你所见到的最大影子是什么。->","completion":" 地球的影子,即每天的晚上\nENDEND"} 297 | {"prompt":"把24个人按5人排列,排城6行,该怎样排。->","completion":" 排成正六边形即可\nENDEND"} 298 | {"prompt":"公共汽车上,两个人正在热烈的交谈,可围观的人却一句话也听不到,这是因为什么。->","completion":" 这是一对聋哑人\nENDEND"} 299 | {"prompt":"一个人在什么情况下,才处于真正的任人宰割的地步。->","completion":" 在手术台上时\nENDEND"} 300 | {"prompt":"什么东西愈生气,它便愈大。->","completion":" 脾气\nENDEND"} 301 | {"prompt":"问医生病人的情况,医生只举起5个手指家人就哭了,是什么原因呢。->","completion":" 三长二短\nENDEND"} 302 | {"prompt":"人们甘心情愿买假的东西是什么。->","completion":" 假发,假牙\nENDEND"} 303 | {"prompt":"什么东西越洗越脏。->","completion":" 水\nENDEND"} 304 | {"prompt":"最不听话的是谁。->","completion":" 聋子\nENDEND"} 305 | {"prompt":"一个人掉到河里,还挣扎了几下,它从河里爬上来,衣服全湿了,头发却没湿,为什么。->","completion":" 因为他是光头\nENDEND"} 306 | {"prompt":"小明新买的袜子就有一个洞,他却不去找售货员换,你知道为什么吗。->","completion":" 袜口\nENDEND"} 307 | {"prompt":"什么事你明明没有做,但却要受罚。->","completion":" 家庭作业\nENDEND"} 308 | {"prompt":"大家都不想得到的是什么。->","completion":" 得病\nENDEND"} 309 | {"prompt":"什么英文字母最多人喜欢听呢。->","completion":" CD\nENDEND"} 310 | {"prompt":"你看我穿这件衣服好看吗?->","completion":" “嗯嗯,不错,就它了,我去买单”或“宝贝,这衣服真的不太适合你。”\nENDEND"} 311 | {"prompt":"你爱我吗?->","completion":" 你可以凝视着她的双眼三秒钟,然后轻轻地亲一下她的额头,然后小声地在她耳边说一句我爱你。\nENDEND"} 312 | {"prompt":"亲爱的,你觉得我胖了吗?->","completion":" 我就是喜欢你现在这个样子,有点肉,挺可爱的。\nENDEND"} 313 | {"prompt":"我和你妈同时掉进水里,你先救谁?->","completion":" 我会先救我妈,然后再救你,如果你不幸淹死了,我再跳下去和你一起死。\nENDEND"} 314 | {"prompt":"你觉得我这朋友怎样?->","completion":" 她人挺不错的,你要好好珍惜这样的朋友。\nENDEND"} 315 | {"prompt":"你中了大乐透500万怎么分?->","completion":" 我一毛钱都不会给你,因为我是你的。\nENDEND"} 316 | {"prompt":"你谈过几个男/女朋友?->","completion":" 你不是我第一个,但是我想你是我最后一个。\nENDEND"} 317 | {"prompt":"你在干嘛呢?->","completion":" 们两个真的很有默契,刚好我也想发信息问你在干嘛呢。\nENDEND"} 318 | {"prompt":"你睡了么?->","completion":" 我睡不着,没有拉,就是觉得你……\nENDEND"} 319 | {"prompt":"你想我了么?->","completion":" 不敢想,因为想也见不到。\nENDEND"} 320 | {"prompt":"你觉得我怎么样啊?->","completion":" 你这么问,是不是对我有意思啊。。\nENDEND"} 321 | {"prompt":"你为什么喜欢我?->","completion":" 我以为我喜欢的是你的优秀,到现在我才发现喜欢你,没有理由。\nENDEND"} 322 | {"prompt":"晚上想吃什么?->","completion":" 是以前还是现在啊?以前的我想吃火锅,现在的我想和你吃火锅\nENDEND"} 323 | {"prompt":"你觉得我们下辈子还会在一起吗?->","completion":" 傻瓜,这个问题你上辈子不就问过了吗。\nENDEND"} 324 | {"prompt":"你闻到烧焦的味道了吗??->","completion":" 是我爱你的心在燃烧。\nENDEND"} 325 | {"prompt":"我有种神奇的魔力……,总能找到好看的东西->","completion":" 比如:你\nENDEND"} 326 | {"prompt":"你相信一见钟情吗?->","completion":" 要不我再从你身边路过一次试试。\nENDEND"} 327 | {"prompt":"你知道,通往幸福的门是什么门吗?->","completion":" 是我们。\nENDEND"} 328 | {"prompt":"你会一直喜欢我吗?->","completion":" 喜欢你,不是一时兴起,也没有心口不一\nENDEND"} 329 | {"prompt":"头发剪的好丑啊!->","completion":" 稍微降低一下颜值,给别人一条活路不行吗?\nENDEND"} 330 | {"prompt":"你知道你哪里错了吗?->","completion":" 难道 我没有做错,就不能被你骂?\nENDEND"} 331 | {"prompt":"我今天画眉笔的时候,眉笔不出水甩了几下,不小心甩到你的衬衫上了。->","completion":" 没事,我再给你买一个眉笔,不是不出水吗?\nENDEND"} 332 | {"prompt":"你都没有看到我吗?->","completion":" 我在路上从来不看女生的,尤其是长得好看的女生\nENDEND"} 333 | {"prompt":"范冰冰和Angelababy谁漂亮?->","completion":" 难道选项里不加上你吗?\nENDEND"} 334 | {"prompt":"你之前都谈过好几个了,我就谈一次就一辈子跟你了。->","completion":" 你还好意思说,我找一个不是你,再找一个还不是你,害我找那么长时间。你倒好,找一次我就出现在你面前了。\nENDEND"} 335 | {"prompt":"你不要和我说话。->","completion":" 因为我不配和你这样的小仙女说话!\nENDEND"} 336 | {"prompt":"如果你出去蹦迪,有女孩拼命地往你身上蹭,你会怎么办?->","completion":" 我为什么要去蹦迪?如果我去蹦迪了,家里的衣服谁来洗,饭谁来做,地谁来拖?如果朋友非要叫我去蹦迪,那么我也会带上你,根本就不给别人靠近我的机会\nENDEND"} 337 | {"prompt":"如果我跟你吵架,离家出走,你会不会来找我?->","completion":" 吵架?根本不会存在,你不开心就是我的错,更别说吵架了,那我还不得抱着你的腿,24小时不放手?\nENDEND"} 338 | {"prompt":"我剥小龙虾的时候,油不小心滴到了你新买的名牌衣服上,怎么办?->","completion":" 你要我干嘛的,嗯?只要我有手的一天,就不会让你亲自剥虾。\nENDEND"} 339 | {"prompt":"如果有一天,我和你妈同时掉进水里,你会先去救谁?->","completion":" 我为什么要让你和我妈同时掉进水里,要我是干嘛用的,而且我妈会游泳,平时我妈出去,我爸也都在他身边,不存在的,这种事情你别太费心,我呢?肯定跟我爸一样,守在自己媳妇儿身边!\nENDEND"} 340 | {"prompt":"如果有一天,我们都没钱了,可是我还是想吃好吃的,想喝好喝的,怎么办?->","completion":" 根本不会存在这样的问题,只要你和我在一起的一天,我都会因为你拼命的努力赚钱,我要给你一个好的未来,放心吧,别想那么多,我会加油的!\nENDEND"} 341 | {"prompt":"如果以后我生完孩子,身材走样,你会不会不爱我?->","completion":" 说的我好像现在的身材很好一样,我不是也胖了吗?那我问你,你会不会因为我身材走样而不爱我呢?不会,对吗?那不就完了,我们这是幸福肥,懂吗,以后别再这么说了,好不好?\nENDEND"} 342 | {"prompt":"如果你女朋友生病了要去医院,但这个时候你的王者荣耀刚开局,你选哪个?->","completion":" 当然是去医院陪女朋友啦。\nENDEND"} 343 | {"prompt":"亲爱的,你觉得范冰冰漂亮还是刘亦菲漂亮?->","completion":" 在我眼里你最好看,她们都没有你好看。\nENDEND"} 344 | {"prompt":"女朋友生理期到了你怎么办?->","completion":" 陪在她身边,给她按摩肚子,煮红糖水。\nENDEND"} 345 | {"prompt":"老公,我穿这件衣服好胖啊。->","completion":" 我觉得很好看啊,你穿那件都好看,我媳妇天生丽质。\nENDEND"} 346 | {"prompt":"给我讲讲你前女友的事吧,我保证不生气。->","completion":" 前女友有什么好说的,我都忘完了,懒得讲。\nENDEND"} 347 | {"prompt":"打游戏的时候你能不能让着我啊?->","completion":" 没问题,只要宝贝开心,游戏算什么。\nENDEND"} 348 | {"prompt":"我今晚不吃晚饭了,长胖了不好看,你就不喜欢我了。->","completion":" 那不行,必须吃晚饭。你又不胖,就算胖了,我也喜欢。所以,今晚想吃火锅还是小龙虾?\nENDEND"} 349 | {"prompt":"吃饭时停电为什么扒拉两口饭灯就会亮?->","completion":" 因为巴啦啦能量\nENDEND"} 350 | {"prompt":"小王剪了中分会变成什么?->","completion":" 小全\nENDEND"} 351 | {"prompt":"狐狸为什么站不起来?->","completion":" 因为他狡猾(脚滑)\nENDEND"} 352 | {"prompt":"吸血鬼喜欢吃辣吗?->","completion":" 不喜欢,因为他们喜欢blood\nENDEND"} 353 | {"prompt":"为什么许仙给白娘子买了顶帽子,白娘子觉得头很重?->","completion":" 因为是压蛇帽\nENDEND"} 354 | {"prompt":"我在树上唱rap,猜一个字。->","completion":" 桑,因为我在树上又又又。\nENDEND"} 355 | {"prompt":"有一天三角形,正方形,梯形,长方形,圆形约好出去玩,三角形没来,这个情形叫什么?->","completion":" 全等三角形。\nENDEND"} 356 | {"prompt":"狮子和熊比赛拉粑粑最后谁赢了?->","completion":" 狮子,因为事实胜于雄辩。\nENDEND"} 357 | {"prompt":"从前有个人姓铁,他总是不长头发,他得了什么病?->","completion":" 老铁没毛病。\nENDEND"} 358 | {"prompt":"一头公牛,加上一头母牛,打三个字。->","completion":" 两头牛。\nENDEND"} 359 | {"prompt":"为什么有钱人家的狗不会乱叫?->","completion":" 苟富贵,勿相忘。\nENDEND"} 360 | {"prompt":"有一只红怪兽和一只绿怪兽,红怪兽需要两颗子弹才能打死,绿怪兽只需要一颗,但你只有两颗子弹,请问怎么才能都杀死?->","completion":" 先杀绿色,然后红色的脸也被吓绿了。\nENDEND"} 361 | {"prompt":"透明的剑是什么剑?->","completion":" 看不见\nENDEND"} 362 | {"prompt":"依萍嘴炮,打一地名。->","completion":" 陆家嘴 因为依萍是陆家的人,所以是陆家嘴。\nENDEND"} 363 | {"prompt":"从1倒9,哪个数字最勤劳,哪个数字最懒惰?->","completion":" 1懒惰,2勤劳(一不做二不休)\nENDEND"} 364 | {"prompt":"什么汤最鲜->","completion":" 鱼羊汤,因为鱼羊一鲜\nENDEND"} 365 | {"prompt":"什么植物和动物像鸡->","completion":" 树和马,因为数码相机(树马)\nENDEND"} 366 | {"prompt":"请问热奶茶除了加冰之外,加什么可以变成冻奶茶?->","completion":" 加钱\nENDEND"} 367 | {"prompt":"两只骆驼在沙漠里看到一个梨。(猜-一个国家名)->","completion":" 咦?大梨(意大利)\nENDEND"} 368 | {"prompt":"两只骆驼又在沙漠里看到一个梨。(再猜一个国家名)->","completion":" 噢,大梨呀(澳大利亚) \nENDEND"} 369 | {"prompt":"小鸟穿着防弹衣在树上跳舞,被猎人看到,拿枪打死了,问:小鸟为什么会被打死?->","completion":" 因为它跳的是脱衣舞\nENDEND"} 370 | {"prompt":"汽车会飞,打一种饮料。->","completion":" Car飞=咖啡\nENDEND"} 371 | {"prompt":"蓝色的刀和蓝色的枪,打一成语。->","completion":" 刀枪blue\nENDEND"} -------------------------------------------------------------------------------- /src/test/java/cn/jianwoo/openai/DemoTest.java: -------------------------------------------------------------------------------- 1 | package cn.jianwoo.openai; 2 | 3 | import java.io.File; 4 | import java.math.BigDecimal; 5 | import java.net.InetSocketAddress; 6 | import java.net.Proxy; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.Collections; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | import cn.hutool.core.date.DateUtil; 14 | import cn.hutool.http.HttpRequest; 15 | import cn.hutool.http.HttpResponse; 16 | import cn.jianwoo.openai.chatgptapi.bo.BillingUsage; 17 | import cn.jianwoo.openai.chatgptapi.bo.FunctionsReq; 18 | import cn.jianwoo.openai.chatgptapi.bo.ParametersReq; 19 | import cn.jianwoo.openai.chatgptapi.bo.PropertyReq; 20 | import cn.jianwoo.openai.chatgptapi.bo.Subscription; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import com.alibaba.fastjson2.JSONObject; 24 | 25 | import cn.jianwoo.openai.chatgptapi.auth.OpenAiAuth; 26 | import cn.jianwoo.openai.chatgptapi.bo.AudioReq; 27 | import cn.jianwoo.openai.chatgptapi.bo.AudioRes; 28 | import cn.jianwoo.openai.chatgptapi.bo.CompletionReq; 29 | import cn.jianwoo.openai.chatgptapi.bo.CompletionRes; 30 | import cn.jianwoo.openai.chatgptapi.bo.EmbeddingsReq; 31 | import cn.jianwoo.openai.chatgptapi.bo.EmbeddingsRes; 32 | import cn.jianwoo.openai.chatgptapi.bo.EnginesDataRes; 33 | import cn.jianwoo.openai.chatgptapi.bo.EnginesListRes; 34 | import cn.jianwoo.openai.chatgptapi.bo.EventListRes; 35 | import cn.jianwoo.openai.chatgptapi.bo.FileDetRes; 36 | import cn.jianwoo.openai.chatgptapi.bo.FileListRes; 37 | import cn.jianwoo.openai.chatgptapi.bo.FileReq; 38 | import cn.jianwoo.openai.chatgptapi.bo.FineTuneListRes; 39 | import cn.jianwoo.openai.chatgptapi.bo.FineTunesReq; 40 | import cn.jianwoo.openai.chatgptapi.bo.FineTunesRes; 41 | import cn.jianwoo.openai.chatgptapi.bo.ImageReq; 42 | import cn.jianwoo.openai.chatgptapi.bo.ImageRes; 43 | import cn.jianwoo.openai.chatgptapi.bo.MessageReq; 44 | import cn.jianwoo.openai.chatgptapi.bo.ModelDataRes; 45 | import cn.jianwoo.openai.chatgptapi.bo.ModelRes; 46 | import cn.jianwoo.openai.chatgptapi.bo.ModerationsReq; 47 | import cn.jianwoo.openai.chatgptapi.bo.ModerationsRes; 48 | import cn.jianwoo.openai.chatgptapi.bo.ObjDelRes; 49 | import cn.jianwoo.openai.chatgptapi.completions.FastCompletion; 50 | import cn.jianwoo.openai.chatgptapi.constants.Model; 51 | import cn.jianwoo.openai.chatgptapi.constants.Role; 52 | import cn.jianwoo.openai.chatgptapi.exception.ApiException; 53 | import cn.jianwoo.openai.chatgptapi.service.PostApiService; 54 | import cn.jianwoo.openai.chatgptapi.service.impl.ChatGptApiPost; 55 | 56 | /** 57 | * @author gulihua 58 | * @Description 59 | * @date 2023-03-01 09:54 60 | */ 61 | public class DemoTest 62 | { 63 | static Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890)); 64 | 65 | static String apiKey = "sk-M****************************************************I"; 66 | static PostApiService service = new ChatGptApiPost(new OpenAiAuth(apiKey, proxy)); 67 | 68 | /** 69 | * 70 | * 列出模型 71 | * 72 | * @author gulihua 73 | */ 74 | @Test 75 | public void models() throws ApiException 76 | { 77 | ModelRes res = service.models(); 78 | System.out.println(JSONObject.toJSONString(res)); 79 | } 80 | 81 | 82 | /** 83 | * 84 | * 检索模型 85 | * 86 | * @author gulihua 87 | */ 88 | @Test 89 | public void model() throws ApiException 90 | { 91 | ModelDataRes res = service.model("text-davinci-001"); 92 | System.out.println(JSONObject.toJSONString(res)); 93 | } 94 | 95 | 96 | /** 97 | * 98 | * 创建AI对话 99 | * 100 | * @author gulihua 101 | */ 102 | @Test 103 | public void completions() throws ApiException 104 | { 105 | CompletionReq req = CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()).prompt("你好").build(); 106 | CompletionRes res = service.completions(req); 107 | System.out.println(JSONObject.toJSONString(res)); 108 | } 109 | 110 | 111 | /** 112 | * 113 | * 连续对话 114 | * 115 | * @author gulihua 116 | */ 117 | @Test 118 | public void completionsContext() throws ApiException 119 | { 120 | CompletionReq req = CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()) 121 | .stop("[\" Human:\", \" Bot:\"]").prompt("Human: 你好").build(); 122 | CompletionRes res = service.completions(req); 123 | System.out.println(JSONObject.toJSONString(res)); 124 | req.setPrompt(res.getAnswer() + "\n" + "Human: 你叫什么"); 125 | res = service.completions(req); 126 | System.out.println(JSONObject.toJSONString(res)); 127 | } 128 | 129 | 130 | /** 131 | * 132 | * 创建异步对话(流式) 133 | * 134 | * @author gulihua 135 | */ 136 | public static void completionsStream() throws Exception 137 | { 138 | CompletionReq req = CompletionReq.builder().model(Model.TEXT_DAVINCI_003.getName()).prompt("你是什么模型").build(); 139 | service.completionsStream(req, res -> { 140 | // 回调方法 141 | if (res != null) 142 | { 143 | System.out.println("isSuccess:" + res.getIsSuccess() + ", Done:" + res.getDone() + ", 接收到的数据: " 144 | + res.getAnswer()); 145 | 146 | } 147 | }); 148 | } 149 | 150 | 151 | /** 152 | * 153 | * 使用gpt-3.5-turbo模型聊天 154 | * 155 | * @author gulihua 156 | */ 157 | @Test 158 | public void completionsChat() throws ApiException 159 | { 160 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 161 | .messages( 162 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 163 | .build(); 164 | CompletionRes res = service.completionsChat(req); 165 | System.out.println(JSONObject.toJSONString(res)); 166 | } 167 | 168 | 169 | /** 170 | * 171 | * 使用gpt-3.5-turbo模型聊天 172 | * 173 | * @author gulihua 174 | */ 175 | @Test 176 | public void completionsChatContext() throws ApiException 177 | { 178 | long start = System.currentTimeMillis(); 179 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 180 | .messages(Collections 181 | .singletonList(MessageReq.builder().role(Role.USER.getName()).content("请重复我的话").build())) 182 | .build(); 183 | CompletionRes res = service.completionsChat(req); 184 | System.out.println(JSONObject.toJSONString(res)); 185 | long end = System.currentTimeMillis(); 186 | System.out.println("cost1=" + (end - start)); 187 | start = System.currentTimeMillis(); 188 | List messages = new ArrayList<>(); 189 | messages.add(res.getChoices().get(0).getMessage()); 190 | messages.add(MessageReq.builder().role(Role.USER.getName()).content("我是中国人").build()); 191 | req.setMessages(messages); 192 | res = service.completionsChat(req); 193 | System.out.println(JSONObject.toJSONString(res)); 194 | end = System.currentTimeMillis(); 195 | System.out.println("cost2=" + (end - start)); 196 | 197 | } 198 | 199 | 200 | /** 201 | * 202 | * 使用gpt-3.5-turbo模型聊天(流式) 203 | * 204 | * @author gulihua 205 | */ 206 | public static void completionsChatStream() throws Exception 207 | { 208 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO.getName()) 209 | .messages( 210 | Collections.singletonList(MessageReq.builder().role(Role.USER.getName()).content("你好").build())) 211 | .build(); 212 | service.completionsChatStream(req, res -> { 213 | // 回调方法 214 | if (res != null) 215 | { 216 | System.out.println("isSuccess:" + res.getIsSuccess() + ", Done:" + res.getDone() + ", 接收到的数据: " 217 | + res.getChatContent()); 218 | } 219 | }); 220 | } 221 | 222 | 223 | /** 224 | * 225 | * 使用gpt-3.5-turbo模型聊天(使用函数) 226 | * 227 | * @author gulihua 228 | */ 229 | @Test 230 | public void completionsChatFunctions() throws ApiException 231 | { 232 | PropertyReq location = PropertyReq.builder().name("location").type("string").description("城市,比如:上海").build(); 233 | PropertyReq format = PropertyReq.builder().name("format").type("string").description("温度单位") 234 | .enums(Arrays.asList("摄氏度", "华氏度")).build(); 235 | JSONObject properties = new JSONObject(); 236 | properties.putAll(location.toJSON()); 237 | properties.putAll(format.toJSON()); 238 | ParametersReq parametersReq = ParametersReq.builder().required(Arrays.asList("properties", "format")) 239 | .properties(properties).build(); 240 | FunctionsReq functions = FunctionsReq.builder().name("getCurrentWeather").description("查询天气") 241 | .parameters(parametersReq).build(); 242 | MessageReq messageReq = MessageReq.builder().role(Role.USER.getName()).content("南京天气怎么样,并给出穿衣建议").build(); 243 | 244 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 245 | .messages(Collections.singletonList(messageReq)).functions(Collections.singletonList(functions)) 246 | .build(); 247 | CompletionRes res = service.completionsChat(req); 248 | // System.out.println(JSONObject.toJSONString(res)); 249 | // System.out.println(res.getFunctionArgs()); 250 | MessageReq messageReq1 = MessageReq.builder().role(Role.ASSISTANT.getName()) 251 | .content(queryWeather(res.getFunctionArgs().getString("location"))).build(); 252 | 253 | req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 254 | .messages(Arrays.asList(messageReq, messageReq1)).build(); 255 | res = service.completionsChat(req); 256 | System.out.println(JSONObject.toJSONString(res)); 257 | } 258 | 259 | 260 | /** 261 | * 262 | * 使用gpt-3.5-turbo模型聊天(流式, 使用函数) 263 | * 264 | * @author gulihua 265 | */ 266 | public static void completionsChatStreamFunctions() throws Exception 267 | { 268 | PropertyReq location = PropertyReq.builder().name("location").type("string").description("城市,比如:上海").build(); 269 | PropertyReq format = PropertyReq.builder().name("format").type("string").description("温度单位") 270 | .enums(Arrays.asList("摄氏度", "华氏度")).build(); 271 | JSONObject properties = new JSONObject(); 272 | properties.putAll(location.toJSON()); 273 | properties.putAll(format.toJSON()); 274 | ParametersReq parametersReq = ParametersReq.builder().required(Arrays.asList("properties", "format")) 275 | .properties(properties).build(); 276 | FunctionsReq functions = FunctionsReq.builder().name("getCurrentWeather").description("查询天气") 277 | .parameters(parametersReq).build(); 278 | MessageReq messageReq = MessageReq.builder().role(Role.USER.getName()).content("南京天气怎么样,并给出穿衣建议").build(); 279 | 280 | CompletionReq req = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 281 | .messages(Collections.singletonList(messageReq)).functions(Collections.singletonList(functions)) 282 | .build(); 283 | StringBuilder sb = new StringBuilder(); 284 | service.completionsChatStream(req, res -> { 285 | // 回调方法 286 | if (res != null) 287 | { 288 | sb.append(res.getChatContent()); 289 | // 接收结束 290 | if (res.getDone()) 291 | { 292 | JSONObject args = JSONObject.parseObject(sb.toString()); 293 | MessageReq messageReq1 = MessageReq.builder().role(Role.ASSISTANT.getName()) 294 | .content(queryWeather(args.getString("location"))).build(); 295 | CompletionReq req1 = CompletionReq.builder().model(Model.GPT_35_TURBO_16K_0613.getName()) 296 | .messages(Arrays.asList(messageReq, messageReq1)).build(); 297 | StringBuilder sb1 = new StringBuilder(); 298 | service.completionsChatStream(req1, res1 -> { 299 | // 回调方法 300 | if (res1 != null) 301 | { 302 | System.out.println("isSuccess:" + res1.getIsSuccess() + ", Done:" + res1.getDone() 303 | + ", 接收到的数据: " + res1.getChatContent()); 304 | sb1.append(res1.getChatContent()); 305 | if (res1.getDone()) 306 | { 307 | System.out.println(sb1); 308 | } 309 | 310 | } 311 | }); 312 | } 313 | } 314 | }); 315 | 316 | } 317 | 318 | 319 | public static void main(String[] args) throws Exception 320 | { 321 | // completionsStream(); 322 | // completionsChatStream(); 323 | completionsChatStreamFunctions(); 324 | } 325 | 326 | 327 | private static String queryWeather(String city) 328 | { 329 | city = city.replaceAll("市", ""); 330 | String url = "https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=35229654&appsecret=o1KeF9bn&city=" 331 | + city; 332 | HttpResponse response = HttpRequest.get(url).execute(); 333 | JSONObject res = JSONObject.parse(response.body()); 334 | StringBuilder sb = new StringBuilder(); 335 | sb.append(res.getString("wea")); 336 | sb.append(","); 337 | sb.append("温度:"); 338 | sb.append(res.getString("tem2")).append("~").append(res.getString("tem1")); 339 | sb.append("风力:"); 340 | sb.append(res.getString("win")).append(" ").append(res.getString("win_speed")); 341 | sb.append("空气质量:"); 342 | sb.append(res.getString("air_level")); 343 | return sb.toString(); 344 | 345 | } 346 | 347 | 348 | /** 349 | * 350 | * 编辑会话文本 351 | * 352 | * @author gulihua 353 | */ 354 | @Test 355 | public void completionsEdit() throws ApiException 356 | { 357 | CompletionReq req = CompletionReq.builder().model("text-davinci-edit-001").input("What day of the wek is it?") 358 | .instruction("Fix the spelling mistakes").build(); 359 | CompletionRes res = service.completionsEdit(req); 360 | System.out.println(JSONObject.toJSONString(res)); 361 | } 362 | 363 | 364 | /** 365 | * 366 | * 根据描述生成图片 367 | * 368 | * @author gulihua 369 | */ 370 | @Test 371 | public void imageCreate() throws ApiException 372 | { 373 | ImageReq req = ImageReq.builder().prompt("cat").build(); 374 | ImageRes res = service.imageCreate(req); 375 | System.out.println(JSONObject.toJSONString(res)); 376 | } 377 | 378 | 379 | /** 380 | * 381 | * 编辑图片 382 | * 383 | * @author gulihua 384 | */ 385 | @Test 386 | public void imageEdit() throws ApiException 387 | { 388 | File cat = new File("/Users/gulihua/Downloads/cat.png"); 389 | ImageReq req = ImageReq.builder().prompt("cat").image(cat).build(); 390 | ImageRes res = service.imageEdit(req); 391 | System.out.println(JSONObject.toJSONString(res)); 392 | } 393 | 394 | 395 | /** 396 | * 397 | * 图像更改 398 | * 399 | * @author gulihua 400 | */ 401 | @Test 402 | public void imageVariate() throws ApiException 403 | { 404 | File cat = new File("/Users/gulihua/Downloads/cat.png"); 405 | ImageReq req = ImageReq.builder().prompt("cat").image(cat).build(); 406 | ImageRes res = service.imageVariate(req); 407 | System.out.println(JSONObject.toJSONString(res)); 408 | } 409 | 410 | 411 | /** 412 | * 413 | * 创建embeddings 414 | * 415 | * @author gulihua 416 | */ 417 | @Test 418 | public void embeddingsCreate() throws ApiException 419 | { 420 | EmbeddingsReq req = EmbeddingsReq.builder().model(Model.TEXT_EMBEDDING_ADA_002.getName()) 421 | .input(Collections.singletonList("he food was delicious and the waiter...")).build(); 422 | EmbeddingsRes res = service.embeddingsCreate(req); 423 | System.out.println(JSONObject.toJSONString(res)); 424 | } 425 | 426 | 427 | /** 428 | * 429 | * 语音转录 430 | * 431 | * @author gulihua 432 | */ 433 | @Test 434 | public void audioTranscribes() throws ApiException 435 | { 436 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 437 | AudioReq req = AudioReq.builder().file(audio).build(); 438 | AudioRes res = service.audioTranscribes(req); 439 | System.out.println(JSONObject.toJSONString(res)); 440 | } 441 | 442 | 443 | /** 444 | * 445 | * 语音翻译 446 | * 447 | * @author gulihua 448 | */ 449 | @Test 450 | public void audioTranslates() throws ApiException 451 | { 452 | File audio = new File("/Users/gulihua/Downloads/audio.mp3"); 453 | AudioReq req = AudioReq.builder().file(audio).build(); 454 | AudioRes res = service.audioTranslates(req); 455 | System.out.println(JSONObject.toJSONString(res)); 456 | } 457 | 458 | 459 | /** 460 | * 461 | * 列出所有用户上传的文件 462 | * 463 | * @author gulihua 464 | */ 465 | @Test 466 | public void fileList() throws ApiException 467 | { 468 | FileListRes res = service.fileList(); 469 | System.out.println(JSONObject.toJSONString(res)); 470 | } 471 | 472 | 473 | /** 474 | * 475 | * 文件上传 476 | * 477 | * @author gulihua 478 | */ 479 | @Test 480 | public void fileUpload() throws ApiException 481 | { 482 | File cat = new File("/Users/gulihua/tmp/chatGptApiSdk/src/main/resources/json_prepared.jsonl"); 483 | FileReq req = FileReq.builder().purpose("fine-tune").file(cat).build(); 484 | FileDetRes res = service.fileUpload(req); 485 | System.out.println(JSONObject.toJSONString(res)); 486 | } 487 | 488 | 489 | /** 490 | * 491 | * 文件删除 492 | * 493 | * @author gulihua 494 | */ 495 | @Test 496 | public void fileDelete() throws ApiException 497 | { 498 | ObjDelRes res = service.fileDelete("file-jPU5wZkSxqkWJr32HlvnEou0"); 499 | System.out.println(JSONObject.toJSONString(res)); 500 | } 501 | 502 | 503 | /** 504 | * 505 | * 文件检索 506 | * 507 | * @author gulihua 508 | */ 509 | @Test 510 | public void fileRetrieve() throws ApiException 511 | { 512 | FileDetRes res = service.fileRetrieve("file-2HvmtSTWMTatG5mvRTPerMkn"); 513 | System.out.println(JSONObject.toJSONString(res)); 514 | } 515 | 516 | 517 | /** 518 | * 519 | * 文件检索内容 520 | * 521 | * @author gulihua 522 | */ 523 | @Test 524 | public void fileRetrieveContent() throws ApiException 525 | { 526 | String res = service.fileRetrieveContent("file-2HvmtSTWMTatG5mvRTPerMkn"); 527 | System.out.println(JSONObject.toJSONString(res)); 528 | } 529 | 530 | 531 | /** 532 | * 533 | * 创建Fine-tunes 534 | * 535 | * @author gulihua 536 | */ 537 | @Test 538 | public void fineTuneCreate() throws ApiException 539 | { 540 | FineTunesReq req = FineTunesReq.builder().trainingFile("file-Cj4zi8QGZQAaVhKzMvL6NsGq") 541 | .model(Model.DAVINCI.getName()).suffix("davinci model test01").build(); 542 | FineTunesRes res = service.fineTuneCreate(req); 543 | System.out.println(JSONObject.toJSONString(res)); 544 | } 545 | 546 | 547 | /** 548 | * 549 | * 微调之后测试 550 | * 551 | * @author gulihua 552 | */ 553 | @Test 554 | public void completionsAfterFineTunes() throws ApiException 555 | { 556 | CompletionReq req = CompletionReq.builder().maxTokens(100).stop("END").frequencyPenalty(new BigDecimal(2)) 557 | .model("davinci:ft-personal:davinci-model-test01-2023-05-15-09-07-39") 558 | .prompt("小明的妈妈有三个儿子,大儿子叫大明,二儿子叫二明,三儿子叫什么。").build(); 559 | CompletionRes res = service.completions(req); 560 | System.out.println(JSONObject.toJSONString(res)); 561 | } 562 | 563 | 564 | /** 565 | * 566 | * 列出Fine-tunes 567 | * 568 | * @author gulihua 569 | */ 570 | @Test 571 | public void fineTuneList() throws ApiException 572 | { 573 | FineTuneListRes res = service.fineTuneList(); 574 | System.out.println(JSONObject.toJSONString(res)); 575 | } 576 | 577 | 578 | /** 579 | * 580 | * 检索Fine-tunes 581 | * 582 | * @author gulihua 583 | */ 584 | @Test 585 | public void fineTuneRetrieve() throws ApiException 586 | { 587 | FineTunesRes res = service.fineTuneRetrieve("ft-XyXOimCsBXnRc2Djpf52ghwl"); 588 | System.out.println(JSONObject.toJSONString(res)); 589 | } 590 | 591 | 592 | /** 593 | * 594 | * 取消Fine-tunes 595 | * 596 | * @author gulihua 597 | */ 598 | @Test 599 | public void fineTuneCancel() throws ApiException 600 | { 601 | FineTunesRes res = service.fineTuneCancel("ft-XyXOimCsBXnRc2Djpf52ghwl"); 602 | System.out.println(JSONObject.toJSONString(res)); 603 | } 604 | 605 | 606 | /** 607 | * 608 | * 列出Fine-tunes 事件 609 | * 610 | * @author gulihua 611 | */ 612 | @Test 613 | public void fineTuneEventList() throws ApiException 614 | { 615 | EventListRes res = service.fineTuneEventList("ft-XyXOimCsBXnRc2Djpf52ghwl"); 616 | System.out.println(JSONObject.toJSONString(res)); 617 | } 618 | 619 | 620 | /** 621 | * 622 | * 删除Fine-tunes 623 | * 624 | * @author gulihua 625 | */ 626 | @Test 627 | public void fineTuneDelete() throws ApiException 628 | { 629 | ObjDelRes res = service.fineTuneDelete("curie:ft-acmeco-2021-03-03-21-44-20"); 630 | System.out.println(JSONObject.toJSONString(res)); 631 | } 632 | 633 | 634 | /** 635 | * 636 | * 创建moderations 637 | * 638 | * @author gulihua 639 | */ 640 | @Test 641 | public void moderationsCreate() throws ApiException 642 | { 643 | ModerationsReq req = ModerationsReq.builder().input("I want to kill them.").build(); 644 | ModerationsRes res = service.moderationsCreate(req); 645 | System.out.println(JSONObject.toJSONString(res)); 646 | } 647 | 648 | 649 | /** 650 | * 651 | * 列出所有引擎 652 | * 653 | * @author gulihua 654 | */ 655 | @Test 656 | public void enginesList() throws ApiException 657 | { 658 | EnginesListRes res = service.enginesList(); 659 | System.out.println(JSONObject.toJSONString(res)); 660 | } 661 | 662 | 663 | /** 664 | * 665 | * 检索引擎 666 | * 667 | * @author gulihua 668 | */ 669 | 670 | @Test 671 | public void enginesRetrieve() throws ApiException 672 | { 673 | EnginesDataRes res = service.enginesRetrieve("text-davinci-003"); 674 | System.out.println(JSONObject.toJSONString(res)); 675 | } 676 | 677 | 678 | /** 679 | * 680 | * 账户信息查询:里面包含总金额等信息 681 | * 682 | * @author gulihua 683 | */ 684 | 685 | @Test 686 | public void subscription() throws ApiException 687 | { 688 | Subscription res = service.subscription(); 689 | System.out.println(JSONObject.toJSONString(res)); 690 | } 691 | 692 | 693 | /** 694 | * 695 | * 账户调用接口消耗金额信息查询, 最多查询100天 696 | * 697 | * @author gulihua 698 | */ 699 | 700 | @Test 701 | public void billingUsage() throws ApiException 702 | { 703 | Date startDate = DateUtil.parse("2023-03-01"); 704 | Date endDate = DateUtil.parse("2023-05-11"); 705 | BillingUsage res = service.billingUsage(startDate, endDate); 706 | System.out.println(JSONObject.toJSONString(res)); 707 | } 708 | 709 | 710 | /** 711 | * 712 | * 快速创建会话 713 | * 714 | * @author gulihua 715 | */ 716 | @Test 717 | public void fastCompletionAsk() throws ApiException 718 | { 719 | System.out.println(FastCompletion.ask(apiKey, "介绍一下《三国演义》这本书")); 720 | } 721 | 722 | 723 | /** 724 | * 725 | * 快速创建聊天 726 | * 727 | * @author gulihua 728 | */ 729 | @Test 730 | public void fastCompletionChat() throws ApiException 731 | { 732 | System.out.println(FastCompletion.chat(apiKey, "介绍一下《三国演义》这本书")); 733 | } 734 | 735 | 736 | /** 737 | * 738 | * 快速生成图像 739 | * 740 | * @author gulihua 741 | */ 742 | @Test 743 | public void fastCompletionAsk4Image() throws ApiException 744 | { 745 | System.out.println(FastCompletion.ask4Image(apiKey, "猫")); 746 | } 747 | } 748 | --------------------------------------------------------------------------------