diff --git a/models/spring-ai-oci-genai/README.md b/models/spring-ai-oci-genai/README.md
new file mode 100644
index 00000000000..16d73d51854
--- /dev/null
+++ b/models/spring-ai-oci-genai/README.md
@@ -0,0 +1 @@
+[Oracle Cloud Infrastructure GenAI Documentation](https://docs.oracle.com/en-us/iaas/Content/generative-ai/overview.htm)
diff --git a/models/spring-ai-oci-genai/pom.xml b/models/spring-ai-oci-genai/pom.xml
new file mode 100644
index 00000000000..fc007e9f9b3
--- /dev/null
+++ b/models/spring-ai-oci-genai/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.ai</groupId>
+        <artifactId>spring-ai</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <artifactId>spring-ai-oci-genai</artifactId>
+    <packaging>jar</packaging>
+    <name>Spring AI Model - OCI GenAI</name>
+    <description>OCI GenAI models support</description>
+    <url>https://github.com/spring-projects/spring-ai</url>
+
+    <scm>
+        <url>https://github.com/spring-projects/spring-ai</url>
+        <connection>git://github.com/spring-projects/spring-ai.git</connection>
+        <developerConnection>git@github.com:spring-projects/spring-ai.git</developerConnection>
+    </scm>
+
+    <dependencies>
+
+        <!-- production dependencies -->
+        <dependency>
+            <groupId>org.springframework.ai</groupId>
+            <artifactId>spring-ai-core</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+
+		<dependency>
+			<groupId>com.oracle.oci.sdk</groupId>
+			<artifactId>oci-java-sdk-shaded-full</artifactId>
+			<version>${oci-sdk-version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.oracle.oci.sdk</groupId>
+			<artifactId>oci-java-sdk-addons-oke-workload-identity</artifactId>
+			<version>${oci-sdk-version}</version>
+		</dependency>
+
+        <!-- NOTE: Required only by the @ConstructorBinding. -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>org.springframework.ai</groupId>
+            <artifactId>spring-ai-test</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>
diff --git a/models/spring-ai-oci-genai/src/main/java/org/springframework/ai/oci/OCIEmbeddingModel.java b/models/spring-ai-oci-genai/src/main/java/org/springframework/ai/oci/OCIEmbeddingModel.java
new file mode 100644
index 00000000000..123e0705f36
--- /dev/null
+++ b/models/spring-ai-oci-genai/src/main/java/org/springframework/ai/oci/OCIEmbeddingModel.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.oci;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.oracle.bmc.generativeaiinference.GenerativeAiInference;
+import com.oracle.bmc.generativeaiinference.model.DedicatedServingMode;
+import com.oracle.bmc.generativeaiinference.model.EmbedTextDetails;
+import com.oracle.bmc.generativeaiinference.model.EmbedTextResult;
+import com.oracle.bmc.generativeaiinference.model.OnDemandServingMode;
+import com.oracle.bmc.generativeaiinference.model.ServingMode;
+import com.oracle.bmc.generativeaiinference.requests.EmbedTextRequest;
+import io.micrometer.observation.ObservationRegistry;
+import org.springframework.ai.chat.metadata.EmptyUsage;
+import org.springframework.ai.document.Document;
+import org.springframework.ai.embedding.AbstractEmbeddingModel;
+import org.springframework.ai.embedding.Embedding;
+import org.springframework.ai.embedding.EmbeddingOptions;
+import org.springframework.ai.embedding.EmbeddingRequest;
+import org.springframework.ai.embedding.EmbeddingResponse;
+import org.springframework.ai.embedding.EmbeddingResponseMetadata;
+import org.springframework.ai.embedding.observation.DefaultEmbeddingModelObservationConvention;
+import org.springframework.ai.embedding.observation.EmbeddingModelObservationContext;
+import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention;
+import org.springframework.ai.embedding.observation.EmbeddingModelObservationDocumentation;
+import org.springframework.ai.model.ModelOptionsUtils;
+import org.springframework.ai.observation.conventions.AiProvider;
+import org.springframework.util.Assert;
+
+/**
+ * {@link org.springframework.ai.embedding.EmbeddingModel} implementation that uses the
+ * OCI GenAI Embedding API.
+ *
+ * @author Anders Swanson
+ * @since 1.0.0
+ */
+public class OCIEmbeddingModel extends AbstractEmbeddingModel {
+
+	// The OCI GenAI API has a batch size of 96 for embed text requests.
+	private static final int EMBEDTEXT_BATCH_SIZE = 96;
+
+	private static final EmbeddingModelObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultEmbeddingModelObservationConvention();
+
+	private final GenerativeAiInference genAi;
+
+	private final OCIEmbeddingOptions options;
+
+	private final ObservationRegistry observationRegistry;
+
+	private final EmbeddingModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;
+
+	public OCIEmbeddingModel(GenerativeAiInference genAi, OCIEmbeddingOptions options) {
+		this(genAi, options, ObservationRegistry.NOOP);
+	}
+
+	public OCIEmbeddingModel(GenerativeAiInference genAi, OCIEmbeddingOptions options,
+			ObservationRegistry observationRegistry) {
+		Assert.notNull(genAi, "com.oracle.bmc.generativeaiinference.GenerativeAiInferenceClient must not be null");
+		Assert.notNull(options, "options must not be null");
+		Assert.notNull(observationRegistry, "observationRegistry must not be null");
+		this.genAi = genAi;
+		this.options = options;
+		this.observationRegistry = observationRegistry;
+	}
+
+	@Override
+	public EmbeddingResponse call(EmbeddingRequest request) {
+		Assert.notEmpty(request.getInstructions(), "At least one text is required!");
+		OCIEmbeddingOptions runtimeOptions = mergeOptions(request.getOptions(), options);
+		List<EmbedTextRequest> embedTextRequests = createRequests(request.getInstructions(), runtimeOptions);
+
+		EmbeddingModelObservationContext context = EmbeddingModelObservationContext.builder()
+			.embeddingRequest(request)
+			.provider(AiProvider.OCI_GENAI.value())
+			.requestOptions(runtimeOptions)
+			.build();
+
+		return EmbeddingModelObservationDocumentation.EMBEDDING_MODEL_OPERATION
+			.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> context,
+					this.observationRegistry)
+			.observe(() -> embedAllWithContext(embedTextRequests, context));
+	}
+
+	@Override
+	public float[] embed(Document document) {
+		return embed(document.getContent());
+	}
+
+	private EmbeddingResponse embedAllWithContext(List<EmbedTextRequest> embedTextRequests,
+			EmbeddingModelObservationContext context) {
+		String modelId = null;
+		AtomicInteger index = new AtomicInteger(0);
+		List<Embedding> embeddings = new ArrayList<>();
+		for (EmbedTextRequest embedTextRequest : embedTextRequests) {
+			EmbedTextResult embedTextResult = genAi.embedText(embedTextRequest).getEmbedTextResult();
+			if (modelId == null) {
+				modelId = embedTextResult.getModelId();
+			}
+			for (List<Float> e : embedTextResult.getEmbeddings()) {
+				float[] data = toFloats(e);
+				embeddings.add(new Embedding(data, index.getAndIncrement()));
+			}
+		}
+		EmbeddingResponseMetadata metadata = new EmbeddingResponseMetadata();
+		metadata.setModel(modelId);
+		metadata.setUsage(new EmptyUsage());
+		EmbeddingResponse embeddingResponse = new EmbeddingResponse(embeddings, metadata);
+		context.setResponse(embeddingResponse);
+		return embeddingResponse;
+	}
+
+	private ServingMode servingMode(OCIEmbeddingOptions embeddingOptions) {
+		return switch (embeddingOptions.getServingMode()) {
+			case "dedicated" -> DedicatedServingMode.builder().endpointId(embeddingOptions.getModel()).build();
+			case "on-demand" -> OnDemandServingMode.builder().modelId(embeddingOptions.getModel()).build();
+			default -> throw new IllegalArgumentException(
+					"unknown serving mode for OCI embedding model: " + embeddingOptions.getServingMode());
+		};
+	}
+
+	private List<EmbedTextRequest> createRequests(List<String> inputs, OCIEmbeddingOptions embeddingOptions) {
+		int size = inputs.size();
+		List<EmbedTextRequest> requests = new ArrayList<>();
+		for (int i = 0; i < inputs.size(); i += EMBEDTEXT_BATCH_SIZE) {
+			List<String> batch = inputs.subList(i, Math.min(i + EMBEDTEXT_BATCH_SIZE, size));
+			requests.add(createRequest(batch, embeddingOptions));
+		}
+		return requests;
+	}
+
+	private EmbedTextRequest createRequest(List<String> inputs, OCIEmbeddingOptions embeddingOptions) {
+		EmbedTextDetails embedTextDetails = EmbedTextDetails.builder()
+			.servingMode(servingMode(embeddingOptions))
+			.compartmentId(embeddingOptions.getCompartment())
+			.inputs(inputs)
+			.truncate(Objects.requireNonNullElse(embeddingOptions.getTruncate(), EmbedTextDetails.Truncate.End))
+			.build();
+		return EmbedTextRequest.builder().embedTextDetails(embedTextDetails).build();
+	}
+
+	private OCIEmbeddingOptions mergeOptions(EmbeddingOptions embeddingOptions, OCIEmbeddingOptions defaultOptions) {
+		if (embeddingOptions instanceof OCIEmbeddingOptions) {
+			OCIEmbeddingOptions dynamicOptions = ModelOptionsUtils.merge(embeddingOptions, defaultOptions,
+					OCIEmbeddingOptions.class);
+			if (dynamicOptions != null) {
+				return dynamicOptions;
+			}
+		}
+		return defaultOptions;
+	}
+
+	private float[] toFloats(List<Float> embedding) {
+		float[] floats = new float[embedding.size()];
+		for (int i = 0; i < embedding.size(); i++) {
+			floats[i] = embedding.get(i);
+		}
+		return floats;
+	}
+
+}
diff --git a/models/spring-ai-oci-genai/src/main/java/org/springframework/ai/oci/OCIEmbeddingOptions.java b/models/spring-ai-oci-genai/src/main/java/org/springframework/ai/oci/OCIEmbeddingOptions.java
new file mode 100644
index 00000000000..e72f5359f5f
--- /dev/null
+++ b/models/spring-ai-oci-genai/src/main/java/org/springframework/ai/oci/OCIEmbeddingOptions.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.oci;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.oracle.bmc.generativeaiinference.model.EmbedTextDetails;
+import org.springframework.ai.embedding.EmbeddingOptions;
+
+/**
+ * The configuration information for OCI embedding requests
+ *
+ * @author Anders Swanson
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class OCIEmbeddingOptions implements EmbeddingOptions {
+
+	private @JsonProperty("model") String model;
+
+	private @JsonProperty("compartment") String compartment;
+
+	private @JsonProperty("servingMode") String servingMode;
+
+	private @JsonProperty("truncate") EmbedTextDetails.Truncate truncate;
+
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	public static class Builder {
+
+		private final OCIEmbeddingOptions options = new OCIEmbeddingOptions();
+
+		public Builder withModel(String model) {
+			this.options.setModel(model);
+			return this;
+		}
+
+		public Builder withCompartment(String compartment) {
+			this.options.setCompartment(compartment);
+			return this;
+		}
+
+		public Builder withServingMode(String servingMode) {
+			this.options.setServingMode(servingMode);
+			return this;
+		}
+
+		public Builder withTruncate(EmbedTextDetails.Truncate truncate) {
+			this.options.truncate = truncate;
+			return this;
+		}
+
+		public OCIEmbeddingOptions build() {
+			return this.options;
+		}
+
+	}
+
+	public String getModel() {
+		return this.model;
+	}
+
+	/**
+	 * Not used by OCI GenAI.
+	 * @return null
+	 */
+	@Override
+	public Integer getDimensions() {
+		return null;
+	}
+
+	public void setModel(String model) {
+		this.model = model;
+	}
+
+	public String getCompartment() {
+		return compartment;
+	}
+
+	public void setCompartment(String compartment) {
+		this.compartment = compartment;
+	}
+
+	public String getServingMode() {
+		return servingMode;
+	}
+
+	public void setServingMode(String servingMode) {
+		this.servingMode = servingMode;
+	}
+
+	public EmbedTextDetails.Truncate getTruncate() {
+		return truncate;
+	}
+
+	public void setTruncate(EmbedTextDetails.Truncate truncate) {
+		this.truncate = truncate;
+	}
+
+}
diff --git a/models/spring-ai-oci-genai/src/test/java/org/springframework/ai/oci/BaseEmbeddingModelTest.java b/models/spring-ai-oci-genai/src/test/java/org/springframework/ai/oci/BaseEmbeddingModelTest.java
new file mode 100644
index 00000000000..5124bd734ee
--- /dev/null
+++ b/models/spring-ai-oci-genai/src/test/java/org/springframework/ai/oci/BaseEmbeddingModelTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.oci;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+
+import com.oracle.bmc.Region;
+import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
+import com.oracle.bmc.generativeaiinference.GenerativeAiInferenceClient;
+
+public class BaseEmbeddingModelTest {
+
+	public static final String OCI_COMPARTMENT_ID_KEY = "OCI_COMPARTMENT_ID";
+
+	public static final String EMBEDDING_MODEL_V2 = "cohere.embed-english-light-v2.0";
+
+	public static final String EMBEDDING_MODEL_V3 = "cohere.embed-english-v3.0";
+
+	private static final String CONFIG_FILE = Paths.get(System.getProperty("user.home"), ".oci", "config").toString();
+
+	private static final String PROFILE = "DEFAULT";
+
+	private static final String REGION = "us-chicago-1";
+
+	private static final String COMPARTMENT_ID = System.getenv(OCI_COMPARTMENT_ID_KEY);
+
+	/**
+	 * Create an OCIEmbeddingModel instance using a config file authentication provider.
+	 * @return OCIEmbeddingModel instance
+	 */
+	public static OCIEmbeddingModel get() {
+		try {
+			ConfigFileAuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(
+					CONFIG_FILE, PROFILE);
+			GenerativeAiInferenceClient aiClient = GenerativeAiInferenceClient.builder()
+				.region(Region.valueOf(REGION))
+				.build(authProvider);
+			OCIEmbeddingOptions options = OCIEmbeddingOptions.builder()
+				.withModel(EMBEDDING_MODEL_V2)
+				.withCompartment(COMPARTMENT_ID)
+				.withServingMode("on-demand")
+				.build();
+			return new OCIEmbeddingModel(aiClient, options);
+		}
+		catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}
diff --git a/models/spring-ai-oci-genai/src/test/java/org/springframework/ai/oci/OCIEmbeddingModelIT.java b/models/spring-ai-oci-genai/src/test/java/org/springframework/ai/oci/OCIEmbeddingModelIT.java
new file mode 100644
index 00000000000..8d25240bf82
--- /dev/null
+++ b/models/spring-ai-oci-genai/src/test/java/org/springframework/ai/oci/OCIEmbeddingModelIT.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.oci;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
+import org.springframework.ai.document.Document;
+import org.springframework.ai.embedding.EmbeddingRequest;
+import org.springframework.ai.embedding.EmbeddingResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.ai.oci.BaseEmbeddingModelTest.OCI_COMPARTMENT_ID_KEY;
+
+@EnabledIfEnvironmentVariable(named = OCI_COMPARTMENT_ID_KEY, matches = ".+")
+public class OCIEmbeddingModelIT extends BaseEmbeddingModelTest {
+
+	private final OCIEmbeddingModel embeddingModel = get();
+
+	private final List<String> content = List.of("How many states are in the USA?", "How many states are in India?");
+
+	@Test
+	void embed() {
+		float[] embedding = embeddingModel.embed(new Document("How many provinces are in Canada?"));
+		assertThat(embedding).hasSize(1024);
+	}
+
+	@Test
+	void call() {
+		EmbeddingResponse response = embeddingModel.call(new EmbeddingRequest(content, null));
+		assertThat(response).isNotNull();
+		assertThat(response.getResults()).hasSize(2);
+		assertThat(response.getMetadata().getModel()).isEqualTo(EMBEDDING_MODEL_V2);
+	}
+
+	@Test
+	void callWithOptions() {
+		EmbeddingResponse response = embeddingModel
+			.call(new EmbeddingRequest(content, OCIEmbeddingOptions.builder().withModel(EMBEDDING_MODEL_V3).build()));
+		assertThat(response).isNotNull();
+		assertThat(response.getResults()).hasSize(2);
+		assertThat(response.getMetadata().getModel()).isEqualTo(EMBEDDING_MODEL_V3);
+	}
+
+}
diff --git a/pom.xml b/pom.xml
index 3aa8ccff5d8..cdbfe43f26b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,7 @@
 		<module>models/spring-ai-huggingface</module>
 		<module>models/spring-ai-minimax</module>
 		<module>models/spring-ai-mistral-ai</module>
+		<module>models/spring-ai-oci-genai</module>
 		<module>models/spring-ai-ollama</module>
 		<module>models/spring-ai-openai</module>
 		<module>models/spring-ai-postgresml</module>
@@ -86,6 +87,7 @@
 		<module>spring-ai-spring-boot-starters/spring-ai-starter-huggingface</module>
 		<module>spring-ai-spring-boot-starters/spring-ai-starter-minimax</module>
 		<module>spring-ai-spring-boot-starters/spring-ai-starter-mistral-ai</module>
+		<module>spring-ai-spring-boot-starters/spring-ai-starter-oci-genai</module>
 		<module>spring-ai-spring-boot-starters/spring-ai-starter-ollama</module>
 		<module>spring-ai-spring-boot-starters/spring-ai-starter-openai</module>
 		<module>spring-ai-spring-boot-starters/spring-ai-starter-postgresml-embedding</module>
@@ -157,8 +159,10 @@
 		<awssdk.version>2.26.7</awssdk.version>
 
 		<jackson.version>2.16.1</jackson.version>
+
 		<djl.version>0.30.0</djl.version>
 		<onnxruntime.version>1.19.2</onnxruntime.version>
+		<oci-sdk-version>3.46.1</oci-sdk-version>
 		<com.google.cloud.version>26.41.0</com.google.cloud.version>
 		<qdrant.version>1.9.1</qdrant.version>
 		<spring-retry.version>2.0.5</spring-retry.version>
diff --git a/spring-ai-bom/pom.xml b/spring-ai-bom/pom.xml
index 805d8fbbb7c..838fabcce3b 100644
--- a/spring-ai-bom/pom.xml
+++ b/spring-ai-bom/pom.xml
@@ -76,6 +76,12 @@
                 <version>${project.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.springframework.ai</groupId>
+                <artifactId>spring-ai-oci-genai</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.springframework.ai</groupId>
                 <artifactId>spring-ai-ollama</artifactId>
@@ -313,6 +319,12 @@
                 <version>${project.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.springframework.ai</groupId>
+                <artifactId>spring-ai-oci-genai-spring-boot-starter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.springframework.ai</groupId>
                 <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
diff --git a/spring-ai-core/src/main/java/org/springframework/ai/observation/conventions/AiProvider.java b/spring-ai-core/src/main/java/org/springframework/ai/observation/conventions/AiProvider.java
index e3da38c6289..cb9a76aea12 100644
--- a/spring-ai-core/src/main/java/org/springframework/ai/observation/conventions/AiProvider.java
+++ b/spring-ai-core/src/main/java/org/springframework/ai/observation/conventions/AiProvider.java
@@ -34,7 +34,8 @@ public enum AiProvider {
 	OLLAMA("ollama"),
 	OPENAI("openai"),
 	SPRING_AI("spring_ai"),
-	VERTEX_AI("vertex_ai");
+	VERTEX_AI("vertex_ai"),
+	OCI_GENAI("oci_genai");
 
 	private final String value;
 
diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc
index 7c544adf656..873cce6f444 100644
--- a/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc
@@ -37,13 +37,13 @@
 // **** xref:api/chat/functions/zhipuai-chat-functions.adoc[Function Calling]
 *** xref:api/chat/watsonx-ai-chat.adoc[watsonx.AI]
 ** xref:api/embeddings.adoc[]
-*** xref:api/embeddings/azure-openai-embeddings.adoc[Azure OpenAI]
 *** xref:api/bedrock.adoc[Amazon Bedrock]
 **** xref:api/embeddings/bedrock-cohere-embedding.adoc[Cohere]
 **** xref:api/embeddings/bedrock-titan-embedding.adoc[Titan]
 *** xref:api/embeddings/azure-openai-embeddings.adoc[Azure OpenAI]
 *** xref:api/embeddings/mistralai-embeddings.adoc[Mistral AI]
 *** xref:api/embeddings/minimax-embeddings.adoc[MiniMax]
+*** xref:api/embeddings/oci-genai-embeddings.adoc[OCI GenAI]
 *** xref:api/embeddings/ollama-embeddings.adoc[Ollama]
 *** xref:api/embeddings/onnx.adoc[(ONNX) Transformers]
 *** xref:api/embeddings/openai-embeddings.adoc[OpenAI]
diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc
index f796b9a6f9b..f99c5442c60 100644
--- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc
@@ -168,3 +168,4 @@ Internally the various `EmbeddingModel` implementations use different low-level
 * xref:api/embeddings/vertexai-embeddings-text.adoc[Spring AI VertexAI Embeddings]
 * xref:api/embeddings/vertexai-embeddings-palm2.adoc[Spring AI VertexAI PaLM2 Embeddings]
 * xref:api/embeddings/mistralai-embeddings.adoc[Spring AI Mistral AI Embeddings]
+* xref:api/embeddings/oci-genai-embeddings.adoc[Spring AI Oracle Cloud Infrastructure GenAI Embeddings]
diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/oci-genai-embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/oci-genai-embeddings.adoc
new file mode 100644
index 00000000000..2912d393501
--- /dev/null
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/oci-genai-embeddings.adoc
@@ -0,0 +1,173 @@
+= Oracle Cloud Infrastructure (OCI) GenAI Embeddings
+
+https://www.oracle.com/artificial-intelligence/generative-ai/generative-ai-service/[OCI GenAI Service] offers text embedding with on-demand models, or dedicated AI clusters.
+
+The https://docs.oracle.com/en-us/iaas/Content/generative-ai/embed-models.htm[OCI Embedding Models Page] and https://docs.oracle.com/en-us/iaas/Content/generative-ai/use-playground-embed.htm[OCI Text Embeddings Page] provide detailed information about using and hosting embedding models on OCI.
+
+== Prerequisites
+
+=== Add Repositories and BOM
+
+Spring AI artifacts are published in Spring Milestone and Snapshot repositories.   Refer to the xref:getting-started.adoc#repositories[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
+
+Spring AI provides Spring Boot auto-configuration for the OCI GenAI Embedding Client.
+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-oci-genai-spring-boot-starter</artifactId>
+</dependency>
+----
+
+or to your Gradle `build.gradle` build file.
+
+[source,groovy]
+----
+dependencies {
+    implementation 'org.springframework.ai:spring-ai-oci-genai-spring-boot-starter'
+}
+----
+
+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.oci.genai` is the property prefix to configure the connection to OCI GenAI.
+
+[cols="3,5,1"]
+|====
+| Property | Description | Default
+
+| spring.ai.oci.genai.authenticationType |  The type of authentication to use when authenticating to OCI. May be `file`, `instance-principal`, `workload-identity`, or `simple`.  | file
+| spring.ai.oci.genai.region | OCI service region. | us-chicago-1
+| spring.ai.oci.genai.tenantId | OCI tenant OCID, used when authenticating with `simple` auth. | -
+| spring.ai.oci.genai.userId | OCI user OCID, used when authenticating with `simple` auth. | -
+| spring.ai.oci.genai.fingerprint | Private key fingerprint, used when authenticating with `simple` auth. | -
+| spring.ai.oci.genai.privateKey | Private key content, used when authenticating with `simple` auth. | -
+| spring.ai.oci.genai.passPhrase | Optional private key passphrase, used when authenticating with `simple` auth and a passphrase protected private key. | -
+| spring.ai.oci.genai.file | Path to OCI config file. Used when authenticating with `file` auth. | <user's home directory>/.oci/config
+| spring.ai.oci.genai.profile | OCI profile name. Used when authenticating with `file` auth. | DEFAULT
+| spring.ai.oci.genai.endpoint | Optional OCI GenAI endpoint. | -
+
+|====
+
+
+The prefix `spring.ai.oci.genai.embedding` is the property prefix that configures the `EmbeddingModel` implementation for OCI GenAI
+
+[cols="3,5,1"]
+|====
+| Property | Description | Default
+
+| spring.ai.oci.genai.embedding.enabled | Enable OCI GenAI embedding model.  | true
+| spring.ai.oci.genai.embedding.compartment | Model compartment OCID.    | -
+| spring.ai.oci.genai.embedding.servingMode | The model serving mode to be used. May be `on-demand`, or `dedicated`.  | on-demand
+| spring.ai.oci.genai.embedding.truncate | How to truncate text if it overruns the embedding context. May be `START`, or `END`.  | END
+| spring.ai.oci.genai.embedding.model | The model or model endpoint used for embeddings. | -
+|====
+
+TIP: All properties prefixed with `spring.ai.oci.genai.embedding.options` can be overridden at runtime by adding a request specific <<embedding-options>> to the `EmbeddingRequest` call.
+
+== Runtime Options [[embedding-options]]
+
+The `OCIEmbeddingOptions` provides the configuration information for the embedding requests.
+The `OCIEmbeddingOptions` offers a builder to create the options.
+
+At start time use the `OCIEmbeddingOptions` constructor to set the  default options used for all embedding requests.
+At run-time you can override the default options, by passing a `OCIEmbeddingOptions` 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"),
+        OCIEmbeddingOptions.builder()
+            .withModel("my-other-embedding-model")
+            .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.oci.genai.embedding.model=<your model>
+spring.ai.oci.genai.embedding.compartment=<your model compartment>
+----
+
+[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 `OCIEmbeddingModel` in your application.
+For this add the `spring-oci-genai-openai` dependency to your project's Maven `pom.xml` file:
+[source, xml]
+----
+<dependency>
+    <groupId>org.springframework.ai</groupId>
+    <artifactId>spring-oci-genai-openai</artifactId>
+</dependency>
+----
+
+or to your Gradle `build.gradle` build file.
+
+[source,gradle]
+----
+dependencies {
+    implementation 'org.springframework.ai:spring-oci-genai-openai'
+}
+----
+
+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 `OCIEmbeddingModel` instance and use it to compute the similarity between two input texts:
+
+[source,java]
+----
+final String EMBEDDING_MODEL = "cohere.embed-english-light-v2.0";
+final String CONFIG_FILE = Paths.get(System.getProperty("user.home"), ".oci", "config").toString();
+final String PROFILE = "DEFAULT";
+final String REGION = "us-chicago-1";
+final String COMPARTMENT_ID = System.getenv("OCI_COMPARTMENT_ID");
+
+var authProvider = new ConfigFileAuthenticationDetailsProvider(
+        CONFIG_FILE, PROFILE);
+var aiClient = GenerativeAiInferenceClient.builder()
+    .region(Region.valueOf(REGION))
+    .build(authProvider);
+var options = OCIEmbeddingOptions.builder()
+    .withModel(EMBEDDING_MODEL)
+    .withCompartment(COMPARTMENT_ID)
+    .withServingMode("on-demand")
+    .build();
+var embeddingModel = new OCIEmbeddingModel(aiClient, options);
+List<Double> embedding = embeddingModel.embed(new Document("How many provinces are in Canada?"));
+----
diff --git a/spring-ai-spring-boot-autoconfigure/pom.xml b/spring-ai-spring-boot-autoconfigure/pom.xml
index 250d6246ca3..9a0428fea01 100644
--- a/spring-ai-spring-boot-autoconfigure/pom.xml
+++ b/spring-ai-spring-boot-autoconfigure/pom.xml
@@ -63,6 +63,13 @@
 			<optional>true</optional>
 		</dependency>
 
+		<dependency>
+			<groupId>org.springframework.ai</groupId>
+			<artifactId>spring-ai-oci-genai</artifactId>
+			<version>${project.parent.version}</version>
+			<optional>true</optional>
+		</dependency>
+
 		<dependency>
 			<groupId>org.springframework.ai</groupId>
 			<artifactId>spring-ai-huggingface</artifactId>
@@ -425,6 +432,13 @@
 			<scope>test</scope>
 		</dependency>
 
+		<dependency>
+			<groupId>org.testcontainers</groupId>
+			<artifactId>oracle-free</artifactId>
+			<version>1.19.8</version>
+			<scope>test</scope>
+    </dependency>
+
 		<dependency>
 			<groupId>org.testcontainers</groupId>
 			<artifactId>junit-jupiter</artifactId>
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIConnectionProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIConnectionProperties.java
new file mode 100644
index 00000000000..6de993705da
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIConnectionProperties.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.autoconfigure.oci.genai;
+
+import java.nio.file.Paths;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Anders Swanson
+ */
+@ConfigurationProperties(OCIConnectionProperties.CONFIG_PREFIX)
+public class OCIConnectionProperties {
+
+	private static final String DEFAULT_PROFILE = "DEFAULT";
+
+	public static final String CONFIG_PREFIX = "spring.ai.oci.genai";
+
+	public enum AuthenticationType {
+
+		FILE("file"), INSTANCE_PRINCIPAL("instance-principal"), WORKLOAD_IDENTITY("workload-identity"),
+		SIMPLE("simple");
+
+		private final String authType;
+
+		AuthenticationType(String authType) {
+			this.authType = authType;
+		}
+
+		public String getAuthType() {
+			return this.authType;
+		}
+
+	}
+
+	private AuthenticationType authenticationType = AuthenticationType.FILE;
+
+	private String profile;
+
+	private String file = Paths.get(System.getProperty("user.home"), ".oci", "config").toString();
+
+	private String tenantId;
+
+	private String userId;
+
+	private String fingerprint;
+
+	private String privateKey;
+
+	private String passPhrase;
+
+	private String region = "us-chicago-1";
+
+	private String endpoint;
+
+	public String getRegion() {
+		return region;
+	}
+
+	public void setRegion(String region) {
+		this.region = region;
+	}
+
+	public String getPassPhrase() {
+		return passPhrase;
+	}
+
+	public void setPassPhrase(String passPhrase) {
+		this.passPhrase = passPhrase;
+	}
+
+	public String getPrivateKey() {
+		return privateKey;
+	}
+
+	public void setPrivateKey(String privateKey) {
+		this.privateKey = privateKey;
+	}
+
+	public String getFingerprint() {
+		return fingerprint;
+	}
+
+	public void setFingerprint(String fingerprint) {
+		this.fingerprint = fingerprint;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+
+	public void setUserId(String userId) {
+		this.userId = userId;
+	}
+
+	public String getTenantId() {
+		return tenantId;
+	}
+
+	public void setTenantId(String tenantId) {
+		this.tenantId = tenantId;
+	}
+
+	public String getFile() {
+		return file;
+	}
+
+	public void setFile(String file) {
+		this.file = file;
+	}
+
+	public String getProfile() {
+		return StringUtils.hasText(profile) ? profile : DEFAULT_PROFILE;
+	}
+
+	public void setProfile(String profile) {
+		this.profile = profile;
+	}
+
+	public AuthenticationType getAuthenticationType() {
+		return authenticationType;
+	}
+
+	public void setAuthenticationType(AuthenticationType authenticationType) {
+		this.authenticationType = authenticationType;
+	}
+
+	public String getEndpoint() {
+		return endpoint;
+	}
+
+	public void setEndpoint(String endpoint) {
+		this.endpoint = endpoint;
+	}
+
+}
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIEmbeddingModelProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIEmbeddingModelProperties.java
new file mode 100644
index 00000000000..cc2ef2b5f11
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIEmbeddingModelProperties.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.autoconfigure.oci.genai;
+
+import com.oracle.bmc.generativeaiinference.model.EmbedTextDetails;
+import org.springframework.ai.oci.OCIEmbeddingOptions;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author Anders Swanson
+ */
+@ConfigurationProperties(OCIEmbeddingModelProperties.CONFIG_PREFIX)
+public class OCIEmbeddingModelProperties {
+
+	public static final String CONFIG_PREFIX = "spring.ai.oci.genai.embedding";
+
+	private ServingMode servingMode = ServingMode.ON_DEMAND;
+
+	private EmbedTextDetails.Truncate truncate = EmbedTextDetails.Truncate.End;
+
+	private String compartment;
+
+	private String model;
+
+	private boolean enabled;
+
+	public OCIEmbeddingOptions getEmbeddingOptions() {
+		return OCIEmbeddingOptions.builder()
+			.withCompartment(compartment)
+			.withModel(model)
+			.withServingMode(servingMode.getMode())
+			.withTruncate(truncate)
+			.build();
+	}
+
+	public ServingMode getServingMode() {
+		return servingMode;
+	}
+
+	public void setServingMode(ServingMode servingMode) {
+		this.servingMode = servingMode;
+	}
+
+	public String getCompartment() {
+		return compartment;
+	}
+
+	public void setCompartment(String compartment) {
+		this.compartment = compartment;
+	}
+
+	public String getModel() {
+		return model;
+	}
+
+	public void setModel(String model) {
+		this.model = model;
+	}
+
+	public boolean isEnabled() {
+		return enabled;
+	}
+
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+	}
+
+	public EmbedTextDetails.Truncate getTruncate() {
+		return truncate;
+	}
+
+	public void setTruncate(EmbedTextDetails.Truncate truncate) {
+		this.truncate = truncate;
+	}
+
+}
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIGenAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIGenAiAutoConfiguration.java
new file mode 100644
index 00000000000..9e8a64059f5
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/OCIGenAiAutoConfiguration.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.autoconfigure.oci.genai;
+
+import java.io.IOException;
+
+import com.oracle.bmc.ClientConfiguration;
+import com.oracle.bmc.Region;
+import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.SimplePrivateKeySupplier;
+import com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider;
+import com.oracle.bmc.generativeaiinference.GenerativeAiInferenceClient;
+import com.oracle.bmc.retrier.RetryConfiguration;
+import org.springframework.ai.oci.OCIEmbeddingModel;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Anders Swanson
+ */
+@AutoConfiguration
+@ConditionalOnClass({ GenerativeAiInferenceClient.class, OCIEmbeddingModel.class })
+@EnableConfigurationProperties({ OCIConnectionProperties.class, OCIEmbeddingModelProperties.class })
+public class OCIGenAiAutoConfiguration {
+
+	@ConditionalOnMissingBean
+	@Bean
+	public GenerativeAiInferenceClient generativeAiInferenceClient(OCIConnectionProperties properties)
+			throws IOException {
+		ClientConfiguration clientConfiguration = ClientConfiguration.builder()
+			.retryConfiguration(RetryConfiguration.SDK_DEFAULT_RETRY_CONFIGURATION)
+			.build();
+		GenerativeAiInferenceClient.Builder builder = GenerativeAiInferenceClient.builder()
+			.configuration(clientConfiguration);
+		if (StringUtils.hasText(properties.getRegion())) {
+			builder.region(Region.valueOf(properties.getRegion()));
+		}
+		if (StringUtils.hasText(properties.getEndpoint())) {
+			builder.endpoint(properties.getEndpoint());
+		}
+		return builder.build(authenticationProvider(properties));
+	}
+
+	@Bean
+	@ConditionalOnProperty(prefix = OCIEmbeddingModelProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
+			matchIfMissing = true)
+	public OCIEmbeddingModel ociEmbeddingModel(GenerativeAiInferenceClient generativeAiClient,
+			OCIEmbeddingModelProperties properties) {
+		return new OCIEmbeddingModel(generativeAiClient, properties.getEmbeddingOptions());
+	}
+
+	private static BasicAuthenticationDetailsProvider authenticationProvider(OCIConnectionProperties properties)
+			throws IOException {
+		return switch (properties.getAuthenticationType()) {
+			case FILE -> new ConfigFileAuthenticationDetailsProvider(properties.getFile(), properties.getProfile());
+			case INSTANCE_PRINCIPAL -> InstancePrincipalsAuthenticationDetailsProvider.builder().build();
+			case WORKLOAD_IDENTITY -> OkeWorkloadIdentityAuthenticationDetailsProvider.builder().build();
+			case SIMPLE -> SimpleAuthenticationDetailsProvider.builder()
+				.userId(properties.getUserId())
+				.tenantId(properties.getTenantId())
+				.fingerprint(properties.getFingerprint())
+				.privateKeySupplier(new SimplePrivateKeySupplier(properties.getPrivateKey()))
+				.passPhrase(properties.getPassPhrase())
+				.region(Region.valueOf(properties.getRegion()))
+				.build();
+		};
+	}
+
+}
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/ServingMode.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/ServingMode.java
new file mode 100644
index 00000000000..7cb2299a2c8
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/oci/genai/ServingMode.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.autoconfigure.oci.genai;
+
+/**
+ * @author Anders Swanson
+ */
+public enum ServingMode {
+
+	ON_DEMAND("on-demand"), DEDICATED("dedicated");
+
+	private final String mode;
+
+	ServingMode(String mode) {
+		this.mode = mode;
+	}
+
+	public String getMode() {
+		return mode;
+	}
+
+}
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index 9fe46cc2609..d5b849aa3c8 100644
--- a/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,5 +1,6 @@
 org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration
 org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration
+org.springframework.ai.autoconfigure.oci.genai.OCIGenAiAutoConfiguration
 org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration
 org.springframework.ai.autoconfigure.transformers.TransformersEmbeddingModelAutoConfiguration
 org.springframework.ai.autoconfigure.huggingface.HuggingfaceChatAutoConfiguration
diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/oci/genai/OCIGenAiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/oci/genai/OCIGenAiAutoConfigurationIT.java
new file mode 100644
index 00000000000..d67a8e0e715
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/oci/genai/OCIGenAiAutoConfigurationIT.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.autoconfigure.oci.genai;
+
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
+import org.springframework.ai.embedding.EmbeddingRequest;
+import org.springframework.ai.embedding.EmbeddingResponse;
+import org.springframework.ai.oci.OCIEmbeddingModel;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@EnabledIfEnvironmentVariable(named = OCIGenAiAutoConfigurationIT.COMPARTMENT_ID_KEY, matches = ".+")
+public class OCIGenAiAutoConfigurationIT {
+
+	public static final String COMPARTMENT_ID_KEY = "OCI_COMPARTMENT_ID";
+
+	private final String CONFIG_FILE = Paths.get(System.getProperty("user.home"), ".oci", "config").toString();
+
+	private final String COMPARTMENT_ID = System.getenv(COMPARTMENT_ID_KEY);
+
+	private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withPropertyValues(
+	// @formatter:off
+				"spring.ai.oci.genai.authenticationType=file",
+				"spring.ai.oci.genai.file=" + CONFIG_FILE,
+				"spring.ai.oci.genai.embedding.compartment=" + COMPARTMENT_ID,
+				"spring.ai.oci.genai.embedding.servingMode=on-demand",
+				"spring.ai.oci.genai.embedding.model=cohere.embed-english-light-v2.0"
+				// @formatter:on
+	).withConfiguration(AutoConfigurations.of(OCIGenAiAutoConfiguration.class));
+
+	@Test
+	void embeddings() {
+		contextRunner.run(context -> {
+			OCIEmbeddingModel embeddingModel = context.getBean(OCIEmbeddingModel.class);
+			assertThat(embeddingModel).isNotNull();
+			EmbeddingResponse response = embeddingModel
+				.call(new EmbeddingRequest(List.of("There are 50 states in the USA", "Canada has 10 provinces"), null));
+			assertThat(response).isNotNull();
+			assertThat(response.getResults()).hasSize(2);
+		});
+	}
+
+}
diff --git a/spring-ai-spring-boot-starters/spring-ai-starter-oci-genai/pom.xml b/spring-ai-spring-boot-starters/spring-ai-starter-oci-genai/pom.xml
new file mode 100644
index 00000000000..2fd347de32d
--- /dev/null
+++ b/spring-ai-spring-boot-starters/spring-ai-starter-oci-genai/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.springframework.ai</groupId>
+		<artifactId>spring-ai</artifactId>
+		<version>1.0.0-SNAPSHOT</version>
+		<relativePath>../../pom.xml</relativePath>
+	</parent>
+	<artifactId>spring-ai-oci-genai-spring-boot-starter</artifactId>
+	<packaging>jar</packaging>
+	<name>Spring AI Starter - OCI GenAI</name>
+	<description>Spring AI OCI GenAI Auto Configuration</description>
+	<url>https://github.com/spring-projects/spring-ai</url>
+
+	<scm>
+		<url>https://github.com/spring-projects/spring-ai</url>
+		<connection>git://github.com/spring-projects/spring-ai.git</connection>
+		<developerConnection>git@github.com:spring-projects/spring-ai.git</developerConnection>
+	</scm>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.ai</groupId>
+			<artifactId>spring-ai-spring-boot-autoconfigure</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.ai</groupId>
+			<artifactId>spring-ai-oci-genai</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+	</dependencies>
+</project>