From d26ad42f868e912a82cd53113365ff87c0e9e23d Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Tue, 26 Nov 2024 12:54:38 +0530 Subject: [PATCH] docs(router_architecture.md): add router architecture docs --- docs/my-website/docs/proxy/config_settings.md | 481 ++++++++++++++++++ docs/my-website/docs/proxy/configs.md | 475 ----------------- docs/my-website/docs/router_architecture.md | 24 + docs/my-website/img/router_architecture.png | Bin 0 -> 60804 bytes docs/my-website/sidebars.js | 8 +- 5 files changed, 511 insertions(+), 477 deletions(-) create mode 100644 docs/my-website/docs/proxy/config_settings.md create mode 100644 docs/my-website/docs/router_architecture.md create mode 100644 docs/my-website/img/router_architecture.png diff --git a/docs/my-website/docs/proxy/config_settings.md b/docs/my-website/docs/proxy/config_settings.md new file mode 100644 index 000000000..91deba958 --- /dev/null +++ b/docs/my-website/docs/proxy/config_settings.md @@ -0,0 +1,481 @@ +# All settings + + +```yaml +environment_variables: {} + +model_list: + - model_name: string + litellm_params: {} + model_info: + id: string + mode: embedding + input_cost_per_token: 0 + output_cost_per_token: 0 + max_tokens: 2048 + base_model: gpt-4-1106-preview + additionalProp1: {} + +litellm_settings: + # Logging/Callback settings + success_callback: ["langfuse"] # list of success callbacks + failure_callback: ["sentry"] # list of failure callbacks + callbacks: ["otel"] # list of callbacks - runs on success and failure + service_callbacks: ["datadog", "prometheus"] # logs redis, postgres failures on datadog, prometheus + turn_off_message_logging: boolean # prevent the messages and responses from being logged to on your callbacks, but request metadata will still be logged. + redact_user_api_key_info: boolean # Redact information about the user api key (hashed token, user_id, team id, etc.), from logs. Currently supported for Langfuse, OpenTelemetry, Logfire, ArizeAI logging. + langfuse_default_tags: ["cache_hit", "cache_key", "proxy_base_url", "user_api_key_alias", "user_api_key_user_id", "user_api_key_user_email", "user_api_key_team_alias", "semantic-similarity", "proxy_base_url"] # default tags for Langfuse Logging + + # Networking settings + request_timeout: 10 # (int) llm requesttimeout in seconds. Raise Timeout error if call takes longer than 10s. Sets litellm.request_timeout + force_ipv4: boolean # If true, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6 + Anthropic API + + set_verbose: boolean # sets litellm.set_verbose=True to view verbose debug logs. DO NOT LEAVE THIS ON IN PRODUCTION + json_logs: boolean # if true, logs will be in json format + + # Fallbacks, reliability + default_fallbacks: ["claude-opus"] # set default_fallbacks, in case a specific model group is misconfigured / bad. + content_policy_fallbacks: [{"gpt-3.5-turbo-small": ["claude-opus"]}] # fallbacks for ContentPolicyErrors + context_window_fallbacks: [{"gpt-3.5-turbo-small": ["gpt-3.5-turbo-large", "claude-opus"]}] # fallbacks for ContextWindowExceededErrors + + + + # Caching settings + cache: true + cache_params: # set cache params for redis + type: redis # type of cache to initialize + + # Optional - Redis Settings + host: "localhost" # The host address for the Redis cache. Required if type is "redis". + port: 6379 # The port number for the Redis cache. Required if type is "redis". + password: "your_password" # The password for the Redis cache. Required if type is "redis". + namespace: "litellm.caching.caching" # namespace for redis cache + + # Optional - Redis Cluster Settings + redis_startup_nodes: [{"host": "127.0.0.1", "port": "7001"}] + + # Optional - Redis Sentinel Settings + service_name: "mymaster" + sentinel_nodes: [["localhost", 26379]] + + # Optional - Qdrant Semantic Cache Settings + qdrant_semantic_cache_embedding_model: openai-embedding # the model should be defined on the model_list + qdrant_collection_name: test_collection + qdrant_quantization_config: binary + similarity_threshold: 0.8 # similarity threshold for semantic cache + + # Optional - S3 Cache Settings + s3_bucket_name: cache-bucket-litellm # AWS Bucket Name for S3 + s3_region_name: us-west-2 # AWS Region Name for S3 + s3_aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID # us os.environ/ to pass environment variables. This is AWS Access Key ID for S3 + s3_aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY # AWS Secret Access Key for S3 + s3_endpoint_url: https://s3.amazonaws.com # [OPTIONAL] S3 endpoint URL, if you want to use Backblaze/cloudflare s3 bucket + + # Common Cache settings + # Optional - Supported call types for caching + supported_call_types: ["acompletion", "atext_completion", "aembedding", "atranscription"] + # /chat/completions, /completions, /embeddings, /audio/transcriptions + mode: default_off # if default_off, you need to opt in to caching on a per call basis + ttl: 600 # ttl for caching + + +callback_settings: + otel: + message_logging: boolean # OTEL logging callback specific settings + +general_settings: + completion_model: string + disable_spend_logs: boolean # turn off writing each transaction to the db + disable_master_key_return: boolean # turn off returning master key on UI (checked on '/user/info' endpoint) + disable_retry_on_max_parallel_request_limit_error: boolean # turn off retries when max parallel request limit is reached + disable_reset_budget: boolean # turn off reset budget scheduled task + disable_adding_master_key_hash_to_db: boolean # turn off storing master key hash in db, for spend tracking + enable_jwt_auth: boolean # allow proxy admin to auth in via jwt tokens with 'litellm_proxy_admin' in claims + enforce_user_param: boolean # requires all openai endpoint requests to have a 'user' param + allowed_routes: ["route1", "route2"] # list of allowed proxy API routes - a user can access. (currently JWT-Auth only) + key_management_system: google_kms # either google_kms or azure_kms + master_key: string + + # Database Settings + database_url: string + database_connection_pool_limit: 0 # default 100 + database_connection_timeout: 0 # default 60s + allow_requests_on_db_unavailable: boolean # if true, will allow requests that can not connect to the DB to verify Virtual Key to still work + + custom_auth: string + max_parallel_requests: 0 # the max parallel requests allowed per deployment + global_max_parallel_requests: 0 # the max parallel requests allowed on the proxy all up + infer_model_from_keys: true + background_health_checks: true + health_check_interval: 300 + alerting: ["slack", "email"] + alerting_threshold: 0 + use_client_credentials_pass_through_routes: boolean # use client credentials for all pass through routes like "/vertex-ai", /bedrock/. When this is True Virtual Key auth will not be applied on these endpoints +``` + +### litellm_settings - Reference + +| Name | Type | Description | +|------|------|-------------| +| success_callback | array of strings | List of success callbacks. [Doc Proxy logging callbacks](logging), [Doc Metrics](prometheus) | +| failure_callback | array of strings | List of failure callbacks [Doc Proxy logging callbacks](logging), [Doc Metrics](prometheus) | +| callbacks | array of strings | List of callbacks - runs on success and failure [Doc Proxy logging callbacks](logging), [Doc Metrics](prometheus) | +| service_callbacks | array of strings | System health monitoring - Logs redis, postgres failures on specified services (e.g. datadog, prometheus) [Doc Metrics](prometheus) | +| turn_off_message_logging | boolean | If true, prevents messages and responses from being logged to callbacks, but request metadata will still be logged [Proxy Logging](logging) | +| modify_params | boolean | If true, allows modifying the parameters of the request before it is sent to the LLM provider | +| enable_preview_features | boolean | If true, enables preview features - e.g. Azure O1 Models with streaming support.| +| redact_user_api_key_info | boolean | If true, redacts information about the user api key from logs [Proxy Logging](logging#redacting-userapikeyinfo) | +| langfuse_default_tags | array of strings | Default tags for Langfuse Logging. Use this if you want to control which LiteLLM-specific fields are logged as tags by the LiteLLM proxy. By default LiteLLM Proxy logs no LiteLLM-specific fields as tags. [Further docs](./logging#litellm-specific-tags-on-langfuse---cache_hit-cache_key) | +| set_verbose | boolean | If true, sets litellm.set_verbose=True to view verbose debug logs. DO NOT LEAVE THIS ON IN PRODUCTION | +| json_logs | boolean | If true, logs will be in json format. If you need to store the logs as JSON, just set the `litellm.json_logs = True`. We currently just log the raw POST request from litellm as a JSON [Further docs](./debugging) | +| default_fallbacks | array of strings | List of fallback models to use if a specific model group is misconfigured / bad. [Further docs](./reliability#default-fallbacks) | +| request_timeout | integer | The timeout for requests in seconds. If not set, the default value is `6000 seconds`. [For reference OpenAI Python SDK defaults to `600 seconds`.](https://github.com/openai/openai-python/blob/main/src/openai/_constants.py) | +| force_ipv4 | boolean | If true, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6 + Anthropic API | +| content_policy_fallbacks | array of objects | Fallbacks to use when a ContentPolicyViolationError is encountered. [Further docs](./reliability#content-policy-fallbacks) | +| context_window_fallbacks | array of objects | Fallbacks to use when a ContextWindowExceededError is encountered. [Further docs](./reliability#context-window-fallbacks) | +| cache | boolean | If true, enables caching. [Further docs](./caching) | +| cache_params | object | Parameters for the cache. [Further docs](./caching) | +| cache_params.type | string | The type of cache to initialize. Can be one of ["local", "redis", "redis-semantic", "s3", "disk", "qdrant-semantic"]. Defaults to "redis". [Furher docs](./caching) | +| cache_params.host | string | The host address for the Redis cache. Required if type is "redis". | +| cache_params.port | integer | The port number for the Redis cache. Required if type is "redis". | +| cache_params.password | string | The password for the Redis cache. Required if type is "redis". | +| cache_params.namespace | string | The namespace for the Redis cache. | +| cache_params.redis_startup_nodes | array of objects | Redis Cluster Settings. [Further docs](./caching) | +| cache_params.service_name | string | Redis Sentinel Settings. [Further docs](./caching) | +| cache_params.sentinel_nodes | array of arrays | Redis Sentinel Settings. [Further docs](./caching) | +| cache_params.ttl | integer | The time (in seconds) to store entries in cache. | +| cache_params.qdrant_semantic_cache_embedding_model | string | The embedding model to use for qdrant semantic cache. | +| cache_params.qdrant_collection_name | string | The name of the collection to use for qdrant semantic cache. | +| cache_params.qdrant_quantization_config | string | The quantization configuration for the qdrant semantic cache. | +| cache_params.similarity_threshold | float | The similarity threshold for the semantic cache. | +| cache_params.s3_bucket_name | string | The name of the S3 bucket to use for the semantic cache. | +| cache_params.s3_region_name | string | The region name for the S3 bucket. | +| cache_params.s3_aws_access_key_id | string | The AWS access key ID for the S3 bucket. | +| cache_params.s3_aws_secret_access_key | string | The AWS secret access key for the S3 bucket. | +| cache_params.s3_endpoint_url | string | Optional - The endpoint URL for the S3 bucket. | +| cache_params.supported_call_types | array of strings | The types of calls to cache. [Further docs](./caching) | +| cache_params.mode | string | The mode of the cache. [Further docs](./caching) | +| disable_end_user_cost_tracking | boolean | If true, turns off end user cost tracking on prometheus metrics + litellm spend logs table on proxy. | +| key_generation_settings | object | Restricts who can generate keys. [Further docs](./virtual_keys.md#restricting-key-generation) | + +### general_settings - Reference + +| Name | Type | Description | +|------|------|-------------| +| completion_model | string | The default model to use for completions when `model` is not specified in the request | +| disable_spend_logs | boolean | If true, turns off writing each transaction to the database | +| disable_master_key_return | boolean | If true, turns off returning master key on UI. (checked on '/user/info' endpoint) | +| disable_retry_on_max_parallel_request_limit_error | boolean | If true, turns off retries when max parallel request limit is reached | +| disable_reset_budget | boolean | If true, turns off reset budget scheduled task | +| disable_adding_master_key_hash_to_db | boolean | If true, turns off storing master key hash in db | +| enable_jwt_auth | boolean | allow proxy admin to auth in via jwt tokens with 'litellm_proxy_admin' in claims. [Doc on JWT Tokens](token_auth) | +| enforce_user_param | boolean | If true, requires all OpenAI endpoint requests to have a 'user' param. [Doc on call hooks](call_hooks)| +| allowed_routes | array of strings | List of allowed proxy API routes a user can access [Doc on controlling allowed routes](enterprise#control-available-public-private-routes)| +| key_management_system | string | Specifies the key management system. [Doc Secret Managers](../secret) | +| master_key | string | The master key for the proxy [Set up Virtual Keys](virtual_keys) | +| database_url | string | The URL for the database connection [Set up Virtual Keys](virtual_keys) | +| database_connection_pool_limit | integer | The limit for database connection pool [Setting DB Connection Pool limit](#configure-db-pool-limits--connection-timeouts) | +| database_connection_timeout | integer | The timeout for database connections in seconds [Setting DB Connection Pool limit, timeout](#configure-db-pool-limits--connection-timeouts) | +| allow_requests_on_db_unavailable | boolean | If true, allows requests to succeed even if DB is unreachable. **Only use this if running LiteLLM in your VPC** This will allow requests to work even when LiteLLM cannot connect to the DB to verify a Virtual Key | +| custom_auth | string | Write your own custom authentication logic [Doc Custom Auth](virtual_keys#custom-auth) | +| max_parallel_requests | integer | The max parallel requests allowed per deployment | +| global_max_parallel_requests | integer | The max parallel requests allowed on the proxy overall | +| infer_model_from_keys | boolean | If true, infers the model from the provided keys | +| background_health_checks | boolean | If true, enables background health checks. [Doc on health checks](health) | +| health_check_interval | integer | The interval for health checks in seconds [Doc on health checks](health) | +| alerting | array of strings | List of alerting methods [Doc on Slack Alerting](alerting) | +| alerting_threshold | integer | The threshold for triggering alerts [Doc on Slack Alerting](alerting) | +| use_client_credentials_pass_through_routes | boolean | If true, uses client credentials for all pass-through routes. [Doc on pass through routes](pass_through) | +| health_check_details | boolean | If false, hides health check details (e.g. remaining rate limit). [Doc on health checks](health) | +| public_routes | List[str] | (Enterprise Feature) Control list of public routes | +| alert_types | List[str] | Control list of alert types to send to slack (Doc on alert types)[./alerting.md] | +| enforced_params | List[str] | (Enterprise Feature) List of params that must be included in all requests to the proxy | +| enable_oauth2_auth | boolean | (Enterprise Feature) If true, enables oauth2.0 authentication | +| use_x_forwarded_for | str | If true, uses the X-Forwarded-For header to get the client IP address | +| service_account_settings | List[Dict[str, Any]] | Set `service_account_settings` if you want to create settings that only apply to service account keys (Doc on service accounts)[./service_accounts.md] | +| image_generation_model | str | The default model to use for image generation - ignores model set in request | +| store_model_in_db | boolean | If true, allows `/model/new` endpoint to store model information in db. Endpoint disabled by default. [Doc on `/model/new` endpoint](./model_management.md#create-a-new-model) | +| max_request_size_mb | int | The maximum size for requests in MB. Requests above this size will be rejected. | +| max_response_size_mb | int | The maximum size for responses in MB. LLM Responses above this size will not be sent. | +| proxy_budget_rescheduler_min_time | int | The minimum time (in seconds) to wait before checking db for budget resets. **Default is 597 seconds** | +| proxy_budget_rescheduler_max_time | int | The maximum time (in seconds) to wait before checking db for budget resets. **Default is 605 seconds** | +| proxy_batch_write_at | int | Time (in seconds) to wait before batch writing spend logs to the db. **Default is 10 seconds** | +| alerting_args | dict | Args for Slack Alerting [Doc on Slack Alerting](./alerting.md) | +| custom_key_generate | str | Custom function for key generation [Doc on custom key generation](./virtual_keys.md#custom--key-generate) | +| allowed_ips | List[str] | List of IPs allowed to access the proxy. If not set, all IPs are allowed. | +| embedding_model | str | The default model to use for embeddings - ignores model set in request | +| default_team_disabled | boolean | If true, users cannot create 'personal' keys (keys with no team_id). | +| alert_to_webhook_url | Dict[str] | [Specify a webhook url for each alert type.](./alerting.md#set-specific-slack-channels-per-alert-type) | +| key_management_settings | List[Dict[str, Any]] | Settings for key management system (e.g. AWS KMS, Azure Key Vault) [Doc on key management](../secret.md) | +| allow_user_auth | boolean | (Deprecated) old approach for user authentication. | +| user_api_key_cache_ttl | int | The time (in seconds) to cache user api keys in memory. | +| disable_prisma_schema_update | boolean | If true, turns off automatic schema updates to DB | +| litellm_key_header_name | str | If set, allows passing LiteLLM keys as a custom header. [Doc on custom headers](./virtual_keys.md#custom-headers) | +| moderation_model | str | The default model to use for moderation. | +| custom_sso | str | Path to a python file that implements custom SSO logic. [Doc on custom SSO](./custom_sso.md) | +| allow_client_side_credentials | boolean | If true, allows passing client side credentials to the proxy. (Useful when testing finetuning models) [Doc on client side credentials](./virtual_keys.md#client-side-credentials) | +| admin_only_routes | List[str] | (Enterprise Feature) List of routes that are only accessible to admin users. [Doc on admin only routes](./enterprise#control-available-public-private-routes) | +| use_azure_key_vault | boolean | If true, load keys from azure key vault | +| use_google_kms | boolean | If true, load keys from google kms | +| spend_report_frequency | str | Specify how often you want a Spend Report to be sent (e.g. "1d", "2d", "30d") [More on this](./alerting.md#spend-report-frequency) | +| ui_access_mode | Literal["admin_only"] | If set, restricts access to the UI to admin users only. [Docs](./ui.md#restrict-ui-access) | +| litellm_jwtauth | Dict[str, Any] | Settings for JWT authentication. [Docs](./token_auth.md) | +| litellm_license | str | The license key for the proxy. [Docs](../enterprise.md#how-does-deployment-with-enterprise-license-work) | +| oauth2_config_mappings | Dict[str, str] | Define the OAuth2 config mappings | +| pass_through_endpoints | List[Dict[str, Any]] | Define the pass through endpoints. [Docs](./pass_through) | +| enable_oauth2_proxy_auth | boolean | (Enterprise Feature) If true, enables oauth2.0 authentication | +| forward_openai_org_id | boolean | If true, forwards the OpenAI Organization ID to the backend LLM call (if it's OpenAI). | +| forward_client_headers_to_llm_api | boolean | If true, forwards the client headers (any `x-` headers) to the backend LLM call | + +### router_settings - Reference + +:::info + +Most values can also be set via `litellm_settings`. If you see overlapping values, settings on `router_settings` will override those on `litellm_settings`. +::: + +```yaml +router_settings: + routing_strategy: usage-based-routing-v2 # Literal["simple-shuffle", "least-busy", "usage-based-routing","latency-based-routing"], default="simple-shuffle" + redis_host: # string + redis_password: # string + redis_port: # string + enable_pre_call_check: true # bool - Before call is made check if a call is within model context window + allowed_fails: 3 # cooldown model if it fails > 1 call in a minute. + cooldown_time: 30 # (in seconds) how long to cooldown model if fails/min > allowed_fails + disable_cooldowns: True # bool - Disable cooldowns for all models + enable_tag_filtering: True # bool - Use tag based routing for requests + retry_policy: { # Dict[str, int]: retry policy for different types of exceptions + "AuthenticationErrorRetries": 3, + "TimeoutErrorRetries": 3, + "RateLimitErrorRetries": 3, + "ContentPolicyViolationErrorRetries": 4, + "InternalServerErrorRetries": 4 + } + allowed_fails_policy: { + "BadRequestErrorAllowedFails": 1000, # Allow 1000 BadRequestErrors before cooling down a deployment + "AuthenticationErrorAllowedFails": 10, # int + "TimeoutErrorAllowedFails": 12, # int + "RateLimitErrorAllowedFails": 10000, # int + "ContentPolicyViolationErrorAllowedFails": 15, # int + "InternalServerErrorAllowedFails": 20, # int + } + content_policy_fallbacks=[{"claude-2": ["my-fallback-model"]}] # List[Dict[str, List[str]]]: Fallback model for content policy violations + fallbacks=[{"claude-2": ["my-fallback-model"]}] # List[Dict[str, List[str]]]: Fallback model for all errors +``` + +| Name | Type | Description | +|------|------|-------------| +| routing_strategy | string | The strategy used for routing requests. Options: "simple-shuffle", "least-busy", "usage-based-routing", "latency-based-routing". Default is "simple-shuffle". [More information here](../routing) | +| redis_host | string | The host address for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them** | +| redis_password | string | The password for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them** | +| redis_port | string | The port number for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them**| +| enable_pre_call_check | boolean | If true, checks if a call is within the model's context window before making the call. [More information here](reliability) | +| content_policy_fallbacks | array of objects | Specifies fallback models for content policy violations. [More information here](reliability) | +| fallbacks | array of objects | Specifies fallback models for all types of errors. [More information here](reliability) | +| enable_tag_filtering | boolean | If true, uses tag based routing for requests [Tag Based Routing](tag_routing) | +| cooldown_time | integer | The duration (in seconds) to cooldown a model if it exceeds the allowed failures. | +| disable_cooldowns | boolean | If true, disables cooldowns for all models. [More information here](reliability) | +| retry_policy | object | Specifies the number of retries for different types of exceptions. [More information here](reliability) | +| allowed_fails | integer | The number of failures allowed before cooling down a model. [More information here](reliability) | +| allowed_fails_policy | object | Specifies the number of allowed failures for different error types before cooling down a deployment. [More information here](reliability) | + + +### environment variables - Reference + +| Name | Description | +|------|-------------| +| ACTIONS_ID_TOKEN_REQUEST_TOKEN | Token for requesting ID in GitHub Actions +| ACTIONS_ID_TOKEN_REQUEST_URL | URL for requesting ID token in GitHub Actions +| AISPEND_ACCOUNT_ID | Account ID for AI Spend +| AISPEND_API_KEY | API Key for AI Spend +| ALLOWED_EMAIL_DOMAINS | List of email domains allowed for access +| ARIZE_API_KEY | API key for Arize platform integration +| ARIZE_SPACE_KEY | Space key for Arize platform +| ARGILLA_BATCH_SIZE | Batch size for Argilla logging +| ARGILLA_API_KEY | API key for Argilla platform +| ARGILLA_SAMPLING_RATE | Sampling rate for Argilla logging +| ARGILLA_DATASET_NAME | Dataset name for Argilla logging +| ARGILLA_BASE_URL | Base URL for Argilla service +| ATHINA_API_KEY | API key for Athina service +| AUTH_STRATEGY | Strategy used for authentication (e.g., OAuth, API key) +| AWS_ACCESS_KEY_ID | Access Key ID for AWS services +| AWS_PROFILE_NAME | AWS CLI profile name to be used +| AWS_REGION_NAME | Default AWS region for service interactions +| AWS_ROLE_NAME | Role name for AWS IAM usage +| AWS_SECRET_ACCESS_KEY | Secret Access Key for AWS services +| AWS_SESSION_NAME | Name for AWS session +| AWS_WEB_IDENTITY_TOKEN | Web identity token for AWS +| AZURE_API_VERSION | Version of the Azure API being used +| AZURE_AUTHORITY_HOST | Azure authority host URL +| AZURE_CLIENT_ID | Client ID for Azure services +| AZURE_CLIENT_SECRET | Client secret for Azure services +| AZURE_FEDERATED_TOKEN_FILE | File path to Azure federated token +| AZURE_KEY_VAULT_URI | URI for Azure Key Vault +| AZURE_TENANT_ID | Tenant ID for Azure Active Directory +| BERRISPEND_ACCOUNT_ID | Account ID for BerriSpend service +| BRAINTRUST_API_KEY | API key for Braintrust integration +| CIRCLE_OIDC_TOKEN | OpenID Connect token for CircleCI +| CIRCLE_OIDC_TOKEN_V2 | Version 2 of the OpenID Connect token for CircleCI +| CONFIG_FILE_PATH | File path for configuration file +| CUSTOM_TIKTOKEN_CACHE_DIR | Custom directory for Tiktoken cache +| DATABASE_HOST | Hostname for the database server +| DATABASE_NAME | Name of the database +| DATABASE_PASSWORD | Password for the database user +| DATABASE_PORT | Port number for database connection +| DATABASE_SCHEMA | Schema name used in the database +| DATABASE_URL | Connection URL for the database +| DATABASE_USER | Username for database connection +| DATABASE_USERNAME | Alias for database user +| DATABRICKS_API_BASE | Base URL for Databricks API +| DD_BASE_URL | Base URL for Datadog integration +| DATADOG_BASE_URL | (Alternative to DD_BASE_URL) Base URL for Datadog integration +| _DATADOG_BASE_URL | (Alternative to DD_BASE_URL) Base URL for Datadog integration +| DD_API_KEY | API key for Datadog integration +| DD_SITE | Site URL for Datadog (e.g., datadoghq.com) +| DD_SOURCE | Source identifier for Datadog logs +| DD_ENV | Environment identifier for Datadog logs. Only supported for `datadog_llm_observability` callback +| DEBUG_OTEL | Enable debug mode for OpenTelemetry +| DIRECT_URL | Direct URL for service endpoint +| DISABLE_ADMIN_UI | Toggle to disable the admin UI +| DISABLE_SCHEMA_UPDATE | Toggle to disable schema updates +| DOCS_DESCRIPTION | Description text for documentation pages +| DOCS_FILTERED | Flag indicating filtered documentation +| DOCS_TITLE | Title of the documentation pages +| DOCS_URL | The path to the Swagger API documentation. **By default this is "/"** +| EMAIL_SUPPORT_CONTACT | Support contact email address +| GCS_BUCKET_NAME | Name of the Google Cloud Storage bucket +| GCS_PATH_SERVICE_ACCOUNT | Path to the Google Cloud service account JSON file +| GCS_FLUSH_INTERVAL | Flush interval for GCS logging (in seconds). Specify how often you want a log to be sent to GCS. **Default is 20 seconds** +| GCS_BATCH_SIZE | Batch size for GCS logging. Specify after how many logs you want to flush to GCS. If `BATCH_SIZE` is set to 10, logs are flushed every 10 logs. **Default is 2048** +| GENERIC_AUTHORIZATION_ENDPOINT | Authorization endpoint for generic OAuth providers +| GENERIC_CLIENT_ID | Client ID for generic OAuth providers +| GENERIC_CLIENT_SECRET | Client secret for generic OAuth providers +| GENERIC_CLIENT_STATE | State parameter for generic client authentication +| GENERIC_INCLUDE_CLIENT_ID | Include client ID in requests for OAuth +| GENERIC_SCOPE | Scope settings for generic OAuth providers +| GENERIC_TOKEN_ENDPOINT | Token endpoint for generic OAuth providers +| GENERIC_USER_DISPLAY_NAME_ATTRIBUTE | Attribute for user's display name in generic auth +| GENERIC_USER_EMAIL_ATTRIBUTE | Attribute for user's email in generic auth +| GENERIC_USER_FIRST_NAME_ATTRIBUTE | Attribute for user's first name in generic auth +| GENERIC_USER_ID_ATTRIBUTE | Attribute for user ID in generic auth +| GENERIC_USER_LAST_NAME_ATTRIBUTE | Attribute for user's last name in generic auth +| GENERIC_USER_PROVIDER_ATTRIBUTE | Attribute specifying the user's provider +| GENERIC_USER_ROLE_ATTRIBUTE | Attribute specifying the user's role +| GENERIC_USERINFO_ENDPOINT | Endpoint to fetch user information in generic OAuth +| GALILEO_BASE_URL | Base URL for Galileo platform +| GALILEO_PASSWORD | Password for Galileo authentication +| GALILEO_PROJECT_ID | Project ID for Galileo usage +| GALILEO_USERNAME | Username for Galileo authentication +| GREENSCALE_API_KEY | API key for Greenscale service +| GREENSCALE_ENDPOINT | Endpoint URL for Greenscale service +| GOOGLE_APPLICATION_CREDENTIALS | Path to Google Cloud credentials JSON file +| GOOGLE_CLIENT_ID | Client ID for Google OAuth +| GOOGLE_CLIENT_SECRET | Client secret for Google OAuth +| GOOGLE_KMS_RESOURCE_NAME | Name of the resource in Google KMS +| HF_API_BASE | Base URL for Hugging Face API +| HELICONE_API_KEY | API key for Helicone service +| HUGGINGFACE_API_BASE | Base URL for Hugging Face API +| IAM_TOKEN_DB_AUTH | IAM token for database authentication +| JSON_LOGS | Enable JSON formatted logging +| JWT_AUDIENCE | Expected audience for JWT tokens +| JWT_PUBLIC_KEY_URL | URL to fetch public key for JWT verification +| LAGO_API_BASE | Base URL for Lago API +| LAGO_API_CHARGE_BY | Parameter to determine charge basis in Lago +| LAGO_API_EVENT_CODE | Event code for Lago API events +| LAGO_API_KEY | API key for accessing Lago services +| LANGFUSE_DEBUG | Toggle debug mode for Langfuse +| LANGFUSE_FLUSH_INTERVAL | Interval for flushing Langfuse logs +| LANGFUSE_HOST | Host URL for Langfuse service +| LANGFUSE_PUBLIC_KEY | Public key for Langfuse authentication +| LANGFUSE_RELEASE | Release version of Langfuse integration +| LANGFUSE_SECRET_KEY | Secret key for Langfuse authentication +| LANGSMITH_API_KEY | API key for Langsmith platform +| LANGSMITH_BASE_URL | Base URL for Langsmith service +| LANGSMITH_BATCH_SIZE | Batch size for operations in Langsmith +| LANGSMITH_DEFAULT_RUN_NAME | Default name for Langsmith run +| LANGSMITH_PROJECT | Project name for Langsmith integration +| LANGSMITH_SAMPLING_RATE | Sampling rate for Langsmith logging +| LANGTRACE_API_KEY | API key for Langtrace service +| LITERAL_API_KEY | API key for Literal integration +| LITERAL_API_URL | API URL for Literal service +| LITERAL_BATCH_SIZE | Batch size for Literal operations +| LITELLM_DONT_SHOW_FEEDBACK_BOX | Flag to hide feedback box in LiteLLM UI +| LITELLM_DROP_PARAMS | Parameters to drop in LiteLLM requests +| LITELLM_EMAIL | Email associated with LiteLLM account +| LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRIES | Maximum retries for parallel requests in LiteLLM +| LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRY_TIMEOUT | Timeout for retries of parallel requests in LiteLLM +| LITELLM_HOSTED_UI | URL of the hosted UI for LiteLLM +| LITELLM_LICENSE | License key for LiteLLM usage +| LITELLM_LOCAL_MODEL_COST_MAP | Local configuration for model cost mapping in LiteLLM +| LITELLM_LOG | Enable detailed logging for LiteLLM +| LITELLM_MODE | Operating mode for LiteLLM (e.g., production, development) +| LITELLM_SALT_KEY | Salt key for encryption in LiteLLM +| LITELLM_SECRET_AWS_KMS_LITELLM_LICENSE | AWS KMS encrypted license for LiteLLM +| LITELLM_TOKEN | Access token for LiteLLM integration +| LOGFIRE_TOKEN | Token for Logfire logging service +| MICROSOFT_CLIENT_ID | Client ID for Microsoft services +| MICROSOFT_CLIENT_SECRET | Client secret for Microsoft services +| MICROSOFT_TENANT | Tenant ID for Microsoft Azure +| NO_DOCS | Flag to disable documentation generation +| NO_PROXY | List of addresses to bypass proxy +| OAUTH_TOKEN_INFO_ENDPOINT | Endpoint for OAuth token info retrieval +| OPENAI_API_BASE | Base URL for OpenAI API +| OPENAI_API_KEY | API key for OpenAI services +| OPENAI_ORGANIZATION | Organization identifier for OpenAI +| OPENID_BASE_URL | Base URL for OpenID Connect services +| OPENID_CLIENT_ID | Client ID for OpenID Connect authentication +| OPENID_CLIENT_SECRET | Client secret for OpenID Connect authentication +| OPENMETER_API_ENDPOINT | API endpoint for OpenMeter integration +| OPENMETER_API_KEY | API key for OpenMeter services +| OPENMETER_EVENT_TYPE | Type of events sent to OpenMeter +| OTEL_ENDPOINT | OpenTelemetry endpoint for traces +| OTEL_ENVIRONMENT_NAME | Environment name for OpenTelemetry +| OTEL_EXPORTER | Exporter type for OpenTelemetry +| OTEL_HEADERS | Headers for OpenTelemetry requests +| OTEL_SERVICE_NAME | Service name identifier for OpenTelemetry +| OTEL_TRACER_NAME | Tracer name for OpenTelemetry tracing +| PREDIBASE_API_BASE | Base URL for Predibase API +| PRESIDIO_ANALYZER_API_BASE | Base URL for Presidio Analyzer service +| PRESIDIO_ANONYMIZER_API_BASE | Base URL for Presidio Anonymizer service +| PROMETHEUS_URL | URL for Prometheus service +| PROMPTLAYER_API_KEY | API key for PromptLayer integration +| PROXY_ADMIN_ID | Admin identifier for proxy server +| PROXY_BASE_URL | Base URL for proxy service +| PROXY_LOGOUT_URL | URL for logging out of the proxy service +| PROXY_MASTER_KEY | Master key for proxy authentication +| QDRANT_API_BASE | Base URL for Qdrant API +| QDRANT_API_KEY | API key for Qdrant service +| QDRANT_URL | Connection URL for Qdrant database +| REDIS_HOST | Hostname for Redis server +| REDIS_PASSWORD | Password for Redis service +| REDIS_PORT | Port number for Redis server +| REDOC_URL | The path to the Redoc Fast API documentation. **By default this is "/redoc"** +| SERVER_ROOT_PATH | Root path for the server application +| SET_VERBOSE | Flag to enable verbose logging +| SLACK_DAILY_REPORT_FREQUENCY | Frequency of daily Slack reports (e.g., daily, weekly) +| SLACK_WEBHOOK_URL | Webhook URL for Slack integration +| SMTP_HOST | Hostname for the SMTP server +| SMTP_PASSWORD | Password for SMTP authentication +| SMTP_PORT | Port number for SMTP server +| SMTP_SENDER_EMAIL | Email address used as the sender in SMTP transactions +| SMTP_SENDER_LOGO | Logo used in emails sent via SMTP +| SMTP_TLS | Flag to enable or disable TLS for SMTP connections +| SMTP_USERNAME | Username for SMTP authentication +| SPEND_LOGS_URL | URL for retrieving spend logs +| SSL_CERTIFICATE | Path to the SSL certificate file +| SSL_VERIFY | Flag to enable or disable SSL certificate verification +| SUPABASE_KEY | API key for Supabase service +| SUPABASE_URL | Base URL for Supabase instance +| TEST_EMAIL_ADDRESS | Email address used for testing purposes +| UI_LOGO_PATH | Path to the logo image used in the UI +| UI_PASSWORD | Password for accessing the UI +| UI_USERNAME | Username for accessing the UI +| UPSTREAM_LANGFUSE_DEBUG | Flag to enable debugging for upstream Langfuse +| UPSTREAM_LANGFUSE_HOST | Host URL for upstream Langfuse service +| UPSTREAM_LANGFUSE_PUBLIC_KEY | Public key for upstream Langfuse authentication +| UPSTREAM_LANGFUSE_RELEASE | Release version identifier for upstream Langfuse +| UPSTREAM_LANGFUSE_SECRET_KEY | Secret key for upstream Langfuse authentication +| USE_AWS_KMS | Flag to enable AWS Key Management Service for encryption +| WEBHOOK_URL | URL for receiving webhooks from external services + diff --git a/docs/my-website/docs/proxy/configs.md b/docs/my-website/docs/proxy/configs.md index df22a29e3..4bd4d2666 100644 --- a/docs/my-website/docs/proxy/configs.md +++ b/docs/my-website/docs/proxy/configs.md @@ -597,481 +597,6 @@ general_settings: database_connection_timeout: 60 # sets a 60s timeout for any connection call to the db ``` -## **All settings** - - -```yaml -environment_variables: {} - -model_list: - - model_name: string - litellm_params: {} - model_info: - id: string - mode: embedding - input_cost_per_token: 0 - output_cost_per_token: 0 - max_tokens: 2048 - base_model: gpt-4-1106-preview - additionalProp1: {} - -litellm_settings: - # Logging/Callback settings - success_callback: ["langfuse"] # list of success callbacks - failure_callback: ["sentry"] # list of failure callbacks - callbacks: ["otel"] # list of callbacks - runs on success and failure - service_callbacks: ["datadog", "prometheus"] # logs redis, postgres failures on datadog, prometheus - turn_off_message_logging: boolean # prevent the messages and responses from being logged to on your callbacks, but request metadata will still be logged. - redact_user_api_key_info: boolean # Redact information about the user api key (hashed token, user_id, team id, etc.), from logs. Currently supported for Langfuse, OpenTelemetry, Logfire, ArizeAI logging. - langfuse_default_tags: ["cache_hit", "cache_key", "proxy_base_url", "user_api_key_alias", "user_api_key_user_id", "user_api_key_user_email", "user_api_key_team_alias", "semantic-similarity", "proxy_base_url"] # default tags for Langfuse Logging - - # Networking settings - request_timeout: 10 # (int) llm requesttimeout in seconds. Raise Timeout error if call takes longer than 10s. Sets litellm.request_timeout - force_ipv4: boolean # If true, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6 + Anthropic API - - set_verbose: boolean # sets litellm.set_verbose=True to view verbose debug logs. DO NOT LEAVE THIS ON IN PRODUCTION - json_logs: boolean # if true, logs will be in json format - - # Fallbacks, reliability - default_fallbacks: ["claude-opus"] # set default_fallbacks, in case a specific model group is misconfigured / bad. - content_policy_fallbacks: [{"gpt-3.5-turbo-small": ["claude-opus"]}] # fallbacks for ContentPolicyErrors - context_window_fallbacks: [{"gpt-3.5-turbo-small": ["gpt-3.5-turbo-large", "claude-opus"]}] # fallbacks for ContextWindowExceededErrors - - - - # Caching settings - cache: true - cache_params: # set cache params for redis - type: redis # type of cache to initialize - - # Optional - Redis Settings - host: "localhost" # The host address for the Redis cache. Required if type is "redis". - port: 6379 # The port number for the Redis cache. Required if type is "redis". - password: "your_password" # The password for the Redis cache. Required if type is "redis". - namespace: "litellm.caching.caching" # namespace for redis cache - - # Optional - Redis Cluster Settings - redis_startup_nodes: [{"host": "127.0.0.1", "port": "7001"}] - - # Optional - Redis Sentinel Settings - service_name: "mymaster" - sentinel_nodes: [["localhost", 26379]] - - # Optional - Qdrant Semantic Cache Settings - qdrant_semantic_cache_embedding_model: openai-embedding # the model should be defined on the model_list - qdrant_collection_name: test_collection - qdrant_quantization_config: binary - similarity_threshold: 0.8 # similarity threshold for semantic cache - - # Optional - S3 Cache Settings - s3_bucket_name: cache-bucket-litellm # AWS Bucket Name for S3 - s3_region_name: us-west-2 # AWS Region Name for S3 - s3_aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID # us os.environ/ to pass environment variables. This is AWS Access Key ID for S3 - s3_aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY # AWS Secret Access Key for S3 - s3_endpoint_url: https://s3.amazonaws.com # [OPTIONAL] S3 endpoint URL, if you want to use Backblaze/cloudflare s3 bucket - - # Common Cache settings - # Optional - Supported call types for caching - supported_call_types: ["acompletion", "atext_completion", "aembedding", "atranscription"] - # /chat/completions, /completions, /embeddings, /audio/transcriptions - mode: default_off # if default_off, you need to opt in to caching on a per call basis - ttl: 600 # ttl for caching - - -callback_settings: - otel: - message_logging: boolean # OTEL logging callback specific settings - -general_settings: - completion_model: string - disable_spend_logs: boolean # turn off writing each transaction to the db - disable_master_key_return: boolean # turn off returning master key on UI (checked on '/user/info' endpoint) - disable_retry_on_max_parallel_request_limit_error: boolean # turn off retries when max parallel request limit is reached - disable_reset_budget: boolean # turn off reset budget scheduled task - disable_adding_master_key_hash_to_db: boolean # turn off storing master key hash in db, for spend tracking - enable_jwt_auth: boolean # allow proxy admin to auth in via jwt tokens with 'litellm_proxy_admin' in claims - enforce_user_param: boolean # requires all openai endpoint requests to have a 'user' param - allowed_routes: ["route1", "route2"] # list of allowed proxy API routes - a user can access. (currently JWT-Auth only) - key_management_system: google_kms # either google_kms or azure_kms - master_key: string - - # Database Settings - database_url: string - database_connection_pool_limit: 0 # default 100 - database_connection_timeout: 0 # default 60s - allow_requests_on_db_unavailable: boolean # if true, will allow requests that can not connect to the DB to verify Virtual Key to still work - - custom_auth: string - max_parallel_requests: 0 # the max parallel requests allowed per deployment - global_max_parallel_requests: 0 # the max parallel requests allowed on the proxy all up - infer_model_from_keys: true - background_health_checks: true - health_check_interval: 300 - alerting: ["slack", "email"] - alerting_threshold: 0 - use_client_credentials_pass_through_routes: boolean # use client credentials for all pass through routes like "/vertex-ai", /bedrock/. When this is True Virtual Key auth will not be applied on these endpoints -``` - -### litellm_settings - Reference - -| Name | Type | Description | -|------|------|-------------| -| success_callback | array of strings | List of success callbacks. [Doc Proxy logging callbacks](logging), [Doc Metrics](prometheus) | -| failure_callback | array of strings | List of failure callbacks [Doc Proxy logging callbacks](logging), [Doc Metrics](prometheus) | -| callbacks | array of strings | List of callbacks - runs on success and failure [Doc Proxy logging callbacks](logging), [Doc Metrics](prometheus) | -| service_callbacks | array of strings | System health monitoring - Logs redis, postgres failures on specified services (e.g. datadog, prometheus) [Doc Metrics](prometheus) | -| turn_off_message_logging | boolean | If true, prevents messages and responses from being logged to callbacks, but request metadata will still be logged [Proxy Logging](logging) | -| modify_params | boolean | If true, allows modifying the parameters of the request before it is sent to the LLM provider | -| enable_preview_features | boolean | If true, enables preview features - e.g. Azure O1 Models with streaming support.| -| redact_user_api_key_info | boolean | If true, redacts information about the user api key from logs [Proxy Logging](logging#redacting-userapikeyinfo) | -| langfuse_default_tags | array of strings | Default tags for Langfuse Logging. Use this if you want to control which LiteLLM-specific fields are logged as tags by the LiteLLM proxy. By default LiteLLM Proxy logs no LiteLLM-specific fields as tags. [Further docs](./logging#litellm-specific-tags-on-langfuse---cache_hit-cache_key) | -| set_verbose | boolean | If true, sets litellm.set_verbose=True to view verbose debug logs. DO NOT LEAVE THIS ON IN PRODUCTION | -| json_logs | boolean | If true, logs will be in json format. If you need to store the logs as JSON, just set the `litellm.json_logs = True`. We currently just log the raw POST request from litellm as a JSON [Further docs](./debugging) | -| default_fallbacks | array of strings | List of fallback models to use if a specific model group is misconfigured / bad. [Further docs](./reliability#default-fallbacks) | -| request_timeout | integer | The timeout for requests in seconds. If not set, the default value is `6000 seconds`. [For reference OpenAI Python SDK defaults to `600 seconds`.](https://github.com/openai/openai-python/blob/main/src/openai/_constants.py) | -| force_ipv4 | boolean | If true, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6 + Anthropic API | -| content_policy_fallbacks | array of objects | Fallbacks to use when a ContentPolicyViolationError is encountered. [Further docs](./reliability#content-policy-fallbacks) | -| context_window_fallbacks | array of objects | Fallbacks to use when a ContextWindowExceededError is encountered. [Further docs](./reliability#context-window-fallbacks) | -| cache | boolean | If true, enables caching. [Further docs](./caching) | -| cache_params | object | Parameters for the cache. [Further docs](./caching) | -| cache_params.type | string | The type of cache to initialize. Can be one of ["local", "redis", "redis-semantic", "s3", "disk", "qdrant-semantic"]. Defaults to "redis". [Furher docs](./caching) | -| cache_params.host | string | The host address for the Redis cache. Required if type is "redis". | -| cache_params.port | integer | The port number for the Redis cache. Required if type is "redis". | -| cache_params.password | string | The password for the Redis cache. Required if type is "redis". | -| cache_params.namespace | string | The namespace for the Redis cache. | -| cache_params.redis_startup_nodes | array of objects | Redis Cluster Settings. [Further docs](./caching) | -| cache_params.service_name | string | Redis Sentinel Settings. [Further docs](./caching) | -| cache_params.sentinel_nodes | array of arrays | Redis Sentinel Settings. [Further docs](./caching) | -| cache_params.ttl | integer | The time (in seconds) to store entries in cache. | -| cache_params.qdrant_semantic_cache_embedding_model | string | The embedding model to use for qdrant semantic cache. | -| cache_params.qdrant_collection_name | string | The name of the collection to use for qdrant semantic cache. | -| cache_params.qdrant_quantization_config | string | The quantization configuration for the qdrant semantic cache. | -| cache_params.similarity_threshold | float | The similarity threshold for the semantic cache. | -| cache_params.s3_bucket_name | string | The name of the S3 bucket to use for the semantic cache. | -| cache_params.s3_region_name | string | The region name for the S3 bucket. | -| cache_params.s3_aws_access_key_id | string | The AWS access key ID for the S3 bucket. | -| cache_params.s3_aws_secret_access_key | string | The AWS secret access key for the S3 bucket. | -| cache_params.s3_endpoint_url | string | Optional - The endpoint URL for the S3 bucket. | -| cache_params.supported_call_types | array of strings | The types of calls to cache. [Further docs](./caching) | -| cache_params.mode | string | The mode of the cache. [Further docs](./caching) | -| disable_end_user_cost_tracking | boolean | If true, turns off end user cost tracking on prometheus metrics + litellm spend logs table on proxy. | -| key_generation_settings | object | Restricts who can generate keys. [Further docs](./virtual_keys.md#restricting-key-generation) | - -### general_settings - Reference - -| Name | Type | Description | -|------|------|-------------| -| completion_model | string | The default model to use for completions when `model` is not specified in the request | -| disable_spend_logs | boolean | If true, turns off writing each transaction to the database | -| disable_master_key_return | boolean | If true, turns off returning master key on UI. (checked on '/user/info' endpoint) | -| disable_retry_on_max_parallel_request_limit_error | boolean | If true, turns off retries when max parallel request limit is reached | -| disable_reset_budget | boolean | If true, turns off reset budget scheduled task | -| disable_adding_master_key_hash_to_db | boolean | If true, turns off storing master key hash in db | -| enable_jwt_auth | boolean | allow proxy admin to auth in via jwt tokens with 'litellm_proxy_admin' in claims. [Doc on JWT Tokens](token_auth) | -| enforce_user_param | boolean | If true, requires all OpenAI endpoint requests to have a 'user' param. [Doc on call hooks](call_hooks)| -| allowed_routes | array of strings | List of allowed proxy API routes a user can access [Doc on controlling allowed routes](enterprise#control-available-public-private-routes)| -| key_management_system | string | Specifies the key management system. [Doc Secret Managers](../secret) | -| master_key | string | The master key for the proxy [Set up Virtual Keys](virtual_keys) | -| database_url | string | The URL for the database connection [Set up Virtual Keys](virtual_keys) | -| database_connection_pool_limit | integer | The limit for database connection pool [Setting DB Connection Pool limit](#configure-db-pool-limits--connection-timeouts) | -| database_connection_timeout | integer | The timeout for database connections in seconds [Setting DB Connection Pool limit, timeout](#configure-db-pool-limits--connection-timeouts) | -| allow_requests_on_db_unavailable | boolean | If true, allows requests to succeed even if DB is unreachable. **Only use this if running LiteLLM in your VPC** This will allow requests to work even when LiteLLM cannot connect to the DB to verify a Virtual Key | -| custom_auth | string | Write your own custom authentication logic [Doc Custom Auth](virtual_keys#custom-auth) | -| max_parallel_requests | integer | The max parallel requests allowed per deployment | -| global_max_parallel_requests | integer | The max parallel requests allowed on the proxy overall | -| infer_model_from_keys | boolean | If true, infers the model from the provided keys | -| background_health_checks | boolean | If true, enables background health checks. [Doc on health checks](health) | -| health_check_interval | integer | The interval for health checks in seconds [Doc on health checks](health) | -| alerting | array of strings | List of alerting methods [Doc on Slack Alerting](alerting) | -| alerting_threshold | integer | The threshold for triggering alerts [Doc on Slack Alerting](alerting) | -| use_client_credentials_pass_through_routes | boolean | If true, uses client credentials for all pass-through routes. [Doc on pass through routes](pass_through) | -| health_check_details | boolean | If false, hides health check details (e.g. remaining rate limit). [Doc on health checks](health) | -| public_routes | List[str] | (Enterprise Feature) Control list of public routes | -| alert_types | List[str] | Control list of alert types to send to slack (Doc on alert types)[./alerting.md] | -| enforced_params | List[str] | (Enterprise Feature) List of params that must be included in all requests to the proxy | -| enable_oauth2_auth | boolean | (Enterprise Feature) If true, enables oauth2.0 authentication | -| use_x_forwarded_for | str | If true, uses the X-Forwarded-For header to get the client IP address | -| service_account_settings | List[Dict[str, Any]] | Set `service_account_settings` if you want to create settings that only apply to service account keys (Doc on service accounts)[./service_accounts.md] | -| image_generation_model | str | The default model to use for image generation - ignores model set in request | -| store_model_in_db | boolean | If true, allows `/model/new` endpoint to store model information in db. Endpoint disabled by default. [Doc on `/model/new` endpoint](./model_management.md#create-a-new-model) | -| max_request_size_mb | int | The maximum size for requests in MB. Requests above this size will be rejected. | -| max_response_size_mb | int | The maximum size for responses in MB. LLM Responses above this size will not be sent. | -| proxy_budget_rescheduler_min_time | int | The minimum time (in seconds) to wait before checking db for budget resets. **Default is 597 seconds** | -| proxy_budget_rescheduler_max_time | int | The maximum time (in seconds) to wait before checking db for budget resets. **Default is 605 seconds** | -| proxy_batch_write_at | int | Time (in seconds) to wait before batch writing spend logs to the db. **Default is 10 seconds** | -| alerting_args | dict | Args for Slack Alerting [Doc on Slack Alerting](./alerting.md) | -| custom_key_generate | str | Custom function for key generation [Doc on custom key generation](./virtual_keys.md#custom--key-generate) | -| allowed_ips | List[str] | List of IPs allowed to access the proxy. If not set, all IPs are allowed. | -| embedding_model | str | The default model to use for embeddings - ignores model set in request | -| default_team_disabled | boolean | If true, users cannot create 'personal' keys (keys with no team_id). | -| alert_to_webhook_url | Dict[str] | [Specify a webhook url for each alert type.](./alerting.md#set-specific-slack-channels-per-alert-type) | -| key_management_settings | List[Dict[str, Any]] | Settings for key management system (e.g. AWS KMS, Azure Key Vault) [Doc on key management](../secret.md) | -| allow_user_auth | boolean | (Deprecated) old approach for user authentication. | -| user_api_key_cache_ttl | int | The time (in seconds) to cache user api keys in memory. | -| disable_prisma_schema_update | boolean | If true, turns off automatic schema updates to DB | -| litellm_key_header_name | str | If set, allows passing LiteLLM keys as a custom header. [Doc on custom headers](./virtual_keys.md#custom-headers) | -| moderation_model | str | The default model to use for moderation. | -| custom_sso | str | Path to a python file that implements custom SSO logic. [Doc on custom SSO](./custom_sso.md) | -| allow_client_side_credentials | boolean | If true, allows passing client side credentials to the proxy. (Useful when testing finetuning models) [Doc on client side credentials](./virtual_keys.md#client-side-credentials) | -| admin_only_routes | List[str] | (Enterprise Feature) List of routes that are only accessible to admin users. [Doc on admin only routes](./enterprise#control-available-public-private-routes) | -| use_azure_key_vault | boolean | If true, load keys from azure key vault | -| use_google_kms | boolean | If true, load keys from google kms | -| spend_report_frequency | str | Specify how often you want a Spend Report to be sent (e.g. "1d", "2d", "30d") [More on this](./alerting.md#spend-report-frequency) | -| ui_access_mode | Literal["admin_only"] | If set, restricts access to the UI to admin users only. [Docs](./ui.md#restrict-ui-access) | -| litellm_jwtauth | Dict[str, Any] | Settings for JWT authentication. [Docs](./token_auth.md) | -| litellm_license | str | The license key for the proxy. [Docs](../enterprise.md#how-does-deployment-with-enterprise-license-work) | -| oauth2_config_mappings | Dict[str, str] | Define the OAuth2 config mappings | -| pass_through_endpoints | List[Dict[str, Any]] | Define the pass through endpoints. [Docs](./pass_through) | -| enable_oauth2_proxy_auth | boolean | (Enterprise Feature) If true, enables oauth2.0 authentication | -| forward_openai_org_id | boolean | If true, forwards the OpenAI Organization ID to the backend LLM call (if it's OpenAI). | -| forward_client_headers_to_llm_api | boolean | If true, forwards the client headers (any `x-` headers) to the backend LLM call | - -### router_settings - Reference - -```yaml -router_settings: - routing_strategy: usage-based-routing-v2 # Literal["simple-shuffle", "least-busy", "usage-based-routing","latency-based-routing"], default="simple-shuffle" - redis_host: # string - redis_password: # string - redis_port: # string - enable_pre_call_check: true # bool - Before call is made check if a call is within model context window - allowed_fails: 3 # cooldown model if it fails > 1 call in a minute. - cooldown_time: 30 # (in seconds) how long to cooldown model if fails/min > allowed_fails - disable_cooldowns: True # bool - Disable cooldowns for all models - enable_tag_filtering: True # bool - Use tag based routing for requests - retry_policy: { # Dict[str, int]: retry policy for different types of exceptions - "AuthenticationErrorRetries": 3, - "TimeoutErrorRetries": 3, - "RateLimitErrorRetries": 3, - "ContentPolicyViolationErrorRetries": 4, - "InternalServerErrorRetries": 4 - } - allowed_fails_policy: { - "BadRequestErrorAllowedFails": 1000, # Allow 1000 BadRequestErrors before cooling down a deployment - "AuthenticationErrorAllowedFails": 10, # int - "TimeoutErrorAllowedFails": 12, # int - "RateLimitErrorAllowedFails": 10000, # int - "ContentPolicyViolationErrorAllowedFails": 15, # int - "InternalServerErrorAllowedFails": 20, # int - } - content_policy_fallbacks=[{"claude-2": ["my-fallback-model"]}] # List[Dict[str, List[str]]]: Fallback model for content policy violations - fallbacks=[{"claude-2": ["my-fallback-model"]}] # List[Dict[str, List[str]]]: Fallback model for all errors -``` - -| Name | Type | Description | -|------|------|-------------| -| routing_strategy | string | The strategy used for routing requests. Options: "simple-shuffle", "least-busy", "usage-based-routing", "latency-based-routing". Default is "simple-shuffle". [More information here](../routing) | -| redis_host | string | The host address for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them** | -| redis_password | string | The password for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them** | -| redis_port | string | The port number for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them**| -| enable_pre_call_check | boolean | If true, checks if a call is within the model's context window before making the call. [More information here](reliability) | -| content_policy_fallbacks | array of objects | Specifies fallback models for content policy violations. [More information here](reliability) | -| fallbacks | array of objects | Specifies fallback models for all types of errors. [More information here](reliability) | -| enable_tag_filtering | boolean | If true, uses tag based routing for requests [Tag Based Routing](tag_routing) | -| cooldown_time | integer | The duration (in seconds) to cooldown a model if it exceeds the allowed failures. | -| disable_cooldowns | boolean | If true, disables cooldowns for all models. [More information here](reliability) | -| retry_policy | object | Specifies the number of retries for different types of exceptions. [More information here](reliability) | -| allowed_fails | integer | The number of failures allowed before cooling down a model. [More information here](reliability) | -| allowed_fails_policy | object | Specifies the number of allowed failures for different error types before cooling down a deployment. [More information here](reliability) | - - -### environment variables - Reference - -| Name | Description | -|------|-------------| -| ACTIONS_ID_TOKEN_REQUEST_TOKEN | Token for requesting ID in GitHub Actions -| ACTIONS_ID_TOKEN_REQUEST_URL | URL for requesting ID token in GitHub Actions -| AISPEND_ACCOUNT_ID | Account ID for AI Spend -| AISPEND_API_KEY | API Key for AI Spend -| ALLOWED_EMAIL_DOMAINS | List of email domains allowed for access -| ARIZE_API_KEY | API key for Arize platform integration -| ARIZE_SPACE_KEY | Space key for Arize platform -| ARGILLA_BATCH_SIZE | Batch size for Argilla logging -| ARGILLA_API_KEY | API key for Argilla platform -| ARGILLA_SAMPLING_RATE | Sampling rate for Argilla logging -| ARGILLA_DATASET_NAME | Dataset name for Argilla logging -| ARGILLA_BASE_URL | Base URL for Argilla service -| ATHINA_API_KEY | API key for Athina service -| AUTH_STRATEGY | Strategy used for authentication (e.g., OAuth, API key) -| AWS_ACCESS_KEY_ID | Access Key ID for AWS services -| AWS_PROFILE_NAME | AWS CLI profile name to be used -| AWS_REGION_NAME | Default AWS region for service interactions -| AWS_ROLE_NAME | Role name for AWS IAM usage -| AWS_SECRET_ACCESS_KEY | Secret Access Key for AWS services -| AWS_SESSION_NAME | Name for AWS session -| AWS_WEB_IDENTITY_TOKEN | Web identity token for AWS -| AZURE_API_VERSION | Version of the Azure API being used -| AZURE_AUTHORITY_HOST | Azure authority host URL -| AZURE_CLIENT_ID | Client ID for Azure services -| AZURE_CLIENT_SECRET | Client secret for Azure services -| AZURE_FEDERATED_TOKEN_FILE | File path to Azure federated token -| AZURE_KEY_VAULT_URI | URI for Azure Key Vault -| AZURE_TENANT_ID | Tenant ID for Azure Active Directory -| BERRISPEND_ACCOUNT_ID | Account ID for BerriSpend service -| BRAINTRUST_API_KEY | API key for Braintrust integration -| CIRCLE_OIDC_TOKEN | OpenID Connect token for CircleCI -| CIRCLE_OIDC_TOKEN_V2 | Version 2 of the OpenID Connect token for CircleCI -| CONFIG_FILE_PATH | File path for configuration file -| CUSTOM_TIKTOKEN_CACHE_DIR | Custom directory for Tiktoken cache -| DATABASE_HOST | Hostname for the database server -| DATABASE_NAME | Name of the database -| DATABASE_PASSWORD | Password for the database user -| DATABASE_PORT | Port number for database connection -| DATABASE_SCHEMA | Schema name used in the database -| DATABASE_URL | Connection URL for the database -| DATABASE_USER | Username for database connection -| DATABASE_USERNAME | Alias for database user -| DATABRICKS_API_BASE | Base URL for Databricks API -| DD_BASE_URL | Base URL for Datadog integration -| DATADOG_BASE_URL | (Alternative to DD_BASE_URL) Base URL for Datadog integration -| _DATADOG_BASE_URL | (Alternative to DD_BASE_URL) Base URL for Datadog integration -| DD_API_KEY | API key for Datadog integration -| DD_SITE | Site URL for Datadog (e.g., datadoghq.com) -| DD_SOURCE | Source identifier for Datadog logs -| DD_ENV | Environment identifier for Datadog logs. Only supported for `datadog_llm_observability` callback -| DEBUG_OTEL | Enable debug mode for OpenTelemetry -| DIRECT_URL | Direct URL for service endpoint -| DISABLE_ADMIN_UI | Toggle to disable the admin UI -| DISABLE_SCHEMA_UPDATE | Toggle to disable schema updates -| DOCS_DESCRIPTION | Description text for documentation pages -| DOCS_FILTERED | Flag indicating filtered documentation -| DOCS_TITLE | Title of the documentation pages -| DOCS_URL | The path to the Swagger API documentation. **By default this is "/"** -| EMAIL_SUPPORT_CONTACT | Support contact email address -| GCS_BUCKET_NAME | Name of the Google Cloud Storage bucket -| GCS_PATH_SERVICE_ACCOUNT | Path to the Google Cloud service account JSON file -| GCS_FLUSH_INTERVAL | Flush interval for GCS logging (in seconds). Specify how often you want a log to be sent to GCS. **Default is 20 seconds** -| GCS_BATCH_SIZE | Batch size for GCS logging. Specify after how many logs you want to flush to GCS. If `BATCH_SIZE` is set to 10, logs are flushed every 10 logs. **Default is 2048** -| GENERIC_AUTHORIZATION_ENDPOINT | Authorization endpoint for generic OAuth providers -| GENERIC_CLIENT_ID | Client ID for generic OAuth providers -| GENERIC_CLIENT_SECRET | Client secret for generic OAuth providers -| GENERIC_CLIENT_STATE | State parameter for generic client authentication -| GENERIC_INCLUDE_CLIENT_ID | Include client ID in requests for OAuth -| GENERIC_SCOPE | Scope settings for generic OAuth providers -| GENERIC_TOKEN_ENDPOINT | Token endpoint for generic OAuth providers -| GENERIC_USER_DISPLAY_NAME_ATTRIBUTE | Attribute for user's display name in generic auth -| GENERIC_USER_EMAIL_ATTRIBUTE | Attribute for user's email in generic auth -| GENERIC_USER_FIRST_NAME_ATTRIBUTE | Attribute for user's first name in generic auth -| GENERIC_USER_ID_ATTRIBUTE | Attribute for user ID in generic auth -| GENERIC_USER_LAST_NAME_ATTRIBUTE | Attribute for user's last name in generic auth -| GENERIC_USER_PROVIDER_ATTRIBUTE | Attribute specifying the user's provider -| GENERIC_USER_ROLE_ATTRIBUTE | Attribute specifying the user's role -| GENERIC_USERINFO_ENDPOINT | Endpoint to fetch user information in generic OAuth -| GALILEO_BASE_URL | Base URL for Galileo platform -| GALILEO_PASSWORD | Password for Galileo authentication -| GALILEO_PROJECT_ID | Project ID for Galileo usage -| GALILEO_USERNAME | Username for Galileo authentication -| GREENSCALE_API_KEY | API key for Greenscale service -| GREENSCALE_ENDPOINT | Endpoint URL for Greenscale service -| GOOGLE_APPLICATION_CREDENTIALS | Path to Google Cloud credentials JSON file -| GOOGLE_CLIENT_ID | Client ID for Google OAuth -| GOOGLE_CLIENT_SECRET | Client secret for Google OAuth -| GOOGLE_KMS_RESOURCE_NAME | Name of the resource in Google KMS -| HF_API_BASE | Base URL for Hugging Face API -| HELICONE_API_KEY | API key for Helicone service -| HUGGINGFACE_API_BASE | Base URL for Hugging Face API -| IAM_TOKEN_DB_AUTH | IAM token for database authentication -| JSON_LOGS | Enable JSON formatted logging -| JWT_AUDIENCE | Expected audience for JWT tokens -| JWT_PUBLIC_KEY_URL | URL to fetch public key for JWT verification -| LAGO_API_BASE | Base URL for Lago API -| LAGO_API_CHARGE_BY | Parameter to determine charge basis in Lago -| LAGO_API_EVENT_CODE | Event code for Lago API events -| LAGO_API_KEY | API key for accessing Lago services -| LANGFUSE_DEBUG | Toggle debug mode for Langfuse -| LANGFUSE_FLUSH_INTERVAL | Interval for flushing Langfuse logs -| LANGFUSE_HOST | Host URL for Langfuse service -| LANGFUSE_PUBLIC_KEY | Public key for Langfuse authentication -| LANGFUSE_RELEASE | Release version of Langfuse integration -| LANGFUSE_SECRET_KEY | Secret key for Langfuse authentication -| LANGSMITH_API_KEY | API key for Langsmith platform -| LANGSMITH_BASE_URL | Base URL for Langsmith service -| LANGSMITH_BATCH_SIZE | Batch size for operations in Langsmith -| LANGSMITH_DEFAULT_RUN_NAME | Default name for Langsmith run -| LANGSMITH_PROJECT | Project name for Langsmith integration -| LANGSMITH_SAMPLING_RATE | Sampling rate for Langsmith logging -| LANGTRACE_API_KEY | API key for Langtrace service -| LITERAL_API_KEY | API key for Literal integration -| LITERAL_API_URL | API URL for Literal service -| LITERAL_BATCH_SIZE | Batch size for Literal operations -| LITELLM_DONT_SHOW_FEEDBACK_BOX | Flag to hide feedback box in LiteLLM UI -| LITELLM_DROP_PARAMS | Parameters to drop in LiteLLM requests -| LITELLM_EMAIL | Email associated with LiteLLM account -| LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRIES | Maximum retries for parallel requests in LiteLLM -| LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRY_TIMEOUT | Timeout for retries of parallel requests in LiteLLM -| LITELLM_HOSTED_UI | URL of the hosted UI for LiteLLM -| LITELLM_LICENSE | License key for LiteLLM usage -| LITELLM_LOCAL_MODEL_COST_MAP | Local configuration for model cost mapping in LiteLLM -| LITELLM_LOG | Enable detailed logging for LiteLLM -| LITELLM_MODE | Operating mode for LiteLLM (e.g., production, development) -| LITELLM_SALT_KEY | Salt key for encryption in LiteLLM -| LITELLM_SECRET_AWS_KMS_LITELLM_LICENSE | AWS KMS encrypted license for LiteLLM -| LITELLM_TOKEN | Access token for LiteLLM integration -| LOGFIRE_TOKEN | Token for Logfire logging service -| MICROSOFT_CLIENT_ID | Client ID for Microsoft services -| MICROSOFT_CLIENT_SECRET | Client secret for Microsoft services -| MICROSOFT_TENANT | Tenant ID for Microsoft Azure -| NO_DOCS | Flag to disable documentation generation -| NO_PROXY | List of addresses to bypass proxy -| OAUTH_TOKEN_INFO_ENDPOINT | Endpoint for OAuth token info retrieval -| OPENAI_API_BASE | Base URL for OpenAI API -| OPENAI_API_KEY | API key for OpenAI services -| OPENAI_ORGANIZATION | Organization identifier for OpenAI -| OPENID_BASE_URL | Base URL for OpenID Connect services -| OPENID_CLIENT_ID | Client ID for OpenID Connect authentication -| OPENID_CLIENT_SECRET | Client secret for OpenID Connect authentication -| OPENMETER_API_ENDPOINT | API endpoint for OpenMeter integration -| OPENMETER_API_KEY | API key for OpenMeter services -| OPENMETER_EVENT_TYPE | Type of events sent to OpenMeter -| OTEL_ENDPOINT | OpenTelemetry endpoint for traces -| OTEL_ENVIRONMENT_NAME | Environment name for OpenTelemetry -| OTEL_EXPORTER | Exporter type for OpenTelemetry -| OTEL_HEADERS | Headers for OpenTelemetry requests -| OTEL_SERVICE_NAME | Service name identifier for OpenTelemetry -| OTEL_TRACER_NAME | Tracer name for OpenTelemetry tracing -| PREDIBASE_API_BASE | Base URL for Predibase API -| PRESIDIO_ANALYZER_API_BASE | Base URL for Presidio Analyzer service -| PRESIDIO_ANONYMIZER_API_BASE | Base URL for Presidio Anonymizer service -| PROMETHEUS_URL | URL for Prometheus service -| PROMPTLAYER_API_KEY | API key for PromptLayer integration -| PROXY_ADMIN_ID | Admin identifier for proxy server -| PROXY_BASE_URL | Base URL for proxy service -| PROXY_LOGOUT_URL | URL for logging out of the proxy service -| PROXY_MASTER_KEY | Master key for proxy authentication -| QDRANT_API_BASE | Base URL for Qdrant API -| QDRANT_API_KEY | API key for Qdrant service -| QDRANT_URL | Connection URL for Qdrant database -| REDIS_HOST | Hostname for Redis server -| REDIS_PASSWORD | Password for Redis service -| REDIS_PORT | Port number for Redis server -| REDOC_URL | The path to the Redoc Fast API documentation. **By default this is "/redoc"** -| SERVER_ROOT_PATH | Root path for the server application -| SET_VERBOSE | Flag to enable verbose logging -| SLACK_DAILY_REPORT_FREQUENCY | Frequency of daily Slack reports (e.g., daily, weekly) -| SLACK_WEBHOOK_URL | Webhook URL for Slack integration -| SMTP_HOST | Hostname for the SMTP server -| SMTP_PASSWORD | Password for SMTP authentication -| SMTP_PORT | Port number for SMTP server -| SMTP_SENDER_EMAIL | Email address used as the sender in SMTP transactions -| SMTP_SENDER_LOGO | Logo used in emails sent via SMTP -| SMTP_TLS | Flag to enable or disable TLS for SMTP connections -| SMTP_USERNAME | Username for SMTP authentication -| SPEND_LOGS_URL | URL for retrieving spend logs -| SSL_CERTIFICATE | Path to the SSL certificate file -| SSL_VERIFY | Flag to enable or disable SSL certificate verification -| SUPABASE_KEY | API key for Supabase service -| SUPABASE_URL | Base URL for Supabase instance -| TEST_EMAIL_ADDRESS | Email address used for testing purposes -| UI_LOGO_PATH | Path to the logo image used in the UI -| UI_PASSWORD | Password for accessing the UI -| UI_USERNAME | Username for accessing the UI -| UPSTREAM_LANGFUSE_DEBUG | Flag to enable debugging for upstream Langfuse -| UPSTREAM_LANGFUSE_HOST | Host URL for upstream Langfuse service -| UPSTREAM_LANGFUSE_PUBLIC_KEY | Public key for upstream Langfuse authentication -| UPSTREAM_LANGFUSE_RELEASE | Release version identifier for upstream Langfuse -| UPSTREAM_LANGFUSE_SECRET_KEY | Secret key for upstream Langfuse authentication -| USE_AWS_KMS | Flag to enable AWS Key Management Service for encryption -| WEBHOOK_URL | URL for receiving webhooks from external services ## Extras diff --git a/docs/my-website/docs/router_architecture.md b/docs/my-website/docs/router_architecture.md new file mode 100644 index 000000000..13e9e411c --- /dev/null +++ b/docs/my-website/docs/router_architecture.md @@ -0,0 +1,24 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Router Architecture (Fallbacks / Retries) + +## High Level architecture + + + +### Request Flow + +1. **User Sends Request**: The process begins when a user sends a request to the LiteLLM Router endpoint. All unified endpoints (`.completion`, `.embeddings`, etc) are supported by LiteLLM Router. + +2. **function_with_fallbacks**: The initial request is sent to the `function_with_fallbacks` function. This function wraps the initial request in a try-except block, to handle any exceptions - doing fallbacks if needed. This request is then sent to the `function_with_retries` function. + + +3. **function_with_retries**: The `function_with_retries` function wraps the request in a try-except block and passes the initial request to a base litellm unified function (`litellm.completion`, `litellm.embeddings`, etc) to handle LLM API calling. `function_with_retries` handles any exceptions - doing retries on the model group if needed (i.e. if the request fails, it will retry on an available model within the model group). + +4. **litellm.completion**: The `litellm.completion` function is a base function that handles the LLM API calling. It is used by `function_with_retries` to make the actual request to the LLM API. + +## Legend + +**model_group**: A group of LLM API deployments that share the same `model_name`, are part of the same `model_group`, and can be load balanced across. \ No newline at end of file diff --git a/docs/my-website/img/router_architecture.png b/docs/my-website/img/router_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..195834185cb95a29c5a7e6314e14335e526cb7e0 GIT binary patch literal 60804 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 KF8swY>VE*)Chs%= literal 0 HcmV?d00001 diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js index cdcf3ba1b..879175db6 100644 --- a/docs/my-website/sidebars.js +++ b/docs/my-website/sidebars.js @@ -29,13 +29,17 @@ const sidebars = { }, items: [ "proxy/docker_quick_start", + { + "type": "category", + "label": "Config.yaml", + "items": ["proxy/configs", "proxy/config_settings"] + }, { type: "category", label: "Setup & Deployment", items: [ "proxy/deploy", "proxy/prod", - "proxy/configs", "proxy/cli", "proxy/model_management", "proxy/health", @@ -47,7 +51,7 @@ const sidebars = { { type: "category", label: "Architecture", - items: ["proxy/architecture", "proxy/db_info"], + items: ["proxy/architecture", "proxy/db_info", "router_architecture"], }, { type: "link",