Skip to content

Commit efe629a

Browse files
committed
Implements ReplicateApi
Signed-off-by: renemrhfr <[email protected]>
1 parent bd1834d commit efe629a

32 files changed

+3585
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2025-2025 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ https://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18+
xmlns="http://maven.apache.org/POM/4.0.0"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20+
<modelVersion>4.0.0</modelVersion>
21+
<parent>
22+
<groupId>org.springframework.ai</groupId>
23+
<artifactId>spring-ai-parent</artifactId>
24+
<version>1.1.0-SNAPSHOT</version>
25+
<relativePath>../../../pom.xml</relativePath>
26+
</parent>
27+
<artifactId>spring-ai-autoconfigure-model-replicate</artifactId>
28+
<packaging>jar</packaging>
29+
<name>Spring AI Replicate Auto Configuration</name>
30+
<description>Spring AI Replicate Auto Configuration</description>
31+
<url>https://github.com/spring-projects/spring-ai</url>
32+
33+
<scm>
34+
<url>https://github.com/spring-projects/spring-ai</url>
35+
<connection>git://github.com/spring-projects/spring-ai.git</connection>
36+
<developerConnection>[email protected]:spring-projects/spring-ai.git</developerConnection>
37+
</scm>
38+
39+
<dependencies>
40+
41+
<!-- Spring AI dependencies -->
42+
43+
<dependency>
44+
<groupId>org.springframework.ai</groupId>
45+
<artifactId>spring-ai-replicate</artifactId>
46+
<version>${project.parent.version}</version>
47+
</dependency>
48+
49+
<!-- Spring AI auto configurations -->
50+
51+
<dependency>
52+
<groupId>org.springframework.ai</groupId>
53+
<artifactId>spring-ai-autoconfigure-retry</artifactId>
54+
<version>${project.parent.version}</version>
55+
</dependency>
56+
57+
<!-- Boot dependencies -->
58+
<dependency>
59+
<groupId>org.springframework.boot</groupId>
60+
<artifactId>spring-boot-starter</artifactId>
61+
<optional>true</optional>
62+
</dependency>
63+
64+
<dependency>
65+
<groupId>org.springframework.boot</groupId>
66+
<artifactId>spring-boot-configuration-processor</artifactId>
67+
<optional>true</optional>
68+
</dependency>
69+
70+
<dependency>
71+
<groupId>org.springframework.boot</groupId>
72+
<artifactId>spring-boot-autoconfigure-processor</artifactId>
73+
<optional>true</optional>
74+
</dependency>
75+
76+
<!-- Test dependencies -->
77+
<dependency>
78+
<groupId>org.springframework.ai</groupId>
79+
<artifactId>spring-ai-test</artifactId>
80+
<version>${project.parent.version}</version>
81+
<scope>test</scope>
82+
</dependency>
83+
84+
<dependency>
85+
<groupId>org.springframework.boot</groupId>
86+
<artifactId>spring-boot-starter-test</artifactId>
87+
<scope>test</scope>
88+
</dependency>
89+
</dependencies>
90+
91+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2025-2025 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.replicate.autoconfigure;
18+
19+
import io.micrometer.observation.ObservationRegistry;
20+
21+
import org.springframework.ai.replicate.ReplicateChatModel;
22+
import org.springframework.ai.replicate.ReplicateMediaModel;
23+
import org.springframework.ai.replicate.ReplicateStringModel;
24+
import org.springframework.ai.replicate.ReplicateStructuredModel;
25+
import org.springframework.ai.replicate.api.ReplicateApi;
26+
import org.springframework.beans.factory.ObjectProvider;
27+
import org.springframework.boot.autoconfigure.AutoConfiguration;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
29+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
30+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
31+
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
32+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
33+
import org.springframework.context.annotation.Bean;
34+
import org.springframework.util.StringUtils;
35+
import org.springframework.web.client.ResponseErrorHandler;
36+
import org.springframework.web.client.RestClient;
37+
38+
/**
39+
* {@link AutoConfiguration Auto-configuration} for Replicate models.
40+
*
41+
* @author Rene Maierhofer
42+
* @since 1.1.0
43+
*/
44+
@AutoConfiguration(after = RestClientAutoConfiguration.class)
45+
@ConditionalOnClass(ReplicateApi.class)
46+
@EnableConfigurationProperties({ ReplicateConnectionProperties.class, ReplicateChatProperties.class,
47+
ReplicateMediaProperties.class, ReplicateStringProperties.class, ReplicateStructuredProperties.class })
48+
@ConditionalOnProperty(prefix = ReplicateConnectionProperties.CONFIG_PREFIX, name = "api-token")
49+
public class ReplicateChatAutoConfiguration {
50+
51+
@Bean
52+
@ConditionalOnMissingBean
53+
@ConditionalOnProperty(prefix = ReplicateConnectionProperties.CONFIG_PREFIX, name = "api-token")
54+
public ReplicateApi replicateApi(ReplicateConnectionProperties connectionProperties,
55+
ObjectProvider<RestClient.Builder> restClientBuilderProvider,
56+
ObjectProvider<ResponseErrorHandler> responseErrorHandlerProvider) {
57+
58+
if (!StringUtils.hasText(connectionProperties.getApiToken())) {
59+
throw new IllegalArgumentException(
60+
"Replicate API token must be configured via spring.ai.replicate.api-token");
61+
}
62+
63+
var builder = ReplicateApi.builder()
64+
.apiKey(connectionProperties.getApiToken())
65+
.baseUrl(connectionProperties.getBaseUrl());
66+
67+
RestClient.Builder restClientBuilder = restClientBuilderProvider.getIfAvailable(RestClient::builder);
68+
if (restClientBuilder != null) {
69+
builder.restClientBuilder(restClientBuilder);
70+
}
71+
72+
ResponseErrorHandler errorHandler = responseErrorHandlerProvider.getIfAvailable();
73+
if (errorHandler != null) {
74+
builder.responseErrorHandler(errorHandler);
75+
}
76+
77+
return builder.build();
78+
}
79+
80+
@Bean
81+
@ConditionalOnMissingBean
82+
public ReplicateChatModel replicateChatModel(ReplicateApi replicateApi, ReplicateChatProperties chatProperties,
83+
ObjectProvider<ObservationRegistry> observationRegistry) {
84+
return ReplicateChatModel.builder()
85+
.replicateApi(replicateApi)
86+
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
87+
.defaultOptions(chatProperties.getOptions())
88+
.build();
89+
}
90+
91+
@Bean
92+
@ConditionalOnMissingBean
93+
public ReplicateMediaModel replicateMediaModel(ReplicateApi replicateApi,
94+
ReplicateMediaProperties mediaProperties) {
95+
return ReplicateMediaModel.builder()
96+
.replicateApi(replicateApi)
97+
.defaultOptions(mediaProperties.getOptions())
98+
.build();
99+
}
100+
101+
@Bean
102+
@ConditionalOnMissingBean
103+
public ReplicateStringModel replicateStringModel(ReplicateApi replicateApi,
104+
ReplicateStringProperties stringProperties) {
105+
return ReplicateStringModel.builder()
106+
.replicateApi(replicateApi)
107+
.defaultOptions(stringProperties.getOptions())
108+
.build();
109+
}
110+
111+
@Bean
112+
@ConditionalOnMissingBean
113+
public ReplicateStructuredModel replicateStructuredModel(ReplicateApi replicateApi,
114+
ReplicateStructuredProperties structuredProperties) {
115+
116+
return ReplicateStructuredModel.builder()
117+
.replicateApi(replicateApi)
118+
.defaultOptions(structuredProperties.getOptions())
119+
.build();
120+
}
121+
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2025-2025 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.replicate.autoconfigure;
18+
19+
import org.springframework.ai.replicate.ReplicateChatOptions;
20+
import org.springframework.boot.context.properties.ConfigurationProperties;
21+
import org.springframework.boot.context.properties.NestedConfigurationProperty;
22+
23+
/**
24+
* Chat properties for Replicate AI.
25+
*
26+
* @author Rene Maierhofer
27+
* @since 1.1.0
28+
*/
29+
@ConfigurationProperties(ReplicateChatProperties.CONFIG_PREFIX)
30+
public class ReplicateChatProperties {
31+
32+
public static final String CONFIG_PREFIX = "spring.ai.replicate.chat";
33+
34+
@NestedConfigurationProperty
35+
private ReplicateChatOptions options = ReplicateChatOptions.builder().build();
36+
37+
public ReplicateChatOptions getOptions() {
38+
return this.options;
39+
}
40+
41+
public void setOptions(ReplicateChatOptions options) {
42+
this.options = options;
43+
}
44+
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2025-2025 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.replicate.autoconfigure;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
21+
/**
22+
* Connection properties for Replicate AI.
23+
*
24+
* @author Rene Maierhofer
25+
* @since 1.1.0
26+
*/
27+
@ConfigurationProperties(ReplicateConnectionProperties.CONFIG_PREFIX)
28+
public class ReplicateConnectionProperties {
29+
30+
public static final String CONFIG_PREFIX = "spring.ai.replicate";
31+
32+
public static final String DEFAULT_BASE_URL = "https://api.replicate.com/v1";
33+
34+
private String apiToken;
35+
36+
private String baseUrl = DEFAULT_BASE_URL;
37+
38+
public String getApiToken() {
39+
return this.apiToken;
40+
}
41+
42+
public void setApiToken(String apiToken) {
43+
this.apiToken = apiToken;
44+
}
45+
46+
public String getBaseUrl() {
47+
return this.baseUrl;
48+
}
49+
50+
public void setBaseUrl(String baseUrl) {
51+
this.baseUrl = baseUrl;
52+
}
53+
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2025-2025 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.replicate.autoconfigure;
18+
19+
import org.springframework.ai.replicate.ReplicateOptions;
20+
import org.springframework.boot.context.properties.ConfigurationProperties;
21+
import org.springframework.boot.context.properties.NestedConfigurationProperty;
22+
23+
/**
24+
* Media model properties for Replicate AI. Used for image, video, and audio generation
25+
* models.
26+
*
27+
* @author Rene Maierhofer
28+
* @since 1.1.0
29+
*/
30+
@ConfigurationProperties(ReplicateMediaProperties.CONFIG_PREFIX)
31+
public class ReplicateMediaProperties {
32+
33+
public static final String CONFIG_PREFIX = "spring.ai.replicate.media";
34+
35+
@NestedConfigurationProperty
36+
private ReplicateOptions options = ReplicateOptions.builder().build();
37+
38+
public ReplicateOptions getOptions() {
39+
return this.options;
40+
}
41+
42+
public void setOptions(ReplicateOptions options) {
43+
this.options = options;
44+
}
45+
46+
}

0 commit comments

Comments
 (0)