diff --git a/server/service/app/ai_claude.go b/server/service/app/ai_claude.go index 5d9026b..ead9ae0 100644 --- a/server/service/app/ai_claude.go +++ b/server/service/app/ai_claude.go @@ -212,7 +212,7 @@ func (s *AiProxyService) forwardClaudeStreamRequest(c *gin.Context, provider *ap reader := bufio.NewReader(httpResp.Body) flusher, _ := c.Writer.(http.Flusher) - // 聚合完整输出用于日志和正则处理 + // 聚合完整输出用于日志 var fullContent bytes.Buffer var totalInputTokens, totalOutputTokens int @@ -235,21 +235,28 @@ func (s *AiProxyService) forwardClaudeStreamRequest(c *gin.Context, provider *ap totalOutputTokens = chunk.Usage.OutputTokens } - // 收集文本内容(不在流式传输时应用正则,避免重复处理) + // 收集文本内容并应用正则处理 if chunk.Delta != nil && chunk.Delta.Text != "" { - fullContent.WriteString(chunk.Delta.Text) + originalText := chunk.Delta.Text + fullContent.WriteString(originalText) + + // 应用输出正则处理 + if injector != nil { + chunk.Delta.Text = injector.ProcessResponse(originalText) + } } - // 直接转发原始响应 + // 重新序列化并转发处理后的响应 + processedData, _ := json.Marshal(chunk) c.Writer.Write([]byte("data: ")) - c.Writer.Write(data) + c.Writer.Write(processedData) c.Writer.Write([]byte("\n\n")) flusher.Flush() } } } - // 流式结束后,对完整内容应用输出正则处理(仅用于日志记录) + // 流式结束后,对完整内容应用输出正则处理(用于日志记录) processedContent := fullContent.String() if injector != nil && processedContent != "" { processedContent = injector.ProcessResponse(processedContent) diff --git a/server/service/app/ai_proxy.go b/server/service/app/ai_proxy.go index 9a0b851..8afe928 100644 --- a/server/service/app/ai_proxy.go +++ b/server/service/app/ai_proxy.go @@ -196,6 +196,13 @@ func (s *AiProxyService) forwardRequest(ctx context.Context, provider *app.AiPro return nil, fmt.Errorf("序列化请求失败: %w", err) } + // 上游请求参数 + global.GVA_LOG.Info("转发 ChatCompletion 请求到上游", + zap.String("provider", provider.Name), + zap.String("model", req.Model), + zap.Any("messages", req.Messages), + ) + url := strings.TrimRight(provider.BaseURL, "/") + "/v1/chat/completions" httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(reqBody)) if err != nil { @@ -238,6 +245,12 @@ func (s *AiProxyService) forwardStreamRequest(c *gin.Context, provider *app.AiPr if err != nil { return err } + // 上游请求参数 + global.GVA_LOG.Info("转发 ChatCompletion 流式请求到上游", + zap.String("provider", provider.Name), + zap.String("model", req.Model), + zap.Any("messages", req.Messages), + ) url := strings.TrimRight(provider.BaseURL, "/") + "/v1/chat/completions" httpReq, err := http.NewRequestWithContext(c.Request.Context(), "POST", url, bytes.NewReader(reqBody)) @@ -302,14 +315,21 @@ func (s *AiProxyService) forwardStreamRequest(c *gin.Context, provider *app.AiPr continue } - // 收集原始内容(不在流式传输时应用正则,避免重复处理) + // 收集原始内容并应用正则处理 if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" { - fullContent.WriteString(chunk.Choices[0].Delta.Content) + originalContent := chunk.Choices[0].Delta.Content + fullContent.WriteString(originalContent) + + // 应用输出正则处理 + if injector != nil { + chunk.Choices[0].Delta.Content = injector.ProcessResponse(originalContent) + } } - // 直接转发原始响应 + // 重新序列化并转发处理后的响应 + processedData, _ := json.Marshal(chunk) c.Writer.Write([]byte("data: ")) - c.Writer.Write(data) + c.Writer.Write(processedData) c.Writer.Write([]byte("\n\n")) flusher.Flush() }