Skip to content

Add missing builders to Mistral models to follow project patterns #3464

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,13 @@ private MistralAiApi mistralAiApi(String apiKey, String commonApiKey, String bas
Assert.hasText(resolvedApiKey, "Mistral API key must be set");
Assert.hasText(resoledBaseUrl, "Mistral base URL must be set");

return new MistralAiApi(resoledBaseUrl, resolvedApiKey, restClientBuilder, webClientBuilder,
responseErrorHandler);
return MistralAiApi.builder()
.baseUrl(resoledBaseUrl)
.apiKey(resolvedApiKey)
.restClientBuilder(restClientBuilder)
.webClientBuilder(webClientBuilder)
.responseErrorHandler(responseErrorHandler)
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ public MistralAiEmbeddingModel mistralAiEmbeddingModel(MistralAiCommonProperties
embeddingProperties.getBaseUrl(), commonProperties.getBaseUrl(),
restClientBuilderProvider.getIfAvailable(RestClient::builder), responseErrorHandler);

var embeddingModel = new MistralAiEmbeddingModel(mistralAiApi, embeddingProperties.getMetadataMode(),
embeddingProperties.getOptions(), retryTemplate,
observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP));
var embeddingModel = MistralAiEmbeddingModel.builder()
.mistralAiApi(mistralAiApi)
.metadataMode(embeddingProperties.getMetadataMode())
.options(embeddingProperties.getOptions())
.retryTemplate(retryTemplate)
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
.build();

observationConvention.ifAvailable(embeddingModel::setObservationConvention);

Expand All @@ -86,7 +90,12 @@ private MistralAiApi mistralAiApi(String apiKey, String commonApiKey, String bas
Assert.hasText(resolvedApiKey, "Mistral API key must be set");
Assert.hasText(resoledBaseUrl, "Mistral base URL must be set");

return new MistralAiApi(resoledBaseUrl, resolvedApiKey, restClientBuilder, responseErrorHandler);
return MistralAiApi.builder()
.baseUrl(resoledBaseUrl)
.apiKey(apiKey)
.restClientBuilder(restClientBuilder)
.responseErrorHandler(responseErrorHandler)
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,18 @@ public MistralAiModerationModel mistralAiModerationModel(MistralAiCommonProperti
Assert.hasText(resolvedApiKey, "Mistral API key must be set");
Assert.hasText(resoledBaseUrl, "Mistral base URL must be set");

var mistralAiModerationAi = new MistralAiModerationApi(resoledBaseUrl, resolvedApiKey,
restClientBuilderProvider.getIfAvailable(RestClient::builder), responseErrorHandler);
var mistralAiModerationApi = MistralAiModerationApi.builder()
.baseUrl(resoledBaseUrl)
.apiKey(resolvedApiKey)
.restClientBuilder(restClientBuilderProvider.getIfAvailable(RestClient::builder))
.responseErrorHandler(responseErrorHandler)
.build();

return new MistralAiModerationModel(mistralAiModerationAi, retryTemplate, moderationProperties.getOptions());
return MistralAiModerationModel.builder()
.mistralAiModerationApi(mistralAiModerationApi)
.retryTemplate(retryTemplate)
.options(moderationProperties.getOptions())
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
* @author luocongqiu
* @author Ilayaperumal Gopinathan
* @author Alexandros Pappas
* @author Jason Smith
* @since 1.0.0
*/
public class MistralAiChatModel implements ChatModel {
Expand Down Expand Up @@ -123,6 +124,7 @@ public class MistralAiChatModel implements ChatModel {
*/
private ChatModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;

@Deprecated
public MistralAiChatModel(MistralAiApi mistralAiApi, MistralAiChatOptions defaultOptions,
ToolCallingManager toolCallingManager, RetryTemplate retryTemplate,
ObservationRegistry observationRegistry) {
Expand Down Expand Up @@ -538,7 +540,7 @@ public static final class Builder {
.model(MistralAiApi.ChatModel.SMALL.getValue())
.build();

private ToolCallingManager toolCallingManager;
private ToolCallingManager toolCallingManager = DEFAULT_TOOL_CALLING_MANAGER;

private ToolExecutionEligibilityPredicate toolExecutionEligibilityPredicate = new DefaultToolExecutionEligibilityPredicate();

Expand Down Expand Up @@ -581,11 +583,7 @@ public Builder observationRegistry(ObservationRegistry observationRegistry) {
}

public MistralAiChatModel build() {
if (this.toolCallingManager != null) {
return new MistralAiChatModel(this.mistralAiApi, this.defaultOptions, this.toolCallingManager,
this.retryTemplate, this.observationRegistry, this.toolExecutionEligibilityPredicate);
}
return new MistralAiChatModel(this.mistralAiApi, this.defaultOptions, DEFAULT_TOOL_CALLING_MANAGER,
return new MistralAiChatModel(this.mistralAiApi, this.defaultOptions, this.toolCallingManager,
this.retryTemplate, this.observationRegistry, this.toolExecutionEligibilityPredicate);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
* @author Christian Tzolov
* @author Thomas Vitale
* @author Alexandros Pappas
* @author Jason Smith
* @since 0.8.1
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
Expand Down Expand Up @@ -403,7 +404,7 @@ public boolean equals(Object obj) {
&& Objects.equals(this.toolContext, other.toolContext);
}

public static class Builder {
public static final class Builder {

private final MistralAiChatOptions options = new MistralAiChatOptions();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
* @see AbstractEmbeddingModel
* @author Ricken Bazolo
* @author Thomas Vitale
* @author Jason Smith
* @since 1.0.0
*/
public class MistralAiEmbeddingModel extends AbstractEmbeddingModel {
Expand All @@ -73,20 +74,24 @@ public class MistralAiEmbeddingModel extends AbstractEmbeddingModel {
*/
private EmbeddingModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;

@Deprecated
public MistralAiEmbeddingModel(MistralAiApi mistralAiApi) {
this(mistralAiApi, MetadataMode.EMBED);
}

@Deprecated
public MistralAiEmbeddingModel(MistralAiApi mistralAiApi, MetadataMode metadataMode) {
this(mistralAiApi, metadataMode,
MistralAiEmbeddingOptions.builder().withModel(MistralAiApi.EmbeddingModel.EMBED.getValue()).build(),
RetryUtils.DEFAULT_RETRY_TEMPLATE);
}

@Deprecated
public MistralAiEmbeddingModel(MistralAiApi mistralAiApi, MistralAiEmbeddingOptions options) {
this(mistralAiApi, MetadataMode.EMBED, options, RetryUtils.DEFAULT_RETRY_TEMPLATE);
}

@Deprecated
public MistralAiEmbeddingModel(MistralAiApi mistralAiApi, MetadataMode metadataMode,
MistralAiEmbeddingOptions options, RetryTemplate retryTemplate) {
this(mistralAiApi, metadataMode, options, retryTemplate, ObservationRegistry.NOOP);
Expand Down Expand Up @@ -188,4 +193,53 @@ public void setObservationConvention(EmbeddingModelObservationConvention observa
this.observationConvention = observationConvention;
}

public static Builder builder() {
return new Builder();
}

public static final class Builder {

private MistralAiApi mistralAiApi;

private MetadataMode metadataMode = MetadataMode.EMBED;

private MistralAiEmbeddingOptions options = MistralAiEmbeddingOptions.builder()
.withModel(MistralAiApi.EmbeddingModel.EMBED.getValue())
.build();

private RetryTemplate retryTemplate = RetryUtils.DEFAULT_RETRY_TEMPLATE;

private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;

public Builder mistralAiApi(MistralAiApi mistralAiApi) {
this.mistralAiApi = mistralAiApi;
return this;
}

public Builder metadataMode(MetadataMode metadataMode) {
this.metadataMode = metadataMode;
return this;
}

public Builder options(MistralAiEmbeddingOptions options) {
this.options = options;
return this;
}

public Builder retryTemplate(RetryTemplate retryTemplate) {
this.retryTemplate = retryTemplate;
return this;
}

public Builder observationRegistry(ObservationRegistry observationRegistry) {
this.observationRegistry = observationRegistry;
return this;
}

public MistralAiEmbeddingModel build() {
return new MistralAiEmbeddingModel(mistralAiApi, metadataMode, options, retryTemplate, observationRegistry);
}

}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 the original author or authors.
* Copyright 2023-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,6 +28,7 @@
*
* @author Ricken Bazolo
* @author Thomas Vitale
* @author Jason Smith
* @since 0.8.1
*/
@JsonInclude(Include.NON_NULL)
Expand Down Expand Up @@ -70,7 +71,7 @@ public Integer getDimensions() {
return null;
}

public static class Builder {
public static final class Builder {

protected MistralAiEmbeddingOptions options;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 the original author or authors.
* Copyright 2023-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -60,10 +60,15 @@
* @author Ricken Bazolo
* @author Christian Tzolov
* @author Thomas Vitale
* @author Jason Smith
* @since 1.0.0
*/
public class MistralAiApi {

public static Builder builder() {
return new Builder();
}

public static final String PROVIDER_NAME = AiProvider.MISTRAL_AI.value();

private static final String DEFAULT_BASE_URL = "https://api.mistral.ai";
Expand All @@ -78,45 +83,48 @@ public class MistralAiApi {

/**
* Create a new client api with DEFAULT_BASE_URL
* @param mistralAiApiKey Mistral api Key.
* @param apiKey Mistral api Key.
*/
public MistralAiApi(String mistralAiApiKey) {
this(DEFAULT_BASE_URL, mistralAiApiKey);
@Deprecated
public MistralAiApi(String apiKey) {
this(DEFAULT_BASE_URL, apiKey);
}

/**
* Create a new client api.
* @param baseUrl api base URL.
* @param mistralAiApiKey Mistral api Key.
* @param apiKey Mistral api Key.
*/
public MistralAiApi(String baseUrl, String mistralAiApiKey) {
this(baseUrl, mistralAiApiKey, RestClient.builder(), RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER);
@Deprecated
public MistralAiApi(String baseUrl, String apiKey) {
this(baseUrl, apiKey, RestClient.builder(), RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER);
}

/**
* Create a new client api.
* @param baseUrl api base URL.
* @param mistralAiApiKey Mistral api Key.
* @param apiKey Mistral api Key.
* @param restClientBuilder RestClient builder.
* @param responseErrorHandler Response error handler.
*/
public MistralAiApi(String baseUrl, String mistralAiApiKey, RestClient.Builder restClientBuilder,
@Deprecated
public MistralAiApi(String baseUrl, String apiKey, RestClient.Builder restClientBuilder,
ResponseErrorHandler responseErrorHandler) {
this(baseUrl, mistralAiApiKey, restClientBuilder, WebClient.builder(), responseErrorHandler);
this(baseUrl, apiKey, restClientBuilder, WebClient.builder(), responseErrorHandler);
}

/**
* Create a new client api.
* @param baseUrl api base URL.
* @param mistralAiApiKey Mistral api Key.
* @param apiKey Mistral api Key.
* @param restClientBuilder RestClient builder.
* @param responseErrorHandler Response error handler.
*/
public MistralAiApi(String baseUrl, String mistralAiApiKey, RestClient.Builder restClientBuilder,
public MistralAiApi(String baseUrl, String apiKey, RestClient.Builder restClientBuilder,
WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler) {

Consumer<HttpHeaders> jsonContentHeaders = headers -> {
headers.setBearerAuth(mistralAiApiKey);
headers.setBearerAuth(apiKey);
headers.setContentType(MediaType.APPLICATION_JSON);
};

Expand Down Expand Up @@ -1074,4 +1082,53 @@ public record ChunkChoice(

}

public static final class Builder {

private String baseUrl = DEFAULT_BASE_URL;

private String apiKey;

private RestClient.Builder restClientBuilder = RestClient.builder();

private WebClient.Builder webClientBuilder = WebClient.builder();

private ResponseErrorHandler responseErrorHandler = RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER;

public Builder baseUrl(String baseUrl) {
Assert.hasText(baseUrl, "baseUrl cannot be null or empty");
this.baseUrl = baseUrl;
return this;
}

public Builder apiKey(String apiKey) {
Assert.hasText(apiKey, "apiKey cannot be null or empty");
this.apiKey = apiKey;
return this;
}

public Builder restClientBuilder(RestClient.Builder restClientBuilder) {
Assert.notNull(restClientBuilder, "restClientBuilder cannot be null");
this.restClientBuilder = restClientBuilder;
return this;
}

public Builder webClientBuilder(WebClient.Builder webClientBuilder) {
Assert.notNull(webClientBuilder, "webClientBuilder cannot be null");
this.webClientBuilder = webClientBuilder;
return this;
}

public Builder responseErrorHandler(ResponseErrorHandler responseErrorHandler) {
Assert.notNull(responseErrorHandler, "responseErrorHandler cannot be null");
this.responseErrorHandler = responseErrorHandler;
return this;
}

public MistralAiApi build() {
return new MistralAiApi(this.baseUrl, this.apiKey, this.restClientBuilder, this.webClientBuilder,
this.responseErrorHandler);
}

}

}
Loading