1616
1717package 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+
1926import com .fasterxml .jackson .annotation .JsonFormat ;
2027import com .fasterxml .jackson .annotation .JsonIgnore ;
2128import com .fasterxml .jackson .annotation .JsonIgnoreProperties ;
2633import com .fasterxml .jackson .databind .ObjectMapper ;
2734import com .fasterxml .jackson .databind .annotation .JsonDeserialize ;
2835import com .fasterxml .jackson .databind .node .ObjectNode ;
29- import java .util .List ;
30- import java .util .Map ;
31- import java .util .concurrent .atomic .AtomicBoolean ;
32- import java .util .function .Consumer ;
33- import java .util .function .Predicate ;
34- import java .util .stream .Collectors ;
36+ import reactor .core .publisher .Flux ;
37+ import reactor .core .publisher .Mono ;
38+
3539import org .springframework .ai .model .ApiKey ;
3640import org .springframework .ai .model .ChatModelDescription ;
3741import org .springframework .ai .model .ModelOptionsUtils ;
5054import org .springframework .web .client .ResponseErrorHandler ;
5155import org .springframework .web .client .RestClient ;
5256import org .springframework .web .reactive .function .client .WebClient ;
53- import reactor .core .publisher .Flux ;
54- import reactor .core .publisher .Mono ;
5557
5658/**
5759 * Single class implementation of the
@@ -196,7 +198,7 @@ public ResponseEntity<ChatCompletion> chatCompletionEntity(ChatCompletionRequest
196198 headers .addAll (additionalHttpHeader );
197199 addDefaultHeadersIfMissing (headers );
198200 })
199- .body (dynamicRequestBody )
201+ .body (dynamicRequestBody )
200202 .retrieve ()
201203 .toEntity (ChatCompletion .class );
202204 // @formatter:on
@@ -260,15 +262,13 @@ public Flux<ChatCompletionChunk> chatCompletionStream(ChatCompletionRequest chat
260262 throw new RuntimeException (e );
261263 }
262264 Object dynamicBody = createDynamicRequestBody (chatRequest );
263- // @formatter:off
264- return this .webClient
265- .post ()
266- .uri (this .completionsPath )
267- .headers (
268- headers -> {
269- headers .addAll (additionalHttpHeader );
270- addDefaultHeadersIfMissing (headers );
271- }) // @formatter:on
265+ // @formatter:off
266+ return this .webClient .post ()
267+ .uri (this .completionsPath )
268+ .headers (headers -> {
269+ headers .addAll (additionalHttpHeader );
270+ addDefaultHeadersIfMissing (headers );
271+ }) // @formatter:on
272272 .bodyValue (dynamicBody )
273273 .retrieve ()
274274 .bodyToFlux (String .class )
@@ -1123,38 +1123,37 @@ public enum OutputModality {
11231123 * @param verbosity Controls the verbosity of the model's response.
11241124 */
11251125 @ JsonInclude (Include .NON_NULL )
1126- public record ChatCompletionRequest ( // @formatter:off
1127- @ JsonProperty ("messages" ) List <ChatCompletionMessage > messages ,
1128- @ JsonProperty ("model" ) String model ,
1129- @ JsonProperty ("store" ) Boolean store ,
1130- @ JsonProperty ("metadata" ) Map <String , String > metadata ,
1131- @ JsonProperty ("frequency_penalty" ) Double frequencyPenalty ,
1132- @ JsonProperty ("logit_bias" ) Map <String , Integer > logitBias ,
1133- @ JsonProperty ("logprobs" ) Boolean logprobs ,
1134- @ JsonProperty ("top_logprobs" ) Integer topLogprobs ,
1135- @ JsonProperty ("max_tokens" ) Integer maxTokens , // original field for specifying token usage.
1136- @ JsonProperty ("max_completion_tokens" )
1137- Integer maxCompletionTokens , // new field for gpt-o1 and other reasoning models
1138- @ JsonProperty ("n" ) Integer n ,
1139- @ JsonProperty ("modalities" ) List <OutputModality > outputModalities ,
1140- @ JsonProperty ("audio" ) AudioParameters audioParameters ,
1141- @ JsonProperty ("presence_penalty" ) Double presencePenalty ,
1142- @ JsonProperty ("response_format" ) ResponseFormat responseFormat ,
1143- @ JsonProperty ("seed" ) Integer seed ,
1144- @ JsonProperty ("service_tier" ) String serviceTier ,
1145- @ JsonProperty ("stop" ) List <String > stop ,
1146- @ JsonProperty ("stream" ) Boolean stream ,
1147- @ JsonProperty ("stream_options" ) StreamOptions streamOptions ,
1148- @ JsonProperty ("temperature" ) Double temperature ,
1149- @ JsonProperty ("top_p" ) Double topP ,
1150- @ JsonProperty ("tools" ) List <FunctionTool > tools ,
1151- @ JsonProperty ("tool_choice" ) Object toolChoice ,
1152- @ JsonProperty ("parallel_tool_calls" ) Boolean parallelToolCalls ,
1153- @ JsonProperty ("user" ) String user ,
1154- @ JsonProperty ("reasoning_effort" ) String reasoningEffort ,
1155- @ JsonProperty ("web_search_options" ) WebSearchOptions webSearchOptions ,
1156- @ JsonProperty ("verbosity" ) String verbosity ,
1157- @ JsonProperty ("extra_body" ) Map <String , Object > extraBody ) {
1126+ public record ChatCompletionRequest (// @formatter:off
1127+ @ JsonProperty ("messages" ) List <ChatCompletionMessage > messages ,
1128+ @ JsonProperty ("model" ) String model ,
1129+ @ JsonProperty ("store" ) Boolean store ,
1130+ @ JsonProperty ("metadata" ) Map <String , String > metadata ,
1131+ @ JsonProperty ("frequency_penalty" ) Double frequencyPenalty ,
1132+ @ JsonProperty ("logit_bias" ) Map <String , Integer > logitBias ,
1133+ @ JsonProperty ("logprobs" ) Boolean logprobs ,
1134+ @ JsonProperty ("top_logprobs" ) Integer topLogprobs ,
1135+ @ JsonProperty ("max_tokens" ) Integer maxTokens , // original field for specifying token usage.
1136+ @ JsonProperty ("max_completion_tokens" ) Integer maxCompletionTokens , // new field for gpt-o1 and other reasoning models
1137+ @ JsonProperty ("n" ) Integer n ,
1138+ @ JsonProperty ("modalities" ) List <OutputModality > outputModalities ,
1139+ @ JsonProperty ("audio" ) AudioParameters audioParameters ,
1140+ @ JsonProperty ("presence_penalty" ) Double presencePenalty ,
1141+ @ JsonProperty ("response_format" ) ResponseFormat responseFormat ,
1142+ @ JsonProperty ("seed" ) Integer seed ,
1143+ @ JsonProperty ("service_tier" ) String serviceTier ,
1144+ @ JsonProperty ("stop" ) List <String > stop ,
1145+ @ JsonProperty ("stream" ) Boolean stream ,
1146+ @ JsonProperty ("stream_options" ) StreamOptions streamOptions ,
1147+ @ JsonProperty ("temperature" ) Double temperature ,
1148+ @ JsonProperty ("top_p" ) Double topP ,
1149+ @ JsonProperty ("tools" ) List <FunctionTool > tools ,
1150+ @ JsonProperty ("tool_choice" ) Object toolChoice ,
1151+ @ JsonProperty ("parallel_tool_calls" ) Boolean parallelToolCalls ,
1152+ @ JsonProperty ("user" ) String user ,
1153+ @ JsonProperty ("reasoning_effort" ) String reasoningEffort ,
1154+ @ JsonProperty ("web_search_options" ) WebSearchOptions webSearchOptions ,
1155+ @ JsonProperty ("verbosity" ) String verbosity ,
1156+ @ JsonProperty ("extra_body" ) Map <String , Object > extraBody ) {
11581157
11591158 /**
11601159 * Shortcut constructor for a chat completion request with the given messages, model and temperature.
@@ -1164,37 +1163,9 @@ public record ChatCompletionRequest( // @formatter:off
11641163 * @param temperature What sampling temperature to use, between 0 and 1.
11651164 */
11661165 public ChatCompletionRequest (List <ChatCompletionMessage > messages , String model , Double temperature ) {
1167- this (
1168- messages ,
1169- model ,
1170- null ,
1171- null ,
1172- null ,
1173- null ,
1174- null ,
1175- null ,
1176- null ,
1177- null ,
1178- null ,
1179- null ,
1180- null ,
1181- null ,
1182- null ,
1183- null ,
1184- null ,
1185- null ,
1186- false ,
1187- null ,
1188- temperature ,
1189- null ,
1190- null ,
1191- null ,
1192- null ,
1193- null ,
1194- null ,
1195- null ,
1196- null ,
1197- null );
1166+ this (messages , model , null , null , null , null , null , null , null , null , null , null , null , null , null ,
1167+ null , null , null , false , null , temperature , null ,
1168+ null , null , null , null , null , null , null ,null );
11981169 }
11991170
12001171 /**
@@ -1205,37 +1176,10 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
12051176 * @param audio Parameters for audio output. Required when audio output is requested with outputModalities: ["audio"].
12061177 */
12071178 public ChatCompletionRequest (List <ChatCompletionMessage > messages , String model , AudioParameters audio , boolean stream ) {
1208- this (
1209- messages ,
1210- model ,
1211- null ,
1212- null ,
1213- null ,
1214- null ,
1215- null ,
1216- null ,
1217- null ,
1218- null ,
1219- null ,
1220- List .of (OutputModality .AUDIO , OutputModality .TEXT ),
1221- audio ,
1222- null ,
1223- null ,
1224- null ,
1225- null ,
1226- null ,
1227- stream ,
1228- null ,
1229- null ,
1230- null ,
1231- null ,
1232- null ,
1233- null ,
1234- null ,
1235- null ,
1236- null ,
1237- null ,
1238- null );
1179+ this (messages , model , null , null , null , null , null , null ,
1180+ null , null , null , List .of (OutputModality .AUDIO , OutputModality .TEXT ), audio , null , null ,
1181+ null , null , null , stream , null , null , null ,
1182+ null , null , null , null , null , null , null ,null );
12391183 }
12401184
12411185 /**
@@ -1248,37 +1192,9 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
12481192 * as they become available, with the stream terminated by a data: [DONE] message.
12491193 */
12501194 public ChatCompletionRequest (List <ChatCompletionMessage > messages , String model , Double temperature , boolean stream ) {
1251- this (
1252- messages ,
1253- model ,
1254- null ,
1255- null ,
1256- null ,
1257- null ,
1258- null ,
1259- null ,
1260- null ,
1261- null ,
1262- null ,
1263- null ,
1264- null ,
1265- null ,
1266- null ,
1267- null ,
1268- null ,
1269- null ,
1270- stream ,
1271- null ,
1272- temperature ,
1273- null ,
1274- null ,
1275- null ,
1276- null ,
1277- null ,
1278- null ,
1279- null ,
1280- null ,
1281- null );
1195+ this (messages , model , null , null , null , null , null , null , null , null , null ,
1196+ null , null , null , null , null , null , null , stream , null , temperature , null ,
1197+ null , null , null , null , null , null , null ,null );
12821198 }
12831199
12841200 /**
@@ -1292,37 +1208,9 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
12921208 */
12931209 public ChatCompletionRequest (List <ChatCompletionMessage > messages , String model ,
12941210 List <FunctionTool > tools , Object toolChoice ) {
1295- this (
1296- messages ,
1297- model ,
1298- null ,
1299- null ,
1300- null ,
1301- null ,
1302- null ,
1303- null ,
1304- null ,
1305- null ,
1306- null ,
1307- null ,
1308- null ,
1309- null ,
1310- null ,
1311- null ,
1312- null ,
1313- null ,
1314- false ,
1315- null ,
1316- 0.8 ,
1317- null ,
1318- tools ,
1319- toolChoice ,
1320- null ,
1321- null ,
1322- null ,
1323- null ,
1324- null ,
1325- null );
1211+ this (messages , model , null , null , null , null , null , null , null , null , null ,
1212+ null , null , null , null , null , null , null , false , null , 0.8 , null ,
1213+ tools , toolChoice , null , null , null , null , null ,null );
13261214 }
13271215
13281216 /**
@@ -1333,10 +1221,9 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
13331221 * as they become available, with the stream terminated by a data: [DONE] message.
13341222 */
13351223 public ChatCompletionRequest (List <ChatCompletionMessage > messages , Boolean stream ) {
1336- this (
1337- messages , null , null , null , null , null , null , null , null , null , null , null , null , null ,
1338- null , null , null , null , stream , null , null , null , null , null , null , null , null , null ,
1339- null , null );
1224+ this (messages , null , null , null , null , null , null , null , null , null , null , null , null , null ,
1225+ null , null , null , null , stream , null , null , null , null , null , null , null , null , null ,
1226+ null , null );
13401227 }
13411228
13421229 /**
@@ -1346,37 +1233,10 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean strea
13461233 * @return A new {@link ChatCompletionRequest} with the specified stream options.
13471234 */
13481235 public ChatCompletionRequest streamOptions (StreamOptions streamOptions ) {
1349- return new ChatCompletionRequest (
1350- this .messages ,
1351- this .model ,
1352- this .store ,
1353- this .metadata ,
1354- this .frequencyPenalty ,
1355- this .logitBias ,
1356- this .logprobs ,
1357- this .topLogprobs ,
1358- this .maxTokens ,
1359- this .maxCompletionTokens ,
1360- this .n ,
1361- this .outputModalities ,
1362- this .audioParameters ,
1363- this .presencePenalty ,
1364- this .responseFormat ,
1365- this .seed ,
1366- this .serviceTier ,
1367- this .stop ,
1368- this .stream ,
1369- streamOptions ,
1370- this .temperature ,
1371- this .topP ,
1372- this .tools ,
1373- this .toolChoice ,
1374- this .parallelToolCalls ,
1375- this .user ,
1376- this .reasoningEffort ,
1377- this .webSearchOptions ,
1378- this .verbosity ,
1379- this .extraBody );
1236+ return new ChatCompletionRequest (this .messages , this .model , this .store , this .metadata , this .frequencyPenalty , this .logitBias , this .logprobs ,
1237+ this .topLogprobs , this .maxTokens , this .maxCompletionTokens , this .n , this .outputModalities , this .audioParameters , this .presencePenalty ,
1238+ this .responseFormat , this .seed , this .serviceTier , this .stop , this .stream , streamOptions , this .temperature , this .topP ,
1239+ this .tools , this .toolChoice , this .parallelToolCalls , this .user , this .reasoningEffort , this .webSearchOptions , this .verbosity ,this .extraBody );
13801240 }
13811241
13821242 /**
@@ -1580,18 +1440,17 @@ public String getValue() {
15801440 */
15811441 @ JsonInclude (Include .NON_NULL )
15821442 @ JsonIgnoreProperties (ignoreUnknown = true )
1583- public record ChatCompletionMessage ( // @formatter:off
1584- @ JsonProperty ("content" ) Object rawContent ,
1585- @ JsonProperty ("role" ) Role role ,
1586- @ JsonProperty ("name" ) String name ,
1587- @ JsonProperty ("tool_call_id" ) String toolCallId ,
1588- @ JsonProperty ("tool_calls" )
1589- @ JsonFormat (with = JsonFormat .Feature .ACCEPT_SINGLE_VALUE_AS_ARRAY )
1590- List <ToolCall > toolCalls ,
1591- @ JsonProperty ("refusal" ) String refusal ,
1592- @ JsonProperty ("audio" ) AudioOutput audioOutput ,
1593- @ JsonProperty ("annotations" ) List <Annotation > annotations ,
1594- @ JsonProperty ("reasoning_content" ) String reasoningContent ) { // @formatter:on
1443+ public record ChatCompletionMessage (// @formatter:off
1444+ @ JsonProperty ("content" ) Object rawContent ,
1445+ @ JsonProperty ("role" ) Role role ,
1446+ @ JsonProperty ("name" ) String name ,
1447+ @ JsonProperty ("tool_call_id" ) String toolCallId ,
1448+ @ JsonProperty ("tool_calls" ) @ JsonFormat (with = JsonFormat .Feature .ACCEPT_SINGLE_VALUE_AS_ARRAY ) List <ToolCall > toolCalls ,
1449+ @ JsonProperty ("refusal" ) String refusal ,
1450+ @ JsonProperty ("audio" ) AudioOutput audioOutput ,
1451+ @ JsonProperty ("annotations" ) List <Annotation > annotations ,
1452+ @ JsonProperty ("reasoning_content" ) String reasoningContent
1453+ ) { // @formatter:on
15951454
15961455 /**
15971456 * Create a chat completion message with the given content and role. All other
0 commit comments