Skip to content

Commit faf0c8b

Browse files
committed
Add support for extraBody and reasoningContent
- OpenAiChatOptions.extraBody: Support for custom parameter extension - ChatCompletionMessage.reasoningContent: Support for reasoning content field Signed-off-by: SenreySong <[email protected]>
1 parent eda3c74 commit faf0c8b

File tree

10 files changed

+633
-435
lines changed

10 files changed

+633
-435
lines changed

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java

Lines changed: 129 additions & 95 deletions
Large diffs are not rendered by default.

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java

Lines changed: 246 additions & 220 deletions
Large diffs are not rendered by default.

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java

Lines changed: 212 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,18 @@
1616

1717
package org.springframework.ai.openai.api;
1818

19-
import java.util.List;
20-
import java.util.Map;
21-
import java.util.concurrent.atomic.AtomicBoolean;
22-
import java.util.function.Consumer;
23-
import java.util.function.Predicate;
24-
import java.util.stream.Collectors;
25-
2619
import com.fasterxml.jackson.annotation.JsonFormat;
2720
import com.fasterxml.jackson.annotation.JsonIgnore;
2821
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2922
import com.fasterxml.jackson.annotation.JsonInclude;
3023
import com.fasterxml.jackson.annotation.JsonInclude.Include;
3124
import com.fasterxml.jackson.annotation.JsonProperty;
32-
import reactor.core.publisher.Flux;
33-
import reactor.core.publisher.Mono;
34-
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.concurrent.atomic.AtomicBoolean;
28+
import java.util.function.Consumer;
29+
import java.util.function.Predicate;
30+
import java.util.stream.Collectors;
3531
import org.springframework.ai.model.ApiKey;
3632
import org.springframework.ai.model.ChatModelDescription;
3733
import org.springframework.ai.model.ModelOptionsUtils;
@@ -50,6 +46,8 @@
5046
import org.springframework.web.client.ResponseErrorHandler;
5147
import org.springframework.web.client.RestClient;
5248
import org.springframework.web.reactive.function.client.WebClient;
49+
import reactor.core.publisher.Flux;
50+
import reactor.core.publisher.Mono;
5351

5452
/**
5553
* Single class implementation of the
@@ -1086,36 +1084,38 @@ public enum OutputModality {
10861084
* @param verbosity Controls the verbosity of the model's response.
10871085
*/
10881086
@JsonInclude(Include.NON_NULL)
1089-
public record ChatCompletionRequest(// @formatter:off
1090-
@JsonProperty("messages") List<ChatCompletionMessage> messages,
1091-
@JsonProperty("model") String model,
1092-
@JsonProperty("store") Boolean store,
1093-
@JsonProperty("metadata") Map<String, String> metadata,
1094-
@JsonProperty("frequency_penalty") Double frequencyPenalty,
1095-
@JsonProperty("logit_bias") Map<String, Integer> logitBias,
1096-
@JsonProperty("logprobs") Boolean logprobs,
1097-
@JsonProperty("top_logprobs") Integer topLogprobs,
1098-
@JsonProperty("max_tokens") Integer maxTokens, // original field for specifying token usage.
1099-
@JsonProperty("max_completion_tokens") Integer maxCompletionTokens, // new field for gpt-o1 and other reasoning models
1100-
@JsonProperty("n") Integer n,
1101-
@JsonProperty("modalities") List<OutputModality> outputModalities,
1102-
@JsonProperty("audio") AudioParameters audioParameters,
1103-
@JsonProperty("presence_penalty") Double presencePenalty,
1104-
@JsonProperty("response_format") ResponseFormat responseFormat,
1105-
@JsonProperty("seed") Integer seed,
1106-
@JsonProperty("service_tier") String serviceTier,
1107-
@JsonProperty("stop") List<String> stop,
1108-
@JsonProperty("stream") Boolean stream,
1109-
@JsonProperty("stream_options") StreamOptions streamOptions,
1110-
@JsonProperty("temperature") Double temperature,
1111-
@JsonProperty("top_p") Double topP,
1112-
@JsonProperty("tools") List<FunctionTool> tools,
1113-
@JsonProperty("tool_choice") Object toolChoice,
1114-
@JsonProperty("parallel_tool_calls") Boolean parallelToolCalls,
1115-
@JsonProperty("user") String user,
1116-
@JsonProperty("reasoning_effort") String reasoningEffort,
1117-
@JsonProperty("web_search_options") WebSearchOptions webSearchOptions,
1118-
@JsonProperty("verbosity") String verbosity) {
1087+
public record ChatCompletionRequest( // @formatter:off
1088+
@JsonProperty("messages") List<ChatCompletionMessage> messages,
1089+
@JsonProperty("model") String model,
1090+
@JsonProperty("store") Boolean store,
1091+
@JsonProperty("metadata") Map<String, String> metadata,
1092+
@JsonProperty("frequency_penalty") Double frequencyPenalty,
1093+
@JsonProperty("logit_bias") Map<String, Integer> logitBias,
1094+
@JsonProperty("logprobs") Boolean logprobs,
1095+
@JsonProperty("top_logprobs") Integer topLogprobs,
1096+
@JsonProperty("max_tokens") Integer maxTokens, // original field for specifying token usage.
1097+
@JsonProperty("max_completion_tokens")
1098+
Integer maxCompletionTokens, // new field for gpt-o1 and other reasoning models
1099+
@JsonProperty("n") Integer n,
1100+
@JsonProperty("modalities") List<OutputModality> outputModalities,
1101+
@JsonProperty("audio") AudioParameters audioParameters,
1102+
@JsonProperty("presence_penalty") Double presencePenalty,
1103+
@JsonProperty("response_format") ResponseFormat responseFormat,
1104+
@JsonProperty("seed") Integer seed,
1105+
@JsonProperty("service_tier") String serviceTier,
1106+
@JsonProperty("stop") List<String> stop,
1107+
@JsonProperty("stream") Boolean stream,
1108+
@JsonProperty("stream_options") StreamOptions streamOptions,
1109+
@JsonProperty("temperature") Double temperature,
1110+
@JsonProperty("top_p") Double topP,
1111+
@JsonProperty("tools") List<FunctionTool> tools,
1112+
@JsonProperty("tool_choice") Object toolChoice,
1113+
@JsonProperty("parallel_tool_calls") Boolean parallelToolCalls,
1114+
@JsonProperty("user") String user,
1115+
@JsonProperty("reasoning_effort") String reasoningEffort,
1116+
@JsonProperty("web_search_options") WebSearchOptions webSearchOptions,
1117+
@JsonProperty("verbosity") String verbosity,
1118+
@JsonProperty("extra_body") Map<String, Object> extraBody) {
11191119

11201120
/**
11211121
* Shortcut constructor for a chat completion request with the given messages, model and temperature.
@@ -1125,9 +1125,37 @@ public record ChatCompletionRequest(// @formatter:off
11251125
* @param temperature What sampling temperature to use, between 0 and 1.
11261126
*/
11271127
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Double temperature) {
1128-
this(messages, model, null, null, null, null, null, null, null, null, null, null, null, null, null,
1129-
null, null, null, false, null, temperature, null,
1130-
null, null, null, null, null, null, null);
1128+
this(
1129+
messages,
1130+
model,
1131+
null,
1132+
null,
1133+
null,
1134+
null,
1135+
null,
1136+
null,
1137+
null,
1138+
null,
1139+
null,
1140+
null,
1141+
null,
1142+
null,
1143+
null,
1144+
null,
1145+
null,
1146+
null,
1147+
false,
1148+
null,
1149+
temperature,
1150+
null,
1151+
null,
1152+
null,
1153+
null,
1154+
null,
1155+
null,
1156+
null,
1157+
null,
1158+
null);
11311159
}
11321160

11331161
/**
@@ -1138,10 +1166,37 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
11381166
* @param audio Parameters for audio output. Required when audio output is requested with outputModalities: ["audio"].
11391167
*/
11401168
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, AudioParameters audio, boolean stream) {
1141-
this(messages, model, null, null, null, null, null, null,
1142-
null, null, null, List.of(OutputModality.AUDIO, OutputModality.TEXT), audio, null, null,
1143-
null, null, null, stream, null, null, null,
1144-
null, null, null, null, null, null, null);
1169+
this(
1170+
messages,
1171+
model,
1172+
null,
1173+
null,
1174+
null,
1175+
null,
1176+
null,
1177+
null,
1178+
null,
1179+
null,
1180+
null,
1181+
List.of(OutputModality.AUDIO, OutputModality.TEXT),
1182+
audio,
1183+
null,
1184+
null,
1185+
null,
1186+
null,
1187+
null,
1188+
stream,
1189+
null,
1190+
null,
1191+
null,
1192+
null,
1193+
null,
1194+
null,
1195+
null,
1196+
null,
1197+
null,
1198+
null,
1199+
null);
11451200
}
11461201

11471202
/**
@@ -1154,9 +1209,37 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
11541209
* as they become available, with the stream terminated by a data: [DONE] message.
11551210
*/
11561211
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Double temperature, boolean stream) {
1157-
this(messages, model, null, null, null, null, null, null, null, null, null,
1158-
null, null, null, null, null, null, null, stream, null, temperature, null,
1159-
null, null, null, null, null, null, null);
1212+
this(
1213+
messages,
1214+
model,
1215+
null,
1216+
null,
1217+
null,
1218+
null,
1219+
null,
1220+
null,
1221+
null,
1222+
null,
1223+
null,
1224+
null,
1225+
null,
1226+
null,
1227+
null,
1228+
null,
1229+
null,
1230+
null,
1231+
stream,
1232+
null,
1233+
temperature,
1234+
null,
1235+
null,
1236+
null,
1237+
null,
1238+
null,
1239+
null,
1240+
null,
1241+
null,
1242+
null);
11601243
}
11611244

11621245
/**
@@ -1170,9 +1253,37 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
11701253
*/
11711254
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
11721255
List<FunctionTool> tools, Object toolChoice) {
1173-
this(messages, model, null, null, null, null, null, null, null, null, null,
1174-
null, null, null, null, null, null, null, false, null, 0.8, null,
1175-
tools, toolChoice, null, null, null, null, null);
1256+
this(
1257+
messages,
1258+
model,
1259+
null,
1260+
null,
1261+
null,
1262+
null,
1263+
null,
1264+
null,
1265+
null,
1266+
null,
1267+
null,
1268+
null,
1269+
null,
1270+
null,
1271+
null,
1272+
null,
1273+
null,
1274+
null,
1275+
false,
1276+
null,
1277+
0.8,
1278+
null,
1279+
tools,
1280+
toolChoice,
1281+
null,
1282+
null,
1283+
null,
1284+
null,
1285+
null,
1286+
null);
11761287
}
11771288

11781289
/**
@@ -1183,9 +1294,10 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
11831294
* as they become available, with the stream terminated by a data: [DONE] message.
11841295
*/
11851296
public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean stream) {
1186-
this(messages, null, null, null, null, null, null, null, null, null, null,
1187-
null, null, null, null, null, null, null, stream, null, null, null,
1188-
null, null, null, null, null, null, null);
1297+
this(
1298+
messages, null, null, null, null, null, null, null, null, null, null, null, null, null,
1299+
null, null, null, null, stream, null, null, null, null, null, null, null, null, null,
1300+
null, null);
11891301
}
11901302

11911303
/**
@@ -1195,10 +1307,37 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean strea
11951307
* @return A new {@link ChatCompletionRequest} with the specified stream options.
11961308
*/
11971309
public ChatCompletionRequest streamOptions(StreamOptions streamOptions) {
1198-
return new ChatCompletionRequest(this.messages, this.model, this.store, this.metadata, this.frequencyPenalty, this.logitBias, this.logprobs,
1199-
this.topLogprobs, this.maxTokens, this.maxCompletionTokens, this.n, this.outputModalities, this.audioParameters, this.presencePenalty,
1200-
this.responseFormat, this.seed, this.serviceTier, this.stop, this.stream, streamOptions, this.temperature, this.topP,
1201-
this.tools, this.toolChoice, this.parallelToolCalls, this.user, this.reasoningEffort, this.webSearchOptions, this.verbosity);
1310+
return new ChatCompletionRequest(
1311+
this.messages,
1312+
this.model,
1313+
this.store,
1314+
this.metadata,
1315+
this.frequencyPenalty,
1316+
this.logitBias,
1317+
this.logprobs,
1318+
this.topLogprobs,
1319+
this.maxTokens,
1320+
this.maxCompletionTokens,
1321+
this.n,
1322+
this.outputModalities,
1323+
this.audioParameters,
1324+
this.presencePenalty,
1325+
this.responseFormat,
1326+
this.seed,
1327+
this.serviceTier,
1328+
this.stop,
1329+
this.stream,
1330+
streamOptions,
1331+
this.temperature,
1332+
this.topP,
1333+
this.tools,
1334+
this.toolChoice,
1335+
this.parallelToolCalls,
1336+
this.user,
1337+
this.reasoningEffort,
1338+
this.webSearchOptions,
1339+
this.verbosity,
1340+
this.extraBody);
12021341
}
12031342

12041343
/**
@@ -1402,16 +1541,18 @@ public String getValue() {
14021541
*/
14031542
@JsonInclude(Include.NON_NULL)
14041543
@JsonIgnoreProperties(ignoreUnknown = true)
1405-
public record ChatCompletionMessage(// @formatter:off
1406-
@JsonProperty("content") Object rawContent,
1407-
@JsonProperty("role") Role role,
1408-
@JsonProperty("name") String name,
1409-
@JsonProperty("tool_call_id") String toolCallId,
1410-
@JsonProperty("tool_calls") @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) List<ToolCall> toolCalls,
1411-
@JsonProperty("refusal") String refusal,
1412-
@JsonProperty("audio") AudioOutput audioOutput,
1413-
@JsonProperty("annotations") List<Annotation> annotations
1414-
) { // @formatter:on
1544+
public record ChatCompletionMessage( // @formatter:off
1545+
@JsonProperty("content") Object rawContent,
1546+
@JsonProperty("role") Role role,
1547+
@JsonProperty("name") String name,
1548+
@JsonProperty("tool_call_id") String toolCallId,
1549+
@JsonProperty("tool_calls")
1550+
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
1551+
List<ToolCall> toolCalls,
1552+
@JsonProperty("refusal") String refusal,
1553+
@JsonProperty("audio") AudioOutput audioOutput,
1554+
@JsonProperty("annotations") List<Annotation> annotations,
1555+
@JsonProperty("reasoning_content") String reasoningContent) { // @formatter:on
14151556

14161557
/**
14171558
* Create a chat completion message with the given content and role. All other
@@ -1420,7 +1561,7 @@ public record ChatCompletionMessage(// @formatter:off
14201561
* @param role The role of the author of this message.
14211562
*/
14221563
public ChatCompletionMessage(Object content, Role role) {
1423-
this(content, role, null, null, null, null, null, null);
1564+
this(content, role, null, null, null, null, null, null, null);
14241565
}
14251566

14261567
/**

0 commit comments

Comments
 (0)