1717package org .springframework .ai .model .tool ;
1818
1919import java .util .ArrayList ;
20+ import java .util .Collections ;
2021import java .util .HashMap ;
2122import java .util .List ;
2223import java .util .Map ;
@@ -128,15 +129,15 @@ public ToolExecutionResult executeToolCalls(Prompt prompt, ChatResponse chatResp
128129 Assert .notNull (chatResponse , "chatResponse cannot be null" );
129130
130131 Optional <Generation > toolCallGeneration = chatResponse .getResults ()
131- .stream ()
132- .filter (g -> !CollectionUtils .isEmpty (g .getOutput ().getToolCalls ()))
133- .findFirst ();
132+ .stream ()
133+ .filter (g -> !CollectionUtils .isEmpty (g .getOutput ().getToolCalls ()))
134+ .findFirst ();
134135
135136 if (toolCallGeneration .isEmpty ()) {
136137 throw new IllegalStateException ("No tool call requested by the chat model" );
137138 }
138139
139- AssistantMessage assistantMessage = toolCallGeneration . get (). getOutput ( );
140+ AssistantMessage assistantMessage = safelyMergeAssistantMessageIfEmptyToolCallPresent ( toolCallGeneration );
140141
141142 ToolContext toolContext = buildToolContext (prompt , assistantMessage );
142143
@@ -147,9 +148,37 @@ public ToolExecutionResult executeToolCalls(Prompt prompt, ChatResponse chatResp
147148 assistantMessage , internalToolExecutionResult .toolResponseMessage ());
148149
149150 return ToolExecutionResult .builder ()
150- .conversationHistory (conversationHistory )
151- .returnDirect (internalToolExecutionResult .returnDirect ())
152- .build ();
151+ .conversationHistory (conversationHistory )
152+ .returnDirect (internalToolExecutionResult .returnDirect ())
153+ .build ();
154+ }
155+
156+ private AssistantMessage safelyMergeAssistantMessageIfEmptyToolCallPresent (Optional <Generation > toolCallGeneration ) {
157+ if (toolCallGeneration .isEmpty ()) {
158+ throw new IllegalStateException ("No tool call requested by the chat model" );
159+ }
160+ AssistantMessage assistantMessage = toolCallGeneration .get ().getOutput ();
161+ List <AssistantMessage .ToolCall > toolCalls = assistantMessage .getToolCalls ();
162+ List <AssistantMessage .ToolCall > reversedToolCalls = new ArrayList <>(toolCalls );
163+ Collections .reverse (reversedToolCalls );
164+ List <AssistantMessage .ToolCall > newToolCalls = new ArrayList <>();
165+ StringBuilder args = new StringBuilder ();
166+ for (AssistantMessage .ToolCall toolCall : reversedToolCalls ) {
167+ args .append (toolCall .arguments ());
168+ if (StringUtils .hasText (toolCall .name ())) {
169+ AssistantMessage .ToolCall newToolCall = new AssistantMessage .ToolCall (
170+ toolCall .id (), toolCall .type (), toolCall .name (), args .toString ());
171+ newToolCalls .add (newToolCall );
172+ args = new StringBuilder ();
173+ }
174+ }
175+ Collections .reverse (newToolCalls );
176+ return AssistantMessage .builder ()
177+ .content (assistantMessage .getText ())
178+ .toolCalls (newToolCalls )
179+ .media (assistantMessage .getMedia ())
180+ .properties (assistantMessage .getMetadata ())
181+ .build ();
153182 }
154183
155184 private static ToolContext buildToolContext (Prompt prompt , AssistantMessage assistantMessage ) {
0 commit comments