mirror of
				https://github.com/linux-do/new-api.git
				synced 2025-11-04 05:13:41 +08:00 
			
		
		
		
	fix: 规范claude返回格式
This commit is contained in:
		@@ -54,17 +54,32 @@ type OpenAIEmbeddingResponse struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ChatCompletionsStreamResponseChoice struct {
 | 
			
		||||
	Delta        ChatCompletionsStreamResponseChoiceDelta `json:"delta"`
 | 
			
		||||
	FinishReason *string                                  `json:"finish_reason,omitempty"`
 | 
			
		||||
	Delta        ChatCompletionsStreamResponseChoiceDelta `json:"delta,omitempty"`
 | 
			
		||||
	FinishReason *string                                  `json:"finish_reason"`
 | 
			
		||||
	Index        int                                      `json:"index,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ChatCompletionsStreamResponseChoiceDelta struct {
 | 
			
		||||
	Content   string     `json:"content"`
 | 
			
		||||
	Content   *string    `json:"content,omitempty"`
 | 
			
		||||
	Role      string     `json:"role,omitempty"`
 | 
			
		||||
	ToolCalls []ToolCall `json:"tool_calls,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ChatCompletionsStreamResponseChoiceDelta) IsEmpty() bool {
 | 
			
		||||
	return c.Content == nil && len(c.ToolCalls) == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ChatCompletionsStreamResponseChoiceDelta) SetContentString(s string) {
 | 
			
		||||
	c.Content = &s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ChatCompletionsStreamResponseChoiceDelta) GetContentString() string {
 | 
			
		||||
	if c.Content == nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	return *c.Content
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ToolCall struct {
 | 
			
		||||
	// Index is not nil only in chat completion chunk object
 | 
			
		||||
	Index    *int         `json:"index,omitempty"`
 | 
			
		||||
 
 | 
			
		||||
@@ -136,7 +136,7 @@ func responseAli2OpenAI(response *AliChatResponse) *dto.OpenAITextResponse {
 | 
			
		||||
 | 
			
		||||
func streamResponseAli2OpenAI(aliResponse *AliChatResponse) *dto.ChatCompletionsStreamResponse {
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	choice.Delta.Content = aliResponse.Output.Text
 | 
			
		||||
	choice.Delta.SetContentString(aliResponse.Output.Text)
 | 
			
		||||
	if aliResponse.Output.FinishReason != "null" {
 | 
			
		||||
		finishReason := aliResponse.Output.FinishReason
 | 
			
		||||
		choice.FinishReason = &finishReason
 | 
			
		||||
@@ -199,7 +199,7 @@ func aliStreamHandler(c *gin.Context, resp *http.Response) (*dto.OpenAIErrorWith
 | 
			
		||||
				usage.TotalTokens = aliResponse.Usage.InputTokens + aliResponse.Usage.OutputTokens
 | 
			
		||||
			}
 | 
			
		||||
			response := streamResponseAli2OpenAI(&aliResponse)
 | 
			
		||||
			response.Choices[0].Delta.Content = strings.TrimPrefix(response.Choices[0].Delta.Content, lastResponseText)
 | 
			
		||||
			response.Choices[0].Delta.SetContentString(strings.TrimPrefix(response.Choices[0].Delta.GetContentString(), lastResponseText))
 | 
			
		||||
			lastResponseText = aliResponse.Output.Text
 | 
			
		||||
			jsonResponse, err := json.Marshal(response)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ func responseBaidu2OpenAI(response *BaiduChatResponse) *dto.OpenAITextResponse {
 | 
			
		||||
 | 
			
		||||
func streamResponseBaidu2OpenAI(baiduResponse *BaiduChatStreamResponse) *dto.ChatCompletionsStreamResponse {
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	choice.Delta.Content = baiduResponse.Result
 | 
			
		||||
	choice.Delta.SetContentString(baiduResponse.Result)
 | 
			
		||||
	if baiduResponse.IsEnd {
 | 
			
		||||
		choice.FinishReason = &relaycommon.StopFinishReason
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -171,8 +171,7 @@ func StreamResponseClaude2OpenAI(reqMode int, claudeResponse *ClaudeResponse) (*
 | 
			
		||||
	response.Choices = make([]dto.ChatCompletionsStreamResponseChoice, 0)
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	if reqMode == RequestModeCompletion {
 | 
			
		||||
		choice.Delta.Content = claudeResponse.Completion
 | 
			
		||||
		choice.Delta.Role = "assistant"
 | 
			
		||||
		choice.Delta.SetContentString(claudeResponse.Completion)
 | 
			
		||||
		finishReason := stopReasonClaude2OpenAI(claudeResponse.StopReason)
 | 
			
		||||
		if finishReason != "null" {
 | 
			
		||||
			choice.FinishReason = &finishReason
 | 
			
		||||
@@ -182,10 +181,12 @@ func StreamResponseClaude2OpenAI(reqMode int, claudeResponse *ClaudeResponse) (*
 | 
			
		||||
			response.Id = claudeResponse.Message.Id
 | 
			
		||||
			response.Model = claudeResponse.Message.Model
 | 
			
		||||
			claudeUsage = &claudeResponse.Message.Usage
 | 
			
		||||
		} else if claudeResponse.Type == "content_block_start" {
 | 
			
		||||
			choice.Delta.SetContentString("")
 | 
			
		||||
			choice.Delta.Role = "assistant"
 | 
			
		||||
		} else if claudeResponse.Type == "content_block_delta" {
 | 
			
		||||
			choice.Index = claudeResponse.Index
 | 
			
		||||
			choice.Delta.Content = claudeResponse.Delta.Text
 | 
			
		||||
			choice.Delta.Role = "assistant"
 | 
			
		||||
			choice.Delta.SetContentString(claudeResponse.Delta.Text)
 | 
			
		||||
		} else if claudeResponse.Type == "message_delta" {
 | 
			
		||||
			finishReason := stopReasonClaude2OpenAI(*claudeResponse.Delta.StopReason)
 | 
			
		||||
			if finishReason != "null" {
 | 
			
		||||
@@ -194,12 +195,15 @@ func StreamResponseClaude2OpenAI(reqMode int, claudeResponse *ClaudeResponse) (*
 | 
			
		||||
			claudeUsage = &claudeResponse.Usage
 | 
			
		||||
		} else if claudeResponse.Type == "message_stop" {
 | 
			
		||||
			return nil, nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if claudeUsage == nil {
 | 
			
		||||
		claudeUsage = &ClaudeUsage{}
 | 
			
		||||
	}
 | 
			
		||||
	response.Choices = append(response.Choices, choice)
 | 
			
		||||
 | 
			
		||||
	return &response, claudeUsage
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -117,7 +117,7 @@ func cohereStreamHandler(c *gin.Context, resp *http.Response, modelName string,
 | 
			
		||||
					{
 | 
			
		||||
						Delta: dto.ChatCompletionsStreamResponseChoiceDelta{
 | 
			
		||||
							Role:    "assistant",
 | 
			
		||||
							Content: cohereResp.Text,
 | 
			
		||||
							Content: &cohereResp.Text,
 | 
			
		||||
						},
 | 
			
		||||
						Index: 0,
 | 
			
		||||
					},
 | 
			
		||||
 
 | 
			
		||||
@@ -151,7 +151,7 @@ func responseGeminiChat2OpenAI(response *GeminiChatResponse) *dto.OpenAITextResp
 | 
			
		||||
 | 
			
		||||
func streamResponseGeminiChat2OpenAI(geminiResponse *GeminiChatResponse) *dto.ChatCompletionsStreamResponse {
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	choice.Delta.Content = geminiResponse.GetResponseText()
 | 
			
		||||
	choice.Delta.SetContentString(geminiResponse.GetResponseText())
 | 
			
		||||
	choice.FinishReason = &relaycommon.StopFinishReason
 | 
			
		||||
	var response dto.ChatCompletionsStreamResponse
 | 
			
		||||
	response.Object = "chat.completion.chunk"
 | 
			
		||||
@@ -203,7 +203,7 @@ func geminiChatStreamHandler(c *gin.Context, resp *http.Response) (*dto.OpenAIEr
 | 
			
		||||
			err := json.Unmarshal([]byte(data), &dummy)
 | 
			
		||||
			responseText += dummy.Content
 | 
			
		||||
			var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
			choice.Delta.Content = dummy.Content
 | 
			
		||||
			choice.Delta.SetContentString(dummy.Content)
 | 
			
		||||
			response := dto.ChatCompletionsStreamResponse{
 | 
			
		||||
				Id:      fmt.Sprintf("chatcmpl-%s", common.GetUUID()),
 | 
			
		||||
				Object:  "chat.completion.chunk",
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*d
 | 
			
		||||
					err := json.Unmarshal(common.StringToByteSlice(item), &streamResponse)
 | 
			
		||||
					if err == nil {
 | 
			
		||||
						for _, choice := range streamResponse.Choices {
 | 
			
		||||
							responseTextBuilder.WriteString(choice.Delta.Content)
 | 
			
		||||
							responseTextBuilder.WriteString(choice.Delta.GetContentString())
 | 
			
		||||
							if choice.Delta.ToolCalls != nil {
 | 
			
		||||
								if len(choice.Delta.ToolCalls) > toolCount {
 | 
			
		||||
									toolCount = len(choice.Delta.ToolCalls)
 | 
			
		||||
@@ -84,7 +84,7 @@ func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*d
 | 
			
		||||
			} else {
 | 
			
		||||
				for _, streamResponse := range streamResponses {
 | 
			
		||||
					for _, choice := range streamResponse.Choices {
 | 
			
		||||
						responseTextBuilder.WriteString(choice.Delta.Content)
 | 
			
		||||
						responseTextBuilder.WriteString(choice.Delta.GetContentString())
 | 
			
		||||
						if choice.Delta.ToolCalls != nil {
 | 
			
		||||
							if len(choice.Delta.ToolCalls) > toolCount {
 | 
			
		||||
								toolCount = len(choice.Delta.ToolCalls)
 | 
			
		||||
 
 | 
			
		||||
@@ -61,7 +61,7 @@ func responsePaLM2OpenAI(response *PaLMChatResponse) *dto.OpenAITextResponse {
 | 
			
		||||
func streamResponsePaLM2OpenAI(palmResponse *PaLMChatResponse) *dto.ChatCompletionsStreamResponse {
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	if len(palmResponse.Candidates) > 0 {
 | 
			
		||||
		choice.Delta.Content = palmResponse.Candidates[0].Content
 | 
			
		||||
		choice.Delta.SetContentString(palmResponse.Candidates[0].Content)
 | 
			
		||||
	}
 | 
			
		||||
	choice.FinishReason = &relaycommon.StopFinishReason
 | 
			
		||||
	var response dto.ChatCompletionsStreamResponse
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ func streamResponseTencent2OpenAI(TencentResponse *TencentChatResponse) *dto.Cha
 | 
			
		||||
	}
 | 
			
		||||
	if len(TencentResponse.Choices) > 0 {
 | 
			
		||||
		var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
		choice.Delta.Content = TencentResponse.Choices[0].Delta.Content
 | 
			
		||||
		choice.Delta.SetContentString(TencentResponse.Choices[0].Delta.Content)
 | 
			
		||||
		if TencentResponse.Choices[0].FinishReason == "stop" {
 | 
			
		||||
			choice.FinishReason = &relaycommon.StopFinishReason
 | 
			
		||||
		}
 | 
			
		||||
@@ -138,7 +138,7 @@ func tencentStreamHandler(c *gin.Context, resp *http.Response) (*dto.OpenAIError
 | 
			
		||||
			}
 | 
			
		||||
			response := streamResponseTencent2OpenAI(&TencentResponse)
 | 
			
		||||
			if len(response.Choices) != 0 {
 | 
			
		||||
				responseText += response.Choices[0].Delta.Content
 | 
			
		||||
				responseText += response.Choices[0].Delta.GetContentString()
 | 
			
		||||
			}
 | 
			
		||||
			jsonResponse, err := json.Marshal(response)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ func streamResponseXunfei2OpenAI(xunfeiResponse *XunfeiChatResponse) *dto.ChatCo
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	choice.Delta.Content = xunfeiResponse.Payload.Choices.Text[0].Content
 | 
			
		||||
	choice.Delta.SetContentString(xunfeiResponse.Payload.Choices.Text[0].Content)
 | 
			
		||||
	if xunfeiResponse.Payload.Choices.Status == 2 {
 | 
			
		||||
		choice.FinishReason = &relaycommon.StopFinishReason
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ func responseZhipu2OpenAI(response *ZhipuResponse) *dto.OpenAITextResponse {
 | 
			
		||||
 | 
			
		||||
func streamResponseZhipu2OpenAI(zhipuResponse string) *dto.ChatCompletionsStreamResponse {
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	choice.Delta.Content = zhipuResponse
 | 
			
		||||
	choice.Delta.SetContentString(zhipuResponse)
 | 
			
		||||
	response := dto.ChatCompletionsStreamResponse{
 | 
			
		||||
		Object:  "chat.completion.chunk",
 | 
			
		||||
		Created: common.GetTimestamp(),
 | 
			
		||||
@@ -138,7 +138,7 @@ func streamResponseZhipu2OpenAI(zhipuResponse string) *dto.ChatCompletionsStream
 | 
			
		||||
 | 
			
		||||
func streamMetaResponseZhipu2OpenAI(zhipuResponse *ZhipuStreamMetaResponse) (*dto.ChatCompletionsStreamResponse, *dto.Usage) {
 | 
			
		||||
	var choice dto.ChatCompletionsStreamResponseChoice
 | 
			
		||||
	choice.Delta.Content = ""
 | 
			
		||||
	choice.Delta.SetContentString("")
 | 
			
		||||
	choice.FinishReason = &relaycommon.StopFinishReason
 | 
			
		||||
	response := dto.ChatCompletionsStreamResponse{
 | 
			
		||||
		Id:      zhipuResponse.RequestId,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user