AIGC: 关于ChatGPT中基于API实现一个客户端Client

Java版的GPT的Client

  • 可作为其他编程语言的参考
  • 注意: 下面包名中的 xxx 可以换成自己的

1 )核心代码结构设计

  • src
    • main
      • java
        • com.xxx.gpt.client
          • entity
            • ChatCompletion.java
            • ChatCompletionResponse.java
            • ChatChoice.java
          • util
            • Proxys.java
          • ChatApi.java
          • ChatGPTClient.java
    • test
      • java
        • com.xxx.gpt.client.test
          • ChatGPTClientTest.java
  • pom.xml

2 ) pom 文件

  • 在 pom 文件里面,我们引入了我们需要引用的依赖
    • 对于 OpenAI 的API访问,由于它是一个HTTP的接口
    • 我们使用的是 okhttp-see
    • 然后通过 retrofit 进行一个封装
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>gpt-client</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>compile</scope><optional>true</optional></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.3.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.3.7</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.2</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.19</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.33</version></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp-sse</artifactId><version>3.14.9</version></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>logging-interceptor</artifactId><version>3.14.9</version></dependency><dependency><groupId>com.squareup.retrofit2</groupId><artifactId>retrofit</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.squareup.retrofit2</groupId><artifactId>converter-jackson</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.squareup.retrofit2</groupId><artifactId>adapter-rxjava2</artifactId><version>2.9.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>com.knuddels</groupId><artifactId>jtokkit</artifactId><version>0.4.0</version></dependency></dependencies>
</project>

3 )entity 目录

  • 在这个包里面,开发了核心的chat completion相关接口
    • 比如对于我们的ChatCompletion请求的一些参数
      • 包括 model,包括需要传入的message和temperature以及top_p, functioncall等等的这些参数
    • 然后对于它的返回值: ChatCompletionResponse 程序里面
      • 包括 id, object, created, model, choice, usage
    • 对于ChatChoice, 里面包含 delta, message 和 finishReason
  • 这几个类和我们前面去访问 OpenAI 它的API文档里面所对应的相关的属性是一致的
    • 这部分照着 API 手册去进行一下相关实体类的开发就可以了

ChatCompletion.java

package com.xxx.gpt.client.entity;import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.xxx.gpt.client.util.TokensUtil;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;import java.io.Serializable;
import java.util.List;
import java.util.Map;@Data
@Builder
@Slf4j
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChatCompletion implements Serializable {@NonNull@Builder.Defaultprivate String model = Model.GPT_3_5_TURBO_0613.getName();@NonNullprivate List<Message> messages;/*** 使用什么取样温度,0到2之间。越高越奔放。越低越保守。* <p>* 不要同时改这个和topP*/@Builder.Defaultprivate double temperature = 0.9;/*** 0-1* 建议0.9* 不要同时改这个和temperature*/@JsonProperty("top_p")@Builder.Defaultprivate double topP = 0.9;/*** auto*/String function_call;List<ChatFunction> functions;/*** 结果数。*/@Builder.Defaultprivate Integer n = 1;/*** 是否流式输出.* default:false*/@Builder.Defaultprivate boolean stream = false;/*** 停用词*/private List<String> stop;/*** 3.5 最大支持4096* 4.0 最大32k*/@JsonProperty("max_tokens")private Integer maxTokens;@JsonProperty("presence_penalty")private double presencePenalty;/*** -2.0 ~~ 2.0*/@JsonProperty("frequency_penalty")private double frequencyPenalty;@JsonProperty("logit_bias")private Map logitBias;/*** 用户唯一值,确保接口不被重复调用*/private String user;public int countTokens() {return TokensUtil.tokens(this.model, this.messages);}
}

ChatCompletionResponse.java

package com.xxx.gpt.client.entity;import lombok.Data;
import java.io.Serializable;
import java.util.List;@Data
public class ChatCompletionResponse implements Serializable {private String id;private String object;private long created;private String model;private List<ChatChoice> choices;private Usage usage;
}

ChatChoice.java

package com.xxx.gpt.client.entity;import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;import java.io.Serializable;@Data
public class ChatChoice implements Serializable {private long index;/*** 请求参数stream为true返回是delta*/@JsonProperty("delta")private Message delta;@JsonProperty("message")private Message message;@JsonProperty("finish_reason")private String finishReason;
}

3 )util 目录

  • 由于国内的网络没办法直接的去进行访问, 我们添加一个 util/Proxys.java, 基于它去做一个代理
    • 里面我们提供两个方法,都是传入我们代理的IP和代理的端口
    • 然后返回 Proxy的Type是HTTP,这是对于HTTP的 Proxy
    • 再来创建一个socks的 Proxy

Proxys.java

package com.xxx.gpt.client.util;import java.net.InetSocketAddress;
import java.net.Proxy;public class Proxys {public static Proxy http(String ip, int port) {return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip, port));}public static Proxy socks5(String ip, int port) {return new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(ip, port));}
}

4 )创建 ChatApi 接口

  • 在ChatAPI里面,我们就添加我们需要去访问的 Open AI 的接口
  • 接口是post请求,接口的URI是 v1/chat/completions
  • 返回值是我们刚刚创建的实体类 ChatCompletionResponse,参数是 ChatCompleination
  • 这是我们要访问的chatAPI它的核心的接口

ChatApi.java

package com.xxx.gpt.client;import com.xxx.gpt.client.entity.ChatCompletion;
import com.xxx.gpt.client.entity.ChatCompletionResponse;
import io.reactivex.Single;
import retrofit2.http.Body;
import retrofit2.http.POST;public interface ChatApi {String CHAT_GPT_API_HOST = "https://api.openai.com/";@POST("v1/chat/completions")Single<ChatCompletionResponse> chatCompletion(@Body ChatCompletion chatCompletion);
}

5 )添加 ChatGPTClient

  • 在这个类里面定义一些属性: apiKey, apiHost, chatApi, okHttpClient, timeout, proxy

  • 再来添加一个init方法

    • 在拦截器里添加apikey
    • 设置timeout,默认300s
    • 设置代理
    • 通过 retrofit 实例化chatapi,供我们去进行使用
  • 这样就完成了一个ChatGPTClient的一个实例化

  • 实例化完成之后呢,我们添加一个调用的方法 chatCompletion,返回值就是我们请求的response

  • 现在已经完成了java版本的ChatGPT的client

ChatGPTClient.java

package com.xxx.gpt.client;import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import com.alibaba.fastjson.JSON;
import com.xxx.gpt.client.entity.BaseResponse;
import com.xxx.gpt.client.entity.ChatCompletion;
import com.xxx.gpt.client.entity.ChatCompletionResponse;
import com.xxx.gpt.client.entity.Message;
import io.reactivex.Single;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;import java.net.Proxy;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;@Slf4j
@Getter
@Setter
@Builder
public class ChatGPTClient {private String apiKey;private List<String> apiKeyList;@Builder.Defaultprivate String apiHost = ChatApi.CHAT_GPT_API_HOST;private ChatApi apiClient;private OkHttpClient okHttpClient;/*** 超时 默认300*/@Builder.Defaultprivate long timeout = 300;/*** okhttp 代理*/@Builder.Defaultprivate Proxy proxy = Proxy.NO_PROXY;public ChatGPTClient init() {OkHttpClient.Builder client = new OkHttpClient.Builder();client.addInterceptor(chain -> {Request original = chain.request();String key = apiKey;if (apiKeyList != null && !apiKeyList.isEmpty()) {key = RandomUtil.randomEle(apiKeyList);}Request request = original.newBuilder().header(Header.AUTHORIZATION.getValue(), "Bearer " + key).header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue()).method(original.method(), original.body()).build();return chain.proceed(request);}).addInterceptor(chain -> {Request original = chain.request();Response response = chain.proceed(original);if (!response.isSuccessful()) {String errorMsg = response.body().string();log.error("请求异常:{}", errorMsg);BaseResponse baseResponse = JSON.parseObject(errorMsg, BaseResponse.class);if (Objects.nonNull(baseResponse.getError())) {log.error(baseResponse.getError().getMessage());throw new RuntimeException(baseResponse.getError().getMessage());}throw new RuntimeException(errorMsg);}return response;});client.connectTimeout(timeout, TimeUnit.SECONDS);client.writeTimeout(timeout, TimeUnit.SECONDS);client.readTimeout(timeout, TimeUnit.SECONDS);if (Objects.nonNull(proxy)) {client.proxy(proxy);}OkHttpClient httpClient = client.build();this.okHttpClient = httpClient;this.apiClient = new Retrofit.Builder().baseUrl(this.apiHost).client(okHttpClient).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).addConverterFactory(JacksonConverterFactory.create()).build().create(ChatApi.class);return this;}public ChatCompletionResponse chatCompletion(ChatCompletion chatCompletion) {Single<ChatCompletionResponse> chatCompletionResponse =this.apiClient.chatCompletion(chatCompletion);return chatCompletionResponse.blockingGet();}public String chat(String message) {ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(Message.of(message))).build();ChatCompletionResponse response = this.chatCompletion(chatCompletion);return response.getChoices().get(0).getMessage().getContent();}
}

6 )添加测试类

  • 需要先对我们的client去进行实例化
  • 首先添加一下代理
  • 再来添加一个测试的方法

ChatGPTClientTest.java

package com.xxx.gpt.client.test;import com.xxx.gpt.client.ChatGPTClient;
import com.xxx.gpt.client.entity.ChatCompletion;
import com.xxx.gpt.client.entity.ChatCompletionResponse;
import com.xxx.gpt.client.entity.Message;
import com.xxx.gpt.client.entity.Model;
import com.xxx.gpt.client.util.Proxys;
import org.junit.Before;
import org.junit.Test;import java.net.Proxy;
import java.util.Arrays;public class ChatGPTClientTest {private ChatGPTClient chatGPTClient;@Beforepublic void before() {Proxy proxy = Proxys.socks5("127.0.0.1", 7890);chatGPTClient = ChatGPTClient.builder().apiKey("sk-6kchn0DjDasdsdfdqOJqkc3aIso5ct").timeout(900).proxy(proxy).apiHost("https://api.openai.com/").build().init();}@Testpublic void chat() {Message system = Message.ofSystem("你是一个作家,学习过很多古诗");Message message = Message.of("写一首关于青春的七言绝句");ChatCompletion chatCompletion = ChatCompletion.builder().model(Model.GPT_3_5_TURBO.getName()).messages(Arrays.asList(system, message)).maxTokens(3000).temperature(0.9).build();ChatCompletionResponse response = chatGPTClient.chatCompletion(chatCompletion);Message res = response.getChoices().get(0).getMessage();System.out.println(res.getContent());}// @Testpublic void tokens() {Message system = Message.ofSystem("你是一个作家,学习过很多古诗");Message message = Message.of("写一首关于青春的七言绝句");ChatCompletion chatCompletion1 = ChatCompletion.builder().model(Model.GPT_3_5_TURBO.getName()).messages(Arrays.asList(system, message)).maxTokens(3000).temperature(0.9).build();ChatCompletion chatCompletion2 = ChatCompletion.builder().model(Model.TEXT_DAVINCI_003.getName()).messages(Arrays.asList(system, message)).maxTokens(3000).temperature(0.9).build();System.out.println(chatCompletion1.countTokens());System.out.println(chatCompletion2.countTokens());}
}
  • 根据前面我们看到的API的文档,构建 Prompt(message)
  • 我们构造一个system角色的一个message
    • 告诉GPT: 你是一个作家, 写过很多诗,然后默认我们再以用户的角色去实例化一个message
    • 让GPT帮我们去写一首关于青春的七言绝句
  • 接下来构造我们的request参数
    • 设置 model,message,maxTokens,temperature
    • 之后执行 build()
  • 这里完成了让GPT根据 Prompt 创作了一首诗歌
  • 以上是 Java 版本的GPT相关核心代码(网上搜集)
  • 可以作为转换成其他编程语言实现的参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++的lambda语法

仿函数的最大缺点是&#xff1a; 如果命名不合规范并且没有给出注释&#xff0c;直接阅读难以理解&#xff08;排序的调用过程中&#xff0c;不查看仿函数细节&#xff0c;则很难直接得知是升序排序还是降序排序&#xff09;每次实现仿函数都需自己构建一个类 因此C从其他语言…

分类详情 API 返回值说明

为了进行此平台API的调用&#xff0c;首先我们需要做下面几件事情。 1、 获取一个KEY&#xff0c;点击获取测试key和secret 2、 参考API文档里的接入方式和示例。 3、查看测试工具是否有需要的接口&#xff0c;响应实例的返回字段是否符合参数要求。 4、利用平台的文档中心…

[前 5 名] 最顶级的数据恢复软件解决方案列表

您是否在互联网上找到适用于 Windows PC 的前 5 名最受好评的数据恢复软件解决方案&#xff1f;嗯&#xff0c;在线市场上有很多工具可以恢复已删除的文件。但并不是所有的应用程序都值得使用它。值得信赖的文件恢复工具将有助于快速检索丢失、删除、格式化的数据并从计算机恢复…

JVM之基本概念(一)

(1) 基本概念&#xff1a; JVM 是可运行 Java 代码的假想计算机 &#xff0c;包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收&#xff0c;堆 和 一个存储方法域。JVM 是运行在操作系统之上的&#xff0c;它与硬件没有直接的交互。 (2) 运行过程&#xff1a; 我们都…

[传智杯 #4 决赛] 小智的疑惑

题目描述 传智专修学院给了小智一个仅包含小写字母的字符串 s&#xff0c;他想知道&#xff0c;里面出现了多少次子串 chuanzhi 呢。 我们称一个字符串 t 是 s 的子串&#xff0c;当且仅当将 s 的开头若干个&#xff08;可以为 0 个&#xff09;连续字符和结尾若干个&#xf…

讲一下mysql的锁

MySQL 中的锁机制是数据库管理系统用于控制并发访问的重要组成部分。锁是一种资源访问的机制&#xff0c;通过它可以确保在同一时间只有一个事务能够对资源进行操作&#xff0c;从而维护数据的一致性和完整性。在 MySQL 中&#xff0c;锁主要分为共享锁&#xff08;Shared Lock…

听GPT 讲Rust源代码--src/tools(7)

File: rust/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs 在Rust源代码中&#xff0c;rust-analyzer/crates/ide/src/inlay_hints/chaining.rs这个文件的作用是生成Rust代码中的链式调用提示。 具体来说&#xff0c;当我们使用链式调用时&#xff0c;例如A…

Python练习题(三)

&#x1f4d1;前言 本文主要是【Python】——Python练习题的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&am…

51单片机PWM讲解

前言 51单片机我已经很久没用过了&#xff0c;毕竟是十年前的产物了&#xff0c;但是由于工作室的学弟学妹需要学习&#xff0c;加之马上就要举行循迹小车比赛&#xff0c;很多人反映看不懂PWM&#xff0c;或者看了不会用&#xff0c;于是写一篇文章简单介绍一下。 PWM普遍应…

Kubernetes学习笔记-Part.08 安装k8s环境

目录 Part.01 Kubernets与docker Part.02 Docker版本 Part.03 Kubernetes原理 Part.04 资源规划 Part.05 基础环境准备 Part.06 Docker安装 Part.07 Harbor搭建 Part.08 K8s环境安装 Part.09 K8s集群构建 Part.10 容器回退 第八章 K8s环境安装 8.1.准备安装文件 在外网服务器…

IDEA如何配置Git 遇到问题的解决

新建项目 点击 会变红 会生成.git隐藏文件 配置远程仓库路径&#xff1a;点击Manage Remotes&#xff1a;将远程仓库的链接放到这里&#xff1a; 得到如下样式&#xff1a; 此时提交到本地仓库 点击add&#xff0c;添加到暂存文件&#xff1a; 此时文件变绿&#xf…

【Ratis】Grpc.proto文件里定义的一些RPC

一、 总览 Raft的提供了三种类型的RPC。分别如下&#xff1a; RaftClientProtocolService&#xff1a;client与server之间的交互RPC&#xff0c;分为ordered和unordered&#xff0c;一种是有序的异步请求流、一种是无序的异步请求流。RaftServerProtocolService&#xff1a;r…

JDK中lock锁的机制,其底层是一种无锁的架构实现的,公平锁和非公平锁

简述JDK中lock锁的机制&#xff0c;其底层是一种无锁的架构实现的&#xff0c;是否知道其是如何实现的 synchronized与lock lock是一个接口&#xff0c;而synchronized是在JVM层面实现的。synchronized释放锁有两种方式&#xff1a; 获取锁的线程执行完同步代码&#xff0c;…

Elasticsearch一些函数查询

1. 根据价格分组统计数量&#xff0c;每组区间为2000&#xff0c; filter_pathaggregations 设置查询结果只展示函数结果 也有date_histogram函数根据日期分组等等 GET order/_search?filter_pathaggregations {"aggs": {"hist_price": {"histogr…

神经网络 代价函数

神经网络 代价函数 首先引入一些便于稍后讨论的新标记方法&#xff1a; 假设神经网络的训练样本有 m m m个&#xff0c;每个包含一组输入 x x x和一组输出信号 y y y&#xff0c; L L L表示神经网络层数&#xff0c; S I S_I SI​表示每层的neuron个数( S l S_l Sl​表示输出…

使用idea如何快速的搭建ssm的开发环境

文章目录 唠嗑部分言归正传1、打开idea&#xff0c;点击新建项目2、填写信息3、找到pom.xml先添加springboot父依赖4、添加其他依赖5、编写启动类、配置文件6、连接创建数据库、创建案例表7、安装MybatisX插件8、逆向工程9、编写controller10、启动项目、测试 结语 唠嗑部分 小…

MIT线性代数笔记-第21讲-特征值,特征向量

目录 21.特征值&#xff0c;特征向量打赏 21.特征值&#xff0c;特征向量 对于一个方阵 A A A&#xff0c;若 A x ⃗ λ x ⃗ A \vec{x} \lambda \vec{x} Ax λx &#xff0c;即 A x ⃗ A \vec{x} Ax 平行于 x ⃗ \vec{x} x &#xff0c;那么 λ \lambda λ是 A A A的特征值…

怎么防止死锁

目录 一、死锁的概念 1、互斥条件 2、 占有和等待条件 3、非抢占条件&#xff08;No Preemption&#xff09;&#xff1a; 4、环路等待条件&#xff08;Circular Wait&#xff09;&#xff1a; 二、防止死锁 死锁预防&#xff08;Deadlock Prevention&#xff09;&#xf…

内网穿透工具获取一个公网ip

下载地址&#xff1a;点击即可下载很简单 然后将他复制到上面的命令行窗口直接回车

LeetCode1423. Maximum Points You Can Obtain from Cards

文章目录 一、题目二、题解 一、题目 There are several cards arranged in a row, and each card has an associated number of points. The points are given in the integer array cardPoints. In one step, you can take one card from the beginning or from the end of…