295 lines
13 KiB
Go
295 lines
13 KiB
Go
// Package schemas defines the core schemas and types used by the Bifrost system.
|
|
package schemas
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
type KeyStatusType string
|
|
|
|
const (
|
|
KeyStatusSuccess KeyStatusType = "success"
|
|
KeyStatusListModelsFailed KeyStatusType = "list_models_failed"
|
|
)
|
|
|
|
// WhiteList is a list of values that are allowed to be used.
|
|
// Semantics:
|
|
// - "*" (alone) means all values are allowed.
|
|
// - Empty list means nothing is allowed.
|
|
// - Non-empty list (without "*") means only the listed values are allowed.
|
|
//
|
|
// This type is used generically for any field that needs whitelist behavior
|
|
// (e.g., allowed models, allowed tools).
|
|
type WhiteList []string
|
|
|
|
// Contains reports whether value is in the whitelist.
|
|
// Returns true if value is in the list.
|
|
func (wl WhiteList) Contains(value string) bool {
|
|
return slices.ContainsFunc(wl, func(s string) bool {
|
|
return strings.EqualFold(s, value)
|
|
})
|
|
}
|
|
|
|
// IsAllowed reports whether value is in the whitelist.
|
|
// Returns true if value is in the list.
|
|
func (wl WhiteList) IsAllowed(value string) bool {
|
|
return wl.IsUnrestricted() || wl.Contains(value)
|
|
}
|
|
|
|
// IsEmpty reports whether the whitelist has no entries.
|
|
func (wl WhiteList) IsEmpty() bool {
|
|
return len(wl) == 0
|
|
}
|
|
|
|
// IsUnrestricted reports whether the whitelist contains only "*",
|
|
// meaning all values are allowed.
|
|
func (wl WhiteList) IsUnrestricted() bool {
|
|
return len(wl) == 1 && wl[0] == "*"
|
|
}
|
|
|
|
// IsRestricted reports whether the whitelist contains entries other than "*",
|
|
// meaning only the listed values are allowed.
|
|
func (wl WhiteList) IsRestricted() bool {
|
|
return !wl.IsUnrestricted()
|
|
}
|
|
|
|
// Validate checks that the whitelist is well-formed.
|
|
// Returns an error if "*" is present alongside other values, or if there are duplicate entries.
|
|
func (wl WhiteList) Validate() error {
|
|
if wl.Contains("*") && len(wl) > 1 {
|
|
return fmt.Errorf("wildcard '*' cannot be used with other values in the whitelist")
|
|
}
|
|
seen := make(map[string]struct{}, len(wl))
|
|
for _, v := range wl {
|
|
normalized := strings.ToLower(v)
|
|
if _, ok := seen[normalized]; ok {
|
|
return fmt.Errorf("duplicate value '%s' in whitelist", v)
|
|
}
|
|
seen[normalized] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BlackList is a list of values that are denied.
|
|
// Semantics:
|
|
// - "*" (alone) means all values are blocked.
|
|
// - Empty list means nothing is blocked.
|
|
// - Non-empty list (without "*") means only the listed values are blocked.
|
|
type BlackList []string
|
|
|
|
func (bl BlackList) Contains(value string) bool {
|
|
return slices.ContainsFunc(bl, func(s string) bool {
|
|
return strings.EqualFold(s, value)
|
|
})
|
|
}
|
|
|
|
// IsBlocked reports whether value is blocked.
|
|
func (bl BlackList) IsBlocked(value string) bool {
|
|
return bl.IsBlockAll() || bl.Contains(value)
|
|
}
|
|
|
|
// IsEmpty reports whether the blacklist has no entries (nothing is blocked).
|
|
func (bl BlackList) IsEmpty() bool {
|
|
return len(bl) == 0
|
|
}
|
|
|
|
// IsBlockAll reports whether the blacklist contains "*", meaning all values are blocked.
|
|
func (bl BlackList) IsBlockAll() bool {
|
|
return len(bl) == 1 && bl[0] == "*"
|
|
}
|
|
|
|
// Validate checks that the blacklist is well-formed.
|
|
func (bl BlackList) Validate() error {
|
|
if bl.Contains("*") && len(bl) > 1 {
|
|
return fmt.Errorf("wildcard '*' cannot be used with other values in the blacklist")
|
|
}
|
|
seen := make(map[string]struct{}, len(bl))
|
|
for _, v := range bl {
|
|
normalized := strings.ToLower(v)
|
|
if _, ok := seen[normalized]; ok {
|
|
return fmt.Errorf("duplicate value '%s' in blacklist", v)
|
|
}
|
|
seen[normalized] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Key represents an API key and its associated configuration for a provider.
|
|
// It contains the key value, supported models, and a weight for load balancing.
|
|
type Key struct {
|
|
ID string `json:"id"` // The unique identifier for the key (used by bifrost to identify the key)
|
|
Name string `json:"name"` // The name of the key (used by users to identify the key, not used by bifrost)
|
|
Value EnvVar `json:"value"` // The actual API key value
|
|
Models WhiteList `json:"models"` // List of models this key can access
|
|
BlacklistedModels BlackList `json:"blacklisted_models"` // List of models this key cannot access
|
|
Weight float64 `json:"weight"` // Weight for load balancing between multiple keys
|
|
Aliases KeyAliases `json:"aliases,omitempty"` // Mapping of model identifiers to inference profiles
|
|
AzureKeyConfig *AzureKeyConfig `json:"azure_key_config,omitempty"` // Azure-specific key configuration
|
|
VertexKeyConfig *VertexKeyConfig `json:"vertex_key_config,omitempty"` // Vertex-specific key configuration
|
|
BedrockKeyConfig *BedrockKeyConfig `json:"bedrock_key_config,omitempty"` // AWS Bedrock-specific key configuration
|
|
VLLMKeyConfig *VLLMKeyConfig `json:"vllm_key_config,omitempty"` // vLLM-specific key configuration
|
|
ReplicateKeyConfig *ReplicateKeyConfig `json:"replicate_key_config,omitempty"` // Replicate-specific key configuration
|
|
OllamaKeyConfig *OllamaKeyConfig `json:"ollama_key_config,omitempty"` // Ollama-specific key configuration
|
|
SGLKeyConfig *SGLKeyConfig `json:"sgl_key_config,omitempty"` // SGLang-specific key configuration
|
|
Enabled *bool `json:"enabled,omitempty"` // Whether the key is active (default:true)
|
|
UseForBatchAPI *bool `json:"use_for_batch_api,omitempty"` // Whether this key can be used for batch API operations (default:false for new keys, migrated keys default to true)
|
|
ConfigHash string `json:"config_hash,omitempty"` // Hash of config.json version, used for change detection
|
|
Status KeyStatusType `json:"status,omitempty"` // Status of key
|
|
Description string `json:"description,omitempty"` // Description of key
|
|
}
|
|
|
|
type KeyAliases map[string]string
|
|
|
|
func (ka KeyAliases) Validate() error {
|
|
seen := make(map[string]struct{}, len(ka))
|
|
for from, to := range ka {
|
|
if strings.TrimSpace(from) == "" {
|
|
return fmt.Errorf("alias source cannot be empty")
|
|
}
|
|
if strings.TrimSpace(to) == "" {
|
|
return fmt.Errorf("alias target for %q cannot be empty", from)
|
|
}
|
|
if strings.TrimSpace(from) != from {
|
|
return fmt.Errorf("alias source %q cannot have leading or trailing whitespace", from)
|
|
}
|
|
if strings.TrimSpace(to) != to {
|
|
return fmt.Errorf("alias target for %q cannot have leading or trailing whitespace", from)
|
|
}
|
|
normalized := strings.ToLower(from)
|
|
if _, ok := seen[normalized]; ok {
|
|
return fmt.Errorf("duplicate alias source %q (case-insensitive)", from)
|
|
}
|
|
seen[normalized] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ka KeyAliases) Resolve(model string) string {
|
|
if ka == nil {
|
|
return model
|
|
}
|
|
if alias, ok := ka[model]; ok {
|
|
return alias
|
|
}
|
|
// Fall back to case-insensitive lookup for consistency with WhiteList.Contains
|
|
for k, v := range ka {
|
|
if strings.EqualFold(k, model) {
|
|
return v
|
|
}
|
|
}
|
|
return model
|
|
}
|
|
|
|
type AzureAuthType string
|
|
|
|
const (
|
|
AzureAuthTypeClientSecret AzureAuthType = "client_secret"
|
|
AzureAuthTypeManagedIdentity AzureAuthType = "managed_identity"
|
|
)
|
|
|
|
// AzureKeyConfig represents the Azure-specific configuration.
|
|
// It contains Azure-specific settings required for service access and deployment management.
|
|
type AzureKeyConfig struct {
|
|
Endpoint EnvVar `json:"endpoint"` // Azure service endpoint URL
|
|
APIVersion *EnvVar `json:"api_version,omitempty"` // Azure API version to use; defaults to "2024-10-21"
|
|
|
|
ClientID *EnvVar `json:"client_id,omitempty"` // Azure client ID for authentication
|
|
ClientSecret *EnvVar `json:"client_secret,omitempty"` // Azure client secret for authentication
|
|
TenantID *EnvVar `json:"tenant_id,omitempty"` // Azure tenant ID for authentication
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
}
|
|
|
|
// VertexKeyConfig represents the Vertex-specific configuration.
|
|
// It contains Vertex-specific settings required for authentication and service access.
|
|
type VertexKeyConfig struct {
|
|
ProjectID EnvVar `json:"project_id"`
|
|
ProjectNumber EnvVar `json:"project_number"`
|
|
Region EnvVar `json:"region"`
|
|
AuthCredentials EnvVar `json:"auth_credentials"`
|
|
}
|
|
|
|
// NOTE: To use Vertex IAM role authentication, set AuthCredentials to empty string.
|
|
|
|
// S3BucketConfig represents a single S3 bucket configuration for batch operations.
|
|
type S3BucketConfig struct {
|
|
BucketName string `json:"bucket_name"` // S3 bucket name
|
|
Prefix string `json:"prefix,omitempty"` // S3 key prefix for batch files
|
|
IsDefault bool `json:"is_default,omitempty"` // Whether this is the default bucket for batch operations
|
|
}
|
|
|
|
// BatchS3Config holds S3 bucket configurations for Bedrock batch operations.
|
|
// Supports multiple buckets to allow flexible batch job routing.
|
|
type BatchS3Config struct {
|
|
Buckets []S3BucketConfig `json:"buckets,omitempty"` // List of S3 bucket configurations
|
|
}
|
|
|
|
// BedrockKeyConfig represents the AWS Bedrock-specific configuration.
|
|
// It contains AWS-specific settings required for authentication and service access.
|
|
type BedrockKeyConfig struct {
|
|
AccessKey EnvVar `json:"access_key,omitempty"` // AWS access key for authentication
|
|
SecretKey EnvVar `json:"secret_key,omitempty"` // AWS secret access key for authentication
|
|
SessionToken *EnvVar `json:"session_token,omitempty"` // AWS session token for temporary credentials
|
|
Region *EnvVar `json:"region,omitempty"` // AWS region for service access
|
|
ARN *EnvVar `json:"arn,omitempty"` // Amazon Resource Name for resource identification
|
|
// IAM role for STS AssumeRole
|
|
RoleARN *EnvVar `json:"role_arn,omitempty"`
|
|
ExternalID *EnvVar `json:"external_id,omitempty"`
|
|
RoleSessionName *EnvVar `json:"session_name,omitempty"`
|
|
|
|
BatchS3Config *BatchS3Config `json:"batch_s3_config,omitempty"` // S3 bucket configuration for batch operations
|
|
}
|
|
|
|
// 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.
|
|
|
|
// VLLMKeyConfig represents the vLLM-specific key configuration.
|
|
// It allows each key to target a different vLLM server URL and model name,
|
|
// enabling per-key routing and round-robin load balancing across multiple vLLM instances.
|
|
type VLLMKeyConfig struct {
|
|
URL EnvVar `json:"url"` // VLLM server base URL (required, supports env. prefix)
|
|
ModelName string `json:"model_name"` // Exact model name served on this VLLM instance (used for key selection)
|
|
}
|
|
|
|
// ReplicateKeyConfig represents the Replicate-specific key configuration.
|
|
// It contains Replicate-specific settings required for authentication and service access.
|
|
type ReplicateKeyConfig struct {
|
|
UseDeploymentsEndpoint bool `json:"use_deployments_endpoint"` // Whether to use the deployments endpoint instead of the models endpoint
|
|
}
|
|
|
|
// OllamaKeyConfig represents the Ollama-specific key configuration.
|
|
// It allows each key to target a different Ollama server URL,
|
|
// enabling per-key routing and round-robin load balancing across multiple Ollama instances.
|
|
type OllamaKeyConfig struct {
|
|
URL EnvVar `json:"url"` // Ollama server base URL (required, supports env. prefix)
|
|
}
|
|
|
|
// SGLKeyConfig represents the SGLang-specific key configuration.
|
|
// It allows each key to target a different SGLang server URL,
|
|
// enabling per-key routing and round-robin load balancing across multiple SGLang instances.
|
|
type SGLKeyConfig struct {
|
|
URL EnvVar `json:"url"` // SGLang server base URL (required, supports env. prefix)
|
|
}
|
|
|
|
// 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 {
|
|
// GetConfiguredProviders returns a list of providers that are configured
|
|
// in the account. This is used to determine which providers are available for use.
|
|
GetConfiguredProviders() ([]ModelProvider, error)
|
|
|
|
// GetKeysForProvider returns the API keys configured for a specific provider.
|
|
// The keys include their values, supported models, and weights for load balancing.
|
|
// The context can carry data from any source that sets values before the Bifrost request,
|
|
// including but not limited to plugin pre-hooks, application logic, or any in app middleware sharing the context.
|
|
// This enables dynamic key selection based on any context values present during the request.
|
|
GetKeysForProvider(ctx context.Context, providerKey ModelProvider) ([]Key, error)
|
|
|
|
// GetConfigForProvider returns the configuration for a specific provider.
|
|
// This includes network settings, authentication details, and other provider-specific
|
|
// configurations.
|
|
GetConfigForProvider(providerKey ModelProvider) (*ProviderConfig, error)
|
|
}
|