diff --git a/core/changelog.md b/core/changelog.md index e69de29bb..a82103a25 100644 --- a/core/changelog.md +++ b/core/changelog.md @@ -0,0 +1,4 @@ +feat: send back raw request in extra fields +feat: added support for reasoning in chat completions +feat: enhanced reasoning support in responses api +enhancement: improved internal inter provider conversions for integrations \ No newline at end of file diff --git a/core/providers/anthropic/anthropic.go b/core/providers/anthropic/anthropic.go index 7fa24ef2a..1dd1ac8cb 100644 --- a/core/providers/anthropic/anthropic.go +++ b/core/providers/anthropic/anthropic.go @@ -23,6 +23,7 @@ type AnthropicProvider struct { client *fasthttp.Client // HTTP client for API requests apiVersion string // API version for the provider networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse customProviderConfig *schemas.CustomProviderConfig // Custom provider config } @@ -103,6 +104,7 @@ func NewAnthropicProvider(config *schemas.ProviderConfig, logger schemas.Logger) client: client, apiVersion: "2023-06-01", networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, customProviderConfig: config.CustomProviderConfig, } @@ -199,7 +201,7 @@ func (provider *AnthropicProvider) listModelsByKey(ctx context.Context, key sche // Parse Anthropic's response var anthropicResponse AnthropicListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &anthropicResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &anthropicResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -208,6 +210,11 @@ func (provider *AnthropicProvider) listModelsByKey(ctx context.Context, key sche response := anthropicResponse.ToBifrostListModelsResponse(provider.GetProviderKey(), key.Models) response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse @@ -264,7 +271,7 @@ func (provider *AnthropicProvider) TextCompletion(ctx context.Context, key schem response := acquireAnthropicTextResponse() defer releaseAnthropicTextResponse(response) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -277,6 +284,11 @@ func (provider *AnthropicProvider) TextCompletion(ctx context.Context, key schem bifrostResponse.ExtraFields.RequestType = schemas.TextCompletionRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse @@ -320,11 +332,10 @@ func (provider *AnthropicProvider) ChatCompletion(ctx context.Context, key schem response := AcquireAnthropicMessageResponse() defer ReleaseAnthropicMessageResponse(response) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } - // Create final response bifrostResponse := response.ToBifrostChatResponse() @@ -334,6 +345,11 @@ func (provider *AnthropicProvider) ChatCompletion(ctx context.Context, key schem bifrostResponse.ExtraFields.RequestType = schemas.ChatCompletionRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse @@ -386,6 +402,7 @@ func (provider *AnthropicProvider) ChatCompletionStream(ctx context.Context, pos jsonData, headers, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -403,6 +420,7 @@ func HandleAnthropicChatCompletionStreaming( jsonBody []byte, headers map[string]string, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, postHookRunner schemas.PostHookRunner, @@ -635,6 +653,10 @@ func HandleAnthropicChatCompletionStreaming( return } } + // Set raw request if enabled + if sendBackRawRequest { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, response, nil, nil, nil), responseChan) @@ -672,7 +694,7 @@ func (provider *AnthropicProvider) Responses(ctx context.Context, key schemas.Ke response := AcquireAnthropicMessageResponse() defer ReleaseAnthropicMessageResponse(response) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -686,6 +708,11 @@ func (provider *AnthropicProvider) Responses(ctx context.Context, key schemas.Ke bifrostResponse.ExtraFields.RequestType = schemas.ResponsesRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse @@ -735,6 +762,7 @@ func (provider *AnthropicProvider) ResponsesStream(ctx context.Context, postHook jsonBody, headers, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -752,6 +780,7 @@ func HandleAnthropicResponsesStream( jsonBody []byte, headers map[string]string, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, postHookRunner schemas.PostHookRunner, @@ -959,6 +988,10 @@ func HandleAnthropicResponsesStream( response.Response = &schemas.BifrostResponsesResponse{} } response.Response.Usage = usage + // Set raw request if enabled + if sendBackRawRequest { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, response, nil, nil), responseChan) diff --git a/core/providers/azure/azure.go b/core/providers/azure/azure.go index c344a7606..870ee0d4f 100644 --- a/core/providers/azure/azure.go +++ b/core/providers/azure/azure.go @@ -23,6 +23,7 @@ type AzureProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -47,6 +48,7 @@ func NewAzureProvider(config *schemas.ProviderConfig, logger schemas.Logger) (*A logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -192,7 +194,7 @@ func (provider *AzureProvider) listModelsByKey(ctx context.Context, key schemas. // Parse Azure-specific response azureResponse := &AzureListModelsResponse{} - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, azureResponse, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, azureResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -205,6 +207,12 @@ func (provider *AzureProvider) listModelsByKey(ctx context.Context, key schemas. response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -263,7 +271,7 @@ func (provider *AzureProvider) TextCompletion(ctx context.Context, key schemas.K response := &schemas.BifrostTextCompletionResponse{} - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -274,6 +282,11 @@ func (provider *AzureProvider) TextCompletion(ctx context.Context, key schemas.K response.ExtraFields.RequestType = schemas.TextCompletionRequest response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse @@ -324,6 +337,7 @@ func (provider *AzureProvider) TextCompletionStream(ctx context.Context, postHoo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -388,18 +402,19 @@ func (provider *AzureProvider) ChatCompletion(ctx context.Context, key schemas.K } response := &schemas.BifrostChatResponse{} + var rawRequest interface{} var rawResponse interface{} if schemas.IsAnthropicModel(deployment) { anthropicResponse := anthropic.AcquireAnthropicMessageResponse() defer anthropic.ReleaseAnthropicMessageResponse(anthropicResponse) - rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, anthropicResponse, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, anthropicResponse, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } response = anthropicResponse.ToBifrostChatResponse() } else { - rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, response, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -411,6 +426,11 @@ func (provider *AzureProvider) ChatCompletion(ctx context.Context, key schemas.K response.ExtraFields.Latency = latency.Milliseconds() response.ExtraFields.RequestType = schemas.ChatCompletionRequest + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse @@ -472,6 +492,7 @@ func (provider *AzureProvider) ChatCompletionStream(ctx context.Context, postHoo jsonData, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -499,6 +520,7 @@ func (provider *AzureProvider) ChatCompletionStream(ctx context.Context, postHoo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -570,18 +592,19 @@ func (provider *AzureProvider) Responses(ctx context.Context, key schemas.Key, r } response := &schemas.BifrostResponsesResponse{} + var rawRequest interface{} var rawResponse interface{} if schemas.IsAnthropicModel(deployment) { anthropicResponse := anthropic.AcquireAnthropicMessageResponse() defer anthropic.ReleaseAnthropicMessageResponse(anthropicResponse) - rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, anthropicResponse, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, anthropicResponse, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } response = anthropicResponse.ToBifrostResponsesResponse() } else { - rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, response, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr = providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -593,6 +616,11 @@ func (provider *AzureProvider) Responses(ctx context.Context, key schemas.Key, r response.ExtraFields.Latency = latency.Milliseconds() response.ExtraFields.RequestType = schemas.ResponsesRequest + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse @@ -651,6 +679,7 @@ func (provider *AzureProvider) ResponsesStream(ctx context.Context, postHookRunn jsonData, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -679,6 +708,7 @@ func (provider *AzureProvider) ResponsesStream(ctx context.Context, postHookRunn request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -728,7 +758,7 @@ func (provider *AzureProvider) Embedding(ctx context.Context, key schemas.Key, r response := &schemas.BifrostEmbeddingResponse{} // Use enhanced response handler with pre-allocated response - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -739,6 +769,12 @@ func (provider *AzureProvider) Embedding(ctx context.Context, key schemas.Key, r response.ExtraFields.ModelDeployment = deployment response.ExtraFields.RequestType = schemas.EmbeddingRequest + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } diff --git a/core/providers/bedrock/bedrock.go b/core/providers/bedrock/bedrock.go index 6ea273a7a..c8d9cf2c2 100644 --- a/core/providers/bedrock/bedrock.go +++ b/core/providers/bedrock/bedrock.go @@ -31,6 +31,7 @@ type BedrockProvider struct { client *http.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers customProviderConfig *schemas.CustomProviderConfig // Custom provider config + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -73,6 +74,7 @@ func NewBedrockProvider(config *schemas.ProviderConfig, logger schemas.Logger) ( client: client, networkConfig: config.NetworkConfig, customProviderConfig: config.CustomProviderConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -447,7 +449,7 @@ func (provider *BedrockProvider) listModelsByKey(ctx context.Context, key schema // Parse Bedrock-specific response bedrockResponse := &BedrockListModelsResponse{} - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, bedrockResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, bedrockResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -460,6 +462,12 @@ func (provider *BedrockProvider) listModelsByKey(ctx context.Context, key schema response.ExtraFields.Latency = time.Since(startTime).Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -540,6 +548,11 @@ func (provider *BedrockProvider) TextCompletion(ctx context.Context, key schemas bifrostResponse.ExtraFields.RequestType = schemas.TextCompletionRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&bifrostResponse.ExtraFields, jsonData) + } + // Parse raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { var rawResponse interface{} @@ -714,6 +727,11 @@ func (provider *BedrockProvider) ChatCompletion(ctx context.Context, key schemas bifrostResponse.ExtraFields.RequestType = schemas.ChatCompletionRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&bifrostResponse.ExtraFields, jsonData) + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { var rawResponse interface{} @@ -881,6 +899,10 @@ func (provider *BedrockProvider) ChatCompletionStream(ctx context.Context, postH // Send final response response := providerUtils.CreateBifrostChatCompletionChunkResponse(id, usage, finishReason, chunkIndex, schemas.ChatCompletionStreamRequest, providerName, request.Model) response.ExtraFields.ModelDeployment = deployment + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonData) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, response, nil, nil, nil), responseChan) @@ -946,6 +968,11 @@ func (provider *BedrockProvider) Responses(ctx context.Context, key schemas.Key, bifrostResponse.ExtraFields.RequestType = schemas.ResponsesRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&bifrostResponse.ExtraFields, jsonData) + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { var rawResponse interface{} @@ -1029,6 +1056,10 @@ func (provider *BedrockProvider) ResponsesStream(ctx context.Context, postHookRu } if i == len(finalResponses)-1 { + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&finalResponse.ExtraFields, jsonData) + } finalResponse.ExtraFields.Latency = time.Since(startTime).Milliseconds() } diff --git a/core/providers/cerebras/cerebras.go b/core/providers/cerebras/cerebras.go index a15465796..68cb9fa45 100644 --- a/core/providers/cerebras/cerebras.go +++ b/core/providers/cerebras/cerebras.go @@ -17,6 +17,7 @@ type CerebrasProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -47,6 +48,7 @@ func NewCerebrasProvider(config *schemas.ProviderConfig, logger schemas.Logger) logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -66,6 +68,7 @@ func (provider *CerebrasProvider) ListModels(ctx context.Context, keys []schemas keys, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -83,6 +86,7 @@ func (provider *CerebrasProvider) TextCompletion(ctx context.Context, key schema key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -104,6 +108,7 @@ func (provider *CerebrasProvider) TextCompletionStream(ctx context.Context, post request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -121,6 +126,7 @@ func (provider *CerebrasProvider) ChatCompletion(ctx context.Context, key schema request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -144,6 +150,7 @@ func (provider *CerebrasProvider) ChatCompletionStream(ctx context.Context, post request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.Cerebras, postHookRunner, diff --git a/core/providers/cohere/cohere.go b/core/providers/cohere/cohere.go index b2fe7ec6d..703710d85 100644 --- a/core/providers/cohere/cohere.go +++ b/core/providers/cohere/cohere.go @@ -68,6 +68,7 @@ type CohereProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse customProviderConfig *schemas.CustomProviderConfig // Custom provider config } @@ -106,6 +107,7 @@ func NewCohereProvider(config *schemas.ProviderConfig, logger schemas.Logger) (* client: client, networkConfig: config.NetworkConfig, customProviderConfig: config.CustomProviderConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -218,7 +220,7 @@ func (provider *CohereProvider) listModelsByKey(ctx context.Context, key schemas // Parse Cohere list models response var cohereResponse CohereListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, &cohereResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, &cohereResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -228,6 +230,12 @@ func (provider *CohereProvider) listModelsByKey(ctx context.Context, key schemas response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -294,7 +302,7 @@ func (provider *CohereProvider) ChatCompletion(ctx context.Context, key schemas. response := acquireCohereResponse() defer releaseCohereResponse(response) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -307,6 +315,11 @@ func (provider *CohereProvider) ChatCompletion(ctx context.Context, key schemas. bifrostResponse.ExtraFields.RequestType = schemas.ChatCompletionRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse @@ -466,6 +479,10 @@ func (provider *CohereProvider) ChatCompletionStream(ctx context.Context, postHo } if isLastChunk { + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, response, nil, nil, nil), responseChan) @@ -511,7 +528,7 @@ func (provider *CohereProvider) Responses(ctx context.Context, key schemas.Key, response := acquireCohereResponse() defer releaseCohereResponse(response) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -526,6 +543,11 @@ func (provider *CohereProvider) Responses(ctx context.Context, key schemas.Key, bifrostResponse.ExtraFields.RequestType = schemas.ResponsesRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse @@ -696,6 +718,10 @@ func (provider *CohereProvider) ResponsesStream(ctx context.Context, postHookRun if response.Response == nil { response.Response = &schemas.BifrostResponsesResponse{} } + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, response, nil, nil), responseChan) @@ -745,7 +771,7 @@ func (provider *CohereProvider) Embedding(ctx context.Context, key schemas.Key, response := acquireCohereEmbeddingResponse() defer releaseCohereEmbeddingResponse(response) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, response, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -758,6 +784,11 @@ func (provider *CohereProvider) Embedding(ctx context.Context, key schemas.Key, bifrostResponse.ExtraFields.RequestType = schemas.EmbeddingRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse diff --git a/core/providers/elevenlabs/elevenlabs.go b/core/providers/elevenlabs/elevenlabs.go index f19ec0859..50e475042 100644 --- a/core/providers/elevenlabs/elevenlabs.go +++ b/core/providers/elevenlabs/elevenlabs.go @@ -24,6 +24,7 @@ type ElevenlabsProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse customProviderConfig *schemas.CustomProviderConfig // Custom provider config } @@ -56,6 +57,7 @@ func NewElevenlabsProvider(config *schemas.ProviderConfig, logger schemas.Logger client: client, networkConfig: config.NetworkConfig, customProviderConfig: config.CustomProviderConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, } } @@ -98,7 +100,7 @@ func (provider *ElevenlabsProvider) listModelsByKey(ctx context.Context, key sch } var elevenlabsResponse ElevenlabsListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &elevenlabsResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &elevenlabsResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -107,6 +109,12 @@ func (provider *ElevenlabsProvider) listModelsByKey(ctx context.Context, key sch response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -245,6 +253,10 @@ func (provider *ElevenlabsProvider) Speech(ctx context.Context, key schemas.Key, }, } + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&bifrostResponse.ExtraFields, jsonData) + } + if withTimestampsRequest { var timestampResponse ElevenlabsSpeechWithTimestampsResponse if err := sonic.Unmarshal(body, ×tampResponse); err != nil { @@ -421,6 +433,10 @@ func (provider *ElevenlabsProvider) SpeechStream(ctx context.Context, postHookRu }, } + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&finalResponse.ExtraFields, jsonBody) + } ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, nil, finalResponse, nil), responseChan) }() @@ -491,13 +507,6 @@ func (provider *ElevenlabsProvider) Transcription(ctx context.Context, key schem return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderResponseDecode, err, providerName) } - var rawResponse interface{} - if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { - if err := sonic.Unmarshal(responseBody, &rawResponse); err != nil { - return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRawResponseUnmarshal, err, providerName) - } - } - chunks, err := parseTranscriptionResponse(responseBody) if err != nil { return nil, providerUtils.NewBifrostOperationError(err.Error(), nil, providerName) @@ -516,6 +525,10 @@ func (provider *ElevenlabsProvider) Transcription(ctx context.Context, key schem } if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { + var rawResponse interface{} + if err := sonic.Unmarshal(responseBody, &rawResponse); err != nil { + return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRawResponseUnmarshal, err, providerName) + } response.ExtraFields.RawResponse = rawResponse } diff --git a/core/providers/gemini/gemini.go b/core/providers/gemini/gemini.go index 129bb9d2b..12b9a2318 100644 --- a/core/providers/gemini/gemini.go +++ b/core/providers/gemini/gemini.go @@ -24,6 +24,7 @@ type GeminiProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse customProviderConfig *schemas.CustomProviderConfig // Custom provider config } @@ -56,6 +57,7 @@ func NewGeminiProvider(config *schemas.ProviderConfig, logger schemas.Logger) *G client: client, networkConfig: config.NetworkConfig, customProviderConfig: config.CustomProviderConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, } } @@ -159,7 +161,7 @@ func (provider *GeminiProvider) listModelsByKey(ctx context.Context, key schemas // Parse Gemini's response var geminiResponse GeminiListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &geminiResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &geminiResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -168,6 +170,12 @@ func (provider *GeminiProvider) listModelsByKey(ctx context.Context, key schemas response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -259,7 +267,7 @@ func (provider *GeminiProvider) ChatCompletion(ctx context.Context, key schemas. response := &schemas.BifrostChatResponse{} - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, jsonData, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -283,6 +291,12 @@ func (provider *GeminiProvider) ChatCompletion(ctx context.Context, key schemas. response.ExtraFields.ModelRequested = request.Model response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -313,6 +327,7 @@ func (provider *GeminiProvider) ChatCompletionStream(ctx context.Context, postHo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -366,6 +381,7 @@ func (provider *GeminiProvider) Embedding(ctx context.Context, key schemas.Key, key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -404,6 +420,11 @@ func (provider *GeminiProvider) Speech(ctx context.Context, key schemas.Key, req response.ExtraFields.ModelRequested = request.Model response.ExtraFields.RequestType = schemas.SpeechRequest response.ExtraFields.Latency = latency.Milliseconds() + + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonData) + } + if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -614,6 +635,10 @@ func (provider *GeminiProvider) SpeechStream(ctx context.Context, postHookRunner }, } + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, nil, response, nil), responseChan) } @@ -653,6 +678,10 @@ func (provider *GeminiProvider) Transcription(ctx context.Context, key schemas.K response.ExtraFields.RequestType = schemas.TranscriptionRequest response.ExtraFields.Latency = latency.Milliseconds() + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonData) + } + if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -877,6 +906,10 @@ func (provider *GeminiProvider) TranscriptionStream(ctx context.Context, postHoo }, } + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, nil, nil, response), responseChan) } diff --git a/core/providers/groq/groq.go b/core/providers/groq/groq.go index b7cec4e8e..c28386ff2 100644 --- a/core/providers/groq/groq.go +++ b/core/providers/groq/groq.go @@ -17,6 +17,7 @@ type GroqProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -52,6 +53,7 @@ func NewGroqProvider(config *schemas.ProviderConfig, logger schemas.Logger) (*Gr logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -71,6 +73,7 @@ func (provider *GroqProvider) ListModels(ctx context.Context, keys []schemas.Key keys, provider.networkConfig.ExtraHeaders, schemas.Groq, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -160,6 +163,7 @@ func (provider *GroqProvider) ChatCompletion(ctx context.Context, key schemas.Ke request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -183,6 +187,7 @@ func (provider *GroqProvider) ChatCompletionStream(ctx context.Context, postHook request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.Groq, postHookRunner, diff --git a/core/providers/mistral/mistral.go b/core/providers/mistral/mistral.go index 96042cfb0..6e093f710 100644 --- a/core/providers/mistral/mistral.go +++ b/core/providers/mistral/mistral.go @@ -18,6 +18,7 @@ type MistralProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -53,6 +54,7 @@ func NewMistralProvider(config *schemas.ProviderConfig, logger schemas.Logger) * logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, } } @@ -100,7 +102,7 @@ func (provider *MistralProvider) listModelsByKey(ctx context.Context, key schema // Parse Mistral's response var mistralResponse MistralListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, &mistralResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, &mistralResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -110,6 +112,11 @@ func (provider *MistralProvider) listModelsByKey(ctx context.Context, key schema response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse @@ -151,6 +158,7 @@ func (provider *MistralProvider) ChatCompletion(ctx context.Context, key schemas request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -174,6 +182,7 @@ func (provider *MistralProvider) ChatCompletionStream(ctx context.Context, postH request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.Mistral, postHookRunner, @@ -222,6 +231,7 @@ func (provider *MistralProvider) Embedding(ctx context.Context, key schemas.Key, key, provider.networkConfig.ExtraHeaders, schemas.Mistral, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) diff --git a/core/providers/ollama/ollama.go b/core/providers/ollama/ollama.go index 0bcc399c9..5fdd00406 100644 --- a/core/providers/ollama/ollama.go +++ b/core/providers/ollama/ollama.go @@ -19,6 +19,7 @@ type OllamaProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -55,6 +56,7 @@ func NewOllamaProvider(config *schemas.ProviderConfig, logger schemas.Logger) (* logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -77,6 +79,7 @@ func (provider *OllamaProvider) ListModels(ctx context.Context, keys []schemas.K keys, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -92,6 +95,7 @@ func (provider *OllamaProvider) TextCompletion(ctx context.Context, key schemas. key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -108,6 +112,7 @@ func (provider *OllamaProvider) TextCompletionStream(ctx context.Context, postHo request, nil, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -125,6 +130,7 @@ func (provider *OllamaProvider) ChatCompletion(ctx context.Context, key schemas. request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -144,6 +150,7 @@ func (provider *OllamaProvider) ChatCompletionStream(ctx context.Context, postHo request, nil, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.Ollama, postHookRunner, @@ -190,6 +197,7 @@ func (provider *OllamaProvider) Embedding(ctx context.Context, key schemas.Key, key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) diff --git a/core/providers/openai/openai.go b/core/providers/openai/openai.go index c2edb4b68..5e40db546 100644 --- a/core/providers/openai/openai.go +++ b/core/providers/openai/openai.go @@ -25,6 +25,7 @@ type OpenAIProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse customProviderConfig *schemas.CustomProviderConfig // Custom provider config } @@ -61,6 +62,7 @@ func NewOpenAIProvider(config *schemas.ProviderConfig, logger schemas.Logger) *O logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, customProviderConfig: config.CustomProviderConfig, } @@ -91,6 +93,7 @@ func (provider *OpenAIProvider) ListModels(ctx context.Context, keys []schemas.K schemas.Key{}, provider.networkConfig.ExtraHeaders, providerName, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), ) } @@ -102,6 +105,7 @@ func (provider *OpenAIProvider) ListModels(ctx context.Context, keys []schemas.K keys, provider.networkConfig.ExtraHeaders, providerName, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -116,6 +120,7 @@ func listModelsByKey( key schemas.Key, extraHeaders map[string]string, providerName schemas.ModelProvider, + sendBackRawRequest bool, sendBackRawResponse bool, ) (*schemas.BifrostListModelsResponse, *schemas.BifrostError) { // Create request @@ -153,7 +158,7 @@ func listModelsByKey( openaiResponse := &OpenAIListModelsResponse{} // Use enhanced response handler with pre-allocated response - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, openaiResponse, sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, openaiResponse, nil, sendBackRawRequest, sendBackRawResponse) if bifrostErr != nil { return nil, bifrostErr } @@ -163,6 +168,13 @@ func listModelsByKey( response.ExtraFields.Provider = providerName response.ExtraFields.RequestType = schemas.ListModelsRequest response.ExtraFields.Latency = latency.Milliseconds() + + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if sendBackRawResponse { response.ExtraFields.RawResponse = rawResponse } @@ -179,14 +191,15 @@ func HandleOpenAIListModelsRequest( keys []schemas.Key, extraHeaders map[string]string, providerName schemas.ModelProvider, + sendBackRawRequest bool, sendBackRawResponse bool, logger schemas.Logger, ) (*schemas.BifrostListModelsResponse, *schemas.BifrostError) { if len(keys) == 0 { - return listModelsByKey(ctx, client, url, schemas.Key{}, extraHeaders, providerName, sendBackRawResponse) + return listModelsByKey(ctx, client, url, schemas.Key{}, extraHeaders, providerName, sendBackRawRequest, sendBackRawResponse) } listModelsByKeyWrapper := func(ctx context.Context, key schemas.Key, request *schemas.BifrostListModelsRequest) (*schemas.BifrostListModelsResponse, *schemas.BifrostError) { - return listModelsByKey(ctx, client, url, key, extraHeaders, providerName, sendBackRawResponse) + return listModelsByKey(ctx, client, url, key, extraHeaders, providerName, sendBackRawRequest, sendBackRawResponse) } return providerUtils.HandleMultipleListModelsRequests( ctx, @@ -211,6 +224,7 @@ func (provider *OpenAIProvider) TextCompletion(ctx context.Context, key schemas. key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -225,6 +239,7 @@ func HandleOpenAITextCompletionRequest( key schemas.Key, extraHeaders map[string]string, providerName schemas.ModelProvider, + sendBackRawRequest bool, sendBackRawResponse bool, logger schemas.Logger, ) (*schemas.BifrostTextCompletionResponse, *schemas.BifrostError) { @@ -274,7 +289,7 @@ func HandleOpenAITextCompletionRequest( response := &schemas.BifrostTextCompletionResponse{} - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, jsonData, sendBackRawRequest, sendBackRawResponse) if bifrostErr != nil { return nil, bifrostErr } @@ -284,6 +299,11 @@ func HandleOpenAITextCompletionRequest( response.ExtraFields.RequestType = schemas.TextCompletionRequest response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if sendBackRawResponse { response.ExtraFields.RawResponse = rawResponse @@ -310,6 +330,7 @@ func (provider *OpenAIProvider) TextCompletionStream(ctx context.Context, postHo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -327,6 +348,7 @@ func HandleOpenAITextCompletionStreaming( request *schemas.BifrostTextCompletionRequest, authHeader map[string]string, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, postHookRunner schemas.PostHookRunner, @@ -571,6 +593,10 @@ func HandleOpenAITextCompletionStreaming( if postResponseConverter != nil { response = postResponseConverter(response) } + // Set raw request if enabled + if sendBackRawRequest { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(response, nil, nil, nil, nil), responseChan) @@ -596,6 +622,7 @@ func (provider *OpenAIProvider) ChatCompletion(ctx context.Context, key schemas. request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -610,6 +637,7 @@ func HandleOpenAIChatCompletionRequest( request *schemas.BifrostChatRequest, key schemas.Key, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, logger schemas.Logger, @@ -662,21 +690,26 @@ func HandleOpenAIChatCompletionRequest( response := &schemas.BifrostChatResponse{} // Use enhanced response handler with pre-allocated response - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, jsonData, sendBackRawRequest, sendBackRawResponse) if bifrostErr != nil { return nil, bifrostErr } - // Set raw response if enabled - if sendBackRawResponse { - response.ExtraFields.RawResponse = rawResponse - } - response.ExtraFields.Provider = providerName response.ExtraFields.ModelRequested = request.Model response.ExtraFields.RequestType = schemas.ChatCompletionRequest response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled + if sendBackRawResponse { + response.ExtraFields.RawResponse = rawResponse + } + return response, nil } @@ -700,6 +733,7 @@ func (provider *OpenAIProvider) ChatCompletionStream(ctx context.Context, postHo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -719,6 +753,7 @@ func HandleOpenAIChatCompletionStreaming( request *schemas.BifrostChatRequest, authHeader map[string]string, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, postHookRunner schemas.PostHookRunner, @@ -939,6 +974,10 @@ func HandleOpenAIChatCompletionStreaming( } if response.Type == schemas.ResponsesStreamResponseTypeCompleted { + // Set raw request if enabled + if sendBackRawRequest { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, response, nil, nil), responseChan) @@ -1041,6 +1080,10 @@ func HandleOpenAIChatCompletionStreaming( if postResponseConverter != nil { response = postResponseConverter(response) } + // Set raw request if enabled + if sendBackRawRequest { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, response, nil, nil, nil), responseChan) @@ -1064,6 +1107,7 @@ func (provider *OpenAIProvider) Responses(ctx context.Context, key schemas.Key, request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -1078,6 +1122,7 @@ func HandleOpenAIResponsesRequest( request *schemas.BifrostResponsesRequest, key schemas.Key, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, logger schemas.Logger, @@ -1131,21 +1176,26 @@ func HandleOpenAIResponsesRequest( response := &schemas.BifrostResponsesResponse{} // Use enhanced response handler with pre-allocated response - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, jsonData, sendBackRawRequest, sendBackRawResponse) if bifrostErr != nil { return nil, bifrostErr } - // Set raw response if enabled - if sendBackRawResponse { - response.ExtraFields.RawResponse = rawResponse - } - response.ExtraFields.Provider = providerName response.ExtraFields.ModelRequested = request.Model response.ExtraFields.RequestType = schemas.ResponsesRequest response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled + if sendBackRawResponse { + response.ExtraFields.RawResponse = rawResponse + } + return response, nil } @@ -1167,6 +1217,7 @@ func (provider *OpenAIProvider) ResponsesStream(ctx context.Context, postHookRun request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -1185,6 +1236,7 @@ func HandleOpenAIResponsesStreaming( request *schemas.BifrostResponsesRequest, authHeader map[string]string, extraHeaders map[string]string, + sendBackRawRequest bool, sendBackRawResponse bool, providerName schemas.ModelProvider, postHookRunner schemas.PostHookRunner, @@ -1373,6 +1425,10 @@ func HandleOpenAIResponsesStreaming( response.ExtraFields.ChunkIndex = response.SequenceNumber if response.Type == schemas.ResponsesStreamResponseTypeCompleted || response.Type == schemas.ResponsesStreamResponseTypeIncomplete { + // Set raw request if enabled + if sendBackRawRequest { + providerUtils.ParseAndSetRawRequest(&response.ExtraFields, jsonBody) + } response.ExtraFields.Latency = time.Since(startTime).Milliseconds() ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true) providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, &response, nil, nil), responseChan) @@ -1412,6 +1468,7 @@ func (provider *OpenAIProvider) Embedding(ctx context.Context, key schemas.Key, key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -1427,6 +1484,7 @@ func HandleOpenAIEmbeddingRequest( key schemas.Key, extraHeaders map[string]string, providerName schemas.ModelProvider, + sendBackRawRequest bool, sendBackRawResponse bool, logger schemas.Logger, ) (*schemas.BifrostEmbeddingResponse, *schemas.BifrostError) { @@ -1479,7 +1537,7 @@ func HandleOpenAIEmbeddingRequest( response := &schemas.BifrostEmbeddingResponse{} // Use enhanced response handler with pre-allocated response - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(body, response, jsonData, sendBackRawRequest, sendBackRawResponse) if bifrostErr != nil { return nil, bifrostErr } @@ -1489,6 +1547,12 @@ func HandleOpenAIEmbeddingRequest( response.ExtraFields.RequestType = schemas.EmbeddingRequest response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if sendBackRawResponse { response.ExtraFields.RawResponse = rawResponse } diff --git a/core/providers/openrouter/openrouter.go b/core/providers/openrouter/openrouter.go index af019e2d7..1271e26cc 100644 --- a/core/providers/openrouter/openrouter.go +++ b/core/providers/openrouter/openrouter.go @@ -19,6 +19,7 @@ type OpenRouterProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -49,6 +50,7 @@ func NewOpenRouterProvider(config *schemas.ProviderConfig, logger schemas.Logger logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, } } @@ -95,7 +97,8 @@ func (provider *OpenRouterProvider) listModelsByKey(ctx context.Context, key sch responseBody := append([]byte(nil), resp.Body()...) var openrouterResponse schemas.BifrostListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, &openrouterResponse, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + // Pass nil requestBody for GET requests - HandleProviderResponse will skip raw request capture + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, &openrouterResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -106,6 +109,11 @@ func (provider *OpenRouterProvider) listModelsByKey(ctx context.Context, key sch openrouterResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + openrouterResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { openrouterResponse.ExtraFields.RawResponse = rawResponse @@ -136,6 +144,7 @@ func (provider *OpenRouterProvider) TextCompletion(ctx context.Context, key sche key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -156,6 +165,7 @@ func (provider *OpenRouterProvider) TextCompletionStream(ctx context.Context, po request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -173,6 +183,7 @@ func (provider *OpenRouterProvider) ChatCompletion(ctx context.Context, key sche request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -196,6 +207,7 @@ func (provider *OpenRouterProvider) ChatCompletionStream(ctx context.Context, po request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.OpenRouter, postHookRunner, @@ -215,6 +227,7 @@ func (provider *OpenRouterProvider) Responses(ctx context.Context, key schemas.K request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -234,6 +247,7 @@ func (provider *OpenRouterProvider) ResponsesStream(ctx context.Context, postHoo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, diff --git a/core/providers/parasail/parasail.go b/core/providers/parasail/parasail.go index 62da04b4b..df7764ec2 100644 --- a/core/providers/parasail/parasail.go +++ b/core/providers/parasail/parasail.go @@ -18,6 +18,7 @@ type ParasailProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -48,6 +49,7 @@ func NewParasailProvider(config *schemas.ProviderConfig, logger schemas.Logger) logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -67,6 +69,7 @@ func (provider *ParasailProvider) ListModels(ctx context.Context, keys []schemas keys, provider.networkConfig.ExtraHeaders, schemas.Parasail, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -93,6 +96,7 @@ func (provider *ParasailProvider) ChatCompletion(ctx context.Context, key schema request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -116,6 +120,7 @@ func (provider *ParasailProvider) ChatCompletionStream(ctx context.Context, post request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.Parasail, postHookRunner, diff --git a/core/providers/perplexity/perplexity.go b/core/providers/perplexity/perplexity.go index 5e45e4756..e77878e49 100644 --- a/core/providers/perplexity/perplexity.go +++ b/core/providers/perplexity/perplexity.go @@ -20,6 +20,7 @@ type PerplexityProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -50,6 +51,7 @@ func NewPerplexityProvider(config *schemas.ProviderConfig, logger schemas.Logger logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -140,7 +142,7 @@ func (provider *PerplexityProvider) ChatCompletion(ctx context.Context, key sche } var response PerplexityChatResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, &response, providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(responseBody, &response, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -153,6 +155,11 @@ func (provider *PerplexityProvider) ChatCompletion(ctx context.Context, key sche bifrostResponse.ExtraFields.RequestType = schemas.ChatCompletionRequest bifrostResponse.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + bifrostResponse.ExtraFields.RawRequest = rawRequest + } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { bifrostResponse.ExtraFields.RawResponse = rawResponse @@ -183,6 +190,7 @@ func (provider *PerplexityProvider) ChatCompletionStream(ctx context.Context, po request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.Perplexity, postHookRunner, diff --git a/core/providers/sgl/sgl.go b/core/providers/sgl/sgl.go index 686419711..af33fc720 100644 --- a/core/providers/sgl/sgl.go +++ b/core/providers/sgl/sgl.go @@ -19,6 +19,7 @@ type SGLProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -55,6 +56,7 @@ func NewSGLProvider(config *schemas.ProviderConfig, logger schemas.Logger) (*SGL logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -74,6 +76,7 @@ func (provider *SGLProvider) ListModels(ctx context.Context, keys []schemas.Key, keys, provider.networkConfig.ExtraHeaders, schemas.SGL, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -89,6 +92,7 @@ func (provider *SGLProvider) TextCompletion(ctx context.Context, key schemas.Key key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) @@ -105,6 +109,7 @@ func (provider *SGLProvider) TextCompletionStream(ctx context.Context, postHookR request, nil, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, @@ -122,6 +127,7 @@ func (provider *SGLProvider) ChatCompletion(ctx context.Context, key schemas.Key request, key, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), provider.logger, @@ -141,6 +147,7 @@ func (provider *SGLProvider) ChatCompletionStream(ctx context.Context, postHookR request, nil, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), schemas.SGL, postHookRunner, @@ -187,6 +194,7 @@ func (provider *SGLProvider) Embedding(ctx context.Context, key schemas.Key, req key, provider.networkConfig.ExtraHeaders, provider.GetProviderKey(), + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.logger, ) diff --git a/core/providers/utils/utils.go b/core/providers/utils/utils.go index efa500528..ee80dcd8b 100644 --- a/core/providers/utils/utils.go +++ b/core/providers/utils/utils.go @@ -341,27 +341,48 @@ func HandleProviderAPIError(resp *fasthttp.Response, errorResp any) *schemas.Bif // It attempts to parse the response body into the provided response type // and returns either the parsed response or a BifrostError if parsing fails. // If sendBackRawResponse is true, it returns the raw response interface, otherwise nil. -func HandleProviderResponse[T any](responseBody []byte, response *T, sendBackRawResponse bool) (interface{}, *schemas.BifrostError) { +func HandleProviderResponse[T any](responseBody []byte, response *T, requestBody []byte, sendBackRawRequest bool, sendBackRawResponse bool) (interface{}, interface{}, *schemas.BifrostError) { + var rawRequest interface{} var rawResponse interface{} var wg sync.WaitGroup - var structuredErr, rawErr error + var structuredErr, rawRequestErr, rawResponseErr error - wg.Add(2) + // Skip raw request capture if requestBody is nil (e.g., for GET requests) + shouldCaptureRawRequest := sendBackRawRequest && requestBody != nil + + // Count goroutines to spawn + numGoroutines := 1 // Always unmarshal structured response + if shouldCaptureRawRequest { + numGoroutines++ + } + if sendBackRawResponse { + numGoroutines++ + } + + wg.Add(numGoroutines) go func() { defer wg.Done() structuredErr = sonic.Unmarshal(responseBody, response) }() - go func() { - defer wg.Done() - if sendBackRawResponse { - rawErr = sonic.Unmarshal(responseBody, &rawResponse) - } - }() + + if shouldCaptureRawRequest { + go func() { + defer wg.Done() + rawRequestErr = sonic.Unmarshal(requestBody, &rawRequest) + }() + } + + if sendBackRawResponse { + go func() { + defer wg.Done() + rawResponseErr = sonic.Unmarshal(responseBody, &rawResponse) + }() + } wg.Wait() if structuredErr != nil { - return nil, &schemas.BifrostError{ + return nil, nil, &schemas.BifrostError{ IsBifrostError: true, Error: &schemas.ErrorField{ Message: schemas.ErrProviderResponseUnmarshal, @@ -370,21 +391,51 @@ func HandleProviderResponse[T any](responseBody []byte, response *T, sendBackRaw } } - if sendBackRawResponse { - if rawErr != nil { - return nil, &schemas.BifrostError{ + if shouldCaptureRawRequest { + if rawRequestErr != nil { + return nil, nil, &schemas.BifrostError{ + IsBifrostError: true, + Error: &schemas.ErrorField{ + Message: schemas.ErrProviderRawRequestUnmarshal, + Error: rawRequestErr, + }, + } + } + if sendBackRawResponse && rawResponseErr != nil { + return nil, nil, &schemas.BifrostError{ IsBifrostError: true, Error: &schemas.ErrorField{ Message: schemas.ErrProviderRawResponseUnmarshal, - Error: rawErr, + Error: rawResponseErr, }, } } + return rawRequest, rawResponse, nil + } - return rawResponse, nil + if sendBackRawResponse { + if rawResponseErr != nil { + return nil, nil, &schemas.BifrostError{ + IsBifrostError: true, + Error: &schemas.ErrorField{ + Message: schemas.ErrProviderRawResponseUnmarshal, + Error: rawResponseErr, + }, + } + } + return rawRequest, rawResponse, nil } - return nil, nil + return nil, nil, nil +} + +func ParseAndSetRawRequest(extraFields *schemas.BifrostResponseExtraFields, jsonBody []byte) { + var rawRequest interface{} + if err := sonic.Unmarshal(jsonBody, &rawRequest); err != nil { + logger.Warn(fmt.Sprintf("Failed to parse raw request: %v", err)) + } else { + extraFields.RawRequest = rawRequest + } } // NewUnsupportedOperationError creates a standardized error for unsupported operations. @@ -479,6 +530,16 @@ func NewProviderAPIError(message string, err error, statusCode int, providerType } } +// ShouldSendBackRawRequest checks if the raw request should be sent back. +// Context overrides are intentionally restricted to asymmetric behavior: a context value can only +// promote false→true and will not override a true config to false, avoiding accidental suppression. +func ShouldSendBackRawRequest(ctx context.Context, defaultSendBackRawRequest bool) bool { + if sendBackRawRequest, ok := ctx.Value(schemas.BifrostContextKeySendBackRawRequest).(bool); ok && sendBackRawRequest { + return sendBackRawRequest + } + return defaultSendBackRawRequest +} + // ShouldSendBackRawResponse checks if the raw response should be sent back, and returns it if it exists. func ShouldSendBackRawResponse(ctx context.Context, defaultSendBackRawResponse bool) bool { if sendBackRawResponse, ok := ctx.Value(schemas.BifrostContextKeySendBackRawResponse).(bool); ok && sendBackRawResponse { diff --git a/core/providers/vertex/vertex.go b/core/providers/vertex/vertex.go index b95d49f86..d63b91308 100644 --- a/core/providers/vertex/vertex.go +++ b/core/providers/vertex/vertex.go @@ -58,6 +58,7 @@ type VertexProvider struct { logger schemas.Logger // Logger for provider operations client *fasthttp.Client // HTTP client for API requests networkConfig schemas.NetworkConfig // Network configuration including extra headers + sendBackRawRequest bool // Whether to include raw request in BifrostResponse sendBackRawResponse bool // Whether to include raw response in BifrostResponse } @@ -78,6 +79,7 @@ func NewVertexProvider(config *schemas.ProviderConfig, logger schemas.Logger) (* logger: logger, client: client, networkConfig: config.NetworkConfig, + sendBackRawRequest: config.SendBackRawRequest, sendBackRawResponse: config.SendBackRawResponse, }, nil } @@ -144,6 +146,7 @@ func (provider *VertexProvider) listModelsByKey(ctx context.Context, key schemas // Accumulate all models from paginated requests var allModels []VertexModel + var rawRequests []interface{} var rawResponses []interface{} pageToken := "" @@ -197,10 +200,13 @@ func (provider *VertexProvider) listModelsByKey(ctx context.Context, key schemas // Parse Vertex's response var vertexResponse VertexListModelsResponse - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &vertexResponse, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), &vertexResponse, nil, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + rawRequests = append(rawRequests, rawRequest) + } if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { rawResponses = append(rawResponses, rawResponse) } @@ -221,6 +227,10 @@ func (provider *VertexProvider) listModelsByKey(ctx context.Context, key schemas } response := aggregatedResponse.ToBifrostListModelsResponse(key.Models, key.VertexKeyConfig.Deployments) + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequests + } + if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponses } @@ -430,7 +440,7 @@ func (provider *VertexProvider) ChatCompletion(ctx context.Context, key schemas. anthropicResponse := anthropic.AcquireAnthropicMessageResponse() defer anthropic.ReleaseAnthropicMessageResponse(anthropicResponse) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), anthropicResponse, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), anthropicResponse, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -450,6 +460,12 @@ func (provider *VertexProvider) ChatCompletion(ctx context.Context, key schemas. response.ExtraFields.ModelDeployment = deployment } + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -459,7 +475,7 @@ func (provider *VertexProvider) ChatCompletion(ctx context.Context, key schemas. response := &schemas.BifrostChatResponse{} // Use enhanced response handler with pre-allocated response - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), response, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), response, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -472,6 +488,12 @@ func (provider *VertexProvider) ChatCompletion(ctx context.Context, key schemas. } response.ExtraFields.Latency = latency.Milliseconds() + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest + } + + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } @@ -580,6 +602,7 @@ func (provider *VertexProvider) ChatCompletionStream(ctx context.Context, postHo jsonData, headers, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), providerName, postHookRunner, @@ -655,6 +678,7 @@ func (provider *VertexProvider) ChatCompletionStream(ctx context.Context, postHo request, authHeader, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), providerName, postHookRunner, @@ -773,7 +797,7 @@ func (provider *VertexProvider) Responses(ctx context.Context, key schemas.Key, anthropicResponse := anthropic.AcquireAnthropicMessageResponse() defer anthropic.ReleaseAnthropicMessageResponse(anthropicResponse) - rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), anthropicResponse, provider.sendBackRawResponse) + rawRequest, rawResponse, bifrostErr := providerUtils.HandleProviderResponse(resp.Body(), anthropicResponse, jsonBody, providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse)) if bifrostErr != nil { return nil, bifrostErr } @@ -789,13 +813,19 @@ func (provider *VertexProvider) Responses(ctx context.Context, key schemas.Key, } response.ExtraFields.ModelRequested = request.Model - if request.Model != deployment { - response.ExtraFields.ModelDeployment = deployment + + // Set raw request if enabled + if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) { + response.ExtraFields.RawRequest = rawRequest } + // Set raw response if enabled if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) { response.ExtraFields.RawResponse = rawResponse } + if request.Model != deployment { + response.ExtraFields.ModelDeployment = deployment + } return response, nil } else { @@ -916,6 +946,7 @@ func (provider *VertexProvider) ResponsesStream(ctx context.Context, postHookRun jsonData, headers, provider.networkConfig.ExtraHeaders, + providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest), providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse), provider.GetProviderKey(), postHookRunner, diff --git a/core/schemas/bifrost.go b/core/schemas/bifrost.go index 27b1bc65a..62b308589 100644 --- a/core/schemas/bifrost.go +++ b/core/schemas/bifrost.go @@ -102,19 +102,20 @@ type BifrostContextKey string // BifrostContextKeyRequestType is a context key for the request type. const ( - BifrostContextKeyVirtualKey BifrostContextKey = "x-bf-vk" // string - BifrostContextKeyRequestID BifrostContextKey = "request-id" // string - BifrostContextKeyFallbackRequestID BifrostContextKey = "fallback-request-id" // string - BifrostContextKeyDirectKey BifrostContextKey = "bifrost-direct-key" // Key struct - BifrostContextKeySelectedKeyID BifrostContextKey = "bifrost-selected-key-id" // string (to store the selected key ID (set by bifrost)) - BifrostContextKeySelectedKeyName BifrostContextKey = "bifrost-selected-key-name" // string (to store the selected key name (set by bifrost)) - BifrostContextKeyNumberOfRetries BifrostContextKey = "bifrost-number-of-retries" // int (to store the number of retries (set by bifrost)) - BifrostContextKeyFallbackIndex BifrostContextKey = "bifrost-fallback-index" // int (to store the fallback index (set by bifrost)) 0 for primary, 1 for first fallback, etc. - BifrostContextKeyStreamEndIndicator BifrostContextKey = "bifrost-stream-end-indicator" // bool (set by bifrost) - BifrostContextKeySkipKeySelection BifrostContextKey = "bifrost-skip-key-selection" // bool (will pass an empty key to the provider) - BifrostContextKeyExtraHeaders BifrostContextKey = "bifrost-extra-headers" // map[string]string - BifrostContextKeyURLPath BifrostContextKey = "bifrost-extra-url-path" // string - BifrostContextKeyUseRawRequestBody BifrostContextKey = "bifrost-use-raw-request-body" // bool + BifrostContextKeyVirtualKey BifrostContextKey = "x-bf-vk" // string + BifrostContextKeyRequestID BifrostContextKey = "request-id" // string + BifrostContextKeyFallbackRequestID BifrostContextKey = "fallback-request-id" // string + BifrostContextKeyDirectKey BifrostContextKey = "bifrost-direct-key" // Key struct + BifrostContextKeySelectedKeyID BifrostContextKey = "bifrost-selected-key-id" // string (to store the selected key ID (set by bifrost)) + BifrostContextKeySelectedKeyName BifrostContextKey = "bifrost-selected-key-name" // string (to store the selected key name (set by bifrost)) + BifrostContextKeyNumberOfRetries BifrostContextKey = "bifrost-number-of-retries" // int (to store the number of retries (set by bifrost)) + BifrostContextKeyFallbackIndex BifrostContextKey = "bifrost-fallback-index" // int (to store the fallback index (set by bifrost)) 0 for primary, 1 for first fallback, etc. + BifrostContextKeyStreamEndIndicator BifrostContextKey = "bifrost-stream-end-indicator" // bool (set by bifrost) + BifrostContextKeySkipKeySelection BifrostContextKey = "bifrost-skip-key-selection" // bool (will pass an empty key to the provider) + BifrostContextKeyExtraHeaders BifrostContextKey = "bifrost-extra-headers" // map[string]string + BifrostContextKeyURLPath BifrostContextKey = "bifrost-extra-url-path" // string + BifrostContextKeyUseRawRequestBody BifrostContextKey = "bifrost-use-raw-request-body" + BifrostContextKeySendBackRawRequest BifrostContextKey = "bifrost-send-back-raw-request" // bool BifrostContextKeySendBackRawResponse BifrostContextKey = "bifrost-send-back-raw-response" // bool BifrostContextKeyIsResponsesToChatCompletionFallback BifrostContextKey = "bifrost-is-responses-to-chat-completion-fallback" // bool (set by bifrost) BifrostContextKeyStructuredOutputToolName BifrostContextKey = "bifrost-structured-output-tool-name" // string (to store the name of the structured output tool (set by bifrost)) @@ -289,6 +290,7 @@ type BifrostResponseExtraFields struct { ModelDeployment string `json:"model_deployment,omitempty"` // only present for providers which use model deployments (e.g. Azure, Bedrock) Latency int64 `json:"latency"` // in milliseconds (for streaming responses this will be each chunk latency, and the last chunk latency will be the total latency) ChunkIndex int `json:"chunk_index"` // used for streaming responses to identify the chunk index, will be 0 for non-streaming responses + RawRequest interface{} `json:"raw_request,omitempty"` RawResponse interface{} `json:"raw_response,omitempty"` CacheDebug *BifrostCacheDebug `json:"cache_debug,omitempty"` } diff --git a/core/schemas/provider.go b/core/schemas/provider.go index c436f2ff6..da0a8e51d 100644 --- a/core/schemas/provider.go +++ b/core/schemas/provider.go @@ -28,6 +28,7 @@ const ( ErrProviderDoRequest = "failed to execute HTTP request to provider API" ErrProviderResponseDecode = "failed to decode response body from provider API" ErrProviderResponseUnmarshal = "failed to unmarshal response from provider API" + ErrProviderRawRequestUnmarshal = "failed to unmarshal raw request from provider API" ErrProviderRawResponseUnmarshal = "failed to unmarshal raw response from provider API" ErrProviderResponseDecompress = "failed to decompress provider's response" ) @@ -237,6 +238,7 @@ type ProviderConfig struct { // Logger instance, can be provided by the user or bifrost default logger is used if not provided Logger Logger `json:"-"` ProxyConfig *ProxyConfig `json:"proxy_config,omitempty"` // Proxy configuration + SendBackRawRequest bool `json:"send_back_raw_request"` // Send raw request back in the bifrost response (default: false) SendBackRawResponse bool `json:"send_back_raw_response"` // Send raw response back in the bifrost response (default: false) CustomProviderConfig *CustomProviderConfig `json:"custom_provider_config,omitempty"` } diff --git a/framework/changelog.md b/framework/changelog.md index bef82cfba..9d970f454 100644 --- a/framework/changelog.md +++ b/framework/changelog.md @@ -1 +1,3 @@ -feat: support raw response accumulation in stream accumulator \ No newline at end of file +feat: support raw response accumulation in stream accumulator +feat: support raw request configuration and logging +feat: added support for reasoning accumulation in stream accumulator \ No newline at end of file diff --git a/framework/configstore/clientconfig.go b/framework/configstore/clientconfig.go index 741acf354..f38d3107a 100644 --- a/framework/configstore/clientconfig.go +++ b/framework/configstore/clientconfig.go @@ -150,6 +150,7 @@ type ProviderConfig struct { NetworkConfig *schemas.NetworkConfig `json:"network_config,omitempty"` // Network-related settings ConcurrencyAndBufferSize *schemas.ConcurrencyAndBufferSize `json:"concurrency_and_buffer_size,omitempty"` // Concurrency settings ProxyConfig *schemas.ProxyConfig `json:"proxy_config,omitempty"` // Proxy configuration + SendBackRawRequest bool `json:"send_back_raw_request"` // Include raw request in BifrostResponse SendBackRawResponse bool `json:"send_back_raw_response"` // Include raw response in BifrostResponse CustomProviderConfig *schemas.CustomProviderConfig `json:"custom_provider_config,omitempty"` // Custom provider configuration ConfigHash string `json:"-"` @@ -200,6 +201,11 @@ func (p *ProviderConfig) GenerateConfigHash(providerName string) (string, error) hash.Write(data) } + // Hash SendBackRawRequest + if p.SendBackRawRequest { + hash.Write([]byte("sendBackRawRequest")) + } + // Hash SendBackRawResponse if p.SendBackRawResponse { hash.Write([]byte("sendBackRawResponse")) diff --git a/framework/configstore/migrations.go b/framework/configstore/migrations.go index 99bedadd5..bed423793 100644 --- a/framework/configstore/migrations.go +++ b/framework/configstore/migrations.go @@ -89,6 +89,9 @@ func triggerMigrations(ctx context.Context, db *gorm.DB) error { if err := migrationAddPluginVersionColumn(ctx, db); err != nil { return err } + if err := migrationAddSendBackRawRequestColumns(ctx, db); err != nil { + return err + } if err := migrationAddConfigHashColumn(ctx, db); err != nil { return err } @@ -1288,6 +1291,35 @@ func migrationAddPluginVersionColumn(ctx context.Context, db *gorm.DB) error { return nil } +func migrationAddSendBackRawRequestColumns(ctx context.Context, db *gorm.DB) error { + m := migrator.New(db, migrator.DefaultOptions, []*migrator.Migration{{ + ID: "add_send_back_raw_request_columns", + Migrate: func(tx *gorm.DB) error { + tx = tx.WithContext(ctx) + migrator := tx.Migrator() + if !migrator.HasColumn(&tables.TableProvider{}, "send_back_raw_request") { + if err := migrator.AddColumn(&tables.TableProvider{}, "send_back_raw_request"); err != nil { + return err + } + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + tx = tx.WithContext(ctx) + migrator := tx.Migrator() + if err := migrator.DropColumn(&tables.TableProvider{}, "send_back_raw_request"); err != nil { + return err + } + return nil + }, + }}) + err := m.Migrate() + if err != nil { + return fmt.Errorf("error while running add send back raw request columns migration: %s", err.Error()) + } + return nil +} + // migrationAddConfigHashColumn adds the config_hash column to the provider and key tables func migrationAddConfigHashColumn(ctx context.Context, db *gorm.DB) error { m := migrator.New(db, migrator.DefaultOptions, []*migrator.Migration{{ @@ -1312,6 +1344,7 @@ func migrationAddConfigHashColumn(ctx context.Context, db *gorm.DB) error { NetworkConfig: provider.NetworkConfig, ConcurrencyAndBufferSize: provider.ConcurrencyAndBufferSize, ProxyConfig: provider.ProxyConfig, + SendBackRawRequest: provider.SendBackRawRequest, SendBackRawResponse: provider.SendBackRawResponse, CustomProviderConfig: provider.CustomProviderConfig, } @@ -1405,7 +1438,7 @@ func migrationAddVirtualKeyConfigHashColumn(ctx context.Context, db *gorm.DB) er return fmt.Errorf("failed to update hash for virtual key %s: %w", vk.ID, err) } } - } + } } return nil }, diff --git a/framework/configstore/rdb.go b/framework/configstore/rdb.go index e13739ed7..4fbbd0535 100644 --- a/framework/configstore/rdb.go +++ b/framework/configstore/rdb.go @@ -211,6 +211,7 @@ func (s *RDBConfigStore) UpdateProvidersConfig(ctx context.Context, providers ma NetworkConfig: providerConfig.NetworkConfig, ConcurrencyAndBufferSize: providerConfig.ConcurrencyAndBufferSize, ProxyConfig: providerConfig.ProxyConfig, + SendBackRawRequest: providerConfig.SendBackRawRequest, SendBackRawResponse: providerConfig.SendBackRawResponse, CustomProviderConfig: providerConfig.CustomProviderConfig, ConfigHash: providerConfig.ConfigHash, @@ -331,6 +332,7 @@ func (s *RDBConfigStore) UpdateProvider(ctx context.Context, provider schemas.Mo dbProvider.NetworkConfig = configCopy.NetworkConfig dbProvider.ConcurrencyAndBufferSize = configCopy.ConcurrencyAndBufferSize dbProvider.ProxyConfig = configCopy.ProxyConfig + dbProvider.SendBackRawRequest = configCopy.SendBackRawRequest dbProvider.SendBackRawResponse = configCopy.SendBackRawResponse dbProvider.CustomProviderConfig = configCopy.CustomProviderConfig dbProvider.ConfigHash = configCopy.ConfigHash @@ -448,6 +450,7 @@ func (s *RDBConfigStore) AddProvider(ctx context.Context, provider schemas.Model NetworkConfig: configCopy.NetworkConfig, ConcurrencyAndBufferSize: configCopy.ConcurrencyAndBufferSize, ProxyConfig: configCopy.ProxyConfig, + SendBackRawRequest: configCopy.SendBackRawRequest, SendBackRawResponse: configCopy.SendBackRawResponse, CustomProviderConfig: configCopy.CustomProviderConfig, ConfigHash: configCopy.ConfigHash, @@ -643,6 +646,7 @@ func (s *RDBConfigStore) GetProvidersConfig(ctx context.Context) (map[schemas.Mo NetworkConfig: dbProvider.NetworkConfig, ConcurrencyAndBufferSize: dbProvider.ConcurrencyAndBufferSize, ProxyConfig: dbProvider.ProxyConfig, + SendBackRawRequest: dbProvider.SendBackRawRequest, SendBackRawResponse: dbProvider.SendBackRawResponse, CustomProviderConfig: dbProvider.CustomProviderConfig, ConfigHash: dbProvider.ConfigHash, diff --git a/framework/configstore/tables/provider.go b/framework/configstore/tables/provider.go index 6c9624dcb..b85af6cb5 100644 --- a/framework/configstore/tables/provider.go +++ b/framework/configstore/tables/provider.go @@ -19,6 +19,7 @@ type TableProvider struct { ConcurrencyBufferJSON string `gorm:"type:text" json:"-"` // JSON serialized schemas.ConcurrencyAndBufferSize ProxyConfigJSON string `gorm:"type:text" json:"-"` // JSON serialized schemas.ProxyConfig CustomProviderConfigJSON string `gorm:"type:text" json:"-"` // JSON serialized schemas.CustomProviderConfig + SendBackRawRequest bool `json:"send_back_raw_request"` SendBackRawResponse bool `json:"send_back_raw_response"` CreatedAt time.Time `gorm:"index;not null" json:"created_at"` UpdatedAt time.Time `gorm:"index;not null" json:"updated_at"` diff --git a/framework/logstore/migrations.go b/framework/logstore/migrations.go index 9bb766a9e..46dc7f32e 100644 --- a/framework/logstore/migrations.go +++ b/framework/logstore/migrations.go @@ -40,6 +40,9 @@ func triggerMigrations(ctx context.Context, db *gorm.DB) error { if err := migrationUpdateTimestampFormat(ctx, db); err != nil { return err } + if err := migrationAddRawRequestColumn(ctx, db); err != nil { + return err + } return nil } @@ -638,3 +641,36 @@ func migrationUpdateTimestampFormat(ctx context.Context, db *gorm.DB) error { } return nil } + +func migrationAddRawRequestColumn(ctx context.Context, db *gorm.DB) error { + opts := *migrator.DefaultOptions + opts.UseTransaction = true + m := migrator.New(db, &opts, []*migrator.Migration{{ + ID: "logs_add_raw_request_column", + Migrate: func(tx *gorm.DB) error { + tx = tx.WithContext(ctx) + migrator := tx.Migrator() + if !migrator.HasColumn(&Log{}, "raw_request") { + if err := migrator.AddColumn(&Log{}, "raw_request"); err != nil { + return err + } + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + tx = tx.WithContext(ctx) + migrator := tx.Migrator() + if migrator.HasColumn(&Log{}, "raw_request") { + if err := migrator.DropColumn(&Log{}, "raw_request"); err != nil { + return err + } + } + return nil + }, + }}) + err := m.Migrate() + if err != nil { + return fmt.Errorf("error while adding raw request column: %s", err.Error()) + } + return nil +} diff --git a/framework/logstore/tables.go b/framework/logstore/tables.go index dddf9f569..dbe037485 100644 --- a/framework/logstore/tables.go +++ b/framework/logstore/tables.go @@ -103,8 +103,9 @@ type Log struct { Status string `gorm:"type:varchar(50);index;not null" json:"status"` // "processing", "success", or "error" ErrorDetails string `gorm:"type:text" json:"-"` // JSON serialized *schemas.BifrostError Stream bool `gorm:"default:false" json:"stream"` // true if this was a streaming response - ContentSummary string `gorm:"type:text" json:"-"` // For content search - RawResponse string `gorm:"type:text" json:"raw_response"` // Populated when `send-back-raw-response` is on + ContentSummary string `gorm:"type:text" json:"-"` + RawRequest string `gorm:"type:text" json:"raw_request"` // Populated when `send-back-raw-request` is on + RawResponse string `gorm:"type:text" json:"raw_response"` // Populated when `send-back-raw-response` is on // Denormalized token fields for easier querying PromptTokens int `gorm:"default:0" json:"-"` diff --git a/framework/streaming/audio.go b/framework/streaming/audio.go index d0f33ba4f..5123d1ede 100644 --- a/framework/streaming/audio.go +++ b/framework/streaming/audio.go @@ -167,6 +167,10 @@ func (a *Accumulator) processAudioStreamingResponse(ctx *schemas.BifrostContext, a.logger.Error("failed to process accumulated chunks for request %s: %v", requestID, processErr) return nil, processErr } + var rawRequest interface{} + if result != nil && result.SpeechStreamResponse != nil && result.SpeechStreamResponse.ExtraFields.RawRequest != nil { + rawRequest = result.SpeechStreamResponse.ExtraFields.RawRequest + } return &ProcessedStreamResponse{ Type: StreamResponseTypeFinal, RequestID: requestID, @@ -174,6 +178,7 @@ func (a *Accumulator) processAudioStreamingResponse(ctx *schemas.BifrostContext, Model: model, Provider: provider, Data: data, + RawRequest: &rawRequest, }, nil } return nil, nil diff --git a/framework/streaming/chat.go b/framework/streaming/chat.go index 707ba80df..ed1b8055f 100644 --- a/framework/streaming/chat.go +++ b/framework/streaming/chat.go @@ -301,6 +301,10 @@ func (a *Accumulator) processChatStreamingResponse(ctx *schemas.BifrostContext, a.logger.Error("failed to process accumulated chunks for request %s: %v", requestID, processErr) return nil, processErr } + var rawRequest interface{} + if result != nil && result.ChatResponse != nil && result.ChatResponse.ExtraFields.RawRequest != nil { + rawRequest = result.ChatResponse.ExtraFields.RawRequest + } return &ProcessedStreamResponse{ Type: StreamResponseTypeFinal, RequestID: requestID, @@ -308,6 +312,7 @@ func (a *Accumulator) processChatStreamingResponse(ctx *schemas.BifrostContext, Provider: provider, Model: model, Data: data, + RawRequest: &rawRequest, }, nil } return nil, nil diff --git a/framework/streaming/responses.go b/framework/streaming/responses.go index 903f63f7a..dfff77f8b 100644 --- a/framework/streaming/responses.go +++ b/framework/streaming/responses.go @@ -720,6 +720,10 @@ func (a *Accumulator) processResponsesStreamingResponse(ctx *schemas.BifrostCont return nil, fmt.Errorf("failed to add responses stream chunk for request %s: %w", requestID, addErr) } if isFinalChunk { + var rawRequest interface{} + if result != nil && result.ResponsesStreamResponse != nil && result.ResponsesStreamResponse.ExtraFields.RawRequest != nil { + rawRequest = result.ResponsesStreamResponse.ExtraFields.RawRequest + } shouldProcess := false // Get the accumulator to check if processing has already been triggered accumulator := a.getOrCreateStreamAccumulator(requestID) @@ -782,6 +786,7 @@ func (a *Accumulator) processResponsesStreamingResponse(ctx *schemas.BifrostCont Provider: provider, Model: model, Data: data, + RawRequest: &rawRequest, }, nil } else { return nil, nil @@ -858,6 +863,11 @@ func (a *Accumulator) processResponsesStreamingResponse(ctx *schemas.BifrostCont return nil, processErr } + var rawRequest interface{} + if result != nil && result.ResponsesStreamResponse != nil && result.ResponsesStreamResponse.ExtraFields.RawRequest != nil { + rawRequest = result.ResponsesStreamResponse.ExtraFields.RawRequest + } + return &ProcessedStreamResponse{ Type: StreamResponseTypeFinal, RequestID: requestID, @@ -865,6 +875,7 @@ func (a *Accumulator) processResponsesStreamingResponse(ctx *schemas.BifrostCont Provider: provider, Model: model, Data: data, + RawRequest: &rawRequest, }, nil } return nil, nil diff --git a/framework/streaming/transcription.go b/framework/streaming/transcription.go index c246d7ec2..314f4cdb5 100644 --- a/framework/streaming/transcription.go +++ b/framework/streaming/transcription.go @@ -186,6 +186,10 @@ func (a *Accumulator) processTranscriptionStreamingResponse(ctx *schemas.Bifrost a.logger.Error("failed to process accumulated chunks for request %s: %v", requestID, processErr) return nil, processErr } + var rawRequest interface{} + if result != nil && result.TranscriptionStreamResponse != nil && result.TranscriptionStreamResponse.ExtraFields.RawRequest != nil { + rawRequest = result.TranscriptionStreamResponse.ExtraFields.RawRequest + } return &ProcessedStreamResponse{ Type: StreamResponseTypeFinal, RequestID: requestID, @@ -193,6 +197,7 @@ func (a *Accumulator) processTranscriptionStreamingResponse(ctx *schemas.Bifrost Provider: provider, Model: model, Data: data, + RawRequest: &rawRequest, }, nil } return nil, nil diff --git a/framework/streaming/types.go b/framework/streaming/types.go index 2473821b3..29bb62dfc 100644 --- a/framework/streaming/types.go +++ b/framework/streaming/types.go @@ -120,6 +120,7 @@ type ProcessedStreamResponse struct { Provider schemas.ModelProvider Model string Data *AccumulatedData + RawRequest *interface{} } // ToBifrostResponse converts a ProcessedStreamResponse to a BifrostResponse @@ -155,6 +156,9 @@ func (p *ProcessedStreamResponse) ToBifrostResponse() *schemas.BifrostResponse { ModelRequested: p.Model, Latency: p.Data.Latency, } + if p.RawRequest != nil { + resp.TextCompletionResponse.ExtraFields.RawRequest = p.RawRequest + } case StreamTypeChat: chatResp := &schemas.BifrostChatResponse{ ID: p.RequestID, @@ -204,6 +208,9 @@ func (p *ProcessedStreamResponse) ToBifrostResponse() *schemas.BifrostResponse { ModelRequested: p.Model, Latency: p.Data.Latency, } + if p.RawRequest != nil { + resp.ChatResponse.ExtraFields.RawRequest = p.RawRequest + } case StreamTypeResponses: responsesResp := &schemas.BifrostResponsesResponse{} @@ -219,6 +226,9 @@ func (p *ProcessedStreamResponse) ToBifrostResponse() *schemas.BifrostResponse { ModelRequested: p.Model, Latency: p.Data.Latency, } + if p.RawRequest != nil { + responsesResp.ExtraFields.RawRequest = p.RawRequest + } resp.ResponsesResponse = responsesResp case StreamTypeAudio: speechResp := p.Data.AudioOutput @@ -232,6 +242,9 @@ func (p *ProcessedStreamResponse) ToBifrostResponse() *schemas.BifrostResponse { ModelRequested: p.Model, Latency: p.Data.Latency, } + if p.RawRequest != nil { + resp.SpeechResponse.ExtraFields.RawRequest = p.RawRequest + } case StreamTypeTranscription: transcriptionResp := p.Data.TranscriptionOutput if transcriptionResp == nil { @@ -244,6 +257,9 @@ func (p *ProcessedStreamResponse) ToBifrostResponse() *schemas.BifrostResponse { ModelRequested: p.Model, Latency: p.Data.Latency, } + if p.RawRequest != nil { + resp.TranscriptionResponse.ExtraFields.RawRequest = p.RawRequest + } } return resp } diff --git a/plugins/logging/changelog.md b/plugins/logging/changelog.md index e69de29bb..b43651aee 100644 --- a/plugins/logging/changelog.md +++ b/plugins/logging/changelog.md @@ -0,0 +1 @@ +feat: support for raw request logging \ No newline at end of file diff --git a/plugins/logging/main.go b/plugins/logging/main.go index 0c805841e..0ede4aca3 100644 --- a/plugins/logging/main.go +++ b/plugins/logging/main.go @@ -42,6 +42,7 @@ type UpdateLogData struct { ErrorDetails *schemas.BifrostError SpeechOutput *schemas.BifrostSpeechResponse // For non-streaming speech responses TranscriptionOutput *schemas.BifrostTranscriptionResponse // For non-streaming transcription responses + RawRequest interface{} RawResponse interface{} } @@ -496,6 +497,9 @@ func (p *LoggerPlugin) PostHook(ctx *schemas.BifrostContext, result *schemas.Bif // Extract raw response extraFields := result.GetExtraFields() if p.disableContentLogging == nil || !*p.disableContentLogging { + if extraFields.RawRequest != nil { + updateData.RawRequest = extraFields.RawRequest + } if extraFields.RawResponse != nil { updateData.RawResponse = extraFields.RawResponse } diff --git a/plugins/logging/operations.go b/plugins/logging/operations.go index fb22c0a61..db2fe01e9 100644 --- a/plugins/logging/operations.go +++ b/plugins/logging/operations.go @@ -122,6 +122,16 @@ func (p *LoggerPlugin) updateLogEntry( updates["transcription_output"] = tempEntry.TranscriptionOutput } } + + // Handle raw request marshaling and logging + if data.RawRequest != nil { + rawRequestBytes, err := sonic.Marshal(data.RawRequest) + if err != nil { + p.logger.Error("failed to marshal raw request: %v", err) + } else { + updates["raw_request"] = string(rawRequestBytes) + } + } } if data.TokenUsage != nil { @@ -168,7 +178,6 @@ func (p *LoggerPlugin) updateLogEntry( updates["raw_response"] = string(rawResponseBytes) } } - return p.store.Update(ctx, requestID, updates) } @@ -293,6 +302,15 @@ func (p *LoggerPlugin) updateStreamingLogEntry( updates["responses_output"] = tempEntry.ResponsesOutput } } + // Handle raw request from stream updates + if streamResponse.RawRequest != nil && *streamResponse.RawRequest != nil { + rawRequestBytes, err := sonic.Marshal(*streamResponse.RawRequest) + if err != nil { + p.logger.Error("failed to marshal raw request: %v", err) + } else { + updates["raw_request"] = string(rawRequestBytes) + } + } // Handle raw response from stream updates if streamResponse.Data.RawResponse != nil { updates["raw_response"] = *streamResponse.Data.RawResponse diff --git a/transports/bifrost-http/handlers/providers.go b/transports/bifrost-http/handlers/providers.go index e61ec6050..0ebcfe957 100644 --- a/transports/bifrost-http/handlers/providers.go +++ b/transports/bifrost-http/handlers/providers.go @@ -58,6 +58,7 @@ type ProviderResponse struct { NetworkConfig schemas.NetworkConfig `json:"network_config"` // Network-related settings ConcurrencyAndBufferSize schemas.ConcurrencyAndBufferSize `json:"concurrency_and_buffer_size"` // Concurrency settings ProxyConfig *schemas.ProxyConfig `json:"proxy_config"` // Proxy configuration + SendBackRawRequest bool `json:"send_back_raw_request"` // Include raw request in BifrostResponse SendBackRawResponse bool `json:"send_back_raw_response"` // Include raw response in BifrostResponse CustomProviderConfig *schemas.CustomProviderConfig `json:"custom_provider_config,omitempty"` // Custom provider configuration Status ProviderStatus `json:"status"` // Status of the provider @@ -175,6 +176,7 @@ func (h *ProviderHandler) addProvider(ctx *fasthttp.RequestCtx) { NetworkConfig *schemas.NetworkConfig `json:"network_config,omitempty"` // Network-related settings ConcurrencyAndBufferSize *schemas.ConcurrencyAndBufferSize `json:"concurrency_and_buffer_size,omitempty"` // Concurrency settings ProxyConfig *schemas.ProxyConfig `json:"proxy_config,omitempty"` // Proxy configuration + SendBackRawRequest *bool `json:"send_back_raw_request,omitempty"` // Include raw request in BifrostResponse SendBackRawResponse *bool `json:"send_back_raw_response,omitempty"` // Include raw response in BifrostResponse CustomProviderConfig *schemas.CustomProviderConfig `json:"custom_provider_config,omitempty"` // Custom provider configuration }{} @@ -245,6 +247,7 @@ func (h *ProviderHandler) addProvider(ctx *fasthttp.RequestCtx) { NetworkConfig: payload.NetworkConfig, ProxyConfig: payload.ProxyConfig, ConcurrencyAndBufferSize: payload.ConcurrencyAndBufferSize, + SendBackRawRequest: payload.SendBackRawRequest != nil && *payload.SendBackRawRequest, SendBackRawResponse: payload.SendBackRawResponse != nil && *payload.SendBackRawResponse, CustomProviderConfig: payload.CustomProviderConfig, } @@ -273,6 +276,7 @@ func (h *ProviderHandler) addProvider(ctx *fasthttp.RequestCtx) { NetworkConfig: config.NetworkConfig, ConcurrencyAndBufferSize: config.ConcurrencyAndBufferSize, ProxyConfig: config.ProxyConfig, + SendBackRawRequest: config.SendBackRawRequest, SendBackRawResponse: config.SendBackRawResponse, CustomProviderConfig: config.CustomProviderConfig, }, ProviderStatusActive) @@ -313,6 +317,7 @@ func (h *ProviderHandler) updateProvider(ctx *fasthttp.RequestCtx) { NetworkConfig schemas.NetworkConfig `json:"network_config"` // Network-related settings ConcurrencyAndBufferSize schemas.ConcurrencyAndBufferSize `json:"concurrency_and_buffer_size"` // Concurrency settings ProxyConfig *schemas.ProxyConfig `json:"proxy_config,omitempty"` // Proxy configuration + SendBackRawRequest *bool `json:"send_back_raw_request,omitempty"` // Include raw request in BifrostResponse SendBackRawResponse *bool `json:"send_back_raw_response,omitempty"` // Include raw response in BifrostResponse CustomProviderConfig *schemas.CustomProviderConfig `json:"custom_provider_config,omitempty"` // Custom provider configuration }{} @@ -423,6 +428,9 @@ func (h *ProviderHandler) updateProvider(ctx *fasthttp.RequestCtx) { config.NetworkConfig = &nc config.ProxyConfig = payload.ProxyConfig config.CustomProviderConfig = payload.CustomProviderConfig + if payload.SendBackRawRequest != nil { + config.SendBackRawRequest = *payload.SendBackRawRequest + } if payload.SendBackRawResponse != nil { config.SendBackRawResponse = *payload.SendBackRawResponse } @@ -451,6 +459,7 @@ func (h *ProviderHandler) updateProvider(ctx *fasthttp.RequestCtx) { NetworkConfig: config.NetworkConfig, ConcurrencyAndBufferSize: config.ConcurrencyAndBufferSize, ProxyConfig: config.ProxyConfig, + SendBackRawRequest: config.SendBackRawRequest, SendBackRawResponse: config.SendBackRawResponse, CustomProviderConfig: config.CustomProviderConfig, }, ProviderStatusActive) @@ -844,6 +853,7 @@ func (h *ProviderHandler) getProviderResponseFromConfig(provider schemas.ModelPr NetworkConfig: *config.NetworkConfig, ConcurrencyAndBufferSize: *config.ConcurrencyAndBufferSize, ProxyConfig: config.ProxyConfig, + SendBackRawRequest: config.SendBackRawRequest, SendBackRawResponse: config.SendBackRawResponse, CustomProviderConfig: config.CustomProviderConfig, Status: status, diff --git a/transports/bifrost-http/lib/account.go b/transports/bifrost-http/lib/account.go index 59c6f579d..b37f756b8 100644 --- a/transports/bifrost-http/lib/account.go +++ b/transports/bifrost-http/lib/account.go @@ -105,6 +105,7 @@ func (baseAccount *BaseAccount) GetConfigForProvider(providerKey schemas.ModelPr providerConfig.ConcurrencyAndBufferSize = schemas.DefaultConcurrencyAndBufferSize } + providerConfig.SendBackRawRequest = config.SendBackRawRequest providerConfig.SendBackRawResponse = config.SendBackRawResponse if config.CustomProviderConfig != nil { diff --git a/transports/bifrost-http/lib/config.go b/transports/bifrost-http/lib/config.go index 13dd6d41d..a27d8d1af 100644 --- a/transports/bifrost-http/lib/config.go +++ b/transports/bifrost-http/lib/config.go @@ -1691,6 +1691,7 @@ func loadDefaultProviders(ctx context.Context, config *Config) error { NetworkConfig: dbProvider.NetworkConfig, ConcurrencyAndBufferSize: dbProvider.ConcurrencyAndBufferSize, ProxyConfig: dbProvider.ProxyConfig, + SendBackRawRequest: dbProvider.SendBackRawRequest, SendBackRawResponse: dbProvider.SendBackRawResponse, CustomProviderConfig: dbProvider.CustomProviderConfig, } @@ -2099,6 +2100,7 @@ func (c *Config) GetProviderConfigRedacted(provider schemas.ModelProvider) (*con NetworkConfig: config.NetworkConfig, ConcurrencyAndBufferSize: config.ConcurrencyAndBufferSize, ProxyConfig: config.ProxyConfig, + SendBackRawRequest: config.SendBackRawRequest, SendBackRawResponse: config.SendBackRawResponse, CustomProviderConfig: config.CustomProviderConfig, } diff --git a/transports/changelog.md b/transports/changelog.md index 01b22b058..e3c827ea0 100644 --- a/transports/changelog.md +++ b/transports/changelog.md @@ -1 +1,5 @@ -feat: support for raw response accumulation for streaming \ No newline at end of file +feat: support for raw response accumulation for streaming +feat: support for raw request logging and sending back in response +feat: added support for reasoning in chat completions +feat: enhanced reasoning support in responses api +enhancement: improved internal inter provider conversions for integrations \ No newline at end of file diff --git a/ui/app/workspace/logs/views/logDetailsSheet.tsx b/ui/app/workspace/logs/views/logDetailsSheet.tsx index 6522f213e..bc32c65c3 100644 --- a/ui/app/workspace/logs/views/logDetailsSheet.tsx +++ b/ui/app/workspace/logs/views/logDetailsSheet.tsx @@ -361,6 +361,31 @@ export function LogDetailSheet({ log, open, onOpenChange, handleDelete }: LogDet /> > )} + {log.raw_request && ( + <> +
+ Include the raw provider request alongside the parsed request for debugging and advanced use cases +
+