Skip to content

Commit 2ced4e6

Browse files
committed
fix: convert functionResponse parts to Spring AI ToolResponseMessage
1 parent d7355a7 commit 2ced4e6

2 files changed

Lines changed: 21 additions & 13 deletions

File tree

contrib/spring-ai/src/main/java/com/google/adk/models/springai/MessageConverter.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.adk.models.LlmResponse;
2323
import com.google.genai.types.Content;
2424
import com.google.genai.types.FunctionCall;
25+
import com.google.genai.types.FunctionResponse;
2526
import com.google.genai.types.GenerateContentResponseUsageMetadata;
2627
import com.google.genai.types.Part;
2728
import java.net.URI;
@@ -261,10 +262,15 @@ private List<Message> handleUserContent(Content content) {
261262
if (part.text().isPresent()) {
262263
textBuilder.append(part.text().get());
263264
} else if (part.functionResponse().isPresent()) {
264-
// TODO: Spring AI 1.1.0 ToolResponseMessage constructors are protected
265-
// For now, we skip tool responses in user messages
266-
// This will need to be addressed in a future update when Spring AI provides
267-
// a public API for creating ToolResponseMessage
265+
FunctionResponse functionResponse = part.functionResponse().get();
266+
String id = functionResponse.id().orElse("");
267+
String name = functionResponse.name().orElse("");
268+
String responseData = toJson(functionResponse.response().orElse(Map.of()));
269+
270+
ToolResponseMessage.ToolResponse toolResponse =
271+
new ToolResponseMessage.ToolResponse(id, name, responseData);
272+
toolResponseMessages.add(
273+
ToolResponseMessage.builder().responses(List.of(toolResponse)).build());
268274
} else if (part.inlineData().isPresent()) {
269275
// Handle inline media data (images, audio, video, etc.)
270276
com.google.genai.types.Blob blob = part.inlineData().get();
@@ -298,7 +304,9 @@ private List<Message> handleUserContent(Content content) {
298304
}
299305

300306
List<Message> messages = new ArrayList<>();
301-
messages.add(UserMessage.builder().text(textBuilder.toString()).media(mediaList).build());
307+
if (textBuilder.length() > 0 || !mediaList.isEmpty() || toolResponseMessages.isEmpty()) {
308+
messages.add(UserMessage.builder().text(textBuilder.toString()).media(mediaList).build());
309+
}
302310
messages.addAll(toolResponseMessages);
303311

304312
return messages;

contrib/spring-ai/src/test/java/com/google/adk/models/springai/MessageConverterTest.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.ai.chat.messages.AssistantMessage;
3838
import org.springframework.ai.chat.messages.Message;
3939
import org.springframework.ai.chat.messages.SystemMessage;
40+
import org.springframework.ai.chat.messages.ToolResponseMessage;
4041
import org.springframework.ai.chat.messages.UserMessage;
4142
import org.springframework.ai.chat.metadata.ChatResponseMetadata;
4243
import org.springframework.ai.chat.metadata.DefaultUsage;
@@ -184,19 +185,18 @@ void testToLlmPromptWithFunctionResponse() {
184185
Prompt prompt = messageConverter.toLlmPrompt(request);
185186

186187
// Currently only UserMessage is created (function response is skipped)
187-
assertThat(prompt.getInstructions()).hasSize(1);
188+
assertThat(prompt.getInstructions()).hasSize(2);
188189

189190
Message userMessage = prompt.getInstructions().get(0);
190191
assertThat(userMessage).isInstanceOf(UserMessage.class);
191192
assertThat(((UserMessage) userMessage).getText()).isEqualTo("What's the weather?");
192193

193-
// When Spring AI provides public API for ToolResponseMessage, uncomment:
194-
// Message toolResponseMessage = prompt.getInstructions().get(1);
195-
// assertThat(toolResponseMessage).isInstanceOf(ToolResponseMessage.class);
196-
// ToolResponseMessage toolResponse = (ToolResponseMessage) toolResponseMessage;
197-
// assertThat(toolResponse.getResponses()).hasSize(1);
198-
// ToolResponseMessage.ToolResponse response = toolResponse.getResponses().get(0);
199-
// assertThat(response.name()).isEqualTo("get_weather");
194+
Message toolResponseMessage = prompt.getInstructions().get(1);
195+
assertThat(toolResponseMessage).isInstanceOf(ToolResponseMessage.class);
196+
ToolResponseMessage toolResponse = (ToolResponseMessage) toolResponseMessage;
197+
assertThat(toolResponse.getResponses()).hasSize(1);
198+
ToolResponseMessage.ToolResponse response = toolResponse.getResponses().get(0);
199+
assertThat(response.name()).isEqualTo("get_weather");
200200
}
201201

202202
@Test

0 commit comments

Comments
 (0)