Skip to content

Commit ed01c22

Browse files
committed
Add convenience method OpenAiChatCompletionResponse#executeTools
1 parent 454f7c5 commit ed01c22

File tree

4 files changed

+51
-30
lines changed

4 files changed

+51
-30
lines changed

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiChatCompletionRequest.java

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.sap.ai.sdk.foundationmodels.openai.generated.model.CreateChatCompletionRequestAllOfResponseFormat;
1010
import com.sap.ai.sdk.foundationmodels.openai.generated.model.CreateChatCompletionRequestAllOfStop;
1111
import java.math.BigDecimal;
12+
import java.util.ArrayList;
1213
import java.util.List;
1314
import java.util.Map;
1415
import java.util.Objects;
@@ -125,6 +126,15 @@ public class OpenAiChatCompletionRequest {
125126
/** List of tools that the model may invoke during the completion. */
126127
@Nullable List<ChatCompletionTool> tools;
127128

129+
/**
130+
* List of tools that are executable at runtime of the application.
131+
*
132+
* @since 1.7.0
133+
*/
134+
@Getter(value = AccessLevel.PACKAGE)
135+
@Nullable
136+
List<OpenAiTool> toolsExecutable;
137+
128138
/** Option to control which tool is invoked by the model. */
129139
@With(AccessLevel.PRIVATE)
130140
@Nullable
@@ -179,6 +189,7 @@ public OpenAiChatCompletionRequest(@Nonnull final List<OpenAiMessage> messages)
179189
null,
180190
null,
181191
null,
192+
null,
182193
null);
183194
}
184195

@@ -226,6 +237,7 @@ public OpenAiChatCompletionRequest withParallelToolCalls(
226237
this.streamOptions,
227238
this.responseFormat,
228239
this.tools,
240+
this.toolsExecutable,
229241
this.toolChoice);
230242
}
231243

@@ -258,6 +270,7 @@ public OpenAiChatCompletionRequest withLogprobs(@Nonnull final Boolean logprobs)
258270
this.streamOptions,
259271
this.responseFormat,
260272
this.tools,
273+
this.toolsExecutable,
261274
this.toolChoice);
262275
}
263276

@@ -282,36 +295,35 @@ public OpenAiChatCompletionRequest withToolChoice(@Nonnull final OpenAiToolChoic
282295
return this.withToolChoice(choice.toolChoice);
283296
}
284297

285-
/**
286-
* Sets the tools to be used in the request with convenience class {@code OpenAiTool}.
287-
*
288-
* @param tools the list of tools to be used
289-
* @return a new OpenAiChatCompletionRequest instance with the specified tools
290-
* @throws IllegalArgumentException if the tool type is not supported
291-
* @since 1.7.0
292-
*/
293-
@Nonnull
294-
@Beta
295-
public OpenAiChatCompletionRequest withToolsExecutable(@Nonnull final List<OpenAiTool> tools) {
296-
return this.withTools(tools.stream().map(OpenAiTool::createChatCompletionTool).toList());
297-
}
298-
299298
/**
300299
* Converts the request to a generated model class CreateChatCompletionRequest.
301300
*
302301
* @return the CreateChatCompletionRequest
303302
*/
304303
CreateChatCompletionRequest createCreateChatCompletionRequest() {
305-
final var request = new CreateChatCompletionRequest();
306-
this.messages.forEach(
307-
message ->
308-
request.addMessagesItem(OpenAiUtils.createChatCompletionRequestMessage(message)));
304+
final var toolsCombined = new ArrayList<ChatCompletionTool>();
305+
if (this.tools != null) {
306+
toolsCombined.addAll(this.tools);
307+
}
308+
if (this.toolsExecutable != null) {
309+
for (OpenAiTool tool : this.toolsExecutable) {
310+
toolsCombined.add(tool.createChatCompletionTool());
311+
}
312+
}
309313

310-
request.stop(this.stop != null ? CreateChatCompletionRequestAllOfStop.create(this.stop) : null);
314+
final var request = new CreateChatCompletionRequest();
315+
for (OpenAiMessage message : this.messages) {
316+
request.addMessagesItem(OpenAiUtils.createChatCompletionRequestMessage(message));
317+
}
318+
if (this.stop != null) {
319+
request.stop(CreateChatCompletionRequestAllOfStop.create(this.stop));
320+
}
321+
if (!toolsCombined.isEmpty()) {
322+
request.tools(toolsCombined);
323+
}
311324

312325
request.temperature(this.temperature);
313326
request.topP(this.topP);
314-
315327
request.stream(null);
316328
request.maxTokens(this.maxTokens);
317329
request.maxCompletionTokens(this.maxCompletionTokens);
@@ -326,7 +338,6 @@ CreateChatCompletionRequest createCreateChatCompletionRequest() {
326338
request.seed(this.seed);
327339
request.streamOptions(this.streamOptions);
328340
request.responseFormat(this.responseFormat);
329-
request.tools(this.tools);
330341
request.toolChoice(this.toolChoice);
331342
request.functionCall(null);
332343
request.functions(null);

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiChatCompletionResponse.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public class OpenAiChatCompletionResponse {
2828
/** The original response from the OpenAI API. */
2929
@Nonnull CreateChatCompletionResponse originalResponse;
3030

31+
/** The original request that was sent to the OpenAI API. */
32+
@Nonnull OpenAiChatCompletionRequest originalRequest;
33+
3134
/**
3235
* Gets the token usage from the original response.
3336
*
@@ -96,4 +99,14 @@ public OpenAiAssistantMessage getMessage() {
9699

97100
return new OpenAiAssistantMessage(new OpenAiMessageContent(contentItems), openAiToolCalls);
98101
}
102+
103+
/**
104+
* Execute tool calls that were suggested by the assistant response.
105+
*
106+
* @return the list of tool messages that were serialized for the computed results. Empty list if
107+
* no tools were called.
108+
*/
109+
public List<OpenAiToolMessage> executeTools() {
110+
return OpenAiTool.execute(getOriginalRequest().getToolsExecutable(), getMessage());
111+
}
99112
}

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ public OpenAiChatCompletionOutput chatCompletion(@Nonnull final String prompt)
158158
public OpenAiChatCompletionResponse chatCompletion(
159159
@Nonnull final OpenAiChatCompletionRequest request) throws OpenAiClientException {
160160
warnIfUnsupportedUsage();
161-
return new OpenAiChatCompletionResponse(
162-
chatCompletion(request.createCreateChatCompletionRequest()));
161+
final var response = chatCompletion(request.createCreateChatCompletionRequest());
162+
return new OpenAiChatCompletionResponse(response, request);
163163
}
164164

165165
/**

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiServiceV2.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,11 @@ public OpenAiChatCompletionResponse chatCompletionToolExecution(
111111
final var request = new OpenAiChatCompletionRequest(messages).withToolsExecutable(tools);
112112
final OpenAiChatCompletionResponse response = client.chatCompletion(request);
113113

114-
// 3. Execute the tool call for given tools
115-
final OpenAiAssistantMessage assistantMessage = response.getMessage();
116-
final List<OpenAiToolMessage> toolMessages = OpenAiTool.execute(tools, assistantMessage);
117-
118-
// 4. Return the results so that the model can incorporate them into the final response.
119-
messages.add(assistantMessage);
120-
messages.addAll(toolMessages);
114+
// 3. Execute the tool calls
115+
messages.add(response.getMessage());
116+
messages.addAll(response.executeTools());
121117

118+
// 4. Have model run the final request with incorporated tool results
122119
return client.chatCompletion(request.withMessages(messages));
123120
}
124121

0 commit comments

Comments
 (0)