Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making Spring AI Optional #530

Merged
merged 5 commits into from
Dec 30, 2024

Conversation

raphaeldelio
Copy link
Contributor

Spring AI is not in a release version yet. Given that there are companies that don't allow the use of milestone versions in their projects, they lost the ability of upgrading to the latest version of Redis OM Spring. To give them back the ability to keep using the latest version of Redis OM Spring, it was decided that the dependencies related to Spring AI were going to become optional.

To make them optional, we have two options:

  1. Set the specific dependencies to "optional" in the Maven file. This will require that anyone who wants to use AI features will have to explicitly declare these dependencies.

Example in Gradle KTS:

	maven {
		name = "Spring Milestones"
		url = uri("https://repo.spring.io/milestone")
		mavenContent {
			snapshotsOnly()
		}
	}
	implementation(platform("org.springframework.ai:spring-ai-bom:1.0.0-M2"))

	implementation("com.redis.om:redis-om-spring:0.9.7")
	implementation("org.springframework.ai:spring-ai-openai")
	implementation("jakarta.websocket:jakarta.websocket-api:2.1.1")
	implementation("jakarta.websocket:jakarta.websocket-client-api:2.1.1")
	implementation("org.springframework.ai:spring-ai-ollama")
	implementation("org.springframework.ai:spring-ai-azure-openai")
	implementation("org.springframework.ai:spring-ai-vertex-ai-palm2")
	implementation("org.springframework.ai:spring-ai-bedrock")
	implementation("org.springframework.ai:spring-ai-transformers")
	implementation("org.springframework.ai:spring-ai-mistral-ai")
	implementation("org.springframework.ai:spring-ai-minimax")
	implementation("org.springframework.ai:spring-ai-zhipuai")
  1. Leave the dependencies as they are and allow those who don't want them to explicitly exclude them.

Example in Gradle KTS:

	implementation("com.redis.om:redis-om-spring:0.9.7"){
		exclude(group = "org.springframework.ai")
		exclude(group = "ai.djl")
		exclude(group = "ai.djlpytorch")
		exclude(group = "ai.djl.spring")
		exclude(group = "ai.djl.huggingface")
	}

Regardless of the choice we decide to go with, we will need to make sure that the Beans related to AI features are only created in case these dependencies are added to the project. To do so, I decided to:

  • Split the RedisModulesConfiguration into itself and RedisAiConfiguration.
    This allowed me to set a Conditional to the whole configuration class. Unfortunately, adding the condition to the beans itself wasn't an option because SpringBoot would load the whole Configuration class before evaluating the condition for each Bean and resulting in a ClassNotFoundException.

Because of this same reason, I decided to split the RedisOMProperties into itself and RedisOMAiProperties too.

We cannot have two Configuration classes with the same prefix. This forced me to use "redis.om.spring.ai" as the prefix for the new RedisOMAiProperties class.

Besides that I also added a warning to BasicSentinelTest because I spent some time trying to figure out why it was failing until I finally understood that for this specific test I had to manually start the Redis Container.

Moreover, I didn't know if the name or location of the new files are correct.

I tested this by loading Redis OM Spring library in a separate project and testing it with and without the dependencies. I couldn't find a way to test it without the dependencies with the existing testing configuration.

When running the project without the required dependencies and the conditional set to true it will throw a ClassNotFoundException at startup due to the missing classes during Bean creation.

If running without the required dependencies and the conditional set to false, it will normally start.

- Separating AI Configuration from RedisModulesConfiguration into RedisAiConfiguration
- Separating AI properties from RedisOMProperties into RedisOMAiProperties
- Adding warning to BasicSentinelTest regarding running Redis manually being a requirement
- Making dependencies related to AI features optional
…when AI is enabled and another one for when it's not.
…when AI is enabled and another one for when it's not.
@raphaeldelio
Copy link
Contributor Author

All tests are now passing locally. Turns out that the optional tag wasn't the issue, the Embedder bean had to be separate into the existing and the new Configuration classes as well.

The existing class will create it as a NoopEmbedder while the new one will create it as a DefaultEmbedder.

Copy link
Contributor

@bsbodden bsbodden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small change... removing the .djl. from the property

@bsbodden bsbodden self-requested a review December 30, 2024 00:31
Copy link
Contributor

@bsbodden bsbodden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@bsbodden bsbodden merged commit 0448262 into redis:main Dec 30, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants