跳至主要內容

自訂驗證

您現在可以覆寫預設的 api key 驗證。

使用自訂驗證的強制執行

預設情況下,自訂驗證只會強制執行您在回傳物件上設定的速率限制。預算與模型存取需要旗標。下表顯示每個控制項要在哪裡設定,以及需要哪些旗標。

會被強制執行的項目

目標設定位置需要的旗標
key / user / team / end-user 速率限制回傳物件(rpm_limitteam_tpm_limit、…)
每個模型的速率限制,key / team 範圍回傳物件上的 metadata / team_metadata
每個模型的速率限制,project 範圍project 記錄(model_tpm_limit / model_rpm_limitcustom_auth_run_common_checks
team / user / project 預算team / user / project 記錄custom_auth_run_common_checks
team / user / project 模型允許清單team / user / project 記錄custom_auth_run_common_checks
end-user 預算end-user 記錄custom_auth_run_common_checksenable_post_custom_auth_checks
key 模型允許清單(models回傳物件兩個旗標都要
key 每個模型的預算(model_max_budget回傳物件enable_post_custom_auth_checks
key 到期(expires回傳物件enable_post_custom_auth_checks
key 純量預算(max_budget / soft_budget不支援;請使用每個範圍的預算不適用

附註: project 的每個模型限制在關閉旗標時會放在物件的 project_metadata 上,但一旦旗標開啟,DB 的 project 記錄會覆寫它,所以請在那裡設定。(透過 team_metadata 的 team 每個模型設定則一律保留在物件上。)

請參閱 強制執行預算與模型存取key 層級強制執行 以查看範例。

使用方式

1. 建立自訂驗證檔案。

請確認回應型別符合 UserAPIKeyAuth pydantic 物件。這會用於記錄該使用者 key 的使用量。

from fastapi import Request
from litellm.proxy._types import UserAPIKeyAuth

async def user_api_key_auth(request: Request, api_key: str) -> UserAPIKeyAuth:
try:
modified_master_key = "sk-my-master-key"
if api_key == modified_master_key:
return UserAPIKeyAuth(api_key=api_key)
raise Exception
except:
raise Exception

2. 傳入檔案路徑(相對於 config.yaml)

將檔案路徑傳給 config.yaml

例如,如果兩者都在同一個目錄中 - ./config.yaml./custom_auth.py,會長這樣:

model_list: 
- model_name: "openai-model"
litellm_params:
model: "gpt-3.5-turbo"

litellm_settings:
drop_params: True
set_verbose: True

general_settings:
custom_auth: custom_auth.user_api_key_auth

實作程式碼

3. 啟動 proxy

$ litellm --config /path/to/config.yaml 

UserAPIKeyAuth 欄位參考

這些欄位會直接從回傳物件讀取,並在不需要旗標的情況下強制執行。預算與模型存取則會在旗標後方強制執行(見下方)。

身分

請求屬於誰。*_id 欄位也會告訴 LiteLLM 在 custom_auth_run_common_checks: true 時要載入哪些 DB 記錄。

UserAPIKeyAuth(
api_key: Optional[str] = None, # The API key (will be hashed automatically)
token: Optional[str] = None, # Hashed token for internal use
key_alias: Optional[str] = None, # Key alias for identification
user_id: Optional[str] = None, # User identifier (also used to load the user record)
user_email: Optional[str] = None, # User email address
user_role: Optional[LitellmUserRoles] = None, # User role (PROXY_ADMIN, INTERNAL_USER, etc.)
team_id: Optional[str] = None, # Team identifier (also used to load the team record)
org_id: Optional[str] = None, # Organization identifier (also used to load the org record)
end_user_id: Optional[str] = None, # End-user identifier (also used to load the end-user record)
)

速率限制

下方所有範圍都會直接從回傳物件強制執行,不需要旗標。

UserAPIKeyAuth(
# Key
tpm_limit: Optional[int] = None,
rpm_limit: Optional[int] = None,
# User
user_tpm_limit: Optional[int] = None,
user_rpm_limit: Optional[int] = None,
# Team
team_tpm_limit: Optional[int] = None,
team_rpm_limit: Optional[int] = None,
# Per team-member
team_member_tpm_limit: Optional[int] = None,
team_member_rpm_limit: Optional[int] = None,
# Per end-user
end_user_tpm_limit: Optional[int] = None,
end_user_rpm_limit: Optional[int] = None,
# Per-model (key / team scoped)
metadata: Dict = {}, # e.g. {"model_tpm_limit": {...}, "model_rpm_limit": {...}}
team_metadata: Optional[Dict] = None, # same keys, team scoped
)
備註

每個模型的速率限制是從 metadata(key)與 team_metadata(team)讀取,並以模型名稱作為索引。模型 key 必須與請求的 model 字串完全相同,否則會靜默略過該限制。

rpm_limit_per_model / tpm_limit_per_model 存在於物件上,但不會生效;請改用 metadata / team_metadata,或使用 project 記錄(見下方)。

進階

UserAPIKeyAuth(
max_parallel_requests: Optional[int] = None, # Concurrent request limit
allowed_model_region: Optional[AllowedModelRegion] = None, # Geographic restrictions
blocked: Optional[bool] = None, # Whether the key is blocked
config: Dict = {}, # Configuration settings
)

物件權限(MCP、agent 等)

from litellm.proxy._experimental.mcp_server.mcp_server_manager import (
global_mcp_server_manager,
)

def _server_id(name: str) -> str:
server = global_mcp_server_manager.get_mcp_server_by_name(name)
if not server:
raise ValueError(f"Unknown MCP server '{name}'")
return server.server_id

object_permission = LiteLLM_ObjectPermissionTable(
mcp_servers=[_server_id("deepwiki"), _server_id("everything")], # MCP servers this key is allowed to use
mcp_tool_permissions={"deepwiki": ["search", "read_doc"]}, # optional per-server tool allow-list
)

UserAPIKeyAuth(
object_permission=object_permission,
)

強制執行預算與模型存取

設定 custom_auth_run_common_checks: true 以在自訂驗證之外一併強制執行預算與模型存取:

general_settings:
custom_auth: custom_auth.user_api_key_auth
custom_auth_run_common_checks: true

您的處理常式會回傳這些 ID;預算與允許清單會存在對應的 DB 記錄(/team/new/user/new/project/new/customer/new,或 UI)上,LiteLLM 會載入並強制執行。

例如,一個具有預算與模型允許清單的 team:

curl -X POST 'http://0.0.0.0:4000/team/new' \
-H 'Authorization: Bearer sk-master-key' \
-H 'Content-Type: application/json' \
-d '{
"team_id": "eng-team",
"max_budget": 100,
"models": ["gpt-4o-mini", "claude-3-haiku"]
}'
# ...then return that team_id from custom auth:
return UserAPIKeyAuth(api_key=api_key, team_id="eng-team")

若要設定 project 的每個模型速率限制,請在 project 記錄上設定 model_tpm_limit / model_rpm_limit(以模型名稱作為索引),並回傳該 project_id

# On the project record (via /project/new or the UI):
# model_tpm_limit = {"gpt-4o": 100000, "claude-3-haiku": 50000}
# model_rpm_limit = {"gpt-4o": 100, "claude-3-haiku": 200}
備註
  • project 記錄的 metadata 會取代您在回傳物件上設定的任何 project_metadata,因此請將 project 的每個模型限制設定在 project 記錄上,而不是物件上。
  • 對於每個模型的速率限制,模型 key 必須與請求的 model 字串完全相同,否則會靜默略過該限制。這正是 Expedia 當時的實際失敗模式。

Key models 與 project models

這些是不同的控制項:

欄位強制執行位置真實來源
modelsUserAPIKeyAuthkey 層級允許清單您從自訂驗證回傳的值
project_idUserAPIKeyAuthproject 層級允許清單LiteLLM 的 DB 中 project 記錄 上的 models

空的 models 清單([])表示不限制。名稱必須與您設定中的 model group 完全一致(支援萬用字元)。請參閱 Project ManagementConfig Settings

Key 層級強制執行

以下項目會根據回傳物件強制執行,但只有在 litellm.enable_post_custom_auth_checks: true 也設定時才會生效:

general_settings:
custom_auth: custom_auth.user_api_key_auth
custom_auth_run_common_checks: true # required for the key models allowlist

litellm_settings:
enable_post_custom_auth_checks: true
from datetime import datetime, timedelta, timezone

return UserAPIKeyAuth(
api_key=api_key,
models=["gpt-4o-mini"], # key model allowlist (needs both flags)
model_max_budget={"gpt-4o": {"budget_limit": 100, "time_period": "30d"}}, # key per-model budget
expires=datetime.now(timezone.utc) + timedelta(days=30), # key expiry
)

end_user_id 已設定時,這條路徑也會強制執行 end-user 預算與每個模型的 end-user 預算。

✨ 支援 LiteLLM Virtual Keys + 自訂驗證

自 v1.72.2+ 起支援

資訊

✨ 支援 Custom Auth + LiteLLM Virtual Keys 是 LiteLLM Enterprise 的功能

Enterprise Pricing

取得 7 天免費試用 key

使用方式

  1. 設定自訂驗證檔案
"""
Example custom auth function.

This will allow all keys starting with "my-custom-key" to pass through.
"""
from typing import Union

from fastapi import Request

from litellm.proxy._types import UserAPIKeyAuth


async def user_api_key_auth(
request: Request, api_key: str
) -> Union[UserAPIKeyAuth, str]:
try:
if api_key.startswith("my-custom-key"):
return "sk-P1zJMdsqCPNN54alZd_ETw"
else:
raise Exception("Invalid API key")
except Exception:
raise Exception("Invalid API key")

  1. 設定 config.yaml

Key 變更集 mode: auto。這會同時檢查 litellm api key 驗證 + 自訂驗證。

model_list: 
- model_name: "openai-model"
litellm_params:
model: "gpt-3.5-turbo"
api_key: os.environ/OPENAI_API_KEY

general_settings:
custom_auth: custom_auth_auto.user_api_key_auth
custom_auth_settings:
mode: "auto" # can be 'on', 'off', 'auto' - 'auto' checks both litellm api key auth + custom auth

流程:

  1. 先檢查自訂驗證

  2. 如果自訂驗證失敗,則檢查 litellm api key 驗證

  3. 如果兩者都失敗,回傳 401

  4. 測試它!

curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer sk-P1zJMdsqCPNN54alZd_ETw' \
-d '{
"model": "openai-model",
"messages": [
{
"role": "user",
"content": "Hey! My name is John"
}
]
}'

向上拋出自訂例外

如果您想要向上拋出自訂例外,可以透過擲出 ProxyException 來達成。

"""
Example custom auth function.

This will allow all keys starting with "my-custom-key" to pass through.
"""

from typing import Union

from fastapi import Request

from litellm.proxy._types import UserAPIKeyAuth, ProxyException


async def user_api_key_auth(
request: Request, api_key: str
) -> Union[UserAPIKeyAuth, str]:
try:
if api_key.startswith("my-custom-key"):
return "sk-P1zJMdsqCPNN54alZd_ETw"
if api_key == "invalid-api-key":
# raise a custom exception back to the client
raise ProxyException(
message="Invalid API key",
type="invalid_request_error",
param="api_key",
code=401,
)
else:
raise Exception("Invalid API key")
except Exception:
raise Exception("Invalid API key")