1 前言
大家好,由于近期需要对接了ChatGPT API所以特地记录下来,据介绍该模型是和当前官网使用的相同的模型,如果你还没体验过ChatGPT,那么今天就教大家如何打破网络壁垒,打造一个属于自己的智能助手把。本文包括API Key的申请以及网络代理的搭建,那么事不宜迟,我们现在开始。
若有想体验的可联系我获取体验账号。
2 对接流程
2.1 API-Key的获取
首先第一步要获取OpenAI接口的API Key,该Key是你用来调用接口的token,主要用于接口鉴权。获取该key首先要注册OpenAi的账号。
2.1.1 打开platform.openai.com网站,点击view API Key
2.1.2 点击创建key
2.1.3 弹窗显示生成的key,记得把key复制,不然等会就找不到这个key了,只能重新创建
将API Key保存好以备用
2.2 API用量的查看
这里可以查看API的使用情况,新账号注册默认有5美元的试用额度,之前都是18美元,API成本降了之后试用额度也狠狠地砍了一刀。
2.3 核心代码实现
2.3.1 pom依赖
其中引入包cdkj-core请参考另一开源项目 维基框架
- <?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">
- <parent>
- <artifactId>framewiki-gpt</artifactId>
- <groupId>com.framewiki.gpt</groupId>
- <version>1.0.0</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>gpt-util</artifactId>
- <dependencies>
- <dependency>
- <groupId>com.cdkjframework</groupId>
- <artifactId>cdkj-core</artifactId>
- </dependency>
- <dependency>
- <groupId>com.cdkjframework</groupId>
- <artifactId>cdkj-util</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-httpclient</groupId>
- <artifactId>commons-httpclient</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-validation</artifactId>
- </dependency>
- </dependencies>
- </project>
2.3.2 实体类ChatMessagesDto.java
用于存放发送的消息信息,注解使用了lombok,如果没有使用lombok可以自动生成构造方法以及get和set方法
- package com.framewiki.gpt.dto.response;
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.dto
- * @ClassName: ChatMessagesDto
- * @Description: java类作用描述
- * @Author: xiaLin
- * @Date: 2023/6/10 22:30
- * @Version: 1.0
- */
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class ChatMessagesDto {
- /**
- * 消息角色
- * system
- * user
- * assistant
- */
- private String role;
- /**
- * 消息内容
- */
- private String content;
- }
2.3.3 实体类CreateChatCompletionDto.java
- package com.framewiki.gpt.dto.request;
- import lombok.Data;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.dto.request
- * @ClassName: CreateChatCompletionDto
- * @Description: java类作用描述
- * @Author: xiaLin
- * @Date: 2023/6/21 22:07
- * @Version: 1.0
- */
- @Data
- public class CreateChatCompletionDto {
- /**
- * 内容
- */
- private String content;
- /**
- * 模型
- */
- private String model;
- /**
- * 用户
- */
- private String user;
- }
2.3.4 实体类ChatCompletionRequestDto.java
用于发送的请求的参数实体类,参数释义如下:
- package com.framewiki.gpt.dto.request;
- import com.alibaba.fastjson.annotation.JSONField;
- import com.framewiki.gpt.dto.response.ChatMessagesDto;
- import lombok.Builder;
- import lombok.Data;
- import java.math.BigDecimal;
- import java.util.List;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.dto
- * @ClassName: ChatCompletionRequestDto
- * @Description: 请求实体
- * @Author: xiaLin
- * @Date: 2023/6/10 22:27
- * @Version: 1.0
- */
- @Data
- @Builder
- public class ChatCompletionRequestDto {
- /**
- * 模型
- * gpt-4
- * gpt-4-0314
- * gpt-4-32k
- * gpt-4-32k-0314
- * gpt-3.5-turbo
- * gpt-3.5-turbo-0301
- */
- private String model;
- /**
- * 温度,参数从0-2,越低表示越精准,越高表示越广发,回答的内容重复率越低
- */
- private BigDecimal temperature;
- /**
- * 消息
- */
- private List<ChatMessagesDto> messages;
- /**
- * 回复条数,一次对话回复的条数
- */
- private Integer n;
- /**
- * 是否流式处理,就像ChatGPT一样的处理方式,会增量的发送信息。
- */
- private Boolean stream;
- /**
- * 状态
- */
- private List<String> stop;
- /**
- * 生成的答案允许的最大token数
- */
- @JSONField(name = "max_tokens")
- private Integer maxTokens;
- /**
- * 对话用户
- */
- private String user;
- }
2.3.5 实体类ChatCompletionResponseDto.java
用于接收请求返回的信息以及执行结果
- package com.framewiki.gpt.dto.response;
- import lombok.Data;
- import java.util.List;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.dto
- * @ClassName: ChatCompletionResponseDto
- * @Description: 响应
- * @Author: xiaLin
- * @Date: 2023/6/16 23:18
- * @Version: 1.0
- */
- @Data
- public class ChatCompletionResponseDto {
- /**
- * ID
- */
- private String id;
- /**
- * 返回的内容
- */
- private String object;
- /**
- * 模型
- */
- private String model;
- /**
- * 创建时间
- */
- private long created;
- /**
- * 用户
- */
- private String user;
- /**
- * 选择
- */
- private List<ChatCompletionChoiceDto> choices;
- /**
- * 用量
- */
- private ChatCompletionUsageDto usage;
- }
2.3.6 实体类ChatCompletionUsageDto.java
- package com.framewiki.gpt.dto.response;
- import com.alibaba.fastjson.annotation.JSONField;
- import lombok.Data;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.dto
- * @ClassName: ChatCompletionUsageDto
- * @Description: 用量信息
- * @Author: xiaLin
- * @Date: 2023/6/16 22:44
- * @Version: 1.0
- */
- @Data
- public class ChatCompletionUsageDto {
- /**
- * 输入 token 数量
- */
- @JSONField(name = "prompt_tokens")
- private int promptTokens;
- /**
- * 完成 token数量
- */
- @JSONField(name = "completion_tokens")
- private int completionTokens;
- /**
- * token 总数
- */
- @JSONField(name = "total_tokens")
- private int totalTokens;
- }
2.3.7 实体类ChatCompletionChoiceDto.java
用于接收ChatGPT返回的数据
- package com.framewiki.gpt.dto.response;
- import lombok.Data;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.dto
- * @ClassName: ChatCompletionChoiceDto
- * @Description: java类作用描述
- * @Author: xiaLin
- * @Date: 2023/6/16 22:44
- * @Version: 1.0
- */
- @Data
- public class ChatCompletionChoiceDto {
- /**
- * 搜索
- */
- private Integer index;
- /**
- * 消息
- */
- private ChatMessagesDto message;
- /**
- * 完成的原因
- */
- private String finishReason;
- }
2.3.8 接口调用核心类ChatServiceImpl.java
使用HttpURLConnection用于进行api接口的调用,支持post和get方法请求。
url为配置文件open.ai.url的值,表示调用api的地址:https://api.openai.com/ ,token为获取的api-key。
执行post或者get方法时增加头部信息headers.put("Authorization", "Bearer " + token); 用于通过接口鉴权。
- package com.framewiki.gpt.service.impl;
- import com.cdkjframework.constant.EncodingConsts;
- import com.cdkjframework.constant.IntegerConsts;
- import com.cdkjframework.entity.http.HttpRequestEntity;
- import com.cdkjframework.enums.HttpMethodEnums;
- import com.cdkjframework.util.log.LogUtils;
- import com.cdkjframework.util.network.http.HttpRequestUtils;
- import com.cdkjframework.util.tool.StringUtils;
- import com.framewiki.gpt.config.ChatConfig;
- import com.framewiki.gpt.config.ChatConfiguration;
- import com.framewiki.gpt.dto.request.ChatCompletionRequestDto;
- import com.framewiki.gpt.dto.request.CreateChatCompletionDto;
- import com.framewiki.gpt.dto.response.ChatCompletionResponseDto;
- import com.framewiki.gpt.dto.response.ChatMessagesDto;
- import com.framewiki.gpt.service.ChatService;
- import lombok.RequiredArgsConstructor;
- import org.springframework.stereotype.Service;
- import java.math.BigDecimal;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.service.impl
- * @ClassName: ChatServiceImpl
- * @Description: java类作用描述
- * @Author: xiaLin
- * @Date: 2023/6/16 22:58
- * @Version: 1.0
- */
- @Service
- @RequiredArgsConstructor
- public class ChatServiceImpl implements ChatService {
- /**
- * 日志
- */
- private LogUtils logUtils = LogUtils.getLogger(ChatServiceImpl.class);
- /**
- * 配置信息
- */
- private final ChatConfiguration configuration;
- /**
- * 地址
- */
- private final ChatConfig chatConfig;
- /**
- * 创建对话
- *
- * @param content 消息内容
- */
- @Override
- public ChatCompletionResponseDto createChatCompletion(CreateChatCompletionDto content) {
- if (StringUtils.isNullAndSpaceOrEmpty(content.getModel())) {
- content.setModel(model);
- }
- List<ChatMessagesDto> messages = new ArrayList<>();
- ChatMessagesDto systemMessage = new ChatMessagesDto(role, content.getContent());
- messages.add(systemMessage);
- ChatCompletionRequestDto chatCompletionRequest = ChatCompletionRequestDto.builder()
- .model(content.getModel())
- .messages(messages)
- .user(content.getUser())
- .maxTokens(IntegerConsts.ONE_HUNDRED * IntegerConsts.FIVE)
- .temperature(BigDecimal.ONE)
- .build();
- HttpRequestEntity request = new HttpRequestEntity();
- request.setRequestAddress(chatConfig.getCreateChatCompletion());
- request.setMethod(HttpMethodEnums.POST);
- request.setData(chatCompletionRequest);
- request.setCharset(EncodingConsts.UTF8);
- // 请求头
- Map<String, String> headerMap = new HashMap<>(IntegerConsts.ONE);
- headerMap.put(AUTHORIZATION, BEARER + configuration.getOpenaiApiKey());
- request.setHeaderMap(headerMap);
- ChatCompletionResponseDto response = null;
- try {
- response = HttpRequestUtils.httpRequest(request, ChatCompletionResponseDto.class);
- response.setUser(content.getUser());
- } catch (Exception e) {
- logUtils.error(e);
- }
- // 返回结果
- return response;
- }
- }
2.3.9 定义接口常量配置类ChatConfig.class
用于维护支持的api接口列表
- package com.framewiki.gpt.config;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.stereotype.Component;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.config
- * @ClassName: GptConfig
- * @Description: GPT配置
- * @Author: xiaLin
- * @Date: 2023/6/10 18:16
- * @Version: 1.0
- */
- @Component
- @Configuration
- public class ChatConfig {
- /**
- * 环境
- */
- @Value("${spring.profiles.active}")
- private String active;
- /**
- * 默认环境
- */
- private final String defaultActive = "prod";
- /**
- * 地址
- */
- private final String OPEN_AI_URI = "https://api.openai.com/v1/";
- /**
- * 测试地址
- */
- private final String TEST_OPEN_AI_URI = "https://vpn.itizzy.com/v1/";
- /**
- * 请求机构
- * 列出模型
- * 检索模型
- */
- private final String MODEL_LIST = "models";
- /**
- * 聊天完成
- */
- private final String CREATE_CHAT_COMPLETION = "chat/completions";
- /**
- * 创建对话
- */
- private final String CREATE_COMPLETION = "completions";
- /**
- * ;
- * 聊天完成地址
- *
- * @return
- */
- public String getCreateChatCompletion() {
- StringBuffer address = new StringBuffer(getAddress());
- address.append(CREATE_CHAT_COMPLETION);
- // 返回结果
- return address.toString();
- }
- /**
- * 获取地址
- */
- private String getAddress() {
- if (active.startsWith(defaultActive)) {
- return OPEN_AI_URI;
- } else {
- return TEST_OPEN_AI_URI;
- }
- }
- }
2.3.10 接口调用OpenAi配置信息类ChatConfiguration.class
- package com.framewiki.gpt.config;
- import lombok.Data;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.context.annotation.Configuration;
- /**
- * @ProjectName: framewiki-gpt
- * @Package: com.framewiki.gpt.config
- * @ClassName: ChatConfiguration
- * @Description: java类作用描述
- * @Author: xiaLin
- * @Date: 2023/6/10 19:35
- * @Version: 1.0
- */
- @Data
- @Configuration
- @ConfigurationProperties(prefix = "open.ai.gpt")
- public class ChatConfiguration {
- /**
- * openai Api密钥
- */
- private String openaiApiKey;
- /**
- * 机构ID
- */
- private String organizationId;
- /**
- * appKey
- */
- private String appKey;
- }
3 常见问题
3.1 OpenAi接口调用不通
因为https://api.openai.com/ 地址也被限制了,但是接口没有对地区做校验,因此可以自己搭建一个代理。
我采用的是亚马逊云代理的模式(新账号可申请1H1G、8G硬盘的云服务器),具体代理配置流程如下:
下载及安装nginx就不在此详说了。
部署nginx并修改/nginx/nginx.conf文件,配置接口代理路径如下
- server {
- listen 443 ssl;
- server_name vpn.ai.com;
- ssl_certificate /usr/local/cert/vpn.ai.com.pem;
- ssl_certificate_key /usr/local/cert/vpn.ai.com.key;
- ssl_session_cache shared:SSL:1m;
- ssl_session_timeout 5m;
- ssl_ciphers HIGH:!aNULL:!MD5;
- ssl_prefer_server_ciphers on;
- location / {
- proxy_pass https://chat.openai.com/;
- proxy_ssl_server_name on;
- proxy_ssl_session_reuse off;
- }
- }
- }
3.2 接口返回401
检查请求方法是否增加token字段以及key是否正确
4 总结
至此JAVA对OpenAI对接就已经完成了,并且也支持连续对话,大家可以在此基础上不断地完善和桥接到web服务,定制自己的ChatGPT助手了。我自己也搭建了个平台,不断地在完善中,想要体验的可以用微信登录体验。
项目开源地址:https://gitee.com/cdkjframework/chatgpt-server
标签:JAVA,String,AI,private,gpt,import,ChatGPT,com,framewiki From: https://www.cnblogs.com/oopo/p/17999771