这段时间比较火的chatGPT,准确来说应该只是openAI的一个小部分,这里对openAI的功能接口进行一个java实现,以文本补全、聊天(也就是chatGPT)和图像生成作为演示,体会一下AI的强大力量。
访问openai.com注册,按照提示输入注册就行,这里注意的就是需要外国手机号,还浪费了我几十块钱,可恶。。
在个人中心里面创建一下api密钥,这里要注意key只有创建时可以看到,创建完之后就不可见了,因此在创建时要注意复制保存,当然如果实在忘了,删除重新创建一个就行
<dependency>
<groupId>com.netflix.feigngroupId>
<artifactId>feign-coreartifactId>
<version>8.18.0version>
dependency>
<dependency>
<groupId>com.netflix.feigngroupId>
<artifactId>feign-jacksonartifactId>
<version>8.18.0version>
dependency>
<dependency>
<groupId>com.netflix.feigngroupId>
<artifactId>feign-okhttpartifactId>
<version>8.18.0version>
dependency>
key就是OpenAI官网申请的API KEY
open-ai:
url: https://api.openai.com/
key: xxxxxxxxx
@Api(tags = "客户端-客户管理")
@RestController
@RequestMapping("/client/chatUser")
public class ChatUserClientController {
@Resource
private 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 {
@Resource
private OpenAIApiDao openAIApiDao;
@Override
public 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;
}
}
public interface OpenAIApiDao {
Response sendChatByOpenAI(OpenAIChatSendMessage openAIChatSendMessage);
}
包含跳过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
@SneakyThrows
protected void init() {
// 跳过https校验
// 1. 创建一个不进行任何证书校验的 TrustManager
TrustManager[] 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() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public 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);
}
@Override
public 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);
}
@Data
public class OpenAIChatMessage {
private String role;
private String content;
}
@Data
public class OpenAIChatSendMessage {
@ApiModelProperty("消息记录")
private List<OpenAIChatMessage> messages;
@ApiModelProperty("是否使用流式传输")
private Boolean stream;
@ApiModelProperty("温度(准确率,温度越高消费时间约长)")
private BigDecimal temperature;
@ApiModelProperty("指定生成文本的概率阈值。这个参数可以控制生成文本的多样性,以避免生成过于相似的文本。")
private BigDecimal top_p;
}
ok,齐活~