mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
Merge pull request #25944 from BerriAI/litellm_internal_staging
Some checks failed
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 30, 8) (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Some checks failed
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 30, 8) (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
merge litellm_internal_staging
This commit is contained in:
commit
2f4b7bcb81
976 changed files with 39150 additions and 19141 deletions
1708
.circleci/config.yml
1708
.circleci/config.yml
File diff suppressed because it is too large
Load diff
|
|
@ -1,21 +0,0 @@
|
|||
# used by CI/CD testing
|
||||
openai==1.100.1
|
||||
python-dotenv
|
||||
tiktoken
|
||||
importlib_metadata
|
||||
cohere
|
||||
redis==5.2.1
|
||||
redisvl==0.4.1
|
||||
anthropic
|
||||
orjson==3.10.15 # fast /embedding responses
|
||||
pydantic==2.12.5
|
||||
google-cloud-aiplatform==1.133.0
|
||||
google-cloud-iam==2.19.1
|
||||
fastapi-sso==0.16.0
|
||||
uvloop==0.21.0
|
||||
mcp==1.26.0 # for MCP server
|
||||
semantic_router==0.1.10 # for auto-routing with litellm
|
||||
fastuuid==0.14.0
|
||||
responses==0.25.7 # for proxy client tests
|
||||
pytest-retry==1.6.3 # for automatic test retries
|
||||
litellm-proxy-extras # for prisma migrations
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
echo "[post-create] Installing poetry via pip"
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install poetry
|
||||
echo "[post-create] Installing uv"
|
||||
curl -LsSf https://astral.sh/uv/0.10.9/install.sh | env UV_NO_MODIFY_PATH=1 sh
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
echo "[post-create] Installing Python dependencies (poetry)"
|
||||
poetry install --with dev --extras proxy
|
||||
echo "[post-create] Installing Python dependencies (uv)"
|
||||
uv sync --frozen --group proxy-dev --extra proxy
|
||||
|
||||
echo "[post-create] Generating Prisma client"
|
||||
poetry run prisma generate
|
||||
uv run --no-sync prisma generate
|
||||
|
||||
echo "[post-create] Installing npm dependencies"
|
||||
cd ui/litellm-dashboard && npm ci
|
||||
|
||||
echo "[post-create] Done"
|
||||
echo "[post-create] Done"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ secret:
|
|||
- "docs/**"
|
||||
- "**/*.md"
|
||||
- "**/*.lock"
|
||||
- "poetry.lock"
|
||||
- "uv.lock"
|
||||
- "package-lock.json"
|
||||
|
||||
# Ignore security incidents with the SHA256 of the occurrence (false positives)
|
||||
|
|
|
|||
29
.github/workflows/_test-unit-base.yml
vendored
29
.github/workflows/_test-unit-base.yml
vendored
|
|
@ -51,37 +51,30 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Cache Poetry dependencies
|
||||
- name: Cache uv dependencies
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pypoetry
|
||||
~/.cache/pip
|
||||
~/.cache/uv
|
||||
.venv
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
|
||||
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
${{ runner.os }}-uv-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry config virtualenvs.in-project true
|
||||
poetry install --with dev,proxy-dev --extras "proxy semantic-router"
|
||||
poetry run pip install google-genai==1.22.0 \
|
||||
google-cloud-aiplatform==1.115.0 fastapi-offline==1.7.3 python-multipart==0.0.22 openapi-core==0.23.0
|
||||
|
||||
- name: Setup litellm-enterprise
|
||||
run: |
|
||||
poetry run pip install --force-reinstall --no-deps -e enterprise/
|
||||
uv sync --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router
|
||||
|
||||
- name: Generate Prisma client
|
||||
env:
|
||||
PRISMA_BINARY_CACHE_DIR: ${{ runner.temp }}/prisma-cache
|
||||
run: |
|
||||
poetry run pip install nodejs-wheel-binaries==24.13.1
|
||||
poetry run prisma generate --schema litellm/proxy/schema.prisma
|
||||
uv run --no-sync prisma generate --schema litellm/proxy/schema.prisma
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
|
|
@ -90,7 +83,7 @@ jobs:
|
|||
WORKERS: ${{ inputs.workers }}
|
||||
RERUNS: ${{ inputs.reruns }}
|
||||
run: |
|
||||
poetry run pytest ${TEST_PATH:?} \
|
||||
uv run --no-sync pytest ${TEST_PATH:?} \
|
||||
--tb=short -vv \
|
||||
--maxfail="${MAX_FAILURES}" \
|
||||
-n "${WORKERS}" \
|
||||
|
|
|
|||
33
.github/workflows/_test-unit-services-base.yml
vendored
33
.github/workflows/_test-unit-services-base.yml
vendored
|
|
@ -86,44 +86,37 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Cache Poetry dependencies
|
||||
- name: Cache uv dependencies
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pypoetry
|
||||
~/.cache/pip
|
||||
~/.cache/uv
|
||||
.venv
|
||||
key: ${{ runner.os }}-poetry-services-${{ hashFiles('poetry.lock') }}
|
||||
key: ${{ runner.os }}-uv-services-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-services-
|
||||
${{ runner.os }}-uv-services-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry config virtualenvs.in-project true
|
||||
poetry install --with dev,proxy-dev --extras "proxy semantic-router"
|
||||
poetry run pip install google-genai==1.22.0 \
|
||||
google-cloud-aiplatform==1.115.0 fastapi-offline==1.7.3 python-multipart==0.0.22 openapi-core==0.23.0
|
||||
|
||||
- name: Setup litellm-enterprise
|
||||
run: |
|
||||
poetry run pip install --force-reinstall --no-deps -e enterprise/
|
||||
uv sync --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router
|
||||
|
||||
- name: Generate Prisma client
|
||||
env:
|
||||
PRISMA_BINARY_CACHE_DIR: ${{ runner.temp }}/prisma-cache
|
||||
run: |
|
||||
poetry run pip install nodejs-wheel-binaries==24.13.1
|
||||
poetry run prisma generate --schema litellm/proxy/schema.prisma
|
||||
uv run --no-sync prisma generate --schema litellm/proxy/schema.prisma
|
||||
|
||||
- name: Run Prisma migrations
|
||||
if: ${{ inputs.enable-postgres }}
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
run: |
|
||||
poetry run prisma db push --schema litellm/proxy/schema.prisma --accept-data-loss
|
||||
uv run --no-sync prisma db push --schema litellm/proxy/schema.prisma --accept-data-loss
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
|
|
@ -134,7 +127,7 @@ jobs:
|
|||
DATABASE_URL: ${{ inputs.enable-postgres && secrets.DATABASE_URL || '' }}
|
||||
run: |
|
||||
if [ "${WORKERS}" = "0" ]; then
|
||||
poetry run pytest ${TEST_PATH:?} \
|
||||
uv run --no-sync pytest ${TEST_PATH:?} \
|
||||
--tb=short -vv \
|
||||
--maxfail="${MAX_FAILURES}" \
|
||||
--reruns "${RERUNS}" \
|
||||
|
|
@ -144,7 +137,7 @@ jobs:
|
|||
--cov-report=xml:coverage.xml \
|
||||
--cov-config=pyproject.toml
|
||||
else
|
||||
poetry run pytest ${TEST_PATH:?} \
|
||||
uv run --no-sync pytest ${TEST_PATH:?} \
|
||||
--tb=short -vv \
|
||||
--maxfail="${MAX_FAILURES}" \
|
||||
-n "${WORKERS}" \
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ jobs:
|
|||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install 'aiohttp==3.13.3'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
- name: Update JSON Data
|
||||
run: |
|
||||
python ".github/workflows/auto_update_price_and_context_window_file.py"
|
||||
uv run --frozen --with 'aiohttp==3.13.3' python ".github/workflows/auto_update_price_and_context_window_file.py"
|
||||
- name: Create Pull Request
|
||||
run: |
|
||||
git add model_prices_and_context_window.json
|
||||
|
|
|
|||
18
.github/workflows/codspeed.yml
vendored
18
.github/workflows/codspeed.yml
vendored
|
|
@ -34,13 +34,21 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -e "."
|
||||
pip install pytest pytest-codspeed==4.3.0
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Run benchmarks
|
||||
uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4.12.1
|
||||
with:
|
||||
mode: simulation
|
||||
run: pytest tests/benchmarks/ --codspeed
|
||||
run: >
|
||||
env PYTEST_DISABLE_PLUGIN_AUTOLOAD=1
|
||||
uv run --frozen --no-default-groups
|
||||
--with pytest==8.3.5
|
||||
--with pytest-codspeed==4.3.0
|
||||
pytest
|
||||
-p pytest_codspeed.plugin
|
||||
tests/benchmarks/
|
||||
--codspeed
|
||||
|
|
|
|||
42
.github/workflows/guard-main-branch.yml
vendored
Normal file
42
.github/workflows/guard-main-branch.yml
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
name: Guard main branch
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
merge_group:
|
||||
|
||||
permissions: {}
|
||||
|
||||
# DO NOT RENAME the job's `name:` — it is referenced by GitHub branch
|
||||
# protection as a required status check on `main`. Renaming silently
|
||||
# breaks the gate.
|
||||
jobs:
|
||||
guard:
|
||||
name: Verify PR source branch
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- name: Reject merge_group events
|
||||
if: github.event_name == 'merge_group'
|
||||
run: |
|
||||
echo "::error::Merge queue is not supported for main. Disable merge queue or update this guard."
|
||||
exit 1
|
||||
- name: Check head branch name
|
||||
env:
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
BASE_REPO: ${{ github.repository }}
|
||||
run: |
|
||||
echo "PR head repo: $HEAD_REPO"
|
||||
echo "PR head branch: $HEAD_REF"
|
||||
if [ "$HEAD_REPO" != "$BASE_REPO" ]; then
|
||||
echo "::error::PRs to main must originate from the canonical repository ($BASE_REPO), not a fork ($HEAD_REPO). External contributors should open PRs against the 'litellm_oss_branch' branch instead."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$HEAD_REF" = "litellm_internal_staging" ] || [[ "$HEAD_REF" == litellm_hotfix_?* ]]; then
|
||||
echo "Allowed source branch."
|
||||
exit 0
|
||||
fi
|
||||
echo "::error::PRs to main must originate from 'litellm_internal_staging' or a 'litellm_hotfix_*' branch. Got: '$HEAD_REF'. If this is a contribution, retarget the PR against 'litellm_oss_branch' instead."
|
||||
exit 1
|
||||
23
.github/workflows/llm-translation-testing.yml
vendored
23
.github/workflows/llm-translation-testing.yml
vendored
|
|
@ -31,26 +31,25 @@ jobs:
|
|||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install Poetry
|
||||
run: |
|
||||
pip install 'poetry==2.3.2'
|
||||
poetry config virtualenvs.create true
|
||||
poetry config virtualenvs.in-project true
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
enable-cache: false
|
||||
|
||||
- name: Restore Poetry dependencies cache
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.0.0
|
||||
- name: Restore uv dependencies cache
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pypoetry
|
||||
~/.cache/uv
|
||||
.venv
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
${{ runner.os }}-uv-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry install --with dev
|
||||
poetry run pip install 'pytest-xdist==3.8.0' 'pytest-timeout==2.4.0'
|
||||
uv sync --frozen
|
||||
|
||||
- name: Create test results directory
|
||||
run: mkdir -p test-results
|
||||
|
|
|
|||
89
.github/workflows/publish_to_pypi.yml
vendored
89
.github/workflows/publish_to_pypi.yml
vendored
|
|
@ -24,10 +24,22 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
enable-cache: false
|
||||
|
||||
- name: Check litellm version on PyPI
|
||||
id: check-litellm
|
||||
run: |
|
||||
VERSION=$(grep -m1 '^version' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
||||
VERSION=$(python - <<'PY'
|
||||
import tomllib
|
||||
|
||||
with open("pyproject.toml", "rb") as f:
|
||||
print(tomllib.load(f)["project"]["version"])
|
||||
PY
|
||||
)
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "Checking if litellm $VERSION exists on PyPI..."
|
||||
|
||||
|
|
@ -42,43 +54,46 @@ jobs:
|
|||
|
||||
- name: Sanity check proxy-extras version
|
||||
run: |
|
||||
# Read pinned version from requirements.txt
|
||||
REQ_VERSION=$(grep -oP 'litellm-proxy-extras==\K[0-9.]+' requirements.txt)
|
||||
if [ -z "$REQ_VERSION" ]; then
|
||||
echo "::error::Could not find litellm-proxy-extras version in requirements.txt"
|
||||
exit 1
|
||||
fi
|
||||
echo "requirements.txt pins litellm-proxy-extras==$REQ_VERSION"
|
||||
# Read pinned version from project optional dependencies
|
||||
PYPROJECT_VERSION=$(python3 - <<'PY'
|
||||
import sys
|
||||
import tomllib
|
||||
|
||||
# Read pinned version from pyproject.toml dependency
|
||||
PYPROJECT_VERSION=$(python3 -c "
|
||||
import re
|
||||
with open('pyproject.toml') as f:
|
||||
content = f.read()
|
||||
match = re.search(r'litellm-proxy-extras\s*=\s*\{version\s*=\s*\"([^\"]+)\"', content)
|
||||
if match:
|
||||
print(match.group(1).lstrip('^~>='))
|
||||
else:
|
||||
import sys
|
||||
print('::error::Could not find litellm-proxy-extras dependency in pyproject.toml', file=sys.stderr)
|
||||
with open("pyproject.toml", "rb") as f:
|
||||
proxy_requirements = tomllib.load(f)["project"]["optional-dependencies"]["proxy"]
|
||||
|
||||
version = None
|
||||
for requirement in proxy_requirements:
|
||||
normalized = requirement.split(";", 1)[0].strip()
|
||||
if not normalized.startswith("litellm-proxy-extras"):
|
||||
continue
|
||||
parts = normalized.split("==", 1)
|
||||
if len(parts) == 2 and parts[0].strip() == "litellm-proxy-extras":
|
||||
candidate = parts[1].strip()
|
||||
if candidate:
|
||||
version = candidate
|
||||
break
|
||||
|
||||
if version is None:
|
||||
print(
|
||||
"::error::Could not find an exact litellm-proxy-extras pin in project.optional-dependencies.proxy",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
")
|
||||
|
||||
print(version)
|
||||
PY
|
||||
)
|
||||
echo "pyproject.toml pins litellm-proxy-extras version: $PYPROJECT_VERSION"
|
||||
|
||||
# Check that both pinned versions match
|
||||
if [ "$REQ_VERSION" != "$PYPROJECT_VERSION" ]; then
|
||||
echo "::error::Version mismatch: requirements.txt has $REQ_VERSION but pyproject.toml has $PYPROJECT_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that the pinned version exists on PyPI
|
||||
echo "Checking if litellm-proxy-extras $REQ_VERSION exists on PyPI..."
|
||||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/litellm-proxy-extras/$REQ_VERSION/json")
|
||||
echo "Checking if litellm-proxy-extras $PYPROJECT_VERSION exists on PyPI..."
|
||||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/litellm-proxy-extras/$PYPROJECT_VERSION/json")
|
||||
if [ "$HTTP_STATUS" != "200" ]; then
|
||||
echo "::error::litellm-proxy-extras $REQ_VERSION is not published on PyPI yet. Publish it before releasing litellm."
|
||||
echo "::error::litellm-proxy-extras $PYPROJECT_VERSION is not published on PyPI yet. Publish it before releasing litellm."
|
||||
exit 1
|
||||
fi
|
||||
echo "litellm-proxy-extras $REQ_VERSION exists on PyPI. Sanity check passed."
|
||||
echo "litellm-proxy-extras $PYPROJECT_VERSION exists on PyPI. Sanity check passed."
|
||||
|
||||
publish-litellm:
|
||||
name: Publish litellm to PyPI
|
||||
|
|
@ -100,16 +115,19 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
enable-cache: false
|
||||
|
||||
- name: Copy model prices backup
|
||||
run: cp model_prices_and_context_window.json litellm/model_prices_and_context_window_backup.json
|
||||
|
||||
- name: Install build tools
|
||||
run: python -m pip install --upgrade pip build==1.4.2
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
rm -rf build dist
|
||||
python -m build
|
||||
uv build
|
||||
|
||||
- name: Verify build artifacts
|
||||
env:
|
||||
|
|
@ -129,8 +147,7 @@ jobs:
|
|||
|
||||
- name: Validate package metadata
|
||||
run: |
|
||||
pip install twine==6.2.0
|
||||
twine check dist/*
|
||||
uv tool run --from 'twine==6.2.0' twine check dist/*
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ def run_tests(test_path: str = "tests/llm_translation/",
|
|||
|
||||
# Run pytest
|
||||
cmd = [
|
||||
"poetry", "run", "pytest", test_path,
|
||||
"uv", "run", "--no-sync", "pytest", test_path,
|
||||
f"--junitxml={junit_xml}",
|
||||
"-v",
|
||||
"--tb=short",
|
||||
|
|
@ -335,7 +335,7 @@ def run_tests(test_path: str = "tests/llm_translation/",
|
|||
|
||||
# Add timeout if pytest-timeout is installed
|
||||
try:
|
||||
subprocess.run(["poetry", "run", "python", "-c", "import pytest_timeout"],
|
||||
subprocess.run(["uv", "run", "--no-sync", "python", "-c", "import pytest_timeout"],
|
||||
capture_output=True, check=True)
|
||||
cmd.extend(["--timeout=300"])
|
||||
except:
|
||||
|
|
@ -436,4 +436,4 @@ if __name__ == "__main__":
|
|||
commit=args.commit
|
||||
)
|
||||
|
||||
sys.exit(exit_code)
|
||||
sys.exit(exit_code)
|
||||
|
|
|
|||
41
.github/workflows/test-linting.yml
vendored
41
.github/workflows/test-linting.yml
vendored
|
|
@ -2,7 +2,11 @@ name: LiteLLM Linting
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -24,26 +28,28 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Clean Python cache
|
||||
run: |
|
||||
find . -type d -name "__pycache__" -exec rm -rf {} + || true
|
||||
find . -name "*.pyc" -delete || true
|
||||
|
||||
- name: Check poetry.lock is up to date
|
||||
- name: Check uv.lock is up to date
|
||||
run: |
|
||||
poetry check --lock || (echo "❌ poetry.lock is out of sync with pyproject.toml. Run 'poetry lock' locally and commit the result." && exit 1)
|
||||
uv lock --check || (echo "❌ uv.lock is out of sync with pyproject.toml. Run 'uv lock' locally and commit the result." && exit 1)
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry install --with dev
|
||||
uv sync --frozen
|
||||
|
||||
- name: Check Black formatting
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run black --check --exclude '/enterprise/' .
|
||||
uv run --no-sync black --check --exclude '/enterprise/' .
|
||||
cd ..
|
||||
|
||||
- name: Debug - Check file state
|
||||
|
|
@ -58,28 +64,28 @@ jobs:
|
|||
- name: Run Ruff linting
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run ruff check .
|
||||
uv run --no-sync ruff check .
|
||||
cd ..
|
||||
|
||||
- name: Print OpenAI version
|
||||
run: |
|
||||
poetry run python -c "import openai; print(f'OpenAI version: {openai.__version__}')"
|
||||
uv run --no-sync python -c "import openai; print(f'OpenAI version: {openai.__version__}')"
|
||||
|
||||
- name: Run MyPy type checking
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run mypy .
|
||||
uv run --no-sync mypy .
|
||||
cd ..
|
||||
|
||||
- name: Check for circular imports
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run python ../tests/documentation_tests/test_circular_imports.py
|
||||
uv run --no-sync python ../tests/documentation_tests/test_circular_imports.py
|
||||
cd ..
|
||||
|
||||
- name: Check import safety
|
||||
run: |
|
||||
poetry run python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
|
||||
uv run --no-sync python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
|
||||
|
||||
secret-scan:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -98,18 +104,21 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Run secret scan test
|
||||
run: |
|
||||
pip install 'pytest==9.0.2'
|
||||
pytest tests/litellm/test_no_hardcoded_secrets.py -v
|
||||
uv run --frozen --with 'pytest==9.0.2' pytest tests/litellm/test_no_hardcoded_secrets.py -v
|
||||
|
||||
- name: Run ggshield secret scan
|
||||
env:
|
||||
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
|
||||
run: |
|
||||
if [ -n "$GITGUARDIAN_API_KEY" ]; then
|
||||
pip install 'ggshield==1.48.0'
|
||||
ggshield secret scan repo .
|
||||
uv tool run --from 'ggshield==1.48.0' ggshield secret scan repo .
|
||||
else
|
||||
echo "GITGUARDIAN_API_KEY not set, skipping ggshield scan"
|
||||
fi
|
||||
|
|
|
|||
6
.github/workflows/test-litellm-ui-build.yml
vendored
6
.github/workflows/test-litellm-ui-build.yml
vendored
|
|
@ -4,7 +4,11 @@ permissions:
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
jobs:
|
||||
build-ui:
|
||||
|
|
|
|||
22
.github/workflows/test-litellm.yml
vendored
22
.github/workflows/test-litellm.yml
vendored
|
|
@ -31,23 +31,15 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry lock
|
||||
poetry install --with dev,proxy-dev --extras "proxy semantic-router"
|
||||
poetry run pip install "pytest-retry==1.6.3"
|
||||
poetry run pip install 'pytest-xdist==3.8.0'
|
||||
poetry run pip install "google-genai==1.22.0"
|
||||
poetry run pip install "google-cloud-aiplatform==1.115.0"
|
||||
poetry run pip install "fastapi-offline==1.7.3"
|
||||
poetry run pip install "python-multipart==0.0.22"
|
||||
poetry run pip install "openapi-core==0.23.0"
|
||||
- name: Setup litellm-enterprise as local package
|
||||
run: |
|
||||
poetry run pip install --force-reinstall --no-deps -e enterprise/
|
||||
uv lock --check
|
||||
uv sync --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router
|
||||
- name: Run tests
|
||||
run: |
|
||||
poetry run pytest tests/test_litellm --tb=short -vv --maxfail=10 -n 4 --durations=50
|
||||
uv run --no-sync pytest tests/test_litellm --tb=short -vv --maxfail=10 -n 4 --durations=50
|
||||
|
|
|
|||
30
.github/workflows/test-mcp.yml
vendored
30
.github/workflows/test-mcp.yml
vendored
|
|
@ -2,7 +2,11 @@ name: LiteLLM MCP Tests (folder - tests/mcp_tests)
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -27,26 +31,16 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry lock
|
||||
poetry install --with dev,proxy-dev --extras "proxy semantic-router"
|
||||
poetry run pip install "pytest==7.3.1"
|
||||
poetry run pip install "pytest-retry==1.6.3"
|
||||
poetry run pip install "pytest-cov==5.0.0"
|
||||
poetry run pip install "pytest-asyncio==0.21.1"
|
||||
poetry run pip install "respx==0.22.0"
|
||||
poetry run pip install "pydantic==2.11.0"
|
||||
poetry run pip install "mcp==1.25.0"
|
||||
poetry run pip install 'pytest-xdist==3.8.0'
|
||||
|
||||
- name: Setup litellm-enterprise as local package
|
||||
run: |
|
||||
poetry run pip install --force-reinstall --no-deps -e enterprise/
|
||||
uv lock --check
|
||||
uv sync --frozen --group proxy-dev --extra proxy --extra semantic-router
|
||||
|
||||
- name: Run MCP tests
|
||||
run: |
|
||||
poetry run pytest tests/mcp_tests -x -vv -n 4 --cov=litellm --cov-report=xml --durations=5
|
||||
uv run --no-sync pytest tests/mcp_tests -x -vv -n 4 --cov=litellm --cov-report=xml --durations=5
|
||||
|
|
|
|||
6
.github/workflows/test-model-map.yaml
vendored
6
.github/workflows/test-model-map.yaml
vendored
|
|
@ -2,7 +2,11 @@ name: Validate model_prices_and_context_window.json
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
6
.github/workflows/test-unit-core-utils.yml
vendored
6
.github/workflows/test-unit-core-utils.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Core Utilities"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
41
.github/workflows/test-unit-documentation.yml
vendored
41
.github/workflows/test-unit-documentation.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Documentation Validation"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -26,42 +30,35 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Cache Poetry dependencies
|
||||
- name: Cache uv dependencies
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pypoetry
|
||||
~/.cache/pip
|
||||
~/.cache/uv
|
||||
.venv
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
|
||||
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
${{ runner.os }}-uv-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry config virtualenvs.in-project true
|
||||
poetry install --with dev,proxy-dev --extras "proxy semantic-router"
|
||||
poetry run pip install google-genai==1.22.0 \
|
||||
google-cloud-aiplatform==1.115.0 fastapi-offline==1.7.3 python-multipart==0.0.22 openapi-core==0.23.0
|
||||
|
||||
- name: Setup litellm-enterprise
|
||||
run: |
|
||||
poetry run pip install --force-reinstall --no-deps -e enterprise/
|
||||
uv sync --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router
|
||||
|
||||
- name: Generate Prisma client
|
||||
env:
|
||||
PRISMA_BINARY_CACHE_DIR: ${{ runner.temp }}/prisma-cache
|
||||
run: |
|
||||
poetry run pip install nodejs-wheel-binaries==24.13.1
|
||||
poetry run prisma generate --schema litellm/proxy/schema.prisma
|
||||
uv run --no-sync prisma generate --schema litellm/proxy/schema.prisma
|
||||
|
||||
# Run the same documentation tests that CircleCI ran (as direct Python scripts)
|
||||
- name: Run documentation validation tests
|
||||
run: |
|
||||
poetry run python ./tests/documentation_tests/test_env_keys.py
|
||||
poetry run python ./tests/documentation_tests/test_router_settings.py
|
||||
poetry run python ./tests/documentation_tests/test_api_docs.py
|
||||
poetry run python ./tests/documentation_tests/test_circular_imports.py
|
||||
uv run --no-sync python ./tests/documentation_tests/test_env_keys.py
|
||||
uv run --no-sync python ./tests/documentation_tests/test_router_settings.py
|
||||
uv run --no-sync python ./tests/documentation_tests/test_api_docs.py
|
||||
uv run --no-sync python ./tests/documentation_tests/test_circular_imports.py
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Enterprise, Google GenAI & Routing"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
6
.github/workflows/test-unit-integrations.yml
vendored
6
.github/workflows/test-unit-integrations.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Integrations (Callbacks & Logging)"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: LLM Provider Transformations"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
6
.github/workflows/test-unit-misc.yml
vendored
6
.github/workflows/test-unit-misc.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: MCP, Secrets, Containers & Misc"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
6
.github/workflows/test-unit-proxy-auth.yml
vendored
6
.github/workflows/test-unit-proxy-auth.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Proxy Auth & Key Management"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
4
.github/workflows/test-unit-proxy-db.yml
vendored
4
.github/workflows/test-unit-proxy-db.yml
vendored
|
|
@ -3,7 +3,7 @@ name: "Unit Tests: Proxy DB Operations"
|
|||
# Uses DATABASE_URL secret — only runs on trusted branches, not PRs.
|
||||
on:
|
||||
push:
|
||||
branches: [main, "litellm_*"]
|
||||
branches: [main, "litellm_**"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -34,7 +34,7 @@ jobs:
|
|||
- test-group: remaining
|
||||
test-path: "tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py"
|
||||
workers: 8
|
||||
timeout: 20
|
||||
timeout: 30
|
||||
uses: ./.github/workflows/_test-unit-services-base.yml
|
||||
with:
|
||||
test-path: ${{ matrix.test-path }}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Proxy API Endpoints"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
6
.github/workflows/test-unit-proxy-infra.yml
vendored
6
.github/workflows/test-unit-proxy-infra.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Proxy Infrastructure"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
35
.github/workflows/test-unit-proxy-legacy.yml
vendored
35
.github/workflows/test-unit-proxy-legacy.yml
vendored
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Proxy Legacy Tests"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -50,43 +54,36 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Poetry
|
||||
run: pip install 'poetry==2.3.2'
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
||||
with:
|
||||
version: "0.10.9"
|
||||
|
||||
- name: Cache Poetry dependencies
|
||||
- name: Cache uv dependencies
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pypoetry
|
||||
~/.cache/pip
|
||||
~/.cache/uv
|
||||
.venv
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
|
||||
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
${{ runner.os }}-uv-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry config virtualenvs.in-project true
|
||||
poetry install --with dev,proxy-dev --extras "proxy semantic-router"
|
||||
poetry run pip install google-genai==1.22.0 \
|
||||
google-cloud-aiplatform==1.115.0 fastapi-offline==1.7.3 python-multipart==0.0.22 openapi-core==0.23.0
|
||||
|
||||
- name: Setup litellm-enterprise
|
||||
run: |
|
||||
poetry run pip install --force-reinstall --no-deps -e enterprise/
|
||||
uv sync --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router
|
||||
|
||||
- name: Generate Prisma client
|
||||
env:
|
||||
PRISMA_BINARY_CACHE_DIR: ${{ runner.temp }}/prisma-cache
|
||||
run: |
|
||||
poetry run pip install nodejs-wheel-binaries==24.13.1
|
||||
poetry run prisma generate --schema litellm/proxy/schema.prisma
|
||||
uv run --no-sync prisma generate --schema litellm/proxy/schema.prisma
|
||||
|
||||
- name: Run tests - ${{ matrix.test-group.name }}
|
||||
env:
|
||||
TEST_PATH: ${{ matrix.test-group.path }}
|
||||
run: |
|
||||
poetry run pytest ${TEST_PATH} \
|
||||
uv run --no-sync pytest ${TEST_PATH} \
|
||||
--tb=short -vv \
|
||||
--maxfail=10 \
|
||||
-n 2 \
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ name: "Unit Tests: Responses, Caching & Types"
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
2
.github/workflows/test-unit-security.yml
vendored
2
.github/workflows/test-unit-security.yml
vendored
|
|
@ -3,7 +3,7 @@ name: "Unit Tests: Security"
|
|||
# Uses DATABASE_URL secret — only runs on trusted branches, not PRs.
|
||||
on:
|
||||
push:
|
||||
branches: [main, "litellm_*"]
|
||||
branches: [main, "litellm_**"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
|||
14
.github/workflows/test_server_root_path.yml
vendored
14
.github/workflows/test_server_root_path.yml
vendored
|
|
@ -4,12 +4,16 @@ permissions:
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches:
|
||||
- main
|
||||
- litellm_internal_staging
|
||||
- litellm_oss_branch
|
||||
- "litellm_**"
|
||||
|
||||
jobs:
|
||||
test-server-root-path:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
timeout-minutes: 30
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
@ -21,6 +25,12 @@ jobs:
|
|||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Free up disk space
|
||||
run: |
|
||||
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/share/boost
|
||||
sudo apt-get clean
|
||||
df -h /
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12
|
||||
|
||||
|
|
|
|||
25
AGENTS.md
25
AGENTS.md
|
|
@ -51,7 +51,9 @@ LiteLLM is a unified interface for 100+ LLMs that:
|
|||
|
||||
### MAKING CODE CHANGES FOR THE UI (IGNORE FOR BACKEND)
|
||||
|
||||
1. **Tremor is DEPRECATED, do not use Tremor components in new features/changes**
|
||||
1. **Always use `antd` for new UI components — Tremor is DEPRECATED**
|
||||
- We are migrating off of `@tremor/react`. Do not introduce new `Badge`, `Text`, `Card`, `Grid`, `Title`, or other imports from `@tremor/react` in any new or modified file.
|
||||
- Use `antd` equivalents: `Tag` for labels, plain `<span>`/`<div>` with Tailwind classes (or `Typography.Text`) for text, `Card` from `antd`, etc. Note that `antd` has no `"yellow"` Tag color — use `"gold"` for amber/yellow.
|
||||
- The only exception is the Tremor Table component and its required Tremor Table sub components.
|
||||
|
||||
2. **Use Common Components as much as possible**:
|
||||
|
|
@ -121,7 +123,7 @@ LiteLLM supports MCP for agent workflows:
|
|||
|
||||
## RUNNING SCRIPTS
|
||||
|
||||
Use `poetry run python script.py` to run Python scripts in the project environment (for non-test files).
|
||||
Use `uv run python script.py` to run Python scripts in the project environment (for non-test files).
|
||||
|
||||
## GITHUB TEMPLATES
|
||||
|
||||
|
|
@ -232,16 +234,16 @@ When opening issues or pull requests, follow these templates:
|
|||
|
||||
### Environment
|
||||
|
||||
- Poetry is installed in `~/.local/bin`; the update script ensures it is on `PATH`.
|
||||
- uv is installed in `~/.local/bin`; the update script ensures it is on `PATH`.
|
||||
- Python 3.12, Node 22 are pre-installed.
|
||||
- The virtual environment lives under `~/.cache/pypoetry/virtualenvs/`.
|
||||
- The project virtual environment lives under `.venv/`.
|
||||
|
||||
### Running the proxy server
|
||||
|
||||
Start the proxy with a config file:
|
||||
|
||||
```bash
|
||||
poetry run litellm --config dev_config.yaml --port 4000
|
||||
uv run litellm --config dev_config.yaml --port 4000
|
||||
```
|
||||
|
||||
The proxy takes ~15-20 seconds to fully start (it runs Prisma migrations on boot). Wait for `/health` to return before sending requests. Without a PostgreSQL `DATABASE_URL`, the proxy connects to a default Neon dev database embedded in the `litellm-proxy-extras` package.
|
||||
|
|
@ -250,17 +252,16 @@ The proxy takes ~15-20 seconds to fully start (it runs Prisma migrations on boot
|
|||
|
||||
See `CLAUDE.md` and the `Makefile` for standard commands. Key notes:
|
||||
|
||||
- `psycopg-binary` must be installed (`poetry run pip install psycopg-binary`) because the pytest-postgresql plugin requires it and the lock file only includes `psycopg` (no binary).
|
||||
- `openapi-core` must be installed (`poetry run pip install openapi-core`) for the OpenAPI compliance tests in `tests/test_litellm/interactions/`.
|
||||
- `uv sync --group proxy-dev --extra proxy` installs the Prisma and proxy-side test dependencies used by the standard local workflow.
|
||||
- The `--timeout` pytest flag is NOT available; don't pass it.
|
||||
- Unit tests: `poetry run pytest tests/test_litellm/ -x -vv -n 4`
|
||||
- **Before committing, always run `poetry run black .` to format your code.** Black formatting is enforced in CI.
|
||||
- If `poetry install` fails with "pyproject.toml changed significantly since poetry.lock was last generated", run `poetry lock` first to regenerate the lock file.
|
||||
- Unit tests: `uv run pytest tests/test_litellm/ -x -vv -n 4`
|
||||
- **Before committing, always run `uv run black .` to format your code.** Black formatting is enforced in CI.
|
||||
- If `uv sync` fails because the lockfile is outdated, run `uv lock` and retry.
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
cd litellm && poetry run ruff check .
|
||||
cd litellm && uv run ruff check .
|
||||
```
|
||||
|
||||
Ruff is the primary fast linter. For the full lint suite (including mypy, black, circular imports), run `make lint` per `CLAUDE.md`.
|
||||
|
|
@ -271,4 +272,4 @@ Ruff is the primary fast linter. For the full lint suite (including mypy, black,
|
|||
- The proxy at port 4000 serves a **pre-built** static UI from `litellm/proxy/_experimental/out/`. After making UI code changes, you must run `npm run build` in the dashboard directory and copy the output: `cp -r ui/litellm-dashboard/out/* litellm/proxy/_experimental/out/` for the proxy to serve the updated UI.
|
||||
- SVGs used as provider logos (loaded via `<img>` tags) must NOT use `fill="currentColor"` — replace with an explicit color like `#000000` or use the `-color` variant from lobehub icons, since CSS color inheritance does not work inside `<img>` elements.
|
||||
- Provider logos live in `ui/litellm-dashboard/public/assets/logos/` (source) and `litellm/proxy/_experimental/out/assets/logos/` (pre-built). Both locations must have the file for it to work in dev and proxy-served modes.
|
||||
- UI Vitest tests: `cd ui/litellm-dashboard && npx vitest run`
|
||||
- UI Vitest tests: `cd ui/litellm-dashboard && npx vitest run`
|
||||
|
|
|
|||
21
CLAUDE.md
21
CLAUDE.md
|
|
@ -7,7 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
### Installation
|
||||
- `make install-dev` - Install core development dependencies
|
||||
- `make install-proxy-dev` - Install proxy development dependencies with full feature set
|
||||
- `make install-test-deps` - Install all test dependencies
|
||||
- `make install-test-deps` - Install the full local test environment and generate the Prisma client
|
||||
|
||||
### Testing
|
||||
- `make test` - Run all tests
|
||||
|
|
@ -20,14 +20,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
- `make format` - Apply Black code formatting
|
||||
- `make lint-ruff` - Run Ruff linting only
|
||||
- `make lint-mypy` - Run MyPy type checking only
|
||||
- **Before committing, always run `poetry run black .` to format your code.** Black formatting is enforced in CI.
|
||||
- **Before committing, always run `uv run black .` to format your code.** Black formatting is enforced in CI.
|
||||
|
||||
### Single Test Files
|
||||
- `poetry run pytest tests/path/to/test_file.py -v` - Run specific test file
|
||||
- `poetry run pytest tests/path/to/test_file.py::test_function -v` - Run specific test
|
||||
- `uv run pytest tests/path/to/test_file.py -v` - Run specific test file
|
||||
- `uv run pytest tests/path/to/test_file.py::test_function -v` - Run specific test
|
||||
|
||||
### Running Scripts
|
||||
- `poetry run python script.py` - Run Python scripts (use for non-test files)
|
||||
- `uv run python script.py` - Run Python scripts (use for non-test files)
|
||||
|
||||
### GitHub Issue & PR Templates
|
||||
When contributing to the project, use the appropriate templates:
|
||||
|
|
@ -109,6 +109,9 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
|
|||
### UI / Backend Consistency
|
||||
- When wiring a new UI entity type to an existing backend endpoint, verify the backend API contract (single value vs. array, required vs. optional params) and ensure the UI controls match — e.g., use a single-select dropdown when the backend accepts a single value, not a multi-select
|
||||
|
||||
### UI Component Library
|
||||
- **Always use `antd` for new UI components** — we are migrating off of `@tremor/react`. Do not introduce new `Badge`, `Text`, `Card`, `Grid`, `Title`, or other imports from `@tremor/react` in any new or modified file. Use `antd` equivalents: `Tag` for labels, plain `<span>`/`<div>` with Tailwind classes (or `Typography.Text`) for text, `Card` from `antd`, etc. Note that `antd` has no `"yellow"` Tag color — use `"gold"` for amber/yellow.
|
||||
|
||||
### MCP OAuth / OpenAPI Transport Mapping
|
||||
- `TRANSPORT.OPENAPI` is a UI-only concept. The backend only accepts `"http"`, `"sse"`, or `"stdio"`. Always map it to `"http"` before any API call (including pre-OAuth temp-session calls).
|
||||
- FastAPI validation errors return `detail` as an array of `{loc, msg, type}` objects. Error extractors must handle: array (map `.msg`), string, nested `{error: string}`, and fallback.
|
||||
|
|
@ -151,6 +154,14 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
|
|||
- Optional features enabled via environment variables
|
||||
- Separate licensing and authentication for enterprise features
|
||||
|
||||
### CI Supply-Chain Safety
|
||||
- **Never pipe a remote script into a shell** (`curl ... | bash`, `wget ... | sh`). Download the artifact to a file, verify its SHA-256 checksum, then install.
|
||||
- **Pin every external tool to a specific version** with a full URL (not `latest` or `stable`). Unversioned downloads silently change under you.
|
||||
- **Verify checksums for all downloaded binaries.** Use the provider's official `.sha256` / `.sha256sum` sidecar file when available; otherwise compute and hardcode the digest.
|
||||
- **Prefer reusable CircleCI commands** (`commands:` section) so a tool is installed and verified in exactly one place, then referenced everywhere with `- install_<tool>` or `- wait_for_service`.
|
||||
- **Don't add tools just because they were there before.** Audit whether an external dependency is still needed. If it can be replaced with a shell one-liner or a tool already in the image, remove it.
|
||||
- These rules apply to every download in CI: binaries, install scripts, language version managers, package repos. No exceptions.
|
||||
|
||||
### HTTP Client Cache Safety
|
||||
- **Never close HTTP/SDK clients on cache eviction.** `LLMClientCache._remove_key()` must not call `close()`/`aclose()` on evicted clients — they may still be used by in-flight requests. Doing so causes `RuntimeError: Cannot send a request, as the client has been closed.` after the 1-hour TTL expires. Cleanup happens at shutdown via `close_litellm_async_clients()`.
|
||||
|
||||
|
|
|
|||
|
|
@ -122,9 +122,17 @@ Run all unit tests (uses parallel execution for speed):
|
|||
make test-unit
|
||||
```
|
||||
|
||||
If you're running broader test suites, proxy tests, or anything that touches PostgreSQL-backed fixtures/plugins, install the full local test environment first:
|
||||
|
||||
```bash
|
||||
make install-test-deps
|
||||
```
|
||||
|
||||
This syncs the locked test environment used across the repo, including `psycopg` v3 plus `psycopg-binary` (used by `pytest-postgresql`), `psycopg2-binary` (used by some proxy E2E tests), and a generated Prisma client for DB-backed proxy tests, so pytest startup matches CI without manual package installs.
|
||||
|
||||
Run specific test files:
|
||||
```bash
|
||||
poetry run pytest tests/test_litellm/test_your_file.py -v
|
||||
uv run pytest tests/test_litellm/test_your_file.py -v
|
||||
```
|
||||
|
||||
### Running Linting and Formatting Checks
|
||||
|
|
@ -185,7 +193,7 @@ Run `make help` to see all available commands:
|
|||
make help # Show all available commands
|
||||
make install-dev # Install development dependencies
|
||||
make install-proxy-dev # Install proxy development dependencies
|
||||
make install-test-deps # Install test dependencies (for running tests)
|
||||
make install-test-deps # Install the full local test environment
|
||||
make format # Apply Black code formatting
|
||||
make format-check # Check Black formatting (matches CI)
|
||||
make lint # Run all linting checks
|
||||
|
|
@ -247,7 +255,7 @@ To run the proxy server locally:
|
|||
make install-proxy-dev
|
||||
|
||||
# Start the proxy server
|
||||
poetry run litellm --config your_config.yaml
|
||||
uv run litellm --config your_config.yaml
|
||||
```
|
||||
|
||||
### Docker Development
|
||||
|
|
@ -332,4 +340,4 @@ Looking for ideas? Check out:
|
|||
- 🧪 Test coverage improvements
|
||||
- 🔌 New LLM provider integrations
|
||||
|
||||
Thank you for contributing to LiteLLM! 🚀
|
||||
Thank you for contributing to LiteLLM! 🚀
|
||||
|
|
|
|||
137
Dockerfile
137
Dockerfile
|
|
@ -3,57 +3,75 @@ ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92
|
|||
|
||||
# Runtime image
|
||||
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502
|
||||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
# Builder stage
|
||||
FROM $LITELLM_BUILD_IMAGE AS builder
|
||||
|
||||
# Set the working directory to /app
|
||||
WORKDIR /app
|
||||
|
||||
USER root
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache bash gcc py3-pip python3 python3-dev openssl openssl-dev
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
|
||||
RUN python -m pip install build==1.4.2
|
||||
RUN apk add --no-cache \
|
||||
bash \
|
||||
gcc \
|
||||
python3 \
|
||||
python3-dev \
|
||||
openssl \
|
||||
openssl-dev \
|
||||
nodejs \
|
||||
npm \
|
||||
libsndfile
|
||||
|
||||
# Copy the current directory contents into the container at /app
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy dependency metadata first for layer caching
|
||||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# Copy full source tree
|
||||
COPY . .
|
||||
|
||||
# Build Admin UI
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
# Build Admin UI before final sync
|
||||
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
||||
|
||||
# Build the package
|
||||
RUN rm -rf dist/* && python -m build
|
||||
# Install project and workspace packages (fast - deps already cached)
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# There should be only one wheel file now, assume the build only creates one
|
||||
RUN ls -1 dist/*.whl | head -1
|
||||
RUN prisma generate --schema=./schema.prisma
|
||||
|
||||
# Install the package
|
||||
RUN pip install dist/*.whl
|
||||
|
||||
# install dependencies as wheels
|
||||
RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt
|
||||
|
||||
# ensure pyjwt is used, not jwt
|
||||
RUN pip uninstall jwt -y
|
||||
RUN pip uninstall PyJWT -y
|
||||
RUN pip install PyJWT==2.12.0 --no-cache-dir
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
|
||||
# Runtime stage
|
||||
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
||||
|
||||
# Ensure runtime stage runs as root
|
||||
USER root
|
||||
|
||||
# Install runtime dependencies (libsndfile needed for audio processing on ARM64)
|
||||
RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \
|
||||
RUN apk add --no-cache bash openssl tzdata nodejs npm python3 libsndfile supervisor && \
|
||||
npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
# SECURITY FIX: npm bundles tar, glob, and brace-expansion at multiple nested
|
||||
# levels inside its dependency tree. `npm install -g <pkg>` only creates a
|
||||
# SEPARATE global package, it does NOT replace npm's internal copies.
|
||||
# We must find and replace EVERY copy inside npm's directory.
|
||||
GLOBAL="$(npm root -g)" && \
|
||||
find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
|
|
@ -70,73 +88,24 @@ RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile
|
|||
find "$GLOBAL/npm" -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done && \
|
||||
# SECURITY FIX: patch npm's own package.json metadata so scanners see the
|
||||
# actual installed versions instead of the stale declared dependencies.
|
||||
find /usr/local/lib /usr/lib -path "*/node_modules/npm/package.json" -exec \
|
||||
sed -i 's/"tar": "\^7\.5\.[0-9]*"/"tar": "^7.5.10"/g; s/"minimatch": "\^10\.[0-9.]*"/"minimatch": "^10.2.4"/g' {} + 2>/dev/null && \
|
||||
npm cache clean --force && \
|
||||
# Remove the apk-tracked npm so its stale SBOM metadata (tar 7.5.9) is
|
||||
# no longer visible to image scanners. The globally installed npm@latest
|
||||
# at /usr/local/lib/node_modules/npm/ remains fully functional.
|
||||
{ apk del --no-cache npm 2>/dev/null || true; }
|
||||
|
||||
WORKDIR /app
|
||||
# Copy the current directory contents into the container at /app
|
||||
COPY . .
|
||||
RUN ls -la /app
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy the built wheel from the builder stage to the runtime stage; assumes only one wheel file is present
|
||||
COPY --from=builder /app/dist/*.whl .
|
||||
COPY --from=builder /wheels/ /wheels/
|
||||
COPY --from=builder /app /app
|
||||
|
||||
# Install the built wheel using pip; again using a wildcard if it's the only file
|
||||
RUN pip install *.whl /wheels/* --no-index --find-links=/wheels/ --no-deps && rm -f *.whl && rm -rf /wheels
|
||||
|
||||
# Replace the nodejs-wheel-binaries bundled node with the system node (fixes CVE-2025-55130)
|
||||
RUN NODEJS_WHEEL_NODE=$(find /usr/lib -path "*/nodejs_wheel/bin/node" 2>/dev/null) && \
|
||||
if [ -n "$NODEJS_WHEEL_NODE" ]; then cp /usr/bin/node "$NODEJS_WHEEL_NODE"; fi
|
||||
|
||||
# Remove test files and keys from dependencies
|
||||
RUN find /usr/lib -type f -path "*/tornado/test/*" -delete && \
|
||||
find /usr/lib -type d -path "*/tornado/test" -delete
|
||||
|
||||
# SECURITY FIX: nodejs-wheel-binaries (pip package used by Prisma) bundles a complete
|
||||
# npm with old vulnerable deps at /usr/lib/python3.*/site-packages/nodejs_wheel/.
|
||||
# Patch every copy of tar, glob, and brace-expansion inside that tree.
|
||||
RUN GLOBAL="$(npm root -g)" && \
|
||||
[ -n "$GLOBAL" ] || { echo "ERROR: npm root -g returned empty; aborting"; exit 1; } && \
|
||||
find /usr/lib -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "glob" -path "*/node_modules/glob" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done
|
||||
|
||||
# Install semantic_router and aurelio-sdk using script
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
RUN sed -i 's/\r$//' docker/install_auto_router.sh && chmod +x docker/install_auto_router.sh && ./docker/install_auto_router.sh
|
||||
|
||||
# Generate prisma client using the correct schema
|
||||
RUN prisma generate --schema=./litellm/proxy/schema.prisma
|
||||
# Convert Windows line endings to Unix for entrypoint scripts
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh
|
||||
RUN sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
RUN find /app/.venv -type f -path "*/tornado/test/*" -delete && \
|
||||
find /app/.venv -type d -path "*/tornado/test" -delete
|
||||
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
RUN apk add --no-cache supervisor
|
||||
COPY docker/supervisord.conf /etc/supervisord.conf
|
||||
|
||||
ENTRYPOINT ["docker/prod_entrypoint.sh"]
|
||||
|
||||
# Append "--detailed_debug" to the end of CMD to view detailed debug logs
|
||||
CMD ["--port", "4000"]
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ This file provides guidance to Gemini when working with code in this repository.
|
|||
- `make lint-mypy` - Run MyPy type checking only
|
||||
|
||||
### Single Test Files
|
||||
- `poetry run pytest tests/path/to/test_file.py -v` - Run specific test file
|
||||
- `poetry run pytest tests/path/to/test_file.py::test_function -v` - Run specific test
|
||||
- `uv run pytest tests/path/to/test_file.py -v` - Run specific test file
|
||||
- `uv run pytest tests/path/to/test_file.py::test_function -v` - Run specific test
|
||||
|
||||
### Running Scripts
|
||||
- `poetry run python script.py` - Run Python scripts (use for non-test files)
|
||||
- `uv run python script.py` - Run Python scripts (use for non-test files)
|
||||
|
||||
### GitHub Issue & PR Templates
|
||||
When contributing to the project, use the appropriate templates:
|
||||
|
|
@ -105,4 +105,4 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
|
|||
### Enterprise Features
|
||||
- Enterprise-specific code in `enterprise/` directory
|
||||
- Optional features enabled via environment variables
|
||||
- Separate licensing and authentication for enterprise features
|
||||
- Separate licensing and authentication for enterprise features
|
||||
|
|
|
|||
88
Makefile
88
Makefile
|
|
@ -15,7 +15,7 @@ help:
|
|||
@echo " make install-proxy-dev - Install proxy development dependencies"
|
||||
@echo " make install-dev-ci - Install dev dependencies (CI-compatible, pins OpenAI)"
|
||||
@echo " make install-proxy-dev-ci - Install proxy dev dependencies (CI-compatible)"
|
||||
@echo " make install-test-deps - Install test dependencies"
|
||||
@echo " make install-test-deps - Install the full local test environment"
|
||||
@echo " make install-helm-unittest - Install helm unittest plugin"
|
||||
@echo " make format - Apply Black code formatting"
|
||||
@echo " make format-check - Check Black code formatting (matches CI)"
|
||||
|
|
@ -40,49 +40,44 @@ help:
|
|||
@echo " make test-integration - Run integration tests"
|
||||
@echo " make test-unit-helm - Run helm unit tests"
|
||||
|
||||
# Keep PIP simple for edge cases:
|
||||
PIP := $(shell command -v pip > /dev/null 2>&1 && echo "pip" || echo "python3 -m pip")
|
||||
UV := uv
|
||||
UV_RUN := $(UV) run --no-sync
|
||||
|
||||
# Show info
|
||||
info:
|
||||
@echo "PIP: $(PIP)"
|
||||
@echo "UV: $(UV)"
|
||||
|
||||
# Installation targets
|
||||
install-dev:
|
||||
poetry install --with dev
|
||||
$(UV) sync --frozen
|
||||
|
||||
install-proxy-dev:
|
||||
poetry install --with dev,proxy-dev --extras proxy
|
||||
$(UV) sync --frozen --group proxy-dev --extra proxy
|
||||
|
||||
# CI-compatible installations (matches GitHub workflows exactly)
|
||||
install-dev-ci:
|
||||
$(PIP) install openai==2.8.0
|
||||
poetry install --with dev
|
||||
$(PIP) install openai==2.8.0
|
||||
$(UV) sync --frozen
|
||||
|
||||
install-proxy-dev-ci:
|
||||
poetry install --with dev,proxy-dev --extras proxy
|
||||
$(PIP) install openai==2.8.0
|
||||
$(UV) sync --frozen --group proxy-dev --extra proxy
|
||||
|
||||
install-test-deps: install-proxy-dev
|
||||
poetry run $(PIP) install "pytest-retry==1.6.3"
|
||||
poetry run $(PIP) install pytest-xdist
|
||||
poetry run $(PIP) install openapi-core
|
||||
cd enterprise && poetry run $(PIP) install -e . && cd ..
|
||||
$(UV) sync --frozen --all-groups --all-extras
|
||||
$(UV_RUN) prisma generate --schema litellm/proxy/schema.prisma
|
||||
|
||||
install-helm-unittest:
|
||||
helm plugin install https://github.com/helm-unittest/helm-unittest --version v0.4.4 || echo "ignore error if plugin exists"
|
||||
|
||||
# Formatting
|
||||
format: install-dev
|
||||
cd litellm && poetry run black . && cd ..
|
||||
cd litellm && $(UV_RUN) black . && cd ..
|
||||
|
||||
format-check: install-dev
|
||||
cd litellm && poetry run black --check . && cd ..
|
||||
cd litellm && $(UV_RUN) black --check . && cd ..
|
||||
|
||||
# Linting targets
|
||||
lint-ruff: install-dev
|
||||
cd litellm && poetry run ruff check . && cd ..
|
||||
cd litellm && $(UV_RUN) ruff check . && cd ..
|
||||
|
||||
# faster linter for developing ...
|
||||
# inspiration from:
|
||||
|
|
@ -96,37 +91,36 @@ lint-format-changed: install-dev
|
|||
$$start = $$1; $$count = $$2 || 1; $$end = $$start + $$count - 1; \
|
||||
print "$$file:$$start:1-$$end:999\n"; \
|
||||
}' | \
|
||||
while read range; do \
|
||||
file="$${range%%:*}"; \
|
||||
lines="$${range#*:}"; \
|
||||
echo "Formatting $$file (lines $$lines)"; \
|
||||
poetry run ruff format --range "$$lines" "$$file"; \
|
||||
done
|
||||
while read range; do \
|
||||
file="$${range%%:*}"; \
|
||||
lines="$${range#*:}"; \
|
||||
echo "Formatting $$file (lines $$lines)"; \
|
||||
$(UV_RUN) ruff format --range "$$lines" "$$file"; \
|
||||
done
|
||||
|
||||
lint-ruff-dev: install-dev
|
||||
@tmpfile=$$(mktemp /tmp/ruff-dev.XXXXXX) && \
|
||||
cd litellm && \
|
||||
(poetry run ruff check . --output-format=pylint || true) > "$$tmpfile" && \
|
||||
poetry run diff-quality --violations=pylint "$$tmpfile" --compare-branch=origin/main && \
|
||||
($(UV_RUN) ruff check . --output-format=pylint || true) > "$$tmpfile" && \
|
||||
$(UV_RUN) diff-quality --violations=pylint "$$tmpfile" --compare-branch=origin/main && \
|
||||
cd .. ; \
|
||||
rm -f "$$tmpfile"
|
||||
|
||||
lint-ruff-FULL-dev: install-dev
|
||||
@files=$$(git diff --name-only origin/main -- '*.py'); \
|
||||
if [ -n "$$files" ]; then echo "$$files" | xargs poetry run ruff check; \
|
||||
if [ -n "$$files" ]; then echo "$$files" | xargs $(UV_RUN) ruff check; \
|
||||
else echo "No changed .py files to check."; fi
|
||||
|
||||
lint-mypy: install-dev
|
||||
poetry run $(PIP) install types-requests types-setuptools types-redis types-PyYAML
|
||||
cd litellm && poetry run mypy . --ignore-missing-imports && cd ..
|
||||
cd litellm && $(UV_RUN) mypy . --ignore-missing-imports && cd ..
|
||||
|
||||
lint-black: format-check
|
||||
|
||||
check-circular-imports: install-dev
|
||||
cd litellm && poetry run python ../tests/documentation_tests/test_circular_imports.py && cd ..
|
||||
cd litellm && $(UV_RUN) python ../tests/documentation_tests/test_circular_imports.py && cd ..
|
||||
|
||||
check-import-safety: install-dev
|
||||
@poetry run python -c "from litellm import *; print('[from litellm import *] OK! no issues!');" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
|
||||
@$(UV_RUN) python -c "from litellm import *; print('[from litellm import *] OK! no issues!');" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
|
||||
|
||||
# Combined linting (matches test-linting.yml workflow)
|
||||
lint: format-check lint-ruff lint-mypy check-circular-imports check-import-safety
|
||||
|
|
@ -135,46 +129,46 @@ lint: format-check lint-ruff lint-mypy check-circular-imports check-import-safet
|
|||
lint-dev: lint-format-changed lint-mypy check-circular-imports check-import-safety
|
||||
|
||||
# Testing targets
|
||||
test:
|
||||
poetry run pytest tests/
|
||||
test: install-test-deps
|
||||
$(UV_RUN) pytest tests/
|
||||
|
||||
test-unit: install-test-deps
|
||||
poetry run pytest tests/test_litellm -x -vv -n 4
|
||||
$(UV_RUN) pytest tests/test_litellm -x -vv -n 4
|
||||
|
||||
# Matrix test targets (matching CI workflow groups)
|
||||
test-unit-llms: install-test-deps
|
||||
poetry run pytest tests/test_litellm/llms --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/llms --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-proxy-guardrails: install-test-deps
|
||||
poetry run pytest tests/test_litellm/proxy/guardrails tests/test_litellm/proxy/management_endpoints tests/test_litellm/proxy/management_helpers --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/proxy/guardrails tests/test_litellm/proxy/management_endpoints tests/test_litellm/proxy/management_helpers --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-proxy-core: install-test-deps
|
||||
poetry run pytest tests/test_litellm/proxy/auth tests/test_litellm/proxy/client tests/test_litellm/proxy/db tests/test_litellm/proxy/hooks tests/test_litellm/proxy/policy_engine --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/proxy/auth tests/test_litellm/proxy/client tests/test_litellm/proxy/db tests/test_litellm/proxy/hooks tests/test_litellm/proxy/policy_engine --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-proxy-misc: install-test-deps
|
||||
poetry run pytest tests/test_litellm/proxy/_experimental tests/test_litellm/proxy/agent_endpoints tests/test_litellm/proxy/anthropic_endpoints tests/test_litellm/proxy/common_utils tests/test_litellm/proxy/discovery_endpoints tests/test_litellm/proxy/experimental tests/test_litellm/proxy/google_endpoints tests/test_litellm/proxy/health_endpoints tests/test_litellm/proxy/image_endpoints tests/test_litellm/proxy/middleware tests/test_litellm/proxy/openai_files_endpoint tests/test_litellm/proxy/pass_through_endpoints tests/test_litellm/proxy/prompts tests/test_litellm/proxy/public_endpoints tests/test_litellm/proxy/response_api_endpoints tests/test_litellm/proxy/spend_tracking tests/test_litellm/proxy/ui_crud_endpoints tests/test_litellm/proxy/vector_store_endpoints tests/test_litellm/proxy/test_*.py --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/proxy/_experimental tests/test_litellm/proxy/agent_endpoints tests/test_litellm/proxy/anthropic_endpoints tests/test_litellm/proxy/common_utils tests/test_litellm/proxy/discovery_endpoints tests/test_litellm/proxy/experimental tests/test_litellm/proxy/google_endpoints tests/test_litellm/proxy/health_endpoints tests/test_litellm/proxy/image_endpoints tests/test_litellm/proxy/middleware tests/test_litellm/proxy/openai_files_endpoint tests/test_litellm/proxy/pass_through_endpoints tests/test_litellm/proxy/prompts tests/test_litellm/proxy/public_endpoints tests/test_litellm/proxy/response_api_endpoints tests/test_litellm/proxy/spend_tracking tests/test_litellm/proxy/ui_crud_endpoints tests/test_litellm/proxy/vector_store_endpoints tests/test_litellm/proxy/test_*.py --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-integrations: install-test-deps
|
||||
poetry run pytest tests/test_litellm/integrations --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/integrations --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-core-utils: install-test-deps
|
||||
poetry run pytest tests/test_litellm/litellm_core_utils --tb=short -vv -n 2 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/litellm_core_utils --tb=short -vv -n 2 --durations=20
|
||||
|
||||
test-unit-other: install-test-deps
|
||||
poetry run pytest tests/test_litellm/caching tests/test_litellm/responses tests/test_litellm/secret_managers tests/test_litellm/vector_stores tests/test_litellm/a2a_protocol tests/test_litellm/anthropic_interface tests/test_litellm/completion_extras tests/test_litellm/containers tests/test_litellm/enterprise tests/test_litellm/experimental_mcp_client tests/test_litellm/google_genai tests/test_litellm/images tests/test_litellm/interactions tests/test_litellm/passthrough tests/test_litellm/router_strategy tests/test_litellm/router_utils tests/test_litellm/types --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/caching tests/test_litellm/responses tests/test_litellm/secret_managers tests/test_litellm/vector_stores tests/test_litellm/a2a_protocol tests/test_litellm/anthropic_interface tests/test_litellm/completion_extras tests/test_litellm/containers tests/test_litellm/enterprise tests/test_litellm/experimental_mcp_client tests/test_litellm/google_genai tests/test_litellm/images tests/test_litellm/interactions tests/test_litellm/passthrough tests/test_litellm/router_strategy tests/test_litellm/router_utils tests/test_litellm/types --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-root: install-test-deps
|
||||
poetry run pytest tests/test_litellm/test_*.py --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/test_litellm/test_*.py --tb=short -vv -n 4 --durations=20
|
||||
|
||||
# Proxy unit tests (tests/proxy_unit_tests split alphabetically)
|
||||
test-proxy-unit-a: install-test-deps
|
||||
poetry run pytest tests/proxy_unit_tests/test_[a-o]*.py --tb=short -vv -n 2 --durations=20
|
||||
$(UV_RUN) pytest tests/proxy_unit_tests/test_[a-o]*.py --tb=short -vv -n 2 --durations=20
|
||||
|
||||
test-proxy-unit-b: install-test-deps
|
||||
poetry run pytest tests/proxy_unit_tests/test_[p-z]*.py --tb=short -vv -n 2 --durations=20
|
||||
$(UV_RUN) pytest tests/proxy_unit_tests/test_[p-z]*.py --tb=short -vv -n 2 --durations=20
|
||||
|
||||
test-integration:
|
||||
poetry run pytest tests/ -k "not test_litellm"
|
||||
test-integration: install-test-deps
|
||||
$(UV_RUN) pytest tests/ -k "not test_litellm"
|
||||
|
||||
test-unit-helm: install-helm-unittest
|
||||
helm unittest -f 'tests/*.yaml' deploy/charts/litellm-helm
|
||||
|
|
@ -188,6 +182,6 @@ test-llm-translation-single: install-test-deps
|
|||
@echo "Running single LLM translation test file..."
|
||||
@if [ -z "$(FILE)" ]; then echo "Usage: make test-llm-translation-single FILE=test_filename.py"; exit 1; fi
|
||||
@mkdir -p test-results
|
||||
poetry run pytest tests/llm_translation/$(FILE) \
|
||||
$(UV_RUN) pytest tests/llm_translation/$(FILE) \
|
||||
--junitxml=test-results/junit.xml \
|
||||
-v --tb=short --maxfail=100 --timeout=300
|
||||
|
|
|
|||
161
README.md
161
README.md
|
|
@ -39,8 +39,45 @@
|
|||
|
||||
<img width="2688" height="1600" alt="Group 7154 (1)" src="https://github.com/user-attachments/assets/c5ee0412-6fb5-4fb6-ab5b-bafae4209ca6" />
|
||||
|
||||
---
|
||||
|
||||
## Use LiteLLM for
|
||||
## What is LiteLLM
|
||||
|
||||
LiteLLM is an open source AI Gateway that gives you a single, unified interface to call 100+ LLM providers — OpenAI, Anthropic, Gemini, Bedrock, Azure, and more — using the OpenAI format.
|
||||
|
||||
Use it as a **Python SDK** for direct library integration, or deploy the **AI Gateway (Proxy Server)** as a centralized service for your team or organization.
|
||||
|
||||
[**Jump to LiteLLM Proxy (LLM Gateway) Docs**](https://docs.litellm.ai/docs/simple_proxy) <br>
|
||||
[**Jump to Supported LLM Providers**](https://docs.litellm.ai/docs/providers)
|
||||
|
||||
---
|
||||
|
||||
## Why LiteLLM
|
||||
|
||||
Managing LLM calls across providers gets complicated fast — different SDKs, auth patterns, request formats, and error types for every model. LiteLLM removes that friction:
|
||||
|
||||
- **Unified API** — one interface for 100+ LLMs, no provider-specific SDK juggling
|
||||
- **Drop-in OpenAI compatibility** — swap providers without rewriting your code
|
||||
- **Production-ready gateway** — virtual keys, spend tracking, guardrails, load balancing, and an admin dashboard out of the box
|
||||
- **8ms P95 latency** at 1k RPS ([benchmarks](https://docs.litellm.ai/docs/benchmarks))
|
||||
|
||||
### OSS Adopters
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img height="60" alt="Stripe" src="https://github.com/user-attachments/assets/f7296d4f-9fbd-460d-9d05-e4df31697c4b" /></td>
|
||||
<td><img height="60" alt="image" src="https://github.com/user-attachments/assets/436fca71-988b-40bb-b5fe-8450c80fdbd0" /></td>
|
||||
<td><img height="60" alt="Google ADK" src="https://github.com/user-attachments/assets/caf270a2-5aee-45c4-8222-41a2070c4f19" /></td>
|
||||
<td><img height="60" alt="Greptile" src="https://github.com/user-attachments/assets/0be4bd8a-7cfa-48d3-9090-f415fe948280" /></td>
|
||||
<td><img height="60" alt="OpenHands" src="https://github.com/user-attachments/assets/a6150c4c-149e-4cae-888b-8b92be6e003f" /></td>
|
||||
<td><h2>Netflix</h2></td>
|
||||
<td><img height="60" alt="OpenAI Agents SDK" src="https://github.com/user-attachments/assets/c02f7be0-8c2e-4d27-aea7-7c024bfaebc0" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
<details open>
|
||||
<summary><b>LLMs</b> - Call 100+ LLMs (Python SDK + AI Gateway)</summary>
|
||||
|
|
@ -50,7 +87,7 @@
|
|||
### Python SDK
|
||||
|
||||
```shell
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
```python
|
||||
|
|
@ -72,7 +109,7 @@ response = completion(model="anthropic/claude-sonnet-4-20250514", messages=[{"ro
|
|||
[**Getting Started - E2E Tutorial**](https://docs.litellm.ai/docs/proxy/docker_quick_start) - Setup virtual keys, make your first request
|
||||
|
||||
```shell
|
||||
pip install 'litellm[proxy]'
|
||||
uv tool install 'litellm[proxy]'
|
||||
litellm --model gpt-4o
|
||||
```
|
||||
|
||||
|
|
@ -223,63 +260,7 @@ curl -X POST 'http://0.0.0.0:4000/v1/chat/completions' \
|
|||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## How to use LiteLLM
|
||||
|
||||
You can use LiteLLM through either the Proxy Server or Python SDK. Both gives you a unified interface to access multiple LLMs (100+ LLMs). Choose the option that best fits your needs:
|
||||
|
||||
<table style={{width: '100%', tableLayout: 'fixed'}}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{width: '14%'}}></th>
|
||||
<th style={{width: '43%'}}><strong><a href="https://docs.litellm.ai/docs/simple_proxy">LiteLLM AI Gateway</a></strong></th>
|
||||
<th style={{width: '43%'}}><strong><a href="https://docs.litellm.ai/docs/">LiteLLM Python SDK</a></strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{width: '14%'}}><strong>Use Case</strong></td>
|
||||
<td style={{width: '43%'}}>Central service (LLM Gateway) to access multiple LLMs</td>
|
||||
<td style={{width: '43%'}}>Use LiteLLM directly in your Python code</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{width: '14%'}}><strong>Who Uses It?</strong></td>
|
||||
<td style={{width: '43%'}}>Gen AI Enablement / ML Platform Teams</td>
|
||||
<td style={{width: '43%'}}>Developers building LLM projects</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{width: '14%'}}><strong>Key Features</strong></td>
|
||||
<td style={{width: '43%'}}>Centralized API gateway with authentication and authorization, multi-tenant cost tracking and spend management per project/user, per-project customization (logging, guardrails, caching), virtual keys for secure access control, admin dashboard UI for monitoring and management</td>
|
||||
<td style={{width: '43%'}}>Direct Python library integration in your codebase, Router with retry/fallback logic across multiple deployments (e.g. Azure/OpenAI) - <a href="https://docs.litellm.ai/docs/routing">Router</a>, application-level load balancing and cost tracking, exception handling with OpenAI-compatible errors, observability callbacks (Lunary, MLflow, Langfuse, etc.)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
LiteLLM Performance: **8ms P95 latency** at 1k RPS (See benchmarks [here](https://docs.litellm.ai/docs/benchmarks))
|
||||
|
||||
[**Jump to LiteLLM Proxy (LLM Gateway) Docs**](https://docs.litellm.ai/docs/simple_proxy) <br>
|
||||
[**Jump to Supported LLM Providers**](https://docs.litellm.ai/docs/providers)
|
||||
|
||||
**Stable Release:** Use docker images with the `-stable` tag. These have undergone 12 hour load tests, before being published. [More information about the release cycle here](https://docs.litellm.ai/docs/proxy/release_cycle)
|
||||
|
||||
Support for more providers. Missing a provider or LLM Platform, raise a [feature request](https://github.com/BerriAI/litellm/issues/new?assignees=&labels=enhancement&projects=&template=feature_request.yml&title=%5BFeature%5D%3A+).
|
||||
|
||||
## OSS Adopters
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img height="60" alt="Stripe" src="https://github.com/user-attachments/assets/f7296d4f-9fbd-460d-9d05-e4df31697c4b" /></td>
|
||||
<td><img height="60" alt="image" src="https://github.com/user-attachments/assets/436fca71-988b-40bb-b5fe-8450c80fdbd0" /></td>
|
||||
<td><img height="60" alt="Google ADK" src="https://github.com/user-attachments/assets/caf270a2-5aee-45c4-8222-41a2070c4f19" /></td>
|
||||
<td><img height="60" alt="Greptile" src="https://github.com/user-attachments/assets/0be4bd8a-7cfa-48d3-9090-f415fe948280" /></td>
|
||||
<td><img height="60" alt="OpenHands" src="https://github.com/user-attachments/assets/a6150c4c-149e-4cae-888b-8b92be6e003f" /></td>
|
||||
<td><h2>Netflix</h2></td>
|
||||
<td><img height="60" alt="OpenAI Agents SDK" src="https://github.com/user-attachments/assets/c02f7be0-8c2e-4d27-aea7-7c024bfaebc0" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Supported Providers ([Website Supported Models](https://models.litellm.ai/) | [Docs](https://docs.litellm.ai/docs/providers))
|
||||
### Supported Providers ([Website Supported Models](https://models.litellm.ai/) | [Docs](https://docs.litellm.ai/docs/providers))
|
||||
|
||||
| Provider | `/chat/completions` | `/messages` | `/responses` | `/embeddings` | `/image/generations` | `/audio/transcriptions` | `/audio/speech` | `/moderations` | `/batches` | `/rerank` |
|
||||
|-------------------------------------------------------------------------------------|---------------------|-------------|--------------|---------------|----------------------|-------------------------|-----------------|----------------|-----------|-----------|
|
||||
|
|
@ -386,25 +367,62 @@ Support for more providers. Missing a provider or LLM Platform, raise a [feature
|
|||
|
||||
[**Read the Docs**](https://docs.litellm.ai/docs/)
|
||||
|
||||
## Run in Developer mode
|
||||
### Services
|
||||
---
|
||||
|
||||
## Get Started
|
||||
|
||||
You can use LiteLLM through either the Proxy Server or Python SDK. Both give you a unified interface to access multiple LLMs (100+ LLMs). Choose the option that best fits your needs:
|
||||
|
||||
<table style={{width: '100%', tableLayout: 'fixed'}}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{width: '14%'}}></th>
|
||||
<th style={{width: '43%'}}><strong><a href="https://docs.litellm.ai/docs/simple_proxy">LiteLLM AI Gateway</a></strong></th>
|
||||
<th style={{width: '43%'}}><strong><a href="https://docs.litellm.ai/docs/">LiteLLM Python SDK</a></strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{width: '14%'}}><strong>Use Case</strong></td>
|
||||
<td style={{width: '43%'}}>Central service (LLM Gateway) to access multiple LLMs</td>
|
||||
<td style={{width: '43%'}}>Use LiteLLM directly in your Python code</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{width: '14%'}}><strong>Who Uses It?</strong></td>
|
||||
<td style={{width: '43%'}}>Gen AI Enablement / ML Platform Teams</td>
|
||||
<td style={{width: '43%'}}>Developers building LLM projects</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{width: '14%'}}><strong>Key Features</strong></td>
|
||||
<td style={{width: '43%'}}>Centralized API gateway with authentication and authorization, multi-tenant cost tracking and spend management per project/user, per-project customization (logging, guardrails, caching), virtual keys for secure access control, admin dashboard UI for monitoring and management</td>
|
||||
<td style={{width: '43%'}}>Direct Python library integration in your codebase, Router with retry/fallback logic across multiple deployments (e.g. Azure/OpenAI) - <a href="https://docs.litellm.ai/docs/routing">Router</a>, application-level load balancing and cost tracking, exception handling with OpenAI-compatible errors, observability callbacks (Lunary, MLflow, Langfuse, etc.)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
**Stable Release:** Use docker images with the `-stable` tag. These have undergone 12 hour load tests, before being published. [More information about the release cycle here](https://docs.litellm.ai/docs/proxy/release_cycle)
|
||||
|
||||
Support for more providers. Missing a provider or LLM Platform, raise a [feature request](https://github.com/BerriAI/litellm/issues/new?assignees=&labels=enhancement&projects=&template=feature_request.yml&title=%5BFeature%5D%3A+).
|
||||
|
||||
### Run in Developer Mode
|
||||
#### Services
|
||||
1. Setup .env file in root
|
||||
2. Run dependant services `docker-compose up db prometheus`
|
||||
|
||||
### Backend
|
||||
#### Backend
|
||||
1. (In root) create virtual environment `python -m venv .venv`
|
||||
2. Activate virtual environment `source .venv/bin/activate`
|
||||
3. Install dependencies `pip install -e ".[all]"`
|
||||
4. `pip install prisma`
|
||||
3. Install dependencies `uv sync --all-extras --group proxy-dev`
|
||||
4. `uv run prisma generate`
|
||||
5. `prisma generate`
|
||||
6. Start proxy backend `python litellm/proxy/proxy_cli.py`
|
||||
|
||||
### Frontend
|
||||
#### Frontend
|
||||
1. Navigate to `ui/litellm-dashboard`
|
||||
2. Install dependencies `npm install`
|
||||
3. Run `npm run dev` to start the dashboard
|
||||
|
||||
# Verify Docker Image Signatures
|
||||
### Verify Docker Image Signatures
|
||||
|
||||
All LiteLLM Docker images published to GHCR are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](https://github.com/BerriAI/litellm/commit/0112e53046018d726492c814b3644b7d376029d0).
|
||||
|
||||
|
|
@ -430,6 +448,8 @@ cosign verify \
|
|||
|
||||
Replace `<release-tag>` with the version you are deploying (e.g. `v1.83.0-stable`).
|
||||
|
||||
---
|
||||
|
||||
# Enterprise
|
||||
For companies that need better security, user management and professional support
|
||||
|
||||
|
|
@ -450,7 +470,7 @@ We welcome contributions to LiteLLM! Whether you're fixing bugs, adding features
|
|||
|
||||
## Quick Start for Contributors
|
||||
|
||||
This requires poetry to be installed.
|
||||
This requires uv to be installed.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/BerriAI/litellm.git
|
||||
|
|
@ -486,10 +506,6 @@ All these checks must pass before your PR can be merged.
|
|||
- [Community Slack 💭](https://www.litellm.ai/support)
|
||||
- Our emails ✉️ ishaan@berri.ai / krrish@berri.ai
|
||||
|
||||
# Why did we build this
|
||||
|
||||
- **Need for simplicity**: Our code started to get extremely complicated managing & translating calls between Azure, OpenAI and Cohere.
|
||||
|
||||
# Contributors
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
|
|
@ -504,4 +520,3 @@ All these checks must pass before your PR can be merged.
|
|||
<a href="https://github.com/BerriAI/litellm/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=BerriAI/litellm" />
|
||||
</a>
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
litellm==1.61.15
|
||||
litellm==1.83.5
|
||||
|
|
@ -9,6 +9,32 @@ This document provides comprehensive instructions for AI agents to generate rele
|
|||
3. **Previous Version Commit Hash** - To compare model pricing changes
|
||||
4. **Reference Release Notes** - Use recent stable releases (v1.76.3-stable, v1.77.2-stable) as templates for consistent formatting
|
||||
|
||||
### Resolving Staging PRs
|
||||
|
||||
The GitHub release page (e.g. `https://github.com/BerriAI/litellm/releases/tag/v1.83.3-stable`) does **not** list the real changelog directly. The "What's Changed" section contains **staging PRs** that each bundle many individual commits/PRs. For example:
|
||||
|
||||
- `Litellm oss staging 03 14 2026 by @RheagalFire in #23686`
|
||||
- `Litellm ryan march 16 by @ryan-crabbe in #23822`
|
||||
|
||||
To get the real changelog, you MUST click into each staging PR (e.g. `#23686`, `#23822`), open its **Commits** tab, and extract every underlying commit/PR (look for the `(#NNNNN)` suffix on commit titles). Those underlying PRs — not the staging PRs — are what get categorized in the release notes. Never treat a staging PR title as a single changelog entry.
|
||||
|
||||
**IMPORTANT — staging PRs are not the complete source.** Some PRs land on the release branch *before* the staging PRs and are therefore not reachable via `gh api /pulls/<staging>/commits`. GitHub's auto-generated "What's Changed" on the release page also misses these. To catch every PR in the release, you MUST additionally walk the full git log range between the previous release's commit and this release's commit:
|
||||
|
||||
```bash
|
||||
git fetch origin --tags
|
||||
git log <prev_release_commit>..<this_release_commit> --oneline | grep -oE '#[0-9]+' | sort -u
|
||||
```
|
||||
|
||||
Union the PR set from the staging-PR walk with the PR set from `git log`. Any PR in `git log` but missing from your staging-expanded set is almost certainly a content PR that merged directly to the release branch — fetch its title/body with `gh pr view <N>` and categorize it. Do not trust the GH release body or the staging PRs alone as the authoritative list.
|
||||
|
||||
**Sanity check for new contributors.** The GH release body's "New Contributors" list is a *floor*, not authoritative. For every PR author who appears in the release (including underlying PRs from staging and PRs found only via `git log`), verify whether they are a first-time contributor by running:
|
||||
|
||||
```bash
|
||||
gh api "search/issues?q=is:pr+author:<login>+repo:BerriAI/litellm+is:merged&sort=created&order=asc" --jq '.items[0] | {n:.number, merged:.closed_at}'
|
||||
```
|
||||
|
||||
If the author's earliest merged PR number matches a PR in this release window, they are a new contributor. If their earliest merged PR predates the previous release tag, they are not. Do not copy the GH release body's list blindly — it can both miss contributors (PRs that merged via an older dev branch) and falsely include contributors whose "first" PR in this window was not actually their first ever.
|
||||
|
||||
## Step-by-Step Process
|
||||
|
||||
### 1. Initial Setup and Analysis
|
||||
|
|
|
|||
|
|
@ -3,55 +3,66 @@ ARG LITELLM_BUILD_IMAGE=python:3.11-alpine@sha256:f07e2ace46f560f09a6eeec7b4913b
|
|||
|
||||
# Runtime image
|
||||
ARG LITELLM_RUNTIME_IMAGE=python:3.11-alpine@sha256:f07e2ace46f560f09a6eeec7b4913b80ee99546e749ef82342a419a326620856
|
||||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
# Builder stage
|
||||
FROM $LITELLM_BUILD_IMAGE AS builder
|
||||
|
||||
# Set the working directory to /app
|
||||
WORKDIR /app
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache gcc python3-dev musl-dev
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
|
||||
RUN pip install --upgrade pip==26.0.1 && \
|
||||
pip install build==1.4.2
|
||||
RUN apk add --no-cache gcc python3-dev musl-dev nodejs npm libsndfile
|
||||
|
||||
# Copy the current directory contents into the container at /app
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy dependency metadata first for layer caching
|
||||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# Copy full source tree
|
||||
COPY . .
|
||||
|
||||
# Build the package
|
||||
RUN rm -rf dist/* && python -m build
|
||||
# Install project and workspace packages (fast - deps already cached)
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# There should be only one wheel file now, assume the build only creates one
|
||||
RUN ls -1 dist/*.whl | head -1
|
||||
RUN prisma generate --schema=./schema.prisma
|
||||
|
||||
# Install the package
|
||||
RUN pip install dist/*.whl
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
|
||||
# install dependencies as wheels
|
||||
RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt
|
||||
|
||||
# Runtime stage
|
||||
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
||||
|
||||
# Update dependencies and clean up, install libsndfile for audio processing
|
||||
RUN apk upgrade --no-cache && apk add --no-cache libsndfile
|
||||
RUN apk upgrade --no-cache && apk add --no-cache libsndfile nodejs npm
|
||||
|
||||
WORKDIR /app
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy the built wheel from the builder stage to the runtime stage; assumes only one wheel file is present
|
||||
COPY --from=builder /app/dist/*.whl .
|
||||
COPY --from=builder /wheels/ /wheels/
|
||||
|
||||
# Install the built wheel using pip; again using a wildcard if it's the only file
|
||||
RUN pip install *.whl /wheels/* --no-index --find-links=/wheels/ --no-deps && rm -f *.whl && rm -rf /wheels
|
||||
|
||||
# Convert Windows line endings to Unix for entrypoint scripts
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh
|
||||
RUN sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
COPY --from=builder /app /app
|
||||
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
# Set your entrypoint and command
|
||||
ENTRYPOINT ["docker/prod_entrypoint.sh"]
|
||||
CMD ["--port", "4000"]
|
||||
|
|
|
|||
|
|
@ -3,53 +3,72 @@ ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92
|
|||
|
||||
# Runtime image
|
||||
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502
|
||||
# Builder stage
|
||||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
FROM $LITELLM_BUILD_IMAGE AS builder
|
||||
|
||||
# Set the working directory to /app
|
||||
WORKDIR /app
|
||||
|
||||
USER root
|
||||
|
||||
# Install build dependencies
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
|
||||
RUN apk add --no-cache \
|
||||
bash \
|
||||
gcc \
|
||||
py3-pip \
|
||||
python3 \
|
||||
python3-dev \
|
||||
openssl \
|
||||
openssl-dev
|
||||
openssl-dev \
|
||||
nodejs \
|
||||
npm \
|
||||
libsndfile
|
||||
|
||||
RUN python -m pip install build==1.4.2
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy the current directory contents into the container at /app
|
||||
# Copy dependency metadata first for layer caching
|
||||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# Copy full source tree
|
||||
COPY . .
|
||||
|
||||
# Build Admin UI
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
# Build Admin UI before final sync
|
||||
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
||||
|
||||
# Build the package
|
||||
RUN rm -rf dist/* && python -m build
|
||||
# Install project and workspace packages (fast - deps already cached)
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# There should be only one wheel file now, assume the build only creates one
|
||||
RUN ls -1 dist/*.whl | head -1
|
||||
RUN prisma generate --schema=./schema.prisma
|
||||
|
||||
# Install the package
|
||||
RUN pip install dist/*.whl
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
|
||||
# install dependencies as wheels
|
||||
RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt
|
||||
|
||||
# Runtime stage
|
||||
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
||||
|
||||
# Ensure runtime stage runs as root
|
||||
USER root
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \
|
||||
RUN apk add --no-cache bash openssl tzdata nodejs npm python3 libsndfile supervisor && \
|
||||
npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
GLOBAL="$(npm root -g)" && \
|
||||
find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
|
|
@ -73,66 +92,18 @@ RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile
|
|||
{ apk del --no-cache npm 2>/dev/null || true; }
|
||||
|
||||
WORKDIR /app
|
||||
# Copy the current directory contents into the container at /app
|
||||
COPY . .
|
||||
RUN ls -la /app
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy the built wheel from the builder stage to the runtime stage; assumes only one wheel file is present
|
||||
COPY --from=builder /app/dist/*.whl .
|
||||
COPY --from=builder /wheels/ /wheels/
|
||||
COPY --from=builder /app /app
|
||||
|
||||
# Install the built wheel using pip; again using a wildcard if it's the only file
|
||||
RUN pip install *.whl /wheels/* --no-index --find-links=/wheels/ --no-deps && rm -f *.whl && rm -rf /wheels
|
||||
RUN find /app/.venv -type f -path "*/tornado/test/*" -delete && \
|
||||
find /app/.venv -type d -path "*/tornado/test" -delete
|
||||
|
||||
# SECURITY FIX: nodejs-wheel-binaries (pip package used by Prisma) bundles a complete
|
||||
# npm with old vulnerable deps at /usr/lib/python3.*/site-packages/nodejs_wheel/.
|
||||
# Patch every copy of tar, glob, and brace-expansion inside that tree.
|
||||
RUN GLOBAL="$(npm root -g)" && \
|
||||
[ -n "$GLOBAL" ] || { echo "ERROR: npm root -g returned empty; aborting"; exit 1; } && \
|
||||
find /usr/lib -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "glob" -path "*/node_modules/glob" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done
|
||||
|
||||
# Install semantic_router and aurelio-sdk using script
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
RUN sed -i 's/\r$//' docker/install_auto_router.sh && chmod +x docker/install_auto_router.sh && ./docker/install_auto_router.sh
|
||||
|
||||
# ensure pyjwt is used, not jwt
|
||||
RUN pip uninstall jwt -y
|
||||
RUN pip uninstall PyJWT -y
|
||||
RUN pip install PyJWT==2.12.0 --no-cache-dir
|
||||
|
||||
# Build Admin UI (runtime stage)
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
||||
|
||||
# Generate prisma client
|
||||
RUN prisma generate
|
||||
# Convert Windows line endings to Unix for entrypoint scripts
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh
|
||||
RUN sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
RUN apk add --no-cache supervisor
|
||||
COPY docker/supervisord.conf /etc/supervisord.conf
|
||||
|
||||
# # Set your entrypoint and command
|
||||
|
||||
|
||||
ENTRYPOINT ["docker/prod_entrypoint.sh"]
|
||||
|
||||
# Append "--detailed_debug" to the end of CMD to view detailed debug logs
|
||||
# CMD ["--port", "4000", "--detailed_debug"]
|
||||
CMD ["--port", "4000"]
|
||||
|
|
|
|||
|
|
@ -3,60 +3,70 @@ ARG LITELLM_BUILD_IMAGE=python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973a
|
|||
|
||||
# Runtime image
|
||||
ARG LITELLM_RUNTIME_IMAGE=python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d
|
||||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
# Builder stage
|
||||
FROM $LITELLM_BUILD_IMAGE AS builder
|
||||
|
||||
# Set the working directory to /app
|
||||
WORKDIR /app
|
||||
|
||||
USER root
|
||||
|
||||
# Install build dependencies in one layer
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
g++ \
|
||||
python3-dev \
|
||||
libssl-dev \
|
||||
pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --upgrade pip==26.0.1 build==1.4.2
|
||||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy requirements first for better layer caching
|
||||
COPY requirements.txt .
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Install Python dependencies with cache mount for faster rebuilds
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt
|
||||
# Copy dependency metadata first for layer caching
|
||||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
|
||||
# Fix JWT dependency conflicts early
|
||||
RUN pip uninstall jwt -y || true && \
|
||||
pip uninstall PyJWT -y || true && \
|
||||
pip install PyJWT==2.12.0 --no-cache-dir
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python
|
||||
|
||||
# Copy only necessary files for build
|
||||
COPY pyproject.toml README.md schema.prisma poetry.lock ./
|
||||
COPY litellm/ ./litellm/
|
||||
COPY enterprise/ ./enterprise/
|
||||
COPY docker/ ./docker/
|
||||
# Copy full source tree
|
||||
COPY . .
|
||||
|
||||
# Build Admin UI once
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
# Build Admin UI before final sync
|
||||
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
||||
|
||||
# Build the package
|
||||
RUN rm -rf dist/* && python -m build
|
||||
# Install project and workspace packages (fast - deps already cached)
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python
|
||||
|
||||
# Install the built package
|
||||
RUN pip install dist/*.whl
|
||||
RUN prisma generate --schema=./schema.prisma
|
||||
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
|
||||
# Runtime stage
|
||||
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
||||
|
||||
# Ensure runtime stage runs as root
|
||||
USER root
|
||||
|
||||
# Install only runtime dependencies
|
||||
RUN apt-get update && apt-get upgrade -y \
|
||||
libxml2 \
|
||||
libexpat1 \
|
||||
|
|
@ -72,9 +82,9 @@ RUN apt-get update && apt-get upgrade -y \
|
|||
libc6 \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libssl3 \
|
||||
libatomic1 \
|
||||
nodejs \
|
||||
npm \
|
||||
libatomic1 \
|
||||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \
|
||||
&& GLOBAL="$(npm root -g)" \
|
||||
|
|
@ -99,53 +109,13 @@ RUN apt-get update && apt-get upgrade -y \
|
|||
&& apt-get purge -y npm
|
||||
|
||||
WORKDIR /app
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
# Copy only necessary runtime files
|
||||
COPY docker/entrypoint.sh docker/prod_entrypoint.sh ./docker/
|
||||
COPY litellm/ ./litellm/
|
||||
COPY pyproject.toml README.md schema.prisma poetry.lock ./
|
||||
|
||||
# Copy pre-built wheels and install everything at once
|
||||
COPY --from=builder /wheels/ /wheels/
|
||||
COPY --from=builder /app/dist/*.whl .
|
||||
|
||||
# Install all dependencies in one step with no-cache for smaller image
|
||||
RUN pip install --no-cache-dir *.whl /wheels/* --no-index --find-links=/wheels/ --no-deps && \
|
||||
rm -f *.whl && \
|
||||
rm -rf /wheels
|
||||
|
||||
# SECURITY FIX: nodejs-wheel-binaries (pip package used by Prisma) bundles a complete
|
||||
# npm with old vulnerable deps at /usr/lib/python3.*/site-packages/nodejs_wheel/.
|
||||
# Patch every copy of tar, glob, and brace-expansion inside that tree.
|
||||
RUN GLOBAL="$(npm root -g)" && \
|
||||
[ -n "$GLOBAL" ] || { echo "ERROR: npm root -g returned empty; aborting"; exit 1; } && \
|
||||
find /usr/lib -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "glob" -path "*/node_modules/glob" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done
|
||||
|
||||
# Generate prisma client and set permissions
|
||||
# Convert Windows line endings to Unix for entrypoint scripts
|
||||
RUN prisma generate && \
|
||||
sed -i 's/\r$//' docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && \
|
||||
chmod +x docker/entrypoint.sh && \
|
||||
chmod +x docker/prod_entrypoint.sh
|
||||
COPY --from=builder /app /app
|
||||
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
ENTRYPOINT ["docker/prod_entrypoint.sh"]
|
||||
|
||||
# Append "--detailed_debug" to the end of CMD to view detailed debug logs
|
||||
CMD ["--port", "4000"]
|
||||
CMD ["--port", "4000"]
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
FROM python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy health check script and requirements
|
||||
# Copy the uv binary and the health check script.
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY pyproject.toml uv.lock /app/
|
||||
COPY scripts/health_check/health_check_client.py /app/health_check_client.py
|
||||
COPY scripts/health_check/health_check_requirements.txt /app/requirements.txt
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Make script executable
|
||||
RUN chmod +x /app/health_check_client.py
|
||||
# Resolve and install the health-check dependencies from the project lockfile
|
||||
# so the runtime image stays self-contained and reproducible.
|
||||
RUN uv export --frozen --no-default-groups --only-group healthcheck --no-emit-project --no-hashes --output-file /tmp/health-check-requirements.txt \
|
||||
&& uv pip install --system -r /tmp/health-check-requirements.txt \
|
||||
&& rm /tmp/health-check-requirements.txt \
|
||||
&& rm /app/pyproject.toml /app/uv.lock \
|
||||
&& chmod +x /app/health_check_client.py
|
||||
|
||||
# Run as non-root user
|
||||
RUN groupadd --gid 1000 appuser && useradd --uid 1000 --gid 1000 --no-create-home appuser
|
||||
|
|
|
|||
|
|
@ -2,51 +2,84 @@
|
|||
ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502
|
||||
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502
|
||||
ARG PROXY_EXTRAS_SOURCE=published
|
||||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
# -----------------
|
||||
# Builder Stage
|
||||
# -----------------
|
||||
FROM $LITELLM_BUILD_IMAGE AS builder
|
||||
ARG PROXY_EXTRAS_SOURCE
|
||||
WORKDIR /app
|
||||
USER root
|
||||
|
||||
# Install build dependencies with retry logic (includes node for UI build)
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
|
||||
RUN for i in 1 2 3; do \
|
||||
apk add --no-cache \
|
||||
python3 \
|
||||
python3-dev \
|
||||
py3-pip \
|
||||
clang \
|
||||
llvm \
|
||||
lld \
|
||||
gcc \
|
||||
linux-headers \
|
||||
build-base \
|
||||
bash \
|
||||
nodejs \
|
||||
npm && break || sleep 5; \
|
||||
done \
|
||||
&& pip install --no-cache-dir --upgrade pip==26.0.1 build==1.4.2
|
||||
python3 \
|
||||
python3-dev \
|
||||
clang \
|
||||
llvm \
|
||||
lld \
|
||||
gcc \
|
||||
linux-headers \
|
||||
build-base \
|
||||
bash \
|
||||
coreutils \
|
||||
curl \
|
||||
openssl \
|
||||
openssl-dev \
|
||||
nodejs \
|
||||
npm \
|
||||
libsndfile && break || sleep 5; \
|
||||
done
|
||||
|
||||
# Cache Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt \
|
||||
&& pip wheel --no-cache-dir --wheel-dir=/wheels/ "semantic_router==0.1.11" "aurelio-sdk==0.0.19" "PyJWT==2.12.0"
|
||||
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
NVM_DIR=/root/.nvm \
|
||||
PATH="/root/.nvm/versions/node/v20.20.2/bin:/app/.venv/bin:${PATH}" \
|
||||
LITELLM_NON_ROOT=true \
|
||||
PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
PRISMA_CLI_BINARY_TARGETS="debian-openssl-3.0.x" \
|
||||
XDG_CACHE_HOME=/app/.cache
|
||||
|
||||
# Copy source after dependency layers
|
||||
# Copy dependency metadata first for layer caching
|
||||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3
|
||||
|
||||
# Copy full source tree
|
||||
COPY . .
|
||||
|
||||
# Set non-root flag for build time consistency
|
||||
ENV LITELLM_NON_ROOT=true
|
||||
|
||||
# Build Admin UI using the upstream command order while keeping a single RUN layer
|
||||
# Build Admin UI once and stage the static output for the runtime image.
|
||||
# NOTE: .npmrc files (which may set ignore-scripts=true and min-release-age=3d)
|
||||
# are temporarily renamed during npm install/ci so they don't block lifecycle
|
||||
# scripts needed by the build. This is safe because npm ci installs from
|
||||
# package-lock.json with pinned versions + integrity hashes.
|
||||
RUN mkdir -p /var/lib/litellm/ui && \
|
||||
RUN mkdir -p /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
([ -f /app/.npmrc ] && mv /app/.npmrc /app/.npmrc.bak || true) && \
|
||||
NVM_VERSION="v0.40.4" && \
|
||||
NVM_CHECKSUM="4b7412c49960c7d31e8df72da90c1fb5b8cccb419ac99537b737028d497aba4f" && \
|
||||
NODE_VERSION="v20.20.2" && \
|
||||
NVM_SCRIPT="/tmp/install-nvm.sh" && \
|
||||
curl -fsSL "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" -o "$NVM_SCRIPT" && \
|
||||
echo "${NVM_CHECKSUM} ${NVM_SCRIPT}" | sha256sum -c - && \
|
||||
bash "$NVM_SCRIPT" && \
|
||||
export NVM_DIR="$HOME/.nvm" && \
|
||||
. "$NVM_DIR/nvm.sh" && \
|
||||
nvm install "${NODE_VERSION}" && \
|
||||
nvm use "${NODE_VERSION}" && \
|
||||
npm install -g npm@11.12.1 && \
|
||||
npm install -g node-gyp@12.2.0 && \
|
||||
ln -sf "$(npm root -g)/node-gyp" "$(npm root -g)/npm/node_modules/node-gyp" && \
|
||||
|
|
@ -56,12 +89,11 @@ RUN mkdir -p /var/lib/litellm/ui && \
|
|||
cp /app/enterprise/enterprise_ui/enterprise_colors.json ./ui_colors.json; \
|
||||
fi && \
|
||||
([ -f .npmrc ] && mv .npmrc .npmrc.bak || true) && \
|
||||
npm ci && \
|
||||
npm ci --no-audit --no-fund && \
|
||||
([ -f .npmrc.bak ] && mv .npmrc.bak .npmrc || true) && \
|
||||
([ -f /app/.npmrc.bak ] && mv /app/.npmrc.bak /app/.npmrc || true) && \
|
||||
npm run build && \
|
||||
cp -r /app/ui/litellm-dashboard/out/* /var/lib/litellm/ui/ && \
|
||||
mkdir -p /var/lib/litellm/assets && \
|
||||
cp /app/litellm/proxy/logo.jpg /var/lib/litellm/assets/logo.jpg && \
|
||||
( cd /var/lib/litellm/ui && \
|
||||
for html_file in *.html; do \
|
||||
|
|
@ -74,175 +106,106 @@ RUN mkdir -p /var/lib/litellm/ui && \
|
|||
touch .litellm_ui_ready ) && \
|
||||
cd /app/ui/litellm-dashboard && rm -rf ./out
|
||||
|
||||
# Build litellm wheel and place it in wheels dir (replace any PyPI wheels)
|
||||
RUN rm -rf dist/* && python -m build && \
|
||||
rm -f /wheels/litellm-*.whl && \
|
||||
cp dist/*.whl /wheels/
|
||||
|
||||
# Optionally build local litellm-proxy-extras wheel
|
||||
RUN if [ "$PROXY_EXTRAS_SOURCE" = "local" ]; then \
|
||||
cd /app/litellm-proxy-extras && rm -rf dist && python -m build && \
|
||||
cp dist/*.whl /wheels/; \
|
||||
RUN if [ "$PROXY_EXTRAS_SOURCE" = "published" ]; then \
|
||||
uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3 \
|
||||
--no-sources-package litellm-proxy-extras; \
|
||||
else \
|
||||
uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python3; \
|
||||
fi
|
||||
|
||||
# Pre-cache Prisma binaries in the builder stage
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
PRISMA_CLI_BINARY_TARGETS="debian-openssl-3.0.x" \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PATH="/usr/lib/python3.13/site-packages/nodejs/bin:${PATH}"
|
||||
|
||||
RUN pip install --no-cache-dir prisma==0.11.0 nodejs-wheel-binaries==24.13.1 \
|
||||
&& mkdir -p /app/.cache/npm
|
||||
|
||||
RUN NPM_CONFIG_CACHE=/app/.cache/npm \
|
||||
python -c "import prisma.cli.prisma as p; p.ensure_cached()"
|
||||
|
||||
RUN prisma generate && \
|
||||
RUN mkdir -p /app/.cache/npm && \
|
||||
prisma generate --schema=./schema.prisma && \
|
||||
prisma --version && \
|
||||
prisma migrate diff --from-empty --to-schema-datamodel ./schema.prisma --script > /dev/null 2>&1 || true
|
||||
|
||||
# -----------------
|
||||
# Runtime Stage
|
||||
# -----------------
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
||||
|
||||
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
||||
ARG PROXY_EXTRAS_SOURCE
|
||||
WORKDIR /app
|
||||
USER root
|
||||
|
||||
# Install runtime dependencies with retry
|
||||
RUN for i in 1 2 3; do \
|
||||
apk upgrade --no-cache && break || sleep 5; \
|
||||
done \
|
||||
&& for i in 1 2 3; do \
|
||||
apk add --no-cache python3 py3-pip bash openssl tzdata nodejs npm supervisor && break || sleep 5; \
|
||||
done \
|
||||
&& apk upgrade --no-cache nodejs \
|
||||
&& npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \
|
||||
&& GLOBAL="$(npm root -g)" \
|
||||
&& find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
done \
|
||||
&& find "$GLOBAL/npm" -type d -name "glob" -path "*/node_modules/glob" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \
|
||||
done \
|
||||
&& find "$GLOBAL/npm" -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \
|
||||
done \
|
||||
&& find "$GLOBAL/npm" -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \
|
||||
done \
|
||||
&& find "$GLOBAL/npm" -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done \
|
||||
&& find /usr/local/lib /usr/lib -path "*/node_modules/npm/package.json" -exec \
|
||||
sed -i 's/"tar": "\^7\.5\.[0-9]*"/"tar": "^7.5.10"/g; s/"minimatch": "\^10\.[0-9.]*"/"minimatch": "^10.2.4"/g' {} + 2>/dev/null \
|
||||
&& npm cache clean --force \
|
||||
&& { apk del --no-cache npm 2>/dev/null || true; }
|
||||
done && \
|
||||
for i in 1 2 3; do \
|
||||
apk add --no-cache python3 bash openssl tzdata nodejs npm supervisor libsndfile && break || sleep 5; \
|
||||
done && \
|
||||
apk upgrade --no-cache nodejs && \
|
||||
npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
GLOBAL="$(npm root -g)" && \
|
||||
find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
done && \
|
||||
find "$GLOBAL/npm" -type d -name "glob" -path "*/node_modules/glob" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \
|
||||
done && \
|
||||
find "$GLOBAL/npm" -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \
|
||||
done && \
|
||||
find "$GLOBAL/npm" -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \
|
||||
done && \
|
||||
find "$GLOBAL/npm" -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done && \
|
||||
find /usr/local/lib /usr/lib -path "*/node_modules/npm/package.json" -exec \
|
||||
sed -i 's/"tar": "\^7\.5\.[0-9]*"/"tar": "^7.5.10"/g; s/"minimatch": "\^10\.[0-9.]*"/"minimatch": "^10.2.4"/g' {} + 2>/dev/null && \
|
||||
npm cache clean --force && \
|
||||
{ apk del --no-cache npm 2>/dev/null || true; }
|
||||
|
||||
# Copy artifacts from builder
|
||||
COPY --from=builder /app/requirements.txt /app/requirements.txt
|
||||
COPY --from=builder /app/docker/entrypoint.sh /app/docker/prod_entrypoint.sh /app/docker/
|
||||
COPY --from=builder /app/docker/supervisord.conf /etc/supervisord.conf
|
||||
COPY --from=builder /app/schema.prisma /app/
|
||||
# Keep enterprise bridge module in runtime so `enterprise.enterprise_hooks`
|
||||
# can load and register managed enterprise hooks (e.g. managed_files).
|
||||
COPY --from=builder /app/enterprise /app/enterprise
|
||||
# Copy prisma_migration.py for Helm migrations job compatibility
|
||||
COPY --from=builder /app/litellm/proxy/prisma_migration.py /app/litellm/proxy/prisma_migration.py
|
||||
COPY --from=builder /wheels/ /wheels/
|
||||
COPY --from=builder /app /app
|
||||
COPY --from=builder /var/lib/litellm/ui /var/lib/litellm/ui
|
||||
COPY --from=builder /var/lib/litellm/assets /var/lib/litellm/assets
|
||||
COPY --from=builder /app/.cache /app/.cache
|
||||
COPY --from=builder /app/litellm-proxy-extras /app/litellm-proxy-extras
|
||||
COPY --from=builder \
|
||||
/usr/lib/python3.13/site-packages/nodejs* \
|
||||
/usr/lib/python3.13/site-packages/prisma* \
|
||||
/usr/lib/python3.13/site-packages/tomlkit* \
|
||||
/usr/lib/python3.13/site-packages/nodeenv* \
|
||||
/usr/lib/python3.13/site-packages/
|
||||
COPY --from=builder /usr/bin/prisma /usr/bin/prisma
|
||||
COPY --from=builder /app/docker/supervisord.conf /etc/supervisord.conf
|
||||
|
||||
# Final runtime environment configuration
|
||||
ENV PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
ENV PATH="/app/.venv/bin:${PATH}" \
|
||||
PRISMA_BINARY_CACHE_DIR=/app/.cache/prisma-python/binaries \
|
||||
PRISMA_CLI_BINARY_TARGETS="debian-openssl-3.0.x" \
|
||||
HOME=/app \
|
||||
LITELLM_NON_ROOT=true \
|
||||
XDG_CACHE_HOME=/app/.cache
|
||||
|
||||
# Install packages from wheels and optional extras without network
|
||||
RUN pip install --no-index --find-links=/wheels/ -r requirements.txt && \
|
||||
pip install --no-index --find-links=/wheels/ /wheels/litellm-*-py3-none-any.whl && \
|
||||
pip install --no-index --find-links=/wheels/ --no-deps semantic_router==0.1.11 && \
|
||||
pip install --no-index --find-links=/wheels/ aurelio-sdk==0.0.19 && \
|
||||
if [ "$PROXY_EXTRAS_SOURCE" = "local" ]; then \
|
||||
if ls /wheels/litellm_proxy_extras-*.whl >/dev/null 2>&1; then \
|
||||
pip install --no-index --find-links=/wheels/ /wheels/litellm_proxy_extras-*.whl; \
|
||||
else \
|
||||
echo "litellm_proxy_extras wheel not found; skipping local install"; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
# SECURITY FIX: nodejs-wheel-binaries (pip package used by Prisma) bundles a complete
|
||||
# npm with old vulnerable deps at /usr/lib/python3.*/site-packages/nodejs_wheel/.
|
||||
# Patch every copy of tar, glob, and brace-expansion inside that tree.
|
||||
RUN GLOBAL="$(npm root -g)" && \
|
||||
[ -n "$GLOBAL" ] || { echo "ERROR: npm root -g returned empty; aborting"; exit 1; } && \
|
||||
find /usr/lib -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "glob" -path "*/node_modules/glob" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \
|
||||
done && \
|
||||
find /usr/lib -type d -name "diff" -path "*/node_modules/diff" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \
|
||||
done
|
||||
|
||||
# Permissions, cleanup, and Prisma prep
|
||||
# Convert Windows line endings to Unix for entrypoint scripts
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && \
|
||||
chmod +x docker/entrypoint.sh docker/prod_entrypoint.sh && \
|
||||
mkdir -p /nonexistent /.npm /var/lib/litellm/assets /var/lib/litellm/ui && \
|
||||
chown -R nobody:nogroup /app /var/lib/litellm/ui /var/lib/litellm/assets /nonexistent /.npm && \
|
||||
pip uninstall jwt -y || true && \
|
||||
pip uninstall PyJWT -y || true && \
|
||||
pip install --no-index --find-links=/wheels/ PyJWT==2.12.0 --no-cache-dir && \
|
||||
rm -rf /wheels && \
|
||||
PRISMA_PATH=$(python -c "import os, prisma; print(os.path.dirname(prisma.__file__))") && \
|
||||
chown -R nobody:nogroup $PRISMA_PATH && \
|
||||
LITELLM_PKG_MIGRATIONS_PATH="$(python -c 'import os, litellm_proxy_extras; print(os.path.dirname(litellm_proxy_extras.__file__))' 2>/dev/null || echo '')/migrations" && \
|
||||
[ -n "$LITELLM_PKG_MIGRATIONS_PATH" ] && chown -R nobody:nogroup $LITELLM_PKG_MIGRATIONS_PATH && \
|
||||
LITELLM_PROXY_EXTRAS_PATH=$(python -c "import os, litellm_proxy_extras; print(os.path.dirname(litellm_proxy_extras.__file__))" 2>/dev/null || echo "") && \
|
||||
chgrp -R 0 $PRISMA_PATH /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chgrp -R 0 $LITELLM_PROXY_EXTRAS_PATH || true && \
|
||||
chmod -R g=u $PRISMA_PATH /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g=u $LITELLM_PROXY_EXTRAS_PATH || true && \
|
||||
chmod -R g+w $PRISMA_PATH /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g+w $LITELLM_PROXY_EXTRAS_PATH || true && \
|
||||
chmod -R g+rX $PRISMA_PATH && \
|
||||
chmod -R g+rX /app/.cache && \
|
||||
mkdir -p /tmp/.npm /nonexistent /.npm
|
||||
|
||||
# Switch to non-root user for runtime
|
||||
USER nobody
|
||||
|
||||
# Generate Prisma client as nobody user to ensure correct file ownership
|
||||
RUN prisma generate
|
||||
|
||||
# Prisma runtime knobs for offline containers
|
||||
ENV PRISMA_SKIP_POSTINSTALL_GENERATE=1 \
|
||||
XDG_CACHE_HOME=/app/.cache \
|
||||
PRISMA_SKIP_POSTINSTALL_GENERATE=1 \
|
||||
PRISMA_HIDE_UPDATE_MESSAGE=1 \
|
||||
PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1 \
|
||||
NPM_CONFIG_CACHE=/app/.cache/npm \
|
||||
NPM_CONFIG_PREFER_OFFLINE=true \
|
||||
PRISMA_OFFLINE_MODE=true
|
||||
|
||||
RUN sed -i 's/\r$//' docker/entrypoint.sh && \
|
||||
sed -i 's/\r$//' docker/prod_entrypoint.sh && \
|
||||
chmod +x docker/entrypoint.sh docker/prod_entrypoint.sh && \
|
||||
mkdir -p /nonexistent /.npm /var/lib/litellm/assets /var/lib/litellm/ui /tmp/.npm && \
|
||||
chown -R nobody:nogroup /app /var/lib/litellm/ui /var/lib/litellm/assets /nonexistent /.npm /tmp/.npm && \
|
||||
PRISMA_PATH=$(python -c "import os, prisma; print(os.path.dirname(prisma.__file__))") && \
|
||||
chown -R nobody:nogroup "$PRISMA_PATH" && \
|
||||
LITELLM_PKG_MIGRATIONS_PATH="$(python -c 'import os, litellm_proxy_extras; print(os.path.dirname(litellm_proxy_extras.__file__))' 2>/dev/null || echo '')/migrations" && \
|
||||
[ -n "$LITELLM_PKG_MIGRATIONS_PATH" ] && chown -R nobody:nogroup "$LITELLM_PKG_MIGRATIONS_PATH" || true && \
|
||||
LITELLM_PROXY_EXTRAS_PATH=$(python -c "import os, litellm_proxy_extras; print(os.path.dirname(litellm_proxy_extras.__file__))" 2>/dev/null || echo "") && \
|
||||
chgrp -R 0 "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chgrp -R 0 "$LITELLM_PROXY_EXTRAS_PATH" || true && \
|
||||
chmod -R g=u "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g=u "$LITELLM_PROXY_EXTRAS_PATH" || true && \
|
||||
chmod -R g+w "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
||||
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g+w "$LITELLM_PROXY_EXTRAS_PATH" || true && \
|
||||
chmod -R g+rX "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets /app/.cache
|
||||
|
||||
USER nobody
|
||||
|
||||
RUN prisma generate --schema=./schema.prisma
|
||||
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
ENTRYPOINT ["/app/docker/prod_entrypoint.sh"]
|
||||
CMD ["--port", "4000"]
|
||||
|
|
|
|||
|
|
@ -1,27 +1,53 @@
|
|||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9@sha256:10902f58a1606787602f303954cea099626a4adb02acbac4c69920fe9d278f82
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
FROM python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d
|
||||
|
||||
ARG LITELLM_VERSION=1.83.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV HOME=/home/litellm
|
||||
ENV PATH="${HOME}/venv/bin:$PATH"
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
|
||||
# Install runtime dependencies needed for building native extensions
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends gcc libffi-dev && \
|
||||
apt-get install -y --no-install-recommends gcc libffi-dev nodejs npm && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN python -m venv ${HOME}/venv
|
||||
RUN ${HOME}/venv/bin/pip install --no-cache-dir --upgrade pip==26.0.1
|
||||
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
COPY docker/build_from_pip/requirements.txt .
|
||||
RUN --mount=type=cache,target=${HOME}/.cache/pip \
|
||||
${HOME}/venv/bin/pip install -r requirements.txt
|
||||
|
||||
# Copy Prisma schema file
|
||||
COPY schema.prisma .
|
||||
|
||||
# Generate prisma client
|
||||
RUN prisma generate
|
||||
# This image is specifically for validating/installing the published PyPI
|
||||
# artifact, not the checked-out source tree.
|
||||
# Keep the moved proxy-runtime packages explicit until the published PyPI
|
||||
# artifact includes that extra; newer releases will simply dedupe these.
|
||||
RUN uv venv --python python && \
|
||||
uv pip install --python /app/.venv/bin/python \
|
||||
"litellm[proxy,proxy-runtime]==${LITELLM_VERSION}" \
|
||||
"google-cloud-aiplatform==1.133.0" \
|
||||
"google-genai==1.37.0" \
|
||||
"anthropic[vertex]==0.84.0" \
|
||||
"grpcio==1.78.0" \
|
||||
"prometheus-client==0.20.0" \
|
||||
"langfuse==2.59.7" \
|
||||
"opentelemetry-api==1.28.0" \
|
||||
"opentelemetry-sdk==1.28.0" \
|
||||
"opentelemetry-exporter-otlp==1.28.0" \
|
||||
"ddtrace==2.19.0" \
|
||||
"sentry-sdk==2.21.0" \
|
||||
"mangum==0.17.0" \
|
||||
"azure-ai-contentsafety==1.0.0" \
|
||||
"azure-storage-file-datalake==12.20.0" \
|
||||
"pypdf==6.7.5" \
|
||||
"llm-sandbox==0.3.31" \
|
||||
"detect-secrets==1.5.0" \
|
||||
"prisma==0.11.0" \
|
||||
"openai==2.24.0"
|
||||
|
||||
RUN prisma generate --schema=./schema.prisma
|
||||
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
litellm[proxy]==1.83.0
|
||||
prometheus_client==0.20.0
|
||||
langfuse==2.59.7
|
||||
prisma==0.11.0
|
||||
openai==2.24.0
|
||||
ddtrace==2.19.0 # for advanced DD tracing / profiling
|
||||
|
|
@ -1,13 +1,16 @@
|
|||
#!/bin/bash
|
||||
echo $(pwd)
|
||||
set -euo pipefail
|
||||
|
||||
# Run the Python migration script
|
||||
python3 litellm/proxy/prisma_migration.py
|
||||
REPO_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
VENV_PYTHON="$REPO_ROOT/.venv/bin/python"
|
||||
MIGRATION_SCRIPT="$REPO_ROOT/litellm/proxy/prisma_migration.py"
|
||||
|
||||
# Check if the Python script executed successfully
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Migration script ran successfully!"
|
||||
if [ -x "$VENV_PYTHON" ]; then
|
||||
"$VENV_PYTHON" "$MIGRATION_SCRIPT"
|
||||
elif command -v uv >/dev/null 2>&1; then
|
||||
(cd "$REPO_ROOT" && uv run --no-sync python "$MIGRATION_SCRIPT")
|
||||
else
|
||||
echo "Migration script failed!"
|
||||
exit 1
|
||||
python3 "$MIGRATION_SCRIPT"
|
||||
fi
|
||||
|
||||
echo "Migration script ran successfully!"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#!/bin/bash
|
||||
pip install semantic_router==0.1.11 --no-deps
|
||||
pip install aurelio-sdk==0.0.19 --no-deps
|
||||
set -euo pipefail
|
||||
|
||||
# semantic-router dependencies are installed via `uv sync`.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,32 @@
|
|||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.10.9
|
||||
|
||||
FROM $UV_IMAGE AS uvbin
|
||||
|
||||
FROM python:3.14.0a3-slim
|
||||
|
||||
COPY --from=uvbin /uv /usr/local/bin/uv
|
||||
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
||||
UV_LINK_MODE=copy \
|
||||
PATH="/app/.venv/bin:${PATH}"
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
python3-dev \
|
||||
libssl-dev \
|
||||
pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--extra extra_proxy \
|
||||
--extra semantic-router \
|
||||
--python python
|
||||
|
||||
EXPOSE $PORT
|
||||
|
||||
CMD litellm --host 0.0.0.0 --port $PORT --workers 10 --config config.yaml
|
||||
CMD ["sh", "-c", "litellm --host 0.0.0.0 --port $PORT --workers 10 --config config.yaml"]
|
||||
|
|
|
|||
366
docs/my-website/blog/claude_opus_4_7/index.md
Normal file
366
docs/my-website/blog/claude_opus_4_7/index.md
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
---
|
||||
slug: claude_opus_4_7
|
||||
title: "Day 0 Support: Claude Opus 4.7"
|
||||
date: 2026-04-16T10:00:00
|
||||
authors:
|
||||
- sameer
|
||||
- ishaan-alt
|
||||
- krrish
|
||||
description: "Day 0 support for Claude Opus 4.7 on LiteLLM AI Gateway - use across Anthropic, Azure, Vertex AI, and Bedrock."
|
||||
tags: [anthropic, claude, opus 4.7]
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
LiteLLM now supports [Claude Opus 4.7](https://www.anthropic.com/news/claude-opus-4-7) on Day 0. Use it across Anthropic, Azure, Vertex AI, and Bedrock through the LiteLLM AI Gateway.
|
||||
|
||||
{/* truncate */}
|
||||
|
||||
## Docker Image
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/berriai/litellm:litellm_stable_release_branch-v1.83.3-stable.opus-4.7
|
||||
```
|
||||
|
||||
## Usage - Anthropic
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="proxy" label="LiteLLM Proxy">
|
||||
|
||||
**1. Setup config.yaml**
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: claude-opus-4-7
|
||||
litellm_params:
|
||||
model: anthropic/claude-opus-4-7
|
||||
api_key: os.environ/ANTHROPIC_API_KEY
|
||||
```
|
||||
|
||||
**2. Start the proxy**
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 4000:4000 \
|
||||
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||
ghcr.io/berriai/litellm:litellm_stable_release_branch-v1.83.3-stable.opus-4.7 \
|
||||
--config /app/config.yaml
|
||||
```
|
||||
|
||||
**3. Test it!**
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer $LITELLM_KEY' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "what llm are you"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Usage - Azure
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="proxy" label="LiteLLM Proxy">
|
||||
|
||||
**1. Setup config.yaml**
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: claude-opus-4-7
|
||||
litellm_params:
|
||||
model: azure_ai/claude-opus-4-7
|
||||
api_key: os.environ/AZURE_AI_API_KEY
|
||||
api_base: os.environ/AZURE_AI_API_BASE # https://<resource>.services.ai.azure.com
|
||||
```
|
||||
|
||||
**2. Start the proxy**
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 4000:4000 \
|
||||
-e AZURE_AI_API_KEY=$AZURE_AI_API_KEY \
|
||||
-e AZURE_AI_API_BASE=$AZURE_AI_API_BASE \
|
||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||
ghcr.io/berriai/litellm:litellm_stable_release_branch-v1.83.3-stable.opus-4.7 \
|
||||
--config /app/config.yaml
|
||||
```
|
||||
|
||||
**3. Test it!**
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer $LITELLM_KEY' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "what llm are you"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Usage - Vertex AI
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="proxy" label="LiteLLM Proxy">
|
||||
|
||||
**1. Setup config.yaml**
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: claude-opus-4-7
|
||||
litellm_params:
|
||||
model: vertex_ai/claude-opus-4-7
|
||||
vertex_project: os.environ/VERTEX_PROJECT
|
||||
vertex_location: us-east5
|
||||
```
|
||||
|
||||
**2. Start the proxy**
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 4000:4000 \
|
||||
-e VERTEX_PROJECT=$VERTEX_PROJECT \
|
||||
-e GOOGLE_APPLICATION_CREDENTIALS=/app/credentials.json \
|
||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||
-v $(pwd)/credentials.json:/app/credentials.json \
|
||||
ghcr.io/berriai/litellm:litellm_stable_release_branch-v1.83.3-stable.opus-4.7 \
|
||||
--config /app/config.yaml
|
||||
```
|
||||
|
||||
**3. Test it!**
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer $LITELLM_KEY' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "what llm are you"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Usage - Bedrock
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="proxy" label="LiteLLM Proxy">
|
||||
|
||||
**1. Setup config.yaml**
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: claude-opus-4-7
|
||||
litellm_params:
|
||||
model: bedrock/anthropic.claude-opus-4-7
|
||||
aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY
|
||||
aws_region_name: us-east-1
|
||||
```
|
||||
|
||||
**2. Start the proxy**
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 4000:4000 \
|
||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||
ghcr.io/berriai/litellm:litellm_stable_release_branch-v1.83.3-stable.opus-4.7 \
|
||||
--config /app/config.yaml
|
||||
```
|
||||
|
||||
**3. Test it!**
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer $LITELLM_KEY' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "what llm are you"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Adaptive Thinking
|
||||
|
||||
:::note
|
||||
When using `reasoning_effort` with Claude Opus 4.7, all values (`low`, `medium`, `high`, `xhigh`) are mapped to `thinking: {type: "adaptive"}`. To use explicit thinking budgets with `type: "enabled"`, pass the native `thinking` parameter directly.
|
||||
:::
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="completions" label="/chat/completions">
|
||||
|
||||
LiteLLM supports adaptive thinking through the `reasoning_effort` parameter:
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer $LITELLM_KEY' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Solve this complex problem: What is the optimal strategy for..."
|
||||
}
|
||||
],
|
||||
"reasoning_effort": "high"
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="messages" label="/v1/messages">
|
||||
|
||||
Use the `thinking` parameter with `type: "adaptive"` to enable adaptive thinking mode:
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/v1/messages' \
|
||||
--header 'x-api-key: sk-12345' \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"max_tokens": 16000,
|
||||
"thinking": {
|
||||
"type": "adaptive"
|
||||
},
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Explain why the sum of two even numbers is always even."
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Effort Levels
|
||||
|
||||
Claude Opus 4.7 supports four effort levels: `low`, `medium`, `high` (default), and `xhigh`. These give you finer-grained control over how much reasoning the model applies to a task. Pass the effort level via the `output_config` parameter.
|
||||
|
||||
`xhigh` is a new effort level introduced with Opus 4.7 that sits above `high`. The `max` effort level is Claude Opus 4.6 only and is not available on 4.7.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="completions" label="/chat/completions">
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer $LITELLM_KEY' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Explain quantum computing"
|
||||
}
|
||||
],
|
||||
"output_config": {
|
||||
"effort": "xhigh"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**Using OpenAI SDK:**
|
||||
|
||||
```python
|
||||
import openai
|
||||
|
||||
client = openai.OpenAI(
|
||||
api_key="your-litellm-key",
|
||||
base_url="http://0.0.0.0:4000"
|
||||
)
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model="claude-opus-4-7",
|
||||
messages=[{"role": "user", "content": "Explain quantum computing"}],
|
||||
extra_body={"output_config": {"effort": "xhigh"}}
|
||||
)
|
||||
```
|
||||
|
||||
**Using LiteLLM SDK:**
|
||||
|
||||
```python
|
||||
from litellm import completion
|
||||
|
||||
response = completion(
|
||||
model="anthropic/claude-opus-4-7",
|
||||
messages=[{"role": "user", "content": "Explain quantum computing"}],
|
||||
output_config={"effort": "xhigh"},
|
||||
)
|
||||
```
|
||||
|
||||
You can combine `reasoning_effort` with `output_config` for even more fine-grained control over the model's behavior.
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="messages" label="/v1/messages">
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/v1/messages' \
|
||||
--header 'x-api-key: sk-12345' \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{
|
||||
"model": "claude-opus-4-7",
|
||||
"max_tokens": 4096,
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Explain quantum computing"
|
||||
}
|
||||
],
|
||||
"output_config": {
|
||||
"effort": "xhigh"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**Effort level guide:**
|
||||
|
||||
| Effort | When to use |
|
||||
|--------|-------------|
|
||||
| `low` | Short, fast responses — simple lookups, formatting, classification |
|
||||
| `medium` | Balanced tradeoff for everyday Q&A and light reasoning |
|
||||
| `high` (default) | Complex reasoning, code generation, analysis |
|
||||
| `xhigh` | Hardest problems — multi-step math, deep research, agentic planning |
|
||||
|
||||
|
|
@ -378,7 +378,7 @@ if __name__ == "__main__":
|
|||
|
||||
1. Install dependencies:
|
||||
```bash
|
||||
pip install fastapi uvicorn
|
||||
uv add fastapi uvicorn
|
||||
```
|
||||
|
||||
2. Save the code above to `prompt_server.py`
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import TabItem from '@theme/TabItem';
|
|||
|
||||
Install redis
|
||||
```shell
|
||||
pip install redis
|
||||
uv add redis
|
||||
```
|
||||
|
||||
For the hosted version you can setup your own Redis DB here: https://redis.io/try-free/
|
||||
|
|
@ -55,7 +55,7 @@ response2 = completion(
|
|||
For GCP Memorystore Redis with IAM authentication:
|
||||
|
||||
```shell
|
||||
pip install google-cloud-iam
|
||||
uv add google-cloud-iam
|
||||
```
|
||||
|
||||
```python
|
||||
|
|
@ -150,7 +150,7 @@ response2 = completion(
|
|||
|
||||
Install boto3
|
||||
```shell
|
||||
pip install boto3
|
||||
uv add boto3
|
||||
```
|
||||
|
||||
Set AWS environment variables
|
||||
|
|
@ -187,7 +187,7 @@ response2 = completion(
|
|||
|
||||
Install azure-storage-blob and azure-identity
|
||||
```shell
|
||||
pip install azure-storage-blob azure-identity
|
||||
uv add azure-storage-blob azure-identity
|
||||
```
|
||||
|
||||
```python
|
||||
|
|
@ -219,7 +219,7 @@ response2 = completion(
|
|||
|
||||
Install redisvl client
|
||||
```shell
|
||||
pip install redisvl==0.4.1
|
||||
uv add redisvl==0.4.1
|
||||
```
|
||||
|
||||
For the hosted version you can setup your own Redis DB here: https://redis.io/try-free/
|
||||
|
|
@ -366,7 +366,7 @@ response2 = completion(
|
|||
Install the disk caching extra:
|
||||
|
||||
```shell
|
||||
pip install "litellm[caching]"
|
||||
uv add "litellm[caching]"
|
||||
```
|
||||
|
||||
Then you can use the disk cache as follows.
|
||||
|
|
|
|||
|
|
@ -14,12 +14,48 @@ The advisor tool is in beta. Include `anthropic-beta: advisor-tool-2026-03-01` i
|
|||
|
||||
## Supported Providers
|
||||
|
||||
| Provider | Chat Completions API | Messages API |
|
||||
|----------|---------------------|--------------|
|
||||
| **Anthropic API** | ✅ | ✅ |
|
||||
| **Azure Anthropic** | ❌ (coming soon) | ❌ (coming soon) |
|
||||
| **Google Cloud Vertex AI** | ❌ (coming soon) | ❌ (coming soon) |
|
||||
| **Amazon Bedrock** | ❌ (coming soon) | ❌ (coming soon) |
|
||||
| Provider | Chat Completions API | Messages API | Notes |
|
||||
|----------|---------------------|--------------|-------|
|
||||
| **Anthropic API** | ✅ | ✅ | Native — runs server-side |
|
||||
| **OpenAI / Azure OpenAI** | ✅ | ✅ | LiteLLM orchestration loop |
|
||||
| **Amazon Bedrock** | ✅ | ✅ | LiteLLM orchestration loop |
|
||||
| **Google Vertex AI** | ✅ | ✅ | LiteLLM orchestration loop |
|
||||
| **Groq / Mistral / others** | ✅ | ✅ | LiteLLM orchestration loop |
|
||||
|
||||
## How it works (LiteLLM native orchestration)
|
||||
|
||||
For non-Anthropic providers, LiteLLM implements the advisor loop itself. The API you call is identical — LiteLLM handles everything transparently.
|
||||
|
||||
When a request arrives with an `advisor_20260301` tool and a non-Anthropic provider, `AdvisorOrchestrationHandler` intercepts it. It translates the advisor tool into a regular function tool the provider understands, then runs an orchestration loop:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["Your request\ntools: advisor_20260301\nmodel: e.g. openai/gpt-4.1-mini"] --> B["AdvisorOrchestrationHandler\ntranslates advisor → regular fn tool"]
|
||||
|
||||
B --> C["EXECUTOR CALL\nopenai / bedrock / vertex / etc."]
|
||||
|
||||
C --> D{"executor calls\nadvisor tool?"}
|
||||
|
||||
D -->|"yes — tool_use\nname=advisor"| E{"max_uses\nexceeded?"}
|
||||
|
||||
E -->|no| F["ADVISOR SUB-CALL\nclaude-opus-4-6\nfull transcript forwarded\nno tools"]
|
||||
|
||||
F --> G["Inject advice as\ntool_result into history"]
|
||||
|
||||
G --> C
|
||||
|
||||
E -->|yes| H["AdvisorMaxIterationsError"]
|
||||
|
||||
D -->|"no — end_turn\nor other stop reason"| I["Clean final response\nno advisor blocks in output"]
|
||||
```
|
||||
|
||||
**What LiteLLM does for you:**
|
||||
|
||||
- Strips `advisor_20260301` from the outgoing request — the provider only sees a standard function tool named `advisor`
|
||||
- When the executor calls it, intercepts before the result reaches you, runs the advisor sub-call, and injects the advice
|
||||
- Strips any `advisor_tool_result` / `server_tool_use` blocks from message history on re-send so non-Anthropic providers never see Anthropic-specific types
|
||||
- Wraps the final response in an SSE stream if you requested `stream=True`
|
||||
- Enforces `max_uses` as a hard cap — `AdvisorMaxIterationsError` is raised if exceeded; `max_uses=0` disables the advisor entirely
|
||||
|
||||
## Model Compatibility
|
||||
|
||||
|
|
@ -305,6 +341,37 @@ response = client.beta.messages.create(
|
|||
print(response)
|
||||
```
|
||||
|
||||
#### Non-Anthropic Provider (LiteLLM orchestration loop)
|
||||
|
||||
```python showLineNumbers title="Advisor Tool with OpenAI executor"
|
||||
import asyncio
|
||||
import litellm
|
||||
|
||||
async def main():
|
||||
# executor: openai/gpt-4.1-mini | advisor: claude-opus-4-6
|
||||
# LiteLLM runs the orchestration loop automatically
|
||||
response = await litellm.anthropic.messages.acreate(
|
||||
model="openai/gpt-4.1-mini",
|
||||
messages=[
|
||||
{"role": "user", "content": "Implement a Python LRU cache with O(1) get and put."}
|
||||
],
|
||||
tools=[
|
||||
{
|
||||
"type": "advisor_20260301",
|
||||
"name": "advisor",
|
||||
"model": "claude-opus-4-6",
|
||||
"max_uses": 3,
|
||||
}
|
||||
],
|
||||
max_tokens=1024,
|
||||
custom_llm_provider="openai",
|
||||
)
|
||||
# Final response is clean — no advisor tool_use blocks
|
||||
print(response["content"][0]["text"])
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Response Structure
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ response = litellm.completion(
|
|||
|
||||
3. Ensure you're using a recent version of LiteLLM:
|
||||
```bash
|
||||
pip install --upgrade litellm
|
||||
uv add --upgrade-package litellm litellm
|
||||
```
|
||||
|
||||
### Unexpected Dummy Tool Results
|
||||
|
|
|
|||
123
docs/my-website/docs/completion/prompt_compression.md
Normal file
123
docs/my-website/docs/completion/prompt_compression.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# Prompt Compression (`compress()`)
|
||||
|
||||
Use `litellm.compress()` to shrink long conversation history before calling `completion()`.
|
||||
|
||||
The function keeps high-relevance and recent context, replaces low-relevance content with lightweight stubs, and returns a retrieval tool so the model can request full content only when needed.
|
||||
|
||||
## Quickstart
|
||||
|
||||
```python
|
||||
import litellm
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a coding assistant."},
|
||||
{"role": "user", "content": "# auth.py\n" + "def authenticate():\n pass\n" * 2000},
|
||||
{"role": "user", "content": "# utils.py\n" + "def helper():\n pass\n" * 2000},
|
||||
{"role": "user", "content": "Fix the bug in auth.py"},
|
||||
]
|
||||
|
||||
compressed = litellm.compress(
|
||||
messages=messages,
|
||||
model="gpt-4o",
|
||||
compression_trigger=1000,
|
||||
compression_target=500,
|
||||
)
|
||||
|
||||
response = litellm.completion(
|
||||
model="gpt-4o",
|
||||
messages=compressed["messages"],
|
||||
tools=compressed["tools"],
|
||||
)
|
||||
```
|
||||
|
||||
## What It Returns
|
||||
|
||||
`compress()` returns a dictionary with:
|
||||
|
||||
- `messages`: compressed conversation messages
|
||||
- `original_tokens`: token count before compression
|
||||
- `compressed_tokens`: token count after compression
|
||||
- `compression_ratio`: fraction of tokens removed
|
||||
- `cache`: key-value mapping of stub key -> original full content
|
||||
- `tools`: retrieval tool definition (`litellm_content_retrieve`) for on-demand restoration
|
||||
|
||||
## Parameters
|
||||
|
||||
- `messages` (`List[dict]`, required): input conversation messages
|
||||
- `model` (`str`, required): model name used for token counting
|
||||
- `compression_trigger` (`int`, default `200000`): compress only if input token count exceeds this
|
||||
- `compression_target` (`Optional[int]`, default `70% of compression_trigger`): desired post-compression token budget
|
||||
- `embedding_model` (`Optional[str]`): if set, combines BM25 + embedding relevance scoring
|
||||
- `embedding_model_params` (`Optional[dict]`): additional kwargs passed to `litellm.embedding()`
|
||||
- `compression_cache` (`Optional[DualCache]`): optional cache used by embedding scoring
|
||||
|
||||
## Behavior Notes
|
||||
|
||||
- Messages below `compression_trigger` are passed through unchanged.
|
||||
- System messages, the last user message, and the last assistant message are always preserved.
|
||||
- If a relevant message does not fully fit the remaining budget, `compress()` may keep a truncated version of it.
|
||||
- Compressed-out content is never lost; it is stored in `cache` and addressable by `litellm_content_retrieve`.
|
||||
|
||||
## Handling Retrieval Tool Calls
|
||||
|
||||
If the model calls `litellm_content_retrieve`, look up the requested key in `compressed["cache"]` and return that value as tool output.
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
tool_call = response.choices[0].message.tool_calls[0]
|
||||
args = json.loads(tool_call.function.arguments)
|
||||
full_content = compressed["cache"][args["key"]]
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
Benchmarked on [SWE-bench Lite](https://huggingface.co/datasets/princeton-nlp/SWE-bench_Lite_bm25_27K) (real GitHub issues with ~27k tokens of BM25-retrieved repo context per problem).
|
||||
|
||||
### Claude Opus — 5 problems, trigger=10k
|
||||
|
||||
| Metric | Baseline | Compressed | Delta |
|
||||
|---|---|---|---|
|
||||
| File overlap | 1.000 | 1.000 | +0.000 |
|
||||
| Exact file match | 100% | 100% | +0.0% |
|
||||
| Hunk overlap | 0.582 | 0.361 | -0.221 |
|
||||
| Content similarity | 0.367 | 0.373 | +0.006 |
|
||||
| Avg prompt tokens | 30,828 | 6,890 | -77.7% |
|
||||
| Avg cost/problem | $0.488 | $0.136 | **-72.0%** |
|
||||
|
||||
**Key takeaways:**
|
||||
|
||||
- **File-level targeting is fully preserved** — the model edits the same files with or without compression.
|
||||
- **Content similarity matches baseline** — the actual lines changed are comparable.
|
||||
- **Hunk overlap drops modestly** (-0.221) — the model targets the right files but may edit slightly different line ranges with less surrounding context.
|
||||
- **72% cost savings** with 78% token reduction.
|
||||
|
||||
### Metrics explained
|
||||
|
||||
| Metric | What it measures |
|
||||
|---|---|
|
||||
| **File overlap** | Fraction of gold-patch files present in the generated patch |
|
||||
| **Exact file match** | Whether the generated patch touches exactly the same set of files |
|
||||
| **Hunk overlap** | Fraction of gold hunk line ranges covered by generated hunks |
|
||||
| **Content similarity** | Jaccard similarity of changed lines (added/removed) between gold and generated patches |
|
||||
|
||||
### Running the SWE-bench eval
|
||||
|
||||
```bash
|
||||
# 5-problem quick check
|
||||
python tests/eval_swe_bench.py --model claude-opus-4-20250514 --problems 5
|
||||
|
||||
# Custom trigger/target
|
||||
python tests/eval_swe_bench.py --model gpt-4o --problems 20 \
|
||||
--compression-trigger 15000 --compression-target 10000
|
||||
|
||||
# With embedding scoring
|
||||
python tests/eval_swe_bench.py --model gpt-4o --problems 10 \
|
||||
--embedding-model text-embedding-3-small
|
||||
```
|
||||
|
||||
### Running the HumanEval-style eval
|
||||
|
||||
```bash
|
||||
python scripts/eval_compression.py --model gpt-4o --problems 5
|
||||
```
|
||||
|
|
@ -29,7 +29,7 @@ general_settings:
|
|||
Start the proxy on port 4000:
|
||||
|
||||
```bash
|
||||
poetry run litellm --config config.yaml --port 4000
|
||||
uv run litellm --config config.yaml --port 4000
|
||||
```
|
||||
|
||||
The UI comes pre-built in the repo. Access it at `http://localhost:4000/ui`
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ If you want to use the non-hosted version, [go here](https://docs.litellm.ai/doc
|
|||
|
||||
|
||||
```
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
<QueryParamReader/>
|
||||
|
|
@ -41,7 +41,7 @@ git clone https://github.com/BerriAI/litellm.git
|
|||
Step 2: Install dev dependencies
|
||||
|
||||
```shell
|
||||
poetry install --with dev --extras proxy
|
||||
uv sync --group dev --extra proxy
|
||||
```
|
||||
|
||||
### 2. Adding tests
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ import TabItem from '@theme/TabItem';
|
|||
import NavigationCards from '@site/src/components/NavigationCards';
|
||||
import Image from '@theme/IdealImage';
|
||||
|
||||
:::note Security Update
|
||||
The Trivy supply-chain compromise has been contained :tada: . All affected packages have been deleted and current releases are free of the compromised code/component. Please refer to our [Security Townhall](/blog/security-townhall-updates) for a deeper understanding of the problem, and [CI/CD v2](/blog/ci-cd-v2-improvements) for how we're improving moving forward.
|
||||
:::
|
||||
|
||||
<Image style={{padding: '10px', margin: '0 0 2.5rem'}} img={require('../img/hero.png')} />
|
||||
|
||||
**LiteLLM** is an open-source library that gives you a single, unified interface to call 100+ LLMs — OpenAI, Anthropic, Vertex AI, Bedrock, and more — using the OpenAI format.
|
||||
|
|
@ -26,13 +30,13 @@ import Image from '@theme/IdealImage';
|
|||
## Installation
|
||||
|
||||
```shell
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
To run the full Proxy Server (LLM Gateway):
|
||||
|
||||
```shell
|
||||
pip install 'litellm[proxy]'
|
||||
uv tool install 'litellm[proxy]'
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -336,7 +340,7 @@ The proxy is a self-hosted OpenAI-compatible gateway. Any client that works with
|
|||
#### Step 1 — Start the proxy
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="pip" label="pip">
|
||||
<TabItem value="cli" label="LiteLLM CLI">
|
||||
|
||||
```shell
|
||||
litellm --model huggingface/bigcode/starcoder
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Letta allows you to build LLM agents that can:
|
|||
## Prerequisites
|
||||
|
||||
```bash
|
||||
pip install letta litellm
|
||||
uv add letta litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
@ -910,7 +910,7 @@ for model in models:
|
|||
```
|
||||
|
||||
### Common SDK Issues
|
||||
- **Import errors**: Ensure `pip install litellm letta` is run
|
||||
- **Import errors**: Ensure `uv add litellm letta` is run
|
||||
- **Model format**: Use `provider/model` format (e.g., `openai/gpt-4`)
|
||||
- **API key format**: Different providers have different key formats
|
||||
- **Rate limits**: Implement exponential backoff for retries
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import TabItem from '@theme/TabItem';
|
|||
|
||||
## Pre-Requisites
|
||||
```shell
|
||||
!pip install litellm langchain
|
||||
!uv add litellm langchain
|
||||
```
|
||||
## Quick Start
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ If you need a Docker or database-first setup, use the [Docker + Database tutoria
|
|||
## 1. Install The Gateway
|
||||
|
||||
```bash
|
||||
pip install 'litellm[proxy]'
|
||||
uv tool install 'litellm[proxy]'
|
||||
```
|
||||
|
||||
## 2. Set One Provider Key
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Use this path if you are integrating LiteLLM directly into application code.
|
|||
## 1. Install LiteLLM
|
||||
|
||||
```bash
|
||||
pip install litellm==1.82.6
|
||||
uv add 'litellm==1.82.6'
|
||||
```
|
||||
|
||||
## 2. Set Provider Credentials
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ model_list:
|
|||
api_base: https://exampleopenaiendpoint-production.up.railway.app/
|
||||
```
|
||||
|
||||
2. `pip install locust`
|
||||
2. `uv add locust`
|
||||
|
||||
3. Create a file called `locustfile.py` on your local machine. Copy the contents from the litellm load test located [here](https://github.com/BerriAI/litellm/blob/main/.github/workflows/locustfile.py)
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ litellm_settings:
|
|||
callbacks: ["prometheus"] # Enterprise LiteLLM Only - use prometheus to get metrics on your load test
|
||||
```
|
||||
|
||||
2. `pip install locust`
|
||||
2. `uv add locust`
|
||||
|
||||
3. Create a file called `locustfile.py` on your local machine. Copy the contents from the litellm load test located [here](https://github.com/BerriAI/litellm/blob/main/.github/workflows/locustfile.py)
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ litellm_settings:
|
|||
callbacks: ["prometheus"] # Enterprise LiteLLM Only - use prometheus to get metrics on your load test
|
||||
```
|
||||
|
||||
2. `pip install locust`
|
||||
2. `uv add locust`
|
||||
|
||||
3. Create a file called `locustfile.py` on your local machine. Copy the contents from the litellm load test located [here](https://github.com/BerriAI/litellm/blob/main/.github/workflows/locustfile.py)
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ SigV4-authenticated MCP servers skip the standard health check on proxy startup.
|
|||
Install the `botocore` package:
|
||||
|
||||
```bash
|
||||
pip install botocore
|
||||
uv add botocore
|
||||
```
|
||||
|
||||
`botocore` is used for SigV4 credential handling and is required when using `aws_sigv4` auth.
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ sequenceDiagram
|
|||
Use [BerriAI/mock-oauth2-mcp-server](https://github.com/BerriAI/mock-oauth2-mcp-server) to test locally:
|
||||
|
||||
```bash title="Terminal 1 - Start mock server" showLineNumbers
|
||||
pip install fastapi uvicorn
|
||||
uv add fastapi uvicorn
|
||||
python mock_oauth2_mcp_server.py # starts on :8765
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import TabItem from '@theme/TabItem';
|
|||
## Quick Start
|
||||
|
||||
```python
|
||||
# pip install braintrust
|
||||
# uv add braintrust
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ litellm.callbacks = ["lago"] # logs cost + usage of successful calls to lago
|
|||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
# pip install lago
|
||||
# uv add lago
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ For Langfuse v3, we recommend using the [Langfuse OTEL](./langfuse_otel_integrat
|
|||
## Usage with LiteLLM Python SDK
|
||||
|
||||
### Pre-Requisites
|
||||
Ensure you have run `pip install langfuse` for this integration
|
||||
Ensure you have run `uv add langfuse` for this integration
|
||||
```shell
|
||||
pip install langfuse==2.59.7 litellm
|
||||
uv add langfuse==2.59.7 litellm
|
||||
```
|
||||
|
||||
### Quick Start
|
||||
|
|
@ -44,7 +44,7 @@ litellm.success_callback = ["langfuse"]
|
|||
litellm.failure_callback = ["langfuse"] # logs errors to langfuse
|
||||
```
|
||||
```python
|
||||
# pip install langfuse
|
||||
# uv add langfuse
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
@ -335,7 +335,7 @@ Be aware that if you are continuing an existing trace, and you set `update_trace
|
|||
|
||||
## Troubleshooting & Errors
|
||||
### Data not getting logged to Langfuse ?
|
||||
- Ensure you're on the latest version of langfuse `pip install langfuse -U`. The latest version allows litellm to log JSON input/outputs to langfuse
|
||||
- Ensure you're on the latest version of langfuse `uv add langfuse -U`. The latest version allows litellm to log JSON input/outputs to langfuse
|
||||
- Follow [this checklist](https://langfuse.com/faq/all/missing-traces) if you don't see any traces in langfuse.
|
||||
|
||||
## Support & Talk to Founders
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ The Langfuse OpenTelemetry integration allows you to send LiteLLM traces and obs
|
|||
2. **API Keys**: Get your public and secret keys from your Langfuse project settings
|
||||
3. **Dependencies**: Install required packages:
|
||||
```bash
|
||||
pip install litellm opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
|
||||
uv add litellm opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ join our [discord](https://discord.gg/wuPM9dRgDw)
|
|||
|
||||
## Pre-Requisites
|
||||
```shell
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Send all your LLM requests and responses to Levo for monitoring and analysis usi
|
|||
**1. Install OpenTelemetry dependencies:**
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http opentelemetry-exporter-otlp-proto-grpc
|
||||
uv add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http opentelemetry-exporter-otlp-proto-grpc
|
||||
```
|
||||
|
||||
**2. Enable Levo callback in your LiteLLM config:**
|
||||
|
|
@ -133,7 +133,7 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \
|
|||
```
|
||||
|
||||
4. **Check for initialization errors**: Look for errors in LiteLLM startup logs. Common issues:
|
||||
- Missing OpenTelemetry packages: Install with `pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http opentelemetry-exporter-otlp-proto-grpc`
|
||||
- Missing OpenTelemetry packages: Install with `uv add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http opentelemetry-exporter-otlp-proto-grpc`
|
||||
- Missing required environment variables: All four required variables must be set
|
||||
- Invalid collector URL: Ensure the URL is correct and reachable
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \
|
|||
- Solution: Set the `LEVOAI_COLLECTOR_URL` environment variable with your collector endpoint URL from Levo support.
|
||||
|
||||
**Error: "No module named 'opentelemetry'"**
|
||||
- Solution: Install OpenTelemetry packages: `pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http opentelemetry-exporter-otlp-proto-grpc`
|
||||
- Solution: Install OpenTelemetry packages: `uv add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http opentelemetry-exporter-otlp-proto-grpc`
|
||||
|
||||
## Additional Resources
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import Image from '@theme/IdealImage';
|
|||
Ensure you have the `literalai` package installed:
|
||||
|
||||
```shell
|
||||
pip install literalai litellm
|
||||
uv add literalai litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ join our [discord](https://discord.gg/wuPM9dRgDw)
|
|||
Ensure you have installed the following packages to use this integration
|
||||
|
||||
```shell
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
|
||||
pip install opentelemetry-api==1.25.0
|
||||
pip install opentelemetry-sdk==1.25.0
|
||||
pip install opentelemetry-exporter-otlp==1.25.0
|
||||
uv add opentelemetry-api==1.25.0
|
||||
uv add opentelemetry-sdk==1.25.0
|
||||
uv add opentelemetry-exporter-otlp==1.25.0
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
@ -33,7 +33,7 @@ litellm.callbacks = ["logfire"]
|
|||
```
|
||||
|
||||
```python
|
||||
# pip install logfire
|
||||
# uv add logfire
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ You can reach out to us anytime by [email](mailto:hello@lunary.ai) or directly [
|
|||
### Pre-Requisites
|
||||
|
||||
```shell
|
||||
pip install litellm lunary
|
||||
uv add litellm lunary
|
||||
```
|
||||
|
||||
### Quick Start
|
||||
|
|
@ -124,7 +124,7 @@ my_chain("Chain input")
|
|||
### Step1: Install dependencies and set your environment variables
|
||||
Install the dependencies
|
||||
```shell
|
||||
pip install litellm lunary
|
||||
uv add litellm lunary
|
||||
```
|
||||
|
||||
Get you Lunary public key from from https://app.lunary.ai/settings
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ MLflow’s integration with LiteLLM supports advanced observability compatible w
|
|||
Install MLflow:
|
||||
|
||||
```shell
|
||||
pip install "litellm[mlflow]"
|
||||
uv add "litellm[mlflow]"
|
||||
```
|
||||
|
||||
To enable MLflow auto tracing for LiteLLM:
|
||||
|
|
@ -167,7 +167,7 @@ This approach generates a unified trace, combining your custom Python code with
|
|||
For using `mlflow` on LiteLLM Proxy Server, you need to install the `mlflow` package on your docker container.
|
||||
|
||||
```shell
|
||||
pip install "mlflow>=3.1.4"
|
||||
uv add "mlflow>=3.1.4"
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ litellm.callbacks = ["openmeter"] # logs cost + usage of successful calls to ope
|
|||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
# pip install openmeter
|
||||
# uv add openmeter
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ USE_OTEL_LITELLM_REQUEST_SPAN=true
|
|||
Install the OpenTelemetry SDK:
|
||||
|
||||
```
|
||||
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
|
||||
uv add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
|
||||
```
|
||||
|
||||
Set the environment variables (different providers may require different variables):
|
||||
|
|
@ -63,7 +63,7 @@ OTEL_EXPORTER_OTLP_PROTOCOL=grpc
|
|||
OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value"
|
||||
```
|
||||
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `pip install "litellm[grpc]"` (or `grpcio`).
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `uv add "litellm[grpc]"` (or `grpcio`).
|
||||
|
||||
</TabItem>
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ OTEL_ENDPOINT="https://api.lmnr.ai:8443"
|
|||
OTEL_HEADERS="authorization=Bearer <project-api-key>"
|
||||
```
|
||||
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `pip install "litellm[grpc]"` (or `grpcio`).
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `uv add "litellm[grpc]"` (or `grpcio`).
|
||||
|
||||
</TabItem>
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Use just 2 lines of code, to instantly log your responses **across all providers
|
|||
You can also use the instrumentor option instead of the callback, which you can find [here](https://docs.arize.com/phoenix/tracing/integrations-tracing/litellm).
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp litellm[proxy]
|
||||
uv add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp litellm[proxy]
|
||||
```
|
||||
```python
|
||||
litellm.callbacks = ["arize_phoenix"]
|
||||
|
|
@ -73,7 +73,7 @@ environment_variables:
|
|||
PHOENIX_COLLECTOR_HTTP_ENDPOINT: "https://app.phoenix.arize.com/s/<space-name>/v1/traces" # OPTIONAL - For setting the HTTP endpoint
|
||||
```
|
||||
|
||||
> Note: If you set the gRPC endpoint, install `grpcio` via `pip install "litellm[grpc]"` (or `grpcio`).
|
||||
> Note: If you set the gRPC endpoint, install `grpcio` via `uv add "litellm[grpc]"` (or `grpcio`).
|
||||
|
||||
2. Start the proxy
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Looking for Qualifire Guardrails? Check out the [Qualifire Guardrails Integratio
|
|||
2. Get your API key and webhook URL from the Qualifire dashboard
|
||||
|
||||
```bash
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ See the raw request/response sent by LiteLLM in your logging provider (OTEL/Lang
|
|||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
# pip install langfuse
|
||||
# uv add langfuse
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ litellm.callbacks = [customHandler]
|
|||
3. Test it!
|
||||
|
||||
```python
|
||||
# pip install langfuse
|
||||
# uv add langfuse
|
||||
|
||||
import os
|
||||
import litellm
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Instrumenting LiteLLM in your AI applications with telemetry ensures full observ
|
|||
- A [SigNoz Cloud account](https://signoz.io/teams/) with an active ingestion key
|
||||
- Internet access to send telemetry data to SigNoz Cloud
|
||||
- [LiteLLM](https://www.litellm.ai/) SDK or Proxy integration
|
||||
- For Python: `pip` installed for managing Python packages and _(optional but recommended)_ a Python virtual environment to isolate dependencies
|
||||
- For Python: `uv` installed for managing Python packages and _(optional but recommended)_ a Python virtual environment to isolate dependencies
|
||||
|
||||
## Monitoring LiteLLM
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ No-code auto-instrumentation is recommended for quick setup with minimal code ch
|
|||
**Step 1:** Install the necessary packages in your Python environment.
|
||||
|
||||
```bash
|
||||
pip install \
|
||||
uv add \
|
||||
opentelemetry-api \
|
||||
opentelemetry-distro \
|
||||
opentelemetry-exporter-otlp \
|
||||
|
|
@ -99,7 +99,7 @@ OTEL_PYTHON_DISABLED_INSTRUMENTATIONS=openai \
|
|||
opentelemetry-instrument <your_run_command>
|
||||
```
|
||||
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `pip install "litellm[grpc]"` (or `grpcio`).
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `uv add "litellm[grpc]"` (or `grpcio`).
|
||||
|
||||
> 📌 Note: We're using `OTEL_PYTHON_DISABLED_INSTRUMENTATIONS=openai` in the run command to disable the OpenAI instrumentor for tracing. This avoids conflicts with LiteLLM's native telemetry/instrumentation, ensuring that telemetry is captured exclusively through LiteLLM's built-in instrumentation.
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ Code-based instrumentation gives you fine-grained control over your telemetry co
|
|||
**Step 1:** Install the necessary packages in your Python environment.
|
||||
|
||||
```bash
|
||||
pip install \
|
||||
uv add \
|
||||
opentelemetry-api \
|
||||
opentelemetry-sdk \
|
||||
opentelemetry-exporter-otlp \
|
||||
|
|
@ -338,7 +338,7 @@ You can also check out our custom LiteLLM SDK dashboard [here](https://signoz.i
|
|||
**Step 1:** Install the necessary packages in your Python environment.
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-api \
|
||||
uv add opentelemetry-api \
|
||||
opentelemetry-sdk \
|
||||
opentelemetry-exporter-otlp \
|
||||
'litellm[proxy]'
|
||||
|
|
@ -364,7 +364,7 @@ export OTEL_METRICS_EXPORTER="otlp"
|
|||
export OTEL_LOGS_EXPORTER="otlp"
|
||||
```
|
||||
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `pip install "litellm[grpc]"` (or `grpcio`).
|
||||
> Note: OTLP gRPC requires `grpcio`. Install via `uv add "litellm[grpc]"` (or `grpcio`).
|
||||
|
||||
- Set the `<region>` to match your SigNoz Cloud [region](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint)
|
||||
- Replace `<your_ingestion_key>` with your SigNoz [ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ join our [discord](https://discord.gg/wuPM9dRgDw)
|
|||
|
||||
### Step 1
|
||||
```shell
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
### Step 2
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ join our [discord](https://discord.gg/wuPM9dRgDw)
|
|||
For more details, see the [HTTP Logs & Metrics Source](https://www.sumologic.com/help/docs/send-data/hosted-collectors/http-source/logs-metrics/) documentation.
|
||||
|
||||
```shell
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ join our [discord](https://discord.gg/wuPM9dRgDw)
|
|||
:::
|
||||
|
||||
## Pre-Requisites
|
||||
Ensure you have run `pip install wandb` for this integration
|
||||
Ensure you have run `uv add wandb` for this integration
|
||||
```shell
|
||||
pip install wandb litellm
|
||||
uv add wandb litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
|
@ -33,7 +33,7 @@ Use just 2 lines of code, to instantly log your responses **across all providers
|
|||
litellm.success_callback = ["wandb"]
|
||||
```
|
||||
```python
|
||||
# pip install wandb
|
||||
# uv add wandb
|
||||
import litellm
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -57,12 +57,31 @@ oidc/config_name_here/
|
|||
|
||||
#### Unofficial Providers (not recommended)
|
||||
|
||||
For the unofficial `file` provider, you can use the following format:
|
||||
For the unofficial `file` provider, you can use the following format
|
||||
(note the double slash — the path after `oidc/file/` must be absolute):
|
||||
|
||||
```
|
||||
oidc/file/home/user/dave/this_is_a_file_with_a_token.txt
|
||||
oidc/file//var/run/secrets/my-token
|
||||
```
|
||||
|
||||
For safety, the resolved path must live inside an allowed credential
|
||||
directory. By default the following directories are allowed:
|
||||
|
||||
- `/var/run/secrets`
|
||||
- `/run/secrets`
|
||||
|
||||
If your deployment mounts credentials elsewhere, set the
|
||||
`LITELLM_OIDC_ALLOWED_CREDENTIAL_DIRS` environment variable to a
|
||||
comma-separated list of absolute directories. The value replaces the
|
||||
default list, so include the defaults if you still need them:
|
||||
|
||||
```bash
|
||||
export LITELLM_OIDC_ALLOWED_CREDENTIAL_DIRS="/var/run/secrets,/etc/litellm/creds"
|
||||
```
|
||||
|
||||
Paths that resolve (after following symlinks and `..`) outside the
|
||||
allowlist are rejected.
|
||||
|
||||
For the unofficial `env`, use the following format, where `SECRET_TOKEN` is the name of the environment variable that contains the token:
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ You can use the [LangChain AWS SDK](https://python.langchain.com/docs/integratio
|
|||
**1. Install LangChain AWS**:
|
||||
|
||||
```bash showLineNumbers
|
||||
pip install langchain-aws
|
||||
uv add langchain-aws
|
||||
```
|
||||
|
||||
**2. Setup LiteLLM Proxy**:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
```bash
|
||||
# Install
|
||||
pip install harbor
|
||||
uv add harbor
|
||||
|
||||
# Run a benchmark with any LiteLLM-supported model
|
||||
harbor run --dataset terminal-bench@2.0 \
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ The [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) is a lig
|
|||
### 1. Install Dependencies
|
||||
|
||||
```bash
|
||||
pip install "openai-agents[litellm]"
|
||||
uv add "openai-agents[litellm]"
|
||||
```
|
||||
|
||||
### 2. Add Model to Config
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,7 @@ In production, [Router connects to a Redis Cache](#redis-queue) to track usage a
|
|||
#### Quick Start
|
||||
|
||||
```python
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
```python
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ response = completion(
|
|||
See all litellm.completion supported params [here](../completion/input.md#translated-openai-params)
|
||||
|
||||
```python
|
||||
# !pip install litellm
|
||||
# !uv add litellm
|
||||
from litellm import completion
|
||||
import os
|
||||
## set ENV variables
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ ALL Bedrock models (Anthropic, Meta, Deepseek, Mistral, Amazon, etc.) are Suppor
|
|||
|
||||
LiteLLM requires `boto3` to be installed on your system for Bedrock requests
|
||||
```shell
|
||||
pip install boto3>=1.28.57
|
||||
uv add boto3>=1.28.57
|
||||
```
|
||||
|
||||
:::info
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ Complete working examples are available in the LiteLLM repository:
|
|||
## Requirements
|
||||
|
||||
```bash
|
||||
pip install litellm websockets pyaudio
|
||||
uv add litellm websockets pyaudio
|
||||
```
|
||||
|
||||
## AWS Configuration
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ If you wish to use custom formatting, please let us know via either [help@bytez.
|
|||
See all litellm.completion supported params [here](https://docs.litellm.ai/docs/completion/input)
|
||||
|
||||
```py
|
||||
# !pip install litellm
|
||||
# !uv add litellm
|
||||
from litellm import completion
|
||||
import os
|
||||
## set ENV variables
|
||||
|
|
@ -160,7 +160,7 @@ Any kwarg supported by huggingface we also support! (Provided the model supports
|
|||
Example `repetition_penalty`
|
||||
|
||||
```py
|
||||
# !pip install litellm
|
||||
# !uv add litellm
|
||||
from litellm import completion
|
||||
import os
|
||||
## set ENV variables
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Anthropic, OpenAI, Qwen, xAI, Gemini and most of Open soured LLMs are Supported
|
|||
## Pre-Requisites
|
||||
|
||||
```bash
|
||||
pip install litellm
|
||||
uv add litellm
|
||||
```
|
||||
|
||||
## Required Environment Variables
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ If no credentials are provided, LiteLLM will use the Databricks SDK for automati
|
|||
from litellm import completion
|
||||
|
||||
# No environment variables needed - uses Databricks SDK unified auth
|
||||
# Requires: pip install databricks-sdk
|
||||
# Requires: uv add databricks-sdk
|
||||
response = completion(
|
||||
model="databricks/databricks-dbrx-instruct",
|
||||
messages=[{"role": "user", "content": "Hello!"}],
|
||||
|
|
@ -220,7 +220,7 @@ response = completion(
|
|||
See all litellm.completion supported params [here](../completion/input.md#translated-openai-params)
|
||||
|
||||
```python
|
||||
# !pip install litellm
|
||||
# !uv add litellm
|
||||
from litellm import completion
|
||||
import os
|
||||
## set ENV variables
|
||||
|
|
@ -457,7 +457,7 @@ For embedding models, databricks lets you pass in an additional param 'instructi
|
|||
|
||||
|
||||
```python
|
||||
# !pip install litellm
|
||||
# !uv add litellm
|
||||
from litellm import embedding
|
||||
import os
|
||||
## set ENV variables
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ LiteLLM supports Google's Veo video generation models through a unified API inte
|
|||
|-------|-------|
|
||||
| Description | Google's Veo AI video generation models |
|
||||
| Provider Route on LiteLLM | `gemini/` |
|
||||
| Supported Models | `veo-3.0-generate-preview`, `veo-3.1-generate-preview` |
|
||||
| Cost Tracking | ✅ Duration-based pricing |
|
||||
| Supported Models | Veo 3.0 / 3.1 preview and production IDs (see table below), including **Veo 3.1 Lite** |
|
||||
| Cost Tracking | ✅ Duration-based pricing; optional **per-resolution** tiers where the catalog lists them (e.g. 720p vs 1080p) |
|
||||
| Logging Support | ✅ Full request/response logging |
|
||||
| Proxy Server Support | ✅ Full proxy integration with virtual keys |
|
||||
| Spend Management | ✅ Budget tracking and rate limiting |
|
||||
|
|
@ -79,6 +79,11 @@ print("Video downloaded successfully!")
|
|||
|------------|-------------|--------------|--------|
|
||||
| veo-3.0-generate-preview | Veo 3.0 video generation | 8 seconds | Preview |
|
||||
| veo-3.1-generate-preview | Veo 3.1 video generation | 8 seconds | Preview |
|
||||
| veo-3.1-lite-generate-preview | Veo 3.1 **Lite** (cost-efficient; [Gemini pricing](https://ai.google.dev/gemini-api/docs/video)) | Per Google docs | Preview |
|
||||
| veo-3.1-fast-generate-preview / `…-001` | Faster / prod variants | Per Google docs | Preview / GA |
|
||||
| veo-3.1-generate-001 | Veo 3.1 production | Per Google docs | GA |
|
||||
|
||||
Use the full LiteLLM model id with the `gemini/` prefix (for example `gemini/veo-3.1-lite-generate-preview`).
|
||||
|
||||
## Video Generation Parameters
|
||||
|
||||
|
|
@ -87,14 +92,29 @@ LiteLLM automatically maps OpenAI-style parameters to Veo's format:
|
|||
| OpenAI Parameter | Veo Parameter | Description | Example |
|
||||
|------------------|---------------|-------------|---------|
|
||||
| `prompt` | `prompt` | Text description of the video | "A cat playing" |
|
||||
| `size` | `aspectRatio` | Video dimensions → aspect ratio | "1280x720" → "16:9" |
|
||||
| `size` | `aspectRatio` and, when applicable, **`resolution`** | Standard widths/heights map to landscape/portrait **and** to `720p` or `1080p` for the API | See below |
|
||||
| `seconds` | `durationSeconds` | Duration in seconds | "8" → 8 |
|
||||
| `input_reference` | `image` | Reference image to animate | File object or path |
|
||||
| `model` | `model` | Model to use | "gemini/veo-3.0-generate-preview" |
|
||||
|
||||
### Size to Aspect Ratio Mapping
|
||||
### `size` and output resolution
|
||||
|
||||
When you pass a **standard `size`** string, LiteLLM sets both:
|
||||
|
||||
- **Aspect ratio** (`16:9` or `9:16`) — same as before.
|
||||
- **Output resolution** (`720p` or `1080p`) when the height is clear from the preset, so the correct Veo tier is requested without extra fields.
|
||||
|
||||
| `size` | Aspect ratio | Resolution sent to Veo |
|
||||
|--------|----------------|-------------------------|
|
||||
| `1280x720`, `720x1280` | `16:9` / `9:16` | `720p` |
|
||||
| `1920x1080`, `1080x1920` | `16:9` / `9:16` | `1080p` |
|
||||
|
||||
Other `size` values still map to an aspect ratio (defaulting to `16:9` when unknown); resolution is left to **Google’s default** unless you set it yourself.
|
||||
|
||||
You can also pass Veo’s **`resolution`** (for example via `extra_body`) if you need an explicit value that does not match the presets above. If you set `resolution` yourself, it takes precedence over the value inferred from `size`.
|
||||
|
||||
### Size to aspect ratio (reference)
|
||||
|
||||
LiteLLM automatically converts size dimensions to Veo's aspect ratio format:
|
||||
- `"1280x720"`, `"1920x1080"` → `"16:9"` (landscape)
|
||||
- `"720x1280"`, `"1080x1920"` → `"9:16"` (portrait)
|
||||
|
||||
|
|
@ -293,7 +313,14 @@ with open("video.mp4", "wb") as f:
|
|||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Cost Tracking
|
||||
## Cost tracking and spend
|
||||
|
||||
LiteLLM estimates **video spend** from:
|
||||
|
||||
1. **How long** the generated clip is billed for (seconds), and
|
||||
2. **The per-second price** for that model in LiteLLM’s model catalog (aligned with [Google’s Gemini API video pricing](https://ai.google.dev/gemini-api/docs/video) where applicable).
|
||||
|
||||
Some models charge **different per-second rates** for **720p** vs **1080p**. When you use the standard `size` presets above (or set `resolution` explicitly), LiteLLM uses the matching tier so **proxy spend, logs, and budgets** line up with the resolution you requested.
|
||||
|
||||
LiteLLM automatically tracks costs for Veo video generation:
|
||||
|
||||
|
|
@ -314,8 +341,8 @@ response = litellm.video_generation(
|
|||
| Feature | OpenAI (Sora) | Gemini (Veo) |
|
||||
|---------|---------------|--------------|
|
||||
| Reference Images | ✅ Supported | ❌ Not supported |
|
||||
| Size Control | ✅ Supported | ❌ Not supported |
|
||||
| Duration Control | ✅ Supported | ❌ Not supported |
|
||||
| Size / dimensions | ✅ Supported | ✅ Supported via `size` → aspect ratio + `720p`/`1080p` where preset |
|
||||
| Duration (`seconds`) | ✅ Supported | ✅ Supported (maps to `durationSeconds`; limits per Google docs) |
|
||||
| Video Remix/Edit | ✅ Supported | ❌ Not supported |
|
||||
| Video List | ✅ Supported | ❌ Not supported |
|
||||
| Prompt-based Generation | ✅ Supported | ✅ Supported |
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue