= Azure OpenAI Embeddings

Azure's OpenAI extends the OpenAI capabilities, offering safe text generation and Embeddings computation models for various task:

- Similarity embeddings are good at capturing semantic similarity between two or more pieces of text.
- Text search embeddings help measure whether long documents are relevant to a short query.
- Code search embeddings are useful for embedding code snippets and embedding natural language search queries.

The Azure OpenAI embeddings rely on `cosine similarity` to compute similarity between documents and a query.

== Prerequisites


The Azure OpenAI client offers three options to connect: using an Azure API key or using an OpenAI API Key, or using Microsoft Entra ID.


=== Azure API Key & Endpoint

Obtain your Azure OpenAI `endpoint` and `api-key` from the Azure OpenAI Service section on the https://portal.azure.com[Azure Portal].

Spring AI defines two configuration properties:

1. `spring.ai.azure.openai.api-key`: Set this to the value of the `API Key` obtained from Azure.
2. `spring.ai.azure.openai.endpoint`: Set this to the endpoint URL obtained when provisioning your model in Azure.

You can set these configuration properties in your `application.properties` or `application.yml` file:

[source,properties]
----
spring.ai.azure.openai.api-key=<your-azure-api-key>
spring.ai.azure.openai.endpoint=<your-azure-endpoint-url>
----

If you prefer to use environment variables for sensitive information like API keys, you can use Spring Expression Language (SpEL) in your configuration:

[source,yaml]
----
# In application.yml
spring:
  ai:
    azure:
      openai:
        api-key: ${AZURE_OPENAI_API_KEY}
        endpoint: ${AZURE_OPENAI_ENDPOINT}
----

[source,bash]
----
# In your environment or .env file
export AZURE_OPENAI_API_KEY=<your-azure-openai-api-key>
export AZURE_OPENAI_ENDPOINT=<your-azure-endpoint-url>
----

=== OpenAI Key

To authenticate with the OpenAI service (not Azure), provide an OpenAI API key.
This will automatically set the endpoint to https://api.openai.com/v1.

When using this approach, set the `spring.ai.azure.openai.chat.options.deployment-name` property to the name of the https://platform.openai.com/docs/models[OpenAI model] you wish to use.

In your application configuration:

[source,properties]
----
spring.ai.azure.openai.openai-api-key=<your-azure-openai-key>
spring.ai.azure.openai.chat.options.deployment-name=<openai-model-name>
----

Using environment variables with SpEL:

[source,yaml]
----
# In application.yml
spring:
  ai:
    azure:
      openai:
        openai-api-key: ${AZURE_OPENAI_API_KEY}
        chat:
          options:
            deployment-name: ${OPENAI_MODEL_NAME}
----

[source,bash]
----
# In your environment or .env file
export AZURE_OPENAI_API_KEY=<your-openai-key>
export OPENAI_MODEL_NAME=<openai-model-name>
----
=== Microsoft Entra ID

For keyless authentication using Microsoft Entra ID (formerly Azure Active Directory), set _only_ the `spring.ai.azure.openai.endpoint` configuration property and _not_ the api-key property mentioned above.

Finding only the endpoint property, your application will evaluate several different options for retrieving credentials and an `OpenAIClient` instance will be created using the token credentials.

NOTE: It is no longer necessary to create a `TokenCredential` bean; it is configured for you automatically.

=== Add Repositories and BOM

Spring AI artifacts are published in Maven Central and Spring Snapshot repositories.
Refer to the xref:getting-started.adoc#artifact-repositories[Artifact Repositories] section to add these repositories to your build system.

To help with dependency management, Spring AI provides a BOM (bill of materials) to ensure that a consistent version of Spring AI is used throughout the entire project. Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build system.


== Auto-configuration

[NOTE]
====
There has been a significant change in the Spring AI auto-configuration, starter modules' artifact names.
Please refer to the https://docs.spring.io/spring-ai/reference/upgrade-notes.html[upgrade notes] for more information.
====

Spring AI provides Spring Boot auto-configuration for the Azure OpenAI Embedding Model.
To enable it add the following dependency to your project's Maven `pom.xml` file:

[source, xml]
----
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-azure-openai</artifactId>
</dependency>
----

or to your Gradle `build.gradle` build file.

[source,groovy]
----
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-azure-openai'
}
----

TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file.

=== Embedding Properties

The prefix `spring.ai.azure.openai` is the property prefix to configure the connection to Azure OpenAI.

[cols="3,5,1", stripes=even]
|====
| Property | Description | Default

| spring.ai.azure.openai.api-key |  The Key from Azure AI OpenAI `Keys and Endpoint` section under `Resource Management`  | -
| spring.ai.azure.openai.endpoint | The endpoint from the Azure AI OpenAI `Keys and Endpoint` section under `Resource Management` | -
| spring.ai.azure.openai.openai-api-key |  (non Azure) OpenAI API key. Used to authenticate with the OpenAI service, instead of Azure OpenAI. 
This automatically sets the endpoint to https://api.openai.com/v1. Use either `api-key` or `openai-api-key` property. 
With this configuration the `spring.ai.azure.openai.embedding.options.deployment-name` is threated as an https://platform.openai.com/docs/models[OpenAi Model] name.| -
|====


[NOTE]
====
Enabling and disabling of the embedding auto-configurations are now configured via top level properties with the prefix `spring.ai.model.embedding`.

To enable, spring.ai.model.embedding=azure-openai (It is enabled by default)

To disable, spring.ai.model.embedding=none (or any value which doesn't match azure-openai)

This change is done to allow configuration of multiple models.
====

The prefix `spring.ai.azure.openai.embedding` is the property prefix that configures the `EmbeddingModel` implementation for Azure OpenAI

[cols="3,5,1", stripes=even]
|====
| Property | Description | Default

| spring.ai.azure.openai.embedding.enabled (Removed and no longer valid) | Enable Azure OpenAI embedding model.  | true
| spring.ai.model.embedding | Enable Azure OpenAI embedding model.  | azure-openai
| spring.ai.azure.openai.embedding.metadata-mode | Document content extraction mode    | EMBED
| spring.ai.azure.openai.embedding.options.deployment-name | This is the value of the 'Deployment Name' as presented in the Azure AI Portal | text-embedding-ada-002
| spring.ai.azure.openai.embedding.options.user | An identifier for the caller or end user of the operation. This may be used for tracking or rate-limiting purposes. | -
|====

TIP: All properties prefixed with `spring.ai.azure.openai.embedding.options` can be overridden at runtime by adding a request specific <<embedding-options>> to the `EmbeddingRequest` call.

== Runtime Options [[embedding-options]]

The `AzureOpenAiEmbeddingOptions` provides the configuration information for the embedding requests.
The `AzureOpenAiEmbeddingOptions` offers a builder to create the options.

At start time use the `AzureOpenAiEmbeddingModel` constructor to set the  default options used for all embedding requests.
At run-time you can override the default options, by passing a `AzureOpenAiEmbeddingOptions` instance with your to the  `EmbeddingRequest` request.

For example to override the default model name for a specific request:

[source,java]
----
EmbeddingResponse embeddingResponse = embeddingModel.call(
    new EmbeddingRequest(List.of("Hello World", "World is big and salvation is near"),
        AzureOpenAiEmbeddingOptions.builder()
        .model("Different-Embedding-Model-Deployment-Name")
        .build()));
----


== Sample Code

This will create a `EmbeddingModel` implementation that you can inject into your class.
Here is an example of a simple `@Controller` class that uses the `EmbeddingModel` implementation.

[source,application.properties]
----
spring.ai.azure.openai.api-key=YOUR_API_KEY
spring.ai.azure.openai.endpoint=YOUR_ENDPOINT
spring.ai.azure.openai.embedding.options.model=text-embedding-ada-002
----

[source,java]
----
@RestController
public class EmbeddingController {

    private final EmbeddingModel embeddingModel;

    @Autowired
    public EmbeddingController(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    @GetMapping("/ai/embedding")
    public Map embed(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        EmbeddingResponse embeddingResponse = this.embeddingModel.embedForResponse(List.of(message));
        return Map.of("embedding", embeddingResponse);
    }
}
----

== Manual Configuration

If you prefer not to use the Spring Boot auto-configuration, you can manually configure the `AzureOpenAiEmbeddingModel` in your application.
For this add the `spring-ai-azure-openai` dependency to your project's Maven `pom.xml` file:
[source, xml]
----
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-azure-openai</artifactId>
</dependency>
----

or to your Gradle `build.gradle` build file.

[source,gradle]
----
dependencies {
    implementation 'org.springframework.ai:spring-ai-azure-openai'
}
----

TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file.

NOTE: The `spring-ai-azure-openai` dependency also provide the access to the `AzureOpenAiEmbeddingModel`. For more information about the `AzureOpenAiChatModel` refer to the link:../embeddings/azure-openai-embeddings.html[Azure OpenAI Embeddings] section.

Next, create an `AzureOpenAiEmbeddingModel` instance and use it to compute the similarity between two input texts:

[source,java]
----
var openAIClient = OpenAIClientBuilder()
        .credential(new AzureKeyCredential(System.getenv("AZURE_OPENAI_API_KEY")))
		.endpoint(System.getenv("AZURE_OPENAI_ENDPOINT"))
		.buildClient();

var embeddingModel = new AzureOpenAiEmbeddingModel(this.openAIClient)
    .withDefaultOptions(AzureOpenAiEmbeddingOptions.builder()
        .model("text-embedding-ada-002")
        .user("user-6")
        .build());

EmbeddingResponse embeddingResponse = this.embeddingModel
	.embedForResponse(List.of("Hello World", "World is big and salvation is near"));
----

NOTE: the `text-embedding-ada-002` is actually the `Deployment Name` as presented in the Azure AI Portal.

