(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response)
| 36 | } |
| 37 | |
| 38 | func xAIStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response) (*dto.Usage, *types.NewAPIError) { |
| 39 | usage := &dto.Usage{} |
| 40 | var responseTextBuilder strings.Builder |
| 41 | var toolCount int |
| 42 | var containStreamUsage bool |
| 43 | |
| 44 | helper.SetEventStreamHeaders(c) |
| 45 | |
| 46 | helper.StreamScannerHandler(c, resp, info, func(data string) bool { |
| 47 | var xAIResp *dto.ChatCompletionsStreamResponse |
| 48 | err := json.Unmarshal([]byte(data), &xAIResp) |
| 49 | if err != nil { |
| 50 | common.SysError("error unmarshalling stream response: " + err.Error()) |
| 51 | return true |
| 52 | } |
| 53 | |
| 54 | // 把 xAI 的usage转换为 OpenAI 的usage |
| 55 | if xAIResp.Usage != nil { |
| 56 | containStreamUsage = true |
| 57 | usage.PromptTokens = xAIResp.Usage.PromptTokens |
| 58 | usage.TotalTokens = xAIResp.Usage.TotalTokens |
| 59 | usage.CompletionTokens = usage.TotalTokens - usage.PromptTokens |
| 60 | } |
| 61 | |
| 62 | openaiResponse := streamResponseXAI2OpenAI(xAIResp, usage) |
| 63 | _ = openai.ProcessStreamResponse(*openaiResponse, &responseTextBuilder, &toolCount) |
| 64 | err = helper.ObjectData(c, openaiResponse) |
| 65 | if err != nil { |
| 66 | common.SysError(err.Error()) |
| 67 | } |
| 68 | return true |
| 69 | }) |
| 70 | |
| 71 | if !containStreamUsage { |
| 72 | usage = service.ResponseText2Usage(responseTextBuilder.String(), info.UpstreamModelName, info.PromptTokens) |
| 73 | usage.CompletionTokens += toolCount * 7 |
| 74 | } |
| 75 | |
| 76 | helper.Done(c) |
| 77 | common.CloseResponseBodyGracefully(resp) |
| 78 | return usage, nil |
| 79 | } |
| 80 | |
| 81 | func xAIHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response) (*dto.Usage, *types.NewAPIError) { |
| 82 | defer common.CloseResponseBodyGracefully(resp) |
no test coverage detected