mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-28 01:32:17 +00:00
Merge f37595bdba into 2dccc0dc79
This commit is contained in:
commit
9cfa41680f
5 changed files with 103 additions and 3 deletions
|
|
@ -104,6 +104,10 @@ response = completion(model="openai/gpt-4o", messages=[{"role": "user", "content
|
|||
response = completion(model="anthropic/claude-sonnet-4-20250514", messages=[{"role": "user", "content": "Hello!"}])
|
||||
```
|
||||
|
||||
By default, LiteLLM loads `.env` when imported in DEV mode. To disable this for the SDK and proxy, set
|
||||
`LITELLM_DISABLE_DOTENV=1` in the process environment before importing LiteLLM. Setting it inside `.env` is too late
|
||||
because LiteLLM reads the flag before loading that file
|
||||
|
||||
### AI Gateway (Proxy Server)
|
||||
|
||||
[**Getting Started - E2E Tutorial**](https://docs.litellm.ai/docs/proxy/docker_quick_start) - Setup virtual keys, make your first request
|
||||
|
|
|
|||
|
|
@ -11,12 +11,14 @@ warnings.filterwarnings("ignore", message=".*Accessing the.*attribute on the ins
|
|||
# cannot enforce it at runtime, which floods proxy boot once such a type is schema-walked
|
||||
warnings.filterwarnings("ignore", message=".*`ReadOnly` qualifier.*")
|
||||
### INIT VARIABLES #########################
|
||||
import threading
|
||||
import os
|
||||
import threading
|
||||
|
||||
# Load .env before any other litellm imports so env vars (e.g. LITELLM_UI_SESSION_DURATION) are available
|
||||
import dotenv as _dotenv
|
||||
|
||||
from ._dotenv_loader import should_load_dotenv as _should_load_dotenv
|
||||
|
||||
|
||||
def _dev_env_hot_reload_enabled() -> bool:
|
||||
"""The proxy exports this flag when started with ``--reload``. A reloaded
|
||||
|
|
@ -26,7 +28,7 @@ def _dev_env_hot_reload_enabled() -> bool:
|
|||
return os.getenv("LITELLM_DEV_ENV_HOT_RELOAD") == "True"
|
||||
|
||||
|
||||
if os.getenv("LITELLM_MODE", "DEV") == "DEV":
|
||||
if _should_load_dotenv():
|
||||
_dotenv.load_dotenv(override=_dev_env_hot_reload_enabled())
|
||||
|
||||
from collections.abc import Mapping, Sequence
|
||||
|
|
|
|||
9
litellm/_dotenv_loader.py
Normal file
9
litellm/_dotenv_loader.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import os
|
||||
from typing import Final
|
||||
|
||||
_TRUTHY_VALUES: Final = frozenset({"1", "true", "t", "yes", "y"})
|
||||
|
||||
|
||||
def should_load_dotenv() -> bool:
|
||||
disable_dotenv: Final = os.getenv("LITELLM_DISABLE_DOTENV", "").strip().casefold()
|
||||
return os.getenv("LITELLM_MODE", "DEV") == "DEV" and disable_dotenv not in _TRUTHY_VALUES
|
||||
|
|
@ -18,6 +18,7 @@ from dotenv import load_dotenv
|
|||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
import litellm
|
||||
from litellm._dotenv_loader import should_load_dotenv
|
||||
from litellm.constants import DEFAULT_NUM_WORKERS_LITELLM_PROXY
|
||||
from litellm.proxy.db.pgbouncer import (
|
||||
PgBouncerError,
|
||||
|
|
@ -52,7 +53,7 @@ sys.path.append(os.getcwd())
|
|||
config_filename: Final = "litellm.secrets"
|
||||
|
||||
litellm_mode: Final = os.getenv("LITELLM_MODE", "DEV") # "PRODUCTION", "DEV"
|
||||
if litellm_mode == "DEV":
|
||||
if should_load_dotenv():
|
||||
load_dotenv()
|
||||
from enum import Enum
|
||||
|
||||
|
|
|
|||
84
tests/test_litellm/test__dotenv_loader.py
Normal file
84
tests/test_litellm/test__dotenv_loader.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
_CONTROL_ENV_VARIABLES: Final = frozenset(
|
||||
{
|
||||
"LITELLM_DISABLE_DOTENV",
|
||||
"LITELLM_DEV_ENV_HOT_RELOAD",
|
||||
"LITELLM_DOTENV_LOADED",
|
||||
"LITELLM_MODE",
|
||||
}
|
||||
)
|
||||
_REPOSITORY_ROOT: Final = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def _dotenv_was_loaded(module: str, environment: Mapping[str, str]) -> bool:
|
||||
process_environment: Final = {
|
||||
key: value for key, value in os.environ.items() if key not in _CONTROL_ENV_VARIABLES
|
||||
} | dict(environment)
|
||||
script: Final = textwrap.dedent(
|
||||
f"""
|
||||
import os
|
||||
import dotenv
|
||||
|
||||
def load_dotenv(*args, **kwargs):
|
||||
os.environ["LITELLM_DOTENV_LOADED"] = "1"
|
||||
return True
|
||||
|
||||
dotenv.load_dotenv = load_dotenv
|
||||
import {module}
|
||||
print(f"LITELLM_DOTENV_LOADED={{os.environ.get('LITELLM_DOTENV_LOADED', '0')}}")
|
||||
"""
|
||||
)
|
||||
result: Final = subprocess.run(
|
||||
[sys.executable, "-c", script],
|
||||
cwd=_REPOSITORY_ROOT,
|
||||
env=process_environment,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
marker: Final = "LITELLM_DOTENV_LOADED="
|
||||
output_line: Final = next(line for line in result.stdout.splitlines() if line.startswith(marker))
|
||||
return output_line.removeprefix(marker) == "1"
|
||||
|
||||
|
||||
def test_default_dev_mode_loads_dotenv() -> None:
|
||||
assert _dotenv_was_loaded("litellm", {})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", ("1", "true", "t", "yes", "y", "TRUE", "YeS"))
|
||||
def test_disable_dotenv_truthy_values_prevent_loading(value: str) -> None:
|
||||
assert not _dotenv_was_loaded("litellm", {"LITELLM_DISABLE_DOTENV": value})
|
||||
|
||||
|
||||
def test_disable_dotenv_false_value_preserves_loading() -> None:
|
||||
assert _dotenv_was_loaded("litellm", {"LITELLM_DISABLE_DOTENV": "false"})
|
||||
|
||||
|
||||
def test_production_mode_still_skips_dotenv() -> None:
|
||||
assert not _dotenv_was_loaded("litellm", {"LITELLM_MODE": "PRODUCTION"})
|
||||
|
||||
|
||||
def test_disable_dotenv_wins_over_dev_hot_reload() -> None:
|
||||
environment: Final = {
|
||||
"LITELLM_DISABLE_DOTENV": "1",
|
||||
"LITELLM_DEV_ENV_HOT_RELOAD": "True",
|
||||
}
|
||||
assert not _dotenv_was_loaded("litellm", environment)
|
||||
|
||||
|
||||
def test_proxy_cli_respects_disable_dotenv() -> None:
|
||||
assert not _dotenv_was_loaded("litellm.proxy.proxy_cli", {"LITELLM_DISABLE_DOTENV": "1"})
|
||||
|
||||
|
||||
def test_proxy_cli_default_dev_mode_loads_dotenv() -> None:
|
||||
assert _dotenv_was_loaded("litellm.proxy.proxy_cli", {})
|
||||
Loading…
Add table
Reference in a new issue