Skip to content

Commit 987cad1

Browse files
committed
Fixes #3824 - Add starters to google-genai and googglere-genai-embedding modules
Signed-off-by: ddobrin <[email protected]>
1 parent cd71573 commit 987cad1

20 files changed

+1749
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Migration Guide: Spring AI Google GenAI Autoconfiguration
2+
3+
## Overview
4+
5+
This guide helps you migrate from the old Vertex AI-based autoconfiguration to the new Google GenAI SDK-based autoconfiguration.
6+
7+
## Key Changes
8+
9+
### 1. Property Namespace Changes
10+
11+
Old properties:
12+
```properties
13+
spring.ai.vertex.ai.gemini.project-id=my-project
14+
spring.ai.vertex.ai.gemini.location=us-central1
15+
spring.ai.vertex.ai.gemini.chat.options.model=gemini-pro
16+
spring.ai.vertex.ai.embedding.text.options.model=textembedding-gecko
17+
```
18+
19+
New properties:
20+
```properties
21+
# For Vertex AI mode
22+
spring.ai.google.genai.project-id=my-project
23+
spring.ai.google.genai.location=us-central1
24+
spring.ai.google.genai.chat.options.model=gemini-2.0-flash
25+
26+
# For Gemini Developer API mode (new!)
27+
spring.ai.google.genai.api-key=your-api-key
28+
spring.ai.google.genai.chat.options.model=gemini-2.0-flash
29+
30+
# Embedding properties
31+
spring.ai.google.genai.embedding.project-id=my-project
32+
spring.ai.google.genai.embedding.location=us-central1
33+
spring.ai.google.genai.embedding.text.options.model=text-embedding-004
34+
```
35+
36+
### 2. New Authentication Options
37+
38+
The new SDK supports both:
39+
- **Vertex AI mode**: Using Google Cloud credentials (same as before)
40+
- **Gemini Developer API mode**: Using API keys (new!)
41+
42+
### 3. Removed Features
43+
44+
- `transport` property is no longer needed
45+
- Multimodal embedding autoconfiguration has been removed (pending support in new SDK)
46+
47+
### 4. Bean Name Changes
48+
49+
If you were autowiring beans by name:
50+
- `vertexAi``googleGenAiClient`
51+
- `vertexAiGeminiChat``googleGenAiChatModel`
52+
- `textEmbedding``googleGenAiTextEmbedding`
53+
54+
### 5. Class Changes
55+
56+
If you were importing classes directly:
57+
- `com.google.cloud.vertexai.VertexAI``com.google.genai.Client`
58+
- `org.springframework.ai.vertexai.gemini.*``org.springframework.ai.google.genai.*`
59+
60+
## Migration Steps
61+
62+
1. Update your application properties:
63+
- Replace `spring.ai.vertex.ai.*` with `spring.ai.google.genai.*`
64+
- Remove any `transport` configuration
65+
66+
2. If using API key authentication:
67+
- Set `spring.ai.google.genai.api-key` property
68+
- Remove project-id and location for chat (not needed with API key)
69+
70+
3. Update any custom configurations or bean references
71+
72+
4. Test your application thoroughly
73+
74+
## Environment Variables
75+
```bash
76+
export GOOGLE_CLOUD_PROJECT=my-project
77+
export GOOGLE_CLOUD_LOCATION=us-central1
78+
```
79+
80+
New (additional option):
81+
```bash
82+
export GOOGLE_API_KEY=your-api-key
83+
```
84+
85+
## Backward Compatibility
86+
87+
The old autoconfiguration module is still available but deprecated. We recommend migrating to the new module as soon as possible.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>org.springframework.ai</groupId>
8+
<artifactId>spring-ai-parent</artifactId>
9+
<version>1.1.0-SNAPSHOT</version>
10+
<relativePath>../../../pom.xml</relativePath>
11+
</parent>
12+
<artifactId>spring-ai-autoconfigure-model-google-genai</artifactId>
13+
<packaging>jar</packaging>
14+
<name>Spring AI Google GenAI Auto Configuration</name>
15+
<description>Spring AI Google GenAI Auto Configuration</description>
16+
<url>https://github.com/spring-projects/spring-ai</url>
17+
18+
<scm>
19+
<url>https://github.com/spring-projects/spring-ai</url>
20+
<connection>git://github.com/spring-projects/spring-ai.git</connection>
21+
<developerConnection>[email protected]:spring-projects/spring-ai.git</developerConnection>
22+
</scm>
23+
24+
25+
<dependencies>
26+
27+
<!-- Spring AI dependencies -->
28+
29+
<!-- Google GenAI Embedding -->
30+
<dependency>
31+
<groupId>org.springframework.ai</groupId>
32+
<artifactId>spring-ai-google-genai-embedding</artifactId>
33+
<version>${project.parent.version}</version>
34+
<optional>true</optional>
35+
</dependency>
36+
37+
<!-- Google GenAI -->
38+
<dependency>
39+
<groupId>org.springframework.ai</groupId>
40+
<artifactId>spring-ai-google-genai</artifactId>
41+
<version>${project.parent.version}</version>
42+
<optional>true</optional>
43+
</dependency>
44+
45+
<!-- Spring AI auto configurations -->
46+
47+
<dependency>
48+
<groupId>org.springframework.ai</groupId>
49+
<artifactId>spring-ai-autoconfigure-model-tool</artifactId>
50+
<version>${project.parent.version}</version>
51+
</dependency>
52+
53+
<dependency>
54+
<groupId>org.springframework.ai</groupId>
55+
<artifactId>spring-ai-autoconfigure-retry</artifactId>
56+
<version>${project.parent.version}</version>
57+
</dependency>
58+
59+
<dependency>
60+
<groupId>org.springframework.ai</groupId>
61+
<artifactId>spring-ai-autoconfigure-model-chat-observation</artifactId>
62+
<version>${project.parent.version}</version>
63+
</dependency>
64+
65+
<dependency>
66+
<groupId>org.springframework.ai</groupId>
67+
<artifactId>spring-ai-autoconfigure-model-embedding-observation</artifactId>
68+
<version>${project.parent.version}</version>
69+
</dependency>
70+
71+
<!-- Boot dependencies -->
72+
<dependency>
73+
<groupId>org.springframework.boot</groupId>
74+
<artifactId>spring-boot-starter</artifactId>
75+
<optional>true</optional>
76+
</dependency>
77+
78+
<dependency>
79+
<groupId>org.springframework.boot</groupId>
80+
<artifactId>spring-boot-configuration-processor</artifactId>
81+
<optional>true</optional>
82+
</dependency>
83+
84+
<dependency>
85+
<groupId>org.springframework.boot</groupId>
86+
<artifactId>spring-boot-autoconfigure-processor</artifactId>
87+
<optional>true</optional>
88+
</dependency>
89+
90+
<!-- Test dependencies -->
91+
<dependency>
92+
<groupId>org.springframework.ai</groupId>
93+
<artifactId>spring-ai-test</artifactId>
94+
<version>${project.parent.version}</version>
95+
<scope>test</scope>
96+
</dependency>
97+
98+
<dependency>
99+
<groupId>org.springframework.boot</groupId>
100+
<artifactId>spring-boot-starter-test</artifactId>
101+
<scope>test</scope>
102+
</dependency>
103+
104+
<dependency>
105+
<groupId>org.mockito</groupId>
106+
<artifactId>mockito-core</artifactId>
107+
<scope>test</scope>
108+
</dependency>
109+
110+
<dependency>
111+
<groupId>org.testcontainers</groupId>
112+
<artifactId>junit-jupiter</artifactId>
113+
<scope>test</scope>
114+
</dependency>
115+
116+
<dependency>
117+
<groupId>org.testcontainers</groupId>
118+
<artifactId>ollama</artifactId>
119+
<scope>test</scope>
120+
</dependency>
121+
</dependencies>
122+
123+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright 2023-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.model.google.genai.autoconfigure.chat;
18+
19+
import java.io.IOException;
20+
21+
import com.google.auth.oauth2.GoogleCredentials;
22+
import com.google.genai.Client;
23+
import io.micrometer.observation.ObservationRegistry;
24+
25+
import org.springframework.ai.chat.observation.ChatModelObservationConvention;
26+
import org.springframework.ai.google.genai.GoogleGenAiChatModel;
27+
import org.springframework.ai.model.SpringAIModelProperties;
28+
import org.springframework.ai.model.SpringAIModels;
29+
import org.springframework.ai.model.tool.DefaultToolExecutionEligibilityPredicate;
30+
import org.springframework.ai.model.tool.ToolCallingManager;
31+
import org.springframework.ai.model.tool.ToolExecutionEligibilityPredicate;
32+
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
33+
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
34+
import org.springframework.beans.factory.ObjectProvider;
35+
import org.springframework.boot.autoconfigure.AutoConfiguration;
36+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
37+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
38+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
39+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
40+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
41+
import org.springframework.context.ApplicationContext;
42+
import org.springframework.context.annotation.Bean;
43+
import org.springframework.retry.support.RetryTemplate;
44+
import org.springframework.util.Assert;
45+
import org.springframework.util.StringUtils;
46+
47+
/**
48+
* Auto-configuration for Google GenAI Chat.
49+
*
50+
* @author Christian Tzolov
51+
* @author Soby Chacko
52+
* @author Mark Pollack
53+
* @author Ilayaperumal Gopinathan
54+
* @since 1.1.0
55+
*/
56+
@AutoConfiguration(after = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class })
57+
@ConditionalOnClass({ Client.class, GoogleGenAiChatModel.class })
58+
@ConditionalOnProperty(name = SpringAIModelProperties.CHAT_MODEL, havingValue = SpringAIModels.GOOGLE_GEN_AI,
59+
matchIfMissing = true)
60+
@EnableConfigurationProperties({ GoogleGenAiChatProperties.class, GoogleGenAiConnectionProperties.class })
61+
@ImportAutoConfiguration(classes = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class })
62+
public class GoogleGenAiChatAutoConfiguration {
63+
64+
@Bean
65+
@ConditionalOnMissingBean
66+
public Client googleGenAiClient(GoogleGenAiConnectionProperties connectionProperties) throws IOException {
67+
68+
Client.Builder clientBuilder = Client.builder();
69+
70+
if (StringUtils.hasText(connectionProperties.getApiKey())) {
71+
// Gemini Developer API mode
72+
clientBuilder.apiKey(connectionProperties.getApiKey());
73+
}
74+
else {
75+
// Vertex AI mode
76+
Assert.hasText(connectionProperties.getProjectId(), "Google GenAI project-id must be set!");
77+
Assert.hasText(connectionProperties.getLocation(), "Google GenAI location must be set!");
78+
79+
clientBuilder.project(connectionProperties.getProjectId())
80+
.location(connectionProperties.getLocation())
81+
.vertexAI(true);
82+
83+
if (connectionProperties.getCredentialsUri() != null) {
84+
GoogleCredentials credentials = GoogleCredentials
85+
.fromStream(connectionProperties.getCredentialsUri().getInputStream());
86+
// Note: The new SDK doesn't have a direct setCredentials method,
87+
// credentials are handled automatically when vertexAI is true
88+
}
89+
}
90+
91+
return clientBuilder.build();
92+
}
93+
94+
@Bean
95+
@ConditionalOnMissingBean
96+
public GoogleGenAiChatModel googleGenAiChatModel(Client googleGenAiClient, GoogleGenAiChatProperties chatProperties,
97+
ToolCallingManager toolCallingManager, ApplicationContext context, RetryTemplate retryTemplate,
98+
ObjectProvider<ObservationRegistry> observationRegistry,
99+
ObjectProvider<ChatModelObservationConvention> observationConvention,
100+
ObjectProvider<ToolExecutionEligibilityPredicate> toolExecutionEligibilityPredicate) {
101+
102+
GoogleGenAiChatModel chatModel = GoogleGenAiChatModel.builder()
103+
.genAiClient(googleGenAiClient)
104+
.defaultOptions(chatProperties.getOptions())
105+
.toolCallingManager(toolCallingManager)
106+
.toolExecutionEligibilityPredicate(
107+
toolExecutionEligibilityPredicate.getIfUnique(() -> new DefaultToolExecutionEligibilityPredicate()))
108+
.retryTemplate(retryTemplate)
109+
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
110+
.build();
111+
112+
observationConvention.ifAvailable(chatModel::setObservationConvention);
113+
114+
return chatModel;
115+
}
116+
117+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2023-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.model.google.genai.autoconfigure.chat;
18+
19+
import org.springframework.ai.google.genai.GoogleGenAiChatModel;
20+
import org.springframework.ai.google.genai.GoogleGenAiChatOptions;
21+
import org.springframework.boot.context.properties.ConfigurationProperties;
22+
import org.springframework.boot.context.properties.NestedConfigurationProperty;
23+
24+
/**
25+
* Configuration properties for Google GenAI Chat.
26+
*
27+
* @author Christian Tzolov
28+
* @author Hyunsang Han
29+
* @since 1.1.0
30+
*/
31+
@ConfigurationProperties(GoogleGenAiChatProperties.CONFIG_PREFIX)
32+
public class GoogleGenAiChatProperties {
33+
34+
public static final String CONFIG_PREFIX = "spring.ai.google.genai.chat";
35+
36+
public static final String DEFAULT_MODEL = GoogleGenAiChatModel.ChatModel.GEMINI_2_0_FLASH.getValue();
37+
38+
/**
39+
* Google GenAI API generative options.
40+
*/
41+
@NestedConfigurationProperty
42+
private GoogleGenAiChatOptions options = GoogleGenAiChatOptions.builder()
43+
.temperature(0.7)
44+
.candidateCount(1)
45+
.model(DEFAULT_MODEL)
46+
.build();
47+
48+
public GoogleGenAiChatOptions getOptions() {
49+
return this.options;
50+
}
51+
52+
public void setOptions(GoogleGenAiChatOptions options) {
53+
this.options = options;
54+
}
55+
56+
}

0 commit comments

Comments
 (0)