@@ -10,6 +10,7 @@ import (
1010 "github.com/mudler/LocalAI/core/backend"
1111 "github.com/mudler/LocalAI/core/config"
1212 mcpTools "github.com/mudler/LocalAI/core/http/endpoints/mcp"
13+ openaiEndpoint "github.com/mudler/LocalAI/core/http/endpoints/openai"
1314 "github.com/mudler/LocalAI/core/http/middleware"
1415 "github.com/mudler/LocalAI/core/schema"
1516 "github.com/mudler/LocalAI/core/templates"
@@ -197,54 +198,24 @@ func handleAnthropicNonStream(c echo.Context, id string, input *schema.Anthropic
197198 xlog .Debug ("Anthropic MCP re-templating" , "iteration" , mcpIteration , "prompt_len" , len (predInput ))
198199 }
199200
200- images := [] string {}
201- for _ , m := range openAIReq .Messages {
202- images = append ( images , m . StringImages ... )
203- }
201+ // Populate openAIReq fields for ComputeChoices
202+ openAIReq .Tools = convertFuncsToOpenAITools ( funcs )
203+ openAIReq . ToolsChoice = input . ToolChoice
204+ openAIReq . Metadata = input . Metadata
204205
205- toolsJSON := ""
206- if len (funcs ) > 0 {
207- openAITools := make ([]functions.Tool , len (funcs ))
208- for i , f := range funcs {
209- openAITools [i ] = functions.Tool {Type : "function" , Function : f }
210- }
211- if toolsBytes , err := json .Marshal (openAITools ); err == nil {
212- toolsJSON = string (toolsBytes )
213- }
214- }
215- toolChoiceJSON := ""
216- if input .ToolChoice != nil {
217- if toolChoiceBytes , err := json .Marshal (input .ToolChoice ); err == nil {
218- toolChoiceJSON = string (toolChoiceBytes )
219- }
206+ var result string
207+ cb := func (s string , c * []schema.Choice ) {
208+ result = s
220209 }
221-
222- predFunc , err := backend .ModelInference (
223- input .Context , predInput , openAIReq .Messages , images , nil , nil , ml , cfg , cl , appConfig , nil , toolsJSON , toolChoiceJSON , nil , nil , nil , input .Metadata )
210+ choices , tokenUsage , chatDeltas , err := openaiEndpoint .ComputeChoices (openAIReq , predInput , cfg , cl , appConfig , ml , cb , nil )
224211 if err != nil {
225212 xlog .Error ("Anthropic model inference failed" , "error" , err )
226213 return sendAnthropicError (c , 500 , "api_error" , fmt .Sprintf ("model inference failed: %v" , err ))
227214 }
228215
229- const maxEmptyRetries = 5
230- var prediction backend.LLMResponse
231- var result string
232- for attempt := 0 ; attempt <= maxEmptyRetries ; attempt ++ {
233- prediction , err = predFunc ()
234- if err != nil {
235- xlog .Error ("Anthropic prediction failed" , "error" , err )
236- return sendAnthropicError (c , 500 , "api_error" , fmt .Sprintf ("prediction failed: %v" , err ))
237- }
238- result = backend .Finetune (* cfg , predInput , prediction .Response )
239- if result != "" || ! shouldUseFn {
240- break
241- }
242- xlog .Warn ("Anthropic: retrying prediction due to empty backend response" , "attempt" , attempt + 1 , "maxRetries" , maxEmptyRetries )
243- }
244-
245216 // Try pre-parsed tool calls from C++ autoparser first, fall back to text parsing
246217 var toolCalls []functions.FuncCallResults
247- if deltaToolCalls := functions .ToolCallsFromChatDeltas (prediction . ChatDeltas ); len (deltaToolCalls ) > 0 {
218+ if deltaToolCalls := functions .ToolCallsFromChatDeltas (chatDeltas ); len (deltaToolCalls ) > 0 {
248219 xlog .Debug ("[ChatDeltas] Anthropic: using pre-parsed tool calls" , "count" , len (deltaToolCalls ))
249220 toolCalls = deltaToolCalls
250221 } else {
@@ -350,8 +321,8 @@ func handleAnthropicNonStream(c echo.Context, id string, input *schema.Anthropic
350321 StopReason : & stopReason ,
351322 Content : contentBlocks ,
352323 Usage : schema.AnthropicUsage {
353- InputTokens : prediction . Usage .Prompt ,
354- OutputTokens : prediction . Usage .Completion ,
324+ InputTokens : tokenUsage .Prompt ,
325+ OutputTokens : tokenUsage .Completion ,
355326 },
356327 }
357328
@@ -397,12 +368,6 @@ func handleAnthropicStream(c echo.Context, id string, input *schema.AnthropicReq
397368 xlog .Debug ("Anthropic MCP stream re-templating" , "iteration" , mcpIteration )
398369 }
399370
400- openAIMessages := openAIReq .Messages
401- images := []string {}
402- for _ , m := range openAIMessages {
403- images = append (images , m .StringImages ... )
404- }
405-
406371 // Track accumulated content for tool call detection
407372 accumulatedContent := ""
408373 currentBlockIndex := 0
@@ -481,38 +446,19 @@ func handleAnthropicStream(c echo.Context, id string, input *schema.AnthropicReq
481446 return true
482447 }
483448
484- toolsJSON := ""
485- if len (funcs ) > 0 {
486- openAITools := make ([]functions.Tool , len (funcs ))
487- for i , f := range funcs {
488- openAITools [i ] = functions.Tool {Type : "function" , Function : f }
489- }
490- if toolsBytes , err := json .Marshal (openAITools ); err == nil {
491- toolsJSON = string (toolsBytes )
492- }
493- }
494- toolChoiceJSON := ""
495- if input .ToolChoice != nil {
496- if toolChoiceBytes , err := json .Marshal (input .ToolChoice ); err == nil {
497- toolChoiceJSON = string (toolChoiceBytes )
498- }
499- }
449+ // Populate openAIReq fields for ComputeChoices
450+ openAIReq .Tools = convertFuncsToOpenAITools (funcs )
451+ openAIReq .ToolsChoice = input .ToolChoice
452+ openAIReq .Metadata = input .Metadata
500453
501- predFunc , err := backend .ModelInference (
502- input .Context , predInput , openAIMessages , images , nil , nil , ml , cfg , cl , appConfig , tokenCallback , toolsJSON , toolChoiceJSON , nil , nil , nil , input .Metadata )
454+ _ , tokenUsage , chatDeltas , err := openaiEndpoint .ComputeChoices (openAIReq , predInput , cfg , cl , appConfig , ml , func (s string , c * []schema.Choice ) {}, tokenCallback )
503455 if err != nil {
504456 xlog .Error ("Anthropic stream model inference failed" , "error" , err )
505457 return sendAnthropicError (c , 500 , "api_error" , fmt .Sprintf ("model inference failed: %v" , err ))
506458 }
507459
508- prediction , err := predFunc ()
509- if err != nil {
510- xlog .Error ("Anthropic stream prediction failed" , "error" , err )
511- return sendAnthropicError (c , 500 , "api_error" , fmt .Sprintf ("prediction failed: %v" , err ))
512- }
513-
514460 // Also check chat deltas for tool calls
515- if deltaToolCalls := functions .ToolCallsFromChatDeltas (prediction . ChatDeltas ); len (deltaToolCalls ) > 0 && len (collectedToolCalls ) == 0 {
461+ if deltaToolCalls := functions .ToolCallsFromChatDeltas (chatDeltas ); len (deltaToolCalls ) > 0 && len (collectedToolCalls ) == 0 {
516462 collectedToolCalls = deltaToolCalls
517463 }
518464
@@ -595,7 +541,7 @@ func handleAnthropicStream(c echo.Context, id string, input *schema.AnthropicReq
595541 StopReason : & stopReason ,
596542 },
597543 Usage : & schema.AnthropicUsage {
598- OutputTokens : prediction . Usage .Completion ,
544+ OutputTokens : tokenUsage .Completion ,
599545 },
600546 })
601547
@@ -613,6 +559,14 @@ func handleAnthropicStream(c echo.Context, id string, input *schema.AnthropicReq
613559 return nil
614560}
615561
562+ func convertFuncsToOpenAITools (funcs functions.Functions ) []functions.Tool {
563+ tools := make ([]functions.Tool , len (funcs ))
564+ for i , f := range funcs {
565+ tools [i ] = functions.Tool {Type : "function" , Function : f }
566+ }
567+ return tools
568+ }
569+
616570func sendAnthropicSSE (c echo.Context , event schema.AnthropicStreamEvent ) {
617571 data , err := json .Marshal (event )
618572 if err != nil {
0 commit comments