on main help sign in
chore: fix openai provider for multi tool call
commit71b7127e35c97dbc32b46ce8d2ee32a5886caa84 authorKujtim Hoxha <kujtimii.h@gmail.com> dateThu 10 Jul 2025, 11:23 (1 year ago) parent72f469e
1 file changed+44−1
internal/llm/provider/openai.go+44−1
internal/llm/provider/openai.go+44−1
@@ -272,10 +272,13 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
272272 currentContent := ""
273273 toolCalls := make([]message.ToolCall, 0)
274274
275+ var currentToolCallID string
276+ var currentToolCall openai.ChatCompletionMessageToolCall
277+ var msgToolCalls []openai.ChatCompletionMessageToolCall
275278 for openaiStream.Next() {
276279 chunk := openaiStream.Current()
277280 acc.AddChunk(chunk)
278−
281+ // This fixes multiple tool calls for some providers
279282 for _, choice := range chunk.Choices {
280283 if choice.Delta.Content != "" {
281284 eventChan <- ProviderEvent{
@@ -283,6 +286,45 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
283286 Content: choice.Delta.Content,
284287 }
285288 currentContent += choice.Delta.Content
289+ } else if len(choice.Delta.ToolCalls) > 0 {
290+ toolCall := choice.Delta.ToolCalls[0]
291+ // Detect tool use start
292+ if currentToolCallID == "" {
293+ if toolCall.ID != "" {
294+ currentToolCallID = toolCall.ID
295+ currentToolCall = openai.ChatCompletionMessageToolCall{
296+ ID: toolCall.ID,
297+ Type: "function",
298+ Function: openai.ChatCompletionMessageToolCallFunction{
299+ Name: toolCall.Function.Name,
300+ Arguments: toolCall.Function.Arguments,
301+ },
302+ }
303+ }
304+ } else {
305+ // Delta tool use
306+ if toolCall.ID == "" {
307+ currentToolCall.Function.Arguments += toolCall.Function.Arguments
308+ } else {
309+ // Detect new tool use
310+ if toolCall.ID != currentToolCallID {
311+ msgToolCalls = append(msgToolCalls, currentToolCall)
312+ currentToolCallID = toolCall.ID
313+ currentToolCall = openai.ChatCompletionMessageToolCall{
314+ ID: toolCall.ID,
315+ Type: "function",
316+ Function: openai.ChatCompletionMessageToolCallFunction{
317+ Name: toolCall.Function.Name,
318+ Arguments: toolCall.Function.Arguments,
319+ },
320+ }
321+ }
322+ }
323+ }
324+ }
325+ if choice.FinishReason == "tool_calls" {
326+ msgToolCalls = append(msgToolCalls, currentToolCall)
327+ acc.Choices[0].Message.ToolCalls = msgToolCalls
286328 }
287329 }
288330 }
@@ -293,6 +335,7 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
293335 jsonData, _ := json.Marshal(acc.ChatCompletion)
294336 slog.Debug("Response", "messages", string(jsonData))
295337 }
338+
296339 resultFinishReason := acc.ChatCompletion.Choices[0].FinishReason
297340 if resultFinishReason == "" {
298341 // If the finish reason is empty, we assume it was a successful completion