这段时间比较火的chatGPT,准确来说应该只是openAI的一个小部分,这里对openAI的功能接口进行一个java实现,以文本补全、聊天(也就是chatGPT)和图像生成作为演示,体会一下AI的强大力量。
一、openAI账号创建以及测试
1.账号
访问openai.com注册,按照提示输入注册就行,这里注意的就是需要外国手机号,还浪费了我几十块钱,可恶。。
2.创建API KEY
在个人中心里面创建一下api密钥,这里要注意key只有创建时可以看到,创建完之后就不可见了,因此在创建时要注意复制保存,当然如果实在忘了,删除重新创建一个就行
二、配置Maven
<dependency><groupId>com.netflix.feign</groupId><artifactId>feign-core</artifactId><version>8.18.0</version></dependency><dependency><groupId>com.netflix.feign</groupId><artifactId>feign-jackson</artifactId><version>8.18.0</version></dependency><dependency><groupId>com.netflix.feign</groupId><artifactId>feign-okhttp</artifactId><version>8.18.0</version></dependency>
三、配置yml文件
key就是OpenAI官网申请的API KEY
open-ai:url: https://api.openai.com/key: xxxxxxxxx
三、Controller(以流的方式返回)
@Api(tags = "客户端-客户管理")
@RestController
@RequestMapping("/client/chatUser")
public class ChatUserClientController {@Resourceprivate ChatUserService chatUserService;/*** 返回数据流 优化用户体验* @return*/@ApiOperation(value = "发送聊天",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)@PostMapping("/sendMessage")public ResponseBodyEmitter sendMessageByStream(@RequestBody OpenAIChatSendMessage openAIChatSendMessage) {return chatUserService.sendMessage(openAIChatSendMessage);}}
四、接口层
public interface ChatUserService extends IService<ChatUser>{ResponseBodyEmitter sendMessage(OpenAIChatSendMessage openAIChatSendMessage);
}
五、实现层
可以根据自己的需求在此处添加判断逻辑
@Service
public class ChatUserServiceImpl extends ServiceImpl<ChatUserMapper, ChatUser> implements ChatUserService {@Resourceprivate OpenAIApiDao openAIApiDao;@Overridepublic ResponseBodyEmitter sendMessage(OpenAIChatSendMessage openAIChatSendMessage) {List<OpenAIChatMessage> messages = openAIChatSendMessage.getMessages();if (CollectionUtils.isEmpty(messages) || messages.size() == 1) {throw new NingException(ServiceCode.FAILED);}// 可在次数加判断逻辑ResponseBodyEmitter emitter = new ResponseBodyEmitter();CompletableFuture.runAsync(() -> {// 调用 OpenAI 返回openAIChatSendMessage.setStream(true);Response response = openAIApiDao.sendChatByOpenAI(openAIChatSendMessage);try {try (InputStream inputStream = response.body().asInputStream()) {byte[] buffer = new byte[1024];int bytesRead = -1;while ((bytesRead = inputStream.read(buffer)) != -1) {emitter.send(Arrays.copyOf(buffer, bytesRead));}} finally {emitter.complete();response.close();}} catch (IOException e) {emitter.completeWithError(e);}});return emitter;}}
六、OpenAIApiDao
public interface OpenAIApiDao {Response sendChatByOpenAI(OpenAIChatSendMessage openAIChatSendMessage);}
七、feign初始化、调用
包含跳过https校验
@Slf4j
@Service
public class OpenAIApiDaoImpl implements OpenAIApiDao {private static OpenAIChatApi OPEN_AI_CHAT_API;@Value("${open-ai.url}")protected String url;@Value("${open-ai.key}")private String key;private static SSLSocketFactory createTrustAllSslSocketFactory(TrustManager[] trustManagers) throws NoSuchAlgorithmException, KeyManagementException {SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, trustManagers, new SecureRandom());return sslContext.getSocketFactory();}@PostConstruct@SneakyThrowsprotected void init() {// 跳过https校验// 1. 创建一个不进行任何证书校验的 TrustManagerTrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {public void checkClientTrusted(X509Certificate[] chain, String authType) {}public void checkServerTrusted(X509Certificate[] chain, String authType) {}public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }}};// 2. 创建一个 OkHttpClient.Builder 对象,并将上面创建的 TrustManager 设置到 OkHttpClient.Builder 中OkHttpClient.Builder builder = new OkHttpClient.Builder().hostnameVerifier((hostname, session) -> true).sslSocketFactory(createTrustAllSslSocketFactory(trustAllCerts), new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}});OPEN_AI_CHAT_API = Feign.builder().client(new feign.okhttp.OkHttpClient(builder.build())).decoder(new Decoder.Default()).encoder(new JacksonEncoder()).errorDecoder(new ErrorDecoder.Default()).target(OpenAIChatApi.class, url);}@Overridepublic Response sendChatByOpenAI(OpenAIChatSendMessage openAIChatSendMessage) {return OPEN_AI_CHAT_API.sendChatMessage(key, openAIChatSendMessage);}
}
八、调用层
public interface OpenAIChatApi {/*** 聊天消息发送*/@RequestLine("POST v1/chat/completions")@Headers({"Content-Type: application/json","Authorization: {key}","Accept: application/octet-stream"})Response sendChatMessage(@Param("key") String key, OpenAIChatSendMessage messages);}
九、VO类
1.OpenAIChatMessage
@Data
public class OpenAIChatMessage {private String role;private String content;
}
2.OpenAIChatSendMessage
@Data
public class OpenAIChatSendMessage {@ApiModelProperty("消息记录")private List<OpenAIChatMessage> messages;@ApiModelProperty("是否使用流式传输")private Boolean stream;@ApiModelProperty("温度(准确率,温度越高消费时间约长)")private BigDecimal temperature;@ApiModelProperty("指定生成文本的概率阈值。这个参数可以控制生成文本的多样性,以避免生成过于相似的文本。")private BigDecimal top_p;
}
ok,齐活~