1声明式WebClient
@HttpExchange
public interface OpenAiClient {
@PostExchange(value = "/v1/chat/completions")
Mono<ChatCompletionResult> createChatCompletion(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorization, @RequestBody ChatCompletionRequest request);
@PostExchange(value = "/v1/chat/completions", accept = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<String> createChatCompletionStream(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorization, @RequestBody ChatCompletionRequest request);
@PostExchange(value = "/v1/images/generations")
Mono<ImageResult> createImage(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorization, @RequestBody CreateImageRequest request);
@PostExchange(value = "/v1/audio/transcriptions", contentType = MediaType.MULTIPART_FORM_DATA_VALUE)
Mono<TranscriptionResult> createAudioTranscriptions(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorization,
@RequestPart(value = "model", required = false) String model,
@RequestPart(value = "response_format", required = false) String responseFormat,
@RequestPart(value = "temperature", required = false) Double temperature,
@RequestPart(value = "language", required = false) String language,
@RequestPart("file") FilePart filePart);
@PostExchange(value = "/v1/audio/speech")
Flux<DataBuffer> createAudioSpeech(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorization, @RequestBody CreateSpeechRequest request);
}
@Configuration
public class OpenAiClientConfiguration {
@Bean
public OpenAiClient openAiClient(OpenAiProperties openAiProperties, ObjectMapper objectMapper) throws SSLException {
ObjectMapper newMapper = objectMapper.copy();
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder().codecs(configurer -> {
ClientCodecConfigurer.ClientDefaultCodecs defaultCodecs = configurer.defaultCodecs();
defaultCodecs.jackson2JsonEncoder(new Jackson2JsonEncoder(newMapper));
defaultCodecs.jackson2JsonDecoder(new Jackson2JsonDecoder(newMapper));
defaultCodecs.maxInMemorySize(-1);
}).build();
SslContext context = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(context)).
option(ChannelOption.CONNECT_TIMEOUT_MILLIS, openAiProperties.getTimeout()).
responseTimeout(Duration.ofMillis(openAiProperties.getTimeout())).
doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(openAiProperties.getTimeout(), TimeUnit.MILLISECONDS)));
WebClient client = WebClient.builder().baseUrl(openAiProperties.getProxyUrl()).defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json").
exchangeStrategies(exchangeStrategies).clientConnector(new ReactorClientHttpConnector(httpClient)).build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).blockTimeout(Duration.ofMillis(openAiProperties.getTimeout())).build();
return factory.createClient(OpenAiClient.class);
}
}
2 WebClient
ClientResponse response = WebClient.create().post().uri(openAiProperties.getProxyUrl() + "/v1/audio/speech").bodyValue(request).
header(HttpHeaders.AUTHORIZATION, Constant.BEARER_PREFIX + modelKeyBO.getKey()).exchange()
.block();
3 HttpClient
HttpClient.create().request(HttpMethod.valueOf(method.get())).uri(server.getUrl() + path).send(ByteBufFlux.fromString(Flux.just(arguments.asText()))).responseSingle((res, content) -> Mono.just(res.status().code())).block();
4 webflux
ClientRequest request = ClientRequest
.create(HttpMethod.valueOf(method.get()), URI.create(server.getUrl() + path))
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.body(BodyInserters.fromValue(JacksonUtils.toObj(arguments.asText(),Map.class)))
.build();
ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector());
Mono<ClientResponse> exchange = exchangeFunction.exchange(request);