Skip to content
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

Introduce Mistral AI support #32

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

ThomasVitale
Copy link
Collaborator

  • Configure MistralAiClient using the Spring HTTP infrastructure
  • Define auto-configuration for using Mistral AI chat and embedding models in Spring Boot
  • Create a Spring Boot starter to provide the integration with Mistral AI

* Configure MistralAiClient using the Spring HTTP infrastructure
* Define auto-configuration for using Mistral AI chat and embedding models in Spring Boot
* Create a Spring Boot starter to provide the integration with Mistral AI

Signed-off-by: Thomas Vitale <[email protected]>
@ThomasVitale ThomasVitale requested a review from langchain4j July 6, 2024 09:59
@ThomasVitale
Copy link
Collaborator Author

The integration tests only run when there's a MISTRAL_AI_API_KEY environment variable defined.

@ThomasVitale
Copy link
Collaborator Author

This change in core LangChain4j would enhance the Spring support for Mistral AI, including being able to use an auto configured RestClient. langchain4j/langchain4j#1416

Copy link
Owner

@langchain4j langchain4j left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ThomasVitale, thanks a lot!

BTW, how will this work together with langchain4j/langchain4j#1103?
With the proposed approach each new model provider will require adding it's own langchain4j-spring-{model-provider} module and have quite a lot of duplication. (The aim of langchain4j/langchain4j#1103 is to have model-agnostic http clients that can plug into any model, so one does not have to re-implement client code over and over again)

.toSingleValueMap()
.entrySet()
.stream()
.filter(e -> !e.getKey().equals(HttpHeaders.AUTHORIZATION))
Copy link
Owner

@langchain4j langchain4j Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are also X-Auth-Token and X-API-KEY common auth headers (they can also be written in different cases)

@Override
public MistralAiChatCompletionResponse chatCompletion(MistralAiChatCompletionRequest chatCompletionRequest) {
Assert.notNull(chatCompletionRequest, "chatCompletionRequest cannot be null");
Assert.isTrue(!chatCompletionRequest.getStream(), "stream mode must be disabled");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
Assert.isTrue(!chatCompletionRequest.getStream(), "stream mode must be disabled");
Assert.isFalse(chatCompletionRequest.getStream(), "stream mode must be disabled");

Assert.notNull(chatCompletionRequest, "chatCompletionRequest cannot be null");
Assert.isTrue(!chatCompletionRequest.getStream(), "stream mode must be disabled");

logger.debug("Sending chat completion request: {}", chatCompletionRequest);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required? It is already logged in HttpLoggingInterceptor
(same for other methods below)

* Adapted from MistralAiChatModelIT in the LangChain4j project.
*/
@EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".*")
class MistralAiChatModelIT {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about making MistralAiChatModelIT in main repo abstract and inherit from it here (instead of having duplicate tests), similar to EmbeddingStoreIT?

@ConfigurationProperties(prefix = MistralAiChatProperties.CONFIG_PREFIX)
public class MistralAiChatProperties {

public static final String CONFIG_PREFIX = "langchain4j.mistralai.chat";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
public static final String CONFIG_PREFIX = "langchain4j.mistralai.chat";
public static final String CONFIG_PREFIX = "langchain4j.mistral-ai.chat-model";

/**
* What sampling temperature to use, between 0.0 and 1.0. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or "top_p" but not both.
*/
private Double temperature = 0.7;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to set default values here? (except for the mandatory params (model)).
I would avoid setting defaults here

@ConfigurationProperties(prefix = MistralAiEmbeddingProperties.CONFIG_PREFIX)
public class MistralAiEmbeddingProperties {

public static final String CONFIG_PREFIX = "langchain4j.mistralai.embedding";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static final String CONFIG_PREFIX = "langchain4j.mistralai.embedding";
public static final String CONFIG_PREFIX = "langchain4j.mistral-ai.embedding-model";

@ConfigurationProperties(MistralAiProperties.CONFIG_PREFIX)
public class MistralAiProperties {

public static final String CONFIG_PREFIX = "langchain4j.mistralai";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static final String CONFIG_PREFIX = "langchain4j.mistralai";
public static final String CONFIG_PREFIX = "langchain4j.mistral-ai";

class MistralAiAutoConfigurationIT {

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("langchain4j.mistralai.client.apiKey=" + System.getenv("MISTRAL_AI_API_KEY"))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having apiKey and other client parameters configured once for all models simplifies configuration a bit, but it is not flexible enough: one cannot use different API keys for different models, or e.g. enable logging responses for chat model only (because embedding model responses are huge and make little sense to log), or set different timeouts for different model types (chat models are much-much slower than embedding models)

@ThomasVitale
Copy link
Collaborator Author

@langchain4j thanks so much for the review and sorry for the late answer. I'm trying to find the time to look more into the new HTTP client abstractions in Core to rethink what I've done in this PR.

@langchain4j
Copy link
Owner

@ThomasVitale thanks a lot in advance! BTW langchain4j/langchain4j#1103 is not set in stone, so feel free to suggest changes if you see the need!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants