How to add multi-model support via Spring AI 1.0.0 custom configurations for Azure OpenAI?

Open
#3,475 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Stale
Tech stack
azure, java

Research direction

The issue provides an OpenAiConfig.java example and names AzureOpenAiChatModel, AzureOpenAiEmbeddingModel, and ChatClient. Start by checking the Spring AI 1.0.0 configuration entry points for these classes; done should be a documented, standard multi-model setup for Azure OpenAI.

Written by the indexing model from the issue text.

Description

status: waiting-for-triage

I've recently shifted from M5 to 1.0.0 and just wondering what can be done to create ChatClient for multiple mods.

I'm using Azure OpenAI based connection along with support for embedding model.

This setup is clunky as i moved from milestone to milestone rewriting everything. I’m looking for a standard way of creating clients with multi-model support.

Here's my code:

AIConfigurations.java

import com.azure.ai.openai.OpenAIClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenCredential;
import com.azure.core.util.ClientOptions;
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
import org.springframework.ai.azure.openai.AzureOpenAiChatOptions;
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupFile;
import reactor.core.publisher.Mono;

import java.time.OffsetDateTime;
import java.util.List;

import static com.azure.ai.openai.OpenAIServiceVersion.V2023_05_15;
import static io.micrometer.observation.ObservationRegistry.NOOP;
import static java.time.Duration.ofHours;
import static org.springframework.ai.document.MetadataMode.EMBED;

/**
 * Defines Gen AI configuration
 *
 */
@Configuration
public class OpenAiConfig {

    @Value("${spring.ai.azure.openai.endpoint:}")
    private String chatModelEndpoint;

    @Value("${spring.ai.azure.openai.chat.options.deployment-name:}")
    private String chatModelDeploymentName;

    @Value("${spring.ai.azure.openai.embedding.endpoint:}")
    private String embeddingModelEndpoint;

    @Value("${spring.ai.azure.openai.embedding.options.deployment-name:}")
    private String embeddingModelDeploymentName;

@Value("${spring.ai.azure.openai.chat.options.api-version:}")
    private String apiVersion;

    @Value("${spring.ai.azure.openai.token.lifetime:10}")
    private int tokenLifetime;

    @Value("#{'${template.file.paths}'.split(',')}")
    private List<String> templateFilePaths;

    private final AzureAuthenticationService azureAuthenticationService;

    /**
     * Constructs an OpenAiConfig instance with the provided AzureAuthenticationService.
     *
     * @param azureAuthenticationService AzureAuthenticationService to be used for fetching access tokens.
     */
    public OpenAiConfig(AzureAuthenticationService azureAuthenticationService) {
        this.azureAuthenticationService = azureAuthenticationService;
    }

    /**
     * Creates a TokenCredential bean that provides access tokens for Azure services.
     * The token is fetched from Microsoft Entra ID (formerly Azure AD) and has a configurable lifetime.
     *
     * @return TokenCredential instance that provides Azure access tokens
     */
    @Bean
    public TokenCredential tokenCredential() {
        return tokenRequestContext ->
                Mono.just(new AccessToken(azureAuthenticationService.fetchAccessToken(),
                        OffsetDateTime.now().plus(ofHours(tokenLifetime))));
    }

    /**
     * Creates an OpenAIClientBuilder configured with endpoint, credentials, and service options.
     * This builder is used to establish connections to Azure OpenAI services.
     *
     * @return OpenAIClientBuilder instance ready for creating OpenAI clients.
     */
    @Bean
    public OpenAIClientBuilder openAIClientBuilder() {
        return new OpenAIClientBuilder()
                .endpoint(chatModelEndpoint)
                .credential(tokenCredential())
                .serviceVersion(V2023_05_15)
                .clientOptions(new ClientOptions().setApplicationId("spring-ai"));
    }

    /**
     * Configures an AzureOpenAiChatModel with appropriate deployment settings and parameters.
     *
     * @param openAIClientBuilder The builder used to establish connections to Azure OpenAI.
     * @return AzureOpenAiChatModel instance with specified deployment settings
     */
    @Bean
    public AzureOpenAiChatModel azureOpenAiChatModel(OpenAIClientBuilder openAIClientBuilder) {
        return AzureOpenAiChatModel.builder()
                .openAIClientBuilder(openAIClientBuilder)
                .defaultOptions(AzureOpenAiChatOptions.builder()
                        .deploymentName(chatModelDeploymentName)
                        .build())
                .build();
    }

    /**
     * Creates a ChatClient that provides a high-level interface for interacting with Azure OpenAI.
     *
     * @param azureOpenAiChatModel the configured model to use for chat completions.
     * @return ChatClient instance ready for sending prompts and receiving completions
     */
    @Bean
    public ChatClient chatClient(AzureOpenAiChatModel azureOpenAiChatModel) {
        return ChatClient.create(azureOpenAiChatModel);
    }

    /**
     * Creates an OpenAIClient configured with endpoint, credentials, and service options.
     * This client is used for embedding operations with Azure OpenAI services.
     *
     * @return OpenAIClient instance ready for embedding operations.
     */
    @Bean
    public OpenAIClient openAIClient() {
        return new OpenAIClientBuilder()
                .endpoint(embeddingModelEndpoint)
                .credential(tokenCredential())
                .serviceVersion(V2023_05_15)
                .clientOptions(new ClientOptions().setApplicationId("spring-ai")).buildClient();
    }

    /**
     * Configures an AzureOpenAiEmbeddingModel with appropriate deployment settings and parameters.
     * This model is used for generating vector embeddings from text, which are essential for
     * document similarity search and retrieval operations.
     *
     * @param openAIClient The OpenAI client used to connect to Azure OpenAI services
     * @return AzureOpenAiEmbeddingModel instance configured for text embedding operations
     */
    @Bean
    public AzureOpenAiEmbeddingModel embeddingModel(OpenAIClient openAIClient) {
        return new AzureOpenAiEmbeddingModel(
                openAIClient,
                EMBED,
                AzureOpenAiEmbeddingOptions.builder()
                        .deploymentName(embeddingModelDeploymentName)
                        .user("user-6")
                        .build(),
                NOOP);
    }

    /**
     * Creates and configures an STGroup bean for template processing.
     *
     * @return STGroup instance initialized with the specified template file.
     */
    @Bean
    public STGroup promptTemplateGroup() {
        STGroup compositeGroup = new STGroup();
        for (String path : templateFilePaths) {
            compositeGroup.importTemplates(new STGroupFile(path.trim()));
        }
        return compositeGroup;
    }
}
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 10h
Merged PRs (30d)
5

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from spring-projects/spring-ai

All issues in spring-projects/spring-ai

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.