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.mzph.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…

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协议可以帮助测试人员理解接口的…

【多线程】CAS详解

目录 &#x1f334;什么是 CAS&#x1f338;CAS 伪代码 &#x1f38d;CAS 是怎么实现的&#x1f340;CAS 有哪些应⽤&#x1f338;实现原子类&#x1f338;实现自旋锁 &#x1f333;CAS 的 ABA 问题&#x1f338;**什么是 ABA 问题**&#xff1f;&#x1f338;ABA 问题引来的 B…

智慧城市建设的新里程碑:公共服务电子支付大屏

随着科技的飞速发展&#xff0c;我们的生活正在经历前所未有的变革。电子支付的出现&#xff0c;无疑是这场变革中的一大亮点&#xff0c;它不仅改变了我们日常的支付方式&#xff0c;更成为智慧城市建设的重要一环&#xff0c;为公众提供了更加便捷、高效的服务体验。 在以前&…

政府采购标书制作的要点解析

导语&#xff1a;政府采购是政府为满足公共利益&#xff0c;按照法定程序和标准&#xff0c;通过招标、竞争性谈判等方式&#xff0c;购买商品、工程和服务的行为。标书作为政府采购活动中的重要文件&#xff0c;其制作质量直接影响到项目的顺利进行。本文将围绕政府采购标书制…

二路归并排序的算法设计和复杂度分析and周记

数据结构实验报告 实验目的: 通过本次实验&#xff0c;了解算法复杂度的分析方法&#xff0c;掌握递归算法时间复杂度的递推计算过程。 实验内容&#xff1a; 二路归并排序的算法设计和复杂度分析 实验过程&#xff1a; 1.算法设计 第一步&#xff0c;首先要将数组进行…

【网站项目】314学生二手书籍交易平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

JVM相关面试题(2024大厂高频面试题系列)

一、JVM的组成 1、JVM由哪些部分组成&#xff0c;运行流程是什么&#xff1f; 回答&#xff1a;在JVM中共有四大部分&#xff0c;分别是Class Loader&#xff08;类加载器&#xff09;、Runtime Data Area&#xff08;运行时数据区&#xff0c;内存分区&#xff09;、Execut…

MyBatis的补充用法

说明&#xff1a;之前介绍过MyBatis的用法&#xff0c;像 用注解和Mapper.xml操作数据库、在Mapper.xml里写动态SQL。最近在一次用MyBatis批量更新数据库对象的场景中&#xff0c;意识到对MyBatis的一些标签用法不太熟悉&#xff0c;所以去 MyBatis官网 看了一些文档&#xff0…

php httpfs链接hdfs

一.代码&#xff08;有bug&#xff09; GitHub - michaelbutler/php-WebHDFS: A PHP client for WebHDFS 二.调用代码 1.代码1.代码 require_once(../webhdfs/src/org/apache/hadoop/WebHDFS.php);require_once(../webhdfs/src/org/apache/hadoop/tools/Curl.php); require_o…

什么是人才储备?如何做人才储备?

很多小伙伴都会有企业面试被拒的情况&#xff0c;然后HR会告诉你&#xff0c;虽然没有录用你&#xff0c;但是你进入了他们的人才储备库&#xff0c;那么这个储备库有什么作用和特点呢&#xff1f;我们如何应用人才测评系统完善人才储备库呢&#xff1f; 人才储备一般有以下三…

Python打发无聊时光:12.用PyQt实现简易的心电起搏器界面

第一步&#xff1a;装PyQt库 pip install PyQt5 第二步&#xff1a;复制代码 import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton, QVBoxLayout,QWidget, QLabel, QProgressBar, QSlider, QLineEdit, QHBoxLayout) from PyQt5.QtCore import …

软件分层(数据结构/软件逻辑上分层+举例),相连节点的概念+如何相连,为什么是层状结构(软件分层,网络协议分层+梳理协议顺序),协议分层(打电话例子)

目录 软件分层 介绍 举例 类的继承 虚拟文件系统 线程接口封装 虚拟地址空间 总结 为什么是层状的 软件分层 网络协议 原因 梳理协议顺序 相连节点 协议分层 引入 示例 实际上 逻辑上 制定出协议 软件分层 介绍 通过将软件系统划分为不同的层次,每一层都有…