Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.ResponseErrorHandler;
Expand All @@ -38,10 +39,10 @@
* @author Ilayaperumal Gopinathan
* @since 0.8.0
*/
@AutoConfiguration
@AutoConfiguration(after = { RestClientAutoConfiguration.class, WebClientAutoConfiguration.class,
SpringAiRetryAutoConfiguration.class })
@ConditionalOnClass(OllamaApi.class)
@EnableConfigurationProperties(OllamaConnectionProperties.class)
@ImportAutoConfiguration(classes = { SpringAiRetryAutoConfiguration.class })
public class OllamaApiAutoConfiguration {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@
import org.springframework.ai.ollama.management.PullModelStrategy;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.support.RetryTemplate;
Expand All @@ -51,13 +48,11 @@
* @author Jonghoon Park
* @since 0.8.0
*/
@AutoConfiguration(after = { RestClientAutoConfiguration.class, ToolCallingAutoConfiguration.class })
@AutoConfiguration(after = { OllamaApiAutoConfiguration.class, ToolCallingAutoConfiguration.class })
@ConditionalOnClass(OllamaChatModel.class)
@ConditionalOnProperty(name = SpringAIModelProperties.CHAT_MODEL, havingValue = SpringAIModels.OLLAMA,
matchIfMissing = true)
@EnableConfigurationProperties({ OllamaChatProperties.class, OllamaInitializationProperties.class })
@ImportAutoConfiguration(classes = { OllamaApiAutoConfiguration.class, RestClientAutoConfiguration.class,
ToolCallingAutoConfiguration.class, WebClientAutoConfiguration.class })
public class OllamaChatAutoConfiguration {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@
import org.springframework.ai.ollama.management.PullModelStrategy;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

Expand All @@ -45,13 +42,11 @@
* @author Ilayaperumal Gopinathan
* @since 0.8.0
*/
@AutoConfiguration(after = RestClientAutoConfiguration.class)
@AutoConfiguration(after = OllamaApiAutoConfiguration.class)
@ConditionalOnClass(OllamaEmbeddingModel.class)
@ConditionalOnProperty(name = SpringAIModelProperties.EMBEDDING_MODEL, havingValue = SpringAIModels.OLLAMA,
matchIfMissing = true)
@EnableConfigurationProperties({ OllamaEmbeddingProperties.class, OllamaInitializationProperties.class })
@ImportAutoConfiguration(classes = { OllamaApiAutoConfiguration.class, RestClientAutoConfiguration.class,
WebClientAutoConfiguration.class })
public class OllamaEmbeddingAutoConfiguration {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.ollama.OllamaContainer;

import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.management.ModelManagementOptions;
import org.springframework.ai.ollama.management.OllamaModelManager;
import org.springframework.ai.ollama.management.PullModelStrategy;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.util.Assert;

@Testcontainers
Expand Down Expand Up @@ -112,4 +116,15 @@ private static void ensureModelIsPresent(final OllamaApi ollamaApi, final String
ollamaModelManager.pullModel(model, PullModelStrategy.WHEN_MISSING);
}

public static AutoConfigurations ollamaAutoConfig(Class<?>... additionalAutoConfigurations) {
Class<?>[] dependencies = new Class[] { OllamaApiAutoConfiguration.class, RestClientAutoConfiguration.class,
SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class };
Class<?>[] allAutoConfigurations = new Class[dependencies.length + additionalAutoConfigurations.length];
System.arraycopy(dependencies, 0, allAutoConfigurations, 0, dependencies.length);
System.arraycopy(additionalAutoConfigurations, 0, allAutoConfigurations, dependencies.length,
additionalAutoConfigurations.length);

return AutoConfigurations.of(allAutoConfigurations);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaModel;
import org.springframework.ai.ollama.management.OllamaModelManager;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -55,7 +54,7 @@ public class OllamaChatAutoConfigurationIT extends BaseOllamaIT {
"spring.ai.ollama.chat.options.temperature=0.5",
"spring.ai.ollama.chat.options.topK=10")
// @formatter:on
.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class));
.withConfiguration(ollamaAutoConfig(OllamaChatAutoConfiguration.class));

private final UserMessage userMessage = new UserMessage("What's the capital of Denmark?");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@

import org.junit.jupiter.api.Test;

import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -43,8 +40,7 @@ public void propertiesTest() {
"spring.ai.ollama.chat.options.topK=123")
// @formatter:on

.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
RestClientAutoConfiguration.class, OllamaChatAutoConfiguration.class))
.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaChatAutoConfiguration.class))
.run(context -> {
var chatProperties = context.getBean(OllamaChatProperties.class);
var connectionProperties = context.getBean(OllamaConnectionProperties.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaModel;
import org.springframework.ai.ollama.management.OllamaModelManager;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -45,8 +43,7 @@ public class OllamaEmbeddingAutoConfigurationIT extends BaseOllamaIT {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.ai.ollama.embedding.options.model=" + MODEL_NAME,
"spring.ai.ollama.base-url=" + getBaseUrl())
.withConfiguration(
AutoConfigurations.of(RestClientAutoConfiguration.class, OllamaEmbeddingAutoConfiguration.class));
.withConfiguration(ollamaAutoConfig(OllamaEmbeddingAutoConfiguration.class));

@BeforeAll
public static void beforeAll() throws IOException, InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@

import org.junit.jupiter.api.Test;

import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -42,8 +39,7 @@ public void propertiesTest() {
// @formatter:on
)

.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
RestClientAutoConfiguration.class, OllamaEmbeddingAutoConfiguration.class))
.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaEmbeddingAutoConfiguration.class))
.run(context -> {
var embeddingProperties = context.getBean(OllamaEmbeddingProperties.class);
var connectionProperties = context.getBean(OllamaConnectionProperties.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.OllamaEmbeddingModel;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -36,19 +35,20 @@ public class OllamaModelConfigurationTests {

@Test
void chatModelActivation() {
this.contextRunner.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class)).run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaChatModel.class)).isNotEmpty();
});
this.contextRunner.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaChatAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaChatModel.class)).isNotEmpty();
});

this.contextRunner.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class))
this.contextRunner.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaChatAutoConfiguration.class))
.withPropertyValues("spring.ai.model.chat=none")
.run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isEmpty();
assertThat(context.getBeansOfType(OllamaChatModel.class)).isEmpty();
});

this.contextRunner.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class))
this.contextRunner.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaChatAutoConfiguration.class))
.withPropertyValues("spring.ai.model.chat=ollama")
.run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty();
Expand All @@ -60,20 +60,20 @@ void chatModelActivation() {

@Test
void embeddingModelActivation() {
this.contextRunner.withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class))
this.contextRunner.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaEmbeddingAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaEmbeddingModel.class)).isNotEmpty();
});

this.contextRunner.withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class))
this.contextRunner.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaEmbeddingAutoConfiguration.class))
.withPropertyValues("spring.ai.model.embedding=none")
.run(context -> {
assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isEmpty();
assertThat(context.getBeansOfType(OllamaEmbeddingModel.class)).isEmpty();
});

this.contextRunner.withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class))
this.contextRunner.withConfiguration(BaseOllamaIT.ollamaAutoConfig(OllamaEmbeddingAutoConfiguration.class))
.withPropertyValues("spring.ai.model.embedding=ollama")
.run(context -> {
assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.springframework.ai.ollama.api.OllamaChatOptions;
import org.springframework.ai.ollama.api.OllamaModel;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -54,7 +53,7 @@ public class FunctionCallbackInPromptIT extends BaseOllamaIT {
"spring.ai.ollama.chat.options.temperature=0.5",
"spring.ai.ollama.chat.options.topK=10")
// @formatter:on
.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class));
.withConfiguration(ollamaAutoConfig(OllamaChatAutoConfiguration.class));

@BeforeAll
public static void beforeAll() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import org.springframework.ai.ollama.api.OllamaChatOptions;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -58,7 +57,7 @@ public class OllamaFunctionCallbackIT extends BaseOllamaIT {
"spring.ai.ollama.chat.options.temperature=0.5",
"spring.ai.ollama.chat.options.topK=10")
// @formatter:on
.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class))
.withConfiguration(ollamaAutoConfig(OllamaChatAutoConfiguration.class))
.withUserConfiguration(Config.class);

@BeforeAll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import org.springframework.ai.ollama.api.OllamaModel;
import org.springframework.ai.support.ToolCallbacks;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -65,7 +64,7 @@ public class OllamaFunctionToolBeanIT extends BaseOllamaIT {
"spring.ai.ollama.chat.options.temperature=0.5",
"spring.ai.ollama.chat.options.topK=10")
// @formatter:on
.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class))
.withConfiguration(ollamaAutoConfig(OllamaChatAutoConfiguration.class))
.withUserConfiguration(Config.class);

@BeforeAll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class FunctionCallbackResolverKotlinIT : BaseOllamaIT() {
"spring.ai.ollama.chat.options.temperature=0.5",
"spring.ai.ollama.chat.options.topK=10"
)
.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration::class.java))
.withConfiguration(ollamaAutoConfig(OllamaChatAutoConfiguration::class.java))
.withUserConfiguration(Config::class.java)

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import org.springframework.ai.model.ollama.autoconfigure.BaseOllamaIT
import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration
import org.springframework.ai.model.tool.ToolCallingChatOptions
import org.springframework.ai.ollama.OllamaChatModel
import org.springframework.boot.autoconfigure.AutoConfigurations
import org.springframework.boot.test.context.runner.ApplicationContextRunner
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
Expand Down Expand Up @@ -55,22 +54,23 @@ class ToolCallbackKotlinIT : BaseOllamaIT() {
"spring.ai.ollama.chat.options.temperature=0.5",
"spring.ai.ollama.chat.options.topK=10"
)
.withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration::class.java))
.withConfiguration(ollamaAutoConfig(OllamaChatAutoConfiguration::class.java))
.withUserConfiguration(Config::class.java)

@Test
fun toolCallTest() {
this.contextRunner.run {context ->
this.contextRunner.run { context ->

val chatModel = context.getBean(OllamaChatModel::class.java)

val userMessage = UserMessage(
"What are the weather conditions in San Francisco, Tokyo, and Paris? Find the temperature in Celsius for each of the three locations.")
"What are the weather conditions in San Francisco, Tokyo, and Paris? Find the temperature in Celsius for each of the three locations."
)

val functionOptions = ToolCallingChatOptions.builder().toolNames("weatherInfo").build()

val response = chatModel
.call(Prompt(listOf(userMessage), functionOptions))
.call(Prompt(listOf(userMessage), functionOptions))

logger.info("Response: $response")

Expand All @@ -86,7 +86,8 @@ class ToolCallbackKotlinIT : BaseOllamaIT() {

// Test weatherFunction
val userMessage = UserMessage(
"What are the weather conditions in San Francisco, Tokyo, and Paris? Find the temperature in Celsius for each of the three locations.")
"What are the weather conditions in San Francisco, Tokyo, and Paris? Find the temperature in Celsius for each of the three locations."
)

val functionOptions = ToolCallingChatOptions.builder().toolNames("weatherInfo").build()

Expand Down