-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvements to HttpClient auto-configuration #115
base: main
Are you sure you want to change the base?
Improvements to HttpClient auto-configuration #115
Conversation
Introduce shared HttpClientAutoConfiguration to define a HttpClientBuilder prototype bean and related task executors, with support for virtual threads (when on Java 21+) and context propagation (when Micrometer is used).
@dliubarskyi This is a suggestion for a possible improvement of the HTTP Client configuration, based on the ideas we considered in the previous PR. |
@Bean | ||
@ConditionalOnMissingBean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This annotation is important because it allows developers to define their own OllamaChatModel
bean if they need additional customisations.
Same for the other model beans in this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I guess ollamaStreamingLanguageModel
should also be annotated with @ConditionalOnMissingBean
?
...oconfigure/src/main/java/dev/langchain4j/autoconfigure/http/HttpClientAutoConfiguration.java
Show resolved
Hide resolved
ObjectProvider<HttpClientBuilderCustomizer> customizers | ||
) { | ||
HttpClientBuilder httpClientBuilder = new SpringRestClientBuilder() | ||
.streamingRequestExecutor(asyncTaskExecutor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there's always an AsyncTaskExecutor
bean available, it can be configured directly, removing the need to operate the createDefaultStreamingRequestExecutor
switch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it always available because of the bean definitions below (httpClientVirtualThreadsTaskExecutor
, etc), right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if there is a way to avoid creating an executor in case it is not required? Or it is not a concern worth worrying about?
...oconfigure/src/main/java/dev/langchain4j/autoconfigure/http/HttpClientBuilderCustomizer.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ThomasVitale thanks a lot, this looks great!
I like how it simplifies the code, but I am a bit worried that now there is no way to precisely configure client/executor per model type and/or provider. WDYT?
return SpringRestClient.builder() | ||
.restClientBuilder(restClientBuilder.getIfAvailable(RestClient::builder)) | ||
// executor is not needed for no-streaming OllamaChatModel | ||
.createDefaultStreamingRequestExecutor(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, with current configuration, task executor will always be created, even if it is not required (e.g., only non-streaming OllamaChatModel
is used in the application)?
@Bean | ||
@ConditionalOnMissingBean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I guess ollamaStreamingLanguageModel
should also be annotated with @ConditionalOnMissingBean
?
@ConditionalOnProperty(PREFIX + ".chat-model.base-url") | ||
OllamaChatModel ollamaChatModel( | ||
@Qualifier(CHAT_MODEL_HTTP_CLIENT_BUILDER) HttpClientBuilder httpClientBuilder, | ||
HttpClientBuilder httpClientBuilder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand correctly that there is currently no way to customize http client and/or executor per model type (e.g., use different configuration for non-streaming and streaming model) or provider (e.g., use different configuration for different LLM providers)?
@@ -31,6 +31,12 @@ | |||
</exclusions> | |||
</dependency> | |||
|
|||
<dependency> | |||
<groupId>dev.langchain4j</groupId> | |||
<artifactId>langchain4j-spring-boot-autoconfigure</artifactId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(note for myself): need to do the same for OpenAI SB starter
ObjectProvider<HttpClientBuilderCustomizer> customizers | ||
) { | ||
HttpClientBuilder httpClientBuilder = new SpringRestClientBuilder() | ||
.streamingRequestExecutor(asyncTaskExecutor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it always available because of the bean definitions below (httpClientVirtualThreadsTaskExecutor
, etc), right?
} | ||
|
||
@Test | ||
void httpClientBuilderWhenNoAutoConfiguredRestClient() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please explain when/why can this happen that there is no RestClientAutoConfiguration
?
ObjectProvider<HttpClientBuilderCustomizer> customizers | ||
) { | ||
HttpClientBuilder httpClientBuilder = new SpringRestClientBuilder() | ||
.streamingRequestExecutor(asyncTaskExecutor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if there is a way to avoid creating an executor in case it is not required? Or it is not a concern worth worrying about?
Change
Introduce shared
HttpClientAutoConfiguration
to define aHttpClientBuilder
prototype bean and related task executors, with support for virtual threads (when on Java 21+) and context propagation (when Micrometer is used).General checklist