Skip to content

Commit 31b9817

Browse files
committed
Support extraBody parameter for OpenAiEmbeddingAutoConfiguration
Signed-off-by: guanxu <1510424541@qq.com>
1 parent 4382044 commit 31b9817

6 files changed

Lines changed: 158 additions & 0 deletions

File tree

auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingProperties.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.ai.model.openai.autoconfigure;
1818

19+
import java.util.Map;
20+
1921
import org.jspecify.annotations.Nullable;
2022

2123
import org.springframework.ai.document.MetadataMode;
@@ -24,6 +26,11 @@
2426
import org.springframework.boot.context.properties.ConfigurationProperties;
2527
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
2628

29+
/**
30+
* OpenAI SDK Embedding autoconfiguration properties.
31+
*
32+
* @author guan xu
33+
*/
2734
@ConfigurationProperties(OpenAiEmbeddingProperties.CONFIG_PREFIX)
2835
public class OpenAiEmbeddingProperties extends AbstractOpenAiProperties {
2936

@@ -39,6 +46,8 @@ public class OpenAiEmbeddingProperties extends AbstractOpenAiProperties {
3946

4047
private @Nullable Integer dimensions;
4148

49+
private @Nullable Map<String, Object> extraBody;
50+
4251
public MetadataMode getMetadataMode() {
4352
return this.metadataMode;
4453
}
@@ -79,12 +88,21 @@ public void setDimensions(@Nullable Integer dimensions) {
7988
this.dimensions = dimensions;
8089
}
8190

91+
public @Nullable Map<String, Object> getExtraBody() {
92+
return this.extraBody;
93+
}
94+
95+
public void setExtraBody(@Nullable Map<String, Object> extraBody) {
96+
this.extraBody = extraBody;
97+
}
98+
8299
public OpenAiEmbeddingOptions toOptions() {
83100
return OpenAiEmbeddingOptions.builder()
84101
.model(this.model)
85102
.user(this.user)
86103
.encodingFormat(this.encodingFormat)
87104
.dimensions(this.dimensions)
105+
.extraBody(this.extraBody)
88106
.build();
89107
}
90108

@@ -142,6 +160,16 @@ public void setDimensions(@Nullable Integer dimensions) {
142160
OpenAiEmbeddingProperties.this.setDimensions(dimensions);
143161
}
144162

163+
@DeprecatedConfigurationProperty(replacement = "spring.ai.openai.embedding.extra-body")
164+
@Deprecated(since = "2.0.0", forRemoval = true)
165+
public @Nullable Map<String, Object> getExtraBody() {
166+
return OpenAiEmbeddingProperties.this.getExtraBody();
167+
}
168+
169+
public void setExtraBody(@Nullable Map<String, Object> extraBody) {
170+
OpenAiEmbeddingProperties.this.setExtraBody(extraBody);
171+
}
172+
145173
}
146174

147175
}

auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfigurationIT.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333

3434
import static org.assertj.core.api.Assertions.assertThat;
3535

36+
/**
37+
* Integration tests for {@link OpenAiEmbeddingAutoConfiguration}.
38+
*
39+
* @author guan xu
40+
*/
3641
@EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+")
3742
public class OpenAiChatAutoConfigurationIT {
3843

@@ -127,4 +132,34 @@ void chatActivation() {
127132

128133
}
129134

135+
@Test
136+
public void chatExtraBodyTest() {
137+
this.contextRunner
138+
.withPropertyValues(// @formatter:off
139+
"spring.ai.openai.api-key=API_KEY",
140+
"spring.ai.openai.base-url=http://TEST.BASE.URL",
141+
142+
"spring.ai.openai.chat.extra-body.key1=value1",
143+
"spring.ai.openai.chat.extra-body.key2=123",
144+
"spring.ai.openai.chat.extra-body.nested.key3=true"
145+
)
146+
// @formatter:on
147+
.withConfiguration(
148+
AutoConfigurations.of(OpenAiChatAutoConfiguration.class, ToolCallingAutoConfiguration.class))
149+
.run(context -> {
150+
var chatProperties = context.getBean(OpenAiChatProperties.class);
151+
152+
assertThat(chatProperties.getExtraBody()).isNotNull();
153+
assertThat(chatProperties.getExtraBody()).containsEntry("key1", "value1");
154+
assertThat(chatProperties.getExtraBody()).containsEntry("key2", "123");
155+
assertThat(chatProperties.getExtraBody()).containsKey("nested");
156+
157+
var options = chatProperties.toOptions();
158+
assertThat(options.getExtraBody()).isNotNull();
159+
assertThat(options.getExtraBody()).containsEntry("key1", "value1");
160+
assertThat(options.getExtraBody()).containsEntry("key2", "123");
161+
assertThat(options.getExtraBody()).containsKey("nested");
162+
});
163+
}
164+
130165
}

auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatPropertiesTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,35 @@ public void chatToolChoiceStringValuesTest() {
141141
}
142142
}
143143

144+
@Test
145+
public void chatExtraBodyTest() {
146+
147+
this.contextRunner
148+
.withPropertyValues(// @formatter:off
149+
"spring.ai.openai.api-key=API_KEY",
150+
"spring.ai.openai.base-url=http://TEST.BASE.URL",
151+
152+
"spring.ai.openai.chat.extra-body.key1=value1",
153+
"spring.ai.openai.chat.extra-body.key2=123",
154+
"spring.ai.openai.chat.extra-body.nested.key3=true"
155+
)
156+
// @formatter:on
157+
.withConfiguration(
158+
AutoConfigurations.of(OpenAiChatAutoConfiguration.class, ToolCallingAutoConfiguration.class))
159+
.run(context -> {
160+
var chatProperties = context.getBean(OpenAiChatProperties.class);
161+
162+
assertThat(chatProperties.getExtraBody()).isNotNull();
163+
assertThat(chatProperties.getExtraBody()).containsEntry("key1", "value1");
164+
assertThat(chatProperties.getExtraBody()).containsEntry("key2", "123");
165+
assertThat(chatProperties.getExtraBody()).containsKey("nested");
166+
167+
var options = chatProperties.toOptions();
168+
assertThat(options.getExtraBody()).isNotNull();
169+
assertThat(options.getExtraBody()).containsEntry("key1", "value1");
170+
assertThat(options.getExtraBody()).containsEntry("key2", "123");
171+
assertThat(options.getExtraBody()).containsKey("nested");
172+
});
173+
}
174+
144175
}

auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingAutoConfigurationIT.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@
3030
import static org.assertj.core.api.Assertions.assertThat;
3131

3232
/**
33+
* Integration tests for {@link OpenAiEmbeddingAutoConfiguration}.
34+
*
3335
* @author Sebastien Deleuze
36+
* @author guan xu
3437
*/
3538
@EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+")
3639
public class OpenAiEmbeddingAutoConfigurationIT {
@@ -114,4 +117,34 @@ public void embeddingOptionsTest() {
114117
});
115118
}
116119

120+
@Test
121+
void embeddingExtraBodyTest() {
122+
123+
this.contextRunner
124+
.withPropertyValues(// @formatter:off
125+
"spring.ai.openai.api-key=API_KEY",
126+
"spring.ai.openai.base-url=http://TEST.BASE.URL",
127+
128+
"spring.ai.openai.embedding.extra-body.key1=value1",
129+
"spring.ai.openai.embedding.extra-body.key2=123",
130+
"spring.ai.openai.embedding.extra-body.nested.key3=true"
131+
)
132+
// @formatter:on
133+
.withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class))
134+
.run(context -> {
135+
var embeddingProperties = context.getBean(OpenAiEmbeddingProperties.class);
136+
137+
assertThat(embeddingProperties.getExtraBody()).isNotNull();
138+
assertThat(embeddingProperties.getExtraBody()).containsEntry("key1", "value1");
139+
assertThat(embeddingProperties.getExtraBody()).containsEntry("key2", "123");
140+
assertThat(embeddingProperties.getExtraBody()).containsKey("nested");
141+
142+
var options = embeddingProperties.toOptions();
143+
assertThat(options.getExtraBody()).isNotNull();
144+
assertThat(options.getExtraBody()).containsEntry("key1", "value1");
145+
assertThat(options.getExtraBody()).containsEntry("key2", "123");
146+
assertThat(options.getExtraBody()).containsKey("nested");
147+
});
148+
}
149+
117150
}

auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingPropertiesTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*
3030
* @author Christian Tzolov
3131
* @author Sebastien Deleuze
32+
* @author guan xu
3233
*/
3334
public class OpenAiEmbeddingPropertiesTests {
3435

@@ -86,4 +87,33 @@ public void embeddingOptionsTest() {
8687
});
8788
}
8889

90+
@Test
91+
public void embeddingExtraBodyTest() {
92+
93+
this.contextRunner
94+
.withPropertyValues(// @formatter:off
95+
"spring.ai.openai.api-key=API_KEY",
96+
"spring.ai.openai.base-url=http://TEST.BASE.URL",
97+
"spring.ai.openai.embedding.extra-body.key1=value1",
98+
"spring.ai.openai.embedding.extra-body.key2=123",
99+
"spring.ai.openai.embedding.extra-body.nested.key3=true"
100+
)
101+
// @formatter:on
102+
.withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class))
103+
.run(context -> {
104+
var embeddingProperties = context.getBean(OpenAiEmbeddingProperties.class);
105+
106+
assertThat(embeddingProperties.getExtraBody()).isNotNull();
107+
assertThat(embeddingProperties.getExtraBody()).containsEntry("key1", "value1");
108+
assertThat(embeddingProperties.getExtraBody()).containsEntry("key2", "123");
109+
assertThat(embeddingProperties.getExtraBody()).containsKey("nested");
110+
111+
var options = embeddingProperties.toOptions();
112+
assertThat(options.getExtraBody()).isNotNull();
113+
assertThat(options.getExtraBody()).containsEntry("key1", "value1");
114+
assertThat(options.getExtraBody()).containsEntry("key2", "123");
115+
assertThat(options.getExtraBody()).containsKey("nested");
116+
});
117+
}
118+
89119
}

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/openai-embeddings.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ The prefix `spring.ai.openai.embedding` is property prefix that configures the `
152152
| spring.ai.openai.embedding.encoding-format | The format to return the embeddings in. Can be either float or base64. | -
153153
| spring.ai.openai.embedding.user | A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. | -
154154
| spring.ai.openai.embedding.dimensions | The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. | -
155+
| spring.ai.openai.embedding.extra-body | Additional body properties to send to the OpenAI-compatible provider. | -
155156
|====
156157

157158
NOTE: You can override the common `spring.ai.openai.base-url` and `spring.ai.openai.api-key` for the `ChatModel` and `EmbeddingModel` implementations.

0 commit comments

Comments
 (0)