From 3292a1341cf845611349adea92d077d93ec7c7ff Mon Sep 17 00:00:00 2001 From: Pratham-Mishra04 Date: Tue, 16 Sep 2025 18:45:34 +0530 Subject: [PATCH] feat: api key support added for bedrock provider --- core/providers/anthropic.go | 2 +- core/providers/bedrock.go | 87 +++++++++++-------- core/providers/openai.go | 7 +- core/providers/utils.go | 2 + core/schemas/account.go | 5 ++ core/utils.go | 25 ------ .../gateway/provider-configuration.mdx | 20 +++-- .../go-sdk/provider-configuration.mdx | 12 +-- framework/configstore/migrations.go | 4 +- framework/configstore/sqlite.go | 5 +- framework/configstore/utils.go | 26 +++++- .../fragments/apiKeysFormFragment.tsx | 87 ++++++++++++++----- .../views/modelProviderKeysTableView.tsx | 2 +- ui/lib/types/config.ts | 4 +- ui/lib/types/schemas.ts | 4 +- 15 files changed, 180 insertions(+), 112 deletions(-) diff --git a/core/providers/anthropic.go b/core/providers/anthropic.go index 0c9c9d239d..2d4c7dd14c 100644 --- a/core/providers/anthropic.go +++ b/core/providers/anthropic.go @@ -1198,7 +1198,7 @@ func handleAnthropicStreaming( logger.Warn(fmt.Sprintf("Error reading %s stream: %v", providerType, err)) processAndSendError(ctx, postHookRunner, err, responseChan, logger) } else { - response := createBifrostChatCompletionChunkResponse(usage, finishReason, chunkIndex, params, providerType) + response := createBifrostChatCompletionChunkResponse(messageID, usage, finishReason, chunkIndex, params, providerType) handleStreamEndWithSuccess(ctx, response, postHookRunner, responseChan, logger) } }() diff --git a/core/providers/bedrock.go b/core/providers/bedrock.go index d4686316fd..6d0520a84d 100644 --- a/core/providers/bedrock.go +++ b/core/providers/bedrock.go @@ -259,7 +259,9 @@ func (provider *BedrockProvider) GetProviderKey() schemas.ModelProvider { // CompleteRequest sends a request to Bedrock's API and handles the response. // It constructs the API URL, sets up AWS authentication, and processes the response. // Returns the response body or an error if the request fails. -func (provider *BedrockProvider) completeRequest(ctx context.Context, requestBody map[string]interface{}, path string, config schemas.BedrockKeyConfig) ([]byte, *schemas.BifrostError) { +func (provider *BedrockProvider) completeRequest(ctx context.Context, requestBody map[string]interface{}, path string, key schemas.Key) ([]byte, *schemas.BifrostError) { + config := key.BedrockKeyConfig + region := "us-east-1" if config.Region != nil { region = *config.Region @@ -301,9 +303,14 @@ func (provider *BedrockProvider) completeRequest(ctx context.Context, requestBod // Set any extra headers from network config setExtraHeadersHTTP(req, provider.networkConfig.ExtraHeaders, nil) - // Sign the request using either explicit credentials or IAM role authentication - if err := signAWSRequest(ctx, req, config.AccessKey, config.SecretKey, config.SessionToken, region, "bedrock", provider.GetProviderKey()); err != nil { - return nil, err + // If Value is set, use API Key authentication - else use IAM role authentication + if key.Value != "" { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", key.Value)) + } else { + // Sign the request using either explicit credentials or IAM role authentication + if err := signAWSRequest(ctx, req, config.AccessKey, config.SecretKey, config.SessionToken, region, "bedrock", provider.GetProviderKey()); err != nil { + return nil, err + } } // Execute the request @@ -834,7 +841,8 @@ func (provider *BedrockProvider) TextCompletion(ctx context.Context, model strin "prompt": text, }, preparedParams) - body, err := provider.completeRequest(ctx, requestBody, fmt.Sprintf("%s/invoke", model), *key.BedrockKeyConfig) + path := provider.getModelPath("invoke", model, key) + body, err := provider.completeRequest(ctx, requestBody, path, key) if err != nil { return nil, err } @@ -1018,19 +1026,10 @@ func (provider *BedrockProvider) ChatCompletion(ctx context.Context, model strin requestBody := mergeConfig(messageBody, preparedParams) // Format the path with proper model identifier - path := fmt.Sprintf("%s/converse", model) - - if key.BedrockKeyConfig.Deployments != nil { - if inferenceProfileId, ok := key.BedrockKeyConfig.Deployments[model]; ok { - if key.BedrockKeyConfig.ARN != nil { - encodedModelIdentifier := url.QueryEscape(fmt.Sprintf("%s/%s", *key.BedrockKeyConfig.ARN, inferenceProfileId)) - path = fmt.Sprintf("%s/converse", encodedModelIdentifier) - } - } - } + path := provider.getModelPath("converse", model, key) // Create the signed request - responseBody, err := provider.completeRequest(ctx, requestBody, path, *key.BedrockKeyConfig) + responseBody, err := provider.completeRequest(ctx, requestBody, path, key) if err != nil { return nil, err } @@ -1223,16 +1222,16 @@ func (provider *BedrockProvider) Embedding(ctx context.Context, model string, ke switch { case strings.Contains(model, "amazon.titan-embed-text"): - return provider.handleTitanEmbedding(ctx, model, *key.BedrockKeyConfig, input, params, providerName) + return provider.handleTitanEmbedding(ctx, model, key, input, params, providerName) case strings.Contains(model, "cohere.embed"): - return provider.handleCohereEmbedding(ctx, model, *key.BedrockKeyConfig, input, params, providerName) + return provider.handleCohereEmbedding(ctx, model, key, input, params, providerName) default: return nil, newConfigurationError("embedding is not supported for this Bedrock model", providerName) } } // handleTitanEmbedding handles embedding requests for Amazon Titan models. -func (provider *BedrockProvider) handleTitanEmbedding(ctx context.Context, model string, config schemas.BedrockKeyConfig, input *schemas.EmbeddingInput, params *schemas.ModelParameters, providerName schemas.ModelProvider) (*schemas.BifrostResponse, *schemas.BifrostError) { +func (provider *BedrockProvider) handleTitanEmbedding(ctx context.Context, model string, key schemas.Key, input *schemas.EmbeddingInput, params *schemas.ModelParameters, providerName schemas.ModelProvider) (*schemas.BifrostResponse, *schemas.BifrostError) { // Titan Text Embeddings V1/V2 - only supports single text input if len(input.Texts) == 0 { return nil, newConfigurationError("no input text provided for embedding", providerName) @@ -1258,8 +1257,8 @@ func (provider *BedrockProvider) handleTitanEmbedding(ctx context.Context, model } // Properly escape model name for URL path to ensure AWS SIGv4 signing works correctly - path := url.PathEscape(model) + "/invoke" - rawResponse, err := provider.completeRequest(ctx, requestBody, path, config) + path := provider.getModelPath("invoke", model, key) + rawResponse, err := provider.completeRequest(ctx, requestBody, path, key) if err != nil { return nil, err } @@ -1306,7 +1305,7 @@ func (provider *BedrockProvider) handleTitanEmbedding(ctx context.Context, model } // handleCohereEmbedding handles embedding requests for Cohere models on Bedrock. -func (provider *BedrockProvider) handleCohereEmbedding(ctx context.Context, model string, config schemas.BedrockKeyConfig, input *schemas.EmbeddingInput, params *schemas.ModelParameters, providerName schemas.ModelProvider) (*schemas.BifrostResponse, *schemas.BifrostError) { +func (provider *BedrockProvider) handleCohereEmbedding(ctx context.Context, model string, key schemas.Key, input *schemas.EmbeddingInput, params *schemas.ModelParameters, providerName schemas.ModelProvider) (*schemas.BifrostResponse, *schemas.BifrostError) { if len(input.Texts) == 0 { return nil, newConfigurationError("no input text provided for embedding", providerName) } @@ -1320,8 +1319,8 @@ func (provider *BedrockProvider) handleCohereEmbedding(ctx context.Context, mode } // Properly escape model name for URL path to ensure AWS SIGv4 signing works correctly - path := url.PathEscape(model) + "/invoke" - rawResponse, err := provider.completeRequest(ctx, requestBody, path, config) + path := provider.getModelPath("invoke", model, key) + rawResponse, err := provider.completeRequest(ctx, requestBody, path, key) if err != nil { return nil, err } @@ -1433,16 +1432,7 @@ func (provider *BedrockProvider) ChatCompletionStream(ctx context.Context, postH requestBody := mergeConfig(messageBody, preparedParams) // Format the path with proper model identifier for streaming - path := fmt.Sprintf("%s/converse-stream", model) - - if key.BedrockKeyConfig.Deployments != nil { - if inferenceProfileId, ok := key.BedrockKeyConfig.Deployments[model]; ok { - if key.BedrockKeyConfig.ARN != nil { - encodedModelIdentifier := url.PathEscape(fmt.Sprintf("%s/%s", *key.BedrockKeyConfig.ARN, inferenceProfileId)) - path = fmt.Sprintf("%s/converse-stream", encodedModelIdentifier) - } - } - } + path := provider.getModelPath("converse-stream", model, key) region := "us-east-1" if key.BedrockKeyConfig.Region != nil { @@ -1464,9 +1454,14 @@ func (provider *BedrockProvider) ChatCompletionStream(ctx context.Context, postH // Set any extra headers from network config setExtraHeadersHTTP(req, provider.networkConfig.ExtraHeaders, nil) - // Sign the request using either explicit credentials or IAM role authentication - if signErr := signAWSRequest(ctx, req, key.BedrockKeyConfig.AccessKey, key.BedrockKeyConfig.SecretKey, key.BedrockKeyConfig.SessionToken, region, "bedrock", providerName); signErr != nil { - return nil, signErr + // If Value is set, use API Key authentication - else use IAM role authentication + if key.Value != "" { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", key.Value)) + } else { + // Sign the request using either explicit credentials or IAM role authentication + if err := signAWSRequest(ctx, req, key.BedrockKeyConfig.AccessKey, key.BedrockKeyConfig.SecretKey, key.BedrockKeyConfig.SessionToken, region, "bedrock", providerName); err != nil { + return nil, err + } } // Make the request @@ -1531,7 +1526,7 @@ func (provider *BedrockProvider) ChatCompletionStream(ctx context.Context, postH } // Send final response - response := createBifrostChatCompletionChunkResponse(usage, finishReason, chunkIndex, params, providerName) + response := createBifrostChatCompletionChunkResponse(messageID, usage, finishReason, chunkIndex, params, providerName) handleStreamEndWithSuccess(ctx, response, postHookRunner, responseChan, provider.logger) }() @@ -1827,3 +1822,19 @@ func (provider *BedrockProvider) Transcription(ctx context.Context, model string func (provider *BedrockProvider) TranscriptionStream(ctx context.Context, postHookRunner schemas.PostHookRunner, model string, key schemas.Key, input *schemas.TranscriptionInput, params *schemas.ModelParameters) (chan *schemas.BifrostStream, *schemas.BifrostError) { return nil, newUnsupportedOperationError("transcription stream", "bedrock") } + +func (provider *BedrockProvider) getModelPath(basePath string, model string, key schemas.Key) string { + // Format the path with proper model identifier for streaming + path := fmt.Sprintf("%s/%s", model, basePath) + + if key.BedrockKeyConfig.Deployments != nil { + if inferenceProfileId, ok := key.BedrockKeyConfig.Deployments[model]; ok { + if key.BedrockKeyConfig.ARN != nil { + encodedModelIdentifier := url.PathEscape(fmt.Sprintf("%s/%s", *key.BedrockKeyConfig.ARN, inferenceProfileId)) + path = fmt.Sprintf("%s/%s", encodedModelIdentifier, basePath) + } + } + } + + return path +} diff --git a/core/providers/openai.go b/core/providers/openai.go index 1440c3588a..b5cc638956 100644 --- a/core/providers/openai.go +++ b/core/providers/openai.go @@ -438,6 +438,7 @@ func handleOpenAIStreaming( usage := &schemas.LLMUsage{} var finishReason *string + var id string for scanner.Scan() { line := scanner.Text() @@ -513,6 +514,10 @@ func handleOpenAIStreaming( response.Choices[0].FinishReason = nil } + if response.ID != "" && id == "" { + id = response.ID + } + // Handle regular content chunks if choice.BifrostStreamResponseChoice != nil && (choice.BifrostStreamResponseChoice.Delta.Content != nil || len(choice.BifrostStreamResponseChoice.Delta.ToolCalls) > 0) { chunkIndex++ @@ -529,7 +534,7 @@ func handleOpenAIStreaming( logger.Warn(fmt.Sprintf("Error reading stream: %v", err)) processAndSendError(ctx, postHookRunner, err, responseChan, logger) } else { - response := createBifrostChatCompletionChunkResponse(usage, finishReason, chunkIndex, params, providerName) + response := createBifrostChatCompletionChunkResponse(id, usage, finishReason, chunkIndex, params, providerName) handleStreamEndWithSuccess(ctx, response, postHookRunner, responseChan, logger) } }() diff --git a/core/providers/utils.go b/core/providers/utils.go index c8673c0d26..54e64b4d21 100644 --- a/core/providers/utils.go +++ b/core/providers/utils.go @@ -804,6 +804,7 @@ func processAndSendError( } func createBifrostChatCompletionChunkResponse( + id string, usage *schemas.LLMUsage, finishReason *string, currentChunkIndex int, @@ -811,6 +812,7 @@ func createBifrostChatCompletionChunkResponse( providerName schemas.ModelProvider, ) *schemas.BifrostResponse { response := &schemas.BifrostResponse{ + ID: id, Object: "chat.completion.chunk", Usage: usage, Choices: []schemas.BifrostResponseChoice{ diff --git a/core/schemas/account.go b/core/schemas/account.go index aa4d66a45a..44563ca7be 100644 --- a/core/schemas/account.go +++ b/core/schemas/account.go @@ -31,6 +31,8 @@ type VertexKeyConfig struct { AuthCredentials string `json:"auth_credentials,omitempty"` } +// NOTE: To use Vertex IAM role authentication, set AuthCredentials to empty string. + // BedrockKeyConfig represents the AWS Bedrock-specific configuration. // It contains AWS-specific settings required for authentication and service access. type BedrockKeyConfig struct { @@ -42,6 +44,9 @@ type BedrockKeyConfig struct { Deployments map[string]string `json:"deployments,omitempty"` // Mapping of model identifiers to inference profiles } +// NOTE: To use Bedrock IAM role authentication, set both AccessKey and SecretKey to empty strings. +// To use Bedrock API Key authentication, set Value in Key struct instead. + // Account defines the interface for managing provider accounts and their configurations. // It provides methods to access provider-specific settings, API keys, and configurations. type Account interface { diff --git a/core/utils.go b/core/utils.go index ab359ac39f..e0bddf0aa6 100644 --- a/core/utils.go +++ b/core/utils.go @@ -2,7 +2,6 @@ package bifrost import ( "context" - "encoding/json" "math/rand" "time" @@ -14,30 +13,6 @@ func Ptr[T any](v T) *T { return &v } -// MarshalToString marshals the given value to a JSON string. -func MarshalToString(v any) (string, error) { - if v == nil { - return "", nil - } - data, err := json.Marshal(v) - if err != nil { - return "", err - } - return string(data), nil -} - -// MarshalToStringPtr marshals the given value to a JSON string and returns a pointer to the string. -func MarshalToStringPtr(v any) (*string, error) { - if v == nil { - return nil, nil - } - data, err := MarshalToString(v) - if err != nil { - return nil, err - } - return &data, nil -} - func attachContextKeys(ctx context.Context, req *schemas.BifrostRequest, requestType schemas.RequestType) context.Context { ctx = context.WithValue(ctx, schemas.BifrostContextKeyRequestType, requestType) ctx = context.WithValue(ctx, schemas.BifrostContextKeyRequestProvider, req.Provider) diff --git a/docs/quickstart/gateway/provider-configuration.mdx b/docs/quickstart/gateway/provider-configuration.mdx index 97b64049b5..d43f244e55 100644 --- a/docs/quickstart/gateway/provider-configuration.mdx +++ b/docs/quickstart/gateway/provider-configuration.mdx @@ -764,12 +764,13 @@ AWS Bedrock supports both explicit credentials and IAM role authentication: ![AWS Bedrock Configuration Interface](../../media/ui-bedrock-config.png) 1. Navigate to **"Providers"** → **"AWS Bedrock"** -2. Set **Access Key**: AWS Access Key ID (or leave empty for IAM) -3. Set **Secret Key**: AWS Secret Access Key (or leave empty for IAM) -4. Set **Region**: e.g., `us-east-1` -5. Configure **Deployments**: Map model names to inference profiles -6. Set **ARN**: Required for deployments mapping -7. Save configuration +2. Set **API Key**: AWS API Key (or leave empty if using IAM role authentication) +3. Set **Access Key**: AWS Access Key ID (or leave empty to use IAM in environment) +4. Set **Secret Key**: AWS Secret Access Key (or leave empty to use IAM in environment) +5. Set **Region**: e.g., `us-east-1` +6. Configure **Deployments**: Map model names to inference profiles +7. Set **ARN**: Required for deployments mapping +8. Save configuration @@ -833,9 +834,10 @@ curl --location 'http://localhost:8080/api/providers' \ **Notes:** -- If both `access_key` and `secret_key` are empty, Bifrost uses IAM role authentication from environment -- `arn` is required for URL formation - `deployments` mapping is ignored without it -- When using `arn` + `deployments`, Bifrost uses model profiles; otherwise forms path with incoming model name directly +- If using API Key authentication, set `value` field to the API key, else leave it empty for IAM role authentication. +- In IAM role authentication, if both `access_key` and `secret_key` are empty, Bifrost uses IAM role authentication from the environment. +- `arn` is required for URL formation - `deployments` mapping is ignored without it. +- When using `arn` + `deployments`, Bifrost uses model profiles; otherwise forms path with incoming model name directly. ### Google Vertex diff --git a/docs/quickstart/go-sdk/provider-configuration.mdx b/docs/quickstart/go-sdk/provider-configuration.mdx index ef25539270..1c7af8456b 100644 --- a/docs/quickstart/go-sdk/provider-configuration.mdx +++ b/docs/quickstart/go-sdk/provider-configuration.mdx @@ -307,9 +307,10 @@ func (a *MyAccount) GetKeysForProvider(ctx *context.Context, provider schemas.Mo { Models: []string{"anthropic.claude-3-sonnet-20240229-v1:0", "anthropic.claude-v2:1"}, Weight: 1.0, + Value: os.Getenv("AWS_API_KEY"), // Leave empty for IAM role authentication BedrockKeyConfig: &schemas.BedrockKeyConfig{ - AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"), // Leave empty for IAM role - SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"), // Leave empty for IAM role + AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"), // Leave empty for API Key authentication or system's IAM pickup + SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"), // Leave empty for API Key authentication or system's IAM pickup SessionToken: bifrost.Ptr(os.Getenv("AWS_SESSION_TOKEN")), // Optional Region: bifrost.Ptr("us-east-1"), // For model profiles (inference profiles) @@ -327,9 +328,10 @@ func (a *MyAccount) GetKeysForProvider(ctx *context.Context, provider schemas.Mo ``` **Notes:** -- If both `AccessKey` and `SecretKey` are empty, Bifrost uses IAM role authentication from environment -- `ARN` is required for URL formation - `Deployments` mapping is ignored without it -- When using `ARN` + `Deployments`, Bifrost uses model profiles; otherwise forms path with incoming model name directly +- If using API Key authentication, set `Value` field to the API key, else leave it empty for IAM role authentication. +- In IAM role authentication, if both `AccessKey` and `SecretKey` are empty, Bifrost uses IAM from the environment. +- `ARN` is required for URL formation - `Deployments` mapping is ignored without it. +- When using `ARN` + `Deployments`, Bifrost uses model profiles; otherwise forms path with incoming model name directly. diff --git a/framework/configstore/migrations.go b/framework/configstore/migrations.go index 89ce7ddecb..b6a7e5e8c1 100644 --- a/framework/configstore/migrations.go +++ b/framework/configstore/migrations.go @@ -9,9 +9,7 @@ import ( // Migrate performs the necessary database migrations. func triggerMigrations(db *gorm.DB) error { - var err error - err = migrationInit(db) - if err != nil { + if err := migrationInit(db); err != nil { return err } return nil diff --git a/framework/configstore/sqlite.go b/framework/configstore/sqlite.go index cfd6603036..76514bbba3 100644 --- a/framework/configstore/sqlite.go +++ b/framework/configstore/sqlite.go @@ -7,7 +7,6 @@ import ( "os" "strings" - bifrost "github.com/maximhq/bifrost/core" "github.com/maximhq/bifrost/core/schemas" "github.com/maximhq/bifrost/framework/logstore" "github.com/maximhq/bifrost/framework/vectorstore" @@ -603,7 +602,7 @@ func (s *SQLiteConfigStore) UpdateVectorStoreConfig(config *vectorstore.Config) if err := tx.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&TableVectorStoreConfig{}).Error; err != nil { return err } - jsonConfig, err := bifrost.MarshalToStringPtr(config.Config) + jsonConfig, err := marshalToStringPtr(config.Config) if err != nil { return err } @@ -642,7 +641,7 @@ func (s *SQLiteConfigStore) UpdateLogsStoreConfig(config *logstore.Config) error if err := tx.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&TableLogStoreConfig{}).Error; err != nil { return err } - jsonConfig, err := bifrost.MarshalToStringPtr(config) + jsonConfig, err := marshalToStringPtr(config) if err != nil { return err } diff --git a/framework/configstore/utils.go b/framework/configstore/utils.go index 78aa44ddc2..fe7137d763 100644 --- a/framework/configstore/utils.go +++ b/framework/configstore/utils.go @@ -8,6 +8,30 @@ import ( "github.com/maximhq/bifrost/core/schemas" ) +// marshalToString marshals the given value to a JSON string. +func marshalToString(v any) (string, error) { + if v == nil { + return "", nil + } + data, err := json.Marshal(v) + if err != nil { + return "", err + } + return string(data), nil +} + +// marshalToStringPtr marshals the given value to a JSON string and returns a pointer to the string. +func marshalToStringPtr(v any) (*string, error) { + if v == nil { + return nil, nil + } + data, err := marshalToString(v) + if err != nil { + return nil, err + } + return &data, nil +} + // deepCopy creates a deep copy of a given type func deepCopy[T any](in T) (T, error) { var out T @@ -134,4 +158,4 @@ func substituteMCPEnvVars(config *schemas.MCPConfig, envKeys map[string][]EnvKey } } } -} \ No newline at end of file +} diff --git a/ui/app/providers/fragments/apiKeysFormFragment.tsx b/ui/app/providers/fragments/apiKeysFormFragment.tsx index 4abe6714a8..b3838b4d61 100644 --- a/ui/app/providers/fragments/apiKeysFormFragment.tsx +++ b/ui/app/providers/fragments/apiKeysFormFragment.tsx @@ -3,6 +3,7 @@ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { Separator } from "@/components/ui/separator"; import { TagInput } from "@/components/ui/tagInput"; import { Textarea } from "@/components/ui/textarea"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; @@ -20,7 +21,7 @@ const MODEL_PLACEHOLDERS = { default: "e.g. gpt-4, gpt-3.5-turbo. Leave blank for all models.", openai: "e.g. gpt-4, gpt-3.5-turbo, gpt-4-turbo, gpt-4o", azure: "e.g. gpt-4, gpt-3.5-turbo (must match deployment mappings)", - bedrock: "e.g. anthropic.claude-v2, amazon.titan-text-express-v1", + bedrock: "e.g. claude-v2, titan-text-express-v1", vertex: "e.g. gemini-pro, text-bison, chat-bison", }; @@ -41,15 +42,15 @@ export function ApiKeyFormFragment({ control, providerName }: Props) { {isBedrock && ( - IAM Role Authentication + Authentication Methods - Leave both Access Key and Secret Key empty to use IAM roles attached to your environment (EC2, Lambda, ECS, EKS). This is the - recommended approach for production deployments. + You can either use IAM role authentication or API key authentication. Please leave API Key empty when using IAM role + authentication. )}
- {!isVertex && !isBedrock && ( + {!isVertex && (
+ + + + IAM Role Authentication + + Leave both Access Key and Secret Key empty to use IAM roles attached to your environment (EC2, Lambda, ECS, EKS). + + ( - ARN + Access Key - + @@ -288,12 +304,19 @@ export function ApiKeyFormFragment({ control, providerName }: Props) { /> ( - Access Key + Secret Key - + @@ -301,25 +324,40 @@ export function ApiKeyFormFragment({ control, providerName }: Props) { /> ( - Secret Key + Session Token (Optional) - + )} /> + ( - Session Token (Optional) + Region (Required) - + @@ -327,12 +365,19 @@ export function ApiKeyFormFragment({ control, providerName }: Props) { /> ( - Region (Required) + ARN - + @@ -347,7 +392,7 @@ export function ApiKeyFormFragment({ control, providerName }: Props) { JSON object mapping model names to inference profile names