= Titan Embeddings

Provides Bedrock Titan Embedding model.
link:https://aws.amazon.com/bedrock/titan/[Amazon Titan] foundation models (FMs) provide customers with a breadth of high-performing image, multimodal embeddings, and text model choices, via a fully managed API.
Amazon Titan models are created by AWS and pretrained on large datasets, making them powerful, general-purpose models built to support a variety of use cases, while also supporting the responsible use of AI.
Use them as is or privately customize them with your own data.

NOTE: Bedrock Titan Embedding supports Text and Image embedding.

NOTE: Bedrock Titan Embedding does NOT support batch embedding.

The https://aws.amazon.com/bedrock/titan/[AWS Bedrock Titan Model Page] and https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html[Amazon Bedrock User Guide] contains detailed information on how to use the AWS hosted model.

== Prerequisites

Refer to the xref:api/bedrock.adoc[Spring AI documentation on Amazon Bedrock] for setting up API access.

=== 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.
====

Add the `spring-ai-starter-model-bedrock` dependency to your project's Maven `pom.xml` file:

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

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

[source,gradle]
----
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-bedrock'
}
----

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

=== Enable Titan Embedding Support

By default, the Titan embedding model is disabled.
To enable it, set the `spring.ai.model.embedding` property to `bedrock-titan` in your application configuration:

[source,properties]
----
spring.ai.model.embedding=bedrock-titan
----

Alternatively, you can use Spring Expression Language (SpEL) to reference an environment variable:

[source,yaml]
----
# In application.yml
spring:
  ai:
    model:
      embedding: ${AI_MODEL_EMBEDDING}
----

[source,bash]
----
# In your environment or .env file
export AI_MODEL_EMBEDDING=bedrock-titan
----

You can also set this property using Java system properties when starting your application:

[source,shell]
----
java -Dspring.ai.model.embedding=bedrock-titan -jar your-application.jar
----

=== Embedding Properties

The prefix `spring.ai.bedrock.aws` is the property prefix to configure the connection to AWS Bedrock.

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

| spring.ai.bedrock.aws.region     | AWS region to use. | us-east-1
| spring.ai.bedrock.aws.access-key | AWS access key.  | -
| spring.ai.bedrock.aws.secret-key | AWS secret key.  | -
|====

[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=bedrock-titan (It is enabled by default)

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

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

The prefix `spring.ai.bedrock.titan.embedding` (defined in `BedrockTitanEmbeddingProperties`) is the property prefix that configures the embedding model implementation for Titan.

[cols="3,4,1", stripes=even]
|====
| Property | Description | Default
| spring.ai.bedrock.titan.embedding.enabled (Removed and no longer valid)             | Enable or disable support for Titan  embedding | false
| spring.ai.model.embedding              | Enable or disable support for Titan  embedding | bedrock-titan
| spring.ai.bedrock.titan.embedding.model                | The model id to use. See the `TitanEmbeddingModel` for the supported models.  | amazon.titan-embed-image-v1
|====

Supported values are: `amazon.titan-embed-image-v1`, `amazon.titan-embed-text-v1` and `amazon.titan-embed-text-v2:0`.
Model ID values can also be found in the https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html[AWS Bedrock documentation for base model IDs].

== Runtime Options [[embedding-options]]

The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanEmbeddingOptions.java[BedrockTitanEmbeddingOptions.java] provides model configurations, such as `input-type`.
On start-up, the default options can be configured with the `BedrockTitanEmbeddingModel(api).withInputType(type)` method or the `spring.ai.bedrock.titan.embedding.input-type` properties.

At run-time you can override the default options by adding new, request specific, options to the `EmbeddingRequest` call.
For example to override the default temperature for a specific request:

[source,java]
----
EmbeddingResponse embeddingResponse = embeddingModel.call(
    new EmbeddingRequest(List.of("Hello World", "World is big and salvation is near"),
        BedrockTitanEmbeddingOptions.builder()
        	.withInputType(InputType.TEXT)
        .build()));
----

== Sample Controller

https://start.spring.io/[Create] a new Spring Boot project and add the `spring-ai-starter-model-bedrock` to your pom (or gradle) dependencies.

Add a `application.properties` file, under the `src/main/resources` directory, to enable and configure the Titan Embedding model:

[source]
----
spring.ai.bedrock.aws.region=eu-central-1
spring.ai.bedrock.aws.access-key=${AWS_ACCESS_KEY_ID}
spring.ai.bedrock.aws.secret-key=${AWS_SECRET_ACCESS_KEY}

spring.ai.model.embedding=bedrock-titan
----

TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials.

This will create a `EmbeddingController` implementation that you can inject into your class.
Here is an example of a simple `@Controller` class that uses the chat model for text generations.

[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

The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanEmbeddingModel.java[BedrockTitanEmbeddingModel] implements the `EmbeddingModel` and uses the <<low-level-api>> to connect to the Bedrock Titan service.

Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file:

[source,xml]
----
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-bedrock</artifactId>
</dependency>
----

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

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

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

Next, create an https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanEmbeddingModel.java[BedrockTitanEmbeddingModel] and use it for text embeddings:

[source,java]
----
var titanEmbeddingApi = new TitanEmbeddingBedrockApi(
	TitanEmbeddingModel.TITAN_EMBED_IMAGE_V1.id(), Region.US_EAST_1.id());

var embeddingModel = new BedrockTitanEmbeddingModel(this.titanEmbeddingApi);

EmbeddingResponse embeddingResponse = this.embeddingModel
	.embedForResponse(List.of("Hello World")); // NOTE titan does not support batch embedding.
----

== Low-level TitanEmbeddingBedrockApi Client [[low-level-api]]

The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/api/TitanEmbeddingBedrockApi.java[TitanEmbeddingBedrockApi] provides is lightweight Java client on top of AWS Bedrock https://docs.aws.amazon.com/bedrock/latest/userguide/titan-multiemb-models.html[Titan Embedding models].

Following class diagram illustrates the TitanEmbeddingBedrockApi interface and building blocks:

image::bedrock/bedrock-titan-embedding-low-level-api.jpg[align="center", width="500px"]

The TitanEmbeddingBedrockApi supports the `amazon.titan-embed-image-v1` and `amazon.titan-embed-image-v1` models for single and batch embedding computation.

Here is a simple snippet how to use the api programmatically:

[source,java]
----
TitanEmbeddingBedrockApi titanEmbedApi = new TitanEmbeddingBedrockApi(
		TitanEmbeddingModel.TITAN_EMBED_TEXT_V1.id(), Region.US_EAST_1.id());

TitanEmbeddingRequest request = TitanEmbeddingRequest.builder()
	.withInputText("I like to eat apples.")
	.build();

TitanEmbeddingResponse response = this.titanEmbedApi.embedding(this.request);
----

To embed an image you need to convert it into `base64` format:

[source,java]
----
TitanEmbeddingBedrockApi titanEmbedApi = new TitanEmbeddingBedrockApi(
		TitanEmbeddingModel.TITAN_EMBED_IMAGE_V1.id(), Region.US_EAST_1.id());

byte[] image = new DefaultResourceLoader()
	.getResource("classpath:/spring_framework.png")
	.getContentAsByteArray();


TitanEmbeddingRequest request = TitanEmbeddingRequest.builder()
	.withInputImage(Base64.getEncoder().encodeToString(this.image))
	.build();

TitanEmbeddingResponse response = this.titanEmbedApi.embedding(this.request);
----
