Use netty client for Azure, remove proxy configuration
This commit is contained in:
@@ -109,10 +109,6 @@ Example profile: src/test/resources/llama3.3-70b-azure.properties
|
|||||||
<groupId>com.azure</groupId>
|
<groupId>com.azure</groupId>
|
||||||
<artifactId>azure-ai-inference</artifactId>
|
<artifactId>azure-ai-inference</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.knuddels</groupId>
|
<groupId>com.knuddels</groupId>
|
||||||
<artifactId>jtokkit</artifactId>
|
<artifactId>jtokkit</artifactId>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package de.extio.lmlib.client.azureai;
|
package de.extio.lmlib.client.azureai;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
@@ -11,6 +9,7 @@ import java.util.Deque;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -28,7 +27,7 @@ import com.azure.ai.inference.models.ChatRequestUserMessage;
|
|||||||
import com.azure.ai.inference.models.CompletionsFinishReason;
|
import com.azure.ai.inference.models.CompletionsFinishReason;
|
||||||
import com.azure.core.credential.AzureKeyCredential;
|
import com.azure.core.credential.AzureKeyCredential;
|
||||||
import com.azure.core.http.HttpClient;
|
import com.azure.core.http.HttpClient;
|
||||||
import com.azure.core.http.okhttp.OkHttpAsyncHttpClientBuilder;
|
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
|
||||||
import com.azure.core.http.policy.ExponentialBackoffOptions;
|
import com.azure.core.http.policy.ExponentialBackoffOptions;
|
||||||
import com.azure.core.http.policy.RetryOptions;
|
import com.azure.core.http.policy.RetryOptions;
|
||||||
|
|
||||||
@@ -43,13 +42,9 @@ import de.extio.lmlib.profile.ModelProfile;
|
|||||||
import de.extio.lmlib.profile.ModelProfile.ModelProvider;
|
import de.extio.lmlib.profile.ModelProfile.ModelProvider;
|
||||||
import de.extio.lmlib.profile.ModelProfileService;
|
import de.extio.lmlib.profile.ModelProfileService;
|
||||||
import de.extio.lmlib.token.Tokenizer;
|
import de.extio.lmlib.token.Tokenizer;
|
||||||
import okhttp3.Authenticator;
|
import io.netty.channel.ChannelOption;
|
||||||
import okhttp3.Challenge;
|
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||||
import okhttp3.Credentials;
|
import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
import okhttp3.Route;
|
|
||||||
|
|
||||||
public final class AzureAiClient implements Client {
|
public final class AzureAiClient implements Client {
|
||||||
|
|
||||||
@@ -65,24 +60,9 @@ public final class AzureAiClient implements Client {
|
|||||||
|
|
||||||
private final Tokenizer tokenizer;
|
private final Tokenizer tokenizer;
|
||||||
|
|
||||||
private final boolean proxyEnabled;
|
AzureAiClient(final ModelProfileService modelProfileService, final Tokenizer tokenizer) {
|
||||||
|
|
||||||
private final String proxyHost;
|
|
||||||
|
|
||||||
private final int proxyPort;
|
|
||||||
|
|
||||||
private final String proxyUser;
|
|
||||||
|
|
||||||
private final String proxyPassword;
|
|
||||||
|
|
||||||
AzureAiClient(final ModelProfileService modelProfileService, final Tokenizer tokenizer, final boolean proxyEnabled, final String proxyHost, final int proxyPort, final String proxyUser, final String proxyPassword) {
|
|
||||||
this.modelProfileService = modelProfileService;
|
this.modelProfileService = modelProfileService;
|
||||||
this.tokenizer = tokenizer;
|
this.tokenizer = tokenizer;
|
||||||
this.proxyEnabled = proxyEnabled;
|
|
||||||
this.proxyHost = proxyHost;
|
|
||||||
this.proxyPort = proxyPort;
|
|
||||||
this.proxyUser = proxyUser;
|
|
||||||
this.proxyPassword = proxyPassword;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -109,7 +89,7 @@ public final class AzureAiClient implements Client {
|
|||||||
|
|
||||||
return this.requestCompletions(chat, modelCategory, modelProfile);
|
return this.requestCompletions(chat, modelCategory, modelProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Completion streamConversation(final ModelCategory modelCategory, final Conversation conversation, final Consumer<String> chunkConsumer) {
|
public Completion streamConversation(final ModelCategory modelCategory, final Conversation conversation, final Consumer<String> chunkConsumer) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
throw new UnsupportedOperationException("Not implemented yet");
|
||||||
@@ -242,44 +222,13 @@ public final class AzureAiClient implements Client {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
final OkHttpClient.Builder nativeOkHttpClientBuilder = new OkHttpClient.Builder();
|
final reactor.netty.http.client.HttpClient httpClient = reactor.netty.http.client.HttpClient.create()
|
||||||
|
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT)
|
||||||
|
.responseTimeout(Duration.ofMillis(TIMEOUT))
|
||||||
|
.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(TIMEOUT, TimeUnit.MILLISECONDS)).addHandlerLast(new WriteTimeoutHandler(TIMEOUT, TimeUnit.MILLISECONDS)));
|
||||||
|
|
||||||
if (this.proxyEnabled) {
|
final NettyAsyncHttpClientBuilder azureHttpClientBuilder = new NettyAsyncHttpClientBuilder(httpClient);
|
||||||
LOGGER.info("Proxy is enabled. Configuring proxy settings for host: {} port: {} user: {}", this.proxyHost, this.proxyPort, this.proxyUser);
|
final HttpClient azureHttpClient = azureHttpClientBuilder
|
||||||
|
|
||||||
final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(this.proxyHost, this.proxyPort));
|
|
||||||
nativeOkHttpClientBuilder.proxy(proxy);
|
|
||||||
|
|
||||||
if (this.proxyUser != null && this.proxyPassword != null) {
|
|
||||||
final Authenticator proxyAuthenticator = new Authenticator() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Request authenticate(final Route route, final Response response) {
|
|
||||||
for (final Challenge challenge : response.challenges()) {
|
|
||||||
if (challenge.scheme().equalsIgnoreCase("OkHttp-Preemptive")) {
|
|
||||||
final String credential = Credentials.basic(proxyUser, proxyPassword);
|
|
||||||
return response.request().newBuilder()
|
|
||||||
.header("Proxy-Authorization", credential)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
nativeOkHttpClientBuilder.proxyAuthenticator(proxyAuthenticator);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOGGER.warn("Proxy user or password is not set. Skipping proxy authentication.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOGGER.info("Proxy is not enabled. Skipping proxy configuration.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final OkHttpClient nativeOkHttpClient = nativeOkHttpClientBuilder.build();
|
|
||||||
final OkHttpAsyncHttpClientBuilder okHttpClientBuilder = new OkHttpAsyncHttpClientBuilder(nativeOkHttpClient);
|
|
||||||
final HttpClient okHttpClient = okHttpClientBuilder
|
|
||||||
.connectionTimeout(Duration.ofMillis(CONNECT_TIMEOUT))
|
|
||||||
.readTimeout(Duration.ofMillis(TIMEOUT))
|
.readTimeout(Duration.ofMillis(TIMEOUT))
|
||||||
.responseTimeout(Duration.ofMillis(TIMEOUT))
|
.responseTimeout(Duration.ofMillis(TIMEOUT))
|
||||||
.writeTimeout(Duration.ofMillis(TIMEOUT))
|
.writeTimeout(Duration.ofMillis(TIMEOUT))
|
||||||
@@ -289,7 +238,7 @@ public final class AzureAiClient implements Client {
|
|||||||
.credential(new AzureKeyCredential(modelProfile.apiKey()))
|
.credential(new AzureKeyCredential(modelProfile.apiKey()))
|
||||||
.endpoint(modelProfile.url())
|
.endpoint(modelProfile.url())
|
||||||
.retryOptions(retryOptions)
|
.retryOptions(retryOptions)
|
||||||
.httpClient(okHttpClient)
|
.httpClient(azureHttpClient)
|
||||||
.buildClient();
|
.buildClient();
|
||||||
return chatCompletionsClient;
|
return chatCompletionsClient;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,27 +9,12 @@ import de.extio.lmlib.profile.ModelProfileService;
|
|||||||
import de.extio.lmlib.token.Tokenizer;
|
import de.extio.lmlib.token.Tokenizer;
|
||||||
|
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@ConditionalOnClass(name = {"com.azure.ai.inference.ChatCompletionsClient", "okhttp3.OkHttpClient" })
|
@ConditionalOnClass(name = {"com.azure.ai.inference.ChatCompletionsClient" })
|
||||||
public class AzureAiClientAutoConfiguration {
|
public class AzureAiClientAutoConfiguration {
|
||||||
|
|
||||||
@Value("${extproxy.enabled:false}")
|
|
||||||
private boolean proxyEnabled;
|
|
||||||
|
|
||||||
@Value("${extproxy.host:}")
|
|
||||||
private String proxyHost;
|
|
||||||
|
|
||||||
@Value("${extproxy.port:0}")
|
|
||||||
private int proxyPort;
|
|
||||||
|
|
||||||
@Value("${extproxy.username:}")
|
|
||||||
private String proxyUser;
|
|
||||||
|
|
||||||
@Value("${extproxy.password:}")
|
|
||||||
private String proxyPassword;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
AzureAiClient azureAiClient(final ModelProfileService modelProfileService, final Tokenizer tokenizer) {
|
AzureAiClient azureAiClient(final ModelProfileService modelProfileService, final Tokenizer tokenizer) {
|
||||||
return new AzureAiClient(modelProfileService, tokenizer, this.proxyEnabled, this.proxyHost, this.proxyPort, this.proxyUser, this.proxyPassword);
|
return new AzureAiClient(modelProfileService, tokenizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user