2222import java .util .List ;
2323import java .util .Locale ;
2424import java .util .Map ;
25+ import java .util .stream .Collectors ;
2526
2627import com .openai .azure .AzureOpenAIServiceVersion ;
28+ import com .openai .core .JsonValue ;
2729import com .openai .credential .Credential ;
2830import com .openai .models .embeddings .EmbeddingCreateParams ;
2931import com .openai .models .embeddings .EmbeddingModel ;
3941 * @author Christian Tzolov
4042 * @author Ilayaperumal Gopinathan
4143 * @author Sebastien Deleuze
44+ * @author guan xu
4245 */
4346public class OpenAiEmbeddingOptions extends AbstractOpenAiOptions implements EmbeddingOptions {
4447
@@ -61,18 +64,28 @@ public class OpenAiEmbeddingOptions extends AbstractOpenAiOptions implements Emb
6164 */
6265 private final @ Nullable Integer dimensions ;
6366
67+ /**
68+ * Extra parameters that are not part of the standard OpenAI API. These parameters are
69+ * passed as additional body properties to support OpenAI-compatible providers like
70+ * vLLM, Ollama, Groq, etc. that support custom parameters such as top_k,
71+ * repetition_penalty, etc.
72+ */
73+ private final @ Nullable Map <String , Object > extraBody ;
74+
6475 protected OpenAiEmbeddingOptions (@ Nullable String baseUrl , @ Nullable String apiKey , @ Nullable Credential credential ,
6576 @ Nullable String model , @ Nullable String microsoftDeploymentName ,
6677 @ Nullable AzureOpenAIServiceVersion microsoftFoundryServiceVersion , @ Nullable String organizationId ,
6778 @ Nullable Boolean isMicrosoftFoundry , @ Nullable Boolean isGitHubModels , @ Nullable Duration timeout ,
6879 @ Nullable Integer maxRetries , @ Nullable Proxy proxy , @ Nullable Map <String , String > customHeaders ,
69- @ Nullable String user , @ Nullable EncodingFormat encodingFormat , @ Nullable Integer dimensions ) {
80+ @ Nullable String user , @ Nullable EncodingFormat encodingFormat , @ Nullable Integer dimensions ,
81+ @ Nullable Map <String , Object > extraBody ) {
7082 super (baseUrl , apiKey , credential , model != null ? model : DEFAULT_EMBEDDING_MODEL , microsoftDeploymentName ,
7183 microsoftFoundryServiceVersion , organizationId , isMicrosoftFoundry , isGitHubModels , timeout , maxRetries ,
7284 proxy , customHeaders );
7385 this .user = user ;
7486 this .encodingFormat = encodingFormat ;
7587 this .dimensions = dimensions ;
88+ this .extraBody = (extraBody != null ? Map .copyOf (extraBody ) : null );
7689 }
7790
7891 public static Builder builder () {
@@ -92,6 +105,10 @@ public static Builder builder() {
92105 return this .dimensions ;
93106 }
94107
108+ public @ Nullable Map <String , Object > getExtraBody () {
109+ return this .extraBody ;
110+ }
111+
95112 public EmbeddingCreateParams toOpenAiCreateParams (List <String > instructions ) {
96113
97114 EmbeddingCreateParams .Builder builder = EmbeddingCreateParams .builder ();
@@ -117,6 +134,17 @@ else if (this.getModel() != null) {
117134 if (this .getDimensions () != null ) {
118135 builder .dimensions (this .getDimensions ());
119136 }
137+
138+ // Add extraBody parameters as additional body properties for OpenAI-compatible
139+ // providers
140+ if (this .getExtraBody () != null && !this .getExtraBody ().isEmpty ()) {
141+ Map <String , JsonValue > extraParams = this .getExtraBody ()
142+ .entrySet ()
143+ .stream ()
144+ .collect (Collectors .toMap (Map .Entry ::getKey , entry -> JsonValue .from (entry .getValue ())));
145+ builder .additionalBodyProperties (extraParams );
146+ }
147+
120148 return builder .build ();
121149 }
122150
@@ -147,6 +175,8 @@ public static final class Builder extends AbstractBuilder<OpenAiEmbeddingOptions
147175
148176 private @ Nullable Integer dimensions ;
149177
178+ private @ Nullable Map <String , Object > extraBody ;
179+
150180 public Builder from (OpenAiEmbeddingOptions fromOptions ) {
151181 // Parent class fields
152182 this .baseUrl = fromOptions .getBaseUrl ();
@@ -166,6 +196,7 @@ public Builder from(OpenAiEmbeddingOptions fromOptions) {
166196 this .user = fromOptions .getUser ();
167197 this .encodingFormat = fromOptions .getEncodingFormat ();
168198 this .dimensions = fromOptions .getDimensions ();
199+ this .extraBody = fromOptions .getExtraBody ();
169200 return this ;
170201 }
171202
@@ -223,6 +254,16 @@ public Builder merge(@Nullable EmbeddingOptions from) {
223254 if (castFrom .getEncodingFormat () != null ) {
224255 this .encodingFormat = castFrom .getEncodingFormat ();
225256 }
257+ if (castFrom .getExtraBody () != null ) {
258+ if (this .extraBody == null ) {
259+ this .extraBody = new HashMap <>(castFrom .getExtraBody ());
260+ }
261+ else {
262+ Map <String , Object > merged = new HashMap <>(this .extraBody );
263+ merged .putAll (castFrom .getExtraBody ());
264+ this .extraBody = merged ;
265+ }
266+ }
226267 }
227268 return this ;
228269 }
@@ -257,12 +298,17 @@ public Builder dimensions(@Nullable Integer dimensions) {
257298 return this ;
258299 }
259300
301+ public Builder extraBody (@ Nullable Map <String , Object > extraBody ) {
302+ this .extraBody = extraBody ;
303+ return this ;
304+ }
305+
260306 @ Override
261307 public OpenAiEmbeddingOptions build () {
262308 return new OpenAiEmbeddingOptions (this .baseUrl , this .apiKey , this .credential , this .model ,
263309 this .microsoftDeploymentName , this .microsoftFoundryServiceVersion , this .organizationId ,
264310 this .isMicrosoftFoundry , this .isGitHubModels , this .timeout , this .maxRetries , this .proxy ,
265- this .customHeaders , this .user , this .encodingFormat , this .dimensions );
311+ this .customHeaders , this .user , this .encodingFormat , this .dimensions , this . extraBody );
266312 }
267313
268314 }
0 commit comments