@@ -467,9 +467,6 @@ func ResponseClaude2OpenAI(claudeResponse *Response) *openai.TextResponse {
467
467
},
468
468
}
469
469
470
- // 打印返回的 OpenAI 格式响应
471
- fmt .Printf ("返回的 OpenAI 格式响应:\n %+v\n " , fullTextResponse )
472
-
473
470
return & fullTextResponse
474
471
}
475
472
@@ -478,16 +475,35 @@ func StreamResponseClaude2OpenAI(claudeResponse *StreamResponse) (*openai.ChatCo
478
475
var response * Response
479
476
var responseText string
480
477
var stopReason string
478
+ tools := make ([]model.Tool , 0 )
479
+
481
480
switch claudeResponse .Type {
482
481
case "message_start" :
483
482
return nil , claudeResponse .Message
484
483
case "content_block_start" :
485
484
if claudeResponse .ContentBlock != nil {
486
485
responseText = claudeResponse .ContentBlock .Text
486
+ if claudeResponse .ContentBlock .Type == "tool_use" {
487
+ tools = append (tools , model.Tool {
488
+ Id : claudeResponse .ContentBlock .Id ,
489
+ Type : "function" ,
490
+ Function : model.Function {
491
+ Name : claudeResponse .ContentBlock .Name ,
492
+ Arguments : "" ,
493
+ },
494
+ })
495
+ }
487
496
}
488
497
case "content_block_delta" :
489
498
if claudeResponse .Delta != nil {
490
499
responseText = claudeResponse .Delta .Text
500
+ if claudeResponse .Delta .Type == "input_json_delta" {
501
+ tools = append (tools , model.Tool {
502
+ Function : model.Function {
503
+ Arguments : claudeResponse .Delta .PartialJson ,
504
+ },
505
+ })
506
+ }
491
507
}
492
508
case "message_delta" :
493
509
if claudeResponse .Usage != nil {
@@ -501,6 +517,10 @@ func StreamResponseClaude2OpenAI(claudeResponse *StreamResponse) (*openai.ChatCo
501
517
}
502
518
var choice openai.ChatCompletionsStreamResponseChoice
503
519
choice .Delta .Content = responseText
520
+ if len (tools ) > 0 {
521
+ choice .Delta .Content = nil // compatible with other OpenAI derivative applications, like LobeOpenAICompatibleFactory ...
522
+ choice .Delta .ToolCalls = tools
523
+ }
504
524
choice .Delta .Role = "assistant"
505
525
finishReason := stopReasonClaude2OpenAI (& stopReason )
506
526
if finishReason != "null" {
@@ -511,7 +531,6 @@ func StreamResponseClaude2OpenAI(claudeResponse *StreamResponse) (*openai.ChatCo
511
531
openaiResponse .Choices = []openai.ChatCompletionsStreamResponseChoice {choice }
512
532
return & openaiResponse , response
513
533
}
514
-
515
534
func responseClaude2OpenAI (claudeResponse * Response ) * openai.TextResponse {
516
535
var responseText string
517
536
if len (claudeResponse .Content ) > 0 {
@@ -578,6 +597,7 @@ func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWithStatusC
578
597
var modelName string
579
598
var id string
580
599
var streamError * model.ErrorWithStatusCode
600
+ var lastToolCallChoice openai.ChatCompletionsStreamResponseChoice
581
601
c .Stream (func (w io.Writer ) bool {
582
602
select {
583
603
case data := <- dataChan :
@@ -593,15 +613,29 @@ func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWithStatusC
593
613
if meta != nil {
594
614
usage .PromptTokens += meta .Usage .InputTokens
595
615
usage .CompletionTokens += meta .Usage .OutputTokens
596
- modelName = meta .Model
597
- id = fmt .Sprintf ("chatcmpl-%s" , meta .Id )
598
- return true
616
+ if len (meta .Id ) > 0 { // only message_start has an id, otherwise it's a finish_reason event.
617
+ id = fmt .Sprintf ("chatcmpl-%s" , meta .Id )
618
+ return true
619
+ } else { // finish_reason case
620
+ ProcessToolCalls (& lastToolCallChoice , response )
621
+ }
599
622
}
600
623
if response == nil {
601
624
return true
602
625
}
603
- responsePart := response .Choices [0 ].Delta .Content .(string )
604
- responseTextBuilder .WriteString (responsePart )
626
+ if response != nil && len (response .Choices ) > 0 {
627
+ choice := response .Choices [0 ]
628
+ if choice .Delta .Content != nil {
629
+ if content , ok := choice .Delta .Content .(string ); ok {
630
+ responseTextBuilder .WriteString (content )
631
+ } else if content , ok := choice .Delta .Content .(map [string ]interface {}); ok {
632
+ // 处理其他可能的内容类型
633
+ if textContent , exists := content ["text" ].(string ); exists {
634
+ responseTextBuilder .WriteString (textContent )
635
+ }
636
+ }
637
+ }
638
+ }
605
639
response .Id = id
606
640
response .Model = modelName
607
641
response .Created = createdTime
@@ -816,3 +850,13 @@ func ClaudeHandler(c *gin.Context, resp *http.Response, promptTokens int, modelN
816
850
_ , err = c .Writer .Write (responseBody )
817
851
return nil , & usage , aitext
818
852
}
853
+ func ProcessToolCalls (lastToolCallChoice * openai.ChatCompletionsStreamResponseChoice , response * openai.ChatCompletionsStreamResponse ) {
854
+ if len (lastToolCallChoice .Delta .ToolCalls ) > 0 {
855
+ lastToolCall := & lastToolCallChoice .Delta .ToolCalls [len (lastToolCallChoice .Delta .ToolCalls )- 1 ]
856
+ if lastToolCall != nil && lastToolCall .Function .Arguments == nil {
857
+ lastToolCall .Function .Arguments = "{}"
858
+ response .Choices [len (response .Choices )- 1 ].Delta .Content = nil
859
+ response .Choices [len (response .Choices )- 1 ].Delta .ToolCalls = lastToolCallChoice .Delta .ToolCalls
860
+ }
861
+ }
862
+ }
0 commit comments