前置条件:
看下API2D官网,第三方API2D服务对接流程:
其对接文档地址
https://api2d.com/wiki/doc
一:创建一个空的Maven项目
完成后整的项目层级图如下
1.pom.xml 中添加相关依赖包
<?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>
<artifactId>jinyi-chatgpt-api2d-starter</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<jinyi-up.version>1.0.0</jinyi-up.version>
<lombok.version>1.18.22</lombok.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<fastjson.version>2.0.22</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<!--不设置optional或者optional是false,表示传递依赖. 此处表示两个项目之间依赖不传递-->
<optional>true</optional>
<version>2.6.11</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
</project>
2.项目中涉及到的类
package com.jinyi.up.chatgpt.api2d.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "dbj.chatgpt.api2d")
public class ChatGptApi2dConfig {
private String host;
private String forwardKey;
}
package com.jinyi.up.chatgpt.api2d.constants;
import lombok.Getter;
/**
* api2d常量
*
* @author zhiquan
*/
@Getter
public class Api2dConstant {
/**
* 正式接口,分布式部署
*/
public static final String API2D_HOST_OFFICIAL = "https://openai.api2d.net";
/**
* 备用接口,如果上一个无法使用(比如因为域名包含 openai 被屏蔽)可以使用这个
*/
public static final String API2D_HOST_STANDBY = "https://oa.api2d.net";
/**
* 临时域名,如果前两个都无法访问可以尝试这两个(过期时间 2024-06-15)
*/
public static final String API2D_HOST_TEMPORARY_1 = "https://oa.api2d.site";
public static final String API2D_HOST_TEMPORARY_2 = "https://oa.api2d.online";
/**
* 备用接口,如果前两个都无法使用,可以使用这个
*/
public static final String API2D_HOST_BACKUP_1 = "https://stream.api2d.net";
/**
* 请求拼接模板
*/
public static final String reqUrlTemplate = "%s%s";
/**
* OpenAI 聊天接口( /v1/chat/completions )
*/
public static final String CHAT_COMPLETIONS_URL = "/v1/chat/completions";
/**
* OpenAI 内容补全接口( /v1/completions )
*/
public static final String COMPLETIONS_URL = "/v1/completions";
/**
* OpenAI 文本编辑接口( /v1/edits )
*/
public static final String EDITS_URL = "/v1/edits";
/**
* OpenAI 向量生成接口( /v1/embeddings )
*/
public static final String EMBEDDINGS_URL = "/v1/embeddings";
/**
* OpenAI 图片生成接口( /v1/images/generations )
*/
public static final String IMAGES_GENERATIONS_URL = "/v1/images/generations";
}
package com.jinyi.up.chatgpt.api2d.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author zhiquan
*/
@AllArgsConstructor
@Getter
public enum Api2dModelTypeEnum {
GPT_4(1, "gpt-4"),
GPT_4_0314(2, "gpt-4-0314"),
GPT_3_5_TURBO_0301(3, "gpt-3.5-turbo-0301"),
GPT_3_5_TURBO(4, "gpt-3.5-turbo");
private Integer status;
private String describe;
public static Api2dModelTypeEnum match(Integer status, Api2dModelTypeEnum defaultEnum) {
if (status != null) {
for (Api2dModelTypeEnum item : Api2dModelTypeEnum.values()) {
if (item.status.equals(status)) {
return item;
}
}
}
return defaultEnum;
}
public static String getDescirbe(Integer status, String defaultStr) {
if (status != null) {
for (Api2dModelTypeEnum item : Api2dModelTypeEnum.values()) {
if (item.status.equals(status)) {
return item.getDescribe();
}
}
}
return defaultStr;
}
}
package com.jinyi.up.chatgpt.api2d.entitys;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* chat 调用 聊天接口( /v1/chat/completions )需要封装的请求对象
* @author zhiquan
*/
@Data
@Accessors(chain = true)
public class Api2dParamData {
private String model;
private List<Api2dParamSonData> messages;
}
package com.jinyi.up.chatgpt.api2d.entitys;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 调用 聊天接口( /v1/chat/completions )需要封装的请求对象Api2dParamData的子对象
* @author zhiquan
*/
@Data
@Accessors(chain = true)
public class Api2dParamSonData {
private String role = "user";
private String content;
}
package com.jinyi.up.chatgpt.api2d.entitys;
import lombok.Data;
import java.util.List;
/**
* chat 调用 聊天接口( /v1/chat/completions )后返回的json
*字段完全同步于第三方响应字段
* @author zhiquan
*/
@Data
public class ChatCompletionsResponse {
/**
* 对话标识符,用于唯一标识此次聊天会话
*/
private String id;
/**
* 对象类型,表示此响应是一个聊天完成事件
*/
private String object;
/**
* 响应创建时间的时间戳
*/
private int created;
/**
* 使用的模型名称,此处为“gpt-3.5-turbo-0301"
*/
private String model;
/**
* 包含模型生成的选择回答的列表,这里只有一个选项
*/
private List<Choices> choices;
/**
* API 的使用情况统计信息
*/
private Usage usage;
}
package com.jinyi.up.chatgpt.api2d.entitys;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* chat 调用 聊天接口( /v1/chat/completions )后返回的json对象的子属性
* 字段完全同步于第三方响应字段
*
* @author zhiquan
*/
@Data
public class Choices {
/**
* 回答的索引号。
*/
private int index;
/**
* 表示模型生成的回答
*/
private Message message;
/**
* 完成原因,这里是“stop",表示模型停止生成回答
*/
@JSONField(name = "finish_reason")
private String finishReason;
}
package com.jinyi.up.chatgpt.api2d.entitys;
import lombok.Data;
/**
* chat 调用 聊天接口( /v1/chat/completions )后返回的json对象的子属性
*字段完全同步于第三方响应字段
* @author zhiquan
*/
@Data
public class Message {
/**
* 角色,这里是“assistant",表示助手角色生成的回答
*/
private String role;
/**
* 回答的内容
*/
private String content;
}
package com.jinyi.up.chatgpt.api2d.entitys;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* chat 调用 聊天接口( /v1/chat/completions )后返回的json对象的子属性
* 字段完全同步于第三方响应字段
*
* @author zhiquan
*/
@Data
public class Usage {
/**
* 用于 prompt 的令牌数量
*/
@JSONField(name="prompt_tokens")
private int promptTokens;
/**
* 生成的回复的令牌数量
*/
@JSONField(name="completion_tokens")
private int completionTokens;
/**
* 请求的总令牌数量 (包括输入和输出)
*/
@JSONField(name="total_tokens")
private int totalTokens;
/**
* 截至此次请求时的令牌数
*/
@JSONField(name="pre_token_count")
private int preTokenCount;
/**
* 初始限制的令牌数。
*/
@JSONField(name="pre_total")
private int preTotal;
/**
* 根据模型的内部限制调整后的令牌数
*/
@JSONField(name="adjust_total")
private int adjustTotal;
/**
* 最终用于此次请求的令牌数。
*/
@JSONField(name="final_total")
private int finalTotal;
}
package com.jinyi.up.chatgpt.api2d.utils;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.jinyi.up.chatgpt.api2d.config.ChatGptApi2dConfig;
import com.jinyi.up.chatgpt.api2d.constants.Api2dConstant;
import com.jinyi.up.chatgpt.api2d.entitys.Api2dParamData;
import com.jinyi.up.chatgpt.api2d.entitys.Api2dParamSonData;
import com.jinyi.up.chatgpt.api2d.entitys.ChatCompletionsResponse;
import com.jinyi.up.chatgpt.api2d.enums.Api2dModelTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* api2d 请求util
*/
@Slf4j
@Component
public class ChartGptApi2dUtil {
@Resource
private ChatGptApi2dConfig chatGptApi2dConfig;
/**
* 调用POST请求类型(application/json)接口
*
* @param
* @return
*/
private String publicApi2dInterface(String jsonStr, String url) throws Exception {
String authTemp = "Bearer %s";
String HttpResponseBodyStr = HttpRequest.post(url)
.header("Content-Type", "application/json")
.header("Authorization", String.format(authTemp, chatGptApi2dConfig.getForwardKey()))
.body(jsonStr)
.timeout(60000)
.execute().body();
return HttpResponseBodyStr;
}
/**
* ChartGPT聊天 返回响应的转换后的对象
*
* @param reqContent 输入的提问内容
* @param modelType chatgpt版本type{@link com.jinyi.up.chatgpt.api2d.enums.Api2dModelTypeEnum}
* @return ChatCompletionsResponse
*/
public ChatCompletionsResponse chatCompletionsEntity(Integer modelType, String reqContent) throws Exception {
String resultJsonStr = chatCompletionsString(modelType, reqContent);
log.info(resultJsonStr);
if (!StringUtils.isBlank(resultJsonStr)) {
ChatCompletionsResponse bean = JSONUtil.toBean(resultJsonStr, ChatCompletionsResponse.class);
return bean;
}
return null;
}
/**
* ChartGPT聊天返回原生响应的JSON STRING
*
* @param reqContent 输入的提问内容
* @param modelType chatgpt版本type{@link com.jinyi.up.chatgpt.api2d.enums.Api2dModelTypeEnum}
* @return
*/
public String chatCompletionsString(Integer modelType, String reqContent) throws Exception {
Api2dParamSonData api2dParamSonData = new Api2dParamSonData()
.setContent(reqContent);
List<Api2dParamSonData> messages = Lists.newArrayList(api2dParamSonData);
Api2dParamData api2dParamData = new Api2dParamData()
.setModel(Api2dModelTypeEnum.getDescirbe(modelType, Api2dModelTypeEnum.GPT_3_5_TURBO.getDescribe())).setMessages(messages);
String url = String.format(Api2dConstant.reqUrlTemplate, chatGptApi2dConfig.getHost(), Api2dConstant.CHAT_COMPLETIONS_URL);
log.info("ChartGPT聊天 请求url:{},请求param:{}", url, api2dParamData);
return publicApi2dInterface(JSONUtil.toJsonStr(api2dParamData), url);
}
}
3.resources文件夹下添加META-INF/spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jinyi.up.chatgpt.api2d.utils.ChartGptApi2dUtil,\
com.jinyi.up.chatgpt.api2d.config.ChatGptApi2dConfig
4.使用说明
jinyi-chatgpt-api2d-starter
jinyi-chatgpt-api2d-starter
时间 | 当前版本 | 版本特性 | 作者 |
---|---|---|---|
2023.7.12 | 0.0.1-RELEASE | 1.初版仅提供chatGpt提问功能 | zhiquan |
组件简介
- 基于API2D的API封装的
1.Spring Boot 项目添加 Maven 依赖
<dependency>
<groupId>com.jinyi.up</groupId>
<artifactId>jinyi-chatgpt-api2d-starter</artifactId>
<version>1.0.0</version>
</dependency>
2、在application.properties
或者 application.yml 等配置文件中增加如下配置
dbj.chatgpt.api2d.host=https://stream.api2d.net #api2d对外提供的ChatGpt访问的Api Host
dbj.chatgpt.api2d.forwardKey=fk****************8 #api2d服务提供的Forward Key
dbj:
chatgpt:
api2d:
host: https://stream.api2d.net #api2d对外提供的api访问Host
forwardKey: fk****************8 #api2d服务提供的Forward Key
3、使用示例
@Slf4j
@RestController
@RequestMapping("/test")
public class StarterTestController {
@Resource
private ChartGptApi2dUtil chartGptApi2dUtil;
@GetMapping("/gptStarter")
public R<Object> gptStarter() {
try {
ChatCompletionsResponse result = chartGptApi2dUtil.chatCompletionsEntity(4, "儿童节文案");
return R.ok(result);
} catch (Exception e) {
log.error("gpt回话请求异常:", e);
}
return R.failed();
}
}
4、ChartGptApi2dUtil能力
4.1 chatCompletionsEntity(Integer modelType, String reqContent)方法: OpenAI 聊天方法,返回封装的ChatCompletionsResponse对象
**4.2 chatCompletionsString(Integer modelType, String reqContent)**方法:OpenAI 聊天方法,返回的调用api2d openApi接口后返回的原生json字符串
chatCompletionsEntity() 和chatCompletionsString()请求参数相同,详见如下表格
参数 | 字段类型 | 是否必填 | 描述 | 备注 |
---|---|---|---|---|
modelType | Integer | * | api2d 对应的model版本枚举 ,1: GPT_4 4:gpt-3.5-turbo | 详见Api2dModelTypeEnum |
reqContent | String | * | 向chatgpt提问的问题内容 |
ChatCompletionsResponse对象属性说明
{
"id": "chatcmpl-7bgwmOfeGf14HkOrpMCJ4x9cvdArF", #对话标识符,用于唯一标识此次聊天会话
"object": "chat.completion", #对象类型,表示此响应是一个聊天完成事件
"created": 1689217580, #响应创建时间的时间戳
"model": "gpt-3.5-turbo-0613", #使用的模型名称,此处为gpt-3.5-turbo-0613
"choices": [ #包含模型生成的选择回答的列表,这里只有一个选项
{
"index": 0, #回答的索引号。
"message": { #表示模型生成的回答
"role": "assistant", #角色,这里是“assistant",表示助手角色生成的回答
"content": "科比,全名科比·布莱恩特(Kobe Bryant),1978年8月23日出生于美国宾夕法尼亚州费城,2019年1月26日因直升机失事意外身亡,是一位美国职业篮球运动员。科比是NBA历史上最伟大的球员之一,被誉为“黑曼巴”,他在职业生涯期间效力于洛杉矶湖人队。\n\n科比在NBA生涯中获得了众多荣誉,包括5个NBA总冠军、2个NBA总决赛最有价值球员(MVP)、4个全明星赛最有价值球员(MVP),以及18次入选NBA全明星阵容等。他也是NBA历史得分榜上位列第4的球员,总得分超过了3万分。\n\n除了在NBA的成功之外,科比也是美国国家队的重要成员,并在2008年和2012年两届奥运会上帮助美国队夺得金牌。\n\n科比在场上以他的得分能力和个人进攻技巧著称,他是一位极具竞争力的球员,对胜利有着强烈的渴望。他的篮球智商和技术使他成为一个精准的得分手,同时他也是一位出色的防守球员。\n\n科比的突然离世使全球篮球界深感痛惜,他的篮球成就和影响力将永远铭记在人们心中。" #回答的内容
},
"finishReason": "stop" #完成原因,这里是“stop",表示模型停止生成回答
}
],
"usage": { #API 的使用情况统计信息
"promptTokens": 9, #用于 prompt 的令牌数量
"completionTokens": 463, #生成的回复的令牌数量
"totalTokens": 472, # 请求的总令牌数量 (包括输入和输出)
"preTokenCount": 4096, # 截至此次请求时的令牌数
"preTotal": 42, #初始限制的令牌数。
"adjustTotal": 37, #根据模型的内部限制调整后的令牌数
"finalTotal": 5 #最终用于此次请求的令牌数。
}
原生Json字符串返回说明:
{"id":"chatcmpl-7bh9aayOMAY9z0iFDR5P4kdLNIjW1","object":"chat.completion","created":1689218374,"model":"gpt-3.5-turbo-0613","choices":[{"index":0,"message":{"role":"assistant","content":"科比(Kobe),全名科比·布莱恩特(Kobe Bryant),是一位美国职业篮球运动员,出生于1978年8月23日,于2020年1月26日因直升机事故不幸去世。科比在NBA的职业生涯中效力于洛杉矶湖人队,被认为是最伟大的篮球运动员之一。\n\n科比从高中时期就开始展现出与众不同的篮球天赋,在1996年的NBA选秀中以第13顺位被夏洛特黄蜂队选中,但很快被湖人队用于交换筹码,成为NBA历史上最年轻的球员之一。\n\n科比在湖人队的职业生涯中取得了众多成绩,包括5次NBA总冠军、2次NBA总决赛MVP、1次常规赛MVP等荣誉。他是湖人队历史上得分最高的球员,并在职业生涯中共获得了4次得分王的称号。\n\n除了职业联赛中的成功,科比还是美国国家队的成员,参加了多次国际比赛,其中包括2008年北京奥运会和2012年伦敦奥运会,帮助美国获得金牌。\n\n科比以其出色的得分能力、技术精湛的投篮和极高的竞争意识而闻名,他被誉为NBA历史上最全能的得分手之一。科比对比赛有着非常高的热情和敬业精神,他的工作态度和专注度也给球迷们留下了深刻的印象。\n\n科比的突然离世给整个篮球界和广大球迷带来了巨大的震惊和悲伤。他将永远被人们铭记为一位伟大的篮球运动员,为他在篮球领域的贡献和对于比赛的热爱致以敬意与怀念。"},"finish_reason":"stop"}],"usage":{"prompt_tokens":9,"completion_tokens":619,"total_tokens":628,"pre_token_count":4096,"pre_total":42,"adjust_total":35,"final_total":7}}