diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/cloud-bindings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/cloud-bindings.adoc index 53e4db80686..33b5acc6ab8 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/cloud-bindings.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/cloud-bindings.adoc @@ -12,7 +12,6 @@ Configuration for `api-key`, `uri`, `username`, `password`, etc. can be specifie To enable cloud binding support, include the following dependency in the application. - [source,xml] ---- @@ -42,6 +41,9 @@ The following are the components for which the cloud binding support is currentl | `Chroma Vecor Store` | `chroma` | `uri`, `username`, `passwor` | `spring.ai.vectorstore.chroma.client.host`, `spring.ai.vectorstore.chroma.client.port`, `spring.ai.vectorstore.chroma.client.username`, `spring.ai.vectorstore.chroma.client.host.password` +| `Mistral AI` +| `mistralai` | `api-key`, `uri` | `spring.ai.mistralai.api-key`, `spring.ai.mistralai.base-url` + | `Ollama` | `ollama` | `uri` | `spring.ai.ollama.base-url` diff --git a/spring-ai-spring-cloud-bindings/src/main/java/org/springframework/ai/bindings/MistralAiBindingsPropertiesProcessor.java b/spring-ai-spring-cloud-bindings/src/main/java/org/springframework/ai/bindings/MistralAiBindingsPropertiesProcessor.java new file mode 100644 index 00000000000..3a22a564fd2 --- /dev/null +++ b/spring-ai-spring-cloud-bindings/src/main/java/org/springframework/ai/bindings/MistralAiBindingsPropertiesProcessor.java @@ -0,0 +1,51 @@ +/* + * 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.bindings; + +import org.springframework.cloud.bindings.Binding; +import org.springframework.cloud.bindings.Bindings; +import org.springframework.cloud.bindings.boot.BindingsPropertiesProcessor; +import org.springframework.core.env.Environment; + +import java.util.Map; + +/** + * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s + * of type: {@value TYPE}. + * + * @author Thomas Vitale + */ +public class MistralAiBindingsPropertiesProcessor implements BindingsPropertiesProcessor { + + /** + * The {@link Binding} type that this processor is interested in: {@value}. + **/ + public static final String TYPE = "mistralai"; + + @Override + public void process(Environment environment, Bindings bindings, Map properties) { + if (!BindingsValidator.isTypeEnabled(environment, TYPE)) { + return; + } + + bindings.filterBindings(TYPE).forEach(binding -> { + properties.put("spring.ai.mistralai.api-key", binding.getSecret().get("api-key")); + properties.put("spring.ai.mistralai.base-url", binding.getSecret().get("uri")); + }); + } + +} diff --git a/spring-ai-spring-cloud-bindings/src/main/resources/META-INF/spring.factories b/spring-ai-spring-cloud-bindings/src/main/resources/META-INF/spring.factories index d8eef2b6c9b..9562cc660d5 100644 --- a/spring-ai-spring-cloud-bindings/src/main/resources/META-INF/spring.factories +++ b/spring-ai-spring-cloud-bindings/src/main/resources/META-INF/spring.factories @@ -1,6 +1,7 @@ # Binding Properties Factories org.springframework.cloud.bindings.boot.BindingsPropertiesProcessor=\ org.springframework.ai.bindings.ChromaBindingsPropertiesProcessor,\ +org.springframework.ai.bindings.MistralAiBindingsPropertiesProcessor,\ org.springframework.ai.bindings.OllamaBindingsPropertiesProcessor,\ org.springframework.ai.bindings.OpenAiBindingsPropertiesProcessor,\ org.springframework.ai.bindings.TanzuBindingsPropertiesProcessor,\ diff --git a/spring-ai-spring-cloud-bindings/src/test/java/org/springframework/ai/bindings/MistralAiBindingsPropertiesProcessorTests.java b/spring-ai-spring-cloud-bindings/src/test/java/org/springframework/ai/bindings/MistralAiBindingsPropertiesProcessorTests.java new file mode 100644 index 00000000000..05d175f3dc7 --- /dev/null +++ b/spring-ai-spring-cloud-bindings/src/test/java/org/springframework/ai/bindings/MistralAiBindingsPropertiesProcessorTests.java @@ -0,0 +1,66 @@ +/* + * 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.bindings; + +import org.junit.jupiter.api.Test; +import org.springframework.cloud.bindings.Binding; +import org.springframework.cloud.bindings.Bindings; +import org.springframework.mock.env.MockEnvironment; + +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.ai.bindings.BindingsValidator.CONFIG_PATH; + +/** + * Unit tests for {@link MistralAiBindingsPropertiesProcessor}. + * + * @author Thomas Vitale + */ +class MistralAiBindingsPropertiesProcessorTests { + + private final Bindings bindings = new Bindings(new Binding("test-name", Paths.get("test-path"), + // @formatter:off + Map.of( + Binding.TYPE, MistralAiBindingsPropertiesProcessor.TYPE, + "api-key", "demo", + "uri", "https://my.mistralai.example.net" + ))); + // @formatter:on + + private final MockEnvironment environment = new MockEnvironment(); + + private final Map properties = new HashMap<>(); + + @Test + void propertiesAreContributed() { + new MistralAiBindingsPropertiesProcessor().process(environment, bindings, properties); + assertThat(properties).containsEntry("spring.ai.mistralai.api-key", "demo"); + assertThat(properties).containsEntry("spring.ai.mistralai.base-url", "https://my.mistralai.example.net"); + } + + @Test + void whenDisabledThenPropertiesAreNotContributed() { + environment.setProperty("%s.mistralai.enabled".formatted(CONFIG_PATH), "false"); + + new MistralAiBindingsPropertiesProcessor().process(environment, bindings, properties); + assertThat(properties).isEmpty(); + } + +}