java調用chatgpt接口,實現專屬于自己的人工智能助手

文章目錄

  • 前言
  • 導包
  • 基本說明
    • 請求參數
    • 響應參數
    • 創建請求和響應的VO類
  • 代碼編寫
  • 使用
  • 最后說明

前言

今天突然突發奇想,就想要用java來調用chatget的接口,實現自己的聊天機器人,但是網上找文章,屬實是少的可憐(可能是不讓發吧)。找到了一些文章,但是基本都是通過調用別人的庫來完成的,導入其他的jar還有不低的學習成本,于是就自己使用HttpClient5寫了一個,在這里講解一下思路。

導包

對于http調用,我使用的是比較流行的httpclient5,然后直接創建了一個springboot項目,方便以后對外提供接口。

    <parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.5.3</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 --><dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.2.1</version></dependency></dependencies>

基本說明

在編寫代碼之前,這個先給出HttpClient的Api文檔 api文檔

在這里插入圖片描述

我們在編寫代碼之前需要了解官方提供的接口如何進行訪問以及返回的結果是什么

請求參數

官方文檔地址為 文檔,請求參數必須填寫的內容如下

{"model": "gpt-3.5-turbo","messages": [{"role": "user", "content": "Hello!"}]
}

一個是model,一個是messages。model根據自己的情況來選擇,聊天的話就是gpt-3.5-turbo,下面的messages里面包含n個對象,每個對象有role和content,role表示角色,content表示內容。
下面為官方文檔中的解釋

在這里插入圖片描述

簡單理解就是我們要問問題,role就是user。如果要實現連續對話,那么就將返回的返回內容設置到messages中,role設置為返回的role。

響應參數

下面直接給出響應的內容

{'id': 'chatcmpl-6p9XYPYSTTRi0xEviKjjilqrWU2Ve','object': 'chat.completion','created': 1677649420,'model': 'gpt-3.5-turbo','usage': {'prompt_tokens': 56, 'completion_tokens': 31, 'total_tokens': 87},'choices': [{'message': {'role': 'assistant','content': 'The 2020 World Series was played in Arlington, Texas at the Globe Life Field, which was the new home stadium for the Texas Rangers.'},'finish_reason': 'stop','index': 0}]
}

我們問問題的答案就在choices.message下的content中,而role就代表了chatGpt扮演的角色。看到這我們就應該知道該干嘛了吧肯定是創建對應的VO類啊。

創建請求和響應的VO類

下面5個類就對應了我們發送和接收的各種信息

ChatGptMessage類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatGptMessage {String role;String content;
}

ChatGptRequestParameter 類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatGptRequestParameter {String model = "gpt-3.5-turbo";List<ChatGptMessage> messages = new ArrayList<>();public void addMessages(ChatGptMessage message) {this.messages.add(message);}}

ChatGptResponseParameter 類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatGptResponseParameter {String id;String object;String created;String model;Usage usage;List<Choices> choices;
}

Choices 類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Choices {ChatGptMessage message;String finish_reason;Integer index;
}

Usage 類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Usage {String prompt_tokens;String completion_tokens;String total_tokens;
}

代碼編寫

不說廢話,首先創建一個CustomChatGpt類

public class CustomChatGpt {}

然后定義一些成員屬性

    /*** 自己chatGpt的ApiKey*/private String apiKey;/*** 使用的模型*/private String model = "gpt-3.5-turbo-0301";/*** 對應的請求接口*/private String url = "https://api.openai.com/v1/chat/completions";/*** 默認編碼*/private Charset charset = StandardCharsets.UTF_8;/*** 創建一個ChatGptRequestParameter,用于攜帶請求參數*/private ChatGptRequestParameter chatGptRequestParameter = new ChatGptRequestParameter();

提供一個ApiKey的構造器,創建該對象必須要傳入ApiKey

    public CustomChatGpt(String apiKey) {this.apiKey = apiKey;}

定義一個響應超時時間

    /*** 響應超時時間,毫秒*/private int responseTimeout = 10000;public void setResponseTimeout(int responseTimeout) {this.responseTimeout = responseTimeout;}

編寫一個getAnswer方法,要求傳入一個CloseableHttpClient和一個問題

    public String getAnswer(CloseableHttpClient client, String question) {}

繼續實現方法,下面會完成一些參數的創建和設置

        // 創建一個HttpPostHttpPost httpPost = new HttpPost(url);// 創建一個ObjectMapper,用于解析和創建jsonObjectMapper objectMapper = new ObjectMapper();// 設置請求參數chatGptRequestParameter.addMessages(new ChatGptMessage("user", question));HttpEntity httpEntity = null;try {// 對象轉換為json字符串httpEntity = new StringEntity(objectMapper.writeValueAsString(chatGptRequestParameter), charset);} catch (JsonProcessingException e) {System.out.println(question + "->json轉換異常");return null;}httpPost.setEntity(httpEntity);

下面會完成一些配置的設置

        // 設置請求頭httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");// 設置登錄憑證httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey);// 用于設置超時時間RequestConfig config = RequestConfig.custom().setResponseTimeout(responseTimeout, TimeUnit.MILLISECONDS).build();httpPost.setConfig(config);

下面代碼會提交請求,解析響應,最后返回對應問題的答案

        try {// 提交請求return client.execute(httpPost, response -> {// 得到返回的內容String resStr = EntityUtils.toString(response.getEntity(), charset);// 轉換為對象ChatGptResponseParameter responseParameter = objectMapper.readValue(resStr, ChatGptResponseParameter.class);String ans = "";// 遍歷所有的Choices(一般都只有一個)for (Choices choice : responseParameter.getChoices()) {ChatGptMessage message = choice.getMessage();chatGptRequestParameter.addMessages(new ChatGptMessage(message.getRole(), message.getContent()));String s = message.getContent().replaceAll("\n+", "\n");ans += s;}// 返回信息return ans;});} catch (IOException e) {e.printStackTrace();}// 發生異常,移除剛剛添加的ChatGptMessagechatGptRequestParameter.getMessages().remove(chatGptRequestParameter.getMessages().size()-1);return "您當前的網絡無法訪問";

下面給出這個類的完整代碼

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ttpfx.vo.ChatGptMessage;
import com.ttpfx.vo.ChatGptRequestParameter;
import com.ttpfx.vo.ChatGptResponseParameter;
import com.ttpfx.vo.Choices;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;/*** @author ttpfx* @date 2023/3/23*/
public class CustomChatGpt {/*** 自己chatGpt的ApiKey*/private String apiKey;/*** 使用的模型*/private String model = "gpt-3.5-turbo-0301";/*** 對應的請求接口*/private String url = "https://api.openai.com/v1/chat/completions";/*** 默認編碼*/private Charset charset = StandardCharsets.UTF_8;/*** 創建一個ChatGptRequestParameter,用于攜帶請求參數*/private ChatGptRequestParameter chatGptRequestParameter = new ChatGptRequestParameter();/*** 相應超時時間,毫秒*/private int responseTimeout = 1000;public void setResponseTimeout(int responseTimeout) {this.responseTimeout = responseTimeout;}public CustomChatGpt(String apiKey) {this.apiKey = apiKey;}public String getAnswer(CloseableHttpClient client, String question) {// 創建一個HttpPostHttpPost httpPost = new HttpPost(url);// 創建一個ObjectMapper,用于解析和創建jsonObjectMapper objectMapper = new ObjectMapper();// 設置請求參數chatGptRequestParameter.addMessages(new ChatGptMessage("user", question));HttpEntity httpEntity = null;try {// 對象轉換為json字符串httpEntity = new StringEntity(objectMapper.writeValueAsString(chatGptRequestParameter), charset);} catch (JsonProcessingException e) {System.out.println(question + "->json轉換異常");return null;}httpPost.setEntity(httpEntity);// 設置請求頭httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");// 設置登錄憑證httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey);// 用于設置超時時間RequestConfig config = RequestConfig.custom().setResponseTimeout(responseTimeout, TimeUnit.MILLISECONDS).build();httpPost.setConfig(config);try {// 提交請求return client.execute(httpPost, response -> {// 得到返回的內容String resStr = EntityUtils.toString(response.getEntity(), charset);// 轉換為對象ChatGptResponseParameter responseParameter = objectMapper.readValue(resStr, ChatGptResponseParameter.class);String ans = "";// 遍歷所有的Choices(一般都只有一個)for (Choices choice : responseParameter.getChoices()) {ChatGptMessage message = choice.getMessage();chatGptRequestParameter.addMessages(new ChatGptMessage(message.getRole(), message.getContent()));String s = message.getContent().replaceAll("\n+", "\n");ans += s;}// 返回信息return ans;});} catch (IOException e) {e.printStackTrace();}// 發生異常,移除剛剛添加的ChatGptMessagechatGptRequestParameter.getMessages().remove(chatGptRequestParameter.getMessages().size()-1);return "您當前的網絡無法訪問";}
}

使用

下面就是測試代碼,我們只需要傳入一個CloseableHttpClient 和 question 即可

public class Test {public static void main(String[] args) throws IOException {CloseableHttpClient httpClient = HttpClients.createDefault();String apiKey = "自己的ApiKey";CustomChatGpt customChatGpt = new CustomChatGpt(apiKey);// 根據自己的網絡設置吧customChatGpt.setResponseTimeout(20000);while (true) {System.out.print("\n請輸入問題(q退出):");String question = new Scanner(System.in).nextLine();if ("q".equals(question)) break;long start = System.currentTimeMillis();String answer = customChatGpt.getAnswer(httpClient, question);long end = System.currentTimeMillis();System.out.println("該回答花費時間為:" + (end - start) / 1000.0 + "秒");System.out.println(answer);}httpClient.close();}
}

下面為運行圖片

在這里插入圖片描述
在這里插入圖片描述

最后說明

對于ApiKey,只能說難者不會,會者不難,這個沒辦法教。

如果代碼無法運行,或者運行速度及其緩慢,請使用代理,在HttpClient里面可以很輕松的使用代理

        String proxyIp = "127.0.0.1";int proxyPort = 7890;HttpHost httpHost = new HttpHost(proxyIp, proxyPort);

上面就是一個示例,對于代理,這里也就無法繼續進行說明了。

如果我們完成了上面的功能,是不是就能夠對外提供接口,然后寫一個自己的網頁端的ChatGpt或者弄一個聊天機器人呢?當然沒問題啊


2023/3/27 23:27更新

很多人找我要這個小程序的demo,其實源代碼上面都已經給出了。既然有人問,那么就給出這個demo的github地址 git地址

使用指令 git clone https://github.com/c-ttpfx/chatGPT.git 可以輕松的下載到本地


2023/3/31 19:54更新
上面這個代碼大家應該發現了問題,就是返回很慢,原因就是我們請求不是異步的,是等待所有答案都給出了再返回,所以速度很慢,并且容易出現超時。

解決方法就是使用異步請求,大家請參照 使用chatgpt實現微信聊天小程序(秒回復),github開源(附帶鏈接) ,基本可以實現秒回復

2023/3/31 14:40更新
最新的代碼已經支持代理,參考使用chatgpt實現微信聊天小程序(秒回復),github開源(附帶鏈接)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713832.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713832.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713832.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ESP32 web 對接華為云平臺--MQTT協議

文章目錄 前言一、MQTT協議二、如何使用MQTT協議對接華為云1.注冊華為云賬號2.設備接入中創建資源空間3.如何連接4.通過MQTT.fx工具做初步對接4.1 設置連接信息4.2 連接平臺 5.查看平臺設備信息 三. 設備測對接平臺1.ESP測引入MQTT庫2.編碼2.1前端編碼修改2.2 后端接口修改 3.M…

element-plus+vue3表單含圖片(可預覽)(線上圖片)

一、要實現的效果&#xff1a; 二、如果期間出現這樣的效果&#xff08;表格穿透過來了&#xff09;&#xff0c;加上了這行代碼就可以了&#xff1a; preview-teleported“true” 如果僅測試用&#xff0c;建議使用線上圖片鏈接的形式&#xff0c;免得本地地址不生效&#xf…

SSH 的兩種認證方式

SSH&#xff08;Secure Shell&#xff09;提供了幾種不同的認證方式&#xff0c;其中兩種最常見的方式是密碼認證和密鑰認證。以下是它們的詳細介紹&#xff1a; 密碼認證&#xff1a; 原理&#xff1a;用戶在連接時輸入用戶名和密碼&#xff0c;然后將密碼傳輸到遠程服務器進行…

數學實驗-Matlab使用(1)

使用方法以及筆記均在文件中 class1_func1.m function f class1_func1(x) % f為輸出&#xff0c;輸出有多個時需要用中括號以矩陣的方式包起來 % x為輸入f sin(x)class1_func2.m function [a,b,u,v] class1_func2(x,y)[a,b] eig(x)[u,v] eig(y)class1.m % 當語句后有…

yolov9從頭開始訓練

yolov9從頭開始訓練 一、準備數據集 數據集相關文件存放布局如下 yolov9-datasets ├── train │ ├── images │ │ ├── image.jpg │ │ ├── │ └── labels │ ├── image.txt │ ├── ├── valid │ ├── images │ │ ├── image.jpg │ │ ├─…

吳恩達deeplearning.ai:模型選擇交叉驗證測試集的訓練方法

以下內容有任何不理解可以翻看我之前的博客哦&#xff1a;吳恩達deeplearning.ai專欄 在上一節中&#xff0c;我們了解了如何利用測試集來評估模型性能。今天我們來進一步完善這個想法&#xff0c;讓你使用該技術自動選擇一個更好的模型。 文章目錄 模型選擇交叉驗證 Cross Va…

SpringBoot 框架(上)

SpringBoot SpringBoot概述依賴管理自動配置SpringBoot 注解使用ConfigurationImport(value {Cat.class,Dog.class})ImportResource(locations "classpath:beans.xml") yaml 標記語言概述基本語法數據類型字面量對象數組 使用細節 Rest 風格請求處理概述注意事項 接…

vue2 開發記錄

el-select 如何修改選擇項的樣式/el-select-dropdown__item 文字上下顯示 測試代碼 <div stylemargin-left: 100px><!-- 測試代碼--><el-select filterablesizemini><div classxxx-el-select><el-optionv-foritem in [{key:1,des:2,…

AVT Prosilica GC Vision Cameras 相機視覺說明使用安裝。具體詳情內容可參看PDF目錄內容。

AVT Prosilica GC Vision Cameras 相機視覺說明使用安裝。具體詳情內容可參看PDF目錄內容。

TikTok矩陣系統功能怎么寫?常用源代碼是什么?

TikTok矩陣系統的功能是如何編寫的?又有哪些常用的源代碼支撐這些功能呢?本文將通過五段源代碼的分享&#xff0c;為大家揭開TikTok矩陣系統的神秘面紗。 一、TikTok矩陣系統的核心功能 TikTok的矩陣系統涵蓋了多個核心功能&#xff0c;包括但不限于用戶管理、內容分發、推…

【接口測試】HTTP協議介紹

目錄 介紹 HTTP狀態碼 HTTP報文 請求方法 HTTP版本 HTTP標頭 通用標頭 請求標頭 響應標頭 get 編碼 post 編碼 RESTful風格 HTTPS 絕大多數的Web服務接口都是基于HTTP協議進行通信的&#xff0c;包括RESTful API和SOAP等。了解HTTP協議可以幫助測試人員理解接口的…

回溯算法題單???

力扣&#xff1a; 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 216. 組合總和 III - 力扣&#xff08;LeetCode&#xff09; LCR 080. 組合 - 力扣&#xff08;LeetCode&#xff09; LCR 082. 組合總和 II - 力扣&#xff08;LeetCode&#xff09; LCR 083. 全排列…

【多線程】CAS詳解

目錄 &#x1f334;什么是 CAS&#x1f338;CAS 偽代碼 &#x1f38d;CAS 是怎么實現的&#x1f340;CAS 有哪些應?&#x1f338;實現原子類&#x1f338;實現自旋鎖 &#x1f333;CAS 的 ABA 問題&#x1f338;**什么是 ABA 問題**&#xff1f;&#x1f338;ABA 問題引來的 B…

【C++】核心編程--函數高級

文章目錄 1. 函數的默認參數2. 函數占位參數3. 函數重載4. 注意事項 1. 函數的默認參數 在C中&#xff0c;函數的形參列表中的形參是可以有默認值的 //語法&#xff1a; 返回值類型 函數名 (參數 默認值){} #include<iostream> using namespace std; //函數默認參數 //如…

異常值檢測-3σ法提交 代碼注釋

背景信息里面都給了相應的答案&#xff0c;但我們可以多了解一下代碼的含義&#xff0c;而不是簡單的復制粘貼 import pandas as pd import matplotlib.pyplot as plt from scipy import stats import numpy as npdata pd.read_csv("src/death.csv", index_colUnna…

ASPICE實操中的那點事兒-如何避免重復性測試

寫在前面 ASPICE理解起來容易&#xff0c;畢竟是有條有理的。但實操起來&#xff0c;尤其是把ASPICE各過程域做全的時候&#xff0c;會遇到各種各樣的問題&#xff08;不是技術問題有多難&#xff0c;而是該如何做選擇&#xff0c;如何既能符合ASPICE要求&#xff0c;保證過程質…

智慧城市建設的新里程碑:公共服務電子支付大屏

隨著科技的飛速發展&#xff0c;我們的生活正在經歷前所未有的變革。電子支付的出現&#xff0c;無疑是這場變革中的一大亮點&#xff0c;它不僅改變了我們日常的支付方式&#xff0c;更成為智慧城市建設的重要一環&#xff0c;為公眾提供了更加便捷、高效的服務體驗。 在以前&…

python SHP2COCO

1. 將shp的標簽數據轉成coco # -*- coding: utf-8 -*- import os, json import cv2 from osgeo import gdal import numpy as np from osgeo import ogr, gdal, osr from shapely.geometry import box, shape from shapely.geometry.polygon import Polygon import collection…

Flutter 的狀態管理

狀態提升&#xff08;Lifting-state-up&#xff09; 把子組件的狀態&#xff0c;提升到上級組件中&#xff0c;從而實現在多個組件之間共享和同步數據的效果 以 flutter counter demo&#xff0c;那個按按鈕1 的來說&#xff0c;現在的 count 是幾&#xff0c;不是存在頁面顯…

政府采購標書制作的要點解析

導語&#xff1a;政府采購是政府為滿足公共利益&#xff0c;按照法定程序和標準&#xff0c;通過招標、競爭性談判等方式&#xff0c;購買商品、工程和服務的行為。標書作為政府采購活動中的重要文件&#xff0c;其制作質量直接影響到項目的順利進行。本文將圍繞政府采購標書制…