diff --git a/.circleci/config.yml b/.circleci/config.yml index 9acffc96257..4306fa5cf05 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,8 +1,56 @@ version: 2.1 orbs: codecov: codecov/codecov@4.0.1 + node: circleci/node@5.1.0 # Add this line to declare the node orb + win: circleci/windows@5.0 # Add Windows orb + +commands: + setup_google_dns: + steps: + - run: + name: "Configure Google DNS" + command: | + # Backup original resolv.conf + sudo cp /etc/resolv.conf /etc/resolv.conf.backup + # Add both local and Google DNS servers + echo "nameserver 127.0.0.11" | sudo tee /etc/resolv.conf + echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf + echo "nameserver 8.8.4.4" | sudo tee -a /etc/resolv.conf + setup_litellm_enterprise_pip: + steps: + - run: + name: "Install local version of litellm-enterprise" + command: | + cd enterprise + python -m pip install -e . + cd .. jobs: + # Add Windows testing job + using_litellm_on_windows: + executor: + name: win/default + shell: powershell.exe + working_directory: ~/project + steps: + - checkout + - run: + name: Install Python + command: | + choco install python --version=3.11.0 -y + refreshenv + python --version + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + pip install pytest + pip install . + - run: + name: Run Windows-specific test + command: | + python -m pytest tests/windows_tests/test_litellm_on_windows.py -v + local_testing: docker: - image: cimg/python:3.11 @@ -13,7 +61,7 @@ jobs: steps: - checkout - + - setup_google_dns - run: name: Show git commit hash command: | @@ -47,7 +95,7 @@ jobs: pip install opentelemetry-api==1.25.0 pip install opentelemetry-sdk==1.25.0 pip install opentelemetry-exporter-otlp==1.25.0 - pip install openai==1.54.0 + pip install openai==1.68.2 pip install prisma==0.11.0 pip install "detect_secrets==1.5.0" pip install "httpx==0.24.1" @@ -64,12 +112,14 @@ jobs: pip install python-multipart pip install google-cloud-aiplatform pip install prometheus-client==0.20.0 - pip install "pydantic==2.7.1" + pip install "pydantic==2.10.2" pip install "diskcache==5.6.1" pip install "Pillow==10.3.0" pip install "jsonschema==4.22.0" pip install "pytest-xdist==3.6.1" - pip install "websockets==10.4" + pip install "websockets==13.1.0" + pip uninstall posthog -y + - setup_litellm_enterprise_pip - save_cache: paths: - ./venv @@ -92,10 +142,13 @@ jobs: name: Linting Testing command: | cd litellm + pip install "cryptography<40.0.0" python -m pip install types-requests types-setuptools types-redis types-PyYAML - if ! python -m mypy . --ignore-missing-imports; then - echo "mypy detected errors" - exit 1 + if ! python -m mypy . \ + --config-file mypy.ini \ + --ignore-missing-imports; then + echo "mypy detected errors" + exit 1 fi cd .. @@ -131,7 +184,7 @@ jobs: steps: - checkout - + - setup_google_dns - run: name: Show git commit hash command: | @@ -165,7 +218,7 @@ jobs: pip install opentelemetry-api==1.25.0 pip install opentelemetry-sdk==1.25.0 pip install opentelemetry-exporter-otlp==1.25.0 - pip install openai==1.54.0 + pip install openai==1.68.2 pip install prisma==0.11.0 pip install "detect_secrets==1.5.0" pip install "httpx==0.24.1" @@ -182,10 +235,12 @@ jobs: pip install python-multipart pip install google-cloud-aiplatform pip install prometheus-client==0.20.0 - pip install "pydantic==2.7.1" + pip install "pydantic==2.10.2" pip install "diskcache==5.6.1" pip install "Pillow==10.3.0" pip install "jsonschema==4.22.0" + pip install "websockets==13.1.0" + - setup_litellm_enterprise_pip - save_cache: paths: - ./venv @@ -230,7 +285,13 @@ jobs: steps: - checkout - + - setup_google_dns + - run: + name: DNS lookup for Redis host + command: | + sudo apt-get update + sudo apt-get install -y dnsutils + dig redis-19899.c239.us-east-1-2.ec2.redns.redis-cloud.com +short - run: name: Show git commit hash command: | @@ -264,7 +325,7 @@ jobs: pip install opentelemetry-api==1.25.0 pip install opentelemetry-sdk==1.25.0 pip install opentelemetry-exporter-otlp==1.25.0 - pip install openai==1.54.0 + pip install openai==1.68.2 pip install prisma==0.11.0 pip install "detect_secrets==1.5.0" pip install "httpx==0.24.1" @@ -281,10 +342,12 @@ jobs: pip install python-multipart pip install google-cloud-aiplatform pip install prometheus-client==0.20.0 - pip install "pydantic==2.7.1" + pip install "pydantic==2.10.2" pip install "diskcache==5.6.1" pip install "Pillow==10.3.0" pip install "jsonschema==4.22.0" + pip install "websockets==13.1.0" + - setup_litellm_enterprise_pip - save_cache: paths: - ./venv @@ -329,6 +392,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -383,6 +447,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -394,12 +459,13 @@ jobs: pip install "pytest-retry==1.6.3" pip install "pytest-asyncio==0.21.1" # Run pytest and generate JUnit XML report + - setup_litellm_enterprise_pip - run: name: Run tests command: | pwd ls - python -m pytest tests/local_testing tests/router_unit_tests --cov=litellm --cov-report=xml -vv -k "router" -x -s -v --junitxml=test-results/junit.xml --durations=5 + python -m pytest tests/local_testing tests/router_unit_tests --cov=litellm --cov-report=xml -vv -k "router" -x -v --junitxml=test-results/junit.xml --durations=5 no_output_timeout: 120m - run: name: Rename the coverage files @@ -415,6 +481,57 @@ jobs: paths: - litellm_router_coverage.xml - litellm_router_coverage + litellm_proxy_security_tests: + docker: + - image: cimg/python:3.11 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + working_directory: ~/project + steps: + - checkout + - setup_google_dns + - run: + name: Show git commit hash + command: | + echo "Git commit hash: $CIRCLE_SHA1" + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-asyncio==0.21.1" + pip install "pytest-cov==5.0.0" + - run: + name: Run prisma ./docker/entrypoint.sh + command: | + set +e + chmod +x docker/entrypoint.sh + ./docker/entrypoint.sh + set -e + # Run pytest and generate JUnit XML report + - run: + name: Run tests + command: | + pwd + ls + python -m pytest tests/proxy_security_tests --cov=litellm --cov-report=xml -vv -x -v --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: 120m + - run: + name: Rename the coverage files + command: | + mv coverage.xml litellm_proxy_security_tests_coverage.xml + mv .coverage litellm_proxy_security_tests_coverage + # Store test results + - store_test_results: + path: test-results + - persist_to_workspace: + root: . + paths: + - litellm_proxy_security_tests_coverage.xml + - litellm_proxy_security_tests_coverage litellm_proxy_unit_testing: # Runs all tests with the "proxy", "key", "jwt" filenames docker: - image: cimg/python:3.11 @@ -424,7 +541,13 @@ jobs: working_directory: ~/project steps: - checkout - + - run: + name: Install PostgreSQL + command: | + sudo apt-get update + sudo apt-get install postgresql postgresql-contrib + echo 'export PATH=/usr/lib/postgresql/*/bin:$PATH' >> $BASH_ENV + - setup_google_dns - run: name: Show git commit hash command: | @@ -458,7 +581,7 @@ jobs: pip install opentelemetry-api==1.25.0 pip install opentelemetry-sdk==1.25.0 pip install opentelemetry-exporter-otlp==1.25.0 - pip install openai==1.54.0 + pip install openai==1.68.2 pip install prisma==0.11.0 pip install "detect_secrets==1.5.0" pip install "httpx==0.24.1" @@ -475,10 +598,13 @@ jobs: pip install python-multipart pip install google-cloud-aiplatform pip install prometheus-client==0.20.0 - pip install "pydantic==2.7.1" + pip install "pydantic==2.10.2" pip install "diskcache==5.6.1" pip install "Pillow==10.3.0" pip install "jsonschema==4.22.0" + pip install "pytest-postgresql==7.0.1" + pip install "fakeredis==2.28.1" + - setup_litellm_enterprise_pip - save_cache: paths: - ./venv @@ -514,7 +640,7 @@ jobs: - litellm_proxy_unit_tests_coverage litellm_assistants_api_testing: # Runs all tests with the "assistants" keyword docker: - - image: cimg/python:3.11 + - image: cimg/python:3.13.1 auth: username: ${DOCKERHUB_USERNAME} password: ${DOCKERHUB_PASSWORD} @@ -522,10 +648,13 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | python -m pip install --upgrade pip + pip install wheel + pip install --upgrade pip wheel setuptools python -m pip install -r requirements.txt pip install "pytest==7.3.1" pip install "respx==0.21.1" @@ -533,6 +662,7 @@ jobs: pip install "pytest-asyncio==0.21.1" pip install "pytest-cov==5.0.0" # Run pytest and generate JUnit XML report + - setup_litellm_enterprise_pip - run: name: Run tests command: | @@ -563,6 +693,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -570,7 +701,13 @@ jobs: python -m pip install -r requirements.txt pip install "pytest==7.3.1" pip install "pytest-retry==1.6.3" + pip install "pytest-cov==5.0.0" pip install "pytest-asyncio==0.21.1" + pip install "respx==0.21.1" + - run: + name: Show current pydantic version + command: | + python -m pip show pydantic # Run pytest and generate JUnit XML report - run: name: Run tests @@ -593,6 +730,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -609,7 +747,7 @@ jobs: command: | pwd ls - python -m pytest -vv tests/llm_translation --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 + python -m pytest -vv tests/llm_translation --cov=litellm --cov-report=xml -x -v --junitxml=test-results/junit.xml --durations=5 no_output_timeout: 120m - run: name: Rename the coverage files @@ -625,6 +763,189 @@ jobs: paths: - llm_translation_coverage.xml - llm_translation_coverage + mcp_testing: + docker: + - image: cimg/python:3.11 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + working_directory: ~/project + + steps: + - checkout + - setup_google_dns + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-cov==5.0.0" + pip install "pytest-asyncio==0.21.1" + pip install "respx==0.21.1" + pip install "pydantic==2.10.2" + pip install "mcp==1.5.0" + # Run pytest and generate JUnit XML report + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/mcp_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: 120m + - run: + name: Rename the coverage files + command: | + mv coverage.xml mcp_coverage.xml + mv .coverage mcp_coverage + + # Store test results + - store_test_results: + path: test-results + - persist_to_workspace: + root: . + paths: + - mcp_coverage.xml + - mcp_coverage + guardrails_testing: + docker: + - image: cimg/python:3.11 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + working_directory: ~/project + + steps: + - checkout + - setup_google_dns + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-cov==5.0.0" + pip install "pytest-asyncio==0.21.1" + pip install "respx==0.21.1" + pip install "pydantic==2.10.2" + pip install "boto3==1.34.34" + # Run pytest and generate JUnit XML report + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/guardrails_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: 120m + - run: + name: Rename the coverage files + command: | + mv coverage.xml guardrails_coverage.xml + mv .coverage guardrails_coverage + + # Store test results + - store_test_results: + path: test-results + - persist_to_workspace: + root: . + paths: + - guardrails_coverage.xml + - guardrails_coverage + llm_responses_api_testing: + docker: + - image: cimg/python:3.11 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + working_directory: ~/project + + steps: + - checkout + - setup_google_dns + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-cov==5.0.0" + pip install "pytest-asyncio==0.21.1" + pip install "respx==0.21.1" + # Run pytest and generate JUnit XML report + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/llm_responses_api_testing --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: 120m + - run: + name: Rename the coverage files + command: | + mv coverage.xml llm_responses_api_coverage.xml + mv .coverage llm_responses_api_coverage + + # Store test results + - store_test_results: + path: test-results + - persist_to_workspace: + root: . + paths: + - llm_responses_api_coverage.xml + - llm_responses_api_coverage + litellm_mapped_tests: + docker: + - image: cimg/python:3.11 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + working_directory: ~/project + + steps: + - checkout + - setup_google_dns + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest-mock==3.12.0" + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-cov==5.0.0" + pip install "pytest-asyncio==0.21.1" + pip install "respx==0.21.1" + pip install "hypercorn==0.17.3" + pip install "pydantic==2.10.2" + pip install "mcp==1.5.0" + pip install "requests-mock>=1.12.1" + pip install "responses==0.25.7" + - setup_litellm_enterprise_pip + # Run pytest and generate JUnit XML report + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/litellm tests/enterprise --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=10 + no_output_timeout: 120m + - run: + name: Rename the coverage files + command: | + mv coverage.xml litellm_mapped_tests_coverage.xml + mv .coverage litellm_mapped_tests_coverage + + # Store test results + - store_test_results: + path: test-results + - persist_to_workspace: + root: . + paths: + - litellm_mapped_tests_coverage.xml + - litellm_mapped_tests_coverage batches_testing: docker: - image: cimg/python:3.11 @@ -635,6 +956,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -679,10 +1001,12 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | python -m pip install --upgrade pip + pip install numpydoc python -m pip install -r requirements.txt pip install "respx==0.21.1" pip install "pytest==7.3.1" @@ -691,7 +1015,6 @@ jobs: pip install "pytest-cov==5.0.0" pip install "google-generativeai==0.3.2" pip install "google-cloud-aiplatform==1.43.0" - pip install numpydoc # Run pytest and generate JUnit XML report - run: name: Run tests @@ -725,6 +1048,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -767,6 +1091,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -809,6 +1134,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -824,6 +1150,7 @@ jobs: pip install "google-cloud-aiplatform==1.43.0" pip install "mlflow==2.17.2" # Run pytest and generate JUnit XML report + - setup_litellm_enterprise_pip - run: name: Run tests command: | @@ -855,6 +1182,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -867,9 +1195,10 @@ jobs: pip install click pip install "boto3==1.34.34" pip install jinja2 - pip install tokenizers=="0.20.0" - pip install uvloop==0.21.0 + pip install "tokenizers==0.20.0" + pip install "uvloop==0.21.0" pip install jsonschema + - setup_litellm_enterprise_pip - run: name: Run tests command: | @@ -887,10 +1216,12 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | python -m pip install --upgrade pip + python -m pip install wheel setuptools python -m pip install -r requirements.txt pip install "pytest==7.3.1" pip install "pytest-retry==1.6.3" @@ -911,6 +1242,7 @@ jobs: steps: - checkout + - setup_google_dns # Install Helm - run: name: Install Helm @@ -980,6 +1312,7 @@ jobs: steps: - checkout + - setup_google_dns - run: name: Install Dependencies command: | @@ -993,6 +1326,7 @@ jobs: - run: python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) - run: ruff check ./litellm # - run: python ./tests/documentation_tests/test_general_setting_keys.py + - run: python ./tests/code_coverage_tests/check_licenses.py - run: python ./tests/code_coverage_tests/router_code_coverage.py - run: python ./tests/code_coverage_tests/callback_manager_test.py - run: python ./tests/code_coverage_tests/recursive_detector.py @@ -1005,6 +1339,7 @@ jobs: - run: python ./tests/code_coverage_tests/ensure_async_clients_test.py - run: python ./tests/code_coverage_tests/enforce_llms_folder_style.py - run: python ./tests/documentation_tests/test_circular_imports.py + - run: python ./tests/code_coverage_tests/prevent_key_leaks_in_exceptions.py - run: helm lint ./deploy/charts/litellm-helm db_migration_disable_update_check: @@ -1014,6 +1349,24 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns + - run: + name: Install Python 3.9 + command: | + curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda + export PATH="$HOME/miniconda/bin:$PATH" + conda init bash + source ~/.bashrc + conda create -n myenv python=3.9 -y + conda activate myenv + python --version + - run: + name: Install Dependencies + command: | + pip install "pytest==7.3.1" + pip install "pytest-asyncio==0.21.1" + pip install aiohttp - run: name: Build Docker image command: | @@ -1021,29 +1374,48 @@ jobs: - run: name: Run Docker container command: | - docker run --name my-app \ + docker run -d \ -p 4000:4000 \ -e DATABASE_URL=$PROXY_DATABASE_URL \ -e DISABLE_SCHEMA_UPDATE="True" \ -v $(pwd)/litellm/proxy/example_config_yaml/bad_schema.prisma:/app/schema.prisma \ -v $(pwd)/litellm/proxy/example_config_yaml/bad_schema.prisma:/app/litellm/proxy/schema.prisma \ -v $(pwd)/litellm/proxy/example_config_yaml/disable_schema_update.yaml:/app/config.yaml \ + --name my-app \ myapp:latest \ --config /app/config.yaml \ - --port 4000 > docker_output.log 2>&1 || true + --port 4000 - run: - name: Display Docker logs - command: cat docker_output.log - - run: - name: Check for expected error + name: Install curl and dockerize command: | - if grep -q "prisma schema out of sync with db. Consider running these sql_commands to sync the two" docker_output.log; then - echo "Expected error found. Test passed." + sudo apt-get update + sudo apt-get install -y curl + sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz + sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz + sudo rm dockerize-linux-amd64-v0.6.1.tar.gz + + - run: + name: Wait for container to be ready + command: dockerize -wait http://localhost:4000 -timeout 1m + - run: + name: Check container logs for expected message + command: | + echo "=== Printing Full Container Startup Logs ===" + docker logs my-app + echo "=== End of Full Container Startup Logs ===" + + if docker logs my-app 2>&1 | grep -q "prisma schema out of sync with db. Consider running these sql_commands to sync the two"; then + echo "Expected message found in logs. Test passed." else - echo "Expected error not found. Test failed." - cat docker_output.log + echo "Expected message not found in logs. Test failed." exit 1 fi + - run: + name: Run Basic Proxy Startup Tests (Health Readiness and Chat Completion) + command: | + python -m pytest -vv tests/basic_proxy_startup_tests -x --junitxml=test-results/junit-2.xml --durations=5 + no_output_timeout: 120m + build_and_test: machine: @@ -1052,6 +1424,7 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns - run: name: Install Docker CLI (In case it's not already installed) command: | @@ -1099,7 +1472,7 @@ jobs: pip install "aiodynamo==23.10.1" pip install "asyncio==3.4.3" pip install "PyGithub==1.59.1" - pip install "openai==1.54.0 " + pip install "openai==1.68.2" - run: name: Install Grype command: | @@ -1174,19 +1547,20 @@ jobs: command: | pwd ls - python -m pytest -s -vv tests/*.py -x --junitxml=test-results/junit.xml --durations=5 --ignore=tests/otel_tests --ignore=tests/pass_through_tests --ignore=tests/proxy_admin_ui_tests --ignore=tests/load_tests --ignore=tests/llm_translation --ignore=tests/image_gen_tests --ignore=tests/pass_through_unit_tests + python -m pytest -s -vv tests/*.py -x --junitxml=test-results/junit.xml --durations=5 --ignore=tests/otel_tests --ignore=tests/spend_tracking_tests --ignore=tests/pass_through_tests --ignore=tests/proxy_admin_ui_tests --ignore=tests/load_tests --ignore=tests/llm_translation --ignore=tests/llm_responses_api_testing --ignore=tests/mcp_tests --ignore=tests/guardrails_tests --ignore=tests/image_gen_tests --ignore=tests/pass_through_unit_tests no_output_timeout: 120m # Store test results - store_test_results: path: test-results - e2e_openai_misc_endpoints: + e2e_openai_endpoints: machine: image: ubuntu-2204:2023.10.1 resource_class: xlarge working_directory: ~/project steps: - checkout + - setup_google_dns - run: name: Install Docker CLI (In case it's not already installed) command: | @@ -1223,6 +1597,7 @@ jobs: pip install "boto3==1.34.34" pip install "aioboto3==12.3.0" pip install langchain + pip install "langchain_mcp_adapters==0.0.5" pip install "langfuse>=2.0.0" pip install "logfire==0.29.0" pip install numpydoc @@ -1235,7 +1610,7 @@ jobs: pip install "aiodynamo==23.10.1" pip install "asyncio==3.4.3" pip install "PyGithub==1.59.1" - pip install "openai==1.54.0 " + pip install "openai==1.68.2" # Run pytest and generate JUnit XML report - run: name: Build Docker image @@ -1297,7 +1672,7 @@ jobs: command: | pwd ls - python -m pytest -s -vv tests/openai_misc_endpoints_tests --junitxml=test-results/junit.xml --durations=5 + python -m pytest -s -vv tests/openai_endpoints_tests --junitxml=test-results/junit.xml --durations=5 no_output_timeout: 120m # Store test results @@ -1310,6 +1685,7 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns - run: name: Install Docker CLI (In case it's not already installed) command: | @@ -1357,7 +1733,7 @@ jobs: pip install "aiodynamo==23.10.1" pip install "asyncio==3.4.3" pip install "PyGithub==1.59.1" - pip install "openai==1.54.0 " + pip install "openai==1.68.2" - run: name: Build Docker image command: docker build -t my-app:latest -f ./docker/Dockerfile.database . @@ -1464,6 +1840,291 @@ jobs: # Store test results - store_test_results: path: test-results + proxy_spend_accuracy_tests: + machine: + image: ubuntu-2204:2023.10.1 + resource_class: xlarge + working_directory: ~/project + steps: + - checkout + - setup_google_dns + - run: + name: Install Docker CLI (In case it's not already installed) + command: | + sudo apt-get update + sudo apt-get install -y docker-ce docker-ce-cli containerd.io + - run: + name: Install Python 3.9 + command: | + curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda + export PATH="$HOME/miniconda/bin:$PATH" + conda init bash + source ~/.bashrc + conda create -n myenv python=3.9 -y + conda activate myenv + python --version + - run: + name: Install Dependencies + command: | + pip install "pytest==7.3.1" + pip install "pytest-asyncio==0.21.1" + pip install aiohttp + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + - run: + name: Build Docker image + command: docker build -t my-app:latest -f ./docker/Dockerfile.database . + - run: + name: Run Docker container + # intentionally give bad redis credentials here + # the OTEL test - should get this as a trace + command: | + docker run -d \ + -p 4000:4000 \ + -e DATABASE_URL=$PROXY_DATABASE_URL \ + -e REDIS_HOST=$REDIS_HOST \ + -e REDIS_PASSWORD=$REDIS_PASSWORD \ + -e REDIS_PORT=$REDIS_PORT \ + -e LITELLM_MASTER_KEY="sk-1234" \ + -e OPENAI_API_KEY=$OPENAI_API_KEY \ + -e LITELLM_LICENSE=$LITELLM_LICENSE \ + -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ + -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ + -e USE_DDTRACE=True \ + -e DD_API_KEY=$DD_API_KEY \ + -e DD_SITE=$DD_SITE \ + -e AWS_REGION_NAME=$AWS_REGION_NAME \ + --name my-app \ + -v $(pwd)/litellm/proxy/example_config_yaml/spend_tracking_config.yaml:/app/config.yaml \ + my-app:latest \ + --config /app/config.yaml \ + --port 4000 \ + --detailed_debug \ + - run: + name: Install curl and dockerize + command: | + sudo apt-get update + sudo apt-get install -y curl + sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz + sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz + sudo rm dockerize-linux-amd64-v0.6.1.tar.gz + - run: + name: Start outputting logs + command: docker logs -f my-app + background: true + - run: + name: Wait for app to be ready + command: dockerize -wait http://localhost:4000 -timeout 5m + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/spend_tracking_tests -x --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: + 120m + # Clean up first container + - run: + name: Stop and remove first container + command: | + docker stop my-app + docker rm my-app + + proxy_multi_instance_tests: + machine: + image: ubuntu-2204:2023.10.1 + resource_class: xlarge + working_directory: ~/project + steps: + - checkout + - setup_google_dns + - run: + name: Install Docker CLI (In case it's not already installed) + command: | + sudo apt-get update + sudo apt-get install -y docker-ce docker-ce-cli containerd.io + - run: + name: Install Python 3.9 + command: | + curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda + export PATH="$HOME/miniconda/bin:$PATH" + conda init bash + source ~/.bashrc + conda create -n myenv python=3.9 -y + conda activate myenv + python --version + - run: + name: Install Dependencies + command: | + pip install "pytest==7.3.1" + pip install "pytest-asyncio==0.21.1" + pip install aiohttp + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-mock==3.12.0" + pip install "pytest-asyncio==0.21.1" + - run: + name: Build Docker image + command: docker build -t my-app:latest -f ./docker/Dockerfile.database . + - run: + name: Run Docker container 1 + # intentionally give bad redis credentials here + # the OTEL test - should get this as a trace + command: | + docker run -d \ + -p 4000:4000 \ + -e DATABASE_URL=$PROXY_DATABASE_URL \ + -e REDIS_HOST=$REDIS_HOST \ + -e REDIS_PASSWORD=$REDIS_PASSWORD \ + -e REDIS_PORT=$REDIS_PORT \ + -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_LICENSE=$LITELLM_LICENSE \ + -e USE_DDTRACE=True \ + -e DD_API_KEY=$DD_API_KEY \ + -e DD_SITE=$DD_SITE \ + --name my-app \ + -v $(pwd)/litellm/proxy/example_config_yaml/multi_instance_simple_config.yaml:/app/config.yaml \ + my-app:latest \ + --config /app/config.yaml \ + --port 4000 \ + --detailed_debug \ + - run: + name: Run Docker container 2 + command: | + docker run -d \ + -p 4001:4001 \ + -e DATABASE_URL=$PROXY_DATABASE_URL \ + -e REDIS_HOST=$REDIS_HOST \ + -e REDIS_PASSWORD=$REDIS_PASSWORD \ + -e REDIS_PORT=$REDIS_PORT \ + -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_LICENSE=$LITELLM_LICENSE \ + -e USE_DDTRACE=True \ + -e DD_API_KEY=$DD_API_KEY \ + -e DD_SITE=$DD_SITE \ + --name my-app-2 \ + -v $(pwd)/litellm/proxy/example_config_yaml/multi_instance_simple_config.yaml:/app/config.yaml \ + my-app:latest \ + --config /app/config.yaml \ + --port 4001 \ + --detailed_debug + - run: + name: Install curl and dockerize + command: | + sudo apt-get update + sudo apt-get install -y curl + sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz + sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz + sudo rm dockerize-linux-amd64-v0.6.1.tar.gz + - run: + name: Start outputting logs + command: docker logs -f my-app + background: true + - run: + name: Wait for instance 1 to be ready + command: dockerize -wait http://localhost:4000 -timeout 5m + - run: + name: Wait for instance 2 to be ready + command: dockerize -wait http://localhost:4001 -timeout 5m + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/multi_instance_e2e_tests -x --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: + 120m + # Clean up first container + # Store test results + - store_test_results: + path: test-results + + proxy_store_model_in_db_tests: + machine: + image: ubuntu-2204:2023.10.1 + resource_class: xlarge + working_directory: ~/project + steps: + - checkout + - setup_google_dns + - run: + name: Install Docker CLI (In case it's not already installed) + command: | + sudo apt-get update + sudo apt-get install -y docker-ce docker-ce-cli containerd.io + - run: + name: Install Python 3.9 + command: | + curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda + export PATH="$HOME/miniconda/bin:$PATH" + conda init bash + source ~/.bashrc + conda create -n myenv python=3.9 -y + conda activate myenv + python --version + - run: + name: Install Dependencies + command: | + pip install "pytest==7.3.1" + pip install "pytest-asyncio==0.21.1" + pip install aiohttp + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-mock==3.12.0" + pip install "pytest-asyncio==0.21.1" + pip install "assemblyai==0.37.0" + - run: + name: Build Docker image + command: docker build -t my-app:latest -f ./docker/Dockerfile.database . + - run: + name: Run Docker container + # intentionally give bad redis credentials here + # the OTEL test - should get this as a trace + command: | + docker run -d \ + -p 4000:4000 \ + -e DATABASE_URL=$CLEAN_STORE_MODEL_IN_DB_DATABASE_URL \ + -e STORE_MODEL_IN_DB="True" \ + -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_LICENSE=$LITELLM_LICENSE \ + --name my-app \ + -v $(pwd)/litellm/proxy/example_config_yaml/store_model_db_config.yaml:/app/config.yaml \ + my-app:latest \ + --config /app/config.yaml \ + --port 4000 \ + --detailed_debug \ + - run: + name: Install curl and dockerize + command: | + sudo apt-get update + sudo apt-get install -y curl + sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz + sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz + sudo rm dockerize-linux-amd64-v0.6.1.tar.gz + - run: + name: Start outputting logs + command: docker logs -f my-app + background: true + - run: + name: Wait for app to be ready + command: dockerize -wait http://localhost:4000 -timeout 5m + - run: + name: Run tests + command: | + pwd + ls + python -m pytest -vv tests/store_model_in_db_tests -x --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: + 120m + # Clean up first container + proxy_build_from_pip_tests: # Change from docker to machine executor machine: @@ -1472,6 +2133,7 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns # Remove Docker CLI installation since it's already available in machine executor - run: name: Install Python 3.13 @@ -1569,6 +2231,7 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns - run: name: Install Docker CLI (In case it's not already installed) command: | @@ -1593,9 +2256,10 @@ jobs: pip install "pytest-asyncio==0.21.1" pip install "google-cloud-aiplatform==1.43.0" pip install aiohttp - pip install "openai==1.54.0 " + pip install "openai==1.68.2" + pip install "assemblyai==0.37.0" python -m pip install --upgrade pip - pip install "pydantic==2.7.1" + pip install "pydantic==2.10.2" pip install "pytest==7.3.1" pip install "pytest-mock==3.12.0" pip install "pytest-asyncio==0.21.1" @@ -1606,12 +2270,15 @@ jobs: pip install prisma pip install fastapi pip install jsonschema - pip install "httpx==0.24.1" + pip install "httpx==0.27.0" pip install "anyio==3.7.1" pip install "asyncio==3.4.3" pip install "PyGithub==1.59.1" pip install "google-cloud-aiplatform==1.59.0" - pip install anthropic + pip install "anthropic==0.49.0" + pip install "langchain_mcp_adapters==0.0.5" + pip install "langchain_openai==0.2.1" + pip install "langgraph==0.3.18" # Run pytest and generate JUnit XML report - run: name: Build Docker image @@ -1626,6 +2293,7 @@ jobs: -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e GEMINI_API_KEY=$GEMINI_API_KEY \ -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \ + -e ASSEMBLYAI_API_KEY=$ASSEMBLYAI_API_KEY \ -e USE_DDTRACE=True \ -e DD_API_KEY=$DD_API_KEY \ -e DD_SITE=$DD_SITE \ @@ -1652,11 +2320,44 @@ jobs: - run: name: Wait for app to be ready command: dockerize -wait http://localhost:4000 -timeout 5m + # Add Ruby installation and testing before the existing Node.js and Python tests + - run: + name: Install Ruby and Bundler + command: | + # Import GPG keys first + gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB || { + curl -sSL https://rvm.io/mpapis.asc | gpg --import - + curl -sSL https://rvm.io/pkuczynski.asc | gpg --import - + } + + # Install Ruby version manager (RVM) + curl -sSL https://get.rvm.io | bash -s stable + + # Source RVM from the correct location + source $HOME/.rvm/scripts/rvm + + # Install Ruby 3.2.2 + rvm install 3.2.2 + rvm use 3.2.2 --default + + # Install latest Bundler + gem install bundler + + - run: + name: Run Ruby tests + command: | + source $HOME/.rvm/scripts/rvm + cd tests/pass_through_tests/ruby_passthrough_tests + bundle install + bundle exec rspec + no_output_timeout: 30m # New steps to run Node.js test - run: name: Install Node.js command: | + export DEBIAN_FRONTEND=noninteractive curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - + sudo apt-get update sudo apt-get install -y nodejs node --version npm --version @@ -1705,7 +2406,7 @@ jobs: python -m venv venv . venv/bin/activate pip install coverage - coverage combine llm_translation_coverage logging_coverage litellm_router_coverage local_testing_coverage litellm_assistants_api_coverage auth_ui_unit_tests_coverage langfuse_coverage caching_coverage litellm_proxy_unit_tests_coverage image_gen_coverage pass_through_unit_tests_coverage batches_coverage + coverage combine llm_translation_coverage llm_responses_api_coverage mcp_coverage logging_coverage litellm_router_coverage local_testing_coverage litellm_assistants_api_coverage auth_ui_unit_tests_coverage langfuse_coverage caching_coverage litellm_proxy_unit_tests_coverage image_gen_coverage pass_through_unit_tests_coverage batches_coverage litellm_proxy_security_tests_coverage guardrails_coverage coverage xml - codecov/upload: file: ./coverage.xml @@ -1769,7 +2470,7 @@ jobs: circleci step halt fi - run: - name: Trigger Github Action for new Docker Container + Trigger Stable Release Testing + name: Trigger Github Action for new Docker Container + Trigger Load Testing command: | echo "Install TOML package." python3 -m pip install toml @@ -1779,9 +2480,117 @@ jobs: -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: Bearer $GITHUB_TOKEN" \ "https://api.github.com/repos/BerriAI/litellm/actions/workflows/ghcr_deploy.yml/dispatches" \ - -d "{\"ref\":\"main\", \"inputs\":{\"tag\":\"v${VERSION}\", \"commit_hash\":\"$CIRCLE_SHA1\"}}" - echo "triggering stable release server for version ${VERSION} and commit ${CIRCLE_SHA1}" - curl -X POST "https://proxyloadtester-production.up.railway.app/start/load/test?version=${VERSION}&commit_hash=${CIRCLE_SHA1}" + -d "{\"ref\":\"main\", \"inputs\":{\"tag\":\"v${VERSION}-nightly\", \"commit_hash\":\"$CIRCLE_SHA1\"}}" + echo "triggering load testing server for version ${VERSION} and commit ${CIRCLE_SHA1}" + curl -X POST "https://proxyloadtester-production.up.railway.app/start/load/test?version=${VERSION}&commit_hash=${CIRCLE_SHA1}&release_type=nightly" + + publish_proxy_extras: + docker: + - image: cimg/python:3.8 + working_directory: ~/project/litellm-proxy-extras + environment: + TWINE_USERNAME: __token__ + + steps: + - checkout: + path: ~/project + + - run: + name: Check if litellm-proxy-extras dir or pyproject.toml was modified + command: | + echo "Install TOML package." + python -m pip install toml + # Get current version from pyproject.toml + CURRENT_VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['version'])") + + # Get last published version from PyPI + LAST_VERSION=$(curl -s https://pypi.org/pypi/litellm-proxy-extras/json | python -c "import json, sys; print(json.load(sys.stdin)['info']['version'])") + + echo "Current version: $CURRENT_VERSION" + echo "Last published version: $LAST_VERSION" + + # Compare versions using Python's packaging.version + VERSION_COMPARE=$(python -c "from packaging import version; print(1 if version.parse('$CURRENT_VERSION') < version.parse('$LAST_VERSION') else 0)") + + echo "Version compare: $VERSION_COMPARE" + if [ "$VERSION_COMPARE" = "1" ]; then + echo "Error: Current version ($CURRENT_VERSION) is less than last published version ($LAST_VERSION)" + exit 1 + fi + + # If versions are equal or current is greater, check contents + pip download --no-deps litellm-proxy-extras==$LAST_VERSION -d /tmp + + echo "Contents of /tmp directory:" + ls -la /tmp + + # Find the downloaded file (could be .whl or .tar.gz) + DOWNLOADED_FILE=$(ls /tmp/litellm_proxy_extras-*) + echo "Downloaded file: $DOWNLOADED_FILE" + + # Extract based on file extension + if [[ "$DOWNLOADED_FILE" == *.whl ]]; then + echo "Extracting wheel file..." + unzip -q "$DOWNLOADED_FILE" -d /tmp/extracted + EXTRACTED_DIR="/tmp/extracted" + else + echo "Extracting tar.gz file..." + tar -xzf "$DOWNLOADED_FILE" -C /tmp + EXTRACTED_DIR="/tmp/litellm_proxy_extras-$LAST_VERSION" + fi + + echo "Contents of extracted package:" + ls -R "$EXTRACTED_DIR" + + # Compare contents + if ! diff -r "$EXTRACTED_DIR/litellm_proxy_extras" ./litellm_proxy_extras; then + if [ "$CURRENT_VERSION" = "$LAST_VERSION" ]; then + echo "Error: Changes detected in litellm-proxy-extras but version was not bumped" + echo "Current version: $CURRENT_VERSION" + echo "Last published version: $LAST_VERSION" + echo "Changes:" + diff -r "$EXTRACTED_DIR/litellm_proxy_extras" ./litellm_proxy_extras + exit 1 + fi + else + echo "No changes detected in litellm-proxy-extras. Skipping PyPI publish." + circleci step halt + fi + + - run: + name: Get new version + command: | + cd litellm-proxy-extras + NEW_VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['version'])") + echo "export NEW_VERSION=$NEW_VERSION" >> $BASH_ENV + + - run: + name: Check if versions match + command: | + cd ~/project + # Check pyproject.toml + CURRENT_VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['dependencies']['litellm-proxy-extras'].split('\"')[1])") + if [ "$CURRENT_VERSION" != "$NEW_VERSION" ]; then + echo "Error: Version in pyproject.toml ($CURRENT_VERSION) doesn't match new version ($NEW_VERSION)" + exit 1 + fi + + # Check requirements.txt + REQ_VERSION=$(grep -oP 'litellm-proxy-extras==\K[0-9.]+' requirements.txt) + if [ "$REQ_VERSION" != "$NEW_VERSION" ]; then + echo "Error: Version in requirements.txt ($REQ_VERSION) doesn't match new version ($NEW_VERSION)" + exit 1 + fi + + - run: + name: Publish to PyPI + command: | + cd litellm-proxy-extras + echo -e "[pypi]\nusername = $PYPI_PUBLISH_USERNAME\npassword = $PYPI_PUBLISH_PASSWORD" > ~/.pypirc + python -m pip install --upgrade pip build twine setuptools wheel + rm -rf build dist + python -m build + twine upload --verbose dist/* e2e_ui_testing: machine: @@ -1790,6 +2599,26 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns + - run: + name: Build UI + command: | + # Set up nvm + export NVM_DIR="/opt/circleci/.nvm" + source "$NVM_DIR/nvm.sh" + source "$NVM_DIR/bash_completion" + + # Install and use Node version + nvm install v18.17.0 + nvm use v18.17.0 + + cd ui/litellm-dashboard + + # Install dependencies first + npm install + + # Now source the build script + source ./build_ui.sh - run: name: Install Docker CLI (In case it's not already installed) command: | @@ -1815,9 +2644,9 @@ jobs: pip install "pytest-retry==1.6.3" pip install "pytest-asyncio==0.21.1" pip install aiohttp - pip install "openai==1.54.0 " + pip install "openai==1.68.2" python -m pip install --upgrade pip - pip install "pydantic==2.7.1" + pip install "pydantic==2.10.2" pip install "pytest==7.3.1" pip install "pytest-mock==3.12.0" pip install "pytest-asyncio==0.21.1" @@ -1834,6 +2663,7 @@ jobs: name: Install Playwright Browsers command: | npx playwright install + - run: name: Build Docker image command: docker build -t my-app:latest -f ./docker/Dockerfile.database . @@ -1884,6 +2714,7 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns - run: name: Build Docker image command: | @@ -1906,6 +2737,7 @@ jobs: working_directory: ~/project steps: - checkout + - setup_google_dns - run: name: Build Docker image command: | @@ -1938,6 +2770,12 @@ workflows: version: 2 build_and_test: jobs: + - using_litellm_on_windows: + filters: + branches: + only: + - main + - /litellm_.*/ - local_testing: filters: branches: @@ -1962,6 +2800,12 @@ workflows: only: - main - /litellm_.*/ + - litellm_proxy_security_tests: + filters: + branches: + only: + - main + - /litellm_.*/ - litellm_assistants_api_testing: filters: branches: @@ -1998,7 +2842,7 @@ workflows: only: - main - /litellm_.*/ - - e2e_openai_misc_endpoints: + - e2e_openai_endpoints: filters: branches: only: @@ -2010,6 +2854,24 @@ workflows: only: - main - /litellm_.*/ + - proxy_spend_accuracy_tests: + filters: + branches: + only: + - main + - /litellm_.*/ + - proxy_multi_instance_tests: + filters: + branches: + only: + - main + - /litellm_.*/ + - proxy_store_model_in_db_tests: + filters: + branches: + only: + - main + - /litellm_.*/ - proxy_build_from_pip_tests: filters: branches: @@ -2028,6 +2890,30 @@ workflows: only: - main - /litellm_.*/ + - mcp_testing: + filters: + branches: + only: + - main + - /litellm_.*/ + - guardrails_testing: + filters: + branches: + only: + - main + - /litellm_.*/ + - llm_responses_api_testing: + filters: + branches: + only: + - main + - /litellm_.*/ + - litellm_mapped_tests: + filters: + branches: + only: + - main + - /litellm_.*/ - batches_testing: filters: branches: @@ -2061,6 +2947,10 @@ workflows: - upload-coverage: requires: - llm_translation_testing + - mcp_testing + - guardrails_testing + - llm_responses_api_testing + - litellm_mapped_tests - batches_testing - litellm_utils_testing - pass_through_unit_testing @@ -2069,6 +2959,7 @@ workflows: - litellm_router_testing - caching_unit_tests - litellm_proxy_unit_testing + - litellm_proxy_security_tests - langfuse_logging_unit_tests - local_testing - litellm_assistants_api_testing @@ -2109,14 +3000,22 @@ workflows: only: - main - /litellm_.*/ + - publish_proxy_extras: + filters: + branches: + only: + - main - publish_to_pypi: requires: - local_testing - build_and_test - - e2e_openai_misc_endpoints + - e2e_openai_endpoints - load_testing - test_bad_database_url - llm_translation_testing + - mcp_testing + - llm_responses_api_testing + - litellm_mapped_tests - batches_testing - litellm_utils_testing - pass_through_unit_testing @@ -2130,13 +3029,16 @@ workflows: - db_migration_disable_update_check - e2e_ui_testing - litellm_proxy_unit_testing + - litellm_proxy_security_tests - installing_litellm_on_python - installing_litellm_on_python_3_13 - proxy_logging_guardrails_model_info_tests + - proxy_spend_accuracy_tests + - proxy_multi_instance_tests + - proxy_store_model_in_db_tests - proxy_build_from_pip_tests - proxy_pass_through_endpoint_tests - check_code_and_doc_quality - filters: - branches: - only: - - main + - publish_proxy_extras + - guardrails_testing + diff --git a/.circleci/requirements.txt b/.circleci/requirements.txt index 12e83a40f29..0e2362c4e3d 100644 --- a/.circleci/requirements.txt +++ b/.circleci/requirements.txt @@ -1,13 +1,15 @@ # used by CI/CD testing -openai==1.54.0 +openai==1.68.2 python-dotenv tiktoken importlib_metadata cohere -redis +redis==5.2.1 +redisvl==0.4.1 anthropic -orjson==3.9.15 -pydantic==2.7.1 +orjson==3.10.12 # fast /embedding responses +pydantic==2.10.2 google-cloud-aiplatform==1.43.0 -fastapi-sso==0.10.0 +fastapi-sso==0.16.0 uvloop==0.21.0 +mcp==1.5.0 # for MCP server diff --git a/.env.example b/.env.example index c87c2ef8fd4..24c2b608414 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # OpenAI OPENAI_API_KEY = "" -OPENAI_API_BASE = "" +OPENAI_BASE_URL = "" # Cohere COHERE_API_KEY = "" # OpenRouter @@ -20,3 +20,12 @@ REPLICATE_API_TOKEN = "" ANTHROPIC_API_KEY = "" # Infisical INFISICAL_TOKEN = "" +# Novita AI +NOVITA_API_KEY = "" +# INFINITY +INFINITY_API_KEY = "" + +# Development Configs +LITELLM_MASTER_KEY = "sk-1234" +DATABASE_URL = "postgresql://llmproxy:dbpassword9090@db:5432/litellm" +STORE_MODEL_IN_DB = "True" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3615d030bfa..85f1769b6f3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,6 +6,16 @@ +## Pre-Submission checklist + +**Please complete all items before asking a LiteLLM maintainer to review your PR** + +- [ ] I have Added testing in the [`tests/litellm/`](https://github.com/BerriAI/litellm/tree/main/tests/litellm) directory, **Adding at least 1 test is a hard requirement** - [see details](https://docs.litellm.ai/docs/extras/contributing_code) +- [ ] I have added a screenshot of my new test passing locally +- [ ] My PR passes all unit tests on [`make test-unit`](https://docs.litellm.ai/docs/extras/contributing_code) +- [ ] My PR's scope is as isolated as possible, it only solves 1 specific problem + + ## Type @@ -20,10 +30,4 @@ ## Changes - - -## [REQUIRED] Testing - Attach a screenshot of any new tests passing locally -If UI changes, send a screenshot/GIF of working UI fixes - - diff --git a/.github/workflows/ghcr_deploy.yml b/.github/workflows/ghcr_deploy.yml index 587abc8ea74..3fc710ad22b 100644 --- a/.github/workflows/ghcr_deploy.yml +++ b/.github/workflows/ghcr_deploy.yml @@ -80,7 +80,6 @@ jobs: permissions: contents: read packages: write - # steps: - name: Checkout repository uses: actions/checkout@v4 @@ -112,10 +111,57 @@ jobs: with: context: . push: true - tags: ${{ steps.meta.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta.outputs.tags }}-${{ github.event.inputs.release_type }} # if a tag is provided, use that, otherwise use the release tag, and if neither is available, use 'latest' + tags: | + ${{ steps.meta.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, + ${{ steps.meta.outputs.tags }}-${{ github.event.inputs.release_type }} + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }}, + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm:main-stable', env.REGISTRY) || '' }} labels: ${{ steps.meta.outputs.labels }} platforms: local,linux/amd64,linux/arm64,linux/arm64/v8 - + + build-and-push-image-ee: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.commit_hash }} + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for EE Dockerfile + id: meta-ee + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee + # Configure multi platform Docker builds + - name: Set up QEMU + uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345 + + - name: Build and push EE Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + file: Dockerfile + push: true + tags: | + ${{ steps.meta-ee.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, + ${{ steps.meta-ee.outputs.tags }}-${{ github.event.inputs.release_type }} + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-ee:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }}, + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-ee:main-stable', env.REGISTRY) || '' }} + labels: ${{ steps.meta-ee.outputs.labels }} + platforms: local,linux/amd64,linux/arm64,linux/arm64/v8 + build-and-push-image-database: runs-on: ubuntu-latest permissions: @@ -151,8 +197,12 @@ jobs: context: . file: ./docker/Dockerfile.database push: true - tags: ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.release_type }} - labels: ${{ steps.meta-database.outputs.labels }} + tags: | + ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, + ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.release_type }} + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-database:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }}, + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-database:main-stable', env.REGISTRY) || '' }} + labels: ${{ steps.meta-database.outputs.labels }} platforms: local,linux/amd64,linux/arm64,linux/arm64/v8 build-and-push-image-non_root: @@ -190,7 +240,11 @@ jobs: context: . file: ./docker/Dockerfile.non_root push: true - tags: ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.release_type }} + tags: | + ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, + ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.release_type }} + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-non_root:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }}, + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-non_root:main-stable', env.REGISTRY) || '' }} labels: ${{ steps.meta-non_root.outputs.labels }} platforms: local,linux/amd64,linux/arm64,linux/arm64/v8 @@ -229,7 +283,11 @@ jobs: context: . file: ./litellm-js/spend-logs/Dockerfile push: true - tags: ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.release_type }} + tags: | + ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, + ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.release_type }} + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-spend_logs:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }}, + ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-spend_logs:main-stable', env.REGISTRY) || '' }} platforms: local,linux/amd64,linux/arm64,linux/arm64/v8 build-and-push-helm-chart: diff --git a/.github/workflows/helm_unit_test.yml b/.github/workflows/helm_unit_test.yml new file mode 100644 index 00000000000..c4b83af70a1 --- /dev/null +++ b/.github/workflows/helm_unit_test.yml @@ -0,0 +1,27 @@ +name: Helm unit test + +on: + pull_request: + push: + branches: + - main + +jobs: + unit-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Helm 3.11.1 + uses: azure/setup-helm@v1 + with: + version: '3.11.1' + + - name: Install Helm Unit Test Plugin + run: | + helm plugin install https://github.com/helm-unittest/helm-unittest --version v0.4.4 + + - name: Run unit tests + run: + helm unittest -f 'tests/*.yaml' deploy/charts/litellm-helm \ No newline at end of file diff --git a/.github/workflows/interpret_load_test.py b/.github/workflows/interpret_load_test.py index b1a28e069b8..6b5e6535d79 100644 --- a/.github/workflows/interpret_load_test.py +++ b/.github/workflows/interpret_load_test.py @@ -52,6 +52,41 @@ def interpret_results(csv_file): return markdown_table +def _get_docker_run_command_stable_release(release_version): + return f""" +\n\n +## Docker Run LiteLLM Proxy + +``` +docker run \\ +-e STORE_MODEL_IN_DB=True \\ +-p 4000:4000 \\ +ghcr.io/berriai/litellm:litellm_stable_release_branch-{release_version} +``` + """ + + +def _get_docker_run_command(release_version): + return f""" +\n\n +## Docker Run LiteLLM Proxy + +``` +docker run \\ +-e STORE_MODEL_IN_DB=True \\ +-p 4000:4000 \\ +ghcr.io/berriai/litellm:main-{release_version} +``` + """ + + +def get_docker_run_command(release_version): + if "stable" in release_version: + return _get_docker_run_command_stable_release(release_version) + else: + return _get_docker_run_command(release_version) + + if __name__ == "__main__": csv_file = "load_test_stats.csv" # Change this to the path of your CSV file markdown_table = interpret_results(csv_file) @@ -79,17 +114,7 @@ if __name__ == "__main__": start_index = latest_release.body.find("Load Test LiteLLM Proxy Results") existing_release_body = latest_release.body[:start_index] - docker_run_command = f""" -\n\n -## Docker Run LiteLLM Proxy - -``` -docker run \\ --e STORE_MODEL_IN_DB=True \\ --p 4000:4000 \\ -ghcr.io/berriai/litellm:main-{release_version} -``` - """ + docker_run_command = get_docker_run_command(release_version) print("docker run command: ", docker_run_command) new_release_body = ( diff --git a/.github/workflows/locustfile.py b/.github/workflows/locustfile.py index 96dd8e19905..36dbeee9c48 100644 --- a/.github/workflows/locustfile.py +++ b/.github/workflows/locustfile.py @@ -8,7 +8,7 @@ class MyUser(HttpUser): def chat_completion(self): headers = { "Content-Type": "application/json", - "Authorization": "Bearer sk-ZoHqrLIs2-5PzJrqBaviAA", + "Authorization": "Bearer sk-8N1tLOOyH8TIxwOLahhIVg", # Include any additional headers you may need for authentication, etc. } diff --git a/.github/workflows/publish-migrations.yml b/.github/workflows/publish-migrations.yml new file mode 100644 index 00000000000..8e5a67bcf85 --- /dev/null +++ b/.github/workflows/publish-migrations.yml @@ -0,0 +1,206 @@ +name: Publish Prisma Migrations + +permissions: + contents: write + pull-requests: write + +on: + push: + paths: + - 'schema.prisma' # Check root schema.prisma + branches: + - main + +jobs: + publish-migrations: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:14 + env: + POSTGRES_DB: temp_db + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + # Add shadow database service + postgres_shadow: + image: postgres:14 + env: + POSTGRES_DB: shadow_db + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5433:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Dependencies + run: | + pip install prisma + pip install python-dotenv + + - name: Generate Initial Migration if None Exists + env: + DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/temp_db" + DIRECT_URL: "postgresql://postgres:postgres@localhost:5432/temp_db" + SHADOW_DATABASE_URL: "postgresql://postgres:postgres@localhost:5433/shadow_db" + run: | + mkdir -p deploy/migrations + echo 'provider = "postgresql"' > deploy/migrations/migration_lock.toml + + if [ -z "$(ls -A deploy/migrations/2* 2>/dev/null)" ]; then + echo "No existing migrations found, creating baseline..." + VERSION=$(date +%Y%m%d%H%M%S) + mkdir -p deploy/migrations/${VERSION}_initial + + echo "Generating initial migration..." + # Save raw output for debugging + prisma migrate diff \ + --from-empty \ + --to-schema-datamodel schema.prisma \ + --shadow-database-url "${SHADOW_DATABASE_URL}" \ + --script > deploy/migrations/${VERSION}_initial/raw_migration.sql + + echo "Raw migration file content:" + cat deploy/migrations/${VERSION}_initial/raw_migration.sql + + echo "Cleaning migration file..." + # Clean the file + sed '/^Installing/d' deploy/migrations/${VERSION}_initial/raw_migration.sql > deploy/migrations/${VERSION}_initial/migration.sql + + # Verify the migration file + if [ ! -s deploy/migrations/${VERSION}_initial/migration.sql ]; then + echo "ERROR: Migration file is empty after cleaning" + echo "Original content was:" + cat deploy/migrations/${VERSION}_initial/raw_migration.sql + exit 1 + fi + + echo "Final migration file content:" + cat deploy/migrations/${VERSION}_initial/migration.sql + + # Verify it starts with SQL + if ! head -n 1 deploy/migrations/${VERSION}_initial/migration.sql | grep -q "^--\|^CREATE\|^ALTER"; then + echo "ERROR: Migration file does not start with SQL command or comment" + echo "First line is:" + head -n 1 deploy/migrations/${VERSION}_initial/migration.sql + echo "Full content is:" + cat deploy/migrations/${VERSION}_initial/migration.sql + exit 1 + fi + + echo "Initial migration generated at $(date -u)" > deploy/migrations/${VERSION}_initial/README.md + fi + + - name: Compare and Generate Migration + if: success() + env: + DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/temp_db" + DIRECT_URL: "postgresql://postgres:postgres@localhost:5432/temp_db" + SHADOW_DATABASE_URL: "postgresql://postgres:postgres@localhost:5433/shadow_db" + run: | + # Create temporary migration workspace + mkdir -p temp_migrations + + # Copy existing migrations (will not fail if directory is empty) + cp -r deploy/migrations/* temp_migrations/ 2>/dev/null || true + + VERSION=$(date +%Y%m%d%H%M%S) + + # Generate diff against existing migrations or empty state + prisma migrate diff \ + --from-migrations temp_migrations \ + --to-schema-datamodel schema.prisma \ + --shadow-database-url "${SHADOW_DATABASE_URL}" \ + --script > temp_migrations/migration_${VERSION}.sql + + # Check if there are actual changes + if [ -s temp_migrations/migration_${VERSION}.sql ]; then + echo "Changes detected, creating new migration" + mkdir -p deploy/migrations/${VERSION}_schema_update + mv temp_migrations/migration_${VERSION}.sql deploy/migrations/${VERSION}_schema_update/migration.sql + echo "Migration generated at $(date -u)" > deploy/migrations/${VERSION}_schema_update/README.md + else + echo "No schema changes detected" + exit 0 + fi + + - name: Verify Migration + if: success() + env: + DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/temp_db" + DIRECT_URL: "postgresql://postgres:postgres@localhost:5432/temp_db" + SHADOW_DATABASE_URL: "postgresql://postgres:postgres@localhost:5433/shadow_db" + run: | + # Create test database + psql "${SHADOW_DATABASE_URL}" -c 'CREATE DATABASE migration_test;' + + # Apply all migrations in order to verify + for migration in deploy/migrations/*/migration.sql; do + echo "Applying migration: $migration" + psql "${SHADOW_DATABASE_URL}" -f $migration + done + + # Add this step before create-pull-request to debug permissions + - name: Check Token Permissions + run: | + echo "Checking token permissions..." + curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/BerriAI/litellm/collaborators + + echo "\nChecking if token can create PRs..." + curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/BerriAI/litellm + + # Add this debug step before git push + - name: Debug Changed Files + run: | + echo "Files staged for commit:" + git diff --name-status --staged + + echo "\nAll changed files:" + git status + + - name: Create Pull Request + if: success() + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore: update prisma migrations" + title: "Update Prisma Migrations" + body: | + Auto-generated migration based on schema.prisma changes. + + Generated files: + - deploy/migrations/${VERSION}_schema_update/migration.sql + - deploy/migrations/${VERSION}_schema_update/README.md + branch: feat/prisma-migration-${{ env.VERSION }} + base: main + delete-branch: true + + - name: Generate and Save Migrations + run: | + # Only add migration files + git add deploy/migrations/ + git status # Debug what's being committed + git commit -m "chore: update prisma migrations" diff --git a/.github/workflows/test-linting.yml b/.github/workflows/test-linting.yml new file mode 100644 index 00000000000..0e1c895c3a4 --- /dev/null +++ b/.github/workflows/test-linting.yml @@ -0,0 +1,57 @@ +name: LiteLLM Linting + +on: + pull_request: + branches: [ main ] + +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Install dependencies + run: | + pip install openai==1.68.2 + poetry install --with dev + pip install openai==1.68.2 + + + + - name: Run Black formatting + run: | + cd litellm + poetry run black . + cd .. + + - name: Run Ruff linting + run: | + cd litellm + poetry run ruff check . + cd .. + + - name: Run MyPy type checking + run: | + cd litellm + poetry run mypy . --ignore-missing-imports + cd .. + + - name: Check for circular imports + run: | + cd litellm + poetry run 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) \ No newline at end of file diff --git a/.github/workflows/test-litellm.yml b/.github/workflows/test-litellm.yml new file mode 100644 index 00000000000..a2b9e6c7c34 --- /dev/null +++ b/.github/workflows/test-litellm.yml @@ -0,0 +1,39 @@ +name: LiteLLM Mock Tests (folder - tests/litellm) + +on: + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 8 + + steps: + - uses: actions/checkout@v4 + + - name: Thank You Message + run: | + echo "### 🙏 Thank you for contributing to LiteLLM!" >> $GITHUB_STEP_SUMMARY + echo "Your PR is being tested now. We appreciate your help in making LiteLLM better!" >> $GITHUB_STEP_SUMMARY + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Install dependencies + run: | + poetry install --with dev,proxy-dev --extras proxy + poetry run pip install pytest-xdist + - name: Setup litellm-enterprise as local package + run: | + cd enterprise + python -m pip install -e . + cd .. + - name: Run tests + run: | + poetry run pytest tests/litellm -x -vv -n 4 \ No newline at end of file diff --git a/.gitignore b/.gitignore index f8779ccae72..93134dabbf4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.python-version .venv .env .newenv @@ -71,3 +72,21 @@ tests/local_testing/log.txt .codegpt litellm/proxy/_new_new_secret_config.yaml +litellm/proxy/custom_guardrail.py +.mypy_cache/* +litellm/proxy/_experimental/out/404.html +litellm/proxy/_experimental/out/404.html +litellm/proxy/_experimental/out/model_hub.html +.mypy_cache/* +litellm/proxy/application.log +tests/llm_translation/vertex_test_account.json +tests/llm_translation/test_vertex_key.json +litellm/proxy/migrations/0_init/migration.sql +litellm/proxy/db/migrations/0_init/migration.sql +litellm/proxy/db/migrations/* +litellm/proxy/migrations/*config.yaml +litellm/proxy/migrations/* +config.yaml +tests/litellm/litellm_core_utils/llm_cost_calc/log.txt +tests/test_custom_dir/* +test.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b8567fce76d..d247c93c2fd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,44 +6,35 @@ repos: entry: pyright language: system types: [python] - files: ^litellm/ + files: ^(litellm/|litellm_proxy_extras/|enterprise/) - id: isort name: isort entry: isort language: system types: [python] - files: litellm/.*\.py + files: (litellm/|litellm_proxy_extras/|enterprise/).*\.py exclude: ^litellm/__init__.py$ -- repo: https://github.com/psf/black - rev: 24.2.0 - hooks: - - id: black + - id: black + name: black + entry: poetry run black + language: system + types: [python] + files: (litellm/|litellm_proxy_extras/|enterprise/).*\.py - repo: https://github.com/pycqa/flake8 rev: 7.0.0 # The version of flake8 to use hooks: - id: flake8 - exclude: ^litellm/tests/|^litellm/proxy/tests/ + exclude: ^litellm/tests/|^litellm/proxy/tests/|^litellm/tests/litellm/|^tests/litellm/ additional_dependencies: [flake8-print] - files: litellm/.*\.py - # - id: flake8 - # name: flake8 (router.py function length) - # files: ^litellm/router\.py$ - # args: [--max-function-length=40] - # # additional_dependencies: [flake8-functions] + files: (litellm/|litellm_proxy_extras/).*\.py - repo: https://github.com/python-poetry/poetry rev: 1.8.0 hooks: - id: poetry-check + files: ^(pyproject.toml|litellm-proxy-extras/pyproject.toml)$ - repo: local hooks: - id: check-files-match name: Check if files match entry: python3 ci_cd/check_files_match.py - language: system - # - id: check-file-length - # name: Check file length - # entry: python check_file_length.py - # args: ["10000"] # set your desired maximum number of lines - # language: python - # files: litellm/.*\.py - # exclude: ^litellm/tests/ \ No newline at end of file + language: system \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index dd699c795b0..3a74c46e688 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,8 +12,7 @@ WORKDIR /app USER root # Install build dependencies -RUN apk update && \ - apk add --no-cache gcc python3-dev openssl openssl-dev +RUN apk add --no-cache gcc python3-dev openssl openssl-dev RUN pip install --upgrade pip && \ @@ -37,9 +36,6 @@ RUN pip install dist/*.whl # install dependencies as wheels RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt -# install semantic-cache [Experimental]- we need this here and not in requirements.txt because redisvl pins to pydantic 1.0 -RUN pip install redisvl==0.0.7 --no-deps - # ensure pyjwt is used, not jwt RUN pip uninstall jwt -y RUN pip uninstall PyJWT -y @@ -55,8 +51,7 @@ FROM $LITELLM_RUNTIME_IMAGE AS runtime USER root # Install runtime dependencies -RUN apk update && \ - apk add --no-cache openssl +RUN apk add --no-cache openssl WORKDIR /app # Copy the current directory contents into the container at /app diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..a06509312db --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +# LiteLLM Makefile +# Simple Makefile for running tests and basic development tasks + +.PHONY: help test test-unit test-integration lint format + +# Default target +help: + @echo "Available commands:" + @echo " make test - Run all tests" + @echo " make test-unit - Run unit tests" + @echo " make test-integration - Run integration tests" + @echo " make test-unit-helm - Run helm unit tests" + +install-dev: + poetry install --with dev + +install-proxy-dev: + poetry install --with dev,proxy-dev + +lint: install-dev + poetry run pip install types-requests types-setuptools types-redis types-PyYAML + cd litellm && poetry run mypy . --ignore-missing-imports + +# Testing +test: + poetry run pytest tests/ + +test-unit: + poetry run pytest tests/litellm/ + +test-integration: + poetry run pytest tests/ -k "not litellm" + +test-unit-helm: + helm unittest -f 'tests/*.yaml' deploy/charts/litellm-helm \ No newline at end of file diff --git a/README.md b/README.md index c7ea44cf462..01a60310522 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,6 @@ PyPI Version - - CircleCI - Y Combinator W23 @@ -40,7 +37,7 @@ LiteLLM manages: [**Jump to LiteLLM Proxy (LLM Gateway) Docs**](https://github.com/BerriAI/litellm?tab=readme-ov-file#openai-proxy---docs)
[**Jump to Supported LLM Providers**](https://github.com/BerriAI/litellm?tab=readme-ov-file#supported-providers-docs) -🚨 **Stable Release:** Use docker images with the `-stable` tag. These have undergone 12 hour load tests, before being published. +🚨 **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+). @@ -64,7 +61,7 @@ import os ## set ENV variables os.environ["OPENAI_API_KEY"] = "your-openai-key" -os.environ["ANTHROPIC_API_KEY"] = "your-cohere-key" +os.environ["ANTHROPIC_API_KEY"] = "your-anthropic-key" messages = [{ "content": "Hello, how are you?","role": "user"}] @@ -187,13 +184,13 @@ os.environ["LANGFUSE_PUBLIC_KEY"] = "" os.environ["LANGFUSE_SECRET_KEY"] = "" os.environ["ATHINA_API_KEY"] = "your-athina-api-key" -os.environ["OPENAI_API_KEY"] +os.environ["OPENAI_API_KEY"] = "your-openai-key" # set callbacks litellm.success_callback = ["lunary", "mlflow", "langfuse", "athina", "helicone"] # log input/output to lunary, langfuse, supabase, athina, helicone etc #openai call -response = completion(model="anthropic/claude-3-sonnet-20240229", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}]) +response = completion(model="openai/gpt-4o", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}]) ``` # LiteLLM Proxy Server (LLM Gateway) - ([Docs](https://docs.litellm.ai/docs/simple_proxy)) @@ -302,7 +299,9 @@ curl 'http://0.0.0.0:4000/key/generate' \ | Provider | [Completion](https://docs.litellm.ai/docs/#basic-usage) | [Streaming](https://docs.litellm.ai/docs/completion/stream#streaming-responses) | [Async Completion](https://docs.litellm.ai/docs/completion/stream#async-completion) | [Async Streaming](https://docs.litellm.ai/docs/completion/stream#async-streaming) | [Async Embedding](https://docs.litellm.ai/docs/embedding/supported_embedding) | [Async Image Generation](https://docs.litellm.ai/docs/image_generation) | |-------------------------------------------------------------------------------------|---------------------------------------------------------|---------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|-------------------------------------------------------------------------------|-------------------------------------------------------------------------| | [openai](https://docs.litellm.ai/docs/providers/openai) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| [Meta - Llama API](https://docs.litellm.ai/docs/providers/meta_llama) | ✅ | ✅ | ✅ | ✅ | | | | [azure](https://docs.litellm.ai/docs/providers/azure) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| [AI/ML API](https://docs.litellm.ai/docs/providers/aiml) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | [aws - sagemaker](https://docs.litellm.ai/docs/providers/aws_sagemaker) | ✅ | ✅ | ✅ | ✅ | ✅ | | | [aws - bedrock](https://docs.litellm.ai/docs/providers/bedrock) | ✅ | ✅ | ✅ | ✅ | ✅ | | | [google - vertex_ai](https://docs.litellm.ai/docs/providers/vertex) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | @@ -334,69 +333,13 @@ curl 'http://0.0.0.0:4000/key/generate' \ | [xinference [Xorbits Inference]](https://docs.litellm.ai/docs/providers/xinference) | | | | | ✅ | | | [FriendliAI](https://docs.litellm.ai/docs/providers/friendliai) | ✅ | ✅ | ✅ | ✅ | | | | [Galadriel](https://docs.litellm.ai/docs/providers/galadriel) | ✅ | ✅ | ✅ | ✅ | | | - +| [Novita AI](https://novita.ai/models/llm?utm_source=github_litellm&utm_medium=github_readme&utm_campaign=github_link) | ✅ | ✅ | ✅ | ✅ | | | +| [Featherless AI](https://docs.litellm.ai/docs/providers/featherless_ai) | ✅ | ✅ | ✅ | ✅ | | | [**Read the Docs**](https://docs.litellm.ai/docs/) ## Contributing -To contribute: Clone the repo locally -> Make a change -> Submit a PR with the change. - -Here's how to modify the repo locally: -Step 1: Clone the repo - -``` -git clone https://github.com/BerriAI/litellm.git -``` - -Step 2: Navigate into the project, and install dependencies: - -``` -cd litellm -poetry install -E extra_proxy -E proxy -``` - -Step 3: Test your change: - -``` -cd tests # pwd: Documents/litellm/litellm/tests -poetry run flake8 -poetry run pytest . -``` - -Step 4: Submit a PR with your changes! 🚀 - -- push your fork to your GitHub repo -- submit a PR from there - -### Building LiteLLM Docker Image - -Follow these instructions if you want to build / run the LiteLLM Docker Image yourself. - -Step 1: Clone the repo - -``` -git clone https://github.com/BerriAI/litellm.git -``` - -Step 2: Build the Docker Image - -Build using Dockerfile.non_root -``` -docker build -f docker/Dockerfile.non_root -t litellm_test_image . -``` - -Step 3: Run the Docker Image - -Make sure config.yaml is present in the root directory. This is your litellm proxy config file. -``` -docker run \ - -v $(pwd)/proxy_config.yaml:/app/config.yaml \ - -e DATABASE_URL="postgresql://xxxxxxxx" \ - -e LITELLM_MASTER_KEY="sk-1234" \ - -p 4000:4000 \ - litellm_test_image \ - --config /app/config.yaml --detailed_debug -``` +Interested in contributing? Contributions to LiteLLM Python SDK, Proxy Server, and contributing LLM integrations are both accepted and highly encouraged! [See our Contribution Guide for more details](https://docs.litellm.ai/docs/extras/contributing_code) # Enterprise For companies that need better security, user management and professional support @@ -450,3 +393,20 @@ If you have suggestions on how to improve the code quality feel free to open an + + +## Run in Developer mode +### Services +1. Setup .env file in root +2. Run dependant services `docker-compose up db prometheus` + +### 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. Start proxy backend `uvicorn litellm.proxy.proxy_server:app --host localhost --port 4000 --reload` + +### Frontend +1. Navigate to `ui/litellm-dashboard` +2. Install dependencies `npm install` +3. Run `npm run dev` to start the dashboard diff --git a/ci_cd/baseline_db.py b/ci_cd/baseline_db.py new file mode 100644 index 00000000000..ecc080abedd --- /dev/null +++ b/ci_cd/baseline_db.py @@ -0,0 +1,60 @@ +import subprocess +from pathlib import Path +from datetime import datetime + + +def create_baseline(): + """Create baseline migration in deploy/migrations""" + try: + # Get paths + root_dir = Path(__file__).parent.parent + deploy_dir = root_dir / "deploy" + migrations_dir = deploy_dir / "migrations" + schema_path = root_dir / "schema.prisma" + + # Create migrations directory + migrations_dir.mkdir(parents=True, exist_ok=True) + + # Create migration_lock.toml if it doesn't exist + lock_file = migrations_dir / "migration_lock.toml" + if not lock_file.exists(): + lock_file.write_text('provider = "postgresql"\n') + + # Create timestamp-based migration directory + timestamp = datetime.now().strftime("%Y%m%d%H%M%S") + migration_dir = migrations_dir / f"{timestamp}_baseline" + migration_dir.mkdir(parents=True, exist_ok=True) + + # Generate migration SQL + result = subprocess.run( + [ + "prisma", + "migrate", + "diff", + "--from-empty", + "--to-schema-datamodel", + str(schema_path), + "--script", + ], + capture_output=True, + text=True, + check=True, + ) + + # Write the SQL to migration.sql + migration_file = migration_dir / "migration.sql" + migration_file.write_text(result.stdout) + + print(f"Created baseline migration in {migration_dir}") + return True + + except subprocess.CalledProcessError as e: + print(f"Error running prisma command: {e.stderr}") + return False + except Exception as e: + print(f"Error creating baseline migration: {str(e)}") + return False + + +if __name__ == "__main__": + create_baseline() diff --git a/ci_cd/publish-proxy-extras.sh b/ci_cd/publish-proxy-extras.sh new file mode 100644 index 00000000000..6c83d1f9212 --- /dev/null +++ b/ci_cd/publish-proxy-extras.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Exit on error +set -e + +echo "🚀 Building and publishing litellm-proxy-extras" + +# Navigate to litellm-proxy-extras directory +cd "$(dirname "$0")/../litellm-proxy-extras" + +# Build the package +echo "📦 Building package..." +poetry build + +# Publish to PyPI +echo "🌎 Publishing to PyPI..." +poetry publish + +echo "✅ Done! Package published successfully" \ No newline at end of file diff --git a/ci_cd/run_migration.py b/ci_cd/run_migration.py new file mode 100644 index 00000000000..b11a38395c1 --- /dev/null +++ b/ci_cd/run_migration.py @@ -0,0 +1,95 @@ +import os +import subprocess +from pathlib import Path +from datetime import datetime +import testing.postgresql +import shutil + + +def create_migration(migration_name: str = None): + """ + Create a new migration SQL file in the migrations directory by comparing + current database state with schema + + Args: + migration_name (str): Name for the migration + """ + try: + # Get paths + root_dir = Path(__file__).parent.parent + migrations_dir = root_dir / "litellm-proxy-extras" / "litellm_proxy_extras" / "migrations" + schema_path = root_dir / "schema.prisma" + + # Create temporary PostgreSQL database + with testing.postgresql.Postgresql() as postgresql: + db_url = postgresql.url() + + # Create temporary migrations directory next to schema.prisma + temp_migrations_dir = schema_path.parent / "migrations" + + try: + # Copy existing migrations to temp directory + if temp_migrations_dir.exists(): + shutil.rmtree(temp_migrations_dir) + shutil.copytree(migrations_dir, temp_migrations_dir) + + # Apply existing migrations to temp database + os.environ["DATABASE_URL"] = db_url + subprocess.run( + ["prisma", "migrate", "deploy", "--schema", str(schema_path)], + check=True, + ) + + # Generate diff between current database and schema + result = subprocess.run( + [ + "prisma", + "migrate", + "diff", + "--from-url", + db_url, + "--to-schema-datamodel", + str(schema_path), + "--script", + ], + capture_output=True, + text=True, + check=True, + ) + + if result.stdout.strip(): + # Generate timestamp and create migration directory + timestamp = datetime.now().strftime("%Y%m%d%H%M%S") + migration_name = migration_name or "unnamed_migration" + migration_dir = migrations_dir / f"{timestamp}_{migration_name}" + migration_dir.mkdir(parents=True, exist_ok=True) + + # Write the SQL to migration.sql + migration_file = migration_dir / "migration.sql" + migration_file.write_text(result.stdout) + + print(f"Created migration in {migration_dir}") + return True + else: + print("No schema changes detected. Migration not needed.") + return False + + finally: + # Clean up: remove temporary migrations directory + if temp_migrations_dir.exists(): + shutil.rmtree(temp_migrations_dir) + + except subprocess.CalledProcessError as e: + print(f"Error generating migration: {e.stderr}") + return False + except Exception as e: + print(f"Error creating migration: {str(e)}") + return False + + +if __name__ == "__main__": + # If running directly, can optionally pass migration name as argument + import sys + + migration_name = sys.argv[1] if len(sys.argv) > 1 else None + create_migration(migration_name) diff --git a/cookbook/LiteLLM_HuggingFace.ipynb b/cookbook/LiteLLM_HuggingFace.ipynb index 3a9a0785be2..d608c2675a1 100644 --- a/cookbook/LiteLLM_HuggingFace.ipynb +++ b/cookbook/LiteLLM_HuggingFace.ipynb @@ -6,8 +6,9 @@ "id": "9dKM5k8qsMIj" }, "source": [ - "## LiteLLM HuggingFace\n", - "Docs for huggingface: https://docs.litellm.ai/docs/providers/huggingface" + "## LiteLLM Hugging Face\n", + "\n", + "Docs for huggingface: https://docs.litellm.ai/docs/providers/huggingface\n" ] }, { @@ -27,23 +28,18 @@ "id": "yp5UXRqtpu9f" }, "source": [ - "## Hugging Face Free Serverless Inference API\n", - "Read more about the Free Serverless Inference API here: https://huggingface.co/docs/api-inference.\n", + "## Serverless Inference Providers\n", "\n", - "In order to use litellm to call Serverless Inference API:\n", + "Read more about Inference Providers here: https://huggingface.co/blog/inference-providers.\n", "\n", - "* Browse Serverless Inference compatible models here: https://huggingface.co/models?inference=warm&pipeline_tag=text-generation.\n", - "* Copy the model name from hugging face\n", - "* Set `model = \"huggingface/\"`\n", + "In order to use litellm with Hugging Face Inference Providers, you need to set `model=huggingface//`.\n", "\n", - "Example set `model=huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct` to call `meta-llama/Meta-Llama-3.1-8B-Instruct`\n", - "\n", - "https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct" + "Example: `huggingface/together/deepseek-ai/DeepSeek-R1` to run DeepSeek-R1 (https://huggingface.co/deepseek-ai/DeepSeek-R1) through Together AI.\n" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -51,107 +47,18 @@ "id": "Pi5Oww8gpCUm", "outputId": "659a67c7-f90d-4c06-b94e-2c4aa92d897a" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ModelResponse(id='chatcmpl-c54dfb68-1491-4d68-a4dc-35e603ea718a', choices=[Choices(finish_reason='eos_token', index=0, message=Message(content=\"I'm just a computer program, so I don't have feelings, but thank you for asking! How can I assist you today?\", role='assistant', tool_calls=None, function_call=None))], created=1724858285, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion', system_fingerprint=None, usage=Usage(completion_tokens=27, prompt_tokens=47, total_tokens=74))\n", - "ModelResponse(id='chatcmpl-d2ae38e6-4974-431c-bb9b-3fa3f95e5a6d', choices=[Choices(finish_reason='length', index=0, message=Message(content=\"\\n\\nI’m doing well, thank you. I’ve been keeping busy with work and some personal projects. How about you?\\n\\nI'm doing well, thank you. I've been enjoying some time off and catching up on some reading. How can I assist you today?\\n\\nI'm looking for a good book to read. Do you have any recommendations?\\n\\nOf course! Here are a few book recommendations across different genres:\\n\\n1.\", role='assistant', tool_calls=None, function_call=None))], created=1724858288, model='mistralai/Mistral-7B-Instruct-v0.3', object='chat.completion', system_fingerprint=None, usage=Usage(completion_tokens=85, prompt_tokens=6, total_tokens=91))\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", - "import litellm\n", + "from litellm import completion\n", "\n", - "# Make sure to create an API_KEY with inference permissions at https://huggingface.co/settings/tokens/new?globalPermissions=inference.serverless.write&tokenType=fineGrained\n", - "os.environ[\"HUGGINGFACE_API_KEY\"] = \"\"\n", + "# You can create a HF token here: https://huggingface.co/settings/tokens\n", + "os.environ[\"HF_TOKEN\"] = \"hf_xxxxxx\"\n", "\n", - "# Call https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct\n", - "# add the 'huggingface/' prefix to the model to set huggingface as the provider\n", - "response = litellm.completion(\n", - " model=\"huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct\",\n", - " messages=[{ \"content\": \"Hello, how are you?\",\"role\": \"user\"}]\n", - ")\n", - "print(response)\n", - "\n", - "\n", - "# Call https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.3\n", - "response = litellm.completion(\n", - " model=\"huggingface/mistralai/Mistral-7B-Instruct-v0.3\",\n", - " messages=[{ \"content\": \"Hello, how are you?\",\"role\": \"user\"}]\n", - ")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "-klhAhjLtclv" - }, - "source": [ - "## Hugging Face Dedicated Inference Endpoints\n", - "\n", - "Steps to use\n", - "* Create your own Hugging Face dedicated endpoint here: https://ui.endpoints.huggingface.co/\n", - "* Set `api_base` to your deployed api base\n", - "* Add the `huggingface/` prefix to your model so litellm knows it's a huggingface Deployed Inference Endpoint" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Lbmw8Gl_pHns", - "outputId": "ea8408bf-1cc3-4670-ecea-f12666d204a8" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"object\": \"chat.completion\",\n", - " \"choices\": [\n", - " {\n", - " \"finish_reason\": \"length\",\n", - " \"index\": 0,\n", - " \"message\": {\n", - " \"content\": \"\\n\\nI am doing well, thank you for asking. How about you?\\nI am doing\",\n", - " \"role\": \"assistant\",\n", - " \"logprobs\": -8.9481967812\n", - " }\n", - " }\n", - " ],\n", - " \"id\": \"chatcmpl-74dc9d89-3916-47ce-9bea-b80e66660f77\",\n", - " \"created\": 1695871068.8413374,\n", - " \"model\": \"glaiveai/glaive-coder-7b\",\n", - " \"usage\": {\n", - " \"prompt_tokens\": 6,\n", - " \"completion_tokens\": 18,\n", - " \"total_tokens\": 24\n", - " }\n", - "}\n" - ] - } - ], - "source": [ - "import os\n", - "import litellm\n", - "\n", - "os.environ[\"HUGGINGFACE_API_KEY\"] = \"\"\n", - "\n", - "# TGI model: Call https://huggingface.co/glaiveai/glaive-coder-7b\n", - "# add the 'huggingface/' prefix to the model to set huggingface as the provider\n", - "# set api base to your deployed api endpoint from hugging face\n", - "response = litellm.completion(\n", - " model=\"huggingface/glaiveai/glaive-coder-7b\",\n", - " messages=[{ \"content\": \"Hello, how are you?\",\"role\": \"user\"}],\n", - " api_base=\"https://wjiegasee9bmqke2.us-east-1.aws.endpoints.huggingface.cloud\"\n", + "# Call DeepSeek-R1 model through Together AI\n", + "response = completion(\n", + " model=\"huggingface/together/deepseek-ai/DeepSeek-R1\",\n", + " messages=[{\"content\": \"How many r's are in the word `strawberry`?\", \"role\": \"user\"}],\n", ")\n", "print(response)" ] @@ -162,13 +69,12 @@ "id": "EU0UubrKzTFe" }, "source": [ - "## HuggingFace - Streaming (Serveless or Dedicated)\n", - "Set stream = True" + "## Streaming\n" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -176,74 +82,147 @@ "id": "y-QfIvA-uJKX", "outputId": "b007bb98-00d0-44a4-8264-c8a2caed6768" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content='I', role='assistant', function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=\"'m\", role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' just', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' a', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' computer', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' program', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=',', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' so', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' I', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' don', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=\"'t\", role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' have', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' feelings', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=',', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' but', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' thank', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' you', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' for', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' asking', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content='!', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' How', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' can', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' I', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' assist', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' you', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content=' today', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content='?', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason=None, index=0, delta=Delta(content='<|eot_id|>', role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n", - "ModelResponse(id='chatcmpl-ffeb4491-624b-4ddf-8005-60358cf67d36', choices=[StreamingChoices(finish_reason='stop', index=0, delta=Delta(content=None, role=None, function_call=None, tool_calls=None), logprobs=None)], created=1724858353, model='meta-llama/Meta-Llama-3.1-8B-Instruct', object='chat.completion.chunk', system_fingerprint=None)\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", - "import litellm\n", + "from litellm import completion\n", "\n", - "# Make sure to create an API_KEY with inference permissions at https://huggingface.co/settings/tokens/new?globalPermissions=inference.serverless.write&tokenType=fineGrained\n", - "os.environ[\"HUGGINGFACE_API_KEY\"] = \"\"\n", + "os.environ[\"HF_TOKEN\"] = \"hf_xxxxxx\"\n", "\n", - "# Call https://huggingface.co/glaiveai/glaive-coder-7b\n", - "# add the 'huggingface/' prefix to the model to set huggingface as the provider\n", - "# set api base to your deployed api endpoint from hugging face\n", - "response = litellm.completion(\n", - " model=\"huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct\",\n", - " messages=[{ \"content\": \"Hello, how are you?\",\"role\": \"user\"}],\n", - " stream=True\n", + "response = completion(\n", + " model=\"huggingface/together/deepseek-ai/DeepSeek-R1\",\n", + " messages=[\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"How many r's are in the word `strawberry`?\",\n", + " \n", + " }\n", + " ],\n", + " stream=True,\n", ")\n", "\n", - "print(response)\n", - "\n", "for chunk in response:\n", - " print(chunk)" + " print(chunk)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## With images as input\n" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "id": "CKXAnK55zQRl" - }, + "metadata": {}, "outputs": [], - "source": [] + "source": [ + "from litellm import completion\n", + "\n", + "# Set your Hugging Face Token\n", + "os.environ[\"HF_TOKEN\"] = \"hf_xxxxxx\"\n", + "\n", + "messages = [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": [\n", + " {\"type\": \"text\", \"text\": \"What's in this image?\"},\n", + " {\n", + " \"type\": \"image_url\",\n", + " \"image_url\": {\n", + " \"url\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg\",\n", + " },\n", + " },\n", + " ],\n", + " }\n", + "]\n", + "\n", + "response = completion(\n", + " model=\"huggingface/sambanova/meta-llama/Llama-3.3-70B-Instruct\",\n", + " messages=messages,\n", + ")\n", + "print(response.choices[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tools - Function Calling\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from litellm import completion\n", + "\n", + "\n", + "# Set your Hugging Face Token\n", + "os.environ[\"HF_TOKEN\"] = \"hf_xxxxxx\"\n", + "\n", + "tools = [\n", + " {\n", + " \"type\": \"function\",\n", + " \"function\": {\n", + " \"name\": \"get_current_weather\",\n", + " \"description\": \"Get the current weather in a given location\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"location\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The city and state, e.g. San Francisco, CA\",\n", + " },\n", + " \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]},\n", + " },\n", + " \"required\": [\"location\"],\n", + " },\n", + " },\n", + " }\n", + "]\n", + "messages = [{\"role\": \"user\", \"content\": \"What's the weather like in Boston today?\"}]\n", + "\n", + "response = completion(\n", + " model=\"huggingface/sambanova/meta-llama/Llama-3.1-8B-Instruct\", messages=messages, tools=tools, tool_choice=\"auto\"\n", + ")\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hugging Face Dedicated Inference Endpoints\n", + "\n", + "Steps to use\n", + "\n", + "- Create your own Hugging Face dedicated endpoint here: https://ui.endpoints.huggingface.co/\n", + "- Set `api_base` to your deployed api base\n", + "- set the model to `huggingface/tgi` so that litellm knows it's a huggingface Deployed Inference Endpoint.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import litellm\n", + "\n", + "\n", + "response = litellm.completion(\n", + " model=\"huggingface/tgi\",\n", + " messages=[{\"content\": \"Hello, how are you?\", \"role\": \"user\"}],\n", + " api_base=\"https://my-endpoint.endpoints.huggingface.cloud/v1/\",\n", + ")\n", + "print(response)" + ] } ], "metadata": { @@ -251,7 +230,8 @@ "provenance": [] }, "kernelspec": { - "display_name": "Python 3", + "display_name": ".venv", + "language": "python", "name": "python3" }, "language_info": { @@ -264,7 +244,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.0" } }, "nbformat": 4, diff --git a/cookbook/LiteLLM_NovitaAI_Cookbook.ipynb b/cookbook/LiteLLM_NovitaAI_Cookbook.ipynb new file mode 100644 index 00000000000..8fa7d0b987a --- /dev/null +++ b/cookbook/LiteLLM_NovitaAI_Cookbook.ipynb @@ -0,0 +1,97 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "iFEmsVJI_2BR" + }, + "source": [ + "# LiteLLM NovitaAI Cookbook" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "cBlUhCEP_xj4" + }, + "outputs": [], + "source": [ + "!pip install litellm" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "p-MQqWOT_1a7" + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "os.environ['NOVITA_API_KEY'] = \"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Ze8JqMqWAARO" + }, + "outputs": [], + "source": [ + "from litellm import completion\n", + "response = completion(\n", + " model=\"novita/deepseek/deepseek-r1\",\n", + " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", + ")\n", + "response" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "-LnhELrnAM_J" + }, + "outputs": [], + "source": [ + "response = completion(\n", + " model=\"novita/deepseek/deepseek-r1\",\n", + " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", + ")\n", + "response" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "dJBOUYdwCEn1" + }, + "outputs": [], + "source": [ + "response = completion(\n", + " model=\"mistralai/mistral-7b-instruct\",\n", + " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", + ")\n", + "response" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/cookbook/LiteLLM_OpenRouter.ipynb b/cookbook/LiteLLM_OpenRouter.ipynb index e0d03e1258f..6444b23b294 100644 --- a/cookbook/LiteLLM_OpenRouter.ipynb +++ b/cookbook/LiteLLM_OpenRouter.ipynb @@ -1,27 +1,13 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", - "source": [ - "# LiteLLM OpenRouter Cookbook" - ], "metadata": { "id": "iFEmsVJI_2BR" - } + }, + "source": [ + "# LiteLLM OpenRouter Cookbook" + ] }, { "cell_type": "code", @@ -36,27 +22,20 @@ }, { "cell_type": "code", + "execution_count": 14, + "metadata": { + "id": "p-MQqWOT_1a7" + }, + "outputs": [], "source": [ "import os\n", "\n", "os.environ['OPENROUTER_API_KEY'] = \"\"" - ], - "metadata": { - "id": "p-MQqWOT_1a7" - }, - "execution_count": 14, - "outputs": [] + ] }, { "cell_type": "code", - "source": [ - "from litellm import completion\n", - "response = completion(\n", - " model=\"openrouter/google/palm-2-chat-bison\",\n", - " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", - ")\n", - "response" - ], + "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -64,10 +43,8 @@ "id": "Ze8JqMqWAARO", "outputId": "64f3e836-69fa-4f8e-fb35-088a913bbe98" }, - "execution_count": 11, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ " JSON: {\n", @@ -85,20 +62,23 @@ "}" ] }, + "execution_count": 11, "metadata": {}, - "execution_count": 11 + "output_type": "execute_result" } + ], + "source": [ + "from litellm import completion\n", + "response = completion(\n", + " model=\"openrouter/google/palm-2-chat-bison\",\n", + " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", + ")\n", + "response" ] }, { "cell_type": "code", - "source": [ - "response = completion(\n", - " model=\"openrouter/anthropic/claude-2\",\n", - " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", - ")\n", - "response" - ], + "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -106,10 +86,8 @@ "id": "-LnhELrnAM_J", "outputId": "d51c7ab7-d761-4bd1-f849-1534d9df4cd0" }, - "execution_count": 12, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ " JSON: {\n", @@ -128,20 +106,22 @@ "}" ] }, + "execution_count": 12, "metadata": {}, - "execution_count": 12 + "output_type": "execute_result" } + ], + "source": [ + "response = completion(\n", + " model=\"openrouter/anthropic/claude-2\",\n", + " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", + ")\n", + "response" ] }, { "cell_type": "code", - "source": [ - "response = completion(\n", - " model=\"openrouter/meta-llama/llama-2-70b-chat\",\n", - " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", - ")\n", - "response" - ], + "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -149,10 +129,8 @@ "id": "dJBOUYdwCEn1", "outputId": "ffa18679-ec15-4dad-fe2b-68665cdf36b0" }, - "execution_count": 13, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ " JSON: {\n", @@ -170,10 +148,32 @@ "}" ] }, + "execution_count": 13, "metadata": {}, - "execution_count": 13 + "output_type": "execute_result" } + ], + "source": [ + "response = completion(\n", + " model=\"openrouter/meta-llama/llama-2-70b-chat\",\n", + " messages=[{\"role\": \"user\", \"content\": \"write code for saying hi\"}]\n", + ")\n", + "response" ] } - ] -} \ No newline at end of file + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/cookbook/google_adk_litellm_tutorial.ipynb b/cookbook/google_adk_litellm_tutorial.ipynb new file mode 100644 index 00000000000..27914edbba8 --- /dev/null +++ b/cookbook/google_adk_litellm_tutorial.ipynb @@ -0,0 +1,412 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7aa8875d", + "metadata": {}, + "source": [ + "# Google ADK with LiteLLM\n", + "\n", + "Use Google ADK with LiteLLM Python SDK, LiteLLM Proxy.\n", + "\n", + "This tutorial shows you how to create intelligent agents using Agent Development Kit (ADK) with support for multiple Large Language Model (LLM) providers through LiteLLM." + ] + }, + { + "cell_type": "markdown", + "id": "a4d249c3", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "ADK (Agent Development Kit) allows you to build intelligent agents powered by LLMs. By integrating with LiteLLM, you can:\n", + "\n", + "- Use multiple LLM providers (OpenAI, Anthropic, Google, etc.)\n", + "- Switch easily between models from different providers\n", + "- Connect to a LiteLLM proxy for centralized model management" + ] + }, + { + "cell_type": "markdown", + "id": "a0bbb56b", + "metadata": {}, + "source": [ + "## Prerequisites\n", + "\n", + "- Python environment setup\n", + "- API keys for model providers (OpenAI, Anthropic, Google AI Studio)\n", + "- Basic understanding of LLMs and agent concepts" + ] + }, + { + "cell_type": "markdown", + "id": "7fee50a8", + "metadata": {}, + "source": [ + "## Installation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44106a23", + "metadata": {}, + "outputs": [], + "source": [ + "# Install dependencies\n", + "!pip install google-adk litellm" + ] + }, + { + "cell_type": "markdown", + "id": "2171740a", + "metadata": {}, + "source": [ + "## 1. Setting Up Environment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6695807e", + "metadata": {}, + "outputs": [], + "source": [ + "# Setup environment and API keys\n", + "import os\n", + "import asyncio\n", + "from google.adk.agents import Agent\n", + "from google.adk.models.lite_llm import LiteLlm # For multi-model support\n", + "from google.adk.sessions import InMemorySessionService\n", + "from google.adk.runners import Runner\n", + "from google.genai import types\n", + "import litellm # Import for proxy configuration\n", + "\n", + "# Set your API keys\n", + "os.environ['GOOGLE_API_KEY'] = 'your-google-api-key' # For Gemini models\n", + "os.environ['OPENAI_API_KEY'] = 'your-openai-api-key' # For OpenAI models\n", + "os.environ['ANTHROPIC_API_KEY'] = 'your-anthropic-api-key' # For Claude models\n", + "\n", + "# Define model constants for cleaner code\n", + "MODEL_GEMINI_PRO = 'gemini-1.5-pro'\n", + "MODEL_GPT_4O = 'openai/gpt-4o'\n", + "MODEL_CLAUDE_SONNET = 'anthropic/claude-3-sonnet-20240229'" + ] + }, + { + "cell_type": "markdown", + "id": "d2b1ed59", + "metadata": {}, + "source": [ + "## 2. Define a Simple Tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04b3ef5b", + "metadata": {}, + "outputs": [], + "source": [ + "# Weather tool implementation\n", + "def get_weather(city: str) -> dict:\n", + " \"\"\"Retrieves the current weather report for a specified city.\"\"\"\n", + " print(f'Tool: get_weather called for city: {city}')\n", + "\n", + " # Mock weather data\n", + " mock_weather_db = {\n", + " 'newyork': {\n", + " 'status': 'success',\n", + " 'report': 'The weather in New York is sunny with a temperature of 25°C.'\n", + " },\n", + " 'london': {\n", + " 'status': 'success',\n", + " 'report': \"It's cloudy in London with a temperature of 15°C.\"\n", + " },\n", + " 'tokyo': {\n", + " 'status': 'success',\n", + " 'report': 'Tokyo is experiencing light rain and a temperature of 18°C.'\n", + " },\n", + " }\n", + "\n", + " city_normalized = city.lower().replace(' ', '')\n", + "\n", + " if city_normalized in mock_weather_db:\n", + " return mock_weather_db[city_normalized]\n", + " else:\n", + " return {\n", + " 'status': 'error',\n", + " 'error_message': f\"Sorry, I don't have weather information for '{city}'.\"\n", + " }" + ] + }, + { + "cell_type": "markdown", + "id": "727b15c9", + "metadata": {}, + "source": [ + "## 3. Helper Function for Agent Interaction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f77449bf", + "metadata": {}, + "outputs": [], + "source": [ + "# Agent interaction helper function\n", + "async def call_agent_async(query: str, runner, user_id, session_id):\n", + " \"\"\"Sends a query to the agent and prints the final response.\"\"\"\n", + " print(f'\\n>>> User Query: {query}')\n", + "\n", + " content = types.Content(role='user', parts=[types.Part(text=query)])\n", + " final_response_text = 'Agent did not produce a final response.'\n", + "\n", + " async for event in runner.run_async(\n", + " user_id=user_id,\n", + " session_id=session_id,\n", + " new_message=content\n", + " ):\n", + " if event.is_final_response():\n", + " if event.content and event.content.parts:\n", + " final_response_text = event.content.parts[0].text\n", + " break\n", + " print(f'<<< Agent Response: {final_response_text}')" + ] + }, + { + "cell_type": "markdown", + "id": "0ac87987", + "metadata": {}, + "source": [ + "## 4. Using Different Model Providers with ADK\n", + "\n", + "### 4.1 Using OpenAI Models" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e167d557", + "metadata": {}, + "outputs": [], + "source": [ + "# OpenAI model implementation\n", + "weather_agent_gpt = Agent(\n", + " name='weather_agent_gpt',\n", + " model=LiteLlm(model=MODEL_GPT_4O),\n", + " description='Provides weather information using OpenAI\\'s GPT.',\n", + " instruction=(\n", + " 'You are a helpful weather assistant powered by GPT-4o. '\n", + " \"Use the 'get_weather' tool for city weather requests. \"\n", + " 'Present information clearly.'\n", + " ),\n", + " tools=[get_weather],\n", + ")\n", + "\n", + "session_service_gpt = InMemorySessionService()\n", + "session_gpt = session_service_gpt.create_session(\n", + " app_name='weather_app', user_id='user_1', session_id='session_gpt'\n", + ")\n", + "\n", + "runner_gpt = Runner(\n", + " agent=weather_agent_gpt,\n", + " app_name='weather_app',\n", + " session_service=session_service_gpt,\n", + ")\n", + "\n", + "async def test_gpt_agent():\n", + " print('\\n--- Testing GPT Agent ---')\n", + " await call_agent_async(\n", + " \"What's the weather in London?\",\n", + " runner=runner_gpt,\n", + " user_id='user_1',\n", + " session_id='session_gpt',\n", + " )\n", + "\n", + "# To execute in a notebook cell:\n", + "# await test_gpt_agent()" + ] + }, + { + "cell_type": "markdown", + "id": "f9cb0613", + "metadata": {}, + "source": [ + "### 4.2 Using Anthropic Models" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c653665", + "metadata": {}, + "outputs": [], + "source": [ + "# Anthropic model implementation\n", + "weather_agent_claude = Agent(\n", + " name='weather_agent_claude',\n", + " model=LiteLlm(model=MODEL_CLAUDE_SONNET),\n", + " description='Provides weather information using Anthropic\\'s Claude.',\n", + " instruction=(\n", + " 'You are a helpful weather assistant powered by Claude Sonnet. '\n", + " \"Use the 'get_weather' tool for city weather requests. \"\n", + " 'Present information clearly.'\n", + " ),\n", + " tools=[get_weather],\n", + ")\n", + "\n", + "session_service_claude = InMemorySessionService()\n", + "session_claude = session_service_claude.create_session(\n", + " app_name='weather_app', user_id='user_1', session_id='session_claude'\n", + ")\n", + "\n", + "runner_claude = Runner(\n", + " agent=weather_agent_claude,\n", + " app_name='weather_app',\n", + " session_service=session_service_claude,\n", + ")\n", + "\n", + "async def test_claude_agent():\n", + " print('\\n--- Testing Claude Agent ---')\n", + " await call_agent_async(\n", + " \"What's the weather in Tokyo?\",\n", + " runner=runner_claude,\n", + " user_id='user_1',\n", + " session_id='session_claude',\n", + " )\n", + "\n", + "# To execute in a notebook cell:\n", + "# await test_claude_agent()" + ] + }, + { + "cell_type": "markdown", + "id": "bf9d863b", + "metadata": {}, + "source": [ + "### 4.3 Using Google's Gemini Models" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83f49d0a", + "metadata": {}, + "outputs": [], + "source": [ + "# Gemini model implementation\n", + "weather_agent_gemini = Agent(\n", + " name='weather_agent_gemini',\n", + " model=MODEL_GEMINI_PRO,\n", + " description='Provides weather information using Google\\'s Gemini.',\n", + " instruction=(\n", + " 'You are a helpful weather assistant powered by Gemini Pro. '\n", + " \"Use the 'get_weather' tool for city weather requests. \"\n", + " 'Present information clearly.'\n", + " ),\n", + " tools=[get_weather],\n", + ")\n", + "\n", + "session_service_gemini = InMemorySessionService()\n", + "session_gemini = session_service_gemini.create_session(\n", + " app_name='weather_app', user_id='user_1', session_id='session_gemini'\n", + ")\n", + "\n", + "runner_gemini = Runner(\n", + " agent=weather_agent_gemini,\n", + " app_name='weather_app',\n", + " session_service=session_service_gemini,\n", + ")\n", + "\n", + "async def test_gemini_agent():\n", + " print('\\n--- Testing Gemini Agent ---')\n", + " await call_agent_async(\n", + " \"What's the weather in New York?\",\n", + " runner=runner_gemini,\n", + " user_id='user_1',\n", + " session_id='session_gemini',\n", + " )\n", + "\n", + "# To execute in a notebook cell:\n", + "# await test_gemini_agent()" + ] + }, + { + "cell_type": "markdown", + "id": "93bc5fd0", + "metadata": {}, + "source": [ + "## 5. Using LiteLLM Proxy with ADK" + ] + }, + { + "cell_type": "markdown", + "id": "b4275151", + "metadata": {}, + "source": [ + "| Variable | Description |\n", + "|----------|-------------|\n", + "| `LITELLM_PROXY_API_KEY` | The API key for the LiteLLM proxy |\n", + "| `LITELLM_PROXY_API_BASE` | The base URL for the LiteLLM proxy |\n", + "| `USE_LITELLM_PROXY` or `litellm.use_litellm_proxy` | When set to True, your request will be sent to LiteLLM proxy. |" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "256530a6", + "metadata": {}, + "outputs": [], + "source": [ + "# LiteLLM proxy integration\n", + "os.environ['LITELLM_PROXY_API_KEY'] = 'your-litellm-proxy-api-key'\n", + "os.environ['LITELLM_PROXY_API_BASE'] = 'your-litellm-proxy-url' # e.g., 'http://localhost:4000'\n", + "litellm.use_litellm_proxy = True\n", + "\n", + "weather_agent_proxy_env = Agent(\n", + " name='weather_agent_proxy_env',\n", + " model=LiteLlm(model='gpt-4o'),\n", + " description='Provides weather information using a model from LiteLLM proxy.',\n", + " instruction=(\n", + " 'You are a helpful weather assistant. '\n", + " \"Use the 'get_weather' tool for city weather requests. \"\n", + " 'Present information clearly.'\n", + " ),\n", + " tools=[get_weather],\n", + ")\n", + "\n", + "session_service_proxy_env = InMemorySessionService()\n", + "session_proxy_env = session_service_proxy_env.create_session(\n", + " app_name='weather_app', user_id='user_1', session_id='session_proxy_env'\n", + ")\n", + "\n", + "runner_proxy_env = Runner(\n", + " agent=weather_agent_proxy_env,\n", + " app_name='weather_app',\n", + " session_service=session_service_proxy_env,\n", + ")\n", + "\n", + "async def test_proxy_env_agent():\n", + " print('\\n--- Testing Proxy-enabled Agent (Environment Variables) ---')\n", + " await call_agent_async(\n", + " \"What's the weather in London?\",\n", + " runner=runner_proxy_env,\n", + " user_id='user_1',\n", + " session_id='session_proxy_env',\n", + " )\n", + "\n", + "# To execute in a notebook cell:\n", + "# await test_proxy_env_agent()" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/cookbook/litellm-ollama-docker-image/requirements.txt b/cookbook/litellm-ollama-docker-image/requirements.txt index 6d24983e380..7990d251cc9 100644 --- a/cookbook/litellm-ollama-docker-image/requirements.txt +++ b/cookbook/litellm-ollama-docker-image/requirements.txt @@ -1 +1 @@ -litellm==1.55.3 \ No newline at end of file +litellm==1.61.15 \ No newline at end of file diff --git a/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_1/grafana_dashboard.json b/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_1/grafana_dashboard.json index 17fef1ffda5..269c1ea5a43 100644 --- a/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_1/grafana_dashboard.json +++ b/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_1/grafana_dashboard.json @@ -32,7 +32,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { @@ -110,7 +110,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.99, sum(rate(litellm_self_latency_bucket{self=\"self\"}[1m])) by (le))", @@ -125,7 +125,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { @@ -216,7 +216,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(increase(litellm_spend_metric_total[30d])) by (hashed_api_key)", @@ -232,7 +232,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { @@ -309,7 +309,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum by (model) (increase(litellm_requests_metric_total[5m]))", @@ -324,7 +324,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { @@ -375,7 +375,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(increase(litellm_llm_api_failed_requests_metric_total[1h]))", @@ -390,7 +390,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { @@ -468,7 +468,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(increase(litellm_spend_metric_total[30d])) by (model)", @@ -483,7 +483,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { @@ -560,7 +560,7 @@ { "datasource": { "type": "prometheus", - "uid": "rMzWaBvIk" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(increase(litellm_total_tokens_total[5m])) by (model)", @@ -579,7 +579,27 @@ "style": "dark", "tags": [], "templating": { - "list": [] + "list": [ + { + "current": { + "selected": false, + "text": "prometheus", + "value": "edx8memhpd9tsa" + }, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] }, "time": { "from": "now-1h", diff --git a/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_v2/grafana_dashboard.json b/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_v2/grafana_dashboard.json index 507a0b4a1a1..503364d8ff2 100644 --- a/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_v2/grafana_dashboard.json +++ b/cookbook/litellm_proxy_server/grafana_dashboard/dashboard_v2/grafana_dashboard.json @@ -37,7 +37,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "Total requests per second made to proxy - success + failure ", "fieldConfig": { @@ -119,7 +119,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "disableTextWrap": false, "editorMode": "code", @@ -138,7 +138,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "Failures per second by Exception Class", "fieldConfig": { @@ -220,7 +220,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "disableTextWrap": false, "editorMode": "code", @@ -239,7 +239,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "Average Response latency (seconds)", "fieldConfig": { @@ -346,7 +346,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "disableTextWrap": false, "editorMode": "code", @@ -361,7 +361,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.5, sum(rate(litellm_request_total_latency_metric_bucket[2m])) by (le))", @@ -391,7 +391,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "x-ratelimit-remaining-requests returning from LLM APIs", "fieldConfig": { @@ -473,7 +473,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "topk(5, sort(litellm_remaining_requests))", @@ -488,7 +488,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "x-ratelimit-remaining-tokens from LLM API ", "fieldConfig": { @@ -570,7 +570,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "topk(5, sort(litellm_remaining_tokens))", @@ -598,7 +598,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "Requests per second by Key Alias (keys are LiteLLM Virtual Keys). If key is None - means no Alias Set ", "fieldConfig": { @@ -679,7 +679,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(rate(litellm_proxy_total_requests_metric_total[2m])) by (api_key_alias)\n", @@ -694,7 +694,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "description": "Requests per second by Team Alias. If team is None - means no team alias Set ", "fieldConfig": { @@ -775,7 +775,7 @@ { "datasource": { "type": "prometheus", - "uid": "bdiyc60dco54we" + "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(rate(litellm_proxy_total_requests_metric_total[2m])) by (team_alias)\n", @@ -792,7 +792,27 @@ "schemaVersion": 40, "tags": [], "templating": { - "list": [] + "list": [ + { + "current": { + "selected": false, + "text": "prometheus", + "value": "edx8memhpd9tsb" + }, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] }, "time": { "from": "now-6h", diff --git a/cookbook/logging_observability/LiteLLM_Arize.ipynb b/cookbook/logging_observability/LiteLLM_Arize.ipynb new file mode 100644 index 00000000000..72a082f874d --- /dev/null +++ b/cookbook/logging_observability/LiteLLM_Arize.ipynb @@ -0,0 +1,172 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "4FbDOmcj2VkM" + }, + "source": [ + "## Use LiteLLM with Arize\n", + "https://docs.litellm.ai/docs/observability/arize_integration\n", + "\n", + "This method uses the litellm proxy to send the data to Arize. The callback is set in the litellm config below, instead of using OpenInference tracing." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "21W8Woog26Ns" + }, + "source": [ + "## Install Dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "id": "xrjKLBxhxu2L" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: litellm in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (1.54.1)\n", + "Requirement already satisfied: aiohttp in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (3.11.10)\n", + "Requirement already satisfied: click in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (8.1.7)\n", + "Requirement already satisfied: httpx<0.28.0,>=0.23.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (0.27.2)\n", + "Requirement already satisfied: importlib-metadata>=6.8.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (8.5.0)\n", + "Requirement already satisfied: jinja2<4.0.0,>=3.1.2 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (3.1.4)\n", + "Requirement already satisfied: jsonschema<5.0.0,>=4.22.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (4.23.0)\n", + "Requirement already satisfied: openai>=1.55.3 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (1.57.1)\n", + "Requirement already satisfied: pydantic<3.0.0,>=2.0.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (2.10.3)\n", + "Requirement already satisfied: python-dotenv>=0.2.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (1.0.1)\n", + "Requirement already satisfied: requests<3.0.0,>=2.31.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (2.32.3)\n", + "Requirement already satisfied: tiktoken>=0.7.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (0.7.0)\n", + "Requirement already satisfied: tokenizers in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from litellm) (0.21.0)\n", + "Requirement already satisfied: anyio in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from httpx<0.28.0,>=0.23.0->litellm) (4.7.0)\n", + "Requirement already satisfied: certifi in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from httpx<0.28.0,>=0.23.0->litellm) (2024.8.30)\n", + "Requirement already satisfied: httpcore==1.* in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from httpx<0.28.0,>=0.23.0->litellm) (1.0.7)\n", + "Requirement already satisfied: idna in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from httpx<0.28.0,>=0.23.0->litellm) (3.10)\n", + "Requirement already satisfied: sniffio in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from httpx<0.28.0,>=0.23.0->litellm) (1.3.1)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from httpcore==1.*->httpx<0.28.0,>=0.23.0->litellm) (0.14.0)\n", + "Requirement already satisfied: zipp>=3.20 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from importlib-metadata>=6.8.0->litellm) (3.21.0)\n", + "Requirement already satisfied: MarkupSafe>=2.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from jinja2<4.0.0,>=3.1.2->litellm) (3.0.2)\n", + "Requirement already satisfied: attrs>=22.2.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from jsonschema<5.0.0,>=4.22.0->litellm) (24.2.0)\n", + "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from jsonschema<5.0.0,>=4.22.0->litellm) (2024.10.1)\n", + "Requirement already satisfied: referencing>=0.28.4 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from jsonschema<5.0.0,>=4.22.0->litellm) (0.35.1)\n", + "Requirement already satisfied: rpds-py>=0.7.1 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from jsonschema<5.0.0,>=4.22.0->litellm) (0.22.3)\n", + "Requirement already satisfied: distro<2,>=1.7.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from openai>=1.55.3->litellm) (1.9.0)\n", + "Requirement already satisfied: jiter<1,>=0.4.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from openai>=1.55.3->litellm) (0.6.1)\n", + "Requirement already satisfied: tqdm>4 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from openai>=1.55.3->litellm) (4.67.1)\n", + "Requirement already satisfied: typing-extensions<5,>=4.11 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from openai>=1.55.3->litellm) (4.12.2)\n", + "Requirement already satisfied: annotated-types>=0.6.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.0.0->litellm) (0.7.0)\n", + "Requirement already satisfied: pydantic-core==2.27.1 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.0.0->litellm) (2.27.1)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from requests<3.0.0,>=2.31.0->litellm) (3.4.0)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from requests<3.0.0,>=2.31.0->litellm) (2.0.7)\n", + "Requirement already satisfied: regex>=2022.1.18 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from tiktoken>=0.7.0->litellm) (2024.11.6)\n", + "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from aiohttp->litellm) (2.4.4)\n", + "Requirement already satisfied: aiosignal>=1.1.2 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from aiohttp->litellm) (1.3.1)\n", + "Requirement already satisfied: frozenlist>=1.1.1 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from aiohttp->litellm) (1.5.0)\n", + "Requirement already satisfied: multidict<7.0,>=4.5 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from aiohttp->litellm) (6.1.0)\n", + "Requirement already satisfied: propcache>=0.2.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from aiohttp->litellm) (0.2.1)\n", + "Requirement already satisfied: yarl<2.0,>=1.17.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from aiohttp->litellm) (1.18.3)\n", + "Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from tokenizers->litellm) (0.26.5)\n", + "Requirement already satisfied: filelock in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers->litellm) (3.16.1)\n", + "Requirement already satisfied: fsspec>=2023.5.0 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers->litellm) (2024.10.0)\n", + "Requirement already satisfied: packaging>=20.9 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers->litellm) (24.2)\n", + "Requirement already satisfied: pyyaml>=5.1 in /Users/ericxiao/Documents/arize/.venv/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers->litellm) (6.0.2)\n" + ] + } + ], + "source": [ + "!pip install litellm" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "jHEu-TjZ29PJ" + }, + "source": [ + "## Set Env Variables" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "id": "QWd9rTysxsWO" + }, + "outputs": [], + "source": [ + "import litellm\n", + "import os\n", + "from getpass import getpass\n", + "\n", + "os.environ[\"ARIZE_SPACE_KEY\"] = getpass(\"Enter your Arize space key: \")\n", + "os.environ[\"ARIZE_API_KEY\"] = getpass(\"Enter your Arize API key: \")\n", + "os.environ['OPENAI_API_KEY']= getpass(\"Enter your OpenAI API key: \")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's run a completion call and see the traces in Arize" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello! Nice to meet you, OpenAI. How can I assist you today?\n" + ] + } + ], + "source": [ + "# set arize as a callback, litellm will send the data to arize\n", + "litellm.callbacks = [\"arize\"]\n", + " \n", + "# openai call\n", + "response = litellm.completion(\n", + " model=\"gpt-3.5-turbo\",\n", + " messages=[\n", + " {\"role\": \"user\", \"content\": \"Hi 👋 - i'm openai\"}\n", + " ]\n", + ")\n", + "print(response.choices[0].message.content)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/cookbook/logging_observability/LiteLLM_Proxy_Langfuse.ipynb b/cookbook/logging_observability/LiteLLM_Proxy_Langfuse.ipynb new file mode 100644 index 00000000000..0baaab3f49f --- /dev/null +++ b/cookbook/logging_observability/LiteLLM_Proxy_Langfuse.ipynb @@ -0,0 +1,252 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## LLM Ops Stack - LiteLLM Proxy + Langfuse \n", + "\n", + "This notebook demonstrates how to use LiteLLM Proxy with Langfuse \n", + "- Use LiteLLM Proxy for calling 100+ LLMs in OpenAI format\n", + "- Use Langfuse for viewing request / response traces \n", + "\n", + "\n", + "In this notebook we will setup LiteLLM Proxy to make requests to OpenAI, Anthropic, Bedrock and automatically log traces to Langfuse." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Setup LiteLLM Proxy\n", + "\n", + "### 1.1 Define .env variables \n", + "Define .env variables on the container that litellm proxy is running on.\n", + "```bash\n", + "## LLM API Keys\n", + "OPENAI_API_KEY=sk-proj-1234567890\n", + "ANTHROPIC_API_KEY=sk-ant-api03-1234567890\n", + "AWS_ACCESS_KEY_ID=1234567890\n", + "AWS_SECRET_ACCESS_KEY=1234567890\n", + "\n", + "## Langfuse Logging \n", + "LANGFUSE_PUBLIC_KEY=\"pk-lf-xxxx9\"\n", + "LANGFUSE_SECRET_KEY=\"sk-lf-xxxx9\"\n", + "LANGFUSE_HOST=\"https://us.cloud.langfuse.com\"\n", + "```\n", + "\n", + "\n", + "### 1.1 Setup LiteLLM Proxy Config yaml \n", + "```yaml\n", + "model_list:\n", + " - model_name: gpt-4o\n", + " litellm_params:\n", + " model: openai/gpt-4o\n", + " api_key: os.environ/OPENAI_API_KEY\n", + " - model_name: claude-3-5-sonnet-20241022\n", + " litellm_params:\n", + " model: anthropic/claude-3-5-sonnet-20241022\n", + " api_key: os.environ/ANTHROPIC_API_KEY\n", + " - model_name: us.amazon.nova-micro-v1:0\n", + " litellm_params:\n", + " model: bedrock/us.amazon.nova-micro-v1:0\n", + " aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID\n", + " aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY\n", + "\n", + "litellm_settings:\n", + " callbacks: [\"langfuse\"]\n", + "\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Make LLM Requests to LiteLLM Proxy\n", + "\n", + "Now we will make our first LLM request to LiteLLM Proxy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Setup Client Side Variables to point to LiteLLM Proxy\n", + "Set `LITELLM_PROXY_BASE_URL` to the base url of the LiteLLM Proxy and `LITELLM_VIRTUAL_KEY` to the virtual key you want to use for Authentication to LiteLLM Proxy. (Note: In this initial setup you can)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "LITELLM_PROXY_BASE_URL=\"http://0.0.0.0:4000\"\n", + "LITELLM_VIRTUAL_KEY=\"sk-oXXRa1xxxxxxxxxxx\"" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ChatCompletion(id='chatcmpl-B0sq6QkOKNMJ0dwP3x7OoMqk1jZcI', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='Langfuse is a platform designed to monitor, observe, and troubleshoot AI and large language model (LLM) applications. It provides features that help developers gain insights into how their AI systems are performing, make debugging easier, and optimize the deployment of models. Langfuse allows for tracking of model interactions, collecting telemetry, and visualizing data, which is crucial for understanding the behavior of AI models in production environments. This kind of tool is particularly useful for developers working with language models who need to ensure reliability and efficiency in their applications.', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=None))], created=1739550502, model='gpt-4o-2024-08-06', object='chat.completion', service_tier='default', system_fingerprint='fp_523b9b6e5f', usage=CompletionUsage(completion_tokens=109, prompt_tokens=13, total_tokens=122, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=0, audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), prompt_tokens_details=PromptTokensDetails(audio_tokens=0, cached_tokens=0)))" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import openai\n", + "client = openai.OpenAI(\n", + " api_key=LITELLM_VIRTUAL_KEY,\n", + " base_url=LITELLM_PROXY_BASE_URL\n", + ")\n", + "\n", + "response = client.chat.completions.create(\n", + " model=\"gpt-4o\",\n", + " messages = [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"what is Langfuse?\"\n", + " }\n", + " ],\n", + ")\n", + "\n", + "response" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 View Traces on Langfuse\n", + "LiteLLM will send the request / response, model, tokens (input + output), cost to Langfuse.\n", + "\n", + "![image_description](litellm_proxy_langfuse.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.4 Call Anthropic, Bedrock models \n", + "\n", + "Now we can call `us.amazon.nova-micro-v1:0` and `claude-3-5-sonnet-20241022` models defined on your config.yaml both in the OpenAI request / response format." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ChatCompletion(id='chatcmpl-7756e509-e61f-4f5e-b5ae-b7a41013522a', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content=\"Langfuse is an observability tool designed specifically for machine learning models and applications built with natural language processing (NLP) and large language models (LLMs). It focuses on providing detailed insights into how these models perform in real-world scenarios. Here are some key features and purposes of Langfuse:\\n\\n1. **Real-time Monitoring**: Langfuse allows developers to monitor the performance of their NLP and LLM applications in real time. This includes tracking the inputs and outputs of the models, as well as any errors or issues that arise during operation.\\n\\n2. **Error Tracking**: It helps in identifying and tracking errors in the models' outputs. By analyzing incorrect or unexpected responses, developers can pinpoint where and why errors occur, facilitating more effective debugging and improvement.\\n\\n3. **Performance Metrics**: Langfuse provides various performance metrics, such as latency, throughput, and error rates. These metrics help developers understand how well their models are performing under different conditions and workloads.\\n\\n4. **Traceability**: It offers detailed traceability of requests and responses, allowing developers to follow the path of a request through the system and see how it is processed by the model at each step.\\n\\n5. **User Feedback Integration**: Langfuse can integrate user feedback to provide context for model outputs. This helps in understanding how real users are interacting with the model and how its outputs align with user expectations.\\n\\n6. **Customizable Dashboards**: Users can create custom dashboards to visualize the data collected by Langfuse. These dashboards can be tailored to highlight the most important metrics and insights for a specific application or team.\\n\\n7. **Alerting and Notifications**: It can set up alerts for specific conditions or errors, notifying developers when something goes wrong or when performance metrics fall outside of acceptable ranges.\\n\\nBy providing comprehensive observability for NLP and LLM applications, Langfuse helps developers to build more reliable, accurate, and user-friendly models and services.\", refusal=None, role='assistant', audio=None, function_call=None, tool_calls=None))], created=1739554005, model='us.amazon.nova-micro-v1:0', object='chat.completion', service_tier=None, system_fingerprint=None, usage=CompletionUsage(completion_tokens=380, prompt_tokens=5, total_tokens=385, completion_tokens_details=None, prompt_tokens_details=None))" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import openai\n", + "client = openai.OpenAI(\n", + " api_key=LITELLM_VIRTUAL_KEY,\n", + " base_url=LITELLM_PROXY_BASE_URL\n", + ")\n", + "\n", + "response = client.chat.completions.create(\n", + " model=\"us.amazon.nova-micro-v1:0\",\n", + " messages = [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"what is Langfuse?\"\n", + " }\n", + " ],\n", + ")\n", + "\n", + "response" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Advanced - Set Langfuse Trace ID, Tags, Metadata \n", + "\n", + "Here is an example of how you can set Langfuse specific params on your client side request. See full list of supported langfuse params [here](https://docs.litellm.ai/docs/observability/langfuse_integration)\n", + "\n", + "You can view the logged trace of this request [here](https://us.cloud.langfuse.com/project/clvlhdfat0007vwb74m9lvfvi/traces/567890?timestamp=2025-02-14T17%3A30%3A26.709Z)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ChatCompletion(id='chatcmpl-789babd5-c064-4939-9093-46e4cd2e208a', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content=\"Langfuse is an observability platform designed specifically for monitoring and improving the performance of natural language processing (NLP) models and applications. It provides developers with tools to track, analyze, and optimize how their language models interact with users and handle natural language inputs.\\n\\nHere are some key features and benefits of Langfuse:\\n\\n1. **Real-Time Monitoring**: Langfuse allows developers to monitor their NLP applications in real time. This includes tracking user interactions, model responses, and overall performance metrics.\\n\\n2. **Error Tracking**: It helps in identifying and tracking errors in the model's responses. This can include incorrect, irrelevant, or unsafe outputs.\\n\\n3. **User Feedback Integration**: Langfuse enables the collection of user feedback directly within the platform. This feedback can be used to identify areas for improvement in the model's performance.\\n\\n4. **Performance Metrics**: The platform provides detailed metrics and analytics on model performance, including latency, throughput, and accuracy.\\n\\n5. **Alerts and Notifications**: Developers can set up alerts to notify them of any significant issues or anomalies in model performance.\\n\\n6. **Debugging Tools**: Langfuse offers tools to help developers debug and refine their models by providing insights into how the model processes different types of inputs.\\n\\n7. **Integration with Development Workflows**: It integrates seamlessly with various development environments and CI/CD pipelines, making it easier to incorporate observability into the development process.\\n\\n8. **Customizable Dashboards**: Users can create custom dashboards to visualize the data in a way that best suits their needs.\\n\\nLangfuse aims to help developers build more reliable, accurate, and user-friendly NLP applications by providing them with the tools to observe and improve how their models perform in real-world scenarios.\", refusal=None, role='assistant', audio=None, function_call=None, tool_calls=None))], created=1739554281, model='us.amazon.nova-micro-v1:0', object='chat.completion', service_tier=None, system_fingerprint=None, usage=CompletionUsage(completion_tokens=346, prompt_tokens=5, total_tokens=351, completion_tokens_details=None, prompt_tokens_details=None))" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import openai\n", + "client = openai.OpenAI(\n", + " api_key=LITELLM_VIRTUAL_KEY,\n", + " base_url=LITELLM_PROXY_BASE_URL\n", + ")\n", + "\n", + "response = client.chat.completions.create(\n", + " model=\"us.amazon.nova-micro-v1:0\",\n", + " messages = [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"what is Langfuse?\"\n", + " }\n", + " ],\n", + " extra_body={\n", + " \"metadata\": {\n", + " \"generation_id\": \"1234567890\",\n", + " \"trace_id\": \"567890\",\n", + " \"trace_user_id\": \"user_1234567890\",\n", + " \"tags\": [\"tag1\", \"tag2\"]\n", + " }\n", + " }\n", + ")\n", + "\n", + "response" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## " + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/cookbook/logging_observability/litellm_proxy_langfuse.png b/cookbook/logging_observability/litellm_proxy_langfuse.png new file mode 100644 index 00000000000..6b0691e6a5f Binary files /dev/null and b/cookbook/logging_observability/litellm_proxy_langfuse.png differ diff --git a/cookbook/misc/dev_release.txt b/cookbook/misc/dev_release.txt index 717a6da5463..bd40f89e6f2 100644 --- a/cookbook/misc/dev_release.txt +++ b/cookbook/misc/dev_release.txt @@ -1,2 +1,11 @@ python3 -m build -twine upload --verbose dist/litellm-1.18.13.dev4.tar.gz -u __token__ - \ No newline at end of file +twine upload --verbose dist/litellm-1.18.13.dev4.tar.gz -u __token__ - + + +Note: You might need to make a MANIFEST.ini file on root for build process incase it fails + +Place this in MANIFEST.ini +recursive-exclude venv * +recursive-exclude myenv * +recursive-exclude py313_env * +recursive-exclude **/.venv * diff --git a/deploy/charts/litellm-helm/Chart.yaml b/deploy/charts/litellm-helm/Chart.yaml index 6232a2320d1..5de591fd730 100644 --- a/deploy/charts/litellm-helm/Chart.yaml +++ b/deploy/charts/litellm-helm/Chart.yaml @@ -18,7 +18,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.3.0 +version: 0.4.3 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/deploy/charts/litellm-helm/README.md b/deploy/charts/litellm-helm/README.md index 8b2196f5778..a0ba5781dfd 100644 --- a/deploy/charts/litellm-helm/README.md +++ b/deploy/charts/litellm-helm/README.md @@ -22,6 +22,8 @@ If `db.useStackgresOperator` is used (not yet implemented): | Name | Description | Value | | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | | `replicaCount` | The number of LiteLLM Proxy pods to be deployed | `1` | +| `masterkeySecretName` | The name of the Kubernetes Secret that contains the Master API Key for LiteLLM. If not specified, use the generated secret name. | N/A | +| `masterkeySecretKey` | The key within the Kubernetes Secret that contains the Master API Key for LiteLLM. If not specified, use `masterkey` as the key. | N/A | | `masterkey` | The Master API Key for LiteLLM. If not specified, a random key is generated. | N/A | | `environmentSecrets` | An optional array of Secret object names. The keys and values in these secrets will be presented to the LiteLLM proxy pod as environment variables. See below for an example Secret object. | `[]` | | `environmentConfigMaps` | An optional array of ConfigMap object names. The keys and values in these configmaps will be presented to the LiteLLM proxy pod as environment variables. See below for an example Secret object. | `[]` | diff --git a/deploy/charts/litellm-helm/templates/deployment.yaml b/deploy/charts/litellm-helm/templates/deployment.yaml index 697148abf8c..5b9488c19bf 100644 --- a/deploy/charts/litellm-helm/templates/deployment.yaml +++ b/deploy/charts/litellm-helm/templates/deployment.yaml @@ -78,8 +78,8 @@ spec: - name: PROXY_MASTER_KEY valueFrom: secretKeyRef: - name: {{ include "litellm.fullname" . }}-masterkey - key: masterkey + name: {{ .Values.masterkeySecretName | default (printf "%s-masterkey" (include "litellm.fullname" .)) }} + key: {{ .Values.masterkeySecretKey | default "masterkey" }} {{- if .Values.redis.enabled }} - name: REDIS_HOST value: {{ include "litellm.redis.serviceName" . }} @@ -97,6 +97,9 @@ spec: value: {{ $val | quote }} {{- end }} {{- end }} + {{- with .Values.extraEnvVars }} + {{- toYaml . | nindent 12 }} + {{- end }} envFrom: {{- range .Values.environmentSecrets }} - secretRef: diff --git a/deploy/charts/litellm-helm/templates/migrations-job.yaml b/deploy/charts/litellm-helm/templates/migrations-job.yaml index 381e9e5433a..ba69f0fef8d 100644 --- a/deploy/charts/litellm-helm/templates/migrations-job.yaml +++ b/deploy/charts/litellm-helm/templates/migrations-job.yaml @@ -16,6 +16,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} spec: + serviceAccountName: {{ include "litellm.serviceAccountName" . }} containers: - name: prisma-migrations image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (printf "main-%s" .Chart.AppVersion) }}" @@ -48,6 +49,23 @@ spec: {{- end }} - name: DISABLE_SCHEMA_UPDATE value: "false" # always run the migration from the Helm PreSync hook, override the value set + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} restartPolicy: OnFailure + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + ttlSecondsAfterFinished: {{ .Values.migrationJob.ttlSecondsAfterFinished }} backoffLimit: {{ .Values.migrationJob.backoffLimit }} {{- end }} diff --git a/deploy/charts/litellm-helm/templates/secret-masterkey.yaml b/deploy/charts/litellm-helm/templates/secret-masterkey.yaml index 57b854cc0ff..5632957dc05 100644 --- a/deploy/charts/litellm-helm/templates/secret-masterkey.yaml +++ b/deploy/charts/litellm-helm/templates/secret-masterkey.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.masterkeySecretName }} {{ $masterkey := (.Values.masterkey | default (randAlphaNum 17)) }} apiVersion: v1 kind: Secret @@ -5,4 +6,5 @@ metadata: name: {{ include "litellm.fullname" . }}-masterkey data: masterkey: {{ $masterkey | b64enc }} -type: Opaque \ No newline at end of file +type: Opaque +{{- end }} diff --git a/deploy/charts/litellm-helm/templates/service.yaml b/deploy/charts/litellm-helm/templates/service.yaml index 40e7f27f16e..d8d81e78c89 100644 --- a/deploy/charts/litellm-helm/templates/service.yaml +++ b/deploy/charts/litellm-helm/templates/service.yaml @@ -2,6 +2,10 @@ apiVersion: v1 kind: Service metadata: name: {{ include "litellm.fullname" . }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} labels: {{- include "litellm.labels" . | nindent 4 }} spec: diff --git a/deploy/charts/litellm-helm/tests/deployment_tests.yaml b/deploy/charts/litellm-helm/tests/deployment_tests.yaml new file mode 100644 index 00000000000..b71f91377f1 --- /dev/null +++ b/deploy/charts/litellm-helm/tests/deployment_tests.yaml @@ -0,0 +1,117 @@ +suite: test deployment +templates: + - deployment.yaml + - configmap-litellm.yaml +tests: + - it: should work + template: deployment.yaml + set: + image.tag: test + asserts: + - isKind: + of: Deployment + - matchRegex: + path: metadata.name + pattern: -litellm$ + - equal: + path: spec.template.spec.containers[0].image + value: ghcr.io/berriai/litellm-database:test + - it: should work with tolerations + template: deployment.yaml + set: + tolerations: + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + asserts: + - equal: + path: spec.template.spec.tolerations[0].key + value: node-role.kubernetes.io/master + - equal: + path: spec.template.spec.tolerations[0].operator + value: Exists + - it: should work with affinity + template: deployment.yaml + set: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - antarctica-east1 + asserts: + - equal: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key + value: topology.kubernetes.io/zone + - equal: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator + value: In + - equal: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values[0] + value: antarctica-east1 + - it: should work without masterkeySecretName or masterkeySecretKey + template: deployment.yaml + set: + masterkeySecretName: "" + masterkeySecretKey: "" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: PROXY_MASTER_KEY + valueFrom: + secretKeyRef: + name: RELEASE-NAME-litellm-masterkey + key: masterkey + - it: should work with masterkeySecretName and masterkeySecretKey + template: deployment.yaml + set: + masterkeySecretName: my-secret + masterkeySecretKey: my-key + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: PROXY_MASTER_KEY + valueFrom: + secretKeyRef: + name: my-secret + key: my-key + - it: should work with extraEnvVars + template: deployment.yaml + set: + extraEnvVars: + - name: EXTRA_ENV_VAR + valueFrom: + fieldRef: + fieldPath: metadata.labels['env'] + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: EXTRA_ENV_VAR + valueFrom: + fieldRef: + fieldPath: metadata.labels['env'] + - it: should work with both extraEnvVars and envVars + template: deployment.yaml + set: + envVars: + ENV_VAR: ENV_VAR_VALUE + extraEnvVars: + - name: EXTRA_ENV_VAR + value: EXTRA_ENV_VAR_VALUE + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ENV_VAR + value: ENV_VAR_VALUE + - contains: + path: spec.template.spec.containers[0].env + content: + name: EXTRA_ENV_VAR + value: EXTRA_ENV_VAR_VALUE diff --git a/deploy/charts/litellm-helm/tests/masterkey-secret_tests.yaml b/deploy/charts/litellm-helm/tests/masterkey-secret_tests.yaml new file mode 100644 index 00000000000..eb1d3c3967f --- /dev/null +++ b/deploy/charts/litellm-helm/tests/masterkey-secret_tests.yaml @@ -0,0 +1,18 @@ +suite: test masterkey secret +templates: + - secret-masterkey.yaml +tests: + - it: should create a secret if masterkeySecretName is not set + template: secret-masterkey.yaml + set: + masterkeySecretName: "" + asserts: + - isKind: + of: Secret + - it: should not create a secret if masterkeySecretName is set + template: secret-masterkey.yaml + set: + masterkeySecretName: my-secret + asserts: + - hasDocuments: + count: 0 diff --git a/deploy/charts/litellm-helm/values.yaml b/deploy/charts/litellm-helm/values.yaml index 19cbf723211..0440e28eed0 100644 --- a/deploy/charts/litellm-helm/values.yaml +++ b/deploy/charts/litellm-helm/values.yaml @@ -75,6 +75,12 @@ ingress: # masterkey: changeit +# if set, use this secret for the master key; otherwise, autogenerate a new one +masterkeySecretName: "" + +# if set, use this secret key for the master key; otherwise, use the default key +masterkeySecretKey: "" + # The elements within proxy_config are rendered as config.yaml for the proxy # Examples: https://github.com/BerriAI/litellm/tree/main/litellm/proxy/example_config_yaml # Reference: https://docs.litellm.ai/docs/proxy/configs @@ -187,10 +193,17 @@ migrationJob: backoffLimit: 4 # Backoff limit for Job restarts disableSchemaUpdate: false # Skip schema migrations for specific environments. When True, the job will exit with code 0. annotations: {} + ttlSecondsAfterFinished: 120 -# Additional environment variables to be added to the deployment +# Additional environment variables to be added to the deployment as a map of key-value pairs envVars: { # USE_DDTRACE: "true" } +# Additional environment variables to be added to the deployment as a list of k8s env vars +extraEnvVars: { + # - name: EXTRA_ENV_VAR + # value: EXTRA_ENV_VAR_VALUE +} + diff --git a/docker-compose.yml b/docker-compose.yml index 1508bd375cc..2ef84882298 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,25 +16,42 @@ services: ports: - "4000:4000" # Map the container port to the host, change the host port if necessary environment: - DATABASE_URL: "postgresql://llmproxy:dbpassword9090@db:5432/litellm" - STORE_MODEL_IN_DB: "True" # allows adding models to proxy via UI + DATABASE_URL: "postgresql://llmproxy:dbpassword9090@db:5432/litellm" + STORE_MODEL_IN_DB: "True" # allows adding models to proxy via UI env_file: - .env # Load local .env file + depends_on: + - db # Indicates that this service depends on the 'db' service, ensuring 'db' starts first + healthcheck: # Defines the health check configuration for the container + test: [ + "CMD", + "curl", + "-f", + "http://localhost:4000/health/liveliness || exit 1", + ] # Command to execute for health check + interval: 30s # Perform health check every 30 seconds + timeout: 10s # Health check command times out after 10 seconds + retries: 3 # Retry up to 3 times if health check fails + start_period: 40s # Wait 40 seconds after container start before beginning health checks - db: - image: postgres + image: postgres:16 restart: always + container_name: litellm_db environment: POSTGRES_DB: litellm POSTGRES_USER: llmproxy POSTGRES_PASSWORD: dbpassword9090 + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data # Persists Postgres data across container restarts healthcheck: test: ["CMD-SHELL", "pg_isready -d litellm -U llmproxy"] interval: 1s timeout: 5s retries: 10 - + prometheus: image: prom/prometheus volumes: @@ -43,14 +60,14 @@ services: ports: - "9090:9090" command: - - '--config.file=/etc/prometheus/prometheus.yml' - - '--storage.tsdb.path=/prometheus' - - '--storage.tsdb.retention.time=15d' + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus" + - "--storage.tsdb.retention.time=15d" restart: always volumes: prometheus_data: driver: local + postgres_data: + name: litellm_postgres_data # Named volume for Postgres data persistence - -# ...rest of your docker-compose config if any diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index 70ab9cac01d..f036081549a 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -11,9 +11,7 @@ FROM $LITELLM_BUILD_IMAGE AS builder WORKDIR /app # Install build dependencies -RUN apk update && \ - apk add --no-cache gcc python3-dev musl-dev && \ - rm -rf /var/cache/apk/* +RUN apk add --no-cache gcc python3-dev musl-dev RUN pip install --upgrade pip && \ pip install build @@ -37,7 +35,7 @@ RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt FROM $LITELLM_RUNTIME_IMAGE AS runtime # Update dependencies and clean up -RUN apk update && apk upgrade && rm -rf /var/cache/apk/* +RUN apk upgrade --no-cache WORKDIR /app diff --git a/docker/Dockerfile.database b/docker/Dockerfile.database index 02eb2861802..da0326fd2cd 100644 --- a/docker/Dockerfile.database +++ b/docker/Dockerfile.database @@ -12,8 +12,7 @@ WORKDIR /app USER root # Install build dependencies -RUN apk update && \ - apk add --no-cache gcc python3-dev openssl openssl-dev +RUN apk add --no-cache gcc python3-dev openssl openssl-dev RUN pip install --upgrade pip && \ @@ -44,8 +43,7 @@ FROM $LITELLM_RUNTIME_IMAGE AS runtime USER root # Install runtime dependencies -RUN apk update && \ - apk add --no-cache openssl +RUN apk add --no-cache openssl WORKDIR /app # Copy the current directory contents into the container at /app @@ -59,9 +57,6 @@ 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/ && rm -f *.whl && rm -rf /wheels -# install semantic-cache [Experimental]- we need this here and not in requirements.txt because redisvl pins to pydantic 1.0 -RUN pip install redisvl==0.0.7 --no-deps - # ensure pyjwt is used, not jwt RUN pip uninstall jwt -y RUN pip uninstall PyJWT -y diff --git a/docker/Dockerfile.non_root b/docker/Dockerfile.non_root index 3a4cdb59d52..079778cafb8 100644 --- a/docker/Dockerfile.non_root +++ b/docker/Dockerfile.non_root @@ -14,7 +14,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install build dependencies RUN apt-get clean && apt-get update && \ - apt-get install -y gcc python3-dev && \ + apt-get install -y gcc g++ python3-dev && \ rm -rf /var/lib/apt/lists/* RUN pip install --no-cache-dir --upgrade pip && \ @@ -56,10 +56,8 @@ 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/ && rm -f *.whl && rm -rf /wheels -# install semantic-cache [Experimental]- we need this here and not in requirements.txt because redisvl pins to pydantic 1.0 # ensure pyjwt is used, not jwt -RUN pip install redisvl==0.0.7 --no-deps --no-cache-dir && \ - pip uninstall jwt -y && \ +RUN pip uninstall jwt -y && \ pip uninstall PyJWT -y && \ pip install PyJWT==2.9.0 --no-cache-dir diff --git a/docker/build_from_pip/requirements.txt b/docker/build_from_pip/requirements.txt index 3fa275ac082..71e038b6267 100644 --- a/docker/build_from_pip/requirements.txt +++ b/docker/build_from_pip/requirements.txt @@ -1,4 +1,4 @@ -litellm[proxy] # Specify the litellm version you want to use +litellm[proxy]==1.67.4.dev1 # Specify the litellm version you want to use prometheus_client langfuse prisma diff --git a/docs/my-website/.gitignore b/docs/my-website/.gitignore index 4d860457230..c5090458cda 100644 --- a/docs/my-website/.gitignore +++ b/docs/my-website/.gitignore @@ -19,3 +19,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* yarn.lock +pnpm-lock.yaml diff --git a/docs/my-website/docs/anthropic_unified.md b/docs/my-website/docs/anthropic_unified.md new file mode 100644 index 00000000000..8a34db52482 --- /dev/null +++ b/docs/my-website/docs/anthropic_unified.md @@ -0,0 +1,301 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# /v1/messages [BETA] + +Use LiteLLM to call all your LLM APIs in the Anthropic `v1/messages` format. + + +## Overview + +| Feature | Supported | Notes | +|-------|-------|-------| +| Cost Tracking | ✅ | | +| Logging | ✅ | works across all integrations | +| End-user Tracking | ✅ | | +| Streaming | ✅ | | +| Fallbacks | ✅ | between anthropic models | +| Loadbalancing | ✅ | between anthropic models | +| Support llm providers | - `anthropic`
- `bedrock` (only Anthropic models) | | + +Planned improvement: +- Vertex AI Anthropic support + +## Usage +--- + +### LiteLLM Python SDK + +#### Non-streaming example +```python showLineNumbers title="Example using LiteLLM Python SDK" +import litellm +response = await litellm.anthropic.messages.acreate( + messages=[{"role": "user", "content": "Hello, can you tell me a short joke?"}], + api_key=api_key, + model="anthropic/claude-3-haiku-20240307", + max_tokens=100, +) +``` + +Example response: +```json +{ + "content": [ + { + "text": "Hi! this is a very short joke", + "type": "text" + } + ], + "id": "msg_013Zva2CMHLNnXjNJJKqJ2EF", + "model": "claude-3-7-sonnet-20250219", + "role": "assistant", + "stop_reason": "end_turn", + "stop_sequence": null, + "type": "message", + "usage": { + "input_tokens": 2095, + "output_tokens": 503, + "cache_creation_input_tokens": 2095, + "cache_read_input_tokens": 0 + } +} +``` + +#### Streaming example +```python showLineNumbers title="Example using LiteLLM Python SDK" +import litellm +response = await litellm.anthropic.messages.acreate( + messages=[{"role": "user", "content": "Hello, can you tell me a short joke?"}], + api_key=api_key, + model="anthropic/claude-3-haiku-20240307", + max_tokens=100, + stream=True, +) +async for chunk in response: + print(chunk) +``` + +### LiteLLM Proxy Server + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: anthropic-claude + litellm_params: + model: claude-3-7-sonnet-latest +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + + + + +```python showLineNumbers title="Example using LiteLLM Proxy Server" +import anthropic + +# point anthropic sdk to litellm proxy +client = anthropic.Anthropic( + base_url="http://0.0.0.0:4000", + api_key="sk-1234", +) + +response = client.messages.create( + messages=[{"role": "user", "content": "Hello, can you tell me a short joke?"}], + model="anthropic-claude", + max_tokens=100, +) +``` + + + +```bash showLineNumbers title="Example using LiteLLM Proxy Server" +curl -L -X POST 'http://0.0.0.0:4000/v1/messages' \ +-H 'content-type: application/json' \ +-H 'x-api-key: $LITELLM_API_KEY' \ +-H 'anthropic-version: 2023-06-01' \ +-d '{ + "model": "anthropic-claude", + "messages": [ + { + "role": "user", + "content": "Hello, can you tell me a short joke?" + } + ], + "max_tokens": 100 +}' +``` + + + + + +## Request Format +--- + +Request body will be in the Anthropic messages API format. **litellm follows the Anthropic messages specification for this endpoint.** + +#### Example request body + +```json +{ + "model": "claude-3-7-sonnet-20250219", + "max_tokens": 1024, + "messages": [ + { + "role": "user", + "content": "Hello, world" + } + ] +} +``` + +#### Required Fields +- **model** (string): + The model identifier (e.g., `"claude-3-7-sonnet-20250219"`). +- **max_tokens** (integer): + The maximum number of tokens to generate before stopping. + _Note: The model may stop before reaching this limit; value must be greater than 1._ +- **messages** (array of objects): + An ordered list of conversational turns. + Each message object must include: + - **role** (enum: `"user"` or `"assistant"`): + Specifies the speaker of the message. + - **content** (string or array of content blocks): + The text or content blocks (e.g., an array containing objects with a `type` such as `"text"`) that form the message. + _Example equivalence:_ + ```json + {"role": "user", "content": "Hello, Claude"} + ``` + is equivalent to: + ```json + {"role": "user", "content": [{"type": "text", "text": "Hello, Claude"}]} + ``` + +#### Optional Fields +- **metadata** (object): + Contains additional metadata about the request (e.g., `user_id` as an opaque identifier). +- **stop_sequences** (array of strings): + Custom sequences that, when encountered in the generated text, cause the model to stop. +- **stream** (boolean): + Indicates whether to stream the response using server-sent events. +- **system** (string or array): + A system prompt providing context or specific instructions to the model. +- **temperature** (number): + Controls randomness in the model’s responses. Valid range: `0 < temperature < 1`. +- **thinking** (object): + Configuration for enabling extended thinking. If enabled, it includes: + - **budget_tokens** (integer): + Minimum of 1024 tokens (and less than `max_tokens`). + - **type** (enum): + E.g., `"enabled"`. +- **tool_choice** (object): + Instructs how the model should utilize any provided tools. +- **tools** (array of objects): + Definitions for tools available to the model. Each tool includes: + - **name** (string): + The tool’s name. + - **description** (string): + A detailed description of the tool. + - **input_schema** (object): + A JSON schema describing the expected input format for the tool. +- **top_k** (integer): + Limits sampling to the top K options. +- **top_p** (number): + Enables nucleus sampling with a cumulative probability cutoff. Valid range: `0 < top_p < 1`. + + +## Response Format +--- + +Responses will be in the Anthropic messages API format. + +#### Example Response + +```json +{ + "content": [ + { + "text": "Hi! My name is Claude.", + "type": "text" + } + ], + "id": "msg_013Zva2CMHLNnXjNJJKqJ2EF", + "model": "claude-3-7-sonnet-20250219", + "role": "assistant", + "stop_reason": "end_turn", + "stop_sequence": null, + "type": "message", + "usage": { + "input_tokens": 2095, + "output_tokens": 503, + "cache_creation_input_tokens": 2095, + "cache_read_input_tokens": 0 + } +} +``` + +#### Response fields + +- **content** (array of objects): + Contains the generated content blocks from the model. Each block includes: + - **type** (string): + Indicates the type of content (e.g., `"text"`, `"tool_use"`, `"thinking"`, or `"redacted_thinking"`). + - **text** (string): + The generated text from the model. + _Note: Maximum length is 5,000,000 characters._ + - **citations** (array of objects or `null`): + Optional field providing citation details. Each citation includes: + - **cited_text** (string): + The excerpt being cited. + - **document_index** (integer): + An index referencing the cited document. + - **document_title** (string or `null`): + The title of the cited document. + - **start_char_index** (integer): + The starting character index for the citation. + - **end_char_index** (integer): + The ending character index for the citation. + - **type** (string): + Typically `"char_location"`. + +- **id** (string): + A unique identifier for the response message. + _Note: The format and length of IDs may change over time._ + +- **model** (string): + Specifies the model that generated the response. + +- **role** (string): + Indicates the role of the generated message. For responses, this is always `"assistant"`. + +- **stop_reason** (string): + Explains why the model stopped generating text. Possible values include: + - `"end_turn"`: The model reached a natural stopping point. + - `"max_tokens"`: The generation stopped because the maximum token limit was reached. + - `"stop_sequence"`: A custom stop sequence was encountered. + - `"tool_use"`: The model invoked one or more tools. + +- **stop_sequence** (string or `null`): + Contains the specific stop sequence that caused the generation to halt, if applicable; otherwise, it is `null`. + +- **type** (string): + Denotes the type of response object, which is always `"message"`. + +- **usage** (object): + Provides details on token usage for billing and rate limiting. This includes: + - **input_tokens** (integer): + Total number of input tokens processed. + - **output_tokens** (integer): + Total number of output tokens generated. + - **cache_creation_input_tokens** (integer or `null`): + Number of tokens used to create a cache entry. + - **cache_read_input_tokens** (integer or `null`): + Number of tokens read from the cache. diff --git a/docs/my-website/docs/apply_guardrail.md b/docs/my-website/docs/apply_guardrail.md new file mode 100644 index 00000000000..740eb232e13 --- /dev/null +++ b/docs/my-website/docs/apply_guardrail.md @@ -0,0 +1,70 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# /guardrails/apply_guardrail + +Use this endpoint to directly call a guardrail configured on your LiteLLM instance. This is useful when you have services that need to directly call a guardrail. + + +## Usage +--- + +In this example `mask_pii` is the guardrail name configured on LiteLLM. + +```bash showLineNumbers title="Example calling the endpoint" +curl -X POST 'http://localhost:4000/guardrails/apply_guardrail' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer your-api-key' \ +-d '{ + "guardrail_name": "mask_pii", + "text": "My name is John Doe and my email is john@example.com", + "language": "en", + "entities": ["NAME", "EMAIL"] +}' +``` + + +## Request Format +--- + +The request body should follow the ApplyGuardrailRequest format. + +#### Example Request Body + +```json +{ + "guardrail_name": "mask_pii", + "text": "My name is John Doe and my email is john@example.com", + "language": "en", + "entities": ["NAME", "EMAIL"] +} +``` + +#### Required Fields +- **guardrail_name** (string): + The identifier for the guardrail to apply (e.g., "mask_pii"). +- **text** (string): + The input text to process through the guardrail. + +#### Optional Fields +- **language** (string): + The language of the input text (e.g., "en" for English). +- **entities** (array of strings): + Specific entities to process or filter (e.g., ["NAME", "EMAIL"]). + +## Response Format +--- + +The response will contain the processed text after applying the guardrail. + +#### Example Response + +```json +{ + "response_text": "My name is [REDACTED] and my email is [REDACTED]" +} +``` + +#### Response Fields +- **response_text** (string): + The text after applying the guardrail. diff --git a/docs/my-website/docs/assistants.md b/docs/my-website/docs/assistants.md index 5e68e8dded1..4032c74557f 100644 --- a/docs/my-website/docs/assistants.md +++ b/docs/my-website/docs/assistants.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Assistants API +# /assistants Covers Threads, Messages, Assistants. diff --git a/docs/my-website/docs/audio_transcription.md b/docs/my-website/docs/audio_transcription.md index 1695946fe45..22517f68e43 100644 --- a/docs/my-website/docs/audio_transcription.md +++ b/docs/my-website/docs/audio_transcription.md @@ -1,13 +1,15 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Speech to Text +# /audio/transcriptions Use this to loadbalance across Azure + OpenAI. ## Quick Start -```python +### LiteLLM Python SDK + +```python showLineNumbers from litellm import transcription import os @@ -20,7 +22,7 @@ response = transcription(model="whisper", file=audio_file) print(f"response: {response}") ``` -## Proxy Usage +### LiteLLM Proxy ### Add model to config @@ -28,7 +30,7 @@ print(f"response: {response}") -```yaml +```yaml showLineNumbers model_list: - model_name: whisper litellm_params: @@ -43,7 +45,7 @@ general_settings: -```yaml +```yaml showLineNumbers model_list: - model_name: whisper litellm_params: @@ -88,9 +90,9 @@ curl --location 'http://0.0.0.0:8000/v1/audio/transcriptions' \ ``` - + -```python +```python showLineNumbers from openai import OpenAI client = openai.OpenAI( api_key="sk-1234", diff --git a/docs/my-website/docs/batches.md b/docs/my-website/docs/batches.md index 4ac9fa61e3b..4918e30d1fd 100644 --- a/docs/my-website/docs/batches.md +++ b/docs/my-website/docs/batches.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# [BETA] Batches API +# /batches Covers Batches, Files diff --git a/docs/my-website/docs/caching/all_caches.md b/docs/my-website/docs/caching/all_caches.md index dc1951cc772..a14170beefa 100644 --- a/docs/my-website/docs/caching/all_caches.md +++ b/docs/my-website/docs/caching/all_caches.md @@ -3,7 +3,7 @@ import TabItem from '@theme/TabItem'; # Caching - In-Memory, Redis, s3, Redis Semantic Cache, Disk -[**See Code**](https://github.com/BerriAI/litellm/blob/main/litellm.caching.caching.py) +[**See Code**](https://github.com/BerriAI/litellm/blob/main/litellm/caching/caching.py) :::info @@ -26,7 +26,7 @@ Install redis pip install redis ``` -For the hosted version you can setup your own Redis DB here: https://app.redislabs.com/ +For the hosted version you can setup your own Redis DB here: https://redis.io/try-free/ ```python import litellm @@ -37,11 +37,11 @@ litellm.cache = Cache(type="redis", host=, port=, password= -Install redis +Install redisvl client ```shell -pip install redisvl==0.0.7 +pip install redisvl==0.4.1 ``` -For the hosted version you can setup your own Redis DB here: https://app.redislabs.com/ +For the hosted version you can setup your own Redis DB here: https://redis.io/try-free/ ```python import litellm @@ -114,6 +114,7 @@ litellm.cache = Cache( port=os.environ["REDIS_PORT"], password=os.environ["REDIS_PASSWORD"], similarity_threshold=0.8, # similarity threshold for cache hits, 0 == no similarity, 1 = exact matches, 0.5 == 50% similarity + ttl=120, redis_semantic_cache_embedding_model="text-embedding-ada-002", # this model is passed to litellm.embedding(), any litellm.embedding() model is supported here ) response1 = completion( @@ -471,11 +472,13 @@ def __init__( password: Optional[str] = None, namespace: Optional[str] = None, default_in_redis_ttl: Optional[float] = None, - similarity_threshold: Optional[float] = None, - redis_semantic_cache_use_async=False, - redis_semantic_cache_embedding_model="text-embedding-ada-002", redis_flush_size=None, + # redis semantic cache params + similarity_threshold: Optional[float] = None, + redis_semantic_cache_embedding_model: str = "text-embedding-ada-002", + redis_semantic_cache_index_name: Optional[str] = None, + # s3 Bucket, boto3 configuration s3_bucket_name: Optional[str] = None, s3_region_name: Optional[str] = None, diff --git a/docs/my-website/docs/completion/audio.md b/docs/my-website/docs/completion/audio.md index 97153a5867d..96b5e4f41c6 100644 --- a/docs/my-website/docs/completion/audio.md +++ b/docs/my-website/docs/completion/audio.md @@ -3,7 +3,7 @@ import TabItem from '@theme/TabItem'; # Using Audio Models -How to send / receieve audio to a `/chat/completions` endpoint +How to send / receive audio to a `/chat/completions` endpoint ## Audio Output from a model diff --git a/docs/my-website/docs/completion/document_understanding.md b/docs/my-website/docs/completion/document_understanding.md index 6719169aef9..04047a5909a 100644 --- a/docs/my-website/docs/completion/document_understanding.md +++ b/docs/my-website/docs/completion/document_understanding.md @@ -3,7 +3,7 @@ import TabItem from '@theme/TabItem'; # Using PDF Input -How to send / receieve pdf's (other document types) to a `/chat/completions` endpoint +How to send / receive pdf's (other document types) to a `/chat/completions` endpoint Works for: - Vertex AI models (Gemini + Anthropic) @@ -27,16 +27,18 @@ os.environ["AWS_REGION_NAME"] = "" # pdf url -image_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" +file_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" # model model = "bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0" -image_content = [ +file_content = [ {"type": "text", "text": "What's this file about?"}, { - "type": "image_url", - "image_url": image_url, # OR {"url": image_url} + "type": "file", + "file": { + "file_id": file_url, + } }, ] @@ -46,7 +48,7 @@ if not supports_pdf_input(model, None): response = completion( model=model, - messages=[{"role": "user", "content": image_content}], + messages=[{"role": "user", "content": file_content}], ) assert response is not None ``` @@ -80,11 +82,15 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -d '{ "model": "bedrock-model", "messages": [ - {"role": "user", "content": {"type": "text", "text": "What's this file about?"}}, - { - "type": "image_url", - "image_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", - } + {"role": "user", "content": [ + {"type": "text", "text": "What's this file about?"}, + { + "type": "file", + "file": { + "file_id": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", + } + } + ]}, ] }' ``` @@ -116,11 +122,13 @@ base64_url = f"data:application/pdf;base64,{encoded_file}" # model model = "bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0" -image_content = [ +file_content = [ {"type": "text", "text": "What's this file about?"}, { - "type": "image_url", - "image_url": base64_url, # OR {"url": base64_url} + "type": "file", + "file": { + "file_data": base64_url, + } }, ] @@ -130,13 +138,146 @@ if not supports_pdf_input(model, None): response = completion( model=model, - messages=[{"role": "user", "content": image_content}], + messages=[{"role": "user", "content": file_content}], ) assert response is not None ``` + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-model + litellm_params: + model: bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0 + aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID + aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY + aws_region_name: os.environ/AWS_REGION_NAME +``` + +2. Start the proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "bedrock-model", + "messages": [ + {"role": "user", "content": [ + {"type": "text", "text": "What's this file about?"}, + { + "type": "file", + "file": { + "file_data": "data:application/pdf;base64...", + } + } + ]}, + ] +}' +``` + +## Specifying format + +To specify the format of the document, you can use the `format` parameter. + + + + + +```python +from litellm.utils import supports_pdf_input, completion + +# set aws credentials +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + + +# pdf url +file_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" + +# model +model = "bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0" + +file_content = [ + {"type": "text", "text": "What's this file about?"}, + { + "type": "file", + "file": { + "file_id": file_url, + "format": "application/pdf", + } + }, +] + + +if not supports_pdf_input(model, None): + print("Model does not support image input") + +response = completion( + model=model, + messages=[{"role": "user", "content": file_content}], +) +assert response is not None +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-model + litellm_params: + model: bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0 + aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID + aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY + aws_region_name: os.environ/AWS_REGION_NAME +``` + +2. Start the proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "bedrock-model", + "messages": [ + {"role": "user", "content": [ + {"type": "text", "text": "What's this file about?"}, + { + "type": "file", + "file": { + "file_id": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", + "format": "application/pdf", + } + } + ]}, + ] +}' +``` + + + + ## Checking if a model supports pdf input diff --git a/docs/my-website/docs/completion/drop_params.md b/docs/my-website/docs/completion/drop_params.md index e79a88e14bb..590d9a45955 100644 --- a/docs/my-website/docs/completion/drop_params.md +++ b/docs/my-website/docs/completion/drop_params.md @@ -107,4 +107,76 @@ response = litellm.completion( -**additional_drop_params**: List or null - Is a list of openai params you want to drop when making a call to the model. \ No newline at end of file +**additional_drop_params**: List or null - Is a list of openai params you want to drop when making a call to the model. + +## Specify allowed openai params in a request + +Tell litellm to allow specific openai params in a request. Use this if you get a `litellm.UnsupportedParamsError` and want to allow a param. LiteLLM will pass the param as is to the model. + + + + + + +In this example we pass `allowed_openai_params=["tools"]` to allow the `tools` param. + +```python showLineNumbers title="Pass allowed_openai_params to LiteLLM Python SDK" +await litellm.acompletion( + model="azure/o_series/", + api_key="xxxxx", + api_base=api_base, + messages=[{"role": "user", "content": "Hello! return a json object"}], + tools=[{"type": "function", "function": {"name": "get_current_time", "description": "Get the current time in a given location.", "parameters": {"type": "object", "properties": {"location": {"type": "string", "description": "The city name, e.g. San Francisco"}}, "required": ["location"]}}}] + allowed_openai_params=["tools"], +) +``` + + + +When using litellm proxy you can pass `allowed_openai_params` in two ways: + +1. Dynamically pass `allowed_openai_params` in a request +2. Set `allowed_openai_params` on the config.yaml file for a specific model + +#### Dynamically pass allowed_openai_params in a request +In this example we pass `allowed_openai_params=["tools"]` to allow the `tools` param for a request sent to the model set on the proxy. + +```python showLineNumbers title="Dynamically pass allowed_openai_params in a request" +import openai +from openai import AsyncAzureOpenAI + +import openai +client = openai.OpenAI( + api_key="anything", + base_url="http://0.0.0.0:4000" +) + +response = client.chat.completions.create( + model="gpt-3.5-turbo", + messages = [ + { + "role": "user", + "content": "this is a test request, write a short poem" + } + ], + extra_body={ + "allowed_openai_params": ["tools"] + } +) +``` + +#### Set allowed_openai_params on config.yaml + +You can also set `allowed_openai_params` on the config.yaml file for a specific model. This means that all requests to this deployment are allowed to pass in the `tools` param. + +```yaml showLineNumbers title="Set allowed_openai_params on config.yaml" +model_list: + - model_name: azure-o1-preview + litellm_params: + model: azure/o_series/ + api_key: xxxxx + api_base: https://openai-prod-test.openai.azure.com/openai/deployments/o1/chat/completions?api-version=2025-01-01-preview + allowed_openai_params: ["tools"] +``` + + \ No newline at end of file diff --git a/docs/my-website/docs/completion/function_call.md b/docs/my-website/docs/completion/function_call.md index 514e8cda1a2..f10df68bf6f 100644 --- a/docs/my-website/docs/completion/function_call.md +++ b/docs/my-website/docs/completion/function_call.md @@ -8,6 +8,7 @@ Use `litellm.supports_function_calling(model="")` -> returns `True` if model sup assert litellm.supports_function_calling(model="gpt-3.5-turbo") == True assert litellm.supports_function_calling(model="azure/gpt-4-1106-preview") == True assert litellm.supports_function_calling(model="palm/chat-bison") == False +assert litellm.supports_function_calling(model="xai/grok-2-latest") == True assert litellm.supports_function_calling(model="ollama/llama2") == False ``` diff --git a/docs/my-website/docs/completion/input.md b/docs/my-website/docs/completion/input.md index 67738a7f1cc..f9751094249 100644 --- a/docs/my-website/docs/completion/input.md +++ b/docs/my-website/docs/completion/input.md @@ -44,6 +44,7 @@ Use `litellm.get_supported_openai_params()` for an updated list of params for ea |Anthropic| ✅ | ✅ | ✅ |✅ | ✅ | ✅ | ✅ | | | | | | |✅ | ✅ | | ✅ | ✅ | | | ✅ | |OpenAI| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |✅ | ✅ | ✅ | ✅ |✅ | ✅ | ✅ | ✅ | ✅ | |Azure OpenAI| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |✅ | ✅ | ✅ | ✅ |✅ | ✅ | | | ✅ | +|xAI| ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | |Replicate | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | |Anyscale | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |Cohere| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | @@ -54,6 +55,7 @@ Use `litellm.get_supported_openai_params()` for an updated list of params for ea |Bedrock| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | | | | | ✅ (model dependent) | | |Sagemaker| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | |TogetherAI| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | ✅ | | | ✅ | | ✅ | ✅ | | | | +|Sambanova| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | | | ✅ | | ✅ | ✅ | | | | |AlephAlpha| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | |NLP Cloud| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | |Petals| ✅ | ✅ | | ✅ | ✅ | | | | | | @@ -61,6 +63,7 @@ Use `litellm.get_supported_openai_params()` for an updated list of params for ea |Databricks| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | | | | | | |ClarifAI| ✅ | ✅ | ✅ | |✅ | ✅ | | | | | | | | | | | |Github| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | ✅ |✅ (model dependent)|✅ (model dependent)| | | +|Novita AI| ✅ | ✅ | | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ | ✅ | | | ✅ | | | | | | | | :::note By default, LiteLLM raises an exception if the openai param being passed in isn't supported. diff --git a/docs/my-website/docs/completion/json_mode.md b/docs/my-website/docs/completion/json_mode.md index 0c3a930764c..ec140ce5827 100644 --- a/docs/my-website/docs/completion/json_mode.md +++ b/docs/my-website/docs/completion/json_mode.md @@ -89,6 +89,7 @@ response_format: { "type": "json_schema", "json_schema": … , "strict": true } Works for: - OpenAI models - Azure OpenAI models +- xAI models (Grok-2 or later) - Google AI Studio - Gemini models - Vertex AI models (Gemini + Anthropic) - Bedrock Models diff --git a/docs/my-website/docs/completion/knowledgebase.md b/docs/my-website/docs/completion/knowledgebase.md new file mode 100644 index 00000000000..033dccea200 --- /dev/null +++ b/docs/my-website/docs/completion/knowledgebase.md @@ -0,0 +1,356 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; + +# Using Vector Stores (Knowledge Bases) + + +

+ Use Vector Stores with any LiteLLM supported model +

+ + +LiteLLM integrates with vector stores, allowing your models to access your organization's data for more accurate and contextually relevant responses. + +## Supported Vector Stores +- [Bedrock Knowledge Bases](https://aws.amazon.com/bedrock/knowledge-bases/) + +## Quick Start + +In order to use a vector store with LiteLLM, you need to + +- Initialize litellm.vector_store_registry +- Pass tools with vector_store_ids to the completion request. Where `vector_store_ids` is a list of vector store ids you initialized in litellm.vector_store_registry + +### LiteLLM Python SDK + +LiteLLM's allows you to use vector stores in the [OpenAI API spec](https://platform.openai.com/docs/api-reference/chat/create) by passing a tool with vector_store_ids you want to use + +```python showLineNumbers title="Basic Bedrock Knowledge Base Usage" +import os +import litellm + +from litellm.vector_stores.vector_store_registry import VectorStoreRegistry, LiteLLM_ManagedVectorStore + +# Init vector store registry +litellm.vector_store_registry = VectorStoreRegistry( + vector_stores=[ + LiteLLM_ManagedVectorStore( + vector_store_id="T37J8R4WTM", + custom_llm_provider="bedrock" + ) + ] +) + + +# Make a completion request with vector_store_ids parameter +response = await litellm.acompletion( + model="anthropic/claude-3-5-sonnet", + messages=[{"role": "user", "content": "What is litellm?"}], + tools=[ + { + "type": "file_search", + "vector_store_ids": ["T37J8R4WTM"] + } + ], +) + +print(response.choices[0].message.content) +``` + +### LiteLLM Proxy + +#### 1. Configure your vector_store_registry + +In order to use a vector store with LiteLLM, you need to configure your vector_store_registry. This tells litellm which vector stores to use and api provider to use for the vector store. + + + + +```yaml showLineNumbers title="config.yaml" +model_list: + - model_name: claude-3-5-sonnet + litellm_params: + model: anthropic/claude-3-5-sonnet + api_key: os.environ/ANTHROPIC_API_KEY + +vector_store_registry: + - vector_store_name: "bedrock-litellm-website-knowledgebase" + litellm_params: + vector_store_id: "T37J8R4WTM" + custom_llm_provider: "bedrock" + vector_store_description: "Bedrock vector store for the Litellm website knowledgebase" + vector_store_metadata: + source: "https://www.litellm.com/docs" + +``` + + + + + +On the LiteLLM UI, Navigate to Experimental > Vector Stores > Create Vector Store. On this page you can create a vector store with a name, vector store id and credentials. + + + + + + + + + +#### 2. Make a request with vector_store_ids parameter + + + + +```bash showLineNumbers title="Curl Request to LiteLLM Proxy" +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_API_KEY" \ + -d '{ + "model": "claude-3-5-sonnet", + "messages": [{"role": "user", "content": "What is litellm?"}], + "tools": [ + { + "type": "file_search", + "vector_store_ids": ["T37J8R4WTM"] + } + ] + }' +``` + + + + + +```python showLineNumbers title="OpenAI Python SDK Request" +from openai import OpenAI + +# Initialize client with your LiteLLM proxy URL +client = OpenAI( + base_url="http://localhost:4000", + api_key="your-litellm-api-key" +) + +# Make a completion request with vector_store_ids parameter +response = client.chat.completions.create( + model="claude-3-5-sonnet", + messages=[{"role": "user", "content": "What is litellm?"}], + tools=[ + { + "type": "file_search", + "vector_store_ids": ["T37J8R4WTM"] + } + ] +) + +print(response.choices[0].message.content) +``` + + + + + + + +## Advanced + +### Logging Vector Store Usage + +LiteLLM allows you to view your vector store usage in the LiteLLM UI on the `Logs` page. + +After completing a request with a vector store, navigate to the `Logs` page on LiteLLM. Here you should be able to see the query sent to the vector store and corresponding response with scores. + + +

+ LiteLLM Logs Page: Vector Store Usage +

+ + +### Listing available vector stores + +You can list all available vector stores using the /vector_store/list endpoint + +**Request:** +```bash showLineNumbers title="List all available vector stores" +curl -X GET "http://localhost:4000/vector_store/list" \ + -H "Authorization: Bearer $LITELLM_API_KEY" +``` + +**Response:** + +The response will be a list of all vector stores that are available to use with LiteLLM. + +```json +{ + "object": "list", + "data": [ + { + "vector_store_id": "T37J8R4WTM", + "custom_llm_provider": "bedrock", + "vector_store_name": "bedrock-litellm-website-knowledgebase", + "vector_store_description": "Bedrock vector store for the Litellm website knowledgebase", + "vector_store_metadata": { + "source": "https://www.litellm.com/docs" + }, + "created_at": "2023-05-03T18:21:36.462Z", + "updated_at": "2023-05-03T18:21:36.462Z", + "litellm_credential_name": "bedrock_credentials" + } + ], + "total_count": 1, + "current_page": 1, + "total_pages": 1 +} +``` + + +### Always on for a model + +**Use this if you want vector stores to be used by default for a specific model.** + +In this config, we add `vector_store_ids` to the claude-3-5-sonnet-with-vector-store model. This means that any request to the claude-3-5-sonnet-with-vector-store model will always use the vector store with the id `T37J8R4WTM` defined in the `vector_store_registry`. + +```yaml showLineNumbers title="Always on for a model" +model_list: + - model_name: claude-3-5-sonnet-with-vector-store + litellm_params: + model: anthropic/claude-3-5-sonnet + vector_store_ids: ["T37J8R4WTM"] + +vector_store_registry: + - vector_store_name: "bedrock-litellm-website-knowledgebase" + litellm_params: + vector_store_id: "T37J8R4WTM" + custom_llm_provider: "bedrock" + vector_store_description: "Bedrock vector store for the Litellm website knowledgebase" + vector_store_metadata: + source: "https://www.litellm.com/docs" +``` + +## How It Works + +If your request includes a `vector_store_ids` parameter where any of the vector store ids are found in the `vector_store_registry`, LiteLLM will automatically use the vector store for the request. + +1. You make a completion request with the `vector_store_ids` parameter and any of the vector store ids are found in the `litellm.vector_store_registry` +2. LiteLLM automatically: + - Uses your last message as the query to retrieve relevant information from the Knowledge Base + - Adds the retrieved context to your conversation + - Sends the augmented messages to the model + +#### Example Transformation + +When you pass `vector_store_ids=["YOUR_KNOWLEDGE_BASE_ID"]`, your request flows through these steps: + +**1. Original Request to LiteLLM:** +```json +{ + "model": "anthropic/claude-3-5-sonnet", + "messages": [ + {"role": "user", "content": "What is litellm?"} + ], + "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"] +} +``` + +**2. Request to AWS Bedrock Knowledge Base:** +```json +{ + "retrievalQuery": { + "text": "What is litellm?" + } +} +``` +This is sent to: `https://bedrock-agent-runtime.{aws_region}.amazonaws.com/knowledgebases/YOUR_KNOWLEDGE_BASE_ID/retrieve` + +**3. Final Request to LiteLLM:** +```json +{ + "model": "anthropic/claude-3-5-sonnet", + "messages": [ + {"role": "user", "content": "What is litellm?"}, + {"role": "user", "content": "Context: \n\nLiteLLM is an open-source SDK to simplify LLM API calls across providers (OpenAI, Claude, etc). It provides a standardized interface with robust error handling, streaming, and observability tools."} + ] +} +``` + +This process happens automatically whenever you include the `vector_store_ids` parameter in your request. + +## API Reference + +### LiteLLM Completion Knowledge Base Parameters + +When using the Knowledge Base integration with LiteLLM, you can include the following parameters: + +| Parameter | Type | Description | +|-----------|------|-------------| +| `vector_store_ids` | List[str] | List of Knowledge Base IDs to query | + +### VectorStoreRegistry + +The `VectorStoreRegistry` is a central component for managing vector stores in LiteLLM. It acts as a registry where you can configure and access your vector stores. + +#### What is VectorStoreRegistry? + +`VectorStoreRegistry` is a class that: +- Maintains a collection of vector stores that LiteLLM can use +- Allows you to register vector stores with their credentials and metadata +- Makes vector stores accessible via their IDs in your completion requests + +#### Using VectorStoreRegistry in Python + +```python +from litellm.vector_stores.vector_store_registry import VectorStoreRegistry, LiteLLM_ManagedVectorStore + +# Initialize the vector store registry with one or more vector stores +litellm.vector_store_registry = VectorStoreRegistry( + vector_stores=[ + LiteLLM_ManagedVectorStore( + vector_store_id="YOUR_VECTOR_STORE_ID", # Required: Unique ID for referencing this store + custom_llm_provider="bedrock" # Required: Provider (e.g., "bedrock") + ) + ] +) +``` + +#### LiteLLM_ManagedVectorStore Parameters + +Each vector store in the registry is configured using a `LiteLLM_ManagedVectorStore` object with these parameters: + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vector_store_id` | str | Yes | Unique identifier for the vector store | +| `custom_llm_provider` | str | Yes | The provider of the vector store (e.g., "bedrock") | +| `vector_store_name` | str | No | A friendly name for the vector store | +| `vector_store_description` | str | No | Description of what the vector store contains | +| `vector_store_metadata` | dict or str | No | Additional metadata about the vector store | +| `litellm_credential_name` | str | No | Name of the credentials to use for this vector store | + +#### Configuring VectorStoreRegistry in config.yaml + +For the LiteLLM Proxy, you can configure the same registry in your `config.yaml` file: + +```yaml showLineNumbers title="Vector store configuration in config.yaml" +vector_store_registry: + - vector_store_name: "bedrock-litellm-website-knowledgebase" # Optional friendly name + litellm_params: + vector_store_id: "T37J8R4WTM" # Required: Unique ID + custom_llm_provider: "bedrock" # Required: Provider + vector_store_description: "Bedrock vector store for the Litellm website knowledgebase" + vector_store_metadata: + source: "https://www.litellm.com/docs" +``` + +The `litellm_params` section accepts all the same parameters as the `LiteLLM_ManagedVectorStore` constructor in the Python SDK. + + diff --git a/docs/my-website/docs/completion/prompt_caching.md b/docs/my-website/docs/completion/prompt_caching.md index 5c795778ef9..9447a11d527 100644 --- a/docs/my-website/docs/completion/prompt_caching.md +++ b/docs/my-website/docs/completion/prompt_caching.md @@ -3,7 +3,13 @@ import TabItem from '@theme/TabItem'; # Prompt Caching -For OpenAI + Anthropic + Deepseek, LiteLLM follows the OpenAI prompt caching usage object format: +Supported Providers: +- OpenAI (`openai/`) +- Anthropic API (`anthropic/`) +- Bedrock (`bedrock/`, `bedrock/invoke/`, `bedrock/converse`) ([All models bedrock supports prompt caching on](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html)) +- Deepseek API (`deepseek/`) + +For the supported providers, LiteLLM follows the OpenAI prompt caching usage object format: ```bash "usage": { @@ -499,4 +505,4 @@ curl -L -X GET 'http://0.0.0.0:4000/v1/model/info' \ -This checks our maintained [model info/cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) \ No newline at end of file +This checks our maintained [model info/cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) diff --git a/docs/my-website/docs/completion/reliable_completions.md b/docs/my-website/docs/completion/reliable_completions.md index 94102e1944e..f38917fe53d 100644 --- a/docs/my-website/docs/completion/reliable_completions.md +++ b/docs/my-website/docs/completion/reliable_completions.md @@ -46,7 +46,7 @@ from litellm import completion fallback_dict = {"gpt-3.5-turbo": "gpt-3.5-turbo-16k"} messages = [{"content": "how does a court case get to the Supreme Court?" * 500, "role": "user"}] -completion(model="gpt-3.5-turbo", messages=messages, context_window_fallback_dict=ctx_window_fallback_dict) +completion(model="gpt-3.5-turbo", messages=messages, context_window_fallback_dict=fallback_dict) ``` ### Fallbacks - Switch Models/API Keys/API Bases (SDK) diff --git a/docs/my-website/docs/completion/vision.md b/docs/my-website/docs/completion/vision.md index 0880d0ec492..76700084868 100644 --- a/docs/my-website/docs/completion/vision.md +++ b/docs/my-website/docs/completion/vision.md @@ -118,9 +118,11 @@ response = client.chat.completions.create( Use `litellm.supports_vision(model="")` -> returns `True` if model supports `vision` and `False` if not ```python -assert litellm.supports_vision(model="gpt-4-vision-preview") == True -assert litellm.supports_vision(model="gemini-1.0-pro-vision") == True -assert litellm.supports_vision(model="gpt-3.5-turbo") == False +assert litellm.supports_vision(model="openai/gpt-4-vision-preview") == True +assert litellm.supports_vision(model="vertex_ai/gemini-1.0-pro-vision") == True +assert litellm.supports_vision(model="openai/gpt-3.5-turbo") == False +assert litellm.supports_vision(model="xai/grok-2-vision-latest") == True +assert litellm.supports_vision(model="xai/grok-2-latest") == False ``` @@ -187,4 +189,138 @@ Expected Response ``` - \ No newline at end of file + + + +## Explicitly specify image type + +If you have images without a mime-type, or if litellm is incorrectly inferring the mime type of your image (e.g. calling `gs://` url's with vertex ai), you can set this explicitly via the `format` param. + +```python +"image_url": { + "url": "gs://my-gs-image", + "format": "image/jpeg" +} +``` + +LiteLLM will use this for any API endpoint, which supports specifying mime-type (e.g. anthropic/bedrock/vertex ai). + +For others (e.g. openai), it will be ignored. + + + + +```python +import os +from litellm import completion + +os.environ["ANTHROPIC_API_KEY"] = "your-api-key" + +# openai call +response = completion( + model = "claude-3-7-sonnet-latest", + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What’s in this image?" + }, + { + "type": "image_url", + "image_url": { + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + "format": "image/jpeg" + } + } + ] + } + ], +) + +``` + + + + +1. Define vision models on config.yaml + +```yaml +model_list: + - model_name: gpt-4-vision-preview # OpenAI gpt-4-vision-preview + litellm_params: + model: openai/gpt-4-vision-preview + api_key: os.environ/OPENAI_API_KEY + - model_name: llava-hf # Custom OpenAI compatible model + litellm_params: + model: openai/llava-hf/llava-v1.6-vicuna-7b-hf + api_base: http://localhost:8000 + api_key: fake-key + model_info: + supports_vision: True # set supports_vision to True so /model/info returns this attribute as True + +``` + +2. Run proxy server + +```bash +litellm --config config.yaml +``` + +3. Test it using the OpenAI Python SDK + + +```python +import os +from openai import OpenAI + +client = OpenAI( + api_key="sk-1234", # your litellm proxy api key +) + +response = client.chat.completions.create( + model = "gpt-4-vision-preview", # use model="llava-hf" to test your custom OpenAI endpoint + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What’s in this image?" + }, + { + "type": "image_url", + "image_url": { + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + "format": "image/jpeg" + } + } + ] + } + ], +) + +``` + + + + + + + + + +## Spec + +``` +"image_url": str + +OR + +"image_url": { + "url": "url OR base64 encoded str", + "detail": "openai-only param", + "format": "specify mime-type of image" +} +``` \ No newline at end of file diff --git a/docs/my-website/docs/completion/web_search.md b/docs/my-website/docs/completion/web_search.md new file mode 100644 index 00000000000..7a67dc265e4 --- /dev/null +++ b/docs/my-website/docs/completion/web_search.md @@ -0,0 +1,308 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Using Web Search + +Use web search with litellm + +| Feature | Details | +|---------|---------| +| Supported Endpoints | - `/chat/completions`
- `/responses` | +| Supported Providers | `openai` | +| LiteLLM Cost Tracking | ✅ Supported | +| LiteLLM Version | `v1.63.15-nightly` or higher | + + +## `/chat/completions` (litellm.completion) + +### Quick Start + + + + +```python showLineNumbers +from litellm import completion + +response = completion( + model="openai/gpt-4o-search-preview", + messages=[ + { + "role": "user", + "content": "What was a positive news story from today?", + } + ], +) +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: gpt-4o-search-preview + litellm_params: + model: openai/gpt-4o-search-preview + api_key: os.environ/OPENAI_API_KEY +``` + +2. Start the proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```python showLineNumbers +from openai import OpenAI + +# Point to your proxy server +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000" +) + +response = client.chat.completions.create( + model="gpt-4o-search-preview", + messages=[ + { + "role": "user", + "content": "What was a positive news story from today?" + } + ] +) +``` + + + +### Search context size + + + + +```python showLineNumbers +from litellm import completion + +# Customize search context size +response = completion( + model="openai/gpt-4o-search-preview", + messages=[ + { + "role": "user", + "content": "What was a positive news story from today?", + } + ], + web_search_options={ + "search_context_size": "low" # Options: "low", "medium" (default), "high" + } +) +``` + + + +```python showLineNumbers +from openai import OpenAI + +# Point to your proxy server +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000" +) + +# Customize search context size +response = client.chat.completions.create( + model="gpt-4o-search-preview", + messages=[ + { + "role": "user", + "content": "What was a positive news story from today?" + } + ], + web_search_options={ + "search_context_size": "low" # Options: "low", "medium" (default), "high" + } +) +``` + + + +## `/responses` (litellm.responses) + +### Quick Start + + + + +```python showLineNumbers +from litellm import responses + +response = responses( + model="openai/gpt-4o", + input=[ + { + "role": "user", + "content": "What was a positive news story from today?" + } + ], + tools=[{ + "type": "web_search_preview" # enables web search with default medium context size + }] +) +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: gpt-4o + litellm_params: + model: openai/gpt-4o + api_key: os.environ/OPENAI_API_KEY +``` + +2. Start the proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```python showLineNumbers +from openai import OpenAI + +# Point to your proxy server +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000" +) + +response = client.responses.create( + model="gpt-4o", + tools=[{ + "type": "web_search_preview" + }], + input="What was a positive news story from today?", +) + +print(response.output_text) +``` + + + +### Search context size + + + + +```python showLineNumbers +from litellm import responses + +# Customize search context size +response = responses( + model="openai/gpt-4o", + input=[ + { + "role": "user", + "content": "What was a positive news story from today?" + } + ], + tools=[{ + "type": "web_search_preview", + "search_context_size": "low" # Options: "low", "medium" (default), "high" + }] +) +``` + + + +```python showLineNumbers +from openai import OpenAI + +# Point to your proxy server +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000" +) + +# Customize search context size +response = client.responses.create( + model="gpt-4o", + tools=[{ + "type": "web_search_preview", + "search_context_size": "low" # Options: "low", "medium" (default), "high" + }], + input="What was a positive news story from today?", +) + +print(response.output_text) +``` + + + + + + + + +## Checking if a model supports web search + + + + +Use `litellm.supports_web_search(model="openai/gpt-4o-search-preview")` -> returns `True` if model can perform web searches + +```python showLineNumbers +assert litellm.supports_web_search(model="openai/gpt-4o-search-preview") == True +``` + + + + +1. Define OpenAI models in config.yaml + +```yaml +model_list: + - model_name: gpt-4o-search-preview + litellm_params: + model: openai/gpt-4o-search-preview + api_key: os.environ/OPENAI_API_KEY + model_info: + supports_web_search: True +``` + +2. Run proxy server + +```bash +litellm --config config.yaml +``` + +3. Call `/model_group/info` to check if a model supports web search + +```shell +curl -X 'GET' \ + 'http://localhost:4000/model_group/info' \ + -H 'accept: application/json' \ + -H 'x-api-key: sk-1234' +``` + +Expected Response + +```json showLineNumbers +{ + "data": [ + { + "model_group": "gpt-4o-search-preview", + "providers": ["openai"], + "max_tokens": 128000, + "supports_web_search": true, # 👈 supports_web_search is true + } + ] +} +``` + + + diff --git a/docs/my-website/docs/data_security.md b/docs/my-website/docs/data_security.md index 13cde26d5d7..30128760f27 100644 --- a/docs/my-website/docs/data_security.md +++ b/docs/my-website/docs/data_security.md @@ -46,7 +46,7 @@ For security inquiries, please contact us at support@berri.ai |-------------------|-------------------------------------------------------------------------------------------------| | SOC 2 Type I | Certified. Report available upon request on Enterprise plan. | | SOC 2 Type II | In progress. Certificate available by April 15th, 2025 | -| ISO27001 | In progress. Certificate available by February 7th, 2025 | +| ISO 27001 | Certified. Report available upon request on Enterprise | ## Supported Data Regions for LiteLLM Cloud @@ -137,7 +137,7 @@ Point of contact email address for general security-related questions: krrish@be Has the Vendor been audited / certified? - SOC 2 Type I. Certified. Report available upon request on Enterprise plan. - SOC 2 Type II. In progress. Certificate available by April 15th, 2025. -- ISO27001. In progress. Certificate available by February 7th, 2025. +- ISO 27001. Certified. Report available upon request on Enterprise plan. Has an information security management system been implemented? - Yes - [CodeQL](https://codeql.github.com/) and a comprehensive ISMS covering multiple security domains. diff --git a/docs/my-website/docs/debugging/local_debugging.md b/docs/my-website/docs/debugging/local_debugging.md index a9409bfab03..8a56d6c34a0 100644 --- a/docs/my-website/docs/debugging/local_debugging.md +++ b/docs/my-website/docs/debugging/local_debugging.md @@ -1,5 +1,5 @@ # Local Debugging -There's 2 ways to do local debugging - `litellm.set_verbose=True` and by passing in a custom function `completion(...logger_fn=)`. Warning: Make sure to not use `set_verbose` in production. It logs API keys, which might end up in log files. +There's 2 ways to do local debugging - `litellm._turn_on_debug()` and by passing in a custom function `completion(...logger_fn=)`. Warning: Make sure to not use `_turn_on_debug()` in production. It logs API keys, which might end up in log files. ## Set Verbose @@ -8,7 +8,7 @@ This is good for getting print statements for everything litellm is doing. import litellm from litellm import completion -litellm.set_verbose=True # 👈 this is the 1-line change you need to make +litellm._turn_on_debug() # 👈 this is the 1-line change you need to make ## set ENV variables os.environ["OPENAI_API_KEY"] = "openai key" diff --git a/docs/my-website/docs/embedding/supported_embedding.md b/docs/my-website/docs/embedding/supported_embedding.md index d0cb59b46e1..6257ca2dba4 100644 --- a/docs/my-website/docs/embedding/supported_embedding.md +++ b/docs/my-website/docs/embedding/supported_embedding.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Embeddings +# /embeddings ## Quick Start ```python @@ -225,36 +225,6 @@ response = embedding( | text-embedding-3-large | `embedding('text-embedding-3-large', input)` | `os.environ['OPENAI_API_KEY']` | | text-embedding-ada-002 | `embedding('text-embedding-ada-002', input)` | `os.environ['OPENAI_API_KEY']` | -## Azure OpenAI Embedding Models - -### API keys -This can be set as env variables or passed as **params to litellm.embedding()** -```python -import os -os.environ['AZURE_API_KEY'] = -os.environ['AZURE_API_BASE'] = -os.environ['AZURE_API_VERSION'] = -``` - -### Usage -```python -from litellm import embedding -response = embedding( - model="azure/", - input=["good morning from litellm"], - api_key=api_key, - api_base=api_base, - api_version=api_version, -) -print(response) -``` - -| Model Name | Function Call | -|----------------------|---------------------------------------------| -| text-embedding-ada-002 | `embedding(model="azure/", input=input)` | - -h/t to [Mikko](https://www.linkedin.com/in/mikkolehtimaki/) for this integration - ## OpenAI Compatible Embedding Models Use this for calling `/embedding` endpoints on OpenAI Compatible Servers, example https://github.com/xorbitsai/inference diff --git a/docs/my-website/docs/enterprise.md b/docs/my-website/docs/enterprise.md index 0306a5b452d..706ca337144 100644 --- a/docs/my-website/docs/enterprise.md +++ b/docs/my-website/docs/enterprise.md @@ -1,3 +1,5 @@ +import Image from '@theme/IdealImage'; + # Enterprise For companies that need SSO, user management and professional support for LiteLLM Proxy @@ -7,6 +9,8 @@ Get free 7-day trial key [here](https://www.litellm.ai/#trial) Includes all enterprise features. + + [**Procurement available via AWS / Azure Marketplace**](./data_security.md#legalcompliance-faqs) @@ -34,9 +38,9 @@ You can use our cloud product where we setup a dedicated instance for you. Professional Support can assist with LLM/Provider integrations, deployment, upgrade management, and LLM Provider troubleshooting. We can’t solve your own infrastructure-related issues but we will guide you to fix them. -- 1 hour for Sev0 issues -- 6 hours for Sev1 -- 24h for Sev2-Sev3 between 7am – 7pm PT (Monday through Saturday) +- 1 hour for Sev0 issues - 100% production traffic is failing +- 6 hours for Sev1 - <100% production traffic is failing +- 24h for Sev2-Sev3 between 7am – 7pm PT (Monday through Saturday) - setup issues e.g. Redis working on our end, but not on your infrastructure. - 72h SLA for patching vulnerabilities in the software. **We can offer custom SLAs** based on your needs and the severity of the issue diff --git a/docs/my-website/docs/extras/contributing.md b/docs/my-website/docs/extras/contributing.md index f470515e3f5..64c068a4d3a 100644 --- a/docs/my-website/docs/extras/contributing.md +++ b/docs/my-website/docs/extras/contributing.md @@ -1,3 +1,6 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # Contributing to Documentation This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. @@ -9,31 +12,51 @@ git clone https://github.com/BerriAI/litellm.git ### Local setup for locally running docs -#### Installation -``` -npm install --global yarn -``` - - -### Local Development - ``` cd docs/my-website ``` -Let's Install requirement + + + + +Installation +``` +npm install --global yarn +``` +Install requirement ``` yarn ``` Run website - ``` yarn start ``` -Open docs here: [http://localhost:3000/](http://localhost:3000/) + + + + +Installation ``` +npm install --global pnpm +``` +Install requirement +``` +pnpm install +``` +Run website +``` +pnpm start +``` + + + + + + +Open docs here: [http://localhost:3000/](http://localhost:3000/) This command builds your Markdown files into HTML and starts a development server to browse your documentation. Open up [http://127.0.0.1:8000/](http://127.0.0.1:8000/) in your web browser to see your documentation. You can make changes to your Markdown files and your docs will automatically rebuild. @@ -42,8 +65,4 @@ This command builds your Markdown files into HTML and starts a development serve ### Making changes to Docs - All the docs are placed under the `docs` directory - If you are adding a new `.md` file or editing the hierarchy edit `mkdocs.yml` in the root of the project -- After testing your changes, make a change to the `main` branch of [github.com/BerriAI/litellm](https://github.com/BerriAI/litellm) - - - - +- After testing your changes, make a change/pull request to the `main` branch of [github.com/BerriAI/litellm](https://github.com/BerriAI/litellm) diff --git a/docs/my-website/docs/extras/contributing_code.md b/docs/my-website/docs/extras/contributing_code.md new file mode 100644 index 00000000000..747df5b60fc --- /dev/null +++ b/docs/my-website/docs/extras/contributing_code.md @@ -0,0 +1,109 @@ +# Contributing Code + +## **Checklist before submitting a PR** + +Here are the core requirements for any PR submitted to LiteLLM + +- [ ] Sign the Contributor License Agreement (CLA) - [see details](#contributor-license-agreement-cla) +- [ ] Add testing, **Adding at least 1 test is a hard requirement** - [see details](#2-adding-testing-to-your-pr) +- [ ] Ensure your PR passes the following tests: + - [ ] [Unit Tests](#3-running-unit-tests) + - [ ] [Formatting / Linting Tests](#35-running-linting-tests) +- [ ] Keep scope as isolated as possible. As a general rule, your changes should address 1 specific problem at a time + +## **Contributor License Agreement (CLA)** + +Before contributing code to LiteLLM, you must sign our [Contributor License Agreement (CLA)](<(https://cla-assistant.io/BerriAI/litellm)>). This is a legal requirement for all contributions to be merged into the main repository. The CLA helps protect both you and the project by clearly defining the terms under which your contributions are made. + +**Important:** We strongly recommend reviewing and signing the CLA before starting work on your contribution to avoid any delays in the PR process. You can find the CLA [here](https://cla-assistant.io/BerriAI/litellm) and sign it through our CLA management system when you submit your first PR. + +## Quick start + +## 1. Setup your local dev environment + +Here's how to modify the repo locally: + +Step 1: Clone the repo + +```shell +git clone https://github.com/BerriAI/litellm.git +``` + +Step 2: Install dev dependencies: + +```shell +poetry install --with dev --extras proxy +``` + +That's it, your local dev environment is ready! + +## 2. Adding Testing to your PR + +- Add your test to the [`tests/litellm/` directory](https://github.com/BerriAI/litellm/tree/main/tests/litellm) + +- This directory 1:1 maps the the `litellm/` directory, and can only contain mocked tests. +- Do not add real llm api calls to this directory. + +### 2.1 File Naming Convention for `tests/litellm/` + +The `tests/litellm/` directory follows the same directory structure as `litellm/`. + +- `litellm/proxy/test_caching_routes.py` maps to `litellm/proxy/caching_routes.py` +- `test_{filename}.py` maps to `litellm/{filename}.py` + +## 3. Running Unit Tests + +run the following command on the root of the litellm directory + +```shell +make test-unit +``` + +## 3.5 Running Linting Tests + +run the following command on the root of the litellm directory + +```shell +make lint +``` + +LiteLLM uses mypy for linting. On ci/cd we also run `black` for formatting. + +## 4. Submit a PR with your changes! + +- push your fork to your GitHub repo +- submit a PR from there + +## Advanced + +### Building LiteLLM Docker Image + +Some people might want to build the LiteLLM docker image themselves. Follow these instructions if you want to build / run the LiteLLM Docker Image yourself. + +Step 1: Clone the repo + +```shell +git clone https://github.com/BerriAI/litellm.git +``` + +Step 2: Build the Docker Image + +Build using Dockerfile.non_root + +```shell +docker build -f docker/Dockerfile.non_root -t litellm_test_image . +``` + +Step 3: Run the Docker Image + +Make sure config.yaml is present in the root directory. This is your litellm proxy config file. + +```shell +docker run \ + -v $(pwd)/proxy_config.yaml:/app/config.yaml \ + -e DATABASE_URL="postgresql://xxxxxxxx" \ + -e LITELLM_MASTER_KEY="sk-1234" \ + -p 4000:4000 \ + litellm_test_image \ + --config /app/config.yaml --detailed_debug +``` diff --git a/docs/my-website/docs/files_endpoints.md b/docs/my-website/docs/files_endpoints.md index cccb35daa98..31a02d41a3f 100644 --- a/docs/my-website/docs/files_endpoints.md +++ b/docs/my-website/docs/files_endpoints.md @@ -2,10 +2,12 @@ import TabItem from '@theme/TabItem'; import Tabs from '@theme/Tabs'; -# Files API +# Provider Files Endpoints Files are used to upload documents that can be used with features like Assistants, Fine-tuning, and Batch API. +Use this to call the provider's `/files` endpoints directly, in the OpenAI format. + ## Quick Start - Upload a File @@ -14,48 +16,105 @@ Files are used to upload documents that can be used with features like Assistant - Delete File - Get File Content + + -```bash -$ export OPENAI_API_KEY="sk-..." +1. Setup config.yaml -$ litellm - -# RUNNING on http://0.0.0.0:4000 +``` +# for /files endpoints +files_settings: + - custom_llm_provider: azure + api_base: https://exampleopenaiendpoint-production.up.railway.app + api_key: fake-key + api_version: "2023-03-15-preview" + - custom_llm_provider: openai + api_key: os.environ/OPENAI_API_KEY ``` -**Upload a File** +2. Start LiteLLM PROXY Server + ```bash -curl http://localhost:4000/v1/files \ - -H "Authorization: Bearer sk-1234" \ - -F purpose="fine-tune" \ - -F file="@mydata.jsonl" +litellm --config /path/to/config.yaml + +## RUNNING on http://0.0.0.0:4000 ``` -**List Files** -```bash -curl http://localhost:4000/v1/files \ - -H "Authorization: Bearer sk-1234" +3. Use OpenAI's /files endpoints + +Upload a File + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-...", + base_url="http://0.0.0.0:4000/v1" +) + +client.files.create( + file=wav_data, + purpose="user_data", + extra_body={"custom_llm_provider": "openai"} +) ``` -**Retrieve File Information** -```bash -curl http://localhost:4000/v1/files/file-abc123 \ - -H "Authorization: Bearer sk-1234" +List Files + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-...", + base_url="http://0.0.0.0:4000/v1" +) + +files = client.files.list(extra_body={"custom_llm_provider": "openai"}) +print("files=", files) ``` -**Delete File** -```bash -curl http://localhost:4000/v1/files/file-abc123 \ - -X DELETE \ - -H "Authorization: Bearer sk-1234" +Retrieve File Information + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-...", + base_url="http://0.0.0.0:4000/v1" +) + +file = client.files.retrieve(file_id="file-abc123", extra_body={"custom_llm_provider": "openai"}) +print("file=", file) ``` -**Get File Content** -```bash -curl http://localhost:4000/v1/files/file-abc123/content \ - -H "Authorization: Bearer sk-1234" +Delete File + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-...", + base_url="http://0.0.0.0:4000/v1" +) + +response = client.files.delete(file_id="file-abc123", extra_body={"custom_llm_provider": "openai"}) +print("delete response=", response) +``` + +Get File Content + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-...", + base_url="http://0.0.0.0:4000/v1" +) + +content = client.files.content(file_id="file-abc123", extra_body={"custom_llm_provider": "openai"}) +print("content=", content) ``` @@ -120,7 +179,7 @@ print("file content=", content) ### [OpenAI](#quick-start) -## [Azure OpenAI](./providers/azure#azure-batches-api) +### [Azure OpenAI](./providers/azure#azure-batches-api) ### [Vertex AI](./providers/vertex#batch-apis) diff --git a/docs/my-website/docs/fine_tuning.md b/docs/my-website/docs/fine_tuning.md index fd5d99a6a12..f9a9297e062 100644 --- a/docs/my-website/docs/fine_tuning.md +++ b/docs/my-website/docs/fine_tuning.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# [Beta] Fine-tuning API +# /fine_tuning :::info diff --git a/docs/my-website/docs/guides/security_settings.md b/docs/my-website/docs/guides/security_settings.md new file mode 100644 index 00000000000..4dfeda2d70b --- /dev/null +++ b/docs/my-website/docs/guides/security_settings.md @@ -0,0 +1,66 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# SSL Security Settings + +If you're in an environment using an older TTS bundle, with an older encryption, follow this guide. + + +LiteLLM uses HTTPX for network requests, unless otherwise specified. + +1. Disable SSL verification + + + + + +```python +import litellm +litellm.ssl_verify = False +``` + + + +```yaml +litellm_settings: + ssl_verify: false +``` + + + + +```bash +export SSL_VERIFY="False" +``` + + + +2. Lower security settings + + + + +```python +import litellm +litellm.ssl_security_level = 1 +litellm.ssl_certificate = "/path/to/certificate.pem" +``` + + + +```yaml +litellm_settings: + ssl_security_level: 1 + ssl_certificate: "/path/to/certificate.pem" +``` + + + +```bash +export SSL_SECURITY_LEVEL="1" +export SSL_CERTIFICATE="/path/to/certificate.pem" +``` + + + + diff --git a/docs/my-website/docs/image_generation.md b/docs/my-website/docs/image_generation.md index 958ff4c0206..5af3e10e0ca 100644 --- a/docs/my-website/docs/image_generation.md +++ b/docs/my-website/docs/image_generation.md @@ -1,8 +1,15 @@ -# Images + +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Image Generations ## Quick Start -```python +### LiteLLM Python SDK + +```python showLineNumbers from litellm import image_generation import os @@ -14,24 +21,23 @@ response = image_generation(prompt="A cute baby sea otter", model="dall-e-3") print(f"response: {response}") ``` -## Proxy Usage +### LiteLLM Proxy ### Setup config.yaml -```yaml +```yaml showLineNumbers model_list: - - model_name: dall-e-2 ### RECEIVED MODEL NAME ### + - model_name: gpt-image-1 ### RECEIVED MODEL NAME ### litellm_params: # all params accepted by litellm.image_generation() - model: azure/dall-e-2 ### MODEL NAME sent to `litellm.image_generation()` ### + model: azure/gpt-image-1 ### MODEL NAME sent to `litellm.image_generation()` ### api_base: https://my-endpoint-europe-berri-992.openai.azure.com/ api_key: "os.environ/AZURE_API_KEY_EU" # does os.getenv("AZURE_API_KEY_EU") - rpm: 6 # [OPTIONAL] Rate limit for this deployment: in requests per minute (rpm) ``` ### Start proxy -```bash +```bash showLineNumbers litellm --config /path/to/config.yaml # RUNNING on http://0.0.0.0:4000 @@ -47,7 +53,7 @@ curl -X POST 'http://0.0.0.0:4000/v1/images/generations' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ -D '{ - "model": "dall-e-2", + "model": "gpt-image-1", "prompt": "A cute baby sea otter", "n": 1, "size": "1024x1024" @@ -57,7 +63,7 @@ curl -X POST 'http://0.0.0.0:4000/v1/images/generations' \ -```python +```python showLineNumbers from openai import OpenAI client = openai.OpenAI( api_key="sk-1234", @@ -104,15 +110,19 @@ Any non-openai params, will be treated as provider-specific params, and sent in litellm_logging_obj=None, custom_llm_provider=None, -- `model`: *string (optional)* The model to use for image generation. Defaults to openai/dall-e-2 +- `model`: *string (optional)* The model to use for image generation. Defaults to openai/gpt-image-1 - `n`: *int (optional)* The number of images to generate. Must be between 1 and 10. For dall-e-3, only n=1 is supported. -- `quality`: *string (optional)* The quality of the image that will be generated. hd creates images with finer details and greater consistency across the image. This param is only supported for dall-e-3. - +- `quality`: *string (optional)* The quality of the image that will be generated. + * `auto` (default value) will automatically select the best quality for the given model. + * `high`, `medium` and `low` are supported for `gpt-image-1`. + * `hd` and `standard` are supported for `dall-e-3`. + * `standard` is the only option for `dall-e-2`. + - `response_format`: *string (optional)* The format in which the generated images are returned. Must be one of url or b64_json. -- `size`: *string (optional)* The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024 for dall-e-2. Must be one of 1024x1024, 1792x1024, or 1024x1792 for dall-e-3 models. +- `size`: *string (optional)* The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for `gpt-image-1`, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. - `timeout`: *integer* - The maximum time, in seconds, to wait for the API to respond. Defaults to 600 seconds (10 minutes). @@ -148,13 +158,14 @@ Any non-openai params, will be treated as provider-specific params, and sent in from litellm import image_generation import os os.environ['OPENAI_API_KEY'] = "" -response = image_generation(model='dall-e-2', prompt="cute baby otter") +response = image_generation(model='gpt-image-1', prompt="cute baby otter") ``` | Model Name | Function Call | Required OS Variables | |----------------------|---------------------------------------------|--------------------------------------| -| dall-e-2 | `image_generation(model='dall-e-2', prompt="cute baby otter")` | `os.environ['OPENAI_API_KEY']` | +| gpt-image-1 | `image_generation(model='gpt-image-1', prompt="cute baby otter")` | `os.environ['OPENAI_API_KEY']` | | dall-e-3 | `image_generation(model='dall-e-3', prompt="cute baby otter")` | `os.environ['OPENAI_API_KEY']` | +| dall-e-2 | `image_generation(model='dall-e-2', prompt="cute baby otter")` | `os.environ['OPENAI_API_KEY']` | ## Azure OpenAI Image Generation Models @@ -182,8 +193,9 @@ print(response) | Model Name | Function Call | |----------------------|---------------------------------------------| -| dall-e-2 | `image_generation(model="azure/", prompt="cute baby otter")` | +| gpt-image-1 | `image_generation(model="azure/", prompt="cute baby otter")` | | dall-e-3 | `image_generation(model="azure/", prompt="cute baby otter")` | +| dall-e-2 | `image_generation(model="azure/", prompt="cute baby otter")` | ## OpenAI Compatible Image Generation Models diff --git a/docs/my-website/docs/index.md b/docs/my-website/docs/index.md index dd845576c70..58cabc81b48 100644 --- a/docs/my-website/docs/index.md +++ b/docs/my-website/docs/index.md @@ -89,7 +89,21 @@ response = completion( ``` + +```python +from litellm import completion +import os + +## set ENV variables +os.environ["XAI_API_KEY"] = "your-api-key" + +response = completion( + model="xai/grok-2-latest", + messages=[{ "content": "Hello, how are you?","role": "user"}] +) +``` + ```python @@ -97,8 +111,8 @@ from litellm import completion import os # auth: run 'gcloud auth application-default' -os.environ["VERTEX_PROJECT"] = "hardy-device-386718" -os.environ["VERTEX_LOCATION"] = "us-central1" +os.environ["VERTEXAI_PROJECT"] = "hardy-device-386718" +os.environ["VERTEXAI_LOCATION"] = "us-central1" response = completion( model="vertex_ai/gemini-1.5-pro", @@ -194,6 +208,22 @@ response = completion( ) ``` + + + +```python +from litellm import completion +import os + +## set ENV variables. Visit https://novita.ai/settings/key-management to get your API key +os.environ["NOVITA_API_KEY"] = "novita-api-key" + +response = completion( + model="novita/deepseek/deepseek-r1", + messages=[{ "content": "Hello, how are you?","role": "user"}] +) +``` + @@ -272,7 +302,22 @@ response = completion( ``` + +```python +from litellm import completion +import os + +## set ENV variables +os.environ["XAI_API_KEY"] = "your-api-key" + +response = completion( + model="xai/grok-2-latest", + messages=[{ "content": "Hello, how are you?","role": "user"}], + stream=True, +) +``` + ```python @@ -382,6 +427,23 @@ response = completion( ) ``` + + + +```python +from litellm import completion +import os + +## set ENV variables. Visit https://novita.ai/settings/key-management to get your API key +os.environ["NOVITA_API_KEY"] = "novita_api_key" + +response = completion( + model="novita/deepseek/deepseek-r1", + messages = [{ "content": "Hello, how are you?","role": "user"}], + stream=True, +) +``` + diff --git a/docs/my-website/docs/mcp.md b/docs/my-website/docs/mcp.md new file mode 100644 index 00000000000..f04324f965f --- /dev/null +++ b/docs/my-website/docs/mcp.md @@ -0,0 +1,429 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; + +# /mcp [BETA] - Model Context Protocol + +## Expose MCP tools on LiteLLM Proxy Server + +This allows you to define tools that can be called by any MCP compatible client. Define your `mcp_servers` with LiteLLM and all your clients can list and call available tools. + + +

+ LiteLLM MCP Architecture: Use MCP tools with all LiteLLM supported models +

+ +#### How it works + +LiteLLM exposes the following MCP endpoints: + +- `/mcp/tools/list` - List all available tools +- `/mcp/tools/call` - Call a specific tool with the provided arguments + +When MCP clients connect to LiteLLM they can follow this workflow: + +1. Connect to the LiteLLM MCP server +2. List all available tools on LiteLLM +3. Client makes LLM API request with tool call(s) +4. LLM API returns which tools to call and with what arguments +5. MCP client makes MCP tool calls to LiteLLM +6. LiteLLM makes the tool calls to the appropriate MCP server +7. LiteLLM returns the tool call results to the MCP client + +#### Usage + +#### 1. Define your tools on under `mcp_servers` in your config.yaml file. + +LiteLLM allows you to define your tools on the `mcp_servers` section in your config.yaml file. All tools listed here will be available to MCP clients (when they connect to LiteLLM and call `list_tools`). + +```yaml title="config.yaml" showLineNumbers +model_list: + - model_name: gpt-4o + litellm_params: + model: openai/gpt-4o + api_key: sk-xxxxxxx + +mcp_servers: + zapier_mcp: + url: "https://actions.zapier.com/mcp/sk-akxxxxx/sse" + fetch: + url: "http://localhost:8000/sse" +``` + + +#### 2. Start LiteLLM Gateway + + + + +```shell title="Docker Run" showLineNumbers +docker run -d \ + -p 4000:4000 \ + -e OPENAI_API_KEY=$OPENAI_API_KEY \ + --name my-app \ + -v $(pwd)/my_config.yaml:/app/config.yaml \ + my-app:latest \ + --config /app/config.yaml \ + --port 4000 \ + --detailed_debug \ +``` + + + + + +```shell title="litellm pip" showLineNumbers +litellm --config config.yaml --detailed_debug +``` + + + + + +#### 3. Make an LLM API request + +In this example we will do the following: + +1. Use MCP client to list MCP tools on LiteLLM Proxy +2. Use `transform_mcp_tool_to_openai_tool` to convert MCP tools to OpenAI tools +3. Provide the MCP tools to `gpt-4o` +4. Handle tool call from `gpt-4o` +5. Convert OpenAI tool call to MCP tool call +6. Execute tool call on MCP server + +```python title="MCP Client List Tools" showLineNumbers +import asyncio +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletionUserMessageParam +from mcp import ClientSession +from mcp.client.sse import sse_client +from litellm.experimental_mcp_client.tools import ( + transform_mcp_tool_to_openai_tool, + transform_openai_tool_call_request_to_mcp_tool_call_request, +) + + +async def main(): + # Initialize clients + + # point OpenAI client to LiteLLM Proxy + client = AsyncOpenAI(api_key="sk-1234", base_url="http://localhost:4000") + + # Point MCP client to LiteLLM Proxy + async with sse_client("http://localhost:4000/mcp/") as (read, write): + async with ClientSession(read, write) as session: + await session.initialize() + + # 1. List MCP tools on LiteLLM Proxy + mcp_tools = await session.list_tools() + print("List of MCP tools for MCP server:", mcp_tools.tools) + + # Create message + messages = [ + ChatCompletionUserMessageParam( + content="Send an email about LiteLLM supporting MCP", role="user" + ) + ] + + # 2. Use `transform_mcp_tool_to_openai_tool` to convert MCP tools to OpenAI tools + # Since OpenAI only supports tools in the OpenAI format, we need to convert the MCP tools to the OpenAI format. + openai_tools = [ + transform_mcp_tool_to_openai_tool(tool) for tool in mcp_tools.tools + ] + + # 3. Provide the MCP tools to `gpt-4o` + response = await client.chat.completions.create( + model="gpt-4o", + messages=messages, + tools=openai_tools, + tool_choice="auto", + ) + + # 4. Handle tool call from `gpt-4o` + if response.choices[0].message.tool_calls: + tool_call = response.choices[0].message.tool_calls[0] + if tool_call: + + # 5. Convert OpenAI tool call to MCP tool call + # Since MCP servers expect tools in the MCP format, we need to convert the OpenAI tool call to the MCP format. + # This is done using litellm.experimental_mcp_client.tools.transform_openai_tool_call_request_to_mcp_tool_call_request + mcp_call = ( + transform_openai_tool_call_request_to_mcp_tool_call_request( + openai_tool=tool_call.model_dump() + ) + ) + + # 6. Execute tool call on MCP server + result = await session.call_tool( + name=mcp_call.name, arguments=mcp_call.arguments + ) + + print("Result:", result) + + +# Run it +asyncio.run(main()) +``` + +## LiteLLM Python SDK MCP Bridge + +LiteLLM Python SDK acts as a MCP bridge to utilize MCP tools with all LiteLLM supported models. LiteLLM offers the following features for using MCP + +- **List** Available MCP Tools: OpenAI clients can view all available MCP tools + - `litellm.experimental_mcp_client.load_mcp_tools` to list all available MCP tools +- **Call** MCP Tools: OpenAI clients can call MCP tools + - `litellm.experimental_mcp_client.call_openai_tool` to call an OpenAI tool on an MCP server + + +### 1. List Available MCP Tools + +In this example we'll use `litellm.experimental_mcp_client.load_mcp_tools` to list all available MCP tools on any MCP server. This method can be used in two ways: + +- `format="mcp"` - (default) Return MCP tools + - Returns: `mcp.types.Tool` +- `format="openai"` - Return MCP tools converted to OpenAI API compatible tools. Allows using with OpenAI endpoints. + - Returns: `openai.types.chat.ChatCompletionToolParam` + + + + +```python title="MCP Client List Tools" showLineNumbers +# Create server parameters for stdio connection +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client +import os +import litellm +from litellm import experimental_mcp_client + + +server_params = StdioServerParameters( + command="python3", + # Make sure to update to the full absolute path to your mcp_server.py file + args=["./mcp_server.py"], +) + +async with stdio_client(server_params) as (read, write): + async with ClientSession(read, write) as session: + # Initialize the connection + await session.initialize() + + # Get tools + tools = await experimental_mcp_client.load_mcp_tools(session=session, format="openai") + print("MCP TOOLS: ", tools) + + messages = [{"role": "user", "content": "what's (3 + 5)"}] + llm_response = await litellm.acompletion( + model="gpt-4o", + api_key=os.getenv("OPENAI_API_KEY"), + messages=messages, + tools=tools, + ) + print("LLM RESPONSE: ", json.dumps(llm_response, indent=4, default=str)) +``` + + + + + +In this example we'll walk through how you can use the OpenAI SDK pointed to the LiteLLM proxy to call MCP tools. The key difference here is we use the OpenAI SDK to make the LLM API request + +```python title="MCP Client List Tools" showLineNumbers +# Create server parameters for stdio connection +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client +import os +from openai import OpenAI +from litellm import experimental_mcp_client + +server_params = StdioServerParameters( + command="python3", + # Make sure to update to the full absolute path to your mcp_server.py file + args=["./mcp_server.py"], +) + +async with stdio_client(server_params) as (read, write): + async with ClientSession(read, write) as session: + # Initialize the connection + await session.initialize() + + # Get tools using litellm mcp client + tools = await experimental_mcp_client.load_mcp_tools(session=session, format="openai") + print("MCP TOOLS: ", tools) + + # Use OpenAI SDK pointed to LiteLLM proxy + client = OpenAI( + api_key="your-api-key", # Your LiteLLM proxy API key + base_url="http://localhost:4000" # Your LiteLLM proxy URL + ) + + messages = [{"role": "user", "content": "what's (3 + 5)"}] + llm_response = client.chat.completions.create( + model="gpt-4", + messages=messages, + tools=tools + ) + print("LLM RESPONSE: ", llm_response) +``` + + + + +### 2. List and Call MCP Tools + +In this example we'll use +- `litellm.experimental_mcp_client.load_mcp_tools` to list all available MCP tools on any MCP server +- `litellm.experimental_mcp_client.call_openai_tool` to call an OpenAI tool on an MCP server + +The first llm response returns a list of OpenAI tools. We take the first tool call from the LLM response and pass it to `litellm.experimental_mcp_client.call_openai_tool` to call the tool on the MCP server. + +#### How `litellm.experimental_mcp_client.call_openai_tool` works + +- Accepts an OpenAI Tool Call from the LLM response +- Converts the OpenAI Tool Call to an MCP Tool +- Calls the MCP Tool on the MCP server +- Returns the result of the MCP Tool call + + + + +```python title="MCP Client List and Call Tools" showLineNumbers +# Create server parameters for stdio connection +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client +import os +import litellm +from litellm import experimental_mcp_client + + +server_params = StdioServerParameters( + command="python3", + # Make sure to update to the full absolute path to your mcp_server.py file + args=["./mcp_server.py"], +) + +async with stdio_client(server_params) as (read, write): + async with ClientSession(read, write) as session: + # Initialize the connection + await session.initialize() + + # Get tools + tools = await experimental_mcp_client.load_mcp_tools(session=session, format="openai") + print("MCP TOOLS: ", tools) + + messages = [{"role": "user", "content": "what's (3 + 5)"}] + llm_response = await litellm.acompletion( + model="gpt-4o", + api_key=os.getenv("OPENAI_API_KEY"), + messages=messages, + tools=tools, + ) + print("LLM RESPONSE: ", json.dumps(llm_response, indent=4, default=str)) + + openai_tool = llm_response["choices"][0]["message"]["tool_calls"][0] + # Call the tool using MCP client + call_result = await experimental_mcp_client.call_openai_tool( + session=session, + openai_tool=openai_tool, + ) + print("MCP TOOL CALL RESULT: ", call_result) + + # send the tool result to the LLM + messages.append(llm_response["choices"][0]["message"]) + messages.append( + { + "role": "tool", + "content": str(call_result.content[0].text), + "tool_call_id": openai_tool["id"], + } + ) + print("final messages with tool result: ", messages) + llm_response = await litellm.acompletion( + model="gpt-4o", + api_key=os.getenv("OPENAI_API_KEY"), + messages=messages, + tools=tools, + ) + print( + "FINAL LLM RESPONSE: ", json.dumps(llm_response, indent=4, default=str) + ) +``` + + + + +In this example we'll walk through how you can use the OpenAI SDK pointed to the LiteLLM proxy to call MCP tools. The key difference here is we use the OpenAI SDK to make the LLM API request + +```python title="MCP Client with OpenAI SDK" showLineNumbers +# Create server parameters for stdio connection +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client +import os +from openai import OpenAI +from litellm import experimental_mcp_client + +server_params = StdioServerParameters( + command="python3", + # Make sure to update to the full absolute path to your mcp_server.py file + args=["./mcp_server.py"], +) + +async with stdio_client(server_params) as (read, write): + async with ClientSession(read, write) as session: + # Initialize the connection + await session.initialize() + + # Get tools using litellm mcp client + tools = await experimental_mcp_client.load_mcp_tools(session=session, format="openai") + print("MCP TOOLS: ", tools) + + # Use OpenAI SDK pointed to LiteLLM proxy + client = OpenAI( + api_key="your-api-key", # Your LiteLLM proxy API key + base_url="http://localhost:8000" # Your LiteLLM proxy URL + ) + + messages = [{"role": "user", "content": "what's (3 + 5)"}] + llm_response = client.chat.completions.create( + model="gpt-4", + messages=messages, + tools=tools + ) + print("LLM RESPONSE: ", llm_response) + + # Get the first tool call + tool_call = llm_response.choices[0].message.tool_calls[0] + + # Call the tool using MCP client + call_result = await experimental_mcp_client.call_openai_tool( + session=session, + openai_tool=tool_call.model_dump(), + ) + print("MCP TOOL CALL RESULT: ", call_result) + + # Send the tool result back to the LLM + messages.append(llm_response.choices[0].message.model_dump()) + messages.append({ + "role": "tool", + "content": str(call_result.content[0].text), + "tool_call_id": tool_call.id, + }) + + final_response = client.chat.completions.create( + model="gpt-4", + messages=messages, + tools=tools + ) + print("FINAL RESPONSE: ", final_response) +``` + + + + +### Permission Management + +Currently, all Virtual Keys are able to access the MCP endpoints. We are working on a feature to allow restricting MCP access by keys/teams/users/orgs. + +Join the discussion [here](https://github.com/BerriAI/litellm/discussions/9891) \ No newline at end of file diff --git a/docs/my-website/docs/moderation.md b/docs/my-website/docs/moderation.md index 6dd092fb52a..95fe8b2856d 100644 --- a/docs/my-website/docs/moderation.md +++ b/docs/my-website/docs/moderation.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Moderation +# /moderations ### Usage diff --git a/docs/my-website/docs/observability/agentops_integration.md b/docs/my-website/docs/observability/agentops_integration.md new file mode 100644 index 00000000000..e0599fab701 --- /dev/null +++ b/docs/my-website/docs/observability/agentops_integration.md @@ -0,0 +1,83 @@ +# 🖇️ AgentOps - LLM Observability Platform + +:::tip + +This is community maintained. Please make an issue if you run into a bug: +https://github.com/BerriAI/litellm + +::: + +[AgentOps](https://docs.agentops.ai) is an observability platform that enables tracing and monitoring of LLM calls, providing detailed insights into your AI operations. + +## Using AgentOps with LiteLLM + +LiteLLM provides `success_callbacks` and `failure_callbacks`, allowing you to easily integrate AgentOps for comprehensive tracing and monitoring of your LLM operations. + +### Integration + +Use just a few lines of code to instantly trace your responses **across all providers** with AgentOps: +Get your AgentOps API Keys from https://app.agentops.ai/ +```python +import litellm + +# Configure LiteLLM to use AgentOps +litellm.success_callback = ["agentops"] + +# Make your LLM calls as usual +response = litellm.completion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello, how are you?"}], +) +``` + +Complete Code: + +```python +import os +from litellm import completion + +# Set env variables +os.environ["OPENAI_API_KEY"] = "your-openai-key" +os.environ["AGENTOPS_API_KEY"] = "your-agentops-api-key" + +# Configure LiteLLM to use AgentOps +litellm.success_callback = ["agentops"] + +# OpenAI call +response = completion( + model="gpt-4", + messages=[{"role": "user", "content": "Hi 👋 - I'm OpenAI"}], +) + +print(response) +``` + +### Configuration Options + +The AgentOps integration can be configured through environment variables: + +- `AGENTOPS_API_KEY` (str, optional): Your AgentOps API key +- `AGENTOPS_ENVIRONMENT` (str, optional): Deployment environment (defaults to "production") +- `AGENTOPS_SERVICE_NAME` (str, optional): Service name for tracing (defaults to "agentops") + +### Advanced Usage + +You can configure additional settings through environment variables: + +```python +import os + +# Configure AgentOps settings +os.environ["AGENTOPS_API_KEY"] = "your-agentops-api-key" +os.environ["AGENTOPS_ENVIRONMENT"] = "staging" +os.environ["AGENTOPS_SERVICE_NAME"] = "my-service" + +# Enable AgentOps tracing +litellm.success_callback = ["agentops"] +``` + +### Support + +For issues or questions, please refer to: +- [AgentOps Documentation](https://docs.agentops.ai) +- [LiteLLM Documentation](https://docs.litellm.ai) \ No newline at end of file diff --git a/docs/my-website/docs/observability/arize_integration.md b/docs/my-website/docs/observability/arize_integration.md index a69d32e5b3d..a654a1b4de3 100644 --- a/docs/my-website/docs/observability/arize_integration.md +++ b/docs/my-website/docs/observability/arize_integration.md @@ -1,4 +1,7 @@ + import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; # Arize AI @@ -11,6 +14,8 @@ https://github.com/BerriAI/litellm ::: + + ## Pre-Requisites @@ -19,16 +24,19 @@ Make an account on [Arize AI](https://app.arize.com/auth/login) ## Quick Start Use just 2 lines of code, to instantly log your responses **across all providers** with arize +You can also use the instrumentor option instead of the callback, which you can find [here](https://docs.arize.com/arize/llm-tracing/tracing-integrations-auto/litellm). ```python litellm.callbacks = ["arize"] ``` + ```python + import litellm import os os.environ["ARIZE_SPACE_KEY"] = "" -os.environ["ARIZE_API_KEY"] = "" # defaults to litellm-completion +os.environ["ARIZE_API_KEY"] = "" # LLM API Keys os.environ['OPENAI_API_KEY']="" @@ -47,7 +55,7 @@ response = litellm.completion( ### Using with LiteLLM Proxy - +1. Setup config.yaml ```yaml model_list: - model_name: gpt-4 @@ -59,13 +67,134 @@ model_list: litellm_settings: callbacks: ["arize"] +general_settings: + master_key: "sk-1234" # can also be set as an environment variable + environment_variables: ARIZE_SPACE_KEY: "d0*****" ARIZE_API_KEY: "141a****" ARIZE_ENDPOINT: "https://otlp.arize.com/v1" # OPTIONAL - your custom arize GRPC api endpoint - ARIZE_HTTP_ENDPOINT: "https://otlp.arize.com/v1" # OPTIONAL - your custom arize HTTP api endpoint. Set either this or ARIZE_ENDPOINT + ARIZE_HTTP_ENDPOINT: "https://otlp.arize.com/v1" # OPTIONAL - your custom arize HTTP api endpoint. Set either this or ARIZE_ENDPOINT or Neither (defaults to https://otlp.arize.com/v1 on grpc) ``` +2. Start the proxy + +```bash +litellm --config config.yaml +``` + +3. Test it! + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ "model": "gpt-4", "messages": [{"role": "user", "content": "Hi 👋 - i'm openai"}]}' +``` + +## Pass Arize Space/Key per-request + +Supported parameters: +- `arize_api_key` +- `arize_space_key` + + + + +```python +import litellm +import os + +# LLM API Keys +os.environ['OPENAI_API_KEY']="" + +# set arize as a callback, litellm will send the data to arize +litellm.callbacks = ["arize"] + +# openai call +response = litellm.completion( + model="gpt-3.5-turbo", + messages=[ + {"role": "user", "content": "Hi 👋 - i'm openai"} + ], + arize_api_key=os.getenv("ARIZE_SPACE_2_API_KEY"), + arize_space_key=os.getenv("ARIZE_SPACE_2_KEY"), +) +``` + + + + +1. Setup config.yaml +```yaml +model_list: + - model_name: gpt-4 + litellm_params: + model: openai/fake + api_key: fake-key + api_base: https://exampleopenaiendpoint-production.up.railway.app/ + +litellm_settings: + callbacks: ["arize"] + +general_settings: + master_key: "sk-1234" # can also be set as an environment variable +``` + +2. Start the proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + + + + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "Hi 👋 - i'm openai"}], + "arize_api_key": "ARIZE_SPACE_2_API_KEY", + "arize_space_key": "ARIZE_SPACE_2_KEY" +}' +``` + + + +```python +import openai +client = openai.OpenAI( + api_key="anything", + base_url="http://0.0.0.0:4000" +) + +# request sent to model set on litellm proxy, `litellm --model` +response = client.chat.completions.create( + model="gpt-3.5-turbo", + messages = [ + { + "role": "user", + "content": "this is a test request, write a short poem" + } + ], + extra_body={ + "arize_api_key": "ARIZE_SPACE_2_API_KEY", + "arize_space_key": "ARIZE_SPACE_2_KEY" + } +) + +print(response) +``` + + + + + ## Support & Talk to Founders - [Schedule Demo 👋](https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version) diff --git a/docs/my-website/docs/observability/athina_integration.md b/docs/my-website/docs/observability/athina_integration.md index f7c99a4a9c6..ba93ea4c980 100644 --- a/docs/my-website/docs/observability/athina_integration.md +++ b/docs/my-website/docs/observability/athina_integration.md @@ -78,7 +78,10 @@ Following are the allowed fields in metadata, their types, and their description * `context: Optional[Union[dict, str]]` - This is the context used as information for the prompt. For RAG applications, this is the "retrieved" data. You may log context as a string or as an object (dictionary). * `expected_response: Optional[str]` - This is the reference response to compare against for evaluation purposes. This is useful for segmenting inference calls by expected response. * `user_query: Optional[str]` - This is the user's query. For conversational applications, this is the user's last message. - +* `tags: Optional[list]` - This is a list of tags. This is useful for segmenting inference calls by tags. +* `user_feedback: Optional[str]` - The end user’s feedback. +* `model_options: Optional[dict]` - This is a dictionary of model options. This is useful for getting insights into how model behavior affects your end users. +* `custom_attributes: Optional[dict]` - This is a dictionary of custom attributes. This is useful for additional information about the inference. ## Using a self hosted deployment of Athina diff --git a/docs/my-website/docs/observability/greenscale_integration.md b/docs/my-website/docs/observability/greenscale_integration.md index 49eadc6453d..c9b00cd0e86 100644 --- a/docs/my-website/docs/observability/greenscale_integration.md +++ b/docs/my-website/docs/observability/greenscale_integration.md @@ -53,7 +53,7 @@ response = completion( ## Additional information in metadata -You can send any additional information to Greenscale by using the `metadata` field in completion and `greenscale_` prefix. This can be useful for sending metadata about the request, such as the project and application name, customer_id, enviornment, or any other information you want to track usage. `greenscale_project` and `greenscale_application` are required fields. +You can send any additional information to Greenscale by using the `metadata` field in completion and `greenscale_` prefix. This can be useful for sending metadata about the request, such as the project and application name, customer_id, environment, or any other information you want to track usage. `greenscale_project` and `greenscale_application` are required fields. ```python #openai call with additional metadata diff --git a/docs/my-website/docs/observability/langfuse_integration.md b/docs/my-website/docs/observability/langfuse_integration.md index 97277303630..576135ba67c 100644 --- a/docs/my-website/docs/observability/langfuse_integration.md +++ b/docs/my-website/docs/observability/langfuse_integration.md @@ -185,7 +185,7 @@ curl --location --request POST 'http://0.0.0.0:4000/chat/completions' \ * `trace_release` - Release for the trace, defaults to `None` * `trace_metadata` - Metadata for the trace, defaults to `None` * `trace_user_id` - User identifier for the trace, defaults to completion argument `user` -* `tags` - Tags for the trace, defeaults to `None` +* `tags` - Tags for the trace, defaults to `None` ##### Updatable Parameters on Continuation diff --git a/docs/my-website/docs/observability/langsmith_integration.md b/docs/my-website/docs/observability/langsmith_integration.md index 8f55c854db8..cada4122b20 100644 --- a/docs/my-website/docs/observability/langsmith_integration.md +++ b/docs/my-website/docs/observability/langsmith_integration.md @@ -1,4 +1,6 @@ import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; # Langsmith - Logging LLM Input/Output @@ -22,10 +24,13 @@ pip install litellm ## Quick Start Use just 2 lines of code, to instantly log your responses **across all providers** with Langsmith + + ```python -litellm.success_callback = ["langsmith"] +litellm.callbacks = ["langsmith"] ``` + ```python import litellm import os @@ -37,7 +42,7 @@ os.environ["LANGSMITH_DEFAULT_RUN_NAME"] = "" # defaults to LLMRun os.environ['OPENAI_API_KEY']="" # set langsmith as a callback, litellm will send the data to langsmith -litellm.success_callback = ["langsmith"] +litellm.callbacks = ["langsmith"] # openai call response = litellm.completion( @@ -47,8 +52,124 @@ response = litellm.completion( ] ) ``` + + + +1. Setup config.yaml +```yaml +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: openai/gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + +litellm_settings: + callbacks: ["langsmith"] +``` + +2. Start LiteLLM Proxy +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-eWkpOhYaHiuIZV-29JDeTQ' \ +-d '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "Hey, how are you?" + } + ], + "max_completion_tokens": 250 +}' +``` + + + + ## Advanced + +### Local Testing - Control Batch Size + +Set the size of the batch that Langsmith will process at a time, default is 512. + +Set `langsmith_batch_size=1` when testing locally, to see logs land quickly. + + + + +```python +import litellm +import os + +os.environ["LANGSMITH_API_KEY"] = "" +# LLM API Keys +os.environ['OPENAI_API_KEY']="" + +# set langsmith as a callback, litellm will send the data to langsmith +litellm.callbacks = ["langsmith"] +litellm.langsmith_batch_size = 1 # 👈 KEY CHANGE + +response = litellm.completion( + model="gpt-3.5-turbo", + messages=[ + {"role": "user", "content": "Hi 👋 - i'm openai"} + ] +) +print(response) +``` + + + +1. Setup config.yaml +```yaml +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: openai/gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + +litellm_settings: + langsmith_batch_size: 1 + callbacks: ["langsmith"] +``` + +2. Start LiteLLM Proxy +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-eWkpOhYaHiuIZV-29JDeTQ' \ +-d '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "Hey, how are you?" + } + ], + "max_completion_tokens": 250 +}' +``` + + + + + + + + + ### Set Langsmith fields ```python diff --git a/docs/my-website/docs/observability/opentelemetry_integration.md b/docs/my-website/docs/observability/opentelemetry_integration.md index 5df82c93c87..958c33f18e6 100644 --- a/docs/my-website/docs/observability/opentelemetry_integration.md +++ b/docs/my-website/docs/observability/opentelemetry_integration.md @@ -34,8 +34,9 @@ OTEL_HEADERS="Authorization=Bearer%20" ```shell -OTEL_EXPORTER="otlp_http" -OTEL_ENDPOINT="http://0.0.0.0:4318" +OTEL_EXPORTER_OTLP_ENDPOINT="http://0.0.0.0:4318" +OTEL_EXPORTER_OTLP_PROTOCOL=http/json +OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value" ``` @@ -43,8 +44,9 @@ OTEL_ENDPOINT="http://0.0.0.0:4318" ```shell -OTEL_EXPORTER="otlp_grpc" -OTEL_ENDPOINT="http://0.0.0.0:4317" +OTEL_EXPORTER_OTLP_ENDPOINT="http://0.0.0.0:4318" +OTEL_EXPORTER_OTLP_PROTOCOL=grpc +OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value" ``` @@ -98,7 +100,7 @@ LiteLLM emits the user_api_key_metadata - user_id - team_id -for successful + failed requests +for successful + failed requests click under `litellm_request` in the trace diff --git a/docs/my-website/docs/observability/opik_integration.md b/docs/my-website/docs/observability/opik_integration.md index d8075c70e34..b4bcef53937 100644 --- a/docs/my-website/docs/observability/opik_integration.md +++ b/docs/my-website/docs/observability/opik_integration.md @@ -1,3 +1,5 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; import Image from '@theme/IdealImage'; # Comet Opik - Logging + Evals @@ -21,17 +23,16 @@ Use just 4 lines of code, to instantly log your responses **across all providers Get your Opik API Key by signing up [here](https://www.comet.com/signup?utm_source=litelllm&utm_medium=docs&utm_content=api_key_cell)! ```python -from litellm.integrations.opik.opik import OpikLogger import litellm - -opik_logger = OpikLogger() -litellm.callbacks = [opik_logger] +litellm.callbacks = ["opik"] ``` Full examples: + + + ```python -from litellm.integrations.opik.opik import OpikLogger import litellm import os @@ -43,8 +44,7 @@ os.environ["OPIK_WORKSPACE"] = "" os.environ["OPENAI_API_KEY"] = "" # set "opik" as a callback, litellm will send the data to an Opik server (such as comet.com) -opik_logger = OpikLogger() -litellm.callbacks = [opik_logger] +litellm.callbacks = ["opik"] # openai call response = litellm.completion( @@ -55,18 +55,16 @@ response = litellm.completion( ) ``` -If you are liteLLM within a function tracked using Opik's `@track` decorator, +If you are using liteLLM within a function tracked using Opik's `@track` decorator, you will need provide the `current_span_data` field in the metadata attribute so that the LLM call is assigned to the correct trace: ```python from opik import track from opik.opik_context import get_current_span_data -from litellm.integrations.opik.opik import OpikLogger import litellm -opik_logger = OpikLogger() -litellm.callbacks = [opik_logger] +litellm.callbacks = ["opik"] @track() def streaming_function(input): @@ -87,6 +85,126 @@ response = streaming_function("Why is tracking and evaluation of LLMs important? chunks = list(response) ``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: gpt-3.5-turbo-testing + litellm_params: + model: gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + +litellm_settings: + callbacks: ["opik"] + +environment_variables: + OPIK_API_KEY: "" + OPIK_WORKSPACE: "" +``` + +2. Run proxy + +```bash +litellm --config config.yaml +``` + +3. Test it! + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gpt-3.5-turbo-testing", + "messages": [ + { + "role": "user", + "content": "What's the weather like in Boston today?" + } + ] +}' +``` + + + + +## Opik-Specific Parameters + +These can be passed inside metadata with the `opik` key. + +### Fields + +- `project_name` - Name of the Opik project to send data to. +- `current_span_data` - The current span data to be used for tracing. +- `tags` - Tags to be used for tracing. + +### Usage + + + + +```python +from opik import track +from opik.opik_context import get_current_span_data +import litellm + +litellm.callbacks = ["opik"] + +messages = [{"role": "user", "content": input}] +response = litellm.completion( + model="gpt-3.5-turbo", + messages=messages, + metadata = { + "opik": { + "current_span_data": get_current_span_data(), + "tags": ["streaming-test"], + }, + } +) +return response +``` + + + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gpt-3.5-turbo-testing", + "messages": [ + { + "role": "user", + "content": "What's the weather like in Boston today?" + } + ], + "metadata": { + "opik": { + "current_span_data": "...", + "tags": ["streaming-test"], + }, + } +}' +``` + + + + + + + + + + + + + + + + ## Support & Talk to Founders - [Schedule Demo 👋](https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version) diff --git a/docs/my-website/docs/observability/phoenix_integration.md b/docs/my-website/docs/observability/phoenix_integration.md new file mode 100644 index 00000000000..d15eea9a834 --- /dev/null +++ b/docs/my-website/docs/observability/phoenix_integration.md @@ -0,0 +1,78 @@ +import Image from '@theme/IdealImage'; + +# Arize Phoenix OSS + +Open source tracing and evaluation platform + +:::tip + +This is community maintained, Please make an issue if you run into a bug +https://github.com/BerriAI/litellm + +::: + + +## Pre-Requisites +Make an account on [Phoenix OSS](https://phoenix.arize.com) +OR self-host your own instance of [Phoenix](https://docs.arize.com/phoenix/deployment) + +## Quick Start +Use just 2 lines of code, to instantly log your responses **across all providers** with Phoenix + +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] +``` +```python +litellm.callbacks = ["arize_phoenix"] +``` +```python +import litellm +import os + +os.environ["PHOENIX_API_KEY"] = "" # Necessary only using Phoenix Cloud +os.environ["PHOENIX_COLLECTOR_HTTP_ENDPOINT"] = "" # The URL of your Phoenix OSS instance e.g. http://localhost:6006/v1/traces +# This defaults to https://app.phoenix.arize.com/v1/traces for Phoenix Cloud + +# LLM API Keys +os.environ['OPENAI_API_KEY']="" + +# set arize as a callback, litellm will send the data to arize +litellm.callbacks = ["arize_phoenix"] + +# openai call +response = litellm.completion( + model="gpt-3.5-turbo", + messages=[ + {"role": "user", "content": "Hi 👋 - i'm openai"} + ] +) +``` + +### Using with LiteLLM Proxy + + +```yaml +model_list: + - model_name: gpt-4o + litellm_params: + model: openai/fake + api_key: fake-key + api_base: https://exampleopenaiendpoint-production.up.railway.app/ + +litellm_settings: + callbacks: ["arize_phoenix"] + +environment_variables: + PHOENIX_API_KEY: "d0*****" + PHOENIX_COLLECTOR_ENDPOINT: "https://app.phoenix.arize.com/v1/traces" # OPTIONAL, for setting the GRPC endpoint + PHOENIX_COLLECTOR_HTTP_ENDPOINT: "https://app.phoenix.arize.com/v1/traces" # OPTIONAL, for setting the HTTP endpoint +``` + +## Support & Talk to Founders + +- [Schedule Demo 👋](https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version) +- [Community Discord 💭](https://discord.gg/wuPM9dRgDw) +- Our numbers 📞 +1 (770) 8783-106 / ‭+1 (412) 618-6238‬ +- Our emails ✉️ ishaan@berri.ai / krrish@berri.ai diff --git a/docs/my-website/docs/pass_through/assembly_ai.md b/docs/my-website/docs/pass_through/assembly_ai.md new file mode 100644 index 00000000000..4606640c5c4 --- /dev/null +++ b/docs/my-website/docs/pass_through/assembly_ai.md @@ -0,0 +1,85 @@ +# Assembly AI + +Pass-through endpoints for Assembly AI - call Assembly AI endpoints, in native format (no translation). + +| Feature | Supported | Notes | +|-------|-------|-------| +| Cost Tracking | ✅ | works across all integrations | +| Logging | ✅ | works across all integrations | + + +Supports **ALL** Assembly AI Endpoints + +[**See All Assembly AI Endpoints**](https://www.assemblyai.com/docs/api-reference) + + + + +## Quick Start + +Let's call the Assembly AI [`/v2/transcripts` endpoint](https://www.assemblyai.com/docs/api-reference/transcripts) + +1. Add Assembly AI API Key to your environment + +```bash +export ASSEMBLYAI_API_KEY="" +``` + +2. Start LiteLLM Proxy + +```bash +litellm + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +Let's call the Assembly AI `/v2/transcripts` endpoint + +```python +import assemblyai as aai + +LITELLM_VIRTUAL_KEY = "sk-1234" # +LITELLM_PROXY_BASE_URL = "http://0.0.0.0:4000/assemblyai" # /assemblyai + +aai.settings.api_key = f"Bearer {LITELLM_VIRTUAL_KEY}" +aai.settings.base_url = LITELLM_PROXY_BASE_URL + +# URL of the file to transcribe +FILE_URL = "https://assembly.ai/wildfires.mp3" + +# You can also transcribe a local file by passing in a file path +# FILE_URL = './path/to/file.mp3' + +transcriber = aai.Transcriber() +transcript = transcriber.transcribe(FILE_URL) +print(transcript) +print(transcript.id) +``` + +## Calling Assembly AI EU endpoints + +If you want to send your request to the Assembly AI EU endpoint, you can do so by setting the `LITELLM_PROXY_BASE_URL` to `/eu.assemblyai` + + +```python +import assemblyai as aai + +LITELLM_VIRTUAL_KEY = "sk-1234" # +LITELLM_PROXY_BASE_URL = "http://0.0.0.0:4000/eu.assemblyai" # /eu.assemblyai + +aai.settings.api_key = f"Bearer {LITELLM_VIRTUAL_KEY}" +aai.settings.base_url = LITELLM_PROXY_BASE_URL + +# URL of the file to transcribe +FILE_URL = "https://assembly.ai/wildfires.mp3" + +# You can also transcribe a local file by passing in a file path +# FILE_URL = './path/to/file.mp3' + +transcriber = aai.Transcriber() +transcript = transcriber.transcribe(FILE_URL) +print(transcript) +print(transcript.id) +``` diff --git a/docs/my-website/docs/pass_through/bedrock.md b/docs/my-website/docs/pass_through/bedrock.md index ed184f57064..5c90f3c5d1c 100644 --- a/docs/my-website/docs/pass_through/bedrock.md +++ b/docs/my-website/docs/pass_through/bedrock.md @@ -257,7 +257,7 @@ proxy_endpoint = "http://0.0.0.0:4000/bedrock" # 👈 your proxy base url # # Create a Config object with the proxy # Custom headers custom_headers = { - 'litellm_user_api_key': 'sk-1234', # 👈 your proxy api key + 'litellm_user_api_key': 'Bearer sk-1234', # 👈 your proxy api key } @@ -274,9 +274,7 @@ runtime_client = boto3.client( # Custom header injection def inject_custom_headers(request, **kwargs): - request.headers.update({ - 'litellm_user_api_key': 'sk-1234', - }) + request.headers.update(custom_headers) # Attach the event to inject custom headers before the request is sent runtime_client.meta.events.register('before-send.*.*', inject_custom_headers) diff --git a/docs/my-website/docs/pass_through/cohere.md b/docs/my-website/docs/pass_through/cohere.md index 87eabd462c8..227ff5777a4 100644 --- a/docs/my-website/docs/pass_through/cohere.md +++ b/docs/my-website/docs/pass_through/cohere.md @@ -4,7 +4,7 @@ Pass-through endpoints for Cohere - call provider-specific endpoint, in native f | Feature | Supported | Notes | |-------|-------|-------| -| Cost Tracking | ❌ | [Tell us if you need this](https://github.com/BerriAI/litellm/issues/new) | +| Cost Tracking | ✅ | Supported for `/v1/chat`, and `/v2/chat` | | Logging | ✅ | works across all integrations | | End-user Tracking | ❌ | [Tell us if you need this](https://github.com/BerriAI/litellm/issues/new) | | Streaming | ✅ | | diff --git a/docs/my-website/docs/pass_through/mistral.md b/docs/my-website/docs/pass_through/mistral.md new file mode 100644 index 00000000000..ee7ca800c4f --- /dev/null +++ b/docs/my-website/docs/pass_through/mistral.md @@ -0,0 +1,217 @@ +# Mistral + +Pass-through endpoints for Mistral - call provider-specific endpoint, in native format (no translation). + +| Feature | Supported | Notes | +|-------|-------|-------| +| Cost Tracking | ❌ | Not supported | +| Logging | ✅ | works across all integrations | +| End-user Tracking | ❌ | [Tell us if you need this](https://github.com/BerriAI/litellm/issues/new) | +| Streaming | ✅ | | + +Just replace `https://api.mistral.ai/v1` with `LITELLM_PROXY_BASE_URL/mistral` 🚀 + +#### **Example Usage** + +```bash +curl -L -X POST 'http://0.0.0.0:4000/mistral/v1/ocr' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "mistral-ocr-latest", + "document": { + "type": "image_url", + "image_url": "https://raw.githubusercontent.com/mistralai/cookbook/refs/heads/main/mistral/ocr/receipt.png" + } + +}' +``` + +Supports **ALL** Mistral Endpoints (including streaming). + +## Quick Start + +Let's call the Mistral [`/chat/completions` endpoint](https://docs.mistral.ai/api/#tag/chat/operation/chat_completion_v1_chat_completions_post) + +1. Add MISTRAL_API_KEY to your environment + +```bash +export MISTRAL_API_KEY="sk-1234" +``` + +2. Start LiteLLM Proxy + +```bash +litellm + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +Let's call the Mistral `/ocr` endpoint + +```bash +curl -L -X POST 'http://0.0.0.0:4000/mistral/v1/ocr' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "mistral-ocr-latest", + "document": { + "type": "image_url", + "image_url": "https://raw.githubusercontent.com/mistralai/cookbook/refs/heads/main/mistral/ocr/receipt.png" + } + +}' +``` + + +## Examples + +Anything after `http://0.0.0.0:4000/mistral` is treated as a provider-specific route, and handled accordingly. + +Key Changes: + +| **Original Endpoint** | **Replace With** | +|------------------------------------------------------|-----------------------------------| +| `https://api.mistral.ai/v1` | `http://0.0.0.0:4000/mistral` (LITELLM_PROXY_BASE_URL="http://0.0.0.0:4000") | +| `bearer $MISTRAL_API_KEY` | `bearer anything` (use `bearer LITELLM_VIRTUAL_KEY` if Virtual Keys are setup on proxy) | + + +### **Example 1: OCR endpoint** + +#### LiteLLM Proxy Call + +```bash +curl -L -X POST 'http://0.0.0.0:4000/mistral/v1/ocr' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_API_KEY' \ +-d '{ + "model": "mistral-ocr-latest", + "document": { + "type": "image_url", + "image_url": "https://raw.githubusercontent.com/mistralai/cookbook/refs/heads/main/mistral/ocr/receipt.png" + } +}' +``` + + +#### Direct Mistral API Call + +```bash +curl https://api.mistral.ai/v1/ocr \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${MISTRAL_API_KEY}" \ + -d '{ + "model": "mistral-ocr-latest", + "document": { + "type": "document_url", + "document_url": "https://arxiv.org/pdf/2201.04234" + }, + "include_image_base64": true + }' +``` + +### **Example 2: Chat API** + +#### LiteLLM Proxy Call + +```bash +curl -L -X POST 'http://0.0.0.0:4000/mistral/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_VIRTUAL_KEY' \ +-d '{ + "messages": [ + { + "role": "user", + "content": "I am going to Paris, what should I see?" + } + ], + "max_tokens": 2048, + "temperature": 0.8, + "top_p": 0.1, + "model": "mistral-large-latest", +}' +``` + +#### Direct Mistral API Call + +```bash +curl -L -X POST 'https://api.mistral.ai/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-d '{ + "messages": [ + { + "role": "user", + "content": "I am going to Paris, what should I see?" + } + ], + "max_tokens": 2048, + "temperature": 0.8, + "top_p": 0.1, + "model": "mistral-large-latest", +}' +``` + + +## Advanced - Use with Virtual Keys + +Pre-requisites +- [Setup proxy with DB](../proxy/virtual_keys.md#setup) + +Use this, to avoid giving developers the raw Mistral API key, but still letting them use Mistral endpoints. + +### Usage + +1. Setup environment + +```bash +export DATABASE_URL="" +export LITELLM_MASTER_KEY="" +export MISTRAL_API_BASE="" +``` + +```bash +litellm + +# RUNNING on http://0.0.0.0:4000 +``` + +2. Generate virtual key + +```bash +curl -X POST 'http://0.0.0.0:4000/key/generate' \ +-H 'Authorization: Bearer sk-1234' \ +-H 'Content-Type: application/json' \ +-d '{}' +``` + +Expected Response + +```bash +{ + ... + "key": "sk-1234ewknldferwedojwojw" +} +``` + +3. Test it! + + +```bash +curl -L -X POST 'http://0.0.0.0:4000/mistral/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234ewknldferwedojwojw' \ + --data '{ + "messages": [ + { + "role": "user", + "content": "I am going to Paris, what should I see?" + } + ], + "max_tokens": 2048, + "temperature": 0.8, + "top_p": 0.1, + "model": "qwen2.5-7b-instruct", +}' +``` \ No newline at end of file diff --git a/docs/my-website/docs/pass_through/openai_passthrough.md b/docs/my-website/docs/pass_through/openai_passthrough.md new file mode 100644 index 00000000000..27123695751 --- /dev/null +++ b/docs/my-website/docs/pass_through/openai_passthrough.md @@ -0,0 +1,95 @@ +# OpenAI Passthrough + +Pass-through endpoints for `/openai` + +## Overview + +| Feature | Supported | Notes | +|-------|-------|-------| +| Cost Tracking | ❌ | Not supported | +| Logging | ✅ | Works across all integrations | +| Streaming | ✅ | Fully supported | + +### When to use this? + +- For 90% of your use cases, you should use the [native LiteLLM OpenAI Integration](https://docs.litellm.ai/docs/providers/openai) (`/chat/completions`, `/embeddings`, `/completions`, `/images`, `/batches`, etc.) +- Use this passthrough to call less popular or newer OpenAI endpoints that LiteLLM doesn't fully support yet, such as `/assistants`, `/threads`, `/vector_stores` + +Simply replace `https://api.openai.com` with `LITELLM_PROXY_BASE_URL/openai` + +## Usage Examples + +### Assistants API + +#### Create OpenAI Client + +Make sure you do the following: +- Point `base_url` to your `LITELLM_PROXY_BASE_URL/openai` +- Use your `LITELLM_API_KEY` as the `api_key` + +```python +import openai + +client = openai.OpenAI( + base_url="http://0.0.0.0:4000/openai", # /openai + api_key="sk-anything" # +) +``` + +#### Create an Assistant + +```python +# Create an assistant +assistant = client.beta.assistants.create( + name="Math Tutor", + instructions="You are a math tutor. Help solve equations.", + model="gpt-4o", +) +``` + +#### Create a Thread +```python +# Create a thread +thread = client.beta.threads.create() +``` + +#### Add a Message to the Thread +```python +# Add a message +message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content="Solve 3x + 11 = 14", +) +``` + +#### Run the Assistant +```python +# Create a run to get the assistant's response +run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant.id, +) + +# Check run status +run_status = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id +) +``` + +#### Retrieve Messages +```python +# List messages after the run completes +messages = client.beta.threads.messages.list( + thread_id=thread.id +) +``` + +#### Delete the Assistant + +```python +# Delete the assistant when done +client.beta.assistants.delete(assistant.id) +``` + diff --git a/docs/my-website/docs/pass_through/vertex_ai.md b/docs/my-website/docs/pass_through/vertex_ai.md index ce366af541a..b99f0fcf982 100644 --- a/docs/my-website/docs/pass_through/vertex_ai.md +++ b/docs/my-website/docs/pass_through/vertex_ai.md @@ -13,8 +13,102 @@ Pass-through endpoints for Vertex AI - call provider-specific endpoint, in nativ | End-user Tracking | ❌ | [Tell us if you need this](https://github.com/BerriAI/litellm/issues/new) | | Streaming | ✅ | | +## Supported Endpoints + +LiteLLM supports 2 vertex ai passthrough routes: + +1. `/vertex_ai` → routes to `https://{vertex_location}-aiplatform.googleapis.com/` +2. `/vertex_ai/discovery` → routes to [`https://discoveryengine.googleapis.com`](https://discoveryengine.googleapis.com/) + +## How to use + Just replace `https://REGION-aiplatform.googleapis.com` with `LITELLM_PROXY_BASE_URL/vertex_ai` +LiteLLM supports 3 flows for calling Vertex AI endpoints via pass-through: + +1. **Specific Credentials**: Admin sets passthrough credentials for a specific project/region. + +2. **Default Credentials**: Admin sets default credentials. + +3. **Client-Side Credentials**: User can send client-side credentials through to Vertex AI (default behavior - if no default or mapped credentials are found, the request is passed through directly). + + +## Example Usage + + + + +```yaml +model_list: + - model_name: gemini-1.0-pro + litellm_params: + model: vertex_ai/gemini-1.0-pro + vertex_project: adroit-crow-413218 + vertex_region: us-central1 + vertex_credentials: /path/to/credentials.json + use_in_pass_through: true # 👈 KEY CHANGE +``` + + + + + + + +```yaml +default_vertex_config: + vertex_project: adroit-crow-413218 + vertex_region: us-central1 + vertex_credentials: /path/to/credentials.json +``` + + + +```bash +export DEFAULT_VERTEXAI_PROJECT="adroit-crow-413218" +export DEFAULT_VERTEXAI_LOCATION="us-central1" +export DEFAULT_GOOGLE_APPLICATION_CREDENTIALS="/path/to/credentials.json" +``` + + + + + + +Try Gemini 2.0 Flash (curl) + +``` +MODEL_ID="gemini-2.0-flash-001" +PROJECT_ID="YOUR_PROJECT_ID" +``` + +```bash +curl \ + -X POST \ + -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ + -H "Content-Type: application/json" \ + "${LITELLM_PROXY_BASE_URL}/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${MODEL_ID}:streamGenerateContent" -d \ + $'{ + "contents": { + "role": "user", + "parts": [ + { + "fileData": { + "mimeType": "image/png", + "fileUri": "gs://generativeai-downloads/images/scones.jpg" + } + }, + { + "text": "Describe this picture." + } + ] + } + }' +``` + + + + #### **Example Usage** @@ -22,7 +116,7 @@ Just replace `https://REGION-aiplatform.googleapis.com` with `LITELLM_PROXY_BASE ```bash -curl http://localhost:4000/vertex_ai/publishers/google/models/gemini-1.0-pro:generateContent \ +curl http://localhost:4000/vertex_ai/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${MODEL_ID}:generateContent \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{ @@ -101,7 +195,7 @@ litellm Let's call the Google AI Studio token counting endpoint ```bash -curl http://localhost:4000/vertex-ai/publishers/google/models/gemini-1.0-pro:generateContent \ +curl http://localhost:4000/vertex-ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-1.0-pro:generateContent \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ @@ -128,7 +222,7 @@ curl http://localhost:4000/vertex-ai/publishers/google/models/gemini-1.0-pro:gen LiteLLM Proxy Server supports two methods of authentication to Vertex AI: -1. Pass Vertex Credetials client side to proxy server +1. Pass Vertex Credentials client side to proxy server 2. Set Vertex AI credentials on proxy server @@ -140,7 +234,7 @@ LiteLLM Proxy Server supports two methods of authentication to Vertex AI: ```shell -curl http://localhost:4000/vertex_ai/publishers/google/models/gemini-1.5-flash-001:generateContent \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-1.5-flash-001:generateContent \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{"contents":[{"role": "user", "parts":[{"text": "hi"}]}]}' @@ -152,7 +246,7 @@ curl http://localhost:4000/vertex_ai/publishers/google/models/gemini-1.5-flash-0 ```shell -curl http://localhost:4000/vertex_ai/publishers/google/models/textembedding-gecko@001:predict \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/textembedding-gecko@001:predict \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{"instances":[{"content": "gm"}]}' @@ -162,7 +256,7 @@ curl http://localhost:4000/vertex_ai/publishers/google/models/textembedding-geck ### Imagen API ```shell -curl http://localhost:4000/vertex_ai/publishers/google/models/imagen-3.0-generate-001:predict \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/imagen-3.0-generate-001:predict \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{"instances":[{"prompt": "make an otter"}], "parameters": {"sampleCount": 1}}' @@ -172,7 +266,7 @@ curl http://localhost:4000/vertex_ai/publishers/google/models/imagen-3.0-generat ### Count Tokens API ```shell -curl http://localhost:4000/vertex_ai/publishers/google/models/gemini-1.5-flash-001:countTokens \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-1.5-flash-001:countTokens \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{"contents":[{"role": "user", "parts":[{"text": "hi"}]}]}' @@ -183,7 +277,7 @@ Create Fine Tuning Job ```shell -curl http://localhost:4000/vertex_ai/tuningJobs \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-1.5-flash-001:tuningJobs \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{ @@ -243,7 +337,7 @@ Expected Response ```bash -curl http://localhost:4000/vertex_ai/publishers/google/models/gemini-1.0-pro:generateContent \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-1.0-pro:generateContent \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -d '{ @@ -268,7 +362,7 @@ tags: ["vertex-js-sdk", "pass-through-endpoint"] ```bash -curl http://localhost:4000/vertex-ai/publishers/google/models/gemini-1.0-pro:generateContent \ +curl http://localhost:4000/vertex_ai/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-1.0-pro:generateContent \ -H "Content-Type: application/json" \ -H "x-litellm-api-key: Bearer sk-1234" \ -H "tags: vertex-js-sdk,pass-through-endpoint" \ diff --git a/docs/my-website/docs/pass_through/vllm.md b/docs/my-website/docs/pass_through/vllm.md new file mode 100644 index 00000000000..b267622948b --- /dev/null +++ b/docs/my-website/docs/pass_through/vllm.md @@ -0,0 +1,185 @@ +# VLLM + +Pass-through endpoints for VLLM - call provider-specific endpoint, in native format (no translation). + +| Feature | Supported | Notes | +|-------|-------|-------| +| Cost Tracking | ❌ | Not supported | +| Logging | ✅ | works across all integrations | +| End-user Tracking | ❌ | [Tell us if you need this](https://github.com/BerriAI/litellm/issues/new) | +| Streaming | ✅ | | + +Just replace `https://my-vllm-server.com` with `LITELLM_PROXY_BASE_URL/vllm` 🚀 + +#### **Example Usage** + +```bash +curl -L -X GET 'http://0.0.0.0:4000/vllm/metrics' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +``` + +Supports **ALL** VLLM Endpoints (including streaming). + +## Quick Start + +Let's call the VLLM [`/metrics` endpoint](https://vllm.readthedocs.io/en/latest/api_reference/api_reference.html) + +1. Add HOSTED VLLM API BASE to your environment + +```bash +export HOSTED_VLLM_API_BASE="https://my-vllm-server.com" +``` + +2. Start LiteLLM Proxy + +```bash +litellm + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +Let's call the VLLM `/metrics` endpoint + +```bash +curl -L -X GET 'http://0.0.0.0:4000/vllm/metrics' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +``` + + +## Examples + +Anything after `http://0.0.0.0:4000/vllm` is treated as a provider-specific route, and handled accordingly. + +Key Changes: + +| **Original Endpoint** | **Replace With** | +|------------------------------------------------------|-----------------------------------| +| `https://my-vllm-server.com` | `http://0.0.0.0:4000/vllm` (LITELLM_PROXY_BASE_URL="http://0.0.0.0:4000") | +| `bearer $VLLM_API_KEY` | `bearer anything` (use `bearer LITELLM_VIRTUAL_KEY` if Virtual Keys are setup on proxy) | + + +### **Example 1: Metrics endpoint** + +#### LiteLLM Proxy Call + +```bash +curl -L -X GET 'http://0.0.0.0:4000/vllm/metrics' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_VIRTUAL_KEY' \ +``` + + +#### Direct VLLM API Call + +```bash +curl -L -X GET 'https://my-vllm-server.com/metrics' \ +-H 'Content-Type: application/json' \ +``` + +### **Example 2: Chat API** + +#### LiteLLM Proxy Call + +```bash +curl -L -X POST 'http://0.0.0.0:4000/vllm/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_VIRTUAL_KEY' \ +-d '{ + "messages": [ + { + "role": "user", + "content": "I am going to Paris, what should I see?" + } + ], + "max_tokens": 2048, + "temperature": 0.8, + "top_p": 0.1, + "model": "qwen2.5-7b-instruct", +}' +``` + +#### Direct VLLM API Call + +```bash +curl -L -X POST 'https://my-vllm-server.com/chat/completions' \ +-H 'Content-Type: application/json' \ +-d '{ + "messages": [ + { + "role": "user", + "content": "I am going to Paris, what should I see?" + } + ], + "max_tokens": 2048, + "temperature": 0.8, + "top_p": 0.1, + "model": "qwen2.5-7b-instruct", +}' +``` + + +## Advanced - Use with Virtual Keys + +Pre-requisites +- [Setup proxy with DB](../proxy/virtual_keys.md#setup) + +Use this, to avoid giving developers the raw Cohere API key, but still letting them use Cohere endpoints. + +### Usage + +1. Setup environment + +```bash +export DATABASE_URL="" +export LITELLM_MASTER_KEY="" +export HOSTED_VLLM_API_BASE="" +``` + +```bash +litellm + +# RUNNING on http://0.0.0.0:4000 +``` + +2. Generate virtual key + +```bash +curl -X POST 'http://0.0.0.0:4000/key/generate' \ +-H 'Authorization: Bearer sk-1234' \ +-H 'Content-Type: application/json' \ +-d '{}' +``` + +Expected Response + +```bash +{ + ... + "key": "sk-1234ewknldferwedojwojw" +} +``` + +3. Test it! + + +```bash +curl -L -X POST 'http://0.0.0.0:4000/vllm/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234ewknldferwedojwojw' \ + --data '{ + "messages": [ + { + "role": "user", + "content": "I am going to Paris, what should I see?" + } + ], + "max_tokens": 2048, + "temperature": 0.8, + "top_p": 0.1, + "model": "qwen2.5-7b-instruct", +}' +``` \ No newline at end of file diff --git a/docs/my-website/docs/projects/Elroy.md b/docs/my-website/docs/projects/Elroy.md new file mode 100644 index 00000000000..07652f577a8 --- /dev/null +++ b/docs/my-website/docs/projects/Elroy.md @@ -0,0 +1,14 @@ +# 🐕 Elroy + +Elroy is a scriptable AI assistant that remembers and sets goals. + +Interact through the command line, share memories via MCP, or build your own tools using Python. + + +[![Static Badge][github-shield]][github-url] +[![Discord][discord-shield]][discord-url] + +[github-shield]: https://img.shields.io/badge/Github-repo-white?logo=github +[github-url]: https://github.com/elroy-bot/elroy +[discord-shield]:https://img.shields.io/discord/1200684659277832293?color=7289DA&label=Discord&logo=discord&logoColor=white +[discord-url]: https://discord.gg/5PJUY4eMce diff --git a/docs/my-website/docs/projects/GPTLocalhost.md b/docs/my-website/docs/projects/GPTLocalhost.md new file mode 100644 index 00000000000..791217fe765 --- /dev/null +++ b/docs/my-website/docs/projects/GPTLocalhost.md @@ -0,0 +1,3 @@ +# GPTLocalhost + +[GPTLocalhost](https://gptlocalhost.com/demo#LiteLLM) - LiteLLM is supported by GPTLocalhost, a local Word Add-in for you to use models in LiteLLM within Microsoft Word. 100% Private. diff --git a/docs/my-website/docs/projects/PDL.md b/docs/my-website/docs/projects/PDL.md new file mode 100644 index 00000000000..5d6fd775558 --- /dev/null +++ b/docs/my-website/docs/projects/PDL.md @@ -0,0 +1,5 @@ +PDL - A YAML-based approach to prompt programming + +Github: https://github.com/IBM/prompt-declaration-language + +PDL is a declarative approach to prompt programming, helping users to accumulate messages implicitly, with support for model chaining and tool use. \ No newline at end of file diff --git a/docs/my-website/docs/projects/pgai.md b/docs/my-website/docs/projects/pgai.md new file mode 100644 index 00000000000..bece5baf6a0 --- /dev/null +++ b/docs/my-website/docs/projects/pgai.md @@ -0,0 +1,9 @@ +# pgai + +[pgai](https://github.com/timescale/pgai) is a suite of tools to develop RAG, semantic search, and other AI applications more easily with PostgreSQL. + +If you don't know what pgai is yet check out the [README](https://github.com/timescale/pgai)! + +If you're already familiar with pgai, you can find litellm specific docs here: +- Litellm for [model calling](https://github.com/timescale/pgai/blob/main/docs/model_calling/litellm.md) in pgai +- Use the [litellm provider](https://github.com/timescale/pgai/blob/main/docs/vectorizer/api-reference.md#aiembedding_litellm) to automatically create embeddings for your data via the pgai vectorizer. diff --git a/docs/my-website/docs/providers/aiml.md b/docs/my-website/docs/providers/aiml.md new file mode 100644 index 00000000000..1343cbf8d8e --- /dev/null +++ b/docs/my-website/docs/providers/aiml.md @@ -0,0 +1,160 @@ +# AI/ML API + +Getting started with the AI/ML API is simple. Follow these steps to set up your integration: + +### 1. Get Your API Key +To begin, you need an API key. You can obtain yours here: +🔑 [Get Your API Key](https://aimlapi.com/app/keys/?utm_source=aimlapi&utm_medium=github&utm_campaign=integration) + +### 2. Explore Available Models +Looking for a different model? Browse the full list of supported models: +📚 [Full List of Models](https://docs.aimlapi.com/api-overview/model-database/text-models?utm_source=aimlapi&utm_medium=github&utm_campaign=integration) + +### 3. Read the Documentation +For detailed setup instructions and usage guidelines, check out the official documentation: +📖 [AI/ML API Docs](https://docs.aimlapi.com/quickstart/setting-up?utm_source=aimlapi&utm_medium=github&utm_campaign=integration) + +### 4. Need Help? +If you have any questions, feel free to reach out. We’re happy to assist! 🚀 [Discord](https://discord.gg/hvaUsJpVJf) + +## Usage +You can choose from LLama, Qwen, Flux, and 200+ other open and closed-source models on aimlapi.com/models. For example: + +```python +import litellm + +response = litellm.completion( + model="openai/meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo", # The model name must include prefix "openai" + the model name from ai/ml api + api_key="", # your aiml api-key + api_base="https://api.aimlapi.com/v2", + messages=[ + { + "role": "user", + "content": "Hey, how's it going?", + } + ], +) +``` + +## Streaming + +```python +import litellm + +response = litellm.completion( + model="openai/Qwen/Qwen2-72B-Instruct", # The model name must include prefix "openai" + the model name from ai/ml api + api_key="", # your aiml api-key + api_base="https://api.aimlapi.com/v2", + messages=[ + { + "role": "user", + "content": "Hey, how's it going?", + } + ], + stream=True, +) +for chunk in response: + print(chunk) +``` + +## Async Completion + +```python +import asyncio + +import litellm + + +async def main(): + response = await litellm.acompletion( + model="openai/anthropic/claude-3-5-haiku", # The model name must include prefix "openai" + the model name from ai/ml api + api_key="", # your aiml api-key + api_base="https://api.aimlapi.com/v2", + messages=[ + { + "role": "user", + "content": "Hey, how's it going?", + } + ], + ) + print(response) + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## Async Streaming + +```python +import asyncio +import traceback + +import litellm + + +async def main(): + try: + print("test acompletion + streaming") + response = await litellm.acompletion( + model="openai/nvidia/Llama-3.1-Nemotron-70B-Instruct-HF", # The model name must include prefix "openai" + the model name from ai/ml api + api_key="", # your aiml api-key + api_base="https://api.aimlapi.com/v2", + messages=[{"content": "Hey, how's it going?", "role": "user"}], + stream=True, + ) + print(f"response: {response}") + async for chunk in response: + print(chunk) + except: + print(f"error occurred: {traceback.format_exc()}") + pass + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## Async Embedding + +```python +import asyncio + +import litellm + + +async def main(): + response = await litellm.aembedding( + model="openai/text-embedding-3-small", # The model name must include prefix "openai" + the model name from ai/ml api + api_key="", # your aiml api-key + api_base="https://api.aimlapi.com/v1", # 👈 the URL has changed from v2 to v1 + input="Your text string", + ) + print(response) + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## Async Image Generation + +```python +import asyncio + +import litellm + + +async def main(): + response = await litellm.aimage_generation( + model="openai/dall-e-3", # The model name must include prefix "openai" + the model name from ai/ml api + api_key="", # your aiml api-key + api_base="https://api.aimlapi.com/v1", # 👈 the URL has changed from v2 to v1 + prompt="A cute baby sea otter", + ) + print(response) + + +if __name__ == "__main__": + asyncio.run(main()) +``` \ No newline at end of file diff --git a/docs/my-website/docs/providers/anthropic.md b/docs/my-website/docs/providers/anthropic.md index b3bfe333ccb..990a9b5122e 100644 --- a/docs/my-website/docs/providers/anthropic.md +++ b/docs/my-website/docs/providers/anthropic.md @@ -750,7 +750,11 @@ except Exception as e: s/o @[Shekhar Patnaik](https://www.linkedin.com/in/patnaikshekhar) for requesting this! -### Computer Tools +### Anthropic Hosted Tools (Computer, Text Editor, Web Search) + + + + ```python from litellm import completion @@ -781,6 +785,205 @@ resp = completion( print(resp) ``` + + + + + + +```python +from litellm import completion + +tools = [{ + "type": "text_editor_20250124", + "name": "str_replace_editor" +}] +model = "claude-3-5-sonnet-20241022" +messages = [{"role": "user", "content": "There's a syntax error in my primes.py file. Can you help me fix it?"}] + +resp = completion( + model=model, + messages=messages, + tools=tools, +) + +print(resp) +``` + + + + +1. Setup config.yaml + +```yaml +- model_name: claude-3-5-sonnet-latest + litellm_params: + model: anthropic/claude-3-5-sonnet-latest + api_key: os.environ/ANTHROPIC_API_KEY +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "claude-3-5-sonnet-latest", + "messages": [{"role": "user", "content": "There's a syntax error in my primes.py file. Can you help me fix it?"}], + "tools": [{"type": "text_editor_20250124", "name": "str_replace_editor"}] + }' +``` + + + + + + +:::info +Live from v1.70.1+ +::: + +LiteLLM maps OpenAI's `search_context_size` param to Anthropic's `max_uses` param. + +| OpenAI | Anthropic | +| --- | --- | +| Low | 1 | +| Medium | 5 | +| High | 10 | + + + + + + + + + +```python +from litellm import completion + +model = "claude-3-5-sonnet-20241022" +messages = [{"role": "user", "content": "What's the weather like today?"}] + +resp = completion( + model=model, + messages=messages, + web_search_options={ + "search_context_size": "medium", + "user_location": { + "type": "approximate", + "approximate": { + "city": "San Francisco", + }, + } + } +) + +print(resp) +``` + + + +```python +from litellm import completion + +tools = [{ + "type": "web_search_20250305", + "name": "web_search", + "max_uses": 5 +}] +model = "claude-3-5-sonnet-20241022" +messages = [{"role": "user", "content": "There's a syntax error in my primes.py file. Can you help me fix it?"}] + +resp = completion( + model=model, + messages=messages, + tools=tools, +) + +print(resp) +``` + + + + + + + +1. Setup config.yaml + +```yaml +- model_name: claude-3-5-sonnet-latest + litellm_params: + model: anthropic/claude-3-5-sonnet-latest + api_key: os.environ/ANTHROPIC_API_KEY +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "claude-3-5-sonnet-latest", + "messages": [{"role": "user", "content": "What's the weather like today?"}], + "web_search_options": { + "search_context_size": "medium", + "user_location": { + "type": "approximate", + "approximate": { + "city": "San Francisco", + }, + } + } + }' +``` + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "claude-3-5-sonnet-latest", + "messages": [{"role": "user", "content": "What's the weather like today?"}], + "tools": [{ + "type": "web_search_20250305", + "name": "web_search", + "max_uses": 5 + }] + }' +``` + + + + + + + + + + + ## Usage - Vision ```python @@ -819,6 +1022,160 @@ resp = litellm.completion( print(f"\nResponse: {resp}") ``` +## Usage - Thinking / `reasoning_content` + +LiteLLM translates OpenAI's `reasoning_effort` to Anthropic's `thinking` parameter. [Code](https://github.com/BerriAI/litellm/blob/23051d89dd3611a81617d84277059cd88b2df511/litellm/llms/anthropic/chat/transformation.py#L298) + +| reasoning_effort | thinking | +| ---------------- | -------- | +| "low" | "budget_tokens": 1024 | +| "medium" | "budget_tokens": 2048 | +| "high" | "budget_tokens": 4096 | + + + + +```python +from litellm import completion + +resp = completion( + model="anthropic/claude-3-7-sonnet-20250219", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", +) + +``` + + + + + +1. Setup config.yaml + +```yaml +- model_name: claude-3-7-sonnet-20250219 + litellm_params: + model: anthropic/claude-3-7-sonnet-20250219 + api_key: os.environ/ANTHROPIC_API_KEY +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "model": "claude-3-7-sonnet-20250219", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "reasoning_effort": "low" + }' +``` + + + + + +**Expected Response** + +```python +ModelResponse( + id='chatcmpl-c542d76d-f675-4e87-8e5f-05855f5d0f5e', + created=1740470510, + model='claude-3-7-sonnet-20250219', + object='chat.completion', + system_fingerprint=None, + choices=[ + Choices( + finish_reason='stop', + index=0, + message=Message( + content="The capital of France is Paris.", + role='assistant', + tool_calls=None, + function_call=None, + provider_specific_fields={ + 'citations': None, + 'thinking_blocks': [ + { + 'type': 'thinking', + 'thinking': 'The capital of France is Paris. This is a very straightforward factual question.', + 'signature': 'EuYBCkQYAiJAy6...' + } + ] + } + ), + thinking_blocks=[ + { + 'type': 'thinking', + 'thinking': 'The capital of France is Paris. This is a very straightforward factual question.', + 'signature': 'EuYBCkQYAiJAy6AGB...' + } + ], + reasoning_content='The capital of France is Paris. This is a very straightforward factual question.' + ) + ], + usage=Usage( + completion_tokens=68, + prompt_tokens=42, + total_tokens=110, + completion_tokens_details=None, + prompt_tokens_details=PromptTokensDetailsWrapper( + audio_tokens=None, + cached_tokens=0, + text_tokens=None, + image_tokens=None + ), + cache_creation_input_tokens=0, + cache_read_input_tokens=0 + ) +) +``` + +### Pass `thinking` to Anthropic models + +You can also pass the `thinking` parameter to Anthropic models. + + +You can also pass the `thinking` parameter to Anthropic models. + + + + +```python +response = litellm.completion( + model="anthropic/claude-3-7-sonnet-20250219", + messages=[{"role": "user", "content": "What is the capital of France?"}], + thinking={"type": "enabled", "budget_tokens": 1024}, +) +``` + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "anthropic/claude-3-7-sonnet-20250219", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "thinking": {"type": "enabled", "budget_tokens": 1024} + }' +``` + + + + + + + ## **Passing Extra Headers to Anthropic API** Pass `extra_headers: dict` to `litellm.completion` @@ -927,8 +1284,10 @@ response = completion( "content": [ {"type": "text", "text": "You are a very professional document summarization specialist. Please summarize the given document."}, { - "type": "image_url", - "image_url": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + "type": "file", + "file": { + "file_data": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + } }, ], } @@ -939,7 +1298,7 @@ response = completion( print(response.choices[0]) ``` - + 1. Add model to config @@ -973,8 +1332,10 @@ curl http://0.0.0.0:4000/v1/chat/completions \ "text": "You are a very professional document summarization specialist. Please summarize the given document" }, { - "type": "image_url", - "image_url": "data:application/pdf;base64,{encoded_file}" # 👈 PDF + "type": "file", + "file": { + "file_data": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + } } } ] @@ -987,6 +1348,106 @@ curl http://0.0.0.0:4000/v1/chat/completions \ +## [BETA] Citations API + +Pass `citations: {"enabled": true}` to Anthropic, to get citations on your document responses. + +Note: This interface is in BETA. If you have feedback on how citations should be returned, please [tell us here](https://github.com/BerriAI/litellm/issues/7970#issuecomment-2644437943) + + + + +```python +from litellm import completion + +resp = completion( + model="claude-3-5-sonnet-20241022", + messages=[ + { + "role": "user", + "content": [ + { + "type": "document", + "source": { + "type": "text", + "media_type": "text/plain", + "data": "The grass is green. The sky is blue.", + }, + "title": "My Document", + "context": "This is a trustworthy document.", + "citations": {"enabled": True}, + }, + { + "type": "text", + "text": "What color is the grass and sky?", + }, + ], + } + ], +) + +citations = resp.choices[0].message.provider_specific_fields["citations"] + +assert citations is not None +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: anthropic-claude + litellm_params: + model: anthropic/claude-3-5-sonnet-20241022 + api_key: os.environ/ANTHROPIC_API_KEY +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "anthropic-claude", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "document", + "source": { + "type": "text", + "media_type": "text/plain", + "data": "The grass is green. The sky is blue.", + }, + "title": "My Document", + "context": "This is a trustworthy document.", + "citations": {"enabled": True}, + }, + { + "type": "text", + "text": "What color is the grass and sky?", + }, + ], + } + ] +}' +``` + + + + ## Usage - passing 'user_id' to Anthropic LiteLLM translates the OpenAI `user` param to Anthropic's `metadata[user_id]` param. @@ -1035,3 +1496,4 @@ curl http://0.0.0.0:4000/v1/chat/completions \ + diff --git a/docs/my-website/docs/providers/azure.md b/docs/my-website/docs/providers/azure/azure.md similarity index 84% rename from docs/my-website/docs/providers/azure.md rename to docs/my-website/docs/providers/azure/azure.md index 111738a4495..d0b03719868 100644 --- a/docs/my-website/docs/providers/azure.md +++ b/docs/my-website/docs/providers/azure/azure.md @@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem'; |-------|-------| | Description | Azure OpenAI Service provides REST API access to OpenAI's powerful language models including o1, o1-mini, GPT-4o, GPT-4o mini, GPT-4 Turbo with Vision, GPT-4, GPT-3.5-Turbo, and Embeddings model series | | Provider Route on LiteLLM | `azure/`, [`azure/o_series/`](#azure-o-series-models) | -| Supported Operations | [`/chat/completions`](#azure-openai-chat-completion-models), [`/completions`](#azure-instruct-models), [`/embeddings`](../embedding/supported_embedding#azure-openai-embedding-models), [`/audio/speech`](#azure-text-to-speech-tts), [`/audio/transcriptions`](../audio_transcription), `/fine_tuning`, [`/batches`](#azure-batches-api), `/files`, [`/images`](../image_generation#azure-openai-image-generation-models) | +| Supported Operations | [`/chat/completions`](#azure-openai-chat-completion-models), [`/completions`](#azure-instruct-models), [`/embeddings`](./azure_embedding), [`/audio/speech`](#azure-text-to-speech-tts), [`/audio/transcriptions`](../audio_transcription), `/fine_tuning`, [`/batches`](#azure-batches-api), `/files`, [`/images`](../image_generation#azure-openai-image-generation-models) | | Link to Provider Doc | [Azure OpenAI ↗](https://learn.microsoft.com/en-us/azure/ai-services/openai/overview) ## API Keys, Params @@ -291,14 +291,15 @@ response = completion( ) ``` -## Azure O1 Models +## O-Series Models -| Model Name | Function Call | -|---------------------|----------------------------------------------------| -| o1-mini | `response = completion(model="azure/", messages=messages)` | -| o1-preview | `response = completion(model="azure/", messages=messages)` | +Azure OpenAI O-Series models are supported on LiteLLM. -Set `litellm.enable_preview_features = True` to use Azure O1 Models with streaming support. +LiteLLM routes any deployment name with `o1` or `o3` in the model name, to the O-Series [transformation](https://github.com/BerriAI/litellm/blob/91ed05df2962b8eee8492374b048d27cc144d08c/litellm/llms/azure/chat/o1_transformation.py#L4) logic. + +To set this explicitly, set `model` to `azure/o_series/`. + +**Automatic Routing** @@ -306,60 +307,112 @@ Set `litellm.enable_preview_features = True` to use Azure O1 Models with streami ```python import litellm -litellm.enable_preview_features = True # 👈 KEY CHANGE - -response = litellm.completion( - model="azure/", - messages=[{"role": "user", "content": "What is the weather like in Boston?"}], - stream=True -) - -for chunk in response: - print(chunk) +litellm.completion(model="azure/my-o3-deployment", messages=[{"role": "user", "content": "Hello, world!"}]) # 👈 Note: 'o3' in the deployment name ``` - + -1. Setup config.yaml ```yaml model_list: - - model_name: o1-mini + - model_name: o3-mini litellm_params: - model: azure/o1-mini - api_base: "os.environ/AZURE_API_BASE" - api_key: "os.environ/AZURE_API_KEY" - api_version: "os.environ/AZURE_API_VERSION" - -litellm_settings: - enable_preview_features: true # 👈 KEY CHANGE + model: azure/o3-model + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY ``` -2. Start proxy + + + +**Explicit Routing** + + + + +```python +import litellm + +litellm.completion(model="azure/o_series/my-random-deployment-name", messages=[{"role": "user", "content": "Hello, world!"}]) # 👈 Note: 'o_series/' in the deployment name +``` + + + +```yaml +model_list: + - model_name: o3-mini + litellm_params: + model: azure/o_series/my-random-deployment-name + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY +``` + + + + +## Azure Audio Model + + + + +```python +from litellm import completion +import os + +os.environ["AZURE_API_KEY"] = "" +os.environ["AZURE_API_BASE"] = "" +os.environ["AZURE_API_VERSION"] = "" + +response = completion( + model="azure/azure-openai-4o-audio", + messages=[ + { + "role": "user", + "content": "I want to try out speech to speech" + } + ], + modalities=["text","audio"], + audio={"voice": "alloy", "format": "wav"} +) + +print(response) +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: azure-openai-4o-audio + litellm_params: + model: azure/azure-openai-4o-audio + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY + api_version: os.environ/AZURE_API_VERSION +``` + +2. Start proxy ```bash litellm --config /path/to/config.yaml ``` -3. Test it +3. Test it! -```python -import openai -client = openai.OpenAI( - api_key="anything", - base_url="http://0.0.0.0:4000" -) -response = client.chat.completions.create(model="o1-mini", messages = [ - { - "role": "user", - "content": "this is a test request, write a short poem" - } -], -stream=True) - -for chunk in response: - print(chunk) +```bash +curl http://localhost:4000/v1/chat/completions \ + -H "Authorization: Bearer $LITELLM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "azure-openai-4o-audio", + "messages": [{"role": "user", "content": "I want to try out speech to speech"}], + "modalities": ["text","audio"], + "audio": {"voice": "alloy", "format": "wav"} + }' ``` + + @@ -425,12 +478,12 @@ response.stream_to_file(speech_file_path) ## **Authentication** -### Entrata ID - use `azure_ad_token` +### Entra ID - use `azure_ad_token` This is a walkthrough on how to use Azure Active Directory Tokens - Microsoft Entra ID to make `litellm.completion()` calls Step 1 - Download Azure CLI -Installation instructons: https://learn.microsoft.com/en-us/cli/azure/install-azure-cli +Installation instructions: https://learn.microsoft.com/en-us/cli/azure/install-azure-cli ```shell brew update && brew install azure-cli ``` @@ -492,7 +545,7 @@ model_list: -### Entrata ID - use tenant_id, client_id, client_secret +### Entra ID - use tenant_id, client_id, client_secret Here is an example of setting up `tenant_id`, `client_id`, `client_secret` in your litellm proxy `config.yaml` ```yaml @@ -528,7 +581,7 @@ Example video of using `tenant_id`, `client_id`, `client_secret` with LiteLLM Pr -### Entrata ID - use client_id, username, password +### Entra ID - use client_id, username, password Here is an example of setting up `client_id`, `azure_username`, `azure_password` in your litellm proxy `config.yaml` ```yaml @@ -948,60 +1001,124 @@ Expected Response: {"data":[{"id":"batch_R3V...} ``` -## O-Series Models -Azure OpenAI O-Series models are supported on LiteLLM. +## **Azure Responses API** -LiteLLM routes any deployment name with `o1` or `o3` in the model name, to the O-Series [transformation](https://github.com/BerriAI/litellm/blob/91ed05df2962b8eee8492374b048d27cc144d08c/litellm/llms/azure/chat/o1_transformation.py#L4) logic. +| Property | Details | +|-------|-------| +| Description | Azure OpenAI Responses API | +| `custom_llm_provider` on LiteLLM | `azure/` | +| Supported Operations | `/v1/responses`| +| Azure OpenAI Responses API | [Azure OpenAI Responses API ↗](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/responses?tabs=python-secure) | +| Cost Tracking, Logging Support | ✅ LiteLLM will log, track cost for Responses API Requests | +| Supported OpenAI Params | ✅ All OpenAI params are supported, [See here](https://github.com/BerriAI/litellm/blob/0717369ae6969882d149933da48eeb8ab0e691bd/litellm/llms/openai/responses/transformation.py#L23) | -To set this explicitly, set `model` to `azure/o_series/`. +## Usage -**Automatic Routing** +## Create a model response - + -```python +#### Non-streaming + +```python showLineNumbers title="Azure Responses API" import litellm -litellm.completion(model="azure/my-o3-deployment", messages=[{"role": "user", "content": "Hello, world!"}]) # 👈 Note: 'o3' in the deployment name -``` - - +# Non-streaming response +response = litellm.responses( + model="azure/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100, + api_key=os.getenv("AZURE_RESPONSES_OPENAI_API_KEY"), + api_base="https://litellm8397336933.openai.azure.com/", + api_version="2023-03-15-preview", +) -```yaml -model_list: - - model_name: o3-mini - litellm_params: - model: azure/o3-model - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY +print(response) ``` - - - -**Explicit Routing** - - - - -```python +#### Streaming +```python showLineNumbers title="Azure Responses API" import litellm -litellm.completion(model="azure/o_series/my-random-deployment-name", messages=[{"role": "user", "content": "Hello, world!"}]) # 👈 Note: 'o_series/' in the deployment name -``` - - +# Streaming response +response = litellm.responses( + model="azure/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True, + api_key=os.getenv("AZURE_RESPONSES_OPENAI_API_KEY"), + api_base="https://litellm8397336933.openai.azure.com/", + api_version="2023-03-15-preview", +) -```yaml -model_list: - - model_name: o3-mini - litellm_params: - model: azure/o_series/my-random-deployment-name - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY +for event in response: + print(event) ``` + + + + +First, add this to your litellm proxy config.yaml: +```yaml showLineNumbers title="Azure Responses API" +model_list: + - model_name: o1-pro + litellm_params: + model: azure/o1-pro + api_key: os.environ/AZURE_RESPONSES_OPENAI_API_KEY + api_base: https://litellm8397336933.openai.azure.com/ + api_version: 2023-03-15-preview +``` + +Start your LiteLLM proxy: +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +Then use the OpenAI SDK pointed to your proxy: + +#### Non-streaming +```python showLineNumbers +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + @@ -1076,32 +1193,24 @@ print(response) ``` -### Parallel Function calling +### Tool Calling / Function Calling + See a detailed walthrough of parallel function calling with litellm [here](https://docs.litellm.ai/docs/completion/function_call) + + + + + ```python # set Azure env variables import os +import litellm +import json + os.environ['AZURE_API_KEY'] = "" # litellm reads AZURE_API_KEY from .env and sends the request os.environ['AZURE_API_BASE'] = "https://openai-gpt-4-test-v-1.openai.azure.com/" os.environ['AZURE_API_VERSION'] = "2023-07-01-preview" -import litellm -import json -# Example dummy function hard coded to return the same weather -# In production, this could be your backend API or an external API -def get_current_weather(location, unit="fahrenheit"): - """Get the current weather in a given location""" - if "tokyo" in location.lower(): - return json.dumps({"location": "Tokyo", "temperature": "10", "unit": "celsius"}) - elif "san francisco" in location.lower(): - return json.dumps({"location": "San Francisco", "temperature": "72", "unit": "fahrenheit"}) - elif "paris" in location.lower(): - return json.dumps({"location": "Paris", "temperature": "22", "unit": "celsius"}) - else: - return json.dumps({"location": location, "temperature": "unknown"}) - -## Step 1: send the conversation and available functions to the model -messages = [{"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris?"}] tools = [ { "type": "function", @@ -1125,7 +1234,7 @@ tools = [ response = litellm.completion( model="azure/chatgpt-functioncalling", # model = azure/ - messages=messages, + messages=[{"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris?"}], tools=tools, tool_choice="auto", # auto is default, but we'll be explicit ) @@ -1134,8 +1243,49 @@ response_message = response.choices[0].message tool_calls = response.choices[0].message.tool_calls print("\nTool Choice:\n", tool_calls) ``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: azure-gpt-3.5 + litellm_params: + model: azure/chatgpt-functioncalling + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY + api_version: "2023-07-01-preview" +``` + +2. Start proxy + +```bash +litellm --config config.yaml +``` + +3. Test it + +```bash +curl -L -X POST 'http://localhost:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "azure-gpt-3.5", + "messages": [ + { + "role": "user", + "content": "Hey, how'\''s it going? Thinking long and hard before replying - what is the meaning of the world and life itself" + } + ] +}' +``` + + + + ### Spend Tracking for Azure OpenAI Models (PROXY) Set base model for cost tracking azure image-gen call diff --git a/docs/my-website/docs/providers/azure/azure_embedding.md b/docs/my-website/docs/providers/azure/azure_embedding.md new file mode 100644 index 00000000000..03bb501f36f --- /dev/null +++ b/docs/my-website/docs/providers/azure/azure_embedding.md @@ -0,0 +1,93 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Azure OpenAI Embeddings + +### API keys +This can be set as env variables or passed as **params to litellm.embedding()** +```python +import os +os.environ['AZURE_API_KEY'] = +os.environ['AZURE_API_BASE'] = +os.environ['AZURE_API_VERSION'] = +``` + +### Usage +```python +from litellm import embedding +response = embedding( + model="azure/", + input=["good morning from litellm"], + api_key=api_key, + api_base=api_base, + api_version=api_version, +) +print(response) +``` + +| Model Name | Function Call | +|----------------------|---------------------------------------------| +| text-embedding-ada-002 | `embedding(model="azure/", input=input)` | + +h/t to [Mikko](https://www.linkedin.com/in/mikkolehtimaki/) for this integration + + +## **Usage - LiteLLM Proxy Server** + +Here's how to call Azure OpenAI models with the LiteLLM Proxy Server + +### 1. Save key in your environment + +```bash +export AZURE_API_KEY="" +``` + +### 2. Start the proxy + +```yaml +model_list: + - model_name: text-embedding-ada-002 + litellm_params: + model: azure/my-deployment-name + api_base: https://openai-gpt-4-test-v-1.openai.azure.com/ + api_version: "2023-05-15" + api_key: os.environ/AZURE_API_KEY # The `os.environ/` prefix tells litellm to read this from the env. +``` + +### 3. Test it + + + + +```shell +curl --location 'http://0.0.0.0:4000/embeddings' \ + --header 'Content-Type: application/json' \ + --data ' { + "model": "text-embedding-ada-002", + "input": ["write a litellm poem"] + }' +``` + + + +```python +import openai +from openai import OpenAI + +# set base_url to your proxy server +# set api_key to send to proxy server +client = OpenAI(api_key="", base_url="http://0.0.0.0:4000") + +response = client.embeddings.create( + input=["hello from litellm"], + model="text-embedding-ada-002" +) + +print(response) + +``` + + + + diff --git a/docs/my-website/docs/providers/bedrock.md b/docs/my-website/docs/providers/bedrock.md index ad2124676fd..8217f429ff3 100644 --- a/docs/my-website/docs/providers/bedrock.md +++ b/docs/my-website/docs/providers/bedrock.md @@ -7,9 +7,10 @@ ALL Bedrock models (Anthropic, Meta, Deepseek, Mistral, Amazon, etc.) are Suppor | Property | Details | |-------|-------| | Description | Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs). | -| Provider Route on LiteLLM | `bedrock/`, [`bedrock/converse/`](#set-converse--invoke-route), [`bedrock/invoke/`](#set-invoke-route), [`bedrock/converse_like/`](#calling-via-internal-proxy), [`bedrock/llama/`](#bedrock-imported-models-deepseek) | +| Provider Route on LiteLLM | `bedrock/`, [`bedrock/converse/`](#set-converse--invoke-route), [`bedrock/invoke/`](#set-invoke-route), [`bedrock/converse_like/`](#calling-via-internal-proxy), [`bedrock/llama/`](#deepseek-not-r1), [`bedrock/deepseek_r1/`](#deepseek-r1) | | Provider Doc | [Amazon Bedrock ↗](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) | | Supported OpenAI Endpoints | `/chat/completions`, `/completions`, `/embeddings`, `/images/generations` | +| Rerank Endpoint | `/rerank` | | Pass-through Endpoint | [Supported](../pass_through/bedrock.md) | @@ -59,12 +60,12 @@ Here's how to call Bedrock with the LiteLLM Proxy Server ```yaml model_list: - - model_name: bedrock-claude-v1 + - model_name: bedrock-claude-3-5-sonnet litellm_params: - model: bedrock/anthropic.claude-instant-v1 - aws_access_key_id: os.environ/CUSTOM_AWS_ACCESS_KEY_ID - aws_secret_access_key: os.environ/CUSTOM_AWS_SECRET_ACCESS_KEY - aws_region_name: os.environ/CUSTOM_AWS_REGION_NAME + model: bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0 + aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID + aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY + aws_region_name: os.environ/AWS_REGION_NAME ``` All possible auth params: @@ -78,6 +79,7 @@ aws_session_name: Optional[str], aws_profile_name: Optional[str], aws_role_name: Optional[str], aws_web_identity_token: Optional[str], +aws_bedrock_runtime_endpoint: Optional[str], ``` ### 2. Start the proxy @@ -285,9 +287,12 @@ print(response) -## Usage - Function Calling +## Usage - Function Calling / Tool calling -LiteLLM uses Bedrock's Converse API for making tool calls +LiteLLM supports tool calling via Bedrock's Converse and Invoke API's. + + + ```python from litellm import completion @@ -332,6 +337,69 @@ assert isinstance( response.choices[0].message.tool_calls[0].function.arguments, str ) ``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-claude-3-7 + litellm_params: + model: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0 # for bedrock invoke, specify `bedrock/invoke/` +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer $LITELLM_API_KEY" \ +-d '{ + "model": "bedrock-claude-3-7", + "messages": [ + { + "role": "user", + "content": "What'\''s the weather like in Boston today?" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA" + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"] + } + }, + "required": ["location"] + } + } + } + ], + "tool_choice": "auto" +}' + +``` + + + + ## Usage - Vision @@ -376,6 +444,282 @@ print(f"\nResponse: {resp}") ``` +## Usage - 'thinking' / 'reasoning content' + +This is currently only supported for Anthropic's Claude 3.7 Sonnet + Deepseek R1. + +Works on v1.61.20+. + +Returns 2 new fields in `message` and `delta` object: +- `reasoning_content` - string - The reasoning content of the response +- `thinking_blocks` - list of objects (Anthropic only) - The thinking blocks of the response + +Each object has the following fields: +- `type` - Literal["thinking"] - The type of thinking block +- `thinking` - string - The thinking of the response. Also returned in `reasoning_content` +- `signature` - string - A base64 encoded string, returned by Anthropic. + +The `signature` is required by Anthropic on subsequent calls, if 'thinking' content is passed in (only required to use `thinking` with tool calling). [Learn more](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#understanding-thinking-blocks) + + + + +```python +from litellm import completion + +# set env +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + + +resp = completion( + model="bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", +) + +print(resp) +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-claude-3-7 + litellm_params: + model: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0 + reasoning_effort: "low" # 👈 EITHER HERE OR ON REQUEST +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "model": "bedrock-claude-3-7", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "reasoning_effort": "low" # 👈 EITHER HERE OR ON CONFIG.YAML + }' +``` + + + + + +**Expected Response** + +Same as [Anthropic API response](../providers/anthropic#usage---thinking--reasoning_content). + +```python +{ + "id": "chatcmpl-c661dfd7-7530-49c9-b0cc-d5018ba4727d", + "created": 1740640366, + "model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0", + "object": "chat.completion", + "system_fingerprint": null, + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "The capital of France is Paris. It's not only the capital city but also the largest city in France, serving as the country's major cultural, economic, and political center.", + "role": "assistant", + "tool_calls": null, + "function_call": null, + "reasoning_content": "The capital of France is Paris. This is a straightforward factual question.", + "thinking_blocks": [ + { + "type": "thinking", + "thinking": "The capital of France is Paris. This is a straightforward factual question.", + "signature": "EqoBCkgIARABGAIiQL2UoU0b1OHYi+yCHpBY7U6FQW8/FcoLewocJQPa2HnmLM+NECy50y44F/kD4SULFXi57buI9fAvyBwtyjlOiO0SDE3+r3spdg6PLOo9PBoMma2ku5OTAoR46j9VIjDRlvNmBvff7YW4WI9oU8XagaOBSxLPxElrhyuxppEn7m6bfT40dqBSTDrfiw4FYB4qEPETTI6TA6wtjGAAqmFqKTo=" + } + ] + } + } + ], + "usage": { + "completion_tokens": 64, + "prompt_tokens": 42, + "total_tokens": 106, + "completion_tokens_details": null, + "prompt_tokens_details": null + } +} +``` + +### Pass `thinking` to Anthropic models + +Same as [Anthropic API response](../providers/anthropic#usage---thinking--reasoning_content). + + +## Usage - Structured Output / JSON mode + + + + +```python +from litellm import completion +import os +from pydantic import BaseModel + +# set env +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + +class CalendarEvent(BaseModel): + name: str + date: str + participants: list[str] + +class EventsList(BaseModel): + events: list[CalendarEvent] + +response = completion( + model="bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0", # specify invoke via `bedrock/invoke/anthropic.claude-3-7-sonnet-20250219-v1:0` + response_format=EventsList, + messages=[ + {"role": "system", "content": "You are a helpful assistant designed to output JSON."}, + {"role": "user", "content": "Who won the world series in 2020?"} + ], +) +print(response.choices[0].message.content) +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-claude-3-7 + litellm_params: + model: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0 # specify invoke via `bedrock/invoke/` + aws_access_key_id: os.environ/CUSTOM_AWS_ACCESS_KEY_ID + aws_secret_access_key: os.environ/CUSTOM_AWS_SECRET_ACCESS_KEY + aws_region_name: os.environ/CUSTOM_AWS_REGION_NAME +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "bedrock-claude-3-7", + "messages": [ + { + "role": "system", + "content": "You are a helpful assistant designed to output JSON." + }, + { + "role": "user", + "content": "Who won the worlde series in 2020?" + } + ], + "response_format": { + "type": "json_schema", + "json_schema": { + "name": "math_reasoning", + "description": "reason about maths", + "schema": { + "type": "object", + "properties": { + "steps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "explanation": { "type": "string" }, + "output": { "type": "string" } + }, + "required": ["explanation", "output"], + "additionalProperties": false + } + }, + "final_answer": { "type": "string" } + }, + "required": ["steps", "final_answer"], + "additionalProperties": false + }, + "strict": true + } + } + }' +``` + + + +## Usage - Latency Optimized Inference + +Valid from v1.65.1+ + + + + +```python +from litellm import completion + +response = completion( + model="bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0", + messages=[{"role": "user", "content": "What is the capital of France?"}], + performanceConfig={"latency": "optimized"}, +) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-claude-3-7 + litellm_params: + model: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0 + performanceConfig: {"latency": "optimized"} # 👈 EITHER HERE OR ON REQUEST +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "bedrock-claude-3-7", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "performanceConfig": {"latency": "optimized"} # 👈 EITHER HERE OR ON CONFIG.YAML + }' +``` + + + + ## Usage - Bedrock Guardrails Example of using [Bedrock Guardrails with LiteLLM](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-use-converse-api.html) @@ -828,14 +1172,22 @@ os.environ["AWS_REGION_NAME"] = "" # pdf url image_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" +# Download the file +response = requests.get(url) +file_data = response.content + +encoded_file = base64.b64encode(file_data).decode("utf-8") + # model model = "bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0" image_content = [ {"type": "text", "text": "What's this file about?"}, { - "type": "image_url", - "image_url": image_url, # OR {"url": image_url} + "type": "file", + "file": { + "file_data": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + } }, ] @@ -881,8 +1233,10 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ "messages": [ {"role": "user", "content": {"type": "text", "text": "What's this file about?"}}, { - "type": "image_url", - "image_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", + "type": "file", + "file": { + "file_data": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + } } ] }' @@ -975,6 +1329,477 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +## Bedrock Imported Models (Deepseek, Deepseek R1) + +### Deepseek R1 + +This is a separate route, as the chat template is different. + +| Property | Details | +|----------|---------| +| Provider Route | `bedrock/deepseek_r1/{model_arn}` | +| Provider Documentation | [Bedrock Imported Models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-import-model.html), [Deepseek Bedrock Imported Model](https://aws.amazon.com/blogs/machine-learning/deploy-deepseek-r1-distilled-llama-models-with-amazon-bedrock-custom-model-import/) | + + + + +```python +from litellm import completion +import os + +response = completion( + model="bedrock/deepseek_r1/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n", # bedrock/deepseek_r1/{your-model-arn} + messages=[{"role": "user", "content": "Tell me a joke"}], +) +``` + + + + + + +**1. Add to config** + +```yaml +model_list: + - model_name: DeepSeek-R1-Distill-Llama-70B + litellm_params: + model: bedrock/deepseek_r1/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n + +``` + +**2. Start proxy** + +```bash +litellm --config /path/to/config.yaml + +# RUNNING at http://0.0.0.0:4000 +``` + +**3. Test it!** + +```bash +curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Authorization: Bearer sk-1234' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "DeepSeek-R1-Distill-Llama-70B", # 👈 the 'model_name' in config + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ], + }' +``` + + + + + +### Deepseek (not R1) + +| Property | Details | +|----------|---------| +| Provider Route | `bedrock/llama/{model_arn}` | +| Provider Documentation | [Bedrock Imported Models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-import-model.html), [Deepseek Bedrock Imported Model](https://aws.amazon.com/blogs/machine-learning/deploy-deepseek-r1-distilled-llama-models-with-amazon-bedrock-custom-model-import/) | + + + +Use this route to call Bedrock Imported Models that follow the `llama` Invoke Request / Response spec + + + + + +```python +from litellm import completion +import os + +response = completion( + model="bedrock/llama/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n", # bedrock/llama/{your-model-arn} + messages=[{"role": "user", "content": "Tell me a joke"}], +) +``` + + + + + + +**1. Add to config** + +```yaml +model_list: + - model_name: DeepSeek-R1-Distill-Llama-70B + litellm_params: + model: bedrock/llama/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n + +``` + +**2. Start proxy** + +```bash +litellm --config /path/to/config.yaml + +# RUNNING at http://0.0.0.0:4000 +``` + +**3. Test it!** + +```bash +curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Authorization: Bearer sk-1234' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "DeepSeek-R1-Distill-Llama-70B", # 👈 the 'model_name' in config + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ], + }' +``` + + + + + + +## Provisioned throughput models +To use provisioned throughput Bedrock models pass +- `model=bedrock/`, example `model=bedrock/anthropic.claude-v2`. Set `model` to any of the [Supported AWS models](#supported-aws-bedrock-models) +- `model_id=provisioned-model-arn` + +Completion +```python +import litellm +response = litellm.completion( + model="bedrock/anthropic.claude-instant-v1", + model_id="provisioned-model-arn", + messages=[{"content": "Hello, how are you?", "role": "user"}] +) +``` + +Embedding +```python +import litellm +response = litellm.embedding( + model="bedrock/amazon.titan-embed-text-v1", + model_id="provisioned-model-arn", + input=["hi"], +) +``` + + +## Supported AWS Bedrock Models + +LiteLLM supports ALL Bedrock models. + +Here's an example of using a bedrock model with LiteLLM. For a complete list, refer to the [model cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) + +| Model Name | Command | +|----------------------------|------------------------------------------------------------------| +| Deepseek R1 | `completion(model='bedrock/us.deepseek.r1-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-V3.5 Sonnet | `completion(model='bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-V3 sonnet | `completion(model='bedrock/anthropic.claude-3-sonnet-20240229-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-V3 Haiku | `completion(model='bedrock/anthropic.claude-3-haiku-20240307-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-V3 Opus | `completion(model='bedrock/anthropic.claude-3-opus-20240229-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-V2.1 | `completion(model='bedrock/anthropic.claude-v2:1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-V2 | `completion(model='bedrock/anthropic.claude-v2', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Anthropic Claude-Instant V1 | `completion(model='bedrock/anthropic.claude-instant-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Meta llama3-1-405b | `completion(model='bedrock/meta.llama3-1-405b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Meta llama3-1-70b | `completion(model='bedrock/meta.llama3-1-70b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Meta llama3-1-8b | `completion(model='bedrock/meta.llama3-1-8b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Meta llama3-70b | `completion(model='bedrock/meta.llama3-70b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Meta llama3-8b | `completion(model='bedrock/meta.llama3-8b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | +| Amazon Titan Lite | `completion(model='bedrock/amazon.titan-text-lite-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| Amazon Titan Express | `completion(model='bedrock/amazon.titan-text-express-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| Cohere Command | `completion(model='bedrock/cohere.command-text-v14', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| AI21 J2-Mid | `completion(model='bedrock/ai21.j2-mid-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| AI21 J2-Ultra | `completion(model='bedrock/ai21.j2-ultra-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| AI21 Jamba-Instruct | `completion(model='bedrock/ai21.jamba-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| Meta Llama 2 Chat 13b | `completion(model='bedrock/meta.llama2-13b-chat-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| Meta Llama 2 Chat 70b | `completion(model='bedrock/meta.llama2-70b-chat-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| Mistral 7B Instruct | `completion(model='bedrock/mistral.mistral-7b-instruct-v0:2', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | +| Mixtral 8x7B Instruct | `completion(model='bedrock/mistral.mixtral-8x7b-instruct-v0:1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | + +## Bedrock Embedding + +### API keys +This can be set as env variables or passed as **params to litellm.embedding()** +```python +import os +os.environ["AWS_ACCESS_KEY_ID"] = "" # Access key +os.environ["AWS_SECRET_ACCESS_KEY"] = "" # Secret access key +os.environ["AWS_REGION_NAME"] = "" # us-east-1, us-east-2, us-west-1, us-west-2 +``` + +### Usage +```python +from litellm import embedding +response = embedding( + model="bedrock/amazon.titan-embed-text-v1", + input=["good morning from litellm"], +) +print(response) +``` + +## Supported AWS Bedrock Embedding Models + +| Model Name | Usage | Supported Additional OpenAI params | +|----------------------|---------------------------------------------|-----| +| Titan Embeddings V2 | `embedding(model="bedrock/amazon.titan-embed-text-v2:0", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/amazon_titan_v2_transformation.py#L59) | +| Titan Embeddings - V1 | `embedding(model="bedrock/amazon.titan-embed-text-v1", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/amazon_titan_g1_transformation.py#L53) +| Titan Multimodal Embeddings | `embedding(model="bedrock/amazon.titan-embed-image-v1", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/amazon_titan_multimodal_transformation.py#L28) | +| Cohere Embeddings - English | `embedding(model="bedrock/cohere.embed-english-v3", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/cohere_transformation.py#L18) +| Cohere Embeddings - Multilingual | `embedding(model="bedrock/cohere.embed-multilingual-v3", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/cohere_transformation.py#L18) + +### Advanced - [Drop Unsupported Params](https://docs.litellm.ai/docs/completion/drop_params#openai-proxy-usage) + +### Advanced - [Pass model/provider-specific Params](https://docs.litellm.ai/docs/completion/provider_specific_params#proxy-usage) + +## Image Generation +Use this for stable diffusion, and amazon nova canvas on bedrock + + +### Usage + + + + +```python +import os +from litellm import image_generation + +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + +response = image_generation( + prompt="A cute baby sea otter", + model="bedrock/stability.stable-diffusion-xl-v0", + ) +print(f"response: {response}") +``` + +**Set optional params** +```python +import os +from litellm import image_generation + +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + +response = image_generation( + prompt="A cute baby sea otter", + model="bedrock/stability.stable-diffusion-xl-v0", + ### OPENAI-COMPATIBLE ### + size="128x512", # width=128, height=512 + ### PROVIDER-SPECIFIC ### see `AmazonStabilityConfig` in bedrock.py for all params + seed=30 + ) +print(f"response: {response}") +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: amazon.nova-canvas-v1:0 + litellm_params: + model: bedrock/amazon.nova-canvas-v1:0 + aws_region_name: "us-east-1" + aws_secret_access_key: my-key # OPTIONAL - all boto3 auth params supported + aws_secret_access_id: my-id # OPTIONAL - all boto3 auth params supported +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/images/generations' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_VIRTUAL_KEY' \ +-d '{ + "model": "amazon.nova-canvas-v1:0", + "prompt": "A cute baby sea otter" +}' +``` + + + + +## Supported AWS Bedrock Image Generation Models + +| Model Name | Function Call | +|----------------------|---------------------------------------------| +| Stable Diffusion 3 - v0 | `embedding(model="bedrock/stability.stability.sd3-large-v1:0", prompt=prompt)` | +| Stable Diffusion - v0 | `embedding(model="bedrock/stability.stable-diffusion-xl-v0", prompt=prompt)` | +| Stable Diffusion - v0 | `embedding(model="bedrock/stability.stable-diffusion-xl-v1", prompt=prompt)` | + + +## Rerank API + +Use Bedrock's Rerank API in the Cohere `/rerank` format. + +Supported Cohere Rerank Params +- `model` - the foundation model ARN +- `query` - the query to rerank against +- `documents` - the list of documents to rerank +- `top_n` - the number of results to return + + + + +```python +from litellm import rerank +import os + +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + +response = rerank( + model="bedrock/arn:aws:bedrock:us-west-2::foundation-model/amazon.rerank-v1:0", # provide the model ARN - get this here https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock/client/list_foundation_models.html + query="hello", + documents=["hello", "world"], + top_n=2, +) + +print(response) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: bedrock-rerank + litellm_params: + model: bedrock/arn:aws:bedrock:us-west-2::foundation-model/amazon.rerank-v1:0 + aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID + aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY + aws_region_name: os.environ/AWS_REGION_NAME +``` + +2. Start proxy server + +```bash +litellm --config config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/rerank \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "bedrock-rerank", + "query": "What is the capital of the United States?", + "documents": [ + "Carson City is the capital city of the American state of Nevada.", + "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan.", + "Washington, D.C. is the capital of the United States.", + "Capital punishment has existed in the United States since before it was a country." + ], + "top_n": 3 + + + }' +``` + + + + + +## Bedrock Application Inference Profile + +Use Bedrock Application Inference Profile to track costs for projects on AWS. + +You can either pass it in the model name - `model="bedrock/arn:...` or as a separate `model_id="arn:..` param. + +### Set via `model_id` + + + + +```python +from litellm import completion +import os + +os.environ["AWS_ACCESS_KEY_ID"] = "" +os.environ["AWS_SECRET_ACCESS_KEY"] = "" +os.environ["AWS_REGION_NAME"] = "" + +response = completion( + model="bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0", + messages=[{"role": "user", "content": "Hello, how are you?"}], + model_id="arn:aws:bedrock:eu-central-1:000000000000:application-inference-profile/a0a0a0a0a0a0", +) + +print(response) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: anthropic-claude-3-5-sonnet + litellm_params: + model: bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0 + # You have to set the ARN application inference profile in the model_id parameter + model_id: arn:aws:bedrock:eu-central-1:000000000000:application-inference-profile/a0a0a0a0a0a0 +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_API_KEY' \ +-d '{ + "model": "anthropic-claude-3-5-sonnet", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "List 5 important events in the XIX century" + } + ] + } + ] +}' +``` + + + + ## Boto3 - Authentication ### Passing credentials as parameters - Completion() @@ -1017,6 +1842,7 @@ response = completion( ) ``` + 1. Setup config.yaml @@ -1061,11 +1887,13 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ ``` + ### SSO Login (AWS Profile) - Set `AWS_PROFILE` environment variable - Make bedrock completion call + ```python import os from litellm import completion @@ -1158,12 +1986,46 @@ model_list: +Text to Image : +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/images/generations' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_VIRTUAL_KEY' \ +-d '{ + "model": "amazon.nova-canvas-v1:0", + "prompt": "A cute baby sea otter" +}' +``` +Color Guided Generation: +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/images/generations' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer $LITELLM_VIRTUAL_KEY' \ +-d '{ + "model": "amazon.nova-canvas-v1:0", + "prompt": "A cute baby sea otter", + "taskType": "COLOR_GUIDED_GENERATION", + "colorGuidedGenerationParams":{"colors":["#FFFFFF"]} +}' +``` + +| Model Name | Function Call | +|-------------------------|---------------------------------------------| +| Stable Diffusion 3 - v0 | `image_generation(model="bedrock/stability.stability.sd3-large-v1:0", prompt=prompt)` | +| Stable Diffusion - v0 | `image_generation(model="bedrock/stability.stable-diffusion-xl-v0", prompt=prompt)` | +| Stable Diffusion - v1 | `image_generation(model="bedrock/stability.stable-diffusion-xl-v1", prompt=prompt)` | +| Amazon Nova Canvas - v0 | `image_generation(model="bedrock/amazon.nova-canvas-v1:0", prompt=prompt)` | + + ### Passing an external BedrockRuntime.Client as a parameter - Completion() + +This is a deprecated flow. Boto3 is not async. And boto3.client does not let us make the http call through httpx. Pass in your aws params through the method above 👆. [See Auth Code](https://github.com/BerriAI/litellm/blob/55a20c7cce99a93d36a82bf3ae90ba3baf9a7f89/litellm/llms/bedrock_httpx.py#L284) [Add new auth flow](https://github.com/BerriAI/litellm/issues) :::warning -This is a deprecated flow. Boto3 is not async. And boto3.client does not let us make the http call through httpx. Pass in your aws params through the method above 👆. [See Auth Code](https://github.com/BerriAI/litellm/blob/55a20c7cce99a93d36a82bf3ae90ba3baf9a7f89/litellm/llms/bedrock_httpx.py#L284) [Add new auth flow](https://github.com/BerriAI/litellm/issues) + + Experimental - 2024-Jun-23: @@ -1210,7 +2072,7 @@ response = completion( aws_bedrock_client=bedrock, ) ``` -## Calling via Internal Proxy +## Calling via Internal Proxy (not bedrock url compatible) Use the `bedrock/converse_like/model` endpoint to call bedrock converse model via your internal proxy. @@ -1276,287 +2138,3 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ ```bash https://some-api-url/models ``` - -## Bedrock Imported Models (Deepseek) - -| Property | Details | -|----------|---------| -| Provider Route | `bedrock/llama/{model_arn}` | -| Provider Documentation | [Bedrock Imported Models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-import-model.html), [Deepseek Bedrock Imported Model](https://aws.amazon.com/blogs/machine-learning/deploy-deepseek-r1-distilled-llama-models-with-amazon-bedrock-custom-model-import/) | - -Use this route to call Bedrock Imported Models that follow the `llama` Invoke Request / Response spec - - - - - -```python -from litellm import completion -import os - -response = completion( - model="bedrock/llama/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n", # bedrock/llama/{your-model-arn} - messages=[{"role": "user", "content": "Tell me a joke"}], -) -``` - - - - - - -**1. Add to config** - -```yaml -model_list: - - model_name: DeepSeek-R1-Distill-Llama-70B - litellm_params: - model: bedrock/llama/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n - -``` - -**2. Start proxy** - -```bash -litellm --config /path/to/config.yaml - -# RUNNING at http://0.0.0.0:4000 -``` - -**3. Test it!** - -```bash -curl --location 'http://0.0.0.0:4000/chat/completions' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "DeepSeek-R1-Distill-Llama-70B", # 👈 the 'model_name' in config - "messages": [ - { - "role": "user", - "content": "what llm are you" - } - ], - }' -``` - - - - - - -## Provisioned throughput models -To use provisioned throughput Bedrock models pass -- `model=bedrock/`, example `model=bedrock/anthropic.claude-v2`. Set `model` to any of the [Supported AWS models](#supported-aws-bedrock-models) -- `model_id=provisioned-model-arn` - -Completion -```python -import litellm -response = litellm.completion( - model="bedrock/anthropic.claude-instant-v1", - model_id="provisioned-model-arn", - messages=[{"content": "Hello, how are you?", "role": "user"}] -) -``` - -Embedding -```python -import litellm -response = litellm.embedding( - model="bedrock/amazon.titan-embed-text-v1", - model_id="provisioned-model-arn", - input=["hi"], -) -``` - - -## Supported AWS Bedrock Models -Here's an example of using a bedrock model with LiteLLM. For a complete list, refer to the [model cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) - -| Model Name | Command | -|----------------------------|------------------------------------------------------------------| -| Anthropic Claude-V3.5 Sonnet | `completion(model='bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Anthropic Claude-V3 sonnet | `completion(model='bedrock/anthropic.claude-3-sonnet-20240229-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Anthropic Claude-V3 Haiku | `completion(model='bedrock/anthropic.claude-3-haiku-20240307-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Anthropic Claude-V3 Opus | `completion(model='bedrock/anthropic.claude-3-opus-20240229-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Anthropic Claude-V2.1 | `completion(model='bedrock/anthropic.claude-v2:1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Anthropic Claude-V2 | `completion(model='bedrock/anthropic.claude-v2', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Anthropic Claude-Instant V1 | `completion(model='bedrock/anthropic.claude-instant-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Meta llama3-1-405b | `completion(model='bedrock/meta.llama3-1-405b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Meta llama3-1-70b | `completion(model='bedrock/meta.llama3-1-70b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Meta llama3-1-8b | `completion(model='bedrock/meta.llama3-1-8b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Meta llama3-70b | `completion(model='bedrock/meta.llama3-70b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Meta llama3-8b | `completion(model='bedrock/meta.llama3-8b-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']` | -| Amazon Titan Lite | `completion(model='bedrock/amazon.titan-text-lite-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| Amazon Titan Express | `completion(model='bedrock/amazon.titan-text-express-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| Cohere Command | `completion(model='bedrock/cohere.command-text-v14', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| AI21 J2-Mid | `completion(model='bedrock/ai21.j2-mid-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| AI21 J2-Ultra | `completion(model='bedrock/ai21.j2-ultra-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| AI21 Jamba-Instruct | `completion(model='bedrock/ai21.jamba-instruct-v1:0', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| Meta Llama 2 Chat 13b | `completion(model='bedrock/meta.llama2-13b-chat-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| Meta Llama 2 Chat 70b | `completion(model='bedrock/meta.llama2-70b-chat-v1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| Mistral 7B Instruct | `completion(model='bedrock/mistral.mistral-7b-instruct-v0:2', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | -| Mixtral 8x7B Instruct | `completion(model='bedrock/mistral.mixtral-8x7b-instruct-v0:1', messages=messages)` | `os.environ['AWS_ACCESS_KEY_ID']`, `os.environ['AWS_SECRET_ACCESS_KEY']`, `os.environ['AWS_REGION_NAME']` | - -## Bedrock Embedding - -### API keys -This can be set as env variables or passed as **params to litellm.embedding()** -```python -import os -os.environ["AWS_ACCESS_KEY_ID"] = "" # Access key -os.environ["AWS_SECRET_ACCESS_KEY"] = "" # Secret access key -os.environ["AWS_REGION_NAME"] = "" # us-east-1, us-east-2, us-west-1, us-west-2 -``` - -### Usage -```python -from litellm import embedding -response = embedding( - model="bedrock/amazon.titan-embed-text-v1", - input=["good morning from litellm"], -) -print(response) -``` - -## Supported AWS Bedrock Embedding Models - -| Model Name | Usage | Supported Additional OpenAI params | -|----------------------|---------------------------------------------|-----| -| Titan Embeddings V2 | `embedding(model="bedrock/amazon.titan-embed-text-v2:0", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/amazon_titan_v2_transformation.py#L59) | -| Titan Embeddings - V1 | `embedding(model="bedrock/amazon.titan-embed-text-v1", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/amazon_titan_g1_transformation.py#L53) -| Titan Multimodal Embeddings | `embedding(model="bedrock/amazon.titan-embed-image-v1", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/amazon_titan_multimodal_transformation.py#L28) | -| Cohere Embeddings - English | `embedding(model="bedrock/cohere.embed-english-v3", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/cohere_transformation.py#L18) -| Cohere Embeddings - Multilingual | `embedding(model="bedrock/cohere.embed-multilingual-v3", input=input)` | [here](https://github.com/BerriAI/litellm/blob/f5905e100068e7a4d61441d7453d7cf5609c2121/litellm/llms/bedrock/embed/cohere_transformation.py#L18) - -### Advanced - [Drop Unsupported Params](https://docs.litellm.ai/docs/completion/drop_params#openai-proxy-usage) - -### Advanced - [Pass model/provider-specific Params](https://docs.litellm.ai/docs/completion/provider_specific_params#proxy-usage) - -## Image Generation -Use this for stable diffusion on bedrock - - -### Usage -```python -import os -from litellm import image_generation - -os.environ["AWS_ACCESS_KEY_ID"] = "" -os.environ["AWS_SECRET_ACCESS_KEY"] = "" -os.environ["AWS_REGION_NAME"] = "" - -response = image_generation( - prompt="A cute baby sea otter", - model="bedrock/stability.stable-diffusion-xl-v0", - ) -print(f"response: {response}") -``` - -**Set optional params** -```python -import os -from litellm import image_generation - -os.environ["AWS_ACCESS_KEY_ID"] = "" -os.environ["AWS_SECRET_ACCESS_KEY"] = "" -os.environ["AWS_REGION_NAME"] = "" - -response = image_generation( - prompt="A cute baby sea otter", - model="bedrock/stability.stable-diffusion-xl-v0", - ### OPENAI-COMPATIBLE ### - size="128x512", # width=128, height=512 - ### PROVIDER-SPECIFIC ### see `AmazonStabilityConfig` in bedrock.py for all params - seed=30 - ) -print(f"response: {response}") -``` - -## Supported AWS Bedrock Image Generation Models - -| Model Name | Function Call | -|----------------------|---------------------------------------------| -| Stable Diffusion 3 - v0 | `embedding(model="bedrock/stability.stability.sd3-large-v1:0", prompt=prompt)` | -| Stable Diffusion - v0 | `embedding(model="bedrock/stability.stable-diffusion-xl-v0", prompt=prompt)` | -| Stable Diffusion - v0 | `embedding(model="bedrock/stability.stable-diffusion-xl-v1", prompt=prompt)` | - - -## Rerank API - -Use Bedrock's Rerank API in the Cohere `/rerank` format. - -Supported Cohere Rerank Params -- `model` - the foundation model ARN -- `query` - the query to rerank against -- `documents` - the list of documents to rerank -- `top_n` - the number of results to return - - - - -```python -from litellm import rerank -import os - -os.environ["AWS_ACCESS_KEY_ID"] = "" -os.environ["AWS_SECRET_ACCESS_KEY"] = "" -os.environ["AWS_REGION_NAME"] = "" - -response = rerank( - model="bedrock/arn:aws:bedrock:us-west-2::foundation-model/amazon.rerank-v1:0", # provide the model ARN - get this here https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock/client/list_foundation_models.html - query="hello", - documents=["hello", "world"], - top_n=2, -) - -print(response) -``` - - - - -1. Setup config.yaml - -```yaml -model_list: - - model_name: bedrock-rerank - litellm_params: - model: bedrock/arn:aws:bedrock:us-west-2::foundation-model/amazon.rerank-v1:0 - aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID - aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY - aws_region_name: os.environ/AWS_REGION_NAME -``` - -2. Start proxy server - -```bash -litellm --config config.yaml - -# RUNNING on http://0.0.0.0:4000 -``` - -3. Test it! - -```bash -curl http://0.0.0.0:4000/rerank \ - -H "Authorization: Bearer sk-1234" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "bedrock-rerank", - "query": "What is the capital of the United States?", - "documents": [ - "Carson City is the capital city of the American state of Nevada.", - "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan.", - "Washington, D.C. is the capital of the United States.", - "Capital punishment has existed in the United States since before it was a country." - ], - "top_n": 3 - }' -``` - - - - - diff --git a/docs/my-website/docs/providers/bedrock_vector_store.md b/docs/my-website/docs/providers/bedrock_vector_store.md new file mode 100644 index 00000000000..779c4fd0417 --- /dev/null +++ b/docs/my-website/docs/providers/bedrock_vector_store.md @@ -0,0 +1,144 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; + +# Bedrock Knowledge Bases + +AWS Bedrock Knowledge Bases allows you to connect your LLM's to your organization's data, letting your models retrieve and reference information specific to your business. + +| Property | Details | +|----------|---------| +| Description | Bedrock Knowledge Bases connects your data to LLM's, enabling them to retrieve and reference your organization's information in their responses. | +| Provider Route on LiteLLM | `bedrock` in the litellm vector_store_registry | +| Provider Doc | [AWS Bedrock Knowledge Bases ↗](https://aws.amazon.com/bedrock/knowledge-bases/) | + +## Quick Start + +### LiteLLM Python SDK + +```python showLineNumbers title="Example using LiteLLM Python SDK" +import os +import litellm + +from litellm.vector_stores.vector_store_registry import VectorStoreRegistry, LiteLLM_ManagedVectorStore + +# Init vector store registry with your Bedrock Knowledge Base +litellm.vector_store_registry = VectorStoreRegistry( + vector_stores=[ + LiteLLM_ManagedVectorStore( + vector_store_id="YOUR_KNOWLEDGE_BASE_ID", # KB ID from AWS Bedrock + custom_llm_provider="bedrock" + ) + ] +) + +# Make a completion request using your Knowledge Base +response = await litellm.acompletion( + model="anthropic/claude-3-5-sonnet", + messages=[{"role": "user", "content": "What does our company policy say about remote work?"}], + tools=[ + { + "type": "file_search", + "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"] + } + ], +) + +print(response.choices[0].message.content) +``` + +### LiteLLM Proxy + +#### 1. Configure your vector_store_registry + + + + +```yaml +model_list: + - model_name: claude-3-5-sonnet + litellm_params: + model: anthropic/claude-3-5-sonnet + api_key: os.environ/ANTHROPIC_API_KEY + +vector_store_registry: + - vector_store_name: "bedrock-company-docs" + litellm_params: + vector_store_id: "YOUR_KNOWLEDGE_BASE_ID" + custom_llm_provider: "bedrock" + vector_store_description: "Bedrock Knowledge Base for company documents" + vector_store_metadata: + source: "Company internal documentation" +``` + + + + + +On the LiteLLM UI, Navigate to Experimental > Vector Stores > Create Vector Store. On this page you can create a vector store with a name, vector store id and credentials. + + + + + + +#### 2. Make a request with vector_store_ids parameter + + + + +```bash +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_API_KEY" \ + -d '{ + "model": "claude-3-5-sonnet", + "messages": [{"role": "user", "content": "What does our company policy say about remote work?"}], + "tools": [ + { + "type": "file_search", + "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"] + } + ] + }' +``` + + + + + +```python +from openai import OpenAI + +# Initialize client with your LiteLLM proxy URL +client = OpenAI( + base_url="http://localhost:4000", + api_key="your-litellm-api-key" +) + +# Make a completion request with vector_store_ids parameter +response = client.chat.completions.create( + model="claude-3-5-sonnet", + messages=[{"role": "user", "content": "What does our company policy say about remote work?"}], + tools=[ + { + "type": "file_search", + "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"] + } + ] +) + +print(response.choices[0].message.content) +``` + + + + + +Futher Reading Vector Stores: +- [Always on Vector Stores](https://docs.litellm.ai/docs/completion/knowledgebase#always-on-for-a-model) +- [Listing available vector stores on litellm proxy](https://docs.litellm.ai/docs/completion/knowledgebase#listing-available-vector-stores) +- [How LiteLLM Vector Stores Work](https://docs.litellm.ai/docs/completion/knowledgebase#how-it-works) \ No newline at end of file diff --git a/docs/my-website/docs/providers/cerebras.md b/docs/my-website/docs/providers/cerebras.md index 4fabeb31cbc..33bef5e1079 100644 --- a/docs/my-website/docs/providers/cerebras.md +++ b/docs/my-website/docs/providers/cerebras.md @@ -23,14 +23,16 @@ import os os.environ['CEREBRAS_API_KEY'] = "" response = completion( - model="cerebras/meta/llama3-70b-instruct", + model="cerebras/llama3-70b-instruct", messages=[ { "role": "user", - "content": "What's the weather like in Boston today in Fahrenheit?", + "content": "What's the weather like in Boston today in Fahrenheit? (Write in JSON)", } ], max_tokens=10, + + # The prompt should include JSON if 'json_object' is selected; otherwise, you will get error code 400. response_format={ "type": "json_object" }, seed=123, stop=["\n\n"], @@ -50,16 +52,18 @@ import os os.environ['CEREBRAS_API_KEY'] = "" response = completion( - model="cerebras/meta/llama3-70b-instruct", + model="cerebras/llama3-70b-instruct", messages=[ { "role": "user", - "content": "What's the weather like in Boston today in Fahrenheit?", + "content": "What's the weather like in Boston today in Fahrenheit? (Write in JSON)", } ], stream=True, max_tokens=10, - response_format={ "type": "json_object" }, + + # The prompt should include JSON if 'json_object' is selected; otherwise, you will get error code 400. + response_format={ "type": "json_object" }, seed=123, stop=["\n\n"], temperature=0.2, diff --git a/docs/my-website/docs/providers/cohere.md b/docs/my-website/docs/providers/cohere.md index 1154dc3c4ea..9c424010570 100644 --- a/docs/my-website/docs/providers/cohere.md +++ b/docs/my-website/docs/providers/cohere.md @@ -13,7 +13,9 @@ os.environ["COHERE_API_KEY"] = "" ## Usage -```python +### LiteLLM Python SDK + +```python showLineNumbers from litellm import completion ## set ENV variables @@ -26,9 +28,9 @@ response = completion( ) ``` -## Usage - Streaming +#### Streaming -```python +```python showLineNumbers from litellm import completion ## set ENV variables @@ -46,15 +48,90 @@ for chunk in response: ``` + +## Usage with LiteLLM Proxy + +Here's how to call Cohere with the LiteLLM Proxy Server + +### 1. Save key in your environment + +```bash +export COHERE_API_KEY="your-api-key" +``` + +### 2. Start the proxy + +Define the cohere models you want to use in the config.yaml + +```yaml showLineNumbers +model_list: + - model_name: command-a-03-2025 + litellm_params: + model: command-a-03-2025 + api_key: "os.environ/COHERE_API_KEY" +``` + +```bash +litellm --config /path/to/config.yaml +``` + + +### 3. Test it + + + + + +```shell showLineNumbers +curl --location 'http://0.0.0.0:4000/chat/completions' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ' \ +--data ' { + "model": "command-a-03-2025", + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ] + } +' +``` + + + +```python showLineNumbers +import openai +client = openai.OpenAI( + api_key="anything", + base_url="http://0.0.0.0:4000" +) + +# request sent to model set on litellm proxy +response = client.chat.completions.create(model="command-a-03-2025", messages = [ + { + "role": "user", + "content": "this is a test request, write a short poem" + } +]) + +print(response) + +``` + + + + ## Supported Models | Model Name | Function Call | |------------|----------------| -| command-r-plus-08-2024 | `completion('command-r-plus-08-2024', messages)` | -| command-r-08-2024 | `completion('command-r-08-2024', messages)` | -| command-r-plus | `completion('command-r-plus', messages)` | -| command-r | `completion('command-r', messages)` | -| command-light | `completion('command-light', messages)` | -| command-nightly | `completion('command-nightly', messages)` | +| command-a-03-2025 | `litellm.completion('command-a-03-2025', messages)` | +| command-r-plus-08-2024 | `litellm.completion('command-r-plus-08-2024', messages)` | +| command-r-08-2024 | `litellm.completion('command-r-08-2024', messages)` | +| command-r-plus | `litellm.completion('command-r-plus', messages)` | +| command-r | `litellm.completion('command-r', messages)` | +| command-light | `litellm.completion('command-light', messages)` | +| command-nightly | `litellm.completion('command-nightly', messages)` | ## Embedding @@ -108,7 +185,7 @@ response = embedding( ### Usage - +LiteLLM supports the v1 and v2 clients for Cohere rerank. By default, the `rerank` endpoint uses the v2 client, but you can specify the v1 client by explicitly calling `v1/rerank` diff --git a/docs/my-website/docs/providers/databricks.md b/docs/my-website/docs/providers/databricks.md index 395a544db45..8631cbfdad9 100644 --- a/docs/my-website/docs/providers/databricks.md +++ b/docs/my-website/docs/providers/databricks.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# 🆕 Databricks +# Databricks LiteLLM supports all models on Databricks @@ -154,7 +154,205 @@ response = completion( temperature: 0.5 ``` -## Passings Databricks specific params - 'instruction' + +## Usage - Thinking / `reasoning_content` + +LiteLLM translates OpenAI's `reasoning_effort` to Anthropic's `thinking` parameter. [Code](https://github.com/BerriAI/litellm/blob/23051d89dd3611a81617d84277059cd88b2df511/litellm/llms/anthropic/chat/transformation.py#L298) + +| reasoning_effort | thinking | +| ---------------- | -------- | +| "low" | "budget_tokens": 1024 | +| "medium" | "budget_tokens": 2048 | +| "high" | "budget_tokens": 4096 | + + +Known Limitations: +- Support for passing thinking blocks back to Claude [Issue](https://github.com/BerriAI/litellm/issues/9790) + + + + + +```python +from litellm import completion +import os + +# set ENV variables (can also be passed in to .completion() - e.g. `api_base`, `api_key`) +os.environ["DATABRICKS_API_KEY"] = "databricks key" +os.environ["DATABRICKS_API_BASE"] = "databricks base url" + +resp = completion( + model="databricks/databricks-claude-3-7-sonnet", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", +) + +``` + + + + + +1. Setup config.yaml + +```yaml +- model_name: claude-3-7-sonnet + litellm_params: + model: databricks/databricks-claude-3-7-sonnet + api_key: os.environ/DATABRICKS_API_KEY + api_base: os.environ/DATABRICKS_API_BASE +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "model": "claude-3-7-sonnet", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "reasoning_effort": "low" + }' +``` + + + + + +**Expected Response** + +```python +ModelResponse( + id='chatcmpl-c542d76d-f675-4e87-8e5f-05855f5d0f5e', + created=1740470510, + model='claude-3-7-sonnet-20250219', + object='chat.completion', + system_fingerprint=None, + choices=[ + Choices( + finish_reason='stop', + index=0, + message=Message( + content="The capital of France is Paris.", + role='assistant', + tool_calls=None, + function_call=None, + provider_specific_fields={ + 'citations': None, + 'thinking_blocks': [ + { + 'type': 'thinking', + 'thinking': 'The capital of France is Paris. This is a very straightforward factual question.', + 'signature': 'EuYBCkQYAiJAy6...' + } + ] + } + ), + thinking_blocks=[ + { + 'type': 'thinking', + 'thinking': 'The capital of France is Paris. This is a very straightforward factual question.', + 'signature': 'EuYBCkQYAiJAy6AGB...' + } + ], + reasoning_content='The capital of France is Paris. This is a very straightforward factual question.' + ) + ], + usage=Usage( + completion_tokens=68, + prompt_tokens=42, + total_tokens=110, + completion_tokens_details=None, + prompt_tokens_details=PromptTokensDetailsWrapper( + audio_tokens=None, + cached_tokens=0, + text_tokens=None, + image_tokens=None + ), + cache_creation_input_tokens=0, + cache_read_input_tokens=0 + ) +) +``` + +### Pass `thinking` to Anthropic models + +You can also pass the `thinking` parameter to Anthropic models. + + +You can also pass the `thinking` parameter to Anthropic models. + + + + +```python +from litellm import completion +import os + +# set ENV variables (can also be passed in to .completion() - e.g. `api_base`, `api_key`) +os.environ["DATABRICKS_API_KEY"] = "databricks key" +os.environ["DATABRICKS_API_BASE"] = "databricks base url" + +response = litellm.completion( + model="databricks/databricks-claude-3-7-sonnet", + messages=[{"role": "user", "content": "What is the capital of France?"}], + thinking={"type": "enabled", "budget_tokens": 1024}, +) +``` + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "databricks/databricks-claude-3-7-sonnet", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "thinking": {"type": "enabled", "budget_tokens": 1024} + }' +``` + + + + + + + + +## Supported Databricks Chat Completion Models + +:::tip + +**We support ALL Databricks models, just set `model=databricks/` as a prefix when sending litellm requests** + +::: + + +| Model Name | Command | +|----------------------------|------------------------------------------------------------------| +| databricks/databricks-claude-3-7-sonnet | `completion(model='databricks/databricks/databricks-claude-3-7-sonnet', messages=messages)` | +| databricks-meta-llama-3-1-70b-instruct | `completion(model='databricks/databricks-meta-llama-3-1-70b-instruct', messages=messages)` | +| databricks-meta-llama-3-1-405b-instruct | `completion(model='databricks/databricks-meta-llama-3-1-405b-instruct', messages=messages)` | +| databricks-dbrx-instruct | `completion(model='databricks/databricks-dbrx-instruct', messages=messages)` | +| databricks-meta-llama-3-70b-instruct | `completion(model='databricks/databricks-meta-llama-3-70b-instruct', messages=messages)` | +| databricks-llama-2-70b-chat | `completion(model='databricks/databricks-llama-2-70b-chat', messages=messages)` | +| databricks-mixtral-8x7b-instruct | `completion(model='databricks/databricks-mixtral-8x7b-instruct', messages=messages)` | +| databricks-mpt-30b-instruct | `completion(model='databricks/databricks-mpt-30b-instruct', messages=messages)` | +| databricks-mpt-7b-instruct | `completion(model='databricks/databricks-mpt-7b-instruct', messages=messages)` | + + +## Embedding Models + +### Passing Databricks specific params - 'instruction' For embedding models, databricks lets you pass in an additional param 'instruction'. [Full Spec](https://github.com/BerriAI/litellm/blob/43353c28b341df0d9992b45c6ce464222ebd7984/litellm/llms/databricks.py#L164) @@ -187,27 +385,6 @@ response = litellm.embedding( instruction: "Represent this sentence for searching relevant passages:" ``` - -## Supported Databricks Chat Completion Models - -:::tip - -**We support ALL Databricks models, just set `model=databricks/` as a prefix when sending litellm requests** - -::: - - -| Model Name | Command | -|----------------------------|------------------------------------------------------------------| -| databricks-meta-llama-3-1-70b-instruct | `completion(model='databricks/databricks-meta-llama-3-1-70b-instruct', messages=messages)` | -| databricks-meta-llama-3-1-405b-instruct | `completion(model='databricks/databricks-meta-llama-3-1-405b-instruct', messages=messages)` | -| databricks-dbrx-instruct | `completion(model='databricks/databricks-dbrx-instruct', messages=messages)` | -| databricks-meta-llama-3-70b-instruct | `completion(model='databricks/databricks-meta-llama-3-70b-instruct', messages=messages)` | -| databricks-llama-2-70b-chat | `completion(model='databricks/databricks-llama-2-70b-chat', messages=messages)` | -| databricks-mixtral-8x7b-instruct | `completion(model='databricks/databricks-mixtral-8x7b-instruct', messages=messages)` | -| databricks-mpt-30b-instruct | `completion(model='databricks/databricks-mpt-30b-instruct', messages=messages)` | -| databricks-mpt-7b-instruct | `completion(model='databricks/databricks-mpt-7b-instruct', messages=messages)` | - ## Supported Databricks Embedding Models :::tip diff --git a/docs/my-website/docs/providers/featherless_ai.md b/docs/my-website/docs/providers/featherless_ai.md new file mode 100644 index 00000000000..5b9312e435d --- /dev/null +++ b/docs/my-website/docs/providers/featherless_ai.md @@ -0,0 +1,56 @@ +# Featherless AI +https://featherless.ai/ + +:::tip + +**We support ALL Featherless AI models, just set `model=featherless_ai/` as a prefix when sending litellm requests. For the complete supported model list, visit https://featherless.ai/models ** + +::: + + +## API Key +```python +# env variable +os.environ['FEATHERLESS_AI_API_KEY'] +``` + +## Sample Usage +```python +from litellm import completion +import os + +os.environ['FEATHERLESS_AI_API_KEY'] = "" +response = completion( + model="featherless_ai/featherless-ai/Qwerky-72B", + messages=[{"role": "user", "content": "write code for saying hi from LiteLLM"}] +) +``` + +## Sample Usage - Streaming +```python +from litellm import completion +import os + +os.environ['FEATHERLESS_AI_API_KEY'] = "" +response = completion( + model="featherless_ai/featherless-ai/Qwerky-72B", + messages=[{"role": "user", "content": "write code for saying hi from LiteLLM"}], + stream=True +) + +for chunk in response: + print(chunk) +``` + +## Chat Models +| Model Name | Function Call | +|---------------------------------------------|-----------------------------------------------------------------------------------------------| +| featherless-ai/Qwerky-72B | `completion(model="featherless_ai/featherless-ai/Qwerky-72B", messages)` | +| featherless-ai/Qwerky-QwQ-32B | `completion(model="featherless_ai/featherless-ai/Qwerky-QwQ-32B", messages)` | +| Qwen/Qwen2.5-72B-Instruct | `completion(model="featherless_ai/Qwen/Qwen2.5-72B-Instruct", messages)` | +| all-hands/openhands-lm-32b-v0.1 | `completion(model="featherless_ai/all-hands/openhands-lm-32b-v0.1", messages)` | +| Qwen/Qwen2.5-Coder-32B-Instruct | `completion(model="featherless_ai/Qwen/Qwen2.5-Coder-32B-Instruct", messages)` | +| deepseek-ai/DeepSeek-V3-0324 | `completion(model="featherless_ai/deepseek-ai/DeepSeek-V3-0324", messages)` | +| mistralai/Mistral-Small-24B-Instruct-2501 | `completion(model="featherless_ai/mistralai/Mistral-Small-24B-Instruct-2501", messages)` | +| mistralai/Mistral-Nemo-Instruct-2407 | `completion(model="featherless_ai/mistralai/Mistral-Nemo-Instruct-2407", messages)` | +| ProdeusUnity/Stellar-Odyssey-12b-v0.0 | `completion(model="featherless_ai/ProdeusUnity/Stellar-Odyssey-12b-v0.0", messages)` | diff --git a/docs/my-website/docs/providers/gemini.md b/docs/my-website/docs/providers/gemini.md index 0588200465d..80f68679105 100644 --- a/docs/my-website/docs/providers/gemini.md +++ b/docs/my-website/docs/providers/gemini.md @@ -8,7 +8,7 @@ import TabItem from '@theme/TabItem'; |-------|-------| | Description | Google AI Studio is a fully-managed AI development platform for building and using generative AI. | | Provider Route on LiteLLM | `gemini/` | -| Provider Doc | [Google AI Studio ↗](https://ai.google.dev/aistudio) | +| Provider Doc | [Google AI Studio ↗](https://aistudio.google.com/) | | API Endpoint for Provider | https://generativelanguage.googleapis.com | | Supported OpenAI Endpoints | `/chat/completions`, [`/embeddings`](../embedding/supported_embedding#gemini-ai-embedding-models), `/completions` | | Pass-through Endpoint | [Supported](../pass_through/google_ai_studio.md) | @@ -39,14 +39,164 @@ response = completion( - temperature - top_p - max_tokens +- max_completion_tokens - stream - tools - tool_choice +- functions - response_format - n - stop +- logprobs +- frequency_penalty +- modalities +- reasoning_content + +**Anthropic Params** +- thinking (used to set max budget tokens across anthropic/gemini models) + +[**See Updated List**](https://github.com/BerriAI/litellm/blob/main/litellm/llms/gemini/chat/transformation.py#L70) + + + +## Usage - Thinking / `reasoning_content` + +LiteLLM translates OpenAI's `reasoning_effort` to Gemini's `thinking` parameter. [Code](https://github.com/BerriAI/litellm/blob/620664921902d7a9bfb29897a7b27c1a7ef4ddfb/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py#L362) + +**Mapping** + +| reasoning_effort | thinking | +| ---------------- | -------- | +| "low" | "budget_tokens": 1024 | +| "medium" | "budget_tokens": 2048 | +| "high" | "budget_tokens": 4096 | + + + + +```python +from litellm import completion + +resp = completion( + model="gemini/gemini-2.5-flash-preview-04-17", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", +) + +``` + + + + + +1. Setup config.yaml + +```yaml +- model_name: gemini-2.5-flash + litellm_params: + model: gemini/gemini-2.5-flash-preview-04-17 + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "model": "gemini-2.5-flash", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "reasoning_effort": "low" + }' +``` + + + + + +**Expected Response** + +```python +ModelResponse( + id='chatcmpl-c542d76d-f675-4e87-8e5f-05855f5d0f5e', + created=1740470510, + model='claude-3-7-sonnet-20250219', + object='chat.completion', + system_fingerprint=None, + choices=[ + Choices( + finish_reason='stop', + index=0, + message=Message( + content="The capital of France is Paris.", + role='assistant', + tool_calls=None, + function_call=None, + reasoning_content='The capital of France is Paris. This is a very straightforward factual question.' + ), + ) + ], + usage=Usage( + completion_tokens=68, + prompt_tokens=42, + total_tokens=110, + completion_tokens_details=None, + prompt_tokens_details=PromptTokensDetailsWrapper( + audio_tokens=None, + cached_tokens=0, + text_tokens=None, + image_tokens=None + ), + cache_creation_input_tokens=0, + cache_read_input_tokens=0 + ) +) +``` + +### Pass `thinking` to Gemini models + +You can also pass the `thinking` parameter to Gemini models. + +This is translated to Gemini's [`thinkingConfig` parameter](https://ai.google.dev/gemini-api/docs/thinking#set-budget). + + + + +```python +response = litellm.completion( + model="gemini/gemini-2.5-flash-preview-04-17", + messages=[{"role": "user", "content": "What is the capital of France?"}], + thinking={"type": "enabled", "budget_tokens": 1024}, +) +``` + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "gemini/gemini-2.5-flash-preview-04-17", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "thinking": {"type": "enabled", "budget_tokens": 1024} + }' +``` + + + + + + -[**See Updated List**](https://github.com/BerriAI/litellm/blob/1c747f3ad372399c5b95cc5696b06a5fbe53186b/litellm/llms/vertex_httpx.py#L122) ## Passing Gemini Specific Params ### Response schema @@ -365,7 +515,7 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ ## Specifying Safety Settings -In certain use-cases you may need to make calls to the models and pass [safety settigns](https://ai.google.dev/docs/safety_setting_gemini) different from the defaults. To do so, simple pass the `safety_settings` argument to `completion` or `acompletion`. For example: +In certain use-cases you may need to make calls to the models and pass [safety settings](https://ai.google.dev/docs/safety_setting_gemini) different from the defaults. To do so, simple pass the `safety_settings` argument to `completion` or `acompletion`. For example: ```python response = completion( @@ -438,6 +588,179 @@ assert isinstance( ``` +### Google Search Tool + + + + +```python +from litellm import completion +import os + +os.environ["GEMINI_API_KEY"] = ".." + +tools = [{"googleSearch": {}}] # 👈 ADD GOOGLE SEARCH + +response = completion( + model="gemini/gemini-2.0-flash", + messages=[{"role": "user", "content": "What is the weather in San Francisco?"}], + tools=tools, +) + +print(response) +``` + + + + +1. Setup config.yaml +```yaml +model_list: + - model_name: gemini-2.0-flash + litellm_params: + model: gemini/gemini-2.0-flash + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start Proxy +```bash +$ litellm --config /path/to/config.yaml +``` + +3. Make Request! +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gemini-2.0-flash", + "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}], + "tools": [{"googleSearch": {}}] +} +' +``` + + + + +### Google Search Retrieval + + + + + +```python +from litellm import completion +import os + +os.environ["GEMINI_API_KEY"] = ".." + +tools = [{"googleSearch": {}}] # 👈 ADD GOOGLE SEARCH + +response = completion( + model="gemini/gemini-2.0-flash", + messages=[{"role": "user", "content": "What is the weather in San Francisco?"}], + tools=tools, +) + +print(response) +``` + + + + +1. Setup config.yaml +```yaml +model_list: + - model_name: gemini-2.0-flash + litellm_params: + model: gemini/gemini-2.0-flash + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start Proxy +```bash +$ litellm --config /path/to/config.yaml +``` + +3. Make Request! +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gemini-2.0-flash", + "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}], + "tools": [{"googleSearch": {}}] +} +' +``` + + + + + +### Code Execution Tool + + + + + +```python +from litellm import completion +import os + +os.environ["GEMINI_API_KEY"] = ".." + +tools = [{"codeExecution": {}}] # 👈 ADD GOOGLE SEARCH + +response = completion( + model="gemini/gemini-2.0-flash", + messages=[{"role": "user", "content": "What is the weather in San Francisco?"}], + tools=tools, +) + +print(response) +``` + + + + +1. Setup config.yaml +```yaml +model_list: + - model_name: gemini-2.0-flash + litellm_params: + model: gemini/gemini-2.0-flash + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start Proxy +```bash +$ litellm --config /path/to/config.yaml +``` + +3. Make Request! +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gemini-2.0-flash", + "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}], + "tools": [{"codeExecution": {}}] +} +' +``` + + + + + + + + + ## JSON Mode @@ -589,8 +912,10 @@ response = litellm.completion( "content": [ {"type": "text", "text": "Please summarize the audio."}, { - "type": "image_url", - "image_url": "data:audio/mp3;base64,{}".format(encoded_data), # 👈 SET MIME_TYPE + DATA + "type": "file", + "file": { + "file_data": "data:audio/mp3;base64,{}".format(encoded_data), # 👈 SET MIME_TYPE + DATA + } }, ], } @@ -640,8 +965,11 @@ response = litellm.completion( "content": [ {"type": "text", "text": "Please summarize the file."}, { - "type": "image_url", - "image_url": "https://storage..." # 👈 SET THE IMG URL + "type": "file", + "file": { + "file_id": "https://storage...", # 👈 SET THE IMG URL + "format": "application/pdf" # OPTIONAL + } }, ], } @@ -668,8 +996,11 @@ response = litellm.completion( "content": [ {"type": "text", "text": "Please summarize the file."}, { - "type": "image_url", - "image_url": "gs://..." # 👈 SET THE cloud storage bucket url + "type": "file", + "file": { + "file_id": "gs://storage...", # 👈 SET THE IMG URL + "format": "application/pdf" # OPTIONAL + } }, ], } @@ -688,7 +1019,9 @@ response = litellm.completion( |-----------------------|--------------------------------------------------------|--------------------------------| | gemini-pro | `completion(model='gemini/gemini-pro', messages)` | `os.environ['GEMINI_API_KEY']` | | gemini-1.5-pro-latest | `completion(model='gemini/gemini-1.5-pro-latest', messages)` | `os.environ['GEMINI_API_KEY']` | -| gemini-pro-vision | `completion(model='gemini/gemini-pro-vision', messages)` | `os.environ['GEMINI_API_KEY']` | +| gemini-2.0-flash | `completion(model='gemini/gemini-2.0-flash', messages)` | `os.environ['GEMINI_API_KEY']` | +| gemini-2.0-flash-exp | `completion(model='gemini/gemini-2.0-flash-exp', messages)` | `os.environ['GEMINI_API_KEY']` | +| gemini-2.0-flash-lite-preview-02-05 | `completion(model='gemini/gemini-2.0-flash-lite-preview-02-05', messages)` | `os.environ['GEMINI_API_KEY']` | @@ -877,3 +1210,54 @@ response = await client.chat.completions.create( + +## Image Generation + + + + +```python +from litellm import completion + +response = completion( + model="gemini/gemini-2.0-flash-exp-image-generation", + messages=[{"role": "user", "content": "Generate an image of a cat"}], + modalities=["image", "text"], +) +assert response.choices[0].message.content is not None # "data:image/png;base64,e4rr.." +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: gemini-2.0-flash-exp-image-generation + litellm_params: + model: gemini/gemini-2.0-flash-exp-image-generation + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl -L -X POST 'http://localhost:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gemini-2.0-flash-exp-image-generation", + "messages": [{"role": "user", "content": "Generate an image of a cat"}], + "modalities": ["image", "text"] +}' +``` + + + + diff --git a/docs/my-website/docs/providers/github.md b/docs/my-website/docs/providers/github.md index 023eaf7dcbf..7594b6af4c0 100644 --- a/docs/my-website/docs/providers/github.md +++ b/docs/my-website/docs/providers/github.md @@ -7,6 +7,7 @@ https://github.com/marketplace/models :::tip **We support ALL Github models, just set `model=github/` as a prefix when sending litellm requests** +Ignore company prefix: meta/Llama-3.2-11B-Vision-Instruct becomes model=github/Llama-3.2-11B-Vision-Instruct ::: @@ -23,7 +24,7 @@ import os os.environ['GITHUB_API_KEY'] = "" response = completion( - model="github/llama3-8b-8192", + model="github/Llama-3.2-11B-Vision-Instruct", messages=[ {"role": "user", "content": "hello from litellm"} ], @@ -38,7 +39,7 @@ import os os.environ['GITHUB_API_KEY'] = "" response = completion( - model="github/llama3-8b-8192", + model="github/Llama-3.2-11B-Vision-Instruct", messages=[ {"role": "user", "content": "hello from litellm"} ], @@ -57,9 +58,9 @@ for chunk in response: ```yaml model_list: - - model_name: github-llama3-8b-8192 # Model Alias to use for requests + - model_name: github-Llama-3.2-11B-Vision-Instruct # Model Alias to use for requests litellm_params: - model: github/llama3-8b-8192 + model: github/Llama-3.2-11B-Vision-Instruct api_key: "os.environ/GITHUB_API_KEY" # ensure you have `GITHUB_API_KEY` in your .env ``` @@ -80,7 +81,7 @@ Make request to litellm proxy curl --location 'http://0.0.0.0:4000/chat/completions' \ --header 'Content-Type: application/json' \ --data ' { - "model": "github-llama3-8b-8192", + "model": "github-Llama-3.2-11B-Vision-Instruct", "messages": [ { "role": "user", @@ -100,7 +101,7 @@ client = openai.OpenAI( base_url="http://0.0.0.0:4000" ) -response = client.chat.completions.create(model="github-llama3-8b-8192", messages = [ +response = client.chat.completions.create(model="github-Llama-3.2-11B-Vision-Instruct", messages = [ { "role": "user", "content": "this is a test request, write a short poem" @@ -124,7 +125,7 @@ from langchain.schema import HumanMessage, SystemMessage chat = ChatOpenAI( openai_api_base="http://0.0.0.0:4000", # set openai_api_base to the LiteLLM Proxy - model = "github-llama3-8b-8192", + model = "github-Llama-3.2-11B-Vision-Instruct", temperature=0.1 ) @@ -152,7 +153,7 @@ We support ALL Github models, just set `github/` as a prefix when sending comple |--------------------|---------------------------------------------------------| | llama-3.1-8b-instant | `completion(model="github/llama-3.1-8b-instant", messages)` | | llama-3.1-70b-versatile | `completion(model="github/llama-3.1-70b-versatile", messages)` | -| llama3-8b-8192 | `completion(model="github/llama3-8b-8192", messages)` | +| Llama-3.2-11B-Vision-Instruct | `completion(model="github/Llama-3.2-11B-Vision-Instruct", messages)` | | llama3-70b-8192 | `completion(model="github/llama3-70b-8192", messages)` | | llama2-70b-4096 | `completion(model="github/llama2-70b-4096", messages)` | | mixtral-8x7b-32768 | `completion(model="github/mixtral-8x7b-32768", messages)` | @@ -214,7 +215,7 @@ tools = [ } ] response = litellm.completion( - model="github/llama3-8b-8192", + model="github/Llama-3.2-11B-Vision-Instruct", messages=messages, tools=tools, tool_choice="auto", # auto is default, but we'll be explicit @@ -254,7 +255,7 @@ if tool_calls: ) # extend conversation with function response print(f"messages: {messages}") second_response = litellm.completion( - model="github/llama3-8b-8192", messages=messages + model="github/Llama-3.2-11B-Vision-Instruct", messages=messages ) # get a new response from the model where it can see the function response print("second response\n", second_response) ``` diff --git a/docs/my-website/docs/providers/google_ai_studio/files.md b/docs/my-website/docs/providers/google_ai_studio/files.md new file mode 100644 index 00000000000..500f1d57185 --- /dev/null +++ b/docs/my-website/docs/providers/google_ai_studio/files.md @@ -0,0 +1,161 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# [BETA] Google AI Studio (Gemini) Files API + +Use this to upload files to Google AI Studio (Gemini). + +Useful to pass in large media files to Gemini's `/generateContent` endpoint. + +| Action | Supported | +|----------|-----------| +| `create` | Yes | +| `delete` | No | +| `retrieve` | No | +| `list` | No | + +## Usage + + + + +```python +import base64 +import requests +from litellm import completion, create_file +import os + + +### UPLOAD FILE ### + +# Fetch the audio file and convert it to a base64 encoded string +url = "https://cdn.openai.com/API/docs/audio/alloy.wav" +response = requests.get(url) +response.raise_for_status() +wav_data = response.content +encoded_string = base64.b64encode(wav_data).decode('utf-8') + + +file = create_file( + file=wav_data, + purpose="user_data", + extra_body={"custom_llm_provider": "gemini"}, + api_key=os.getenv("GEMINI_API_KEY"), +) + +print(f"file: {file}") + +assert file is not None + + +### GENERATE CONTENT ### +completion = completion( + model="gemini-2.0-flash", + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What is in this recording?" + }, + { + "type": "file", + "file": { + "file_id": file.id, + "filename": "my-test-name", + "format": "audio/wav" + } + } + ] + }, + ] +) + +print(completion.choices[0].message) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: "gemini-2.0-flash" + litellm_params: + model: gemini/gemini-2.0-flash + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start proxy + +```bash +litellm --config config.yaml +``` + +3. Test it + +```python +import base64 +import requests +from openai import OpenAI + +client = OpenAI( + base_url="http://0.0.0.0:4000", + api_key="sk-1234" +) + +# Fetch the audio file and convert it to a base64 encoded string +url = "https://cdn.openai.com/API/docs/audio/alloy.wav" +response = requests.get(url) +response.raise_for_status() +wav_data = response.content +encoded_string = base64.b64encode(wav_data).decode('utf-8') + + +file = client.files.create( + file=wav_data, + purpose="user_data", + extra_body={"target_model_names": "gemini-2.0-flash"} +) + +print(f"file: {file}") + +assert file is not None + +completion = client.chat.completions.create( + model="gemini-2.0-flash", + modalities=["text", "audio"], + audio={"voice": "alloy", "format": "wav"}, + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What is in this recording?" + }, + { + "type": "file", + "file": { + "file_id": file.id, + "filename": "my-test-name", + "format": "audio/wav" + } + } + ] + }, + ], + extra_body={"drop_params": True} +) + +print(completion.choices[0].message) +``` + + + + + + + diff --git a/docs/my-website/docs/providers/google_ai_studio/realtime.md b/docs/my-website/docs/providers/google_ai_studio/realtime.md new file mode 100644 index 00000000000..50a18e131cc --- /dev/null +++ b/docs/my-website/docs/providers/google_ai_studio/realtime.md @@ -0,0 +1,92 @@ +# Gemini Realtime API - Google AI Studio + +| Feature | Description | Comments | +| --- | --- | --- | +| Proxy | ✅ | | +| SDK | ⌛️ | Experimental access via `litellm._arealtime`. | + + +## Proxy Usage + +### Add model to config + +```yaml +model_list: + - model_name: "gemini-2.0-flash" + litellm_params: + model: gemini/gemini-2.0-flash-live-001 + model_info: + mode: realtime +``` + +### Start proxy + +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:8000 +``` + +### Test + +Run this script using node - `node test.js` + +```js +// test.js +const WebSocket = require("ws"); + +const url = "ws://0.0.0.0:4000/v1/realtime?model=openai-gemini-2.0-flash"; + +const ws = new WebSocket(url, { + headers: { + "api-key": `${LITELLM_API_KEY}`, + "OpenAI-Beta": "realtime=v1", + }, +}); + +ws.on("open", function open() { + console.log("Connected to server."); + ws.send(JSON.stringify({ + type: "response.create", + response: { + modalities: ["text"], + instructions: "Please assist the user.", + } + })); +}); + +ws.on("message", function incoming(message) { + console.log(JSON.parse(message.toString())); +}); + +ws.on("error", function handleError(error) { + console.error("Error: ", error); +}); +``` + +## Limitations + +- Does not support audio transcription. +- Does not support tool calling + +## Supported OpenAI Realtime Events + +- `session.created` +- `response.created` +- `response.output_item.added` +- `conversation.item.created` +- `response.content_part.added` +- `response.text.delta` +- `response.audio.delta` +- `response.text.done` +- `response.audio.done` +- `response.content_part.done` +- `response.output_item.done` +- `response.done` + + + +## [Supported Session Params](https://github.com/BerriAI/litellm/blob/e87b536d038f77c2a2206fd7433e275c487179ee/litellm/llms/gemini/realtime/transformation.py#L155) + +## More Examples +### [Gemini Realtime API with Audio Input/Output](../../../docs/tutorials/gemini_realtime_with_audio) \ No newline at end of file diff --git a/docs/my-website/docs/providers/huggingface.md b/docs/my-website/docs/providers/huggingface.md index 5297a688bac..399d49b5f46 100644 --- a/docs/my-website/docs/providers/huggingface.md +++ b/docs/my-website/docs/providers/huggingface.md @@ -2,466 +2,392 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Huggingface +# Hugging Face +LiteLLM supports running inference across multiple services for models hosted on the Hugging Face Hub. -LiteLLM supports the following types of Hugging Face models: +- **Serverless Inference Providers** - Hugging Face offers an easy and unified access to serverless AI inference through multiple inference providers, like [Together AI](https://together.ai) and [Sambanova](https://sambanova.ai). This is the fastest way to integrate AI in your products with a maintenance-free and scalable solution. More details in the [Inference Providers documentation](https://huggingface.co/docs/inference-providers/index). +- **Dedicated Inference Endpoints** - which is a product to easily deploy models to production. Inference is run by Hugging Face in a dedicated, fully managed infrastructure on a cloud provider of your choice. You can deploy your model on Hugging Face Inference Endpoints by following [these steps](https://huggingface.co/docs/inference-endpoints/guides/create_endpoint). -- Serverless Inference API (free) - loaded and ready to use: https://huggingface.co/models?inference=warm&pipeline_tag=text-generation -- Dedicated Inference Endpoints (paid) - manual deployment: https://ui.endpoints.huggingface.co/ -- All LLMs served via Hugging Face's Inference use [Text-generation-inference](https://huggingface.co/docs/text-generation-inference). + +## Supported Models + +### Serverless Inference Providers +You can check available models for an inference provider by going to [huggingface.co/models](https://huggingface.co/models), clicking the "Other" filter tab, and selecting your desired provider: + +![Filter models by Inference Provider](../../img/hf_filter_inference_providers.png) + +For example, you can find all Fireworks supported models [here](https://huggingface.co/models?inference_provider=fireworks-ai&sort=trending). + + +### Dedicated Inference Endpoints +Refer to the [Inference Endpoints catalog](https://endpoints.huggingface.co/catalog) for a list of available models. ## Usage + + + +### Authentication +With a single Hugging Face token, you can access inference through multiple providers. Your calls are routed through Hugging Face and the usage is billed directly to your Hugging Face account at the standard provider API rates. + +Simply set the `HF_TOKEN` environment variable with your Hugging Face token, you can create one here: https://huggingface.co/settings/tokens. + +```bash +export HF_TOKEN="hf_xxxxxx" +``` +or alternatively, you can pass your Hugging Face token as a parameter: +```python +completion(..., api_key="hf_xxxxxx") +``` + +### Getting Started + +To use a Hugging Face model, specify both the provider and model you want to use in the following format: +``` +huggingface/// +``` +Where `/` is the Hugging Face model ID and `` is the inference provider. +By default, if you don't specify a provider, LiteLLM will use the [HF Inference API](https://huggingface.co/docs/api-inference/en/index). + +Examples: + +```python +# Run DeepSeek-R1 inference through Together AI +completion(model="huggingface/together/deepseek-ai/DeepSeek-R1",...) + +# Run Qwen2.5-72B-Instruct inference through Sambanova +completion(model="huggingface/sambanova/Qwen/Qwen2.5-72B-Instruct",...) + +# Run Llama-3.3-70B-Instruct inference through HF Inference API +completion(model="huggingface/meta-llama/Llama-3.3-70B-Instruct",...) +``` + + Open In Colab -You need to tell LiteLLM when you're calling Huggingface. -This is done by adding the "huggingface/" prefix to `model`, example `completion(model="huggingface/",...)`. - - - - -By default, LiteLLM will assume a Hugging Face call follows the [Messages API](https://huggingface.co/docs/text-generation-inference/messages_api), which is fully compatible with the OpenAI Chat Completion API. - - - +### Basic Completion +Here's an example of chat completion using the DeepSeek-R1 model through Together AI: ```python import os from litellm import completion -# [OPTIONAL] set env var -os.environ["HUGGINGFACE_API_KEY"] = "huggingface_api_key" +os.environ["HF_TOKEN"] = "hf_xxxxxx" -messages = [{ "content": "There's a llama in my garden 😱 What should I do?","role": "user"}] - -# e.g. Call 'https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct' from Serverless Inference API response = completion( - model="huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct", - messages=[{ "content": "Hello, how are you?","role": "user"}], + model="huggingface/together/deepseek-ai/DeepSeek-R1", + messages=[ + { + "role": "user", + "content": "How many r's are in the word 'strawberry'?", + } + ], +) +print(response) +``` + +### Streaming +Now, let's see what a streaming request looks like. + +```python +import os +from litellm import completion + +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +response = completion( + model="huggingface/together/deepseek-ai/DeepSeek-R1", + messages=[ + { + "role": "user", + "content": "How many r's are in the word `strawberry`?", + + } + ], + stream=True, +) + +for chunk in response: + print(chunk) +``` + +### Image Input +You can also pass images when the model supports it. Here is an example using [Llama-3.2-11B-Vision-Instruct](https://huggingface.co/meta-llama/Llama-3.2-11B-Vision-Instruct) model through Sambanova. + +```python +from litellm import completion + +# Set your Hugging Face Token +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What's in this image?"}, + { + "type": "image_url", + "image_url": { + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + } + }, + ], + } + ] + +response = completion( + model="huggingface/sambanova/meta-llama/Llama-3.2-11B-Vision-Instruct", + messages=messages, +) +print(response.choices[0]) +``` + +### Function Calling +You can extend the model's capabilities by giving them access to tools. Here is an example with function calling using [Qwen2.5-72B-Instruct](https://huggingface.co/Qwen/Qwen2.5-72B-Instruct) model through Sambanova. + +```python +import os +from litellm import completion + +# Set your Hugging Face Token +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + }, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}, + }, + "required": ["location"], + }, + } + } +] +messages = [ + { + "role": "user", + "content": "What's the weather like in Boston today?", + } +] + +response = completion( + model="huggingface/sambanova/meta-llama/Llama-3.3-70B-Instruct", + messages=messages, + tools=tools, + tool_choice="auto" +) +print(response) +``` + + + + + + + Open In Colab + + +### Basic Completion +After you have [deployed your Hugging Face Inference Endpoint](https://endpoints.huggingface.co/new) on dedicated infrastructure, you can run inference on it by providing the endpoint base URL in `api_base`, and indicating `huggingface/tgi` as the model name. + +```python +import os +from litellm import completion + +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +response = completion( + model="huggingface/tgi", + messages=[{"content": "Hello, how are you?", "role": "user"}], + api_base="https://my-endpoint.endpoints.huggingface.cloud/v1/" +) +print(response) +``` + +### Streaming + +```python +import os +from litellm import completion + +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +response = completion( + model="huggingface/tgi", + messages=[{"content": "Hello, how are you?", "role": "user"}], + api_base="https://my-endpoint.endpoints.huggingface.cloud/v1/", stream=True ) -print(response) -``` - - - - -1. Add models to your config.yaml - -```yaml -model_list: - - model_name: llama-3.1-8B-instruct - litellm_params: - model: huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct - api_key: os.environ/HUGGINGFACE_API_KEY -``` - -2. Start the proxy - -```bash -$ litellm --config /path/to/config.yaml --debug -``` - -3. Test it! - -```shell -curl --location 'http://0.0.0.0:4000/chat/completions' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "llama-3.1-8B-instruct", - "messages": [ - { - "role": "user", - "content": "I like you!" - } - ], -}' -``` - - - - - - -Append `text-classification` to the model name - -e.g. `huggingface/text-classification/` - - - - -```python -import os -from litellm import completion - -# [OPTIONAL] set env var -os.environ["HUGGINGFACE_API_KEY"] = "huggingface_api_key" - -messages = [{ "content": "I like you, I love you!","role": "user"}] - -# e.g. Call 'shahrukhx01/question-vs-statement-classifier' hosted on HF Inference endpoints -response = completion( - model="huggingface/text-classification/shahrukhx01/question-vs-statement-classifier", - messages=messages, - api_base="https://my-endpoint.endpoints.huggingface.cloud", -) - -print(response) -``` - - - - -1. Add models to your config.yaml - -```yaml -model_list: - - model_name: bert-classifier - litellm_params: - model: huggingface/text-classification/shahrukhx01/question-vs-statement-classifier - api_key: os.environ/HUGGINGFACE_API_KEY - api_base: "https://my-endpoint.endpoints.huggingface.cloud" -``` - -2. Start the proxy - -```bash -$ litellm --config /path/to/config.yaml --debug -``` - -3. Test it! - -```shell -curl --location 'http://0.0.0.0:4000/chat/completions' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "bert-classifier", - "messages": [ - { - "role": "user", - "content": "I like you!" - } - ], -}' -``` - - - - - - -Steps to use -* Create your own Hugging Face dedicated endpoint here: https://ui.endpoints.huggingface.co/ -* Set `api_base` to your deployed api base -* Add the `huggingface/` prefix to your model so litellm knows it's a huggingface Deployed Inference Endpoint - - - - -```python -import os -from litellm import completion - -os.environ["HUGGINGFACE_API_KEY"] = "" - -# TGI model: Call https://huggingface.co/glaiveai/glaive-coder-7b -# add the 'huggingface/' prefix to the model to set huggingface as the provider -# set api base to your deployed api endpoint from hugging face -response = completion( - model="huggingface/glaiveai/glaive-coder-7b", - messages=[{ "content": "Hello, how are you?","role": "user"}], - api_base="https://wjiegasee9bmqke2.us-east-1.aws.endpoints.huggingface.cloud" -) -print(response) -``` - - - - -1. Add models to your config.yaml - -```yaml -model_list: - - model_name: glaive-coder - litellm_params: - model: huggingface/glaiveai/glaive-coder-7b - api_key: os.environ/HUGGINGFACE_API_KEY - api_base: "https://wjiegasee9bmqke2.us-east-1.aws.endpoints.huggingface.cloud" -``` - -2. Start the proxy - -```bash -$ litellm --config /path/to/config.yaml --debug -``` - -3. Test it! - -```shell -curl --location 'http://0.0.0.0:4000/chat/completions' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "glaive-coder", - "messages": [ - { - "role": "user", - "content": "I like you!" - } - ], -}' -``` - - - - - - - -## Streaming - - - Open In Colab - - -You need to tell LiteLLM when you're calling Huggingface. -This is done by adding the "huggingface/" prefix to `model`, example `completion(model="huggingface/",...)`. - -```python -import os -from litellm import completion - -# [OPTIONAL] set env var -os.environ["HUGGINGFACE_API_KEY"] = "huggingface_api_key" - -messages = [{ "content": "There's a llama in my garden 😱 What should I do?","role": "user"}] - -# e.g. Call 'facebook/blenderbot-400M-distill' hosted on HF Inference endpoints -response = completion( - model="huggingface/facebook/blenderbot-400M-distill", - messages=messages, - api_base="https://my-endpoint.huggingface.cloud", - stream=True -) - -print(response) for chunk in response: - print(chunk) + print(chunk) ``` +### Image Input + +```python +import os +from litellm import completion + +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What's in this image?"}, + { + "type": "image_url", + "image_url": { + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + } + }, + ], + } + ] +response = completion( + model="huggingface/tgi", + messages=messages, + api_base="https://my-endpoint.endpoints.huggingface.cloud/v1/"" +) +print(response.choices[0]) +``` + +### Function Calling + +```python +import os +from litellm import completion + +os.environ["HF_TOKEN"] = "hf_xxxxxx" + +functions = [{ + "name": "get_weather", + "description": "Get the weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The location to get weather for" + } + }, + "required": ["location"] + } +}] + +response = completion( + model="huggingface/tgi", + messages=[{"content": "What's the weather like in San Francisco?", "role": "user"}], + api_base="https://my-endpoint.endpoints.huggingface.cloud/v1/", + functions=functions +) +print(response) +``` + + + + +## LiteLLM Proxy Server with Hugging Face models +You can set up a [LiteLLM Proxy Server](https://docs.litellm.ai/#litellm-proxy-server-llm-gateway) to serve Hugging Face models through any of the supported Inference Providers. Here's how to do it: + +### Step 1. Setup the config file + +In this case, we are configuring a proxy to serve `DeepSeek R1` from Hugging Face, using Together AI as the backend Inference Provider. + +```yaml +model_list: + - model_name: my-r1-model + litellm_params: + model: huggingface/together/deepseek-ai/DeepSeek-R1 + api_key: os.environ/HF_TOKEN # ensure you have `HF_TOKEN` in your .env +``` + +### Step 2. Start the server +```bash +litellm --config /path/to/config.yaml +``` + +### Step 3. Make a request to the server + + + +```shell +curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "my-r1-model", + "messages": [ + { + "role": "user", + "content": "Hello, how are you?" + } + ] +}' +``` + + + + +```python +# pip install openai +from openai import OpenAI + +client = OpenAI( + base_url="http://0.0.0.0:4000", + api_key="anything", +) + +response = client.chat.completions.create( + model="my-r1-model", + messages=[ + {"role": "user", "content": "Hello, how are you?"} + ] +) +print(response) +``` + + + + + ## Embedding -LiteLLM supports Hugging Face's [text-embedding-inference](https://github.com/huggingface/text-embeddings-inference) format. +LiteLLM supports Hugging Face's [text-embedding-inference](https://github.com/huggingface/text-embeddings-inference) models as well. ```python from litellm import embedding import os -os.environ['HUGGINGFACE_API_KEY'] = "" +os.environ['HF_TOKEN'] = "hf_xxxxxx" response = embedding( model='huggingface/microsoft/codebert-base', input=["good morning from litellm"] ) ``` -## Advanced - -### Setting API KEYS + API BASE - -If required, you can set the api key + api base, set it in your os environment. [Code for how it's sent](https://github.com/BerriAI/litellm/blob/0100ab2382a0e720c7978fbf662cc6e6920e7e03/litellm/llms/huggingface_restapi.py#L25) - -```python -import os -os.environ["HUGGINGFACE_API_KEY"] = "" -os.environ["HUGGINGFACE_API_BASE"] = "" -``` - -### Viewing Log probs - -#### Using `decoder_input_details` - OpenAI `echo` - -The `echo` param is supported by OpenAI Completions - Use `litellm.text_completion()` for this - -```python -from litellm import text_completion -response = text_completion( - model="huggingface/bigcode/starcoder", - prompt="good morning", - max_tokens=10, logprobs=10, - echo=True -) -``` - -#### Output - -```json -{ - "id": "chatcmpl-3fc71792-c442-4ba1-a611-19dd0ac371ad", - "object": "text_completion", - "created": 1698801125.936519, - "model": "bigcode/starcoder", - "choices": [ - { - "text": ", I'm going to make you a sand", - "index": 0, - "logprobs": { - "tokens": [ - "good", - " morning", - ",", - " I", - "'m", - " going", - " to", - " make", - " you", - " a", - " s", - "and" - ], - "token_logprobs": [ - "None", - -14.96875, - -2.2285156, - -2.734375, - -2.0957031, - -2.0917969, - -0.09429932, - -3.1132812, - -1.3203125, - -1.2304688, - -1.6201172, - -0.010292053 - ] - }, - "finish_reason": "length" - } - ], - "usage": { - "completion_tokens": 9, - "prompt_tokens": 2, - "total_tokens": 11 - } -} -``` - -### Models with Prompt Formatting - -For models with special prompt templates (e.g. Llama2), we format the prompt to fit their template. - -#### Models with natively Supported Prompt Templates - -| Model Name | Works for Models | Function Call | Required OS Variables | -| ------------------------------------ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -| mistralai/Mistral-7B-Instruct-v0.1 | mistralai/Mistral-7B-Instruct-v0.1 | `completion(model='huggingface/mistralai/Mistral-7B-Instruct-v0.1', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | -| meta-llama/Llama-2-7b-chat | All meta-llama llama2 chat models | `completion(model='huggingface/meta-llama/Llama-2-7b', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | -| tiiuae/falcon-7b-instruct | All falcon instruct models | `completion(model='huggingface/tiiuae/falcon-7b-instruct', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | -| mosaicml/mpt-7b-chat | All mpt chat models | `completion(model='huggingface/mosaicml/mpt-7b-chat', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | -| codellama/CodeLlama-34b-Instruct-hf | All codellama instruct models | `completion(model='huggingface/codellama/CodeLlama-34b-Instruct-hf', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | -| WizardLM/WizardCoder-Python-34B-V1.0 | All wizardcoder models | `completion(model='huggingface/WizardLM/WizardCoder-Python-34B-V1.0', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | -| Phind/Phind-CodeLlama-34B-v2 | All phind-codellama models | `completion(model='huggingface/Phind/Phind-CodeLlama-34B-v2', messages=messages, api_base="your_api_endpoint")` | `os.environ['HUGGINGFACE_API_KEY']` | - -**What if we don't support a model you need?** -You can also specify you're own custom prompt formatting, in case we don't have your model covered yet. - -**Does this mean you have to specify a prompt for all models?** -No. By default we'll concatenate your message content to make a prompt. - -**Default Prompt Template** - -```python -def default_pt(messages): - return " ".join(message["content"] for message in messages) -``` - -[Code for how prompt formats work in LiteLLM](https://github.com/BerriAI/litellm/blob/main/litellm/llms/prompt_templates/factory.py) - -#### Custom prompt templates - -```python -import litellm - -# Create your own custom prompt template works -litellm.register_prompt_template( - model="togethercomputer/LLaMA-2-7B-32K", - roles={ - "system": { - "pre_message": "[INST] <>\n", - "post_message": "\n<>\n [/INST]\n" - }, - "user": { - "pre_message": "[INST] ", - "post_message": " [/INST]\n" - }, - "assistant": { - "post_message": "\n" - } - } - ) - -def test_huggingface_custom_model(): - model = "huggingface/togethercomputer/LLaMA-2-7B-32K" - response = completion(model=model, messages=messages, api_base="https://ecd4sb5n09bo4ei2.us-east-1.aws.endpoints.huggingface.cloud") - print(response['choices'][0]['message']['content']) - return response - -test_huggingface_custom_model() -``` - -[Implementation Code](https://github.com/BerriAI/litellm/blob/c0b3da2c14c791a0b755f0b1e5a9ef065951ecbf/litellm/llms/huggingface_restapi.py#L52) - -### Deploying a model on huggingface - -You can use any chat/text model from Hugging Face with the following steps: - -- Copy your model id/url from Huggingface Inference Endpoints - - [ ] Go to https://ui.endpoints.huggingface.co/ - - [ ] Copy the url of the specific model you'd like to use - HF_Dashboard -- Set it as your model name -- Set your HUGGINGFACE_API_KEY as an environment variable - -Need help deploying a model on huggingface? [Check out this guide.](https://huggingface.co/docs/inference-endpoints/guides/create_endpoint) - -# output - -Same as the OpenAI format, but also includes logprobs. [See the code](https://github.com/BerriAI/litellm/blob/b4b2dbf005142e0a483d46a07a88a19814899403/litellm/llms/huggingface_restapi.py#L115) - -```json -{ - "choices": [ - { - "finish_reason": "stop", - "index": 0, - "message": { - "content": "\ud83d\ude31\n\nComment: @SarahSzabo I'm", - "role": "assistant", - "logprobs": -22.697942825499993 - } - } - ], - "created": 1693436637.38206, - "model": "https://ji16r2iys9a8rjk2.us-east-1.aws.endpoints.huggingface.cloud", - "usage": { - "prompt_tokens": 14, - "completion_tokens": 11, - "total_tokens": 25 - } -} -``` - # FAQ -**Does this support stop sequences?** +**How does billing work with Hugging Face Inference Providers?** -Yes, we support stop sequences - and you can pass as many as allowed by Hugging Face (or any provider!) +> Billing is centralized on your Hugging Face account, no matter which providers you are using. You are billed the standard provider API rates with no additional markup - Hugging Face simply passes through the provider costs. Note that [Hugging Face PRO](https://huggingface.co/subscribe/pro) users get $2 worth of Inference credits every month that can be used across providers. -**How do you deal with repetition penalty?** +**Do I need to create an account for each Inference Provider?** -We map the presence penalty parameter in openai to the repetition penalty parameter on Hugging Face. [See code](https://github.com/BerriAI/litellm/blob/b4b2dbf005142e0a483d46a07a88a19814899403/litellm/utils.py#L757). +> No, you don't need to create separate accounts. All requests are routed through Hugging Face, so you only need your HF token. This allows you to easily benchmark different providers and choose the one that best fits your needs. -We welcome any suggestions for improving our Hugging Face integration - Create an [issue](https://github.com/BerriAI/litellm/issues/new/choose)/[Join the Discord](https://discord.com/invite/wuPM9dRgDw)! +**Will more inference providers be supported by Hugging Face in the future?** + +> Yes! New inference providers (and models) are being added gradually. + +We welcome any suggestions for improving our Hugging Face integration - Create an [issue](https://github.com/BerriAI/litellm/issues/new/choose)/[Join the Discord](https://discord.com/invite/wuPM9dRgDw)! \ No newline at end of file diff --git a/docs/my-website/docs/providers/infinity.md b/docs/my-website/docs/providers/infinity.md index dd6986dfef9..7900d5adb4a 100644 --- a/docs/my-website/docs/providers/infinity.md +++ b/docs/my-website/docs/providers/infinity.md @@ -1,17 +1,22 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # Infinity -| Property | Details | -|-------|-------| -| Description | Infinity is a high-throughput, low-latency REST API for serving text-embeddings, reranking models and clip| -| Provider Route on LiteLLM | `infinity/` | -| Supported Operations | `/rerank` | -| Link to Provider Doc | [Infinity ↗](https://github.com/michaelfeil/infinity) | - +| Property | Details | +| ------------------------- | ---------------------------------------------------------------------------------------------------------- | +| Description | Infinity is a high-throughput, low-latency REST API for serving text-embeddings, reranking models and clip | +| Provider Route on LiteLLM | `infinity/` | +| Supported Operations | `/rerank`, `/embeddings` | +| Link to Provider Doc | [Infinity ↗](https://github.com/michaelfeil/infinity) | ## **Usage - LiteLLM Python SDK** ```python -from litellm import rerank +from litellm import rerank, embedding +import os + +os.environ["INFINITY_API_BASE"] = "http://localhost:8080" response = rerank( model="infinity/rerank", @@ -33,8 +38,8 @@ model_list: - model_name: custom-infinity-rerank litellm_params: model: infinity/rerank - api_key: os.environ/INFINITY_API_KEY api_base: https://localhost:8080 + api_key: os.environ/INFINITY_API_KEY ``` Start litellm @@ -45,7 +50,9 @@ litellm --config /path/to/config.yaml # RUNNING on http://0.0.0.0:4000 ``` -Test request +## Test request: + +### Rerank ```bash curl http://0.0.0.0:4000/rerank \ @@ -64,4 +71,230 @@ curl http://0.0.0.0:4000/rerank \ }' ``` +#### Supported Cohere Rerank API Params +| Param | Type | Description | +| ------------------ | ----------- | ----------------------------------------------- | +| `query` | `str` | The query to rerank the documents against | +| `documents` | `list[str]` | The documents to rerank | +| `top_n` | `int` | The number of documents to return | +| `return_documents` | `bool` | Whether to return the documents in the response | + +### Usage - Return Documents + + + + +```python +response = rerank( + model="infinity/rerank", + query="What is the capital of France?", + documents=["Paris", "London", "Berlin", "Madrid"], + return_documents=True, +) +``` + + + + + +```bash +curl http://0.0.0.0:4000/rerank \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "custom-infinity-rerank", + "query": "What is the capital of France?", + "documents": [ + "Paris", + "London", + "Berlin", + "Madrid" + ], + "return_documents": True, + }' +``` + + + + +## Pass Provider-specific Params + +Any unmapped params will be passed to the provider as-is. + + + + +```python +from litellm import rerank +import os + +os.environ["INFINITY_API_BASE"] = "http://localhost:8080" + +response = rerank( + model="infinity/rerank", + query="What is the capital of France?", + documents=["Paris", "London", "Berlin", "Madrid"], + raw_scores=True, # 👈 PROVIDER-SPECIFIC PARAM +) +``` + + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: custom-infinity-rerank + litellm_params: + model: infinity/rerank + api_base: https://localhost:8080 + raw_scores: True # 👈 EITHER SET PROVIDER-SPECIFIC PARAMS HERE OR IN REQUEST BODY +``` + +2. Start litellm + +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/rerank \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "custom-infinity-rerank", + "query": "What is the capital of the United States?", + "documents": [ + "Carson City is the capital city of the American state of Nevada.", + "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan.", + "Washington, D.C. is the capital of the United States.", + "Capital punishment has existed in the United States since before it was a country." + ], + "raw_scores": True # 👈 PROVIDER-SPECIFIC PARAM + }' +``` + + + + + +## Embeddings + +LiteLLM provides an OpenAI api compatible `/embeddings` endpoint for embedding calls. + +**Setup** + +Add this to your litellm proxy config.yaml + +```yaml +model_list: + - model_name: custom-infinity-embedding + litellm_params: + model: infinity/provider/custom-embedding-v1 + api_base: http://localhost:8080 + api_key: os.environ/INFINITY_API_KEY +``` + +### Test request: + +```bash +curl http://0.0.0.0:4000/embeddings \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "custom-infinity-embedding", + "input": ["hello"] + }' +``` + +#### Supported Embedding API Params + +| Param | Type | Description | +| ----------------- | ----------- | ----------------------------------------------------------- | +| `model` | `str` | The embedding model to use | +| `input` | `list[str]` | The text inputs to generate embeddings for | +| `encoding_format` | `str` | The format to return embeddings in (e.g. "float", "base64") | +| `modality` | `str` | The type of input (e.g. "text", "image", "audio") | + +### Usage - Basic Examples + + + + +```python +from litellm import embedding +import os + +os.environ["INFINITY_API_BASE"] = "http://localhost:8080" + +response = embedding( + model="infinity/bge-small", + input=["good morning from litellm"] +) + +print(response.data[0]['embedding']) +``` + + + + + +```bash +curl http://0.0.0.0:4000/embeddings \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "custom-infinity-embedding", + "input": ["hello"] + }' +``` + + + + +### Usage - OpenAI Client + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="", + base_url="" +) + +response = client.embeddings.create( + model="bge-small", + input=["The food was delicious and the waiter..."], + encoding_format="float" +) + +print(response.data[0].embedding) +``` + + + + + +```bash +curl http://0.0.0.0:4000/embeddings \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "bge-small", + "input": ["The food was delicious and the waiter..."], + "encoding_format": "float" + }' +``` + + + diff --git a/docs/my-website/docs/providers/litellm_proxy.md b/docs/my-website/docs/providers/litellm_proxy.md index 69377b27f1c..a9de5d5913d 100644 --- a/docs/my-website/docs/providers/litellm_proxy.md +++ b/docs/my-website/docs/providers/litellm_proxy.md @@ -3,13 +3,15 @@ import TabItem from '@theme/TabItem'; # LiteLLM Proxy (LLM Gateway) -:::tip -[LiteLLM Providers a **self hosted** proxy server (AI Gateway)](../simple_proxy) to call all the LLMs in the OpenAI format +| Property | Details | +|-------|-------| +| Description | LiteLLM Proxy is an OpenAI-compatible gateway that allows you to interact with multiple LLM providers through a unified API. Simply use the `litellm_proxy/` prefix before the model name to route your requests through the proxy. | +| Provider Route on LiteLLM | `litellm_proxy/` (add this prefix to the model name, to route any requests to litellm_proxy - e.g. `litellm_proxy/your-model-name`) | +| Setup LiteLLM Gateway | [LiteLLM Gateway ↗](../simple_proxy) | +| Supported Endpoints |`/chat/completions`, `/completions`, `/embeddings`, `/audio/speech`, `/audio/transcriptions`, `/images`, `/rerank` | -::: -**[LiteLLM Proxy](../simple_proxy) is OpenAI compatible**, you just need the `litellm_proxy/` prefix before the model ## Required Variables @@ -55,7 +57,7 @@ messages = [{ "content": "Hello, how are you?","role": "user"}] # litellm proxy call response = completion( model="litellm_proxy/your-model-name", - messages, + messages=messages, api_base = "your-litellm-proxy-url", api_key = "your-litellm-proxy-api-key" ) @@ -74,7 +76,7 @@ messages = [{ "content": "Hello, how are you?","role": "user"}] # openai call response = completion( model="litellm_proxy/your-model-name", - messages, + messages=messages, api_base = "your-litellm-proxy-url", stream=True ) @@ -83,7 +85,123 @@ for chunk in response: print(chunk) ``` +## Embeddings -## **Usage with Langchain, LLamaindex, OpenAI Js, Anthropic SDK, Instructor** +```python +import litellm -#### [Follow this doc to see how to use litellm proxy with langchain, llamaindex, anthropic etc](../proxy/user_keys) \ No newline at end of file +response = litellm.embedding( + model="litellm_proxy/your-embedding-model", + input="Hello world", + api_base="your-litellm-proxy-url", + api_key="your-litellm-proxy-api-key" +) +``` + +## Image Generation + +```python +import litellm + +response = litellm.image_generation( + model="litellm_proxy/dall-e-3", + prompt="A beautiful sunset over mountains", + api_base="your-litellm-proxy-url", + api_key="your-litellm-proxy-api-key" +) +``` + +## Audio Transcription + +```python +import litellm + +response = litellm.transcription( + model="litellm_proxy/whisper-1", + file="your-audio-file", + api_base="your-litellm-proxy-url", + api_key="your-litellm-proxy-api-key" +) +``` + +## Text to Speech + +```python +import litellm + +response = litellm.speech( + model="litellm_proxy/tts-1", + input="Hello world", + api_base="your-litellm-proxy-url", + api_key="your-litellm-proxy-api-key" +) +``` + +## Rerank + +```python +import litellm + +import litellm + +response = litellm.rerank( + model="litellm_proxy/rerank-english-v2.0", + query="What is machine learning?", + documents=[ + "Machine learning is a field of study in artificial intelligence", + "Biology is the study of living organisms" + ], + api_base="your-litellm-proxy-url", + api_key="your-litellm-proxy-api-key" +) +``` + + +## Integration with Other Libraries + +LiteLLM Proxy works seamlessly with Langchain, LlamaIndex, OpenAI JS, Anthropic SDK, Instructor, and more. + +[Learn how to use LiteLLM proxy with these libraries →](../proxy/user_keys) + +## Send all SDK requests to LiteLLM Proxy + +Use this when calling LiteLLM Proxy from any library / codebase already using the LiteLLM SDK. + +These flags will route all requests through your LiteLLM proxy, regardless of the model specified. + +When enabled, requests will use `LITELLM_PROXY_API_BASE` with `LITELLM_PROXY_API_KEY` as the authentication. + +### Option 1: Set Globally in Code + +```python +# Set the flag globally for all requests +litellm.use_litellm_proxy = True + +response = litellm.completion( + model="vertex_ai/gemini-2.0-flash-001", + messages=[{"role": "user", "content": "Hello, how are you?"}] +) +``` + +### Option 2: Control via Environment Variable + +```python +# Control proxy usage through environment variable +os.environ["USE_LITELLM_PROXY"] = "True" + +response = litellm.completion( + model="vertex_ai/gemini-2.0-flash-001", + messages=[{"role": "user", "content": "Hello, how are you?"}] +) +``` + +### Option 3: Set Per Request + +```python +# Enable proxy for specific requests only +response = litellm.completion( + model="vertex_ai/gemini-2.0-flash-001", + messages=[{"role": "user", "content": "Hello, how are you?"}], + use_litellm_proxy=True +) +``` diff --git a/docs/my-website/docs/providers/llamafile.md b/docs/my-website/docs/providers/llamafile.md new file mode 100644 index 00000000000..3539bc2eb4f --- /dev/null +++ b/docs/my-website/docs/providers/llamafile.md @@ -0,0 +1,158 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Llamafile + +LiteLLM supports all models on Llamafile. + +| Property | Details | +|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| Description | llamafile lets you distribute and run LLMs with a single file. [Docs](https://github.com/Mozilla-Ocho/llamafile/blob/main/README.md) | +| Provider Route on LiteLLM | `llamafile/` (for OpenAI compatible server) | +| Provider Doc | [llamafile ↗](https://github.com/Mozilla-Ocho/llamafile/blob/main/llama.cpp/server/README.md#api-endpoints) | +| Supported Endpoints | `/chat/completions`, `/embeddings`, `/completions` | + + +# Quick Start + +## Usage - litellm.completion (calling OpenAI compatible endpoint) +llamafile Provides an OpenAI compatible endpoint for chat completions - here's how to call it with LiteLLM + +To use litellm to call llamafile add the following to your completion call + +* `model="llamafile/"` +* `api_base = "your-hosted-llamafile"` + +```python +import litellm + +response = litellm.completion( + model="llamafile/mistralai/mistral-7b-instruct-v0.2", # pass the llamafile model name for completeness + messages=messages, + api_base="http://localhost:8080/v1", + temperature=0.2, + max_tokens=80) + +print(response) +``` + + +## Usage - LiteLLM Proxy Server (calling OpenAI compatible endpoint) + +Here's how to call an OpenAI-Compatible Endpoint with the LiteLLM Proxy Server + +1. Modify the config.yaml + + ```yaml + model_list: + - model_name: my-model + litellm_params: + model: llamafile/mistralai/mistral-7b-instruct-v0.2 # add llamafile/ prefix to route as OpenAI provider + api_base: http://localhost:8080/v1 # add api base for OpenAI compatible provider + ``` + +1. Start the proxy + + ```bash + $ litellm --config /path/to/config.yaml + ``` + +1. Send Request to LiteLLM Proxy Server + + + + + + ```python + import openai + client = openai.OpenAI( + api_key="sk-1234", # pass litellm proxy key, if you're using virtual keys + base_url="http://0.0.0.0:4000" # litellm-proxy-base url + ) + + response = client.chat.completions.create( + model="my-model", + messages = [ + { + "role": "user", + "content": "what llm are you" + } + ], + ) + + print(response) + ``` + + + + + ```shell + curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Authorization: Bearer sk-1234' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "my-model", + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ], + }' + ``` + + + + + +## Embeddings + + + + +```python +from litellm import embedding +import os + +os.environ["LLAMAFILE_API_BASE"] = "http://localhost:8080/v1" + + +embedding = embedding(model="llamafile/sentence-transformers/all-MiniLM-L6-v2", input=["Hello world"]) + +print(embedding) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: my-model + litellm_params: + model: llamafile/sentence-transformers/all-MiniLM-L6-v2 # add llamafile/ prefix to route as OpenAI provider + api_base: http://localhost:8080/v1 # add api base for OpenAI compatible provider +``` + +1. Start the proxy + +```bash +$ litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +1. Test it! + +```bash +curl -L -X POST 'http://0.0.0.0:4000/embeddings' \ +-H 'Authorization: Bearer sk-1234' \ +-H 'Content-Type: application/json' \ +-d '{"input": ["hello world"], "model": "my-model"}' +``` + +[See OpenAI SDK/Langchain/etc. examples](../proxy/user_keys.md#embeddings) + + + \ No newline at end of file diff --git a/docs/my-website/docs/providers/lm_studio.md b/docs/my-website/docs/providers/lm_studio.md index ace138a5326..0cf9acff33d 100644 --- a/docs/my-website/docs/providers/lm_studio.md +++ b/docs/my-website/docs/providers/lm_studio.md @@ -69,7 +69,7 @@ for chunk in response: ## Usage with LiteLLM Proxy Server -Here's how to call a XAI model with the LiteLLM Proxy Server +Here's how to call a LM Studio model with the LiteLLM Proxy Server 1. Modify the config.yaml @@ -153,3 +153,26 @@ response = embedding( ) print(response) ``` + + +## Structured Output + +LM Studio supports structured outputs via JSON Schema. You can pass a pydantic model or a raw schema using `response_format`. +LiteLLM sends the schema as `{ "type": "json_schema", "json_schema": {"schema": } }`. + +```python +from pydantic import BaseModel +from litellm import completion + +class Book(BaseModel): + title: str + author: str + year: int + +response = completion( + model="lm_studio/llama-3-8b-instruct", + messages=[{"role": "user", "content": "Tell me about The Hobbit"}], + response_format=Book, +) +print(response.choices[0].message.content) +``` \ No newline at end of file diff --git a/docs/my-website/docs/providers/meta_llama.md b/docs/my-website/docs/providers/meta_llama.md new file mode 100644 index 00000000000..8219bef12b2 --- /dev/null +++ b/docs/my-website/docs/providers/meta_llama.md @@ -0,0 +1,205 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Meta Llama + +| Property | Details | +|-------|-------| +| Description | Meta's Llama API provides access to Meta's family of large language models. | +| Provider Route on LiteLLM | `meta_llama/` | +| Supported Endpoints | `/chat/completions`, `/completions`, `/responses` | +| API Reference | [Llama API Reference ↗](https://llama.developer.meta.com?utm_source=partner-litellm&utm_medium=website) | + +## Required Variables + +```python showLineNumbers title="Environment Variables" +os.environ["LLAMA_API_KEY"] = "" # your Meta Llama API key +``` + +## Supported Models + +:::info +All models listed here https://llama.developer.meta.com/docs/models/ are supported. We actively maintain the list of models, token window, etc. [here](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json). + +::: + + +| Model ID | Input context length | Output context length | Input Modalities | Output Modalities | +| --- | --- | --- | --- | --- | +| `Llama-4-Scout-17B-16E-Instruct-FP8` | 128k | 4028 | Text, Image | Text | +| `Llama-4-Maverick-17B-128E-Instruct-FP8` | 128k | 4028 | Text, Image | Text | +| `Llama-3.3-70B-Instruct` | 128k | 4028 | Text | Text | +| `Llama-3.3-8B-Instruct` | 128k | 4028 | Text | Text | + +## Usage - LiteLLM Python SDK + +### Non-streaming + +```python showLineNumbers title="Meta Llama Non-streaming Completion" +import os +import litellm +from litellm import completion + +os.environ["LLAMA_API_KEY"] = "" # your Meta Llama API key + +messages = [{"content": "Hello, how are you?", "role": "user"}] + +# Meta Llama call +response = completion(model="meta_llama/Llama-3.3-70B-Instruct", messages=messages) +``` + +### Streaming + +```python showLineNumbers title="Meta Llama Streaming Completion" +import os +import litellm +from litellm import completion + +os.environ["LLAMA_API_KEY"] = "" # your Meta Llama API key + +messages = [{"content": "Hello, how are you?", "role": "user"}] + +# Meta Llama call with streaming +response = completion( + model="meta_llama/Llama-3.3-70B-Instruct", + messages=messages, + stream=True +) + +for chunk in response: + print(chunk) +``` + + +## Usage - LiteLLM Proxy + + +Add the following to your LiteLLM Proxy configuration file: + +```yaml showLineNumbers title="config.yaml" +model_list: + - model_name: meta_llama/Llama-3.3-70B-Instruct + litellm_params: + model: meta_llama/Llama-3.3-70B-Instruct + api_key: os.environ/LLAMA_API_KEY + + - model_name: meta_llama/Llama-3.3-8B-Instruct + litellm_params: + model: meta_llama/Llama-3.3-8B-Instruct + api_key: os.environ/LLAMA_API_KEY +``` + +Start your LiteLLM Proxy server: + +```bash showLineNumbers title="Start LiteLLM Proxy" +litellm --config config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + + + + +```python showLineNumbers title="Meta Llama via Proxy - Non-streaming" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-proxy-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.chat.completions.create( + model="meta_llama/Llama-3.3-70B-Instruct", + messages=[{"role": "user", "content": "Write a short poem about AI."}] +) + +print(response.choices[0].message.content) +``` + +```python showLineNumbers title="Meta Llama via Proxy - Streaming" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-proxy-api-key" # Your proxy API key +) + +# Streaming response +response = client.chat.completions.create( + model="meta_llama/Llama-3.3-70B-Instruct", + messages=[{"role": "user", "content": "Write a short poem about AI."}], + stream=True +) + +for chunk in response: + if chunk.choices[0].delta.content is not None: + print(chunk.choices[0].delta.content, end="") +``` + + + + + +```python showLineNumbers title="Meta Llama via Proxy - LiteLLM SDK" +import litellm + +# Configure LiteLLM to use your proxy +response = litellm.completion( + model="litellm_proxy/meta_llama/Llama-3.3-70B-Instruct", + messages=[{"role": "user", "content": "Write a short poem about AI."}], + api_base="http://localhost:4000", + api_key="your-proxy-api-key" +) + +print(response.choices[0].message.content) +``` + +```python showLineNumbers title="Meta Llama via Proxy - LiteLLM SDK Streaming" +import litellm + +# Configure LiteLLM to use your proxy with streaming +response = litellm.completion( + model="litellm_proxy/meta_llama/Llama-3.3-70B-Instruct", + messages=[{"role": "user", "content": "Write a short poem about AI."}], + api_base="http://localhost:4000", + api_key="your-proxy-api-key", + stream=True +) + +for chunk in response: + if hasattr(chunk.choices[0], 'delta') and chunk.choices[0].delta.content is not None: + print(chunk.choices[0].delta.content, end="") +``` + + + + + +```bash showLineNumbers title="Meta Llama via Proxy - cURL" +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer your-proxy-api-key" \ + -d '{ + "model": "meta_llama/Llama-3.3-70B-Instruct", + "messages": [{"role": "user", "content": "Write a short poem about AI."}] + }' +``` + +```bash showLineNumbers title="Meta Llama via Proxy - cURL Streaming" +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer your-proxy-api-key" \ + -d '{ + "model": "meta_llama/Llama-3.3-70B-Instruct", + "messages": [{"role": "user", "content": "Write a short poem about AI."}], + "stream": true + }' +``` + + + + +For more detailed information on using the LiteLLM Proxy, see the [LiteLLM Proxy documentation](../providers/litellm_proxy). diff --git a/docs/my-website/docs/providers/novita.md b/docs/my-website/docs/providers/novita.md new file mode 100644 index 00000000000..f879ef4abac --- /dev/null +++ b/docs/my-website/docs/providers/novita.md @@ -0,0 +1,234 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Novita AI + +| Property | Details | +|-------|-------| +| Description | Novita AI is an AI cloud platform that helps developers easily deploy AI models through a simple API, backed by affordable and reliable GPU cloud infrastructure. LiteLLM supports all models from [Novita AI](https://novita.ai/models/llm?utm_source=github_litellm&utm_medium=github_readme&utm_campaign=github_link) | +| Provider Route on LiteLLM | `novita/` | +| Provider Doc | [Novita AI Docs ↗](https://novita.ai/docs/guides/introduction) | +| API Endpoint for Provider | https://api.novita.ai/v3/openai | +| Supported OpenAI Endpoints | `/chat/completions`, `/completions` | + +
+ +## API Keys + +Get your API key [here](https://novita.ai/settings/key-management) +```python +import os +os.environ["NOVITA_API_KEY"] = "your-api-key" +``` + +## Supported OpenAI Params +- max_tokens +- stream +- stream_options +- n +- seed +- frequency_penalty +- presence_penalty +- repetition_penalty +- stop +- temperature +- top_p +- top_k +- min_p +- logit_bias +- logprobs +- top_logprobs +- tools +- response_format +- separate_reasoning + + +## Sample Usage + + + + +```python +import os +from litellm import completion +os.environ["NOVITA_API_KEY"] = "" + +response = completion( + model="novita/deepseek/deepseek-r1-turbo", + messages=[{"role": "user", "content": "List 5 popular cookie recipes."}] +) + +content = response.get('choices', [{}])[0].get('message', {}).get('content') +print(content) +``` + + + + +1. Add model to config.yaml +```yaml +model_list: + - model_name: deepseek-r1-turbo + litellm_params: + model: novita/deepseek/deepseek-r1-turbo + api_key: os.environ/NOVITA_API_KEY +``` + +2. Start Proxy + +``` +$ litellm --config /path/to/config.yaml +``` + +3. Make Request! + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk_sujEQQEjTRxGUiMLN3TJh2KadRX4pw2TLWRoIKeoYZ0' \ +-d '{ + "model": "deepseek-r1-turbo", + "messages": [ + {"role": "user", "content": "List 5 popular cookie recipes."} + ] +} +' +``` + + + + + +## Tool Calling + +```python +from litellm import completion +import os +# set env +os.environ["NOVITA_API_KEY"] = "" + +tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + }, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}, + }, + "required": ["location"], + }, + }, + } +] +messages = [{"role": "user", "content": "What's the weather like in Boston today?"}] + +response = completion( + model="novita/deepseek/deepseek-r1-turbo", + messages=messages, + tools=tools, +) +# Add any assertions, here to check response args +print(response) +assert isinstance(response.choices[0].message.tool_calls[0].function.name, str) +assert isinstance( + response.choices[0].message.tool_calls[0].function.arguments, str +) + +``` + +## JSON Mode + + + + +```python +from litellm import completion +import json +import os + +os.environ['NOVITA_API_KEY'] = "" + +messages = [ + { + "role": "user", + "content": "List 5 popular cookie recipes." + } +] + +completion( + model="novita/deepseek/deepseek-r1-turbo", + messages=messages, + response_format={"type": "json_object"} # 👈 KEY CHANGE +) + +print(json.loads(completion.choices[0].message.content)) +``` + + + + +1. Add model to config.yaml +```yaml +model_list: + - model_name: deepseek-r1-turbo + litellm_params: + model: novita/deepseek/deepseek-r1-turbo + api_key: os.environ/NOVITA_API_KEY +``` + +2. Start Proxy + +``` +$ litellm --config /path/to/config.yaml +``` + +3. Make Request! + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "deepseek-r1-turbo", + "messages": [ + {"role": "user", "content": "List 5 popular cookie recipes."} + ], + "response_format": {"type": "json_object"} +} +' +``` + + + + + +## Chat Models + +🚨 LiteLLM supports ALL Novita AI models, send `model=novita/` to send it to Novita AI. See all Novita AI models [here](https://novita.ai/models/llm?utm_source=github_litellm&utm_medium=github_readme&utm_campaign=github_link) + +| Model Name | Function Call | +|---------------------------|-----------------------------------------------------| +| novita/deepseek/deepseek-r1-turbo | `completion('novita/deepseek/deepseek-r1-turbo', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/deepseek/deepseek-v3-turbo | `completion('novita/deepseek/deepseek-v3-turbo', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/deepseek/deepseek-v3-0324 | `completion('novita/deepseek/deepseek-v3-0324', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/qwen/qwen3-235b-a22b-fp8 | `completion('novita/qwen/qwen/qwen3-235b-a22b-fp8', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/qwen/qwen3-30b-a3b-fp8 | `completion('novita/qwen/qwen3-30b-a3b-fp8', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/qwen/qwen/qwen3-32b-fp8 | `completion('novita/qwen/qwen3-32b-fp8', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/qwen/qwen3-30b-a3b-fp8 | `completion('novita/qwen/qwen3-30b-a3b-fp8', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/qwen/qwen2.5-vl-72b-instruct | `completion('novita/qwen/qwen2.5-vl-72b-instruct', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/meta-llama/llama-4-maverick-17b-128e-instruct-fp8 | `completion('novita/meta-llama/llama-4-maverick-17b-128e-instruct-fp8', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/meta-llama/llama-3.3-70b-instruct | `completion('novita/meta-llama/llama-3.3-70b-instruct', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/meta-llama/llama-3.1-8b-instruct | `completion('novita/meta-llama/llama-3.1-8b-instruct', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/meta-llama/llama-3.1-8b-instruct-max | `completion('novita/meta-llama/llama-3.1-8b-instruct-max', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/meta-llama/llama-3.1-70b-instruct | `completion('novita/meta-llama/llama-3.1-70b-instruct', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/gryphe/mythomax-l2-13b | `completion('novita/gryphe/mythomax-l2-13b', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/google/gemma-3-27b-it | `completion('novita/google/gemma-3-27b-it', messages)` | `os.environ['NOVITA_API_KEY']` | +| novita/mistralai/mistral-nemo | `completion('novita/mistralai/mistral-nemo', messages)` | `os.environ['NOVITA_API_KEY']` | \ No newline at end of file diff --git a/docs/my-website/docs/providers/nscale.md b/docs/my-website/docs/providers/nscale.md new file mode 100644 index 00000000000..0413253a4be --- /dev/null +++ b/docs/my-website/docs/providers/nscale.md @@ -0,0 +1,180 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Nscale (EU Sovereign) + +https://docs.nscale.com/docs/inference/chat + +:::tip + +**We support ALL Nscale models, just set `model=nscale/` as a prefix when sending litellm requests** + +::: + +| Property | Details | +|-------|-------| +| Description | European-domiciled full-stack AI cloud platform for LLMs and image generation. | +| Provider Route on LiteLLM | `nscale/` | +| Supported Endpoints | `/chat/completions`, `/images/generations` | +| API Reference | [Nscale docs](https://docs.nscale.com/docs/getting-started/overview) | + +## Required Variables + +```python showLineNumbers title="Environment Variables" +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key +``` + +## Explore Available Models + +Explore our full list of text and multimodal AI models — all available at highly competitive pricing: +📚 [Full List of Models](https://docs.nscale.com/docs/inference/serverless-models/current) + + +## Key Features +- **EU Sovereign**: Full data sovereignty and compliance with European regulations +- **Ultra-Low Cost (starting at $0.01 / M tokens)**: Extremely competitive pricing for both text and image generation models +- **Production Grade**: Reliable serverless deployments with full isolation +- **No Setup Required**: Instant access to compute without infrastructure management +- **Full Control**: Your data remains private and isolated + +## Usage - LiteLLM Python SDK + +### Text Generation + +```python showLineNumbers title="Nscale Text Generation" +from litellm import completion +import os + +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key +response = completion( + model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}] +) +print(response) +``` + +```python showLineNumbers title="Nscale Text Generation - Streaming" +from litellm import completion +import os + +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key +stream = completion( + model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}], + stream=True +) + +for chunk in stream: + if chunk.choices[0].delta.content is not None: + print(chunk.choices[0].delta.content, end="") +``` + +### Image Generation + +```python showLineNumbers title="Nscale Image Generation" +from litellm import image_generation +import os + +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key +response = image_generation( + model="nscale/stabilityai/stable-diffusion-xl-base-1.0", + prompt="A beautiful sunset over mountains", + n=1, + size="1024x1024" +) +print(response) +``` + +## Usage - LiteLLM Proxy + +Add the following to your LiteLLM Proxy configuration file: + +```yaml showLineNumbers title="config.yaml" +model_list: + - model_name: nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct + litellm_params: + model: nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct + api_key: os.environ/NSCALE_API_KEY + - model_name: nscale/meta-llama/Llama-3.3-70B-Instruct + litellm_params: + model: nscale/meta-llama/Llama-3.3-70B-Instruct + api_key: os.environ/NSCALE_API_KEY + - model_name: nscale/stabilityai/stable-diffusion-xl-base-1.0 + litellm_params: + model: nscale/stabilityai/stable-diffusion-xl-base-1.0 + api_key: os.environ/NSCALE_API_KEY +``` + +Start your LiteLLM Proxy server: + +```bash showLineNumbers title="Start LiteLLM Proxy" +litellm --config config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + + + + +```python showLineNumbers title="Nscale via Proxy - Non-streaming" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-proxy-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.chat.completions.create( + model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}] +) + +print(response.choices[0].message.content) +``` + + + + + +```python showLineNumbers title="Nscale via Proxy - LiteLLM SDK" +import litellm + +# Configure LiteLLM to use your proxy +response = litellm.completion( + model="litellm_proxy/nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}], + api_base="http://localhost:4000", + api_key="your-proxy-api-key" +) + +print(response.choices[0].message.content) +``` + + + + + +```bash showLineNumbers title="Nscale via Proxy - cURL" +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer your-proxy-api-key" \ + -d '{ + "model": "nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + "messages": [{"role": "user", "content": "What is LiteLLM?"}] + }' +``` + + + + +## Getting Started +1. Create an account at [console.nscale.com](https://console.nscale.com) +2. Claim free credit +3. Create an API key in settings +4. Start making API calls using LiteLLM + +## Additional Resources +- [Nscale Documentation](https://docs.nscale.com/docs/getting-started/overview) +- [Blog: Sovereign Serverless](https://www.nscale.com/blog/sovereign-serverless-how-we-designed-full-isolation-without-sacrificing-performance) diff --git a/docs/my-website/docs/providers/nvidia_nim.md b/docs/my-website/docs/providers/nvidia_nim.md index 04390e7efec..270b356c917 100644 --- a/docs/my-website/docs/providers/nvidia_nim.md +++ b/docs/my-website/docs/providers/nvidia_nim.md @@ -10,10 +10,19 @@ https://docs.api.nvidia.com/nim/reference/ ::: +| Property | Details | +|-------|-------| +| Description | Nvidia NIM is a platform that provides a simple API for deploying and using AI models. LiteLLM supports all models from [Nvidia NIM](https://developer.nvidia.com/nim/) | +| Provider Route on LiteLLM | `nvidia_nim/` | +| Provider Doc | [Nvidia NIM Docs ↗](https://developer.nvidia.com/nim/) | +| API Endpoint for Provider | https://integrate.api.nvidia.com/v1/ | +| Supported OpenAI Endpoints | `/chat/completions`, `/completions`, `/responses`, `/embeddings` | + ## API Key ```python # env variable -os.environ['NVIDIA_NIM_API_KEY'] +os.environ['NVIDIA_NIM_API_KEY'] = "" +os.environ['NVIDIA_NIM_API_BASE'] = "" # [OPTIONAL] - default is https://integrate.api.nvidia.com/v1/ ``` ## Sample Usage @@ -100,6 +109,7 @@ Here's how to call an Nvidia NIM Endpoint with the LiteLLM Proxy Server litellm_params: model: nvidia_nim/ # add nvidia_nim/ prefix to route as Nvidia NIM provider api_key: api-key # api key to send your model + # api_base: "" # [OPTIONAL] - default is https://integrate.api.nvidia.com/v1/ ``` diff --git a/docs/my-website/docs/providers/ollama.md b/docs/my-website/docs/providers/ollama.md index 848be2beb7c..d59d9dd0cee 100644 --- a/docs/my-website/docs/providers/ollama.md +++ b/docs/my-website/docs/providers/ollama.md @@ -202,6 +202,67 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ + +## Using Ollama FIM on `/v1/completions` + +LiteLLM supports calling Ollama's `/api/generate` endpoint on `/v1/completions` requests. + + + + +```python +import litellm +litellm._turn_on_debug() # turn on debug to see the request +from litellm import completion + +response = completion( + model="ollama/llama3.1", + prompt="Hello, world!", + api_base="http://localhost:11434" +) +print(response) +``` + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: "llama3.1" + litellm_params: + model: "ollama/llama3.1" + api_base: "http://localhost:11434" +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml --detailed_debug + +# RUNNING ON http://0.0.0.0:4000 +``` + +3. Test it! + +```python +from openai import OpenAI + +client = OpenAI( + api_key="anything", # 👈 PROXY KEY (can be anything, if master_key not set) + base_url="http://0.0.0.0:4000" # 👈 PROXY BASE URL +) + +response = client.completions.create( + model="ollama/llama3.1", + prompt="Hello, world!", + api_base="http://localhost:11434" +) +print(response) +``` + + + ## Using ollama `api/chat` In order to send ollama requests to `POST /api/chat` on your ollama server, set the model prefix to `ollama_chat` diff --git a/docs/my-website/docs/providers/openai.md b/docs/my-website/docs/providers/openai.md index 15661f6521b..4fd75035fb0 100644 --- a/docs/my-website/docs/providers/openai.md +++ b/docs/my-website/docs/providers/openai.md @@ -156,13 +156,19 @@ print(response) ```python import os os.environ["OPENAI_ORGANIZATION"] = "your-org-id" # OPTIONAL -os.environ["OPENAI_API_BASE"] = "openaiai-api-base" # OPTIONAL +os.environ["OPENAI_BASE_URL"] = "https://your_host/v1" # OPTIONAL ``` ### OpenAI Chat Completion Models | Model Name | Function Call | |-----------------------|-----------------------------------------------------------------| +| gpt-4.1 | `response = completion(model="gpt-4.1", messages=messages)` | +| gpt-4.1-mini | `response = completion(model="gpt-4.1-mini", messages=messages)` | +| gpt-4.1-nano | `response = completion(model="gpt-4.1-nano", messages=messages)` | +| o4-mini | `response = completion(model="o4-mini", messages=messages)` | +| o3-mini | `response = completion(model="o3-mini", messages=messages)` | +| o3 | `response = completion(model="o3", messages=messages)` | | o1-mini | `response = completion(model="o1-mini", messages=messages)` | | o1-preview | `response = completion(model="o1-preview", messages=messages)` | | gpt-4o-mini | `response = completion(model="gpt-4o-mini", messages=messages)` | @@ -188,7 +194,7 @@ os.environ["OPENAI_API_BASE"] = "openaiai-api-base" # OPTIONAL | gpt-4-32k-0613 | `response = completion(model="gpt-4-32k-0613", messages=messages)` | -These also support the `OPENAI_API_BASE` environment variable, which can be used to specify a custom API endpoint. +These also support the `OPENAI_BASE_URL` environment variable, which can be used to specify a custom API endpoint. ## OpenAI Vision Models | Model Name | Function Call | @@ -228,6 +234,92 @@ response = completion( ``` +## PDF File Parsing + +OpenAI has a new `file` message type that allows you to pass in a PDF file and have it parsed into a structured output. [Read more](https://platform.openai.com/docs/guides/pdf-files?api-mode=chat&lang=python) + + + + +```python +import base64 +from litellm import completion + +with open("draconomicon.pdf", "rb") as f: + data = f.read() + +base64_string = base64.b64encode(data).decode("utf-8") + +completion = completion( + model="gpt-4o", + messages=[ + { + "role": "user", + "content": [ + { + "type": "file", + "file": { + "filename": "draconomicon.pdf", + "file_data": f"data:application/pdf;base64,{base64_string}", + } + }, + { + "type": "text", + "text": "What is the first dragon in the book?", + } + ], + }, + ], +) + +print(completion.choices[0].message.content) +``` + + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: openai-model + litellm_params: + model: gpt-4o + api_key: os.environ/OPENAI_API_KEY +``` + +2. Start the proxy + +```bash +litellm --config config.yaml +``` + +3. Test it! + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "openai-model", + "messages": [ + {"role": "user", "content": [ + { + "type": "file", + "file": { + "filename": "draconomicon.pdf", + "file_data": f"data:application/pdf;base64,{base64_string}", + } + } + ]} + ] +}' +``` + + + + ## OpenAI Fine Tuned Models | Model Name | Function Call | @@ -239,6 +331,74 @@ response = completion( | fine tuned `gpt-3.5-turbo-0613` | `response = completion(model="ft:gpt-3.5-turbo-0613", messages=messages)` | +## OpenAI Audio Transcription + +LiteLLM supports OpenAI Audio Transcription endpoint. + +Supported models: + +| Model Name | Function Call | +|---------------------------|-----------------------------------------------------------------| +| `whisper-1` | `response = completion(model="whisper-1", file=audio_file)` | +| `gpt-4o-transcribe` | `response = completion(model="gpt-4o-transcribe", file=audio_file)` | +| `gpt-4o-mini-transcribe` | `response = completion(model="gpt-4o-mini-transcribe", file=audio_file)` | + + + + +```python +from litellm import transcription +import os + +# set api keys +os.environ["OPENAI_API_KEY"] = "" +audio_file = open("/path/to/audio.mp3", "rb") + +response = transcription(model="gpt-4o-transcribe", file=audio_file) + +print(f"response: {response}") +``` + + + + +1. Setup config.yaml + +```yaml +model_list: +- model_name: gpt-4o-transcribe + litellm_params: + model: gpt-4o-transcribe + api_key: os.environ/OPENAI_API_KEY + model_info: + mode: audio_transcription + +general_settings: + master_key: sk-1234 +``` + +2. Start the proxy + +```bash +litellm --config config.yaml +``` + +3. Test it! + +```bash +curl --location 'http://0.0.0.0:8000/v1/audio/transcriptions' \ +--header 'Authorization: Bearer sk-1234' \ +--form 'file=@"/Users/krrishdholakia/Downloads/gettysburg.wav"' \ +--form 'model="gpt-4o-transcribe"' +``` + + + + + + + + ## Advanced ### Getting OpenAI API Response Headers @@ -449,26 +609,6 @@ response = litellm.acompletion( ) ``` -### Using Helicone Proxy with LiteLLM -```python -import os -import litellm -from litellm import completion - -os.environ["OPENAI_API_KEY"] = "" - -# os.environ["OPENAI_API_BASE"] = "" -litellm.api_base = "https://oai.hconeai.com/v1" -litellm.headers = { - "Helicone-Auth": f"Bearer {os.getenv('HELICONE_API_KEY')}", - "Helicone-Cache-Enabled": "true", -} - -messages = [{ "content": "Hello, how are you?","role": "user"}] - -# openai call -response = completion("gpt-3.5-turbo", messages) -``` ### Using OpenAI Proxy with LiteLLM ```python @@ -480,8 +620,8 @@ os.environ["OPENAI_API_KEY"] = "" # set custom api base to your proxy # either set .env or litellm.api_base -# os.environ["OPENAI_API_BASE"] = "" -litellm.api_base = "your-openai-proxy-url" +# os.environ["OPENAI_BASE_URL"] = "https://your_host/v1" +litellm.api_base = "https://your_host/v1" messages = [{ "content": "Hello, how are you?","role": "user"}] diff --git a/docs/my-website/docs/providers/openai/responses_api.md b/docs/my-website/docs/providers/openai/responses_api.md new file mode 100644 index 00000000000..578ce038f37 --- /dev/null +++ b/docs/my-website/docs/providers/openai/responses_api.md @@ -0,0 +1,320 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# OpenAI - Response API + +## Usage + +### LiteLLM Python SDK + + +#### Non-streaming +```python showLineNumbers title="OpenAI Non-streaming Response" +import litellm + +# Non-streaming response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="OpenAI Streaming Response" +import litellm + +# Streaming response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + +#### GET a Response +```python showLineNumbers title="Get Response by ID" +import litellm + +# First, create a response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +# Get the response ID +response_id = response.id + +# Retrieve the response by ID +retrieved_response = litellm.get_responses( + response_id=response_id +) + +print(retrieved_response) + +# For async usage +# retrieved_response = await litellm.aget_responses(response_id=response_id) +``` + +#### DELETE a Response +```python showLineNumbers title="Delete Response by ID" +import litellm + +# First, create a response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +# Get the response ID +response_id = response.id + +# Delete the response by ID +delete_response = litellm.delete_responses( + response_id=response_id +) + +print(delete_response) + +# For async usage +# delete_response = await litellm.adelete_responses(response_id=response_id) +``` + + +### LiteLLM Proxy with OpenAI SDK + +1. Set up config.yaml + +```yaml showLineNumbers title="OpenAI Proxy Configuration" +model_list: + - model_name: openai/o1-pro + litellm_params: + model: openai/o1-pro + api_key: os.environ/OPENAI_API_KEY +``` + +2. Start LiteLLM Proxy Server + +```bash title="Start LiteLLM Proxy Server" +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Use OpenAI SDK with LiteLLM Proxy + +#### Non-streaming +```python showLineNumbers title="OpenAI Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="OpenAI Proxy Streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + +#### GET a Response +```python showLineNumbers title="Get Response by ID with OpenAI SDK" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# First, create a response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +# Get the response ID +response_id = response.id + +# Retrieve the response by ID +retrieved_response = client.responses.retrieve(response_id) + +print(retrieved_response) +``` + +#### DELETE a Response +```python showLineNumbers title="Delete Response by ID with OpenAI SDK" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# First, create a response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +# Get the response ID +response_id = response.id + +# Delete the response by ID +delete_response = client.responses.delete(response_id) + +print(delete_response) +``` + + +## Supported Responses API Parameters + +| Provider | Supported Parameters | +|----------|---------------------| +| `openai` | [All Responses API parameters are supported](https://github.com/BerriAI/litellm/blob/7c3df984da8e4dff9201e4c5353fdc7a2b441831/litellm/llms/openai/responses/transformation.py#L23) | + +## Computer Use + + + + +```python +import litellm + +# Non-streaming response +response = litellm.responses( + model="computer-use-preview", + tools=[{ + "type": "computer_use_preview", + "display_width": 1024, + "display_height": 768, + "environment": "browser" # other possible values: "mac", "windows", "ubuntu" + }], + input=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Check the latest OpenAI news on bing.com." + } + # Optional: include a screenshot of the initial state of the environment + # { + # type: "input_image", + # image_url: f"data:image/png;base64,{screenshot_base64}" + # } + ] + } + ], + reasoning={ + "summary": "concise", + }, + truncation="auto" +) + +print(response.output) +``` + + + + +1. Set up config.yaml + +```yaml showLineNumbers title="OpenAI Proxy Configuration" +model_list: + - model_name: openai/o1-pro + litellm_params: + model: openai/o1-pro + api_key: os.environ/OPENAI_API_KEY +``` + +2. Start LiteLLM Proxy Server + +```bash title="Start LiteLLM Proxy Server" +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +```python showLineNumbers title="OpenAI Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="computer-use-preview", + tools=[{ + "type": "computer_use_preview", + "display_width": 1024, + "display_height": 768, + "environment": "browser" # other possible values: "mac", "windows", "ubuntu" + }], + input=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Check the latest OpenAI news on bing.com." + } + # Optional: include a screenshot of the initial state of the environment + # { + # type: "input_image", + # image_url: f"data:image/png;base64,{screenshot_base64}" + # } + ] + } + ], + reasoning={ + "summary": "concise", + }, + truncation="auto" +) + +print(response) +``` + + + + diff --git a/docs/my-website/docs/providers/openai/text_to_speech.md b/docs/my-website/docs/providers/openai/text_to_speech.md new file mode 100644 index 00000000000..34cd0f069e6 --- /dev/null +++ b/docs/my-website/docs/providers/openai/text_to_speech.md @@ -0,0 +1,122 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# OpenAI - Text-to-speech + +## **LiteLLM Python SDK Usage** +### Quick Start + +```python +from pathlib import Path +from litellm import speech +import os + +os.environ["OPENAI_API_KEY"] = "sk-.." + +speech_file_path = Path(__file__).parent / "speech.mp3" +response = speech( + model="openai/tts-1", + voice="alloy", + input="the quick brown fox jumped over the lazy dogs", + ) +response.stream_to_file(speech_file_path) +``` + +### Async Usage + +```python +from litellm import aspeech +from pathlib import Path +import os, asyncio + +os.environ["OPENAI_API_KEY"] = "sk-.." + +async def test_async_speech(): + speech_file_path = Path(__file__).parent / "speech.mp3" + response = await litellm.aspeech( + model="openai/tts-1", + voice="alloy", + input="the quick brown fox jumped over the lazy dogs", + api_base=None, + api_key=None, + organization=None, + project=None, + max_retries=1, + timeout=600, + client=None, + optional_params={}, + ) + response.stream_to_file(speech_file_path) + +asyncio.run(test_async_speech()) +``` + +## **LiteLLM Proxy Usage** + +LiteLLM provides an openai-compatible `/audio/speech` endpoint for Text-to-speech calls. + +```bash +curl http://0.0.0.0:4000/v1/audio/speech \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "tts-1", + "input": "The quick brown fox jumped over the lazy dog.", + "voice": "alloy" + }' \ + --output speech.mp3 +``` + +**Setup** + +```bash +- model_name: tts + litellm_params: + model: openai/tts-1 + api_key: os.environ/OPENAI_API_KEY +``` + +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +## Supported Models + +| Model | Example | +|-------|-------------| +| tts-1 | speech(model="tts-1", voice="alloy", input="Hello, world!") | +| tts-1-hd | speech(model="tts-1-hd", voice="alloy", input="Hello, world!") | +| gpt-4o-mini-tts | speech(model="gpt-4o-mini-tts", voice="alloy", input="Hello, world!") | + + +## ✨ Enterprise LiteLLM Proxy - Set Max Request File Size + +Use this when you want to limit the file size for requests sent to `audio/transcriptions` + +```yaml +- model_name: whisper + litellm_params: + model: whisper-1 + api_key: sk-******* + max_file_size_mb: 0.00001 # 👈 max file size in MB (Set this intentionally very small for testing) + model_info: + mode: audio_transcription +``` + +Make a test Request with a valid file +```shell +curl --location 'http://localhost:4000/v1/audio/transcriptions' \ +--header 'Authorization: Bearer sk-1234' \ +--form 'file=@"/Users/ishaanjaffer/Github/litellm/tests/gettysburg.wav"' \ +--form 'model="whisper"' +``` + + +Expect to see the follow response + +```shell +{"error":{"message":"File size is too large. Please check your file size. Passed file size: 0.7392807006835938 MB. Max file size: 0.0001 MB","type":"bad_request","param":"file","code":500}}% +``` \ No newline at end of file diff --git a/docs/my-website/docs/providers/openai_compatible.md b/docs/my-website/docs/providers/openai_compatible.md index c7f9bf6f40a..2f11379a8db 100644 --- a/docs/my-website/docs/providers/openai_compatible.md +++ b/docs/my-website/docs/providers/openai_compatible.md @@ -3,13 +3,26 @@ import TabItem from '@theme/TabItem'; # OpenAI-Compatible Endpoints +:::info + +Selecting `openai` as the provider routes your request to an OpenAI-compatible endpoint using the upstream +[official OpenAI Python API library](https://github.com/openai/openai-python/blob/main/README.md). + +This library **requires** an API key for all requests, either through the `api_key` parameter +or the `OPENAI_API_KEY` environment variable. + +If you don’t want to provide a fake API key in each request, consider using a provider that directly matches your +OpenAI-compatible endpoint, such as [`hosted_vllm`](/docs/providers/vllm) or [`llamafile`](/docs/providers/llamafile). + +::: + To call models hosted behind an openai proxy, make 2 changes: 1. For `/chat/completions`: Put `openai/` in front of your model name, so litellm knows you're trying to call an openai `/chat/completions` endpoint. -2. For `/completions`: Put `text-completion-openai/` in front of your model name, so litellm knows you're trying to call an openai `/completions` endpoint. [NOT REQUIRED for `openai/` endpoints called via `/v1/completions` route]. +1. For `/completions`: Put `text-completion-openai/` in front of your model name, so litellm knows you're trying to call an openai `/completions` endpoint. [NOT REQUIRED for `openai/` endpoints called via `/v1/completions` route]. -2. **Do NOT** add anything additional to the base url e.g. `/v1/embedding`. LiteLLM uses the openai-client to make these calls, and that automatically adds the relevant endpoints. +1. **Do NOT** add anything additional to the base url e.g. `/v1/embedding`. LiteLLM uses the openai-client to make these calls, and that automatically adds the relevant endpoints. ## Usage - completion diff --git a/docs/my-website/docs/providers/openrouter.md b/docs/my-website/docs/providers/openrouter.md index 09669c9f9ef..58a87f68495 100644 --- a/docs/my-website/docs/providers/openrouter.md +++ b/docs/my-website/docs/providers/openrouter.md @@ -10,9 +10,11 @@ LiteLLM supports all the text / chat / vision models from [OpenRouter](https://o import os from litellm import completion os.environ["OPENROUTER_API_KEY"] = "" +os.environ["OPENROUTER_API_BASE"] = "" # [OPTIONAL] defaults to https://openrouter.ai/api/v1 -os.environ["OR_SITE_URL"] = "" # optional -os.environ["OR_APP_NAME"] = "" # optional + +os.environ["OR_SITE_URL"] = "" # [OPTIONAL] +os.environ["OR_APP_NAME"] = "" # [OPTIONAL] response = completion( model="openrouter/google/palm-2-chat-bison", diff --git a/docs/my-website/docs/providers/perplexity.md b/docs/my-website/docs/providers/perplexity.md index 446f22b1f2f..5ef1f8861a6 100644 --- a/docs/my-website/docs/providers/perplexity.md +++ b/docs/my-website/docs/providers/perplexity.md @@ -17,7 +17,7 @@ import os os.environ['PERPLEXITYAI_API_KEY'] = "" response = completion( - model="perplexity/mistral-7b-instruct", + model="perplexity/sonar-pro", messages=messages ) print(response) @@ -30,7 +30,7 @@ import os os.environ['PERPLEXITYAI_API_KEY'] = "" response = completion( - model="perplexity/mistral-7b-instruct", + model="perplexity/sonar-pro", messages=messages, stream=True ) @@ -45,90 +45,19 @@ All models listed here https://docs.perplexity.ai/docs/model-cards are supported | Model Name | Function Call | |--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| pplx-7b-chat | `completion(model="perplexity/pplx-7b-chat", messages)` | -| pplx-70b-chat | `completion(model="perplexity/pplx-70b-chat", messages)` | -| pplx-7b-online | `completion(model="perplexity/pplx-7b-online", messages)` | -| pplx-70b-online | `completion(model="perplexity/pplx-70b-online", messages)` | -| codellama-34b-instruct | `completion(model="perplexity/codellama-34b-instruct", messages)` | -| llama-2-13b-chat | `completion(model="perplexity/llama-2-13b-chat", messages)` | -| llama-2-70b-chat | `completion(model="perplexity/llama-2-70b-chat", messages)` | -| mistral-7b-instruct | `completion(model="perplexity/mistral-7b-instruct", messages)` | -| openhermes-2-mistral-7b | `completion(model="perplexity/openhermes-2-mistral-7b", messages)` | -| openhermes-2.5-mistral-7b | `completion(model="perplexity/openhermes-2.5-mistral-7b", messages)` | -| pplx-7b-chat-alpha | `completion(model="perplexity/pplx-7b-chat-alpha", messages)` | -| pplx-70b-chat-alpha | `completion(model="perplexity/pplx-70b-chat-alpha", messages)` | +| sonar-deep-research | `completion(model="perplexity/sonar-deep-research", messages)` | +| sonar-reasoning-pro | `completion(model="perplexity/sonar-reasoning-pro", messages)` | +| sonar-reasoning | `completion(model="perplexity/sonar-reasoning", messages)` | +| sonar-pro | `completion(model="perplexity/sonar-pro", messages)` | +| sonar | `completion(model="perplexity/sonar", messages)` | +| r1-1776 | `completion(model="perplexity/r1-1776", messages)` | - -## Return citations - -Perplexity supports returning citations via `return_citations=True`. [Perplexity Docs](https://docs.perplexity.ai/reference/post_chat_completions). Note: Perplexity has this feature in **closed beta**, so you need them to grant you access to get citations from their API. - -If perplexity returns citations, LiteLLM will pass it straight through. - :::info -For passing more provider-specific, [go here](../completion/provider_specific_params.md) +For more information about passing provider-specific parameters, [go here](../completion/provider_specific_params.md) ::: - - - - -```python -from litellm import completion -import os - -os.environ['PERPLEXITYAI_API_KEY'] = "" -response = completion( - model="perplexity/mistral-7b-instruct", - messages=messages, - return_citations=True -) -print(response) -``` - - - - -1. Add perplexity to config.yaml - -```yaml -model_list: - - model_name: "perplexity-model" - litellm_params: - model: "llama-3.1-sonar-small-128k-online" - api_key: os.environ/PERPLEXITY_API_KEY -``` - -2. Start proxy - -```bash -litellm --config /path/to/config.yaml -``` - -3. Test it! - -```bash -curl -L -X POST 'http://0.0.0.0:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-1234' \ --d '{ - "model": "perplexity-model", - "messages": [ - { - "role": "user", - "content": "Who won the world cup in 2022?" - } - ], - "return_citations": true -}' -``` - -[**Call w/ OpenAI SDK, Langchain, Instructor, etc.**](../proxy/user_keys.md#chatcompletions) - - - diff --git a/docs/my-website/docs/providers/predibase.md b/docs/my-website/docs/providers/predibase.md index 31713aef1e8..9f25309c193 100644 --- a/docs/my-website/docs/providers/predibase.md +++ b/docs/my-website/docs/providers/predibase.md @@ -230,7 +230,7 @@ response = completion( model="predibase/llama-3-8b-instruct", messages = [{ "content": "Hello, how are you?","role": "user"}], adapter_id="my_repo/3", - adapter_soruce="pbase", + adapter_source="pbase", ) ``` diff --git a/docs/my-website/docs/providers/sambanova.md b/docs/my-website/docs/providers/sambanova.md index 9fa6ce8b609..290b64a1f09 100644 --- a/docs/my-website/docs/providers/sambanova.md +++ b/docs/my-website/docs/providers/sambanova.md @@ -1,12 +1,12 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Sambanova -https://community.sambanova.ai/t/create-chat-completion-api/ +# SambaNova +[https://cloud.sambanova.ai/](http://cloud.sambanova.ai?utm_source=litellm&utm_medium=external&utm_campaign=cloud_signup) :::tip -**We support ALL Sambanova models, just set `model=sambanova/` as a prefix when sending litellm requests. For the complete supported model list, visit https://sambanova.ai/technology/models ** +**We support ALL Sambanova models, just set `model=sambanova/` as a prefix when sending litellm requests. For the complete supported model list, visit https://docs.sambanova.ai/cloud/docs/get-started/supported-models ** ::: @@ -23,21 +23,17 @@ import os os.environ['SAMBANOVA_API_KEY'] = "" response = completion( - model="sambanova/Meta-Llama-3.1-8B-Instruct", + model="sambanova/Llama-4-Maverick-17B-128E-Instruct", messages=[ { "role": "user", - "content": "What do you know about sambanova.ai", + "content": "What do you know about SambaNova Systems", } ], max_tokens=10, - response_format={ "type": "json_object" }, - seed=123, - stop=["\n\n"], + stop=[], temperature=0.2, top_p=0.9, - tool_choice="auto", - tools=[], user="user", ) print(response) @@ -50,18 +46,17 @@ import os os.environ['SAMBANOVA_API_KEY'] = "" response = completion( - model="sambanova/Meta-Llama-3.1-8B-Instruct", + model="sambanova/Llama-4-Maverick-17B-128E-Instruct", messages=[ { "role": "user", - "content": "What do you know about sambanova.ai", + "content": "What do you know about SambaNova Systems", } ], stream=True, max_tokens=10, response_format={ "type": "json_object" }, - seed=123, - stop=["\n\n"], + stop=[], temperature=0.2, top_p=0.9, tool_choice="auto", @@ -141,3 +136,174 @@ Here's how to call a Sambanova model with the LiteLLM Proxy Server + +## SambaNova - Tool Calling + +```python +import litellm + +# Example dummy function + +def get_current_weather(location, unit="fahrenheit"): + if unit == "fahrenheit" + return{"location": location, "temperature": "72", "unit": "fahrenheit"} + else: + return{"location": location, "temperature": "22", "unit": "celsius"} + +messages = [{"role": "user", "content": "What's the weather like in San Francisco"}] + +tools = [ + { + "type": "function", + "function": { + "name": "import litellm", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + }, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}, + }, + "required": ["location"], + }, + }, + } +] + +response = litellm.completion( + model="sambanova/Meta-Llama-3.3-70B-Instruct", + messages=messages, + tools=tools, + tool_choice="auto", # auto is default, but we'll be explicit +) + +print("\nFirst LLM Response:\n", response) +response_message = response.choices[0].message +tool_calls = response_message.tool_calls + +if tool_calls: + # Step 2: check if the model wanted to call a function +if tool_calls: + # Step 3: call the function + # Note: the JSON response may not always be valid; be sure to handle errors + available_functions = { + "get_current_weather": get_current_weather, + } + messages.append( + response_message + ) # extend conversation with assistant's reply + print("Response message\n", response_message) + # Step 4: send the info for each function call and function response to the model + for tool_call in tool_calls: + function_name = tool_call.function.name + function_to_call = available_functions[function_name] + function_args = json.loads(tool_call.function.arguments) + function_response = function_to_call( + location=function_args.get("location"), + unit=function_args.get("unit"), + ) + messages.append( + { + "tool_call_id": tool_call.id, + "role": "tool", + "name": function_name, + "content": function_response, + } + ) # extend conversation with function response + print(f"messages: {messages}") + second_response = litellm.completion( + model="sambanova/Meta-Llama-3.3-70B-Instruct", messages=messages + ) # get a new response from the model where it can see the function response + print("second response\n", second_response) +``` + +## SambaNova - Vision Example + +```python +import litellm + +# Auxiliary function to get b64 images +def data_url_from_image(file_path): + mime_type, _ = mimetypes.guess_type(file_path) + if mime_type is None: + raise ValueError("Could not determine MIME type of the file") + + with open(file_path, "rb") as image_file: + encoded_string = base64.b64encode(image_file.read()).decode("utf-8") + + data_url = f"data:{mime_type};base64,{encoded_string}" + return data_url + +response = litellm.completion( + model = "sambanova/Llama-4-Maverick-17B-128E-Instruct", + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What's in this image?" + }, + { + "type": "image_url", + "image_url": { + "url": data_url_from_image("your_image_path"), + "format": "image/jpeg" + } + } + ] + } + ], + stream=False +) + +print(response.choices[0].message.content) +``` + + +## SambaNova - Structured Output + +```python +import litellm + +response = litellm.completion( + model="sambanova/Meta-Llama-3.3-70B-Instruct", + messages=[ + { + "role": "system", + "content": "You are an expert at structured data extraction. You will be given unstructured text should convert it into the given structure." + }, + { + "role": "user", + "content": "the section 24 has appliances, and videogames" + }, + ], + response_format={ + "type": "json_schema", + "json_schema": { + "title": "data", + "name": "data_extraction", + "schema": { + "type": "object", + "properties": { + "section": { + "type": "string" }, + "products": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": ["section", "products"], + "additionalProperties": False + }, + "strict": False + } + }, + stream=False +) + +print(response.choices[0].message.content)) +``` diff --git a/docs/my-website/docs/providers/snowflake.md b/docs/my-website/docs/providers/snowflake.md new file mode 100644 index 00000000000..c708613e2f5 --- /dev/null +++ b/docs/my-website/docs/providers/snowflake.md @@ -0,0 +1,90 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + +# Snowflake +| Property | Details | +|-------|-------| +| Description | The Snowflake Cortex LLM REST API lets you access the COMPLETE function via HTTP POST requests| +| Provider Route on LiteLLM | `snowflake/` | +| Link to Provider Doc | [Snowflake ↗](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-llm-rest-api) | +| Base URL | [https://{account-id}.snowflakecomputing.com/api/v2/cortex/inference:complete/](https://{account-id}.snowflakecomputing.com/api/v2/cortex/inference:complete) | +| Supported OpenAI Endpoints | `/chat/completions`, `/completions` | + + + +Currently, Snowflake's REST API does not have an endpoint for `snowflake-arctic-embed` embedding models. If you want to use these embedding models with Litellm, you can call them through our Hugging Face provider. + +Find the Arctic Embed models [here](https://huggingface.co/collections/Snowflake/arctic-embed-661fd57d50fab5fc314e4c18) on Hugging Face. + +## Supported OpenAI Parameters +``` + "temperature", + "max_tokens", + "top_p", + "response_format" +``` + +## API KEYS + +Snowflake does have API keys. Instead, you access the Snowflake API with your JWT token and account identifier. + +```python +import os +os.environ["SNOWFLAKE_JWT"] = "YOUR JWT" +os.environ["SNOWFLAKE_ACCOUNT_ID"] = "YOUR ACCOUNT IDENTIFIER" +``` +## Usage + +```python +from litellm import completion + +## set ENV variables +os.environ["SNOWFLAKE_JWT"] = "YOUR JWT" +os.environ["SNOWFLAKE_ACCOUNT_ID"] = "YOUR ACCOUNT IDENTIFIER" + +# Snowflake call +response = completion( + model="snowflake/mistral-7b", + messages = [{ "content": "Hello, how are you?","role": "user"}] +) +``` + +## Usage with LiteLLM Proxy + +#### 1. Required env variables +```bash +export SNOWFLAKE_JWT="" +export SNOWFLAKE_ACCOUNT_ID = "" +``` + +#### 2. Start the proxy~ +```yaml +model_list: + - model_name: mistral-7b + litellm_params: + model: snowflake/mistral-7b + api_key: YOUR_API_KEY + api_base: https://YOUR-ACCOUNT-ID.snowflakecomputing.com/api/v2/cortex/inference:complete + +``` + +```bash +litellm --config /path/to/config.yaml +``` + +#### 3. Test it +```shell +curl --location 'http://0.0.0.0:4000/chat/completions' \ +--header 'Content-Type: application/json' \ +--data ' { + "model": "snowflake/mistral-7b", + "messages": [ + { + "role": "user", + "content": "Hello, how are you?" + } + ] + } +' +``` diff --git a/docs/my-website/docs/providers/vertex.md b/docs/my-website/docs/providers/vertex.md index cb8c031c062..30887e9f60d 100644 --- a/docs/my-website/docs/providers/vertex.md +++ b/docs/my-website/docs/providers/vertex.md @@ -347,7 +347,7 @@ Return a `list[Recipe]` completion(model="vertex_ai/gemini-1.5-flash-preview-0514", messages=messages, response_format={ "type": "json_object" }) ``` -### **Grounding** +### **Grounding - Web Search** Add Google Search Result grounding to vertex ai calls. @@ -358,13 +358,13 @@ See the grounding metadata with `response_obj._hidden_params["vertex_ai_groundin -```python +```python showLineNumbers from litellm import completion ## SETUP ENVIRONMENT # !gcloud auth application-default login - run this to add vertex credentials to your env -tools = [{"googleSearchRetrieval": {}}] # 👈 ADD GOOGLE SEARCH +tools = [{"googleSearch": {}}] # 👈 ADD GOOGLE SEARCH resp = litellm.completion( model="vertex_ai/gemini-1.0-pro-001", @@ -377,41 +377,137 @@ print(resp) -```bash + + + +```python showLineNumbers +from openai import OpenAI + +client = OpenAI( + api_key="sk-1234", # pass litellm proxy key, if you're using virtual keys + base_url="http://0.0.0.0:4000/v1/" # point to litellm proxy +) + +response = client.chat.completions.create( + model="gemini-pro", + messages=[{"role": "user", "content": "Who won the world cup?"}], + tools=[{"googleSearch": {}}], +) + +print(response) +``` + + + +```bash showLineNumbers curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "model": "gemini-pro", "messages": [ - {"role": "user", "content": "Hello, Claude!"} + {"role": "user", "content": "Who won the world cup?"} ], "tools": [ { - "googleSearchRetrieval": {} + "googleSearch": {} } ] }' ``` + + +You can also use the `enterpriseWebSearch` tool for an [enterprise compliant search](https://cloud.google.com/vertex-ai/generative-ai/docs/grounding/web-grounding-enterprise). + + + + +```python showLineNumbers +from litellm import completion + +## SETUP ENVIRONMENT +# !gcloud auth application-default login - run this to add vertex credentials to your env + +tools = [{"enterpriseWebSearch": {}}] # 👈 ADD GOOGLE ENTERPRISE SEARCH + +resp = litellm.completion( + model="vertex_ai/gemini-1.0-pro-001", + messages=[{"role": "user", "content": "Who won the world cup?"}], + tools=tools, + ) + +print(resp) +``` + + + + + + +```python showLineNumbers +from openai import OpenAI + +client = OpenAI( + api_key="sk-1234", # pass litellm proxy key, if you're using virtual keys + base_url="http://0.0.0.0:4000/v1/" # point to litellm proxy +) + +response = client.chat.completions.create( + model="gemini-pro", + messages=[{"role": "user", "content": "Who won the world cup?"}], + tools=[{"enterpriseWebSearch": {}}], +) + +print(response) +``` + + + +```bash showLineNumbers +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gemini-pro", + "messages": [ + {"role": "user", "content": "Who won the world cup?"} + ], + "tools": [ + { + "enterpriseWebSearch": {} + } + ] + }' + +``` + + + + + + + #### **Moving from Vertex AI SDK to LiteLLM (GROUNDING)** If this was your initial VertexAI Grounding code, ```python -import vertexai +import vertexai +from vertexai.generative_models import GenerativeModel, GenerationConfig, Tool, grounding + vertexai.init(project=project_id, location="us-central1") model = GenerativeModel("gemini-1.5-flash-001") # Use Google Search for grounding -tool = Tool.from_google_search_retrieval(grounding.GoogleSearchRetrieval(disable_attributon=False)) +tool = Tool.from_google_search_retrieval(grounding.GoogleSearchRetrieval()) prompt = "When is the next total solar eclipse in US?" response = model.generate_content( @@ -428,12 +524,12 @@ print(response) then, this is what it looks like now ```python -from litellm import completion +from litellm import completion # !gcloud auth application-default login - run this to add vertex credentials to your env -tools = [{"googleSearchRetrieval": {"disable_attributon": False}}] # 👈 ADD GOOGLE SEARCH +tools = [{"googleSearch": {"disable_attributon": False}}] # 👈 ADD GOOGLE SEARCH resp = litellm.completion( model="vertex_ai/gemini-1.0-pro-001", @@ -446,9 +542,157 @@ print(resp) ``` +### **Thinking / `reasoning_content`** + +LiteLLM translates OpenAI's `reasoning_effort` to Gemini's `thinking` parameter. [Code](https://github.com/BerriAI/litellm/blob/620664921902d7a9bfb29897a7b27c1a7ef4ddfb/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py#L362) + +**Mapping** + +| reasoning_effort | thinking | +| ---------------- | -------- | +| "low" | "budget_tokens": 1024 | +| "medium" | "budget_tokens": 2048 | +| "high" | "budget_tokens": 4096 | + + + + +```python +from litellm import completion + +# !gcloud auth application-default login - run this to add vertex credentials to your env + +resp = completion( + model="vertex_ai/gemini-2.5-flash-preview-04-17", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", + vertex_project="project-id", + vertex_location="us-central1" +) + +``` + + + + + +1. Setup config.yaml + +```yaml +- model_name: gemini-2.5-flash + litellm_params: + model: vertex_ai/gemini-2.5-flash-preview-04-17 + vertex_credentials: {"project_id": "project-id", "location": "us-central1", "project_key": "project-key"} + vertex_project: "project-id" + vertex_location: "us-central1" +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "model": "gemini-2.5-flash", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "reasoning_effort": "low" + }' +``` + + + + + +**Expected Response** + +```python +ModelResponse( + id='chatcmpl-c542d76d-f675-4e87-8e5f-05855f5d0f5e', + created=1740470510, + model='claude-3-7-sonnet-20250219', + object='chat.completion', + system_fingerprint=None, + choices=[ + Choices( + finish_reason='stop', + index=0, + message=Message( + content="The capital of France is Paris.", + role='assistant', + tool_calls=None, + function_call=None, + reasoning_content='The capital of France is Paris. This is a very straightforward factual question.' + ), + ) + ], + usage=Usage( + completion_tokens=68, + prompt_tokens=42, + total_tokens=110, + completion_tokens_details=None, + prompt_tokens_details=PromptTokensDetailsWrapper( + audio_tokens=None, + cached_tokens=0, + text_tokens=None, + image_tokens=None + ), + cache_creation_input_tokens=0, + cache_read_input_tokens=0 + ) +) +``` + +#### Pass `thinking` to Gemini models + +You can also pass the `thinking` parameter to Gemini models. + +This is translated to Gemini's [`thinkingConfig` parameter](https://ai.google.dev/gemini-api/docs/thinking#set-budget). + + + + +```python +from litellm import completion + +# !gcloud auth application-default login - run this to add vertex credentials to your env + +response = litellm.completion( + model="vertex_ai/gemini-2.5-flash-preview-04-17", + messages=[{"role": "user", "content": "What is the capital of France?"}], + thinking={"type": "enabled", "budget_tokens": 1024}, + vertex_project="project-id", + vertex_location="us-central1" +) +``` + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "vertex_ai/gemini-2.5-flash-preview-04-17", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "thinking": {"type": "enabled", "budget_tokens": 1024} + }' +``` + + + + + ### **Context Caching** -Use Vertex AI context caching is supported by calling provider api directly. (Unified Endpoint support comin soon.). +Use Vertex AI context caching is supported by calling provider api directly. (Unified Endpoint support coming soon.). [**Go straight to provider**](../pass_through/vertex_ai.md#context-caching) @@ -666,7 +910,7 @@ export VERTEXAI_PROJECT="my-test-project" # ONLY use if model project is differe ## Specifying Safety Settings -In certain use-cases you may need to make calls to the models and pass [safety settigns](https://ai.google.dev/docs/safety_setting_gemini) different from the defaults. To do so, simple pass the `safety_settings` argument to `completion` or `acompletion`. For example: +In certain use-cases you may need to make calls to the models and pass [safety settings](https://ai.google.dev/docs/safety_setting_gemini) different from the defaults. To do so, simple pass the `safety_settings` argument to `completion` or `acompletion`. For example: ### Set per model/request @@ -852,6 +1096,7 @@ litellm.vertex_location = "us-central1 # Your Location | claude-3-5-sonnet@20240620 | `completion('vertex_ai/claude-3-5-sonnet@20240620', messages)` | | claude-3-sonnet@20240229 | `completion('vertex_ai/claude-3-sonnet@20240229', messages)` | | claude-3-haiku@20240307 | `completion('vertex_ai/claude-3-haiku@20240307', messages)` | +| claude-3-7-sonnet@20250219 | `completion('vertex_ai/claude-3-7-sonnet@20250219', messages)` | ### Usage @@ -926,11 +1171,131 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \ -## Llama 3 API + +### Usage - `thinking` / `reasoning_content` + + + + + +```python +from litellm import completion + +resp = completion( + model="vertex_ai/claude-3-7-sonnet-20250219", + messages=[{"role": "user", "content": "What is the capital of France?"}], + thinking={"type": "enabled", "budget_tokens": 1024}, +) + +``` + + + + + +1. Setup config.yaml + +```yaml +- model_name: claude-3-7-sonnet-20250219 + litellm_params: + model: vertex_ai/claude-3-7-sonnet-20250219 + vertex_ai_project: "my-test-project" + vertex_ai_location: "us-west-1" +``` + +2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +3. Test it! + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "model": "claude-3-7-sonnet-20250219", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "thinking": {"type": "enabled", "budget_tokens": 1024} + }' +``` + + + + + +**Expected Response** + +```python +ModelResponse( + id='chatcmpl-c542d76d-f675-4e87-8e5f-05855f5d0f5e', + created=1740470510, + model='claude-3-7-sonnet-20250219', + object='chat.completion', + system_fingerprint=None, + choices=[ + Choices( + finish_reason='stop', + index=0, + message=Message( + content="The capital of France is Paris.", + role='assistant', + tool_calls=None, + function_call=None, + provider_specific_fields={ + 'citations': None, + 'thinking_blocks': [ + { + 'type': 'thinking', + 'thinking': 'The capital of France is Paris. This is a very straightforward factual question.', + 'signature': 'EuYBCkQYAiJAy6...' + } + ] + } + ), + thinking_blocks=[ + { + 'type': 'thinking', + 'thinking': 'The capital of France is Paris. This is a very straightforward factual question.', + 'signature': 'EuYBCkQYAiJAy6AGB...' + } + ], + reasoning_content='The capital of France is Paris. This is a very straightforward factual question.' + ) + ], + usage=Usage( + completion_tokens=68, + prompt_tokens=42, + total_tokens=110, + completion_tokens_details=None, + prompt_tokens_details=PromptTokensDetailsWrapper( + audio_tokens=None, + cached_tokens=0, + text_tokens=None, + image_tokens=None + ), + cache_creation_input_tokens=0, + cache_read_input_tokens=0 + ) +) +``` + + + +## Meta/Llama API | Model Name | Function Call | |------------------|--------------------------------------| +| meta/llama-3.2-90b-vision-instruct-maas | `completion('vertex_ai/meta/llama-3.2-90b-vision-instruct-maas', messages)` | +| meta/llama3-8b-instruct-maas | `completion('vertex_ai/meta/llama3-8b-instruct-maas', messages)` | +| meta/llama3-70b-instruct-maas | `completion('vertex_ai/meta/llama3-70b-instruct-maas', messages)` | | meta/llama3-405b-instruct-maas | `completion('vertex_ai/meta/llama3-405b-instruct-maas', messages)` | +| meta/llama-4-scout-17b-16e-instruct-maas | `completion('vertex_ai/meta/llama-4-scout-17b-16e-instruct-maas', messages)` | +| meta/llama-4-scout-17-128e-instruct-maas | `completion('vertex_ai/meta/llama-4-scout-128b-16e-instruct-maas', messages)` | +| meta/llama-4-maverick-17b-128e-instruct-maas | `completion('vertex_ai/meta/llama-4-maverick-17b-128e-instruct-maas',messages)` | +| meta/llama-4-maverick-17b-16e-instruct-maas | `completion('vertex_ai/meta/llama-4-maverick-17b-16e-instruct-maas',messages)` | ### Usage @@ -1253,6 +1618,103 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \ +## Gemini Pro +| Model Name | Function Call | +|------------------|--------------------------------------| +| gemini-pro | `completion('gemini-pro', messages)`, `completion('vertex_ai/gemini-pro', messages)` | + +## Fine-tuned Models + +You can call fine-tuned Vertex AI Gemini models through LiteLLM + +| Property | Details | +|----------|---------| +| Provider Route | `vertex_ai/gemini/{MODEL_ID}` | +| Vertex Documentation | [Vertex AI - Fine-tuned Gemini Models](https://cloud.google.com/vertex-ai/generative-ai/docs/models/gemini-use-supervised-tuning#test_the_tuned_model_with_a_prompt)| +| Supported Operations | `/chat/completions`, `/completions`, `/embeddings`, `/images` | + +To use a model that follows the `/gemini` request/response format, simply set the model parameter as + +```python title="Model parameter for calling fine-tuned gemini models" +model="vertex_ai/gemini/" +``` + + + + +```python showLineNumbers title="Example" +import litellm +import os + +## set ENV variables +os.environ["VERTEXAI_PROJECT"] = "hardy-device-38811" +os.environ["VERTEXAI_LOCATION"] = "us-central1" + +response = litellm.completion( + model="vertex_ai/gemini/", # e.g. vertex_ai/gemini/4965075652664360960 + messages=[{ "content": "Hello, how are you?","role": "user"}], +) +``` + + + + +1. Add Vertex Credentials to your env + +```bash title="Authenticate to Vertex AI" +!gcloud auth application-default login +``` + +2. Setup config.yaml + +```yaml showLineNumbers title="Add to litellm config" +- model_name: finetuned-gemini + litellm_params: + model: vertex_ai/gemini/ + vertex_project: + vertex_location: +``` + +3. Test it! + + + + +```python showLineNumbers title="Example request" +from openai import OpenAI + +client = OpenAI( + api_key="your-litellm-key", + base_url="http://0.0.0.0:4000" +) + +response = client.chat.completions.create( + model="finetuned-gemini", + messages=[ + {"role": "user", "content": "hi"} + ] +) +print(response) +``` + + + + +```bash showLineNumbers title="Example request" +curl --location 'https://0.0.0.0:4000/v1/chat/completions' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: ' \ +--data '{"model": "finetuned-gemini" ,"messages":[{"role": "user", "content":[{"type": "text", "text": "hi"}]}]}' +``` + + + + + + + + + ## Model Garden :::tip @@ -1363,67 +1825,6 @@ response = completion( -## Gemini Pro -| Model Name | Function Call | -|------------------|--------------------------------------| -| gemini-pro | `completion('gemini-pro', messages)`, `completion('vertex_ai/gemini-pro', messages)` | - -## Fine-tuned Models - -Fine tuned models on vertex have a numerical model/endpoint id. - - - - -```python -from litellm import completion -import os - -## set ENV variables -os.environ["VERTEXAI_PROJECT"] = "hardy-device-38811" -os.environ["VERTEXAI_LOCATION"] = "us-central1" - -response = completion( - model="vertex_ai/", # e.g. vertex_ai/4965075652664360960 - messages=[{ "content": "Hello, how are you?","role": "user"}], - base_model="vertex_ai/gemini-1.5-pro" # the base model - used for routing -) -``` - - - - -1. Add Vertex Credentials to your env - -```bash -!gcloud auth application-default login -``` - -2. Setup config.yaml - -```yaml -- model_name: finetuned-gemini - litellm_params: - model: vertex_ai/ - vertex_project: - vertex_location: - model_info: - base_model: vertex_ai/gemini-1.5-pro # IMPORTANT -``` - -3. Test it! - -```bash -curl --location 'https://0.0.0.0:4000/v1/chat/completions' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: ' \ ---data '{"model": "finetuned-gemini" ,"messages":[{"role": "user", "content":[{"type": "text", "text": "hi"}]}]}' -``` - - - - - ## Gemini Pro Vision | Model Name | Function Call | @@ -1568,15 +1969,25 @@ assert isinstance( ``` -## Usage - PDF / Videos / etc. Files +## Usage - PDF / Videos / Audio etc. Files Pass any file supported by Vertex AI, through LiteLLM. +LiteLLM Supports the following file types passed in url. + +Using `file` message type for VertexAI is live from v1.65.1+ + +``` +Files with Cloud Storage URIs - gs://cloud-samples-data/generative-ai/image/boats.jpeg +Files with direct links - https://storage.googleapis.com/github-repo/img/gemini/intro/landmark3.jpg +Videos with Cloud Storage URIs - https://storage.googleapis.com/github-repo/img/gemini/multimodality_usecases_overview/pixel8.mp4 +Base64 Encoded Local Files +``` -### **Using `gs://`** +### **Using `gs://` or any URL** ```python from litellm import completion @@ -1588,8 +1999,11 @@ response = completion( "content": [ {"type": "text", "text": "You are a very professional document summarization specialist. Please summarize the given document."}, { - "type": "image_url", - "image_url": "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", # 👈 PDF + "type": "file", + "file": { + "file_id": "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", + "format": "application/pdf" # OPTIONAL - specify mime-type + } }, ], } @@ -1623,8 +2037,16 @@ response = completion( "content": [ {"type": "text", "text": "You are a very professional document summarization specialist. Please summarize the given document."}, { - "type": "image_url", - "image_url": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + "type": "file", + "file": { + "file_data": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + } + }, + { + "type": "audio_input", + "audio_input { + "audio_input": f"data:audio/mp3;base64,{encoded_file}", # 👈 AUDIO File ('file' message works as too) + } }, ], } @@ -1635,7 +2057,7 @@ response = completion( print(response.choices[0]) ``` - + 1. Add model to config @@ -1670,8 +2092,11 @@ curl http://0.0.0.0:4000/v1/chat/completions \ "text": "You are a very professional document summarization specialist. Please summarize the given document" }, { - "type": "image_url", - "image_url": "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf" # 👈 PDF + "type": "file", + "file": { + "file_id": "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", + "format": "application/pdf" # OPTIONAL + } } } ] @@ -1698,11 +2123,18 @@ curl http://0.0.0.0:4000/v1/chat/completions \ "text": "You are a very professional document summarization specialist. Please summarize the given document" }, { - "type": "image_url", - "image_url": "data:application/pdf;base64,{encoded_file}" # 👈 PDF - } - } - ] + "type": "file", + "file": { + "file_data": f"data:application/pdf;base64,{encoded_file}", # 👈 PDF + }, + }, + { + "type": "audio_input", + "audio_input { + "audio_input": f"data:audio/mp3;base64,{encoded_file}", # 👈 AUDIO File ('file' message works as too) + } + }, + ] } ], "max_tokens": 300 @@ -1712,6 +2144,7 @@ curl http://0.0.0.0:4000/v1/chat/completions \ + ## Chat Models | Model Name | Function Call | |------------------|--------------------------------------| @@ -1920,7 +2353,12 @@ print(response) ## **Multi-Modal Embeddings** -Usage + +Known Limitations: +- Only supports 1 image / video / image per request +- Only supports GCS or base64 encoded images / videos + +### Usage @@ -2136,6 +2574,115 @@ print(f"Text Embedding: {embeddings.text_embedding}") +### Text + Image + Video Embeddings + + + + +Text + Image + +```python +response = await litellm.aembedding( + model="vertex_ai/multimodalembedding@001", + input=["hey", "gs://cloud-samples-data/vertex-ai/llm/prompts/landmark1.png"] # will be sent as a gcs image +) +``` + +Text + Video + +```python +response = await litellm.aembedding( + model="vertex_ai/multimodalembedding@001", + input=["hey", "gs://my-bucket/embeddings/supermarket-video.mp4"] # will be sent as a gcs image +) +``` + +Image + Video + +```python +response = await litellm.aembedding( + model="vertex_ai/multimodalembedding@001", + input=["gs://cloud-samples-data/vertex-ai/llm/prompts/landmark1.png", "gs://my-bucket/embeddings/supermarket-video.mp4"] # will be sent as a gcs image +) +``` + + + + + +1. Add model to config.yaml +```yaml +model_list: + - model_name: multimodalembedding@001 + litellm_params: + model: vertex_ai/multimodalembedding@001 + vertex_project: "adroit-crow-413218" + vertex_location: "us-central1" + vertex_credentials: adroit-crow-413218-a956eef1a2a8.json + +litellm_settings: + drop_params: True +``` + +2. Start Proxy + +``` +$ litellm --config /path/to/config.yaml +``` + +3. Make Request use OpenAI Python SDK, Langchain Python SDK + + +Text + Image + +```python +import openai + +client = openai.OpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") + +# # request sent to model set on litellm proxy, `litellm --model` +response = client.embeddings.create( + model="multimodalembedding@001", + input = ["hey", "gs://cloud-samples-data/vertex-ai/llm/prompts/landmark1.png"], +) + +print(response) +``` + +Text + Video +```python +import openai + +client = openai.OpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") + +# # request sent to model set on litellm proxy, `litellm --model` +response = client.embeddings.create( + model="multimodalembedding@001", + input = ["hey", "gs://my-bucket/embeddings/supermarket-video.mp4"], +) + +print(response) +``` + +Image + Video +```python +import openai + +client = openai.OpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") + +# # request sent to model set on litellm proxy, `litellm --model` +response = client.embeddings.create( + model="multimodalembedding@001", + input = ["gs://cloud-samples-data/vertex-ai/llm/prompts/landmark1.png", "gs://my-bucket/embeddings/supermarket-video.mp4"], +) + +print(response) +``` + + + + + ## **Image Generation Models** Usage diff --git a/docs/my-website/docs/providers/vllm.md b/docs/my-website/docs/providers/vllm.md index 9cc0ad487e5..5c8233b0564 100644 --- a/docs/my-website/docs/providers/vllm.md +++ b/docs/my-website/docs/providers/vllm.md @@ -157,6 +157,216 @@ curl -L -X POST 'http://0.0.0.0:4000/embeddings' \ +## Send Video URL to VLLM + +Example Implementation from VLLM [here](https://github.com/vllm-project/vllm/pull/10020) + + + + +Use this to send a video url to VLLM + Gemini in the same format, using OpenAI's `files` message type. + +There are two ways to send a video url to VLLM: + +1. Pass the video url directly + +``` +{"type": "file", "file": {"file_id": video_url}}, +``` + +2. Pass the video data as base64 + +``` +{"type": "file", "file": {"file_data": f"data:video/mp4;base64,{video_data_base64}"}} +``` + + + + +```python +from litellm import completion + +messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Summarize the following video" + }, + { + "type": "file", + "file": { + "file_id": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" + } + } + ] + } +] + +# call vllm +os.environ["HOSTED_VLLM_API_BASE"] = "https://hosted-vllm-api.co" +os.environ["HOSTED_VLLM_API_KEY"] = "" # [optional], if your VLLM server requires an API key +response = completion( + model="hosted_vllm/qwen", # pass the vllm model name + messages=messages, +) + +# call gemini +os.environ["GEMINI_API_KEY"] = "your-gemini-api-key" +response = completion( + model="gemini/gemini-1.5-flash", # pass the gemini model name + messages=messages, +) + +print(response) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: my-model + litellm_params: + model: hosted_vllm/qwen # add hosted_vllm/ prefix to route as OpenAI provider + api_base: https://hosted-vllm-api.co # add api base for OpenAI compatible provider + - model_name: my-gemini-model + litellm_params: + model: gemini/gemini-1.5-flash # add gemini/ prefix to route as Google AI Studio provider + api_key: os.environ/GEMINI_API_KEY +``` + +2. Start the proxy + +```bash +$ litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +```bash +curl -X POST http://0.0.0.0:4000/chat/completions \ +-H "Authorization: Bearer sk-1234" \ +-H "Content-Type: application/json" \ +-d '{ + "model": "my-model", + "messages": [ + {"role": "user", "content": + [ + {"type": "text", "text": "Summarize the following video"}, + {"type": "file", "file": {"file_id": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}} + ] + } + ] +}' +``` + + + + + + + + +Use this to send a video url to VLLM in it's native message format (`video_url`). + +There are two ways to send a video url to VLLM: + +1. Pass the video url directly + +``` +{"type": "video_url", "video_url": {"url": video_url}}, +``` + +2. Pass the video data as base64 + +``` +{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_data_base64}"}} +``` + + + + +```python +from litellm import completion + +response = completion( + model="hosted_vllm/qwen", # pass the vllm model name + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Summarize the following video" + }, + { + "type": "video_url", + "video_url": { + "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" + } + } + ] + } + ], + api_base="https://hosted-vllm-api.co") + +print(response) +``` + + + + +1. Setup config.yaml + +```yaml +model_list: + - model_name: my-model + litellm_params: + model: hosted_vllm/qwen # add hosted_vllm/ prefix to route as OpenAI provider + api_base: https://hosted-vllm-api.co # add api base for OpenAI compatible provider +``` + +2. Start the proxy + +```bash +$ litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Test it! + +```bash +curl -X POST http://0.0.0.0:4000/chat/completions \ +-H "Authorization: Bearer sk-1234" \ +-H "Content-Type: application/json" \ +-d '{ + "model": "my-model", + "messages": [ + {"role": "user", "content": + [ + {"type": "text", "text": "Summarize the following video"}, + {"type": "video_url", "video_url": {"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}} + ] + } + ] +}' +``` + + + + + + + + + ## (Deprecated) for `vllm pip package` ### Using - `litellm.completion` diff --git a/docs/my-website/docs/providers/xai.md b/docs/my-website/docs/providers/xai.md index 131c02b3dc7..49a3640991d 100644 --- a/docs/my-website/docs/providers/xai.md +++ b/docs/my-website/docs/providers/xai.md @@ -1,13 +1,13 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# XAI +# xAI https://docs.x.ai/docs :::tip -**We support ALL XAI models, just set `model=xai/` as a prefix when sending litellm requests** +**We support ALL xAI models, just set `model=xai/` as a prefix when sending litellm requests** ::: @@ -18,13 +18,14 @@ os.environ['XAI_API_KEY'] ``` ## Sample Usage -```python + +```python showLineNumbers title="LiteLLM python sdk usage - Non-streaming" from litellm import completion import os os.environ['XAI_API_KEY'] = "" response = completion( - model="xai/grok-beta", + model="xai/grok-3-mini-beta", messages=[ { "role": "user", @@ -45,13 +46,14 @@ print(response) ``` ## Sample Usage - Streaming -```python + +```python showLineNumbers title="LiteLLM python sdk usage - Streaming" from litellm import completion import os os.environ['XAI_API_KEY'] = "" response = completion( - model="xai/grok-beta", + model="xai/grok-3-mini-beta", messages=[ { "role": "user", @@ -74,6 +76,36 @@ for chunk in response: print(chunk) ``` +## Sample Usage - Vision + +```python showLineNumbers title="LiteLLM python sdk usage - Vision" +import os +from litellm import completion + +os.environ["XAI_API_KEY"] = "your-api-key" + +response = completion( + model="xai/grok-2-vision-latest", + messages=[ + { + "role": "user", + "content": [ + { + "type": "image_url", + "image_url": { + "url": "https://science.nasa.gov/wp-content/uploads/2023/09/web-first-images-release.png", + "detail": "high", + }, + }, + { + "type": "text", + "text": "What's in this image?", + }, + ], + }, + ], +) +``` ## Usage with LiteLLM Proxy Server @@ -81,7 +113,7 @@ Here's how to call a XAI model with the LiteLLM Proxy Server 1. Modify the config.yaml - ```yaml + ```yaml showLineNumbers model_list: - model_name: my-model litellm_params: @@ -102,7 +134,7 @@ Here's how to call a XAI model with the LiteLLM Proxy Server - ```python + ```python showLineNumbers import openai client = openai.OpenAI( api_key="sk-1234", # pass litellm proxy key, if you're using virtual keys @@ -144,3 +176,81 @@ Here's how to call a XAI model with the LiteLLM Proxy Server +## Reasoning Usage + +LiteLLM supports reasoning usage for xAI models. + + + + + +```python showLineNumbers title="reasoning with xai/grok-3-mini-beta" +import litellm +response = litellm.completion( + model="xai/grok-3-mini-beta", + messages=[{"role": "user", "content": "What is 101*3?"}], + reasoning_effort="low", +) + +print("Reasoning Content:") +print(response.choices[0].message.reasoning_content) + +print("\nFinal Response:") +print(completion.choices[0].message.content) + +print("\nNumber of completion tokens (input):") +print(completion.usage.completion_tokens) + +print("\nNumber of reasoning tokens (input):") +print(completion.usage.completion_tokens_details.reasoning_tokens) +``` + + + + +```python showLineNumbers title="reasoning with xai/grok-3-mini-beta" +import openai +client = openai.OpenAI( + api_key="sk-1234", # pass litellm proxy key, if you're using virtual keys + base_url="http://0.0.0.0:4000" # litellm-proxy-base url +) + +response = client.chat.completions.create( + model="xai/grok-3-mini-beta", + messages=[{"role": "user", "content": "What is 101*3?"}], + reasoning_effort="low", +) + +print("Reasoning Content:") +print(response.choices[0].message.reasoning_content) + +print("\nFinal Response:") +print(completion.choices[0].message.content) + +print("\nNumber of completion tokens (input):") +print(completion.usage.completion_tokens) + +print("\nNumber of reasoning tokens (input):") +print(completion.usage.completion_tokens_details.reasoning_tokens) +``` + + + + +**Example Response:** + +```shell +Reasoning Content: +Let me calculate 101 multiplied by 3: +101 * 3 = 303. +I can double-check that: 100 * 3 is 300, and 1 * 3 is 3, so 300 + 3 = 303. Yes, that's correct. + +Final Response: +The result of 101 multiplied by 3 is 303. + +Number of completion tokens (input): +14 + +Number of reasoning tokens (input): +310 +``` diff --git a/docs/my-website/docs/proxy/access_control.md b/docs/my-website/docs/proxy/access_control.md index 3d335380f4f..69b8a3ff6de 100644 --- a/docs/my-website/docs/proxy/access_control.md +++ b/docs/my-website/docs/proxy/access_control.md @@ -10,17 +10,13 @@ Role-based access control (RBAC) is based on Organizations, Teams and Internal U ## Roles -**Admin Roles** - - `proxy_admin`: admin over the platform - - `proxy_admin_viewer`: can login, view all keys, view all spend. **Cannot** create keys/delete keys/add new users - -**Organization Roles** - - `org_admin`: admin over the organization. Can create teams and users within their organization - -**Internal User Roles** - - `internal_user`: can login, view/create/delete their own keys, view their spend. **Cannot** add new users. - - `internal_user_viewer`: can login, view their own keys, view their own spend. **Cannot** create/delete keys, add new users. - +| Role Type | Role Name | Permissions | +|-----------|-----------|-------------| +| **Admin** | `proxy_admin` | Admin over the platform | +| | `proxy_admin_viewer` | Can login, view all keys, view all spend. **Cannot** create keys/delete keys/add new users | +| **Organization** | `org_admin` | Admin over the organization. Can create teams and users within their organization | +| **Internal User** | `internal_user` | Can login, view/create/delete their own keys, view their spend. **Cannot** add new users | +| | `internal_user_viewer` | Can login, view their own keys, view their own spend. **Cannot** create/delete keys, add new users | ## Onboarding Organizations diff --git a/docs/my-website/docs/proxy/admin_ui_sso.md b/docs/my-website/docs/proxy/admin_ui_sso.md index b7f8ddd585e..a0dde80e9cf 100644 --- a/docs/my-website/docs/proxy/admin_ui_sso.md +++ b/docs/my-website/docs/proxy/admin_ui_sso.md @@ -147,11 +147,16 @@ Some SSO providers require a specific redirect url for login and logout. You can - Login: `/sso/key/generate` - Logout: `` +Here's the env var to set the logout url on the proxy +```bash +PROXY_LOGOUT_URL="https://www.google.com" +``` + #### Step 3. Set `PROXY_BASE_URL` in your .env Set this in your .env (so the proxy can set the correct redirect url) ```shell -PROXY_BASE_URL=https://litellm-api.up.railway.app/ +PROXY_BASE_URL=https://litellm-api.up.railway.app ``` #### Step 4. Test flow @@ -238,12 +243,12 @@ We allow you to pass a local image or a an http/https url of your image Set `UI_LOGO_PATH` on your env. We recommend using a hosted image, it's a lot easier to set up and configure / debug -Exaple setting Hosted image +Example setting Hosted image ```shell UI_LOGO_PATH="https://litellm-logo-aws-marketplace.s3.us-west-2.amazonaws.com/berriai-logo-github.png" ``` -Exaple setting a local image (on your container) +Example setting a local image (on your container) ```shell UI_LOGO_PATH="ui_images/logo.jpg" ``` diff --git a/docs/my-website/docs/proxy/alerting.md b/docs/my-website/docs/proxy/alerting.md index c2fc510d962..e2f6223c8fb 100644 --- a/docs/my-website/docs/proxy/alerting.md +++ b/docs/my-website/docs/proxy/alerting.md @@ -213,7 +213,7 @@ model_list: general_settings: master_key: sk-1234 alerting: ["slack"] - alerting_threshold: 0.0001 # (Seconds) set an artifically low threshold for testing alerting + alerting_threshold: 0.0001 # (Seconds) set an artificially low threshold for testing alerting alert_to_webhook_url: { "llm_exceptions": "https://hooks.slack.com/services/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", "llm_too_slow": "https://hooks.slack.com/services/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", @@ -247,7 +247,7 @@ model_list: general_settings: master_key: sk-1234 alerting: ["slack"] - alerting_threshold: 0.0001 # (Seconds) set an artifically low threshold for testing alerting + alerting_threshold: 0.0001 # (Seconds) set an artificially low threshold for testing alerting alert_to_webhook_url: { "llm_exceptions": ["os.environ/SLACK_WEBHOOK_URL", "os.environ/SLACK_WEBHOOK_URL_2"], "llm_too_slow": ["https://webhook.site/7843a980-a494-4967-80fb-d502dbc16886", "https://webhook.site/28cfb179-f4fb-4408-8129-729ff55cf213"], @@ -425,7 +425,7 @@ curl -X GET --location 'http://0.0.0.0:4000/health/services?service=webhook' \ - `projected_exceeded_date` *str or null*: The date when the budget is projected to be exceeded, returned when 'soft_budget' is set for key (optional). - `projected_spend` *float or null*: The projected spend amount, returned when 'soft_budget' is set for key (optional). - `event` *Literal["budget_crossed", "threshold_crossed", "projected_limit_exceeded"]*: The type of event that triggered the webhook. Possible values are: - * "spend_tracked": Emitted whenver spend is tracked for a customer id. + * "spend_tracked": Emitted whenever spend is tracked for a customer id. * "budget_crossed": Indicates that the spend has exceeded the max budget. * "threshold_crossed": Indicates that spend has crossed a threshold (currently sent when 85% and 95% of budget is reached). * "projected_limit_exceeded": For "key" only - Indicates that the projected spend is expected to exceed the soft budget threshold. @@ -480,7 +480,7 @@ LLM-related Alerts | `cooldown_deployment` | Alerts when a deployment is put into cooldown | ✅ | | `new_model_added` | Notifications when a new model is added to litellm proxy through /model/new| ✅ | | `outage_alerts` | Alerts when a specific LLM deployment is facing an outage | ✅ | -| `region_outage_alerts` | Alerts when a specfic LLM region is facing an outage. Example us-east-1 | ✅ | +| `region_outage_alerts` | Alerts when a specific LLM region is facing an outage. Example us-east-1 | ✅ | Budget and Spend Alerts diff --git a/docs/my-website/docs/proxy/architecture.md b/docs/my-website/docs/proxy/architecture.md index 832fd266b6b..2b83583ed93 100644 --- a/docs/my-website/docs/proxy/architecture.md +++ b/docs/my-website/docs/proxy/architecture.md @@ -36,7 +36,7 @@ import TabItem from '@theme/TabItem'; - Virtual Key Rate Limit - User Rate Limit - Team Limit - - The `_PROXY_track_cost_callback` updates spend / usage in the LiteLLM database. [Here is everything tracked in the DB per request](https://github.com/BerriAI/litellm/blob/ba41a72f92a9abf1d659a87ec880e8e319f87481/schema.prisma#L172) + - The `_ProxyDBLogger` updates spend / usage in the LiteLLM database. [Here is everything tracked in the DB per request](https://github.com/BerriAI/litellm/blob/ba41a72f92a9abf1d659a87ec880e8e319f87481/schema.prisma#L172) ## Frequently Asked Questions diff --git a/docs/my-website/docs/proxy/budget_reset_and_tz.md b/docs/my-website/docs/proxy/budget_reset_and_tz.md new file mode 100644 index 00000000000..541ff6a2f0a --- /dev/null +++ b/docs/my-website/docs/proxy/budget_reset_and_tz.md @@ -0,0 +1,33 @@ +## Budget Reset Times and Timezones + +LiteLLM now supports predictable budget reset times that align with natural calendar boundaries: + +- All budgets reset at midnight (00:00:00) in the configured timezone +- Special handling for common durations: + - Daily (24h/1d): Reset at midnight every day + - Weekly (7d): Reset on Monday at midnight + - Monthly (30d): Reset on the 1st of each month at midnight + +### Configuring the Timezone + +You can specify the timezone for all budget resets in your configuration file: + +```yaml +litellm_settings: + max_budget: 100 # (float) sets max budget as $100 USD + budget_duration: 30d # (number)(s/m/h/d) + timezone: "US/Eastern" # Any valid timezone string +``` + +This ensures that all budget resets happen at midnight in your specified timezone rather than in UTC. +If no timezone is specified, UTC will be used by default. + +Common timezone values: + +- `UTC` - Coordinated Universal Time +- `US/Eastern` - Eastern Time +- `US/Pacific` - Pacific Time +- `Europe/London` - UK Time +- `Asia/Kolkata` - Indian Standard Time (IST) +- `Asia/Tokyo` - Japan Standard Time +- `Australia/Sydney` - Australian Eastern Time diff --git a/docs/my-website/docs/proxy/caching.md b/docs/my-website/docs/proxy/caching.md index 3f5342c7e60..84e8c5f8d58 100644 --- a/docs/my-website/docs/proxy/caching.md +++ b/docs/my-website/docs/proxy/caching.md @@ -2,7 +2,6 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Caching -Cache LLM Responses :::note @@ -10,14 +9,20 @@ For OpenAI/Anthropic Prompt Caching, go [here](../completion/prompt_caching.md) ::: -LiteLLM supports: +Cache LLM Responses. LiteLLM's caching system stores and reuses LLM responses to save costs and reduce latency. When you make the same request twice, the cached response is returned instead of calling the LLM API again. + + + +### Supported Caches + - In Memory Cache +- Disk Cache - Redis Cache - Qdrant Semantic Cache - Redis Semantic Cache - s3 Bucket Cache -## Quick Start - Redis, s3 Cache, Semantic Cache +## Quick Start @@ -334,7 +339,7 @@ model_list: litellm_settings: set_verbose: True - cache: True # set cache responses to True, litellm defaults to using a redis cache + cache: True # set cache responses to True cache_params: type: "redis-semantic" similarity_threshold: 0.8 # similarity threshold for semantic cache @@ -365,13 +370,47 @@ $ litellm --config /path/to/config.yaml + + +#### Step 1: Add `cache` to the config.yaml +```yaml +litellm_settings: + cache: True + cache_params: + type: local +``` + +#### Step 2: Run proxy with config +```shell +$ litellm --config /path/to/config.yaml +``` + + + + + +#### Step 1: Add `cache` to the config.yaml +```yaml +litellm_settings: + cache: True + cache_params: + type: disk + disk_cache_dir: /tmp/litellm-cache # OPTIONAL, default to ./.litellm_cache +``` + +#### Step 2: Run proxy with config +```shell +$ litellm --config /path/to/config.yaml +``` + + +## Usage - -## Using Caching - /chat/completions +### Basic @@ -416,6 +455,239 @@ curl --location 'http://0.0.0.0:4000/embeddings' \ +### Dynamic Cache Controls + +| Parameter | Type | Description | +|-----------|------|-------------| +| `ttl` | *Optional(int)* | Will cache the response for the user-defined amount of time (in seconds) | +| `s-maxage` | *Optional(int)* | Will only accept cached responses that are within user-defined range (in seconds) | +| `no-cache` | *Optional(bool)* | Will not store the response in cache. | +| `no-store` | *Optional(bool)* | Will not cache the response | +| `namespace` | *Optional(str)* | Will cache the response under a user-defined namespace | + +Each cache parameter can be controlled on a per-request basis. Here are examples for each parameter: + +### `ttl` + +Set how long (in seconds) to cache a response. + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="your-api-key", + base_url="http://0.0.0.0:4000" +) + +chat_completion = client.chat.completions.create( + messages=[{"role": "user", "content": "Hello"}], + model="gpt-3.5-turbo", + extra_body={ + "cache": { + "ttl": 300 # Cache response for 5 minutes + } + } +) +``` + + + + +```shell +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "cache": {"ttl": 300}, + "messages": [ + {"role": "user", "content": "Hello"} + ] + }' +``` + + + +### `s-maxage` + +Only accept cached responses that are within the specified age (in seconds). + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="your-api-key", + base_url="http://0.0.0.0:4000" +) + +chat_completion = client.chat.completions.create( + messages=[{"role": "user", "content": "Hello"}], + model="gpt-3.5-turbo", + extra_body={ + "cache": { + "s-maxage": 600 # Only use cache if less than 10 minutes old + } + } +) +``` + + + + +```shell +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "cache": {"s-maxage": 600}, + "messages": [ + {"role": "user", "content": "Hello"} + ] + }' +``` + + + +### `no-cache` +Force a fresh response, bypassing the cache. + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="your-api-key", + base_url="http://0.0.0.0:4000" +) + +chat_completion = client.chat.completions.create( + messages=[{"role": "user", "content": "Hello"}], + model="gpt-3.5-turbo", + extra_body={ + "cache": { + "no-cache": True # Skip cache check, get fresh response + } + } +) +``` + + + + +```shell +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "cache": {"no-cache": true}, + "messages": [ + {"role": "user", "content": "Hello"} + ] + }' +``` + + + +### `no-store` + +Will not store the response in cache. + + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="your-api-key", + base_url="http://0.0.0.0:4000" +) + +chat_completion = client.chat.completions.create( + messages=[{"role": "user", "content": "Hello"}], + model="gpt-3.5-turbo", + extra_body={ + "cache": { + "no-store": True # Don't cache this response + } + } +) +``` + + + + +```shell +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "cache": {"no-store": true}, + "messages": [ + {"role": "user", "content": "Hello"} + ] + }' +``` + + + +### `namespace` +Store the response under a specific cache namespace. + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="your-api-key", + base_url="http://0.0.0.0:4000" +) + +chat_completion = client.chat.completions.create( + messages=[{"role": "user", "content": "Hello"}], + model="gpt-3.5-turbo", + extra_body={ + "cache": { + "namespace": "my-custom-namespace" # Store in custom namespace + } + } +) +``` + + + + +```shell +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "cache": {"namespace": "my-custom-namespace"}, + "messages": [ + {"role": "user", "content": "Hello"} + ] + }' +``` + + + + + ## Set cache for proxy, but not on the actual llm api call Use this if you just want to enable features like rate limiting, and loadbalancing across multiple instances. @@ -501,253 +773,6 @@ litellm_settings: # /chat/completions, /completions, /embeddings, /audio/transcriptions ``` -### **Turn on / off caching per request. ** - -The proxy support 4 cache-controls: - -- `ttl`: *Optional(int)* - Will cache the response for the user-defined amount of time (in seconds). -- `s-maxage`: *Optional(int)* Will only accept cached responses that are within user-defined range (in seconds). -- `no-cache`: *Optional(bool)* Will not return a cached response, but instead call the actual endpoint. -- `no-store`: *Optional(bool)* Will not cache the response. - -[Let us know if you need more](https://github.com/BerriAI/litellm/issues/1218) - -**Turn off caching** - -Set `no-cache=True`, this will not return a cached response - - - - -```python -import os -from openai import OpenAI - -client = OpenAI( - # This is the default and can be omitted - api_key=os.environ.get("OPENAI_API_KEY"), - base_url="http://0.0.0.0:4000" -) - -chat_completion = client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "Say this is a test", - } - ], - model="gpt-3.5-turbo", - extra_body = { # OpenAI python accepts extra args in extra_body - cache: { - "no-cache": True # will not return a cached response - } - } -) -``` - - - - -```shell -curl http://localhost:4000/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ - -d '{ - "model": "gpt-3.5-turbo", - "cache": {"no-cache": True}, - "messages": [ - {"role": "user", "content": "Say this is a test"} - ] - }' -``` - - - - - -**Turn on caching** - -By default cache is always on - - - - -```python -import os -from openai import OpenAI - -client = OpenAI( - # This is the default and can be omitted - api_key=os.environ.get("OPENAI_API_KEY"), - base_url="http://0.0.0.0:4000" -) - -chat_completion = client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "Say this is a test", - } - ], - model="gpt-3.5-turbo" -) -``` - - - - -```shell -curl http://localhost:4000/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ - -d '{ - "model": "gpt-3.5-turbo", - "messages": [ - {"role": "user", "content": "Say this is a test"} - ] - }' -``` - - - - - -**Set `ttl`** - -Set `ttl=600`, this will caches response for 10 minutes (600 seconds) - - - - -```python -import os -from openai import OpenAI - -client = OpenAI( - # This is the default and can be omitted - api_key=os.environ.get("OPENAI_API_KEY"), - base_url="http://0.0.0.0:4000" -) - -chat_completion = client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "Say this is a test", - } - ], - model="gpt-3.5-turbo", - extra_body = { # OpenAI python accepts extra args in extra_body - cache: { - "ttl": 600 # caches response for 10 minutes - } - } -) -``` - - - - -```shell -curl http://localhost:4000/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ - -d '{ - "model": "gpt-3.5-turbo", - "cache": {"ttl": 600}, - "messages": [ - {"role": "user", "content": "Say this is a test"} - ] - }' -``` - - - - - - - -**Set `s-maxage`** - -Set `s-maxage`, this will only get responses cached within last 10 minutes - - - - -```python -import os -from openai import OpenAI - -client = OpenAI( - # This is the default and can be omitted - api_key=os.environ.get("OPENAI_API_KEY"), - base_url="http://0.0.0.0:4000" -) - -chat_completion = client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "Say this is a test", - } - ], - model="gpt-3.5-turbo", - extra_body = { # OpenAI python accepts extra args in extra_body - cache: { - "s-maxage": 600 # only get responses cached within last 10 minutes - } - } -) -``` - - - - -```shell -curl http://localhost:4000/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ - -d '{ - "model": "gpt-3.5-turbo", - "cache": {"s-maxage": 600}, - "messages": [ - {"role": "user", "content": "Say this is a test"} - ] - }' -``` - - - - - - -### Turn on / off caching per Key. - -1. Add cache params when creating a key [full list](#turn-on--off-caching-per-key) - -```bash -curl -X POST 'http://0.0.0.0:4000/key/generate' \ --H 'Authorization: Bearer sk-1234' \ --H 'Content-Type: application/json' \ --d '{ - "user_id": "222", - "metadata": { - "cache": { - "no-cache": true - } - } -}' -``` - -2. Test it! - -```bash -curl -X POST 'http://localhost:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer ' \ --d '{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "bom dia"}]}' -``` - ### Deleting Cache Keys - `/cache/delete` In order to delete a cache key, send a request to `/cache/delete` with the `keys` you want to delete @@ -942,4 +967,4 @@ general_settings: user_api_key_cache_ttl: #time in seconds ``` -By default this value is set to 60s. \ No newline at end of file +By default this value is set to 60s. diff --git a/docs/my-website/docs/proxy/call_hooks.md b/docs/my-website/docs/proxy/call_hooks.md index 8ea220cfa10..c588ca0d0e6 100644 --- a/docs/my-website/docs/proxy/call_hooks.md +++ b/docs/my-website/docs/proxy/call_hooks.md @@ -44,7 +44,8 @@ class MyCustomHandler(CustomLogger): # https://docs.litellm.ai/docs/observabilit self, request_data: dict, original_exception: Exception, - user_api_key_dict: UserAPIKeyAuth + user_api_key_dict: UserAPIKeyAuth, + traceback_str: Optional[str] = None, ): pass @@ -70,6 +71,21 @@ class MyCustomHandler(CustomLogger): # https://docs.litellm.ai/docs/observabilit response: str, ): pass + + aasync def async_post_call_streaming_iterator_hook( + self, + user_api_key_dict: UserAPIKeyAuth, + response: Any, + request_data: dict, + ) -> AsyncGenerator[ModelResponseStream, None]: + """ + Passes the entire stream to the guardrail + + This is useful for plugins that need to see the entire stream. + """ + async for item in response: + yield item + proxy_handler_instance = MyCustomHandler() ``` diff --git a/docs/my-website/docs/proxy/config_settings.md b/docs/my-website/docs/proxy/config_settings.md index 4a10cea7abe..fdd68c953f6 100644 --- a/docs/my-website/docs/proxy/config_settings.md +++ b/docs/my-website/docs/proxy/config_settings.md @@ -1,6 +1,5 @@ # All settings - ```yaml environment_variables: {} @@ -95,6 +94,8 @@ general_settings: allowed_routes: ["route1", "route2"] # list of allowed proxy API routes - a user can access. (currently JWT-Auth only) key_management_system: google_kms # either google_kms or azure_kms master_key: string + maximum_spend_logs_retention_period: 30d # The maximum time to retain spend logs before deletion. + maximum_spend_logs_retention_interval: 1d # interval in which the spend log cleanup task should run in. # Database Settings database_url: string @@ -147,6 +148,7 @@ general_settings: |------|------|-------------| | completion_model | string | The default model to use for completions when `model` is not specified in the request | | disable_spend_logs | boolean | If true, turns off writing each transaction to the database | +| disable_spend_updates | boolean | If true, turns off all spend updates to the DB. Including key/user/team spend updates. | | disable_master_key_return | boolean | If true, turns off returning master key on UI. (checked on '/user/info' endpoint) | | disable_retry_on_max_parallel_request_limit_error | boolean | If true, turns off retries when max parallel request limit is reached | | disable_reset_budget | boolean | If true, turns off reset budget scheduled task | @@ -159,7 +161,7 @@ general_settings: | database_url | string | The URL for the database connection [Set up Virtual Keys](virtual_keys) | | database_connection_pool_limit | integer | The limit for database connection pool [Setting DB Connection Pool limit](#configure-db-pool-limits--connection-timeouts) | | database_connection_timeout | integer | The timeout for database connections in seconds [Setting DB Connection Pool limit, timeout](#configure-db-pool-limits--connection-timeouts) | -| allow_requests_on_db_unavailable | boolean | If true, allows requests to succeed even if DB is unreachable. **Only use this if running LiteLLM in your VPC** This will allow requests to work even when LiteLLM cannot connect to the DB to verify a Virtual Key | +| allow_requests_on_db_unavailable | boolean | If true, allows requests to succeed even if DB is unreachable. **Only use this if running LiteLLM in your VPC** This will allow requests to work even when LiteLLM cannot connect to the DB to verify a Virtual Key [Doc on graceful db unavailability](prod#5-if-running-litellm-on-vpc-gracefully-handle-db-unavailability) | | custom_auth | string | Write your own custom authentication logic [Doc Custom Auth](virtual_keys#custom-auth) | | max_parallel_requests | integer | The max parallel requests allowed per deployment | | global_max_parallel_requests | integer | The max parallel requests allowed on the proxy overall | @@ -177,7 +179,7 @@ general_settings: | use_x_forwarded_for | str | If true, uses the X-Forwarded-For header to get the client IP address | | service_account_settings | List[Dict[str, Any]] | Set `service_account_settings` if you want to create settings that only apply to service account keys (Doc on service accounts)[./service_accounts.md] | | image_generation_model | str | The default model to use for image generation - ignores model set in request | -| store_model_in_db | boolean | If true, allows `/model/new` endpoint to store model information in db. Endpoint disabled by default. [Doc on `/model/new` endpoint](./model_management.md#create-a-new-model) | +| store_model_in_db | boolean | If true, enables storing model + credential information in the DB. | | store_prompts_in_spend_logs | boolean | If true, allows prompts and responses to be stored in the spend logs table. | | max_request_size_mb | int | The maximum size for requests in MB. Requests above this size will be rejected. | | max_response_size_mb | int | The maximum size for responses in MB. LLM Responses above this size will not be sent. | @@ -210,7 +212,8 @@ general_settings: | enable_oauth2_proxy_auth | boolean | (Enterprise Feature) If true, enables oauth2.0 authentication | | forward_openai_org_id | boolean | If true, forwards the OpenAI Organization ID to the backend LLM call (if it's OpenAI). | | forward_client_headers_to_llm_api | boolean | If true, forwards the client headers (any `x-` headers) to the backend LLM call | - +| maximum_spend_logs_retention_period | str | Used to set the max retention time for spend logs in the db, after which they will be auto-purged | +| maximum_spend_logs_retention_interval | str | Used to set the interval in which the spend log cleanup task should run in. | ### router_settings - Reference :::info @@ -298,6 +301,9 @@ router_settings: |------|-------------| | ACTIONS_ID_TOKEN_REQUEST_TOKEN | Token for requesting ID in GitHub Actions | ACTIONS_ID_TOKEN_REQUEST_URL | URL for requesting ID token in GitHub Actions +| AGENTOPS_ENVIRONMENT | Environment for AgentOps logging integration +| AGENTOPS_API_KEY | API Key for AgentOps logging integration +| AGENTOPS_SERVICE_NAME | Service Name for AgentOps logging integration | AISPEND_ACCOUNT_ID | Account ID for AI Spend | AISPEND_API_KEY | API Key for AI Spend | ALLOWED_EMAIL_DOMAINS | List of email domains allowed for access @@ -322,17 +328,24 @@ router_settings: | AZURE_AUTHORITY_HOST | Azure authority host URL | AZURE_CLIENT_ID | Client ID for Azure services | AZURE_CLIENT_SECRET | Client secret for Azure services +| AZURE_TENANT_ID | Tenant ID for Azure Active Directory +| AZURE_USERNAME | Username for Azure services, use in conjunction with AZURE_PASSWORD for azure ad token with basic username/password workflow +| AZURE_PASSWORD | Password for Azure services, use in conjunction with AZURE_USERNAME for azure ad token with basic username/password workflow | AZURE_FEDERATED_TOKEN_FILE | File path to Azure federated token | AZURE_KEY_VAULT_URI | URI for Azure Key Vault +| AZURE_OPERATION_POLLING_TIMEOUT | Timeout in seconds for Azure operation polling | AZURE_STORAGE_ACCOUNT_KEY | The Azure Storage Account Key to use for Authentication to Azure Blob Storage logging | AZURE_STORAGE_ACCOUNT_NAME | Name of the Azure Storage Account to use for logging to Azure Blob Storage | AZURE_STORAGE_FILE_SYSTEM | Name of the Azure Storage File System to use for logging to Azure Blob Storage. (Typically the Container name) | AZURE_STORAGE_TENANT_ID | The Application Tenant ID to use for Authentication to Azure Blob Storage logging | AZURE_STORAGE_CLIENT_ID | The Application Client ID to use for Authentication to Azure Blob Storage logging | AZURE_STORAGE_CLIENT_SECRET | The Application Client Secret to use for Authentication to Azure Blob Storage logging -| AZURE_TENANT_ID | Tenant ID for Azure Active Directory +| BATCH_STATUS_POLL_INTERVAL_SECONDS | Interval in seconds for polling batch status. Default is 3600 (1 hour) +| BATCH_STATUS_POLL_MAX_ATTEMPTS | Maximum number of attempts for polling batch status. Default is 24 (for 24 hours) +| BEDROCK_MAX_POLICY_SIZE | Maximum size for Bedrock policy. Default is 75 | BERRISPEND_ACCOUNT_ID | Account ID for BerriSpend service | BRAINTRUST_API_KEY | API key for Braintrust integration +| CACHED_STREAMING_CHUNK_DELAY | Delay in seconds for cached streaming chunks. Default is 0.02 | CIRCLE_OIDC_TOKEN | OpenID Connect token for CircleCI | CIRCLE_OIDC_TOKEN_V2 | Version 2 of the OpenID Connect token for CircleCI | CONFIG_FILE_PATH | File path for configuration file @@ -346,6 +359,9 @@ router_settings: | DATABASE_USER | Username for database connection | DATABASE_USERNAME | Alias for database user | DATABRICKS_API_BASE | Base URL for Databricks API +| DAYS_IN_A_MONTH | Days in a month for calculation purposes. Default is 28 +| DAYS_IN_A_WEEK | Days in a week for calculation purposes. Default is 7 +| DAYS_IN_A_YEAR | Days in a year for calculation purposes. Default is 365 | DD_BASE_URL | Base URL for Datadog integration | DATADOG_BASE_URL | (Alternative to DD_BASE_URL) Base URL for Datadog integration | _DATADOG_BASE_URL | (Alternative to DD_BASE_URL) Base URL for Datadog integration @@ -356,6 +372,39 @@ router_settings: | DD_SERVICE | Service identifier for Datadog logs. Defaults to "litellm-server" | DD_VERSION | Version identifier for Datadog logs. Defaults to "unknown" | DEBUG_OTEL | Enable debug mode for OpenTelemetry +| DEFAULT_ALLOWED_FAILS | Maximum failures allowed before cooling down a model. Default is 3 +| DEFAULT_ANTHROPIC_CHAT_MAX_TOKENS | Default maximum tokens for Anthropic chat completions. Default is 4096 +| DEFAULT_BATCH_SIZE | Default batch size for operations. Default is 512 +| DEFAULT_COOLDOWN_TIME_SECONDS | Duration in seconds to cooldown a model after failures. Default is 5 +| DEFAULT_CRON_JOB_LOCK_TTL_SECONDS | Time-to-live for cron job locks in seconds. Default is 60 (1 minute) +| DEFAULT_FAILURE_THRESHOLD_PERCENT | Threshold percentage of failures to cool down a deployment. Default is 0.5 (50%) +| DEFAULT_FLUSH_INTERVAL_SECONDS | Default interval in seconds for flushing operations. Default is 5 +| DEFAULT_HEALTH_CHECK_INTERVAL | Default interval in seconds for health checks. Default is 300 (5 minutes) +| DEFAULT_IMAGE_HEIGHT | Default height for images. Default is 300 +| DEFAULT_IMAGE_TOKEN_COUNT | Default token count for images. Default is 250 +| DEFAULT_IMAGE_WIDTH | Default width for images. Default is 300 +| DEFAULT_IN_MEMORY_TTL | Default time-to-live for in-memory cache in seconds. Default is 5 +| DEFAULT_MAX_LRU_CACHE_SIZE | Default maximum size for LRU cache. Default is 16 +| DEFAULT_MAX_RECURSE_DEPTH | Default maximum recursion depth. Default is 100 +| DEFAULT_MAX_RECURSE_DEPTH_SENSITIVE_DATA_MASKER | Default maximum recursion depth for sensitive data masker. Default is 10 +| DEFAULT_MAX_RETRIES | Default maximum retry attempts. Default is 2 +| DEFAULT_MAX_TOKENS | Default maximum tokens for LLM calls. Default is 4096 +| DEFAULT_MAX_TOKENS_FOR_TRITON | Default maximum tokens for Triton models. Default is 2000 +| DEFAULT_MOCK_RESPONSE_COMPLETION_TOKEN_COUNT | Default token count for mock response completions. Default is 20 +| DEFAULT_MOCK_RESPONSE_PROMPT_TOKEN_COUNT | Default token count for mock response prompts. Default is 10 +| DEFAULT_MODEL_CREATED_AT_TIME | Default creation timestamp for models. Default is 1677610602 +| DEFAULT_PROMPT_INJECTION_SIMILARITY_THRESHOLD | Default threshold for prompt injection similarity. Default is 0.7 +| DEFAULT_POLLING_INTERVAL | Default polling interval for schedulers in seconds. Default is 0.03 +| DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET | Default high reasoning effort thinking budget. Default is 4096 +| DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET | Default low reasoning effort thinking budget. Default is 1024 +| DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET | Default medium reasoning effort thinking budget. Default is 2048 +| DEFAULT_REDIS_SYNC_INTERVAL | Default Redis synchronization interval in seconds. Default is 1 +| DEFAULT_REPLICATE_GPU_PRICE_PER_SECOND | Default price per second for Replicate GPU. Default is 0.001400 +| DEFAULT_REPLICATE_POLLING_DELAY_SECONDS | Default delay in seconds for Replicate polling. Default is 1 +| DEFAULT_REPLICATE_POLLING_RETRIES | Default number of retries for Replicate polling. Default is 5 +| DEFAULT_SLACK_ALERTING_THRESHOLD | Default threshold for Slack alerting. Default is 300 +| DEFAULT_SOFT_BUDGET | Default soft budget for LiteLLM proxy keys. Default is 50.0 +| DEFAULT_TRIM_RATIO | Default ratio of tokens to trim from prompt end. Default is 0.75 | DIRECT_URL | Direct URL for service endpoint | DISABLE_ADMIN_UI | Toggle to disable the admin UI | DISABLE_SCHEMA_UPDATE | Toggle to disable schema updates @@ -363,7 +412,19 @@ router_settings: | DOCS_FILTERED | Flag indicating filtered documentation | DOCS_TITLE | Title of the documentation pages | DOCS_URL | The path to the Swagger API documentation. **By default this is "/"** +| EMAIL_LOGO_URL | URL for the logo used in emails | EMAIL_SUPPORT_CONTACT | Support contact email address +| EXPERIMENTAL_MULTI_INSTANCE_RATE_LIMITING | Flag to enable new multi-instance rate limiting. **Default is False** +| FIREWORKS_AI_4_B | Size parameter for Fireworks AI 4B model. Default is 4 +| FIREWORKS_AI_16_B | Size parameter for Fireworks AI 16B model. Default is 16 +| FIREWORKS_AI_56_B_MOE | Size parameter for Fireworks AI 56B MOE model. Default is 56 +| FIREWORKS_AI_80_B | Size parameter for Fireworks AI 80B model. Default is 80 +| FIREWORKS_AI_176_B_MOE | Size parameter for Fireworks AI 176B MOE model. Default is 176 +| FUNCTION_DEFINITION_TOKEN_COUNT | Token count for function definitions. Default is 9 +| GALILEO_BASE_URL | Base URL for Galileo platform +| GALILEO_PASSWORD | Password for Galileo authentication +| GALILEO_PROJECT_ID | Project ID for Galileo usage +| GALILEO_USERNAME | Username for Galileo authentication | GCS_BUCKET_NAME | Name of the Google Cloud Storage bucket | GCS_PATH_SERVICE_ACCOUNT | Path to the Google Cloud service account JSON file | GCS_FLUSH_INTERVAL | Flush interval for GCS logging (in seconds). Specify how often you want a log to be sent to GCS. **Default is 20 seconds** @@ -395,6 +456,7 @@ router_settings: | GOOGLE_CLIENT_ID | Client ID for Google OAuth | GOOGLE_CLIENT_SECRET | Client secret for Google OAuth | GOOGLE_KMS_RESOURCE_NAME | Name of the resource in Google KMS +| HEALTH_CHECK_TIMEOUT_SECONDS | Timeout in seconds for health checks. Default is 60 | HF_API_BASE | Base URL for Hugging Face API | HCP_VAULT_ADDR | Address for [Hashicorp Vault Secret Manager](../secret.md#hashicorp-vault) | HCP_VAULT_CLIENT_CERT | Path to client certificate for [Hashicorp Vault Secret Manager](../secret.md#hashicorp-vault) @@ -404,8 +466,13 @@ router_settings: | HCP_VAULT_CERT_ROLE | Role for [Hashicorp Vault Secret Manager Auth](../secret.md#hashicorp-vault) | HELICONE_API_KEY | API key for Helicone service | HOSTNAME | Hostname for the server, this will be [emitted to `datadog` logs](https://docs.litellm.ai/docs/proxy/logging#datadog) +| HOURS_IN_A_DAY | Hours in a day for calculation purposes. Default is 24 | HUGGINGFACE_API_BASE | Base URL for Hugging Face API +| HUGGINGFACE_API_KEY | API key for Hugging Face API +| HUMANLOOP_PROMPT_CACHE_TTL_SECONDS | Time-to-live in seconds for cached prompts in Humanloop. Default is 60 | IAM_TOKEN_DB_AUTH | IAM token for database authentication +| INITIAL_RETRY_DELAY | Initial delay in seconds for retrying requests. Default is 0.5 +| JITTER | Jitter factor for retry delay calculations. Default is 0.75 | JSON_LOGS | Enable JSON formatted logging | JWT_AUDIENCE | Expected audience for JWT tokens | JWT_PUBLIC_KEY_URL | URL to fetch public key for JWT verification @@ -426,14 +493,17 @@ router_settings: | LANGSMITH_PROJECT | Project name for Langsmith integration | LANGSMITH_SAMPLING_RATE | Sampling rate for Langsmith logging | LANGTRACE_API_KEY | API key for Langtrace service +| LENGTH_OF_LITELLM_GENERATED_KEY | Length of keys generated by LiteLLM. Default is 16 | LITERAL_API_KEY | API key for Literal integration | LITERAL_API_URL | API URL for Literal service | LITERAL_BATCH_SIZE | Batch size for Literal operations | LITELLM_DONT_SHOW_FEEDBACK_BOX | Flag to hide feedback box in LiteLLM UI | LITELLM_DROP_PARAMS | Parameters to drop in LiteLLM requests +| LITELLM_MODIFY_PARAMS | Parameters to modify in LiteLLM requests | LITELLM_EMAIL | Email associated with LiteLLM account | LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRIES | Maximum retries for parallel requests in LiteLLM | LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRY_TIMEOUT | Timeout for retries of parallel requests in LiteLLM +| LITELLM_MIGRATION_DIR | Custom migrations directory for prisma migrations, used for baselining db in read-only file systems. | LITELLM_HOSTED_UI | URL of the hosted UI for LiteLLM | LITELLM_LICENSE | License key for LiteLLM usage | LITELLM_LOCAL_MODEL_COST_MAP | Local configuration for model cost mapping in LiteLLM @@ -444,14 +514,36 @@ router_settings: | LITELLM_TOKEN | Access token for LiteLLM integration | LITELLM_PRINT_STANDARD_LOGGING_PAYLOAD | If true, prints the standard logging payload to the console - useful for debugging | LOGFIRE_TOKEN | Token for Logfire logging service +| MAX_EXCEPTION_MESSAGE_LENGTH | Maximum length for exception messages. Default is 2000 +| MAX_IN_MEMORY_QUEUE_FLUSH_COUNT | Maximum count for in-memory queue flush operations. Default is 1000 +| MAX_LONG_SIDE_FOR_IMAGE_HIGH_RES | Maximum length for the long side of high-resolution images. Default is 2000 +| MAX_REDIS_BUFFER_DEQUEUE_COUNT | Maximum count for Redis buffer dequeue operations. Default is 100 +| MAX_SHORT_SIDE_FOR_IMAGE_HIGH_RES | Maximum length for the short side of high-resolution images. Default is 768 +| MAX_SIZE_IN_MEMORY_QUEUE | Maximum size for in-memory queue. Default is 10000 +| MAX_SIZE_PER_ITEM_IN_MEMORY_CACHE_IN_KB | Maximum size in KB for each item in memory cache. Default is 512 or 1024 +| MAX_SPENDLOG_ROWS_TO_QUERY | Maximum number of spend log rows to query. Default is 1,000,000 +| MAX_TEAM_LIST_LIMIT | Maximum number of teams to list. Default is 20 +| MAX_TILE_HEIGHT | Maximum height for image tiles. Default is 512 +| MAX_TILE_WIDTH | Maximum width for image tiles. Default is 512 +| MAX_TOKEN_TRIMMING_ATTEMPTS | Maximum number of attempts to trim a token message. Default is 10 +| MAXIMUM_TRACEBACK_LINES_TO_LOG | Maximum number of lines to log in traceback in LiteLLM Logs UI. Default is 100 +| MAX_RETRY_DELAY | Maximum delay in seconds for retrying requests. Default is 8.0 +| MIN_NON_ZERO_TEMPERATURE | Minimum non-zero temperature value. Default is 0.0001 +| MINIMUM_PROMPT_CACHE_TOKEN_COUNT | Minimum token count for caching a prompt. Default is 1024 +| MISTRAL_API_BASE | Base URL for Mistral API +| MISTRAL_API_KEY | API key for Mistral API | MICROSOFT_CLIENT_ID | Client ID for Microsoft services | MICROSOFT_CLIENT_SECRET | Client secret for Microsoft services | MICROSOFT_TENANT | Tenant ID for Microsoft Azure +| MICROSOFT_SERVICE_PRINCIPAL_ID | Service Principal ID for Microsoft Enterprise Application. (This is an advanced feature if you want litellm to auto-assign members to Litellm Teams based on their Microsoft Entra ID Groups) | NO_DOCS | Flag to disable documentation generation | NO_PROXY | List of addresses to bypass proxy +| NON_LLM_CONNECTION_TIMEOUT | Timeout in seconds for non-LLM service connections. Default is 15 | OAUTH_TOKEN_INFO_ENDPOINT | Endpoint for OAuth token info retrieval +| OPENAI_BASE_URL | Base URL for OpenAI API | OPENAI_API_BASE | Base URL for OpenAI API | OPENAI_API_KEY | API key for OpenAI services +| OPENAI_FILE_SEARCH_COST_PER_1K_CALLS | Cost per 1000 calls for OpenAI file search. Default is 0.0025 | OPENAI_ORGANIZATION | Organization identifier for OpenAI | OPENID_BASE_URL | Base URL for OpenID Connect services | OPENID_CLIENT_ID | Client ID for OpenID Connect authentication @@ -460,46 +552,80 @@ router_settings: | OPENMETER_API_KEY | API key for OpenMeter services | OPENMETER_EVENT_TYPE | Type of events sent to OpenMeter | OTEL_ENDPOINT | OpenTelemetry endpoint for traces +| OTEL_EXPORTER_OTLP_ENDPOINT | OpenTelemetry endpoint for traces | OTEL_ENVIRONMENT_NAME | Environment name for OpenTelemetry | OTEL_EXPORTER | Exporter type for OpenTelemetry +| OTEL_EXPORTER_OTLP_PROTOCOL | Exporter type for OpenTelemetry | OTEL_HEADERS | Headers for OpenTelemetry requests +| OTEL_EXPORTER_OTLP_HEADERS | Headers for OpenTelemetry requests | OTEL_SERVICE_NAME | Service name identifier for OpenTelemetry | OTEL_TRACER_NAME | Tracer name for OpenTelemetry tracing | PAGERDUTY_API_KEY | API key for PagerDuty Alerting +| PHOENIX_API_KEY | API key for Arize Phoenix +| PHOENIX_COLLECTOR_ENDPOINT | API endpoint for Arize Phoenix +| PHOENIX_COLLECTOR_HTTP_ENDPOINT | API http endpoint for Arize Phoenix | POD_NAME | Pod name for the server, this will be [emitted to `datadog` logs](https://docs.litellm.ai/docs/proxy/logging#datadog) as `POD_NAME` | PREDIBASE_API_BASE | Base URL for Predibase API | PRESIDIO_ANALYZER_API_BASE | Base URL for Presidio Analyzer service | PRESIDIO_ANONYMIZER_API_BASE | Base URL for Presidio Anonymizer service +| PROMETHEUS_BUDGET_METRICS_REFRESH_INTERVAL_MINUTES | Refresh interval in minutes for Prometheus budget metrics. Default is 5 +| PROMETHEUS_FALLBACK_STATS_SEND_TIME_HOURS | Fallback time in hours for sending stats to Prometheus. Default is 9 | PROMETHEUS_URL | URL for Prometheus service | PROMPTLAYER_API_KEY | API key for PromptLayer integration | PROXY_ADMIN_ID | Admin identifier for proxy server | PROXY_BASE_URL | Base URL for proxy service +| PROXY_BATCH_WRITE_AT | Time in seconds to wait before batch writing spend logs to the database. Default is 10 +| PROXY_BUDGET_RESCHEDULER_MAX_TIME | Maximum time in seconds to wait before checking database for budget resets. Default is 605 +| PROXY_BUDGET_RESCHEDULER_MIN_TIME | Minimum time in seconds to wait before checking database for budget resets. Default is 597 | PROXY_LOGOUT_URL | URL for logging out of the proxy service -| PROXY_MASTER_KEY | Master key for proxy authentication +| LITELLM_MASTER_KEY | Master key for proxy authentication | QDRANT_API_BASE | Base URL for Qdrant API | QDRANT_API_KEY | API key for Qdrant service +| QDRANT_SCALAR_QUANTILE | Scalar quantile for Qdrant operations. Default is 0.99 | QDRANT_URL | Connection URL for Qdrant database +| QDRANT_VECTOR_SIZE | Vector size for Qdrant operations. Default is 1536 +| REDIS_CONNECTION_POOL_TIMEOUT | Timeout in seconds for Redis connection pool. Default is 5 | REDIS_HOST | Hostname for Redis server | REDIS_PASSWORD | Password for Redis service | REDIS_PORT | Port number for Redis server +| REDIS_SOCKET_TIMEOUT | Timeout in seconds for Redis socket operations. Default is 0.1 | REDOC_URL | The path to the Redoc Fast API documentation. **By default this is "/redoc"** +| REPEATED_STREAMING_CHUNK_LIMIT | Limit for repeated streaming chunks to detect looping. Default is 100 +| REPLICATE_MODEL_NAME_WITH_ID_LENGTH | Length of Replicate model names with ID. Default is 64 +| REPLICATE_POLLING_DELAY_SECONDS | Delay in seconds for Replicate polling operations. Default is 0.5 +| REQUEST_TIMEOUT | Timeout in seconds for requests. Default is 6000 +| ROUTER_MAX_FALLBACKS | Maximum number of fallbacks for router. Default is 5 +| SECRET_MANAGER_REFRESH_INTERVAL | Refresh interval in seconds for secret manager. Default is 86400 (24 hours) | SERVER_ROOT_PATH | Root path for the server application | SET_VERBOSE | Flag to enable verbose logging +| SINGLE_DEPLOYMENT_TRAFFIC_FAILURE_THRESHOLD | Minimum number of requests to consider "reasonable traffic" for single-deployment cooldown logic. Default is 1000 | SLACK_DAILY_REPORT_FREQUENCY | Frequency of daily Slack reports (e.g., daily, weekly) | SLACK_WEBHOOK_URL | Webhook URL for Slack integration | SMTP_HOST | Hostname for the SMTP server -| SMTP_PASSWORD | Password for SMTP authentication +| SMTP_PASSWORD | Password for SMTP authentication (do not set if SMTP does not require auth) | SMTP_PORT | Port number for SMTP server | SMTP_SENDER_EMAIL | Email address used as the sender in SMTP transactions | SMTP_SENDER_LOGO | Logo used in emails sent via SMTP | SMTP_TLS | Flag to enable or disable TLS for SMTP connections -| SMTP_USERNAME | Username for SMTP authentication +| SMTP_USERNAME | Username for SMTP authentication (do not set if SMTP does not require auth) | SPEND_LOGS_URL | URL for retrieving spend logs | SSL_CERTIFICATE | Path to the SSL certificate file +| SSL_SECURITY_LEVEL | [BETA] Security level for SSL/TLS connections. E.g. `DEFAULT@SECLEVEL=1` | SSL_VERIFY | Flag to enable or disable SSL certificate verification | SUPABASE_KEY | API key for Supabase service | SUPABASE_URL | Base URL for Supabase instance +| STORE_MODEL_IN_DB | If true, enables storing model + credential information in the DB. +| SYSTEM_MESSAGE_TOKEN_COUNT | Token count for system messages. Default is 4 | TEST_EMAIL_ADDRESS | Email address used for testing purposes +| TOGETHER_AI_4_B | Size parameter for Together AI 4B model. Default is 4 +| TOGETHER_AI_8_B | Size parameter for Together AI 8B model. Default is 8 +| TOGETHER_AI_21_B | Size parameter for Together AI 21B model. Default is 21 +| TOGETHER_AI_41_B | Size parameter for Together AI 41B model. Default is 41 +| TOGETHER_AI_80_B | Size parameter for Together AI 80B model. Default is 80 +| TOGETHER_AI_110_B | Size parameter for Together AI 110B model. Default is 110 +| TOGETHER_AI_EMBEDDING_150_M | Size parameter for Together AI 150M embedding model. Default is 150 +| TOGETHER_AI_EMBEDDING_350_M | Size parameter for Together AI 350M embedding model. Default is 350 +| TOOL_CHOICE_OBJECT_TOKEN_COUNT | Token count for tool choice objects. Default is 4 | UI_LOGO_PATH | Path to the logo image used in the UI | UI_PASSWORD | Password for accessing the UI | UI_USERNAME | Username for accessing the UI @@ -509,5 +635,6 @@ router_settings: | UPSTREAM_LANGFUSE_RELEASE | Release version identifier for upstream Langfuse | UPSTREAM_LANGFUSE_SECRET_KEY | Secret key for upstream Langfuse authentication | USE_AWS_KMS | Flag to enable AWS Key Management Service for encryption +| USE_PRISMA_MIGRATE | Flag to use prisma migrate instead of prisma db push. Recommended for production environments. | WEBHOOK_URL | URL for receiving webhooks from external services - +| SPEND_LOG_RUN_LOOPS | Constant for setting how many runs of 1000 batch deletes should spend_log_cleanup task run \ No newline at end of file diff --git a/docs/my-website/docs/proxy/configs.md b/docs/my-website/docs/proxy/configs.md index efb263d344e..db737f75afe 100644 --- a/docs/my-website/docs/proxy/configs.md +++ b/docs/my-website/docs/proxy/configs.md @@ -448,6 +448,34 @@ model_list: s/o to [@David Manouchehri](https://www.linkedin.com/in/davidmanouchehri/) for helping with this. +### Centralized Credential Management + +Define credentials once and reuse them across multiple models. This helps with: +- Secret rotation +- Reducing config duplication + +```yaml +model_list: + - model_name: gpt-4o + litellm_params: + model: azure/gpt-4o + litellm_credential_name: default_azure_credential # Reference credential below + +credential_list: + - credential_name: default_azure_credential + credential_values: + api_key: os.environ/AZURE_API_KEY # Load from environment + api_base: os.environ/AZURE_API_BASE + api_version: "2023-05-15" + credential_info: + description: "Production credentials for EU region" +``` + +#### Key Parameters +- `credential_name`: Unique identifier for the credential set +- `credential_values`: Key-value pairs of credentials/secrets (supports `os.environ/` syntax) +- `credential_info`: Key-value pairs of user provided credentials information. No key-value pairs are required, but the dictionary must exist. + ### Load API Keys from Secret Managers (Azure Vault, etc) [**Using Secret Managers with LiteLLM Proxy**](../secret) @@ -641,4 +669,4 @@ docker run --name litellm-proxy \ ghcr.io/berriai/litellm-database:main-latest ``` - \ No newline at end of file + diff --git a/docs/my-website/docs/proxy/cost_tracking.md b/docs/my-website/docs/proxy/cost_tracking.md index 7f90273c39c..5b17e565a5d 100644 --- a/docs/my-website/docs/proxy/cost_tracking.md +++ b/docs/my-website/docs/proxy/cost_tracking.md @@ -6,6 +6,8 @@ import Image from '@theme/IdealImage'; Track spend for keys, users, and teams across 100+ LLMs. +LiteLLM automatically tracks spend for all known models. See our [model cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) + ### How to Track Spend with LiteLLM **Step 1** @@ -35,10 +37,10 @@ response = client.chat.completions.create( "content": "this is a test request, write a short poem" } ], - user="palantir", - extra_body={ + user="palantir", # OPTIONAL: pass user to track spend by user + extra_body={ "metadata": { - "tags": ["jobID:214590dsff09fds", "taskName:run_page_classification"] + "tags": ["jobID:214590dsff09fds", "taskName:run_page_classification"] # ENTERPRISE: pass tags to track spend by tags } } ) @@ -63,9 +65,9 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \ "content": "what llm are you" } ], - "user": "palantir", + "user": "palantir", # OPTIONAL: pass user to track spend by user "metadata": { - "tags": ["jobID:214590dsff09fds", "taskName:run_page_classification"] + "tags": ["jobID:214590dsff09fds", "taskName:run_page_classification"] # ENTERPRISE: pass tags to track spend by tags } }' ``` @@ -90,7 +92,7 @@ chat = ChatOpenAI( user="palantir", extra_body={ "metadata": { - "tags": ["jobID:214590dsff09fds", "taskName:run_page_classification"] + "tags": ["jobID:214590dsff09fds", "taskName:run_page_classification"] # ENTERPRISE: pass tags to track spend by tags } } ) @@ -150,8 +152,112 @@ Navigate to the Usage Tab on the LiteLLM UI (found on https://your-proxy-endpoin -## ✨ (Enterprise) API Endpoints to get Spend -### Getting Spend Reports - To Charge Other Teams, Customers, Users +### Allowing Non-Proxy Admins to access `/spend` endpoints + +Use this when you want non-proxy admins to access `/spend` endpoints + +:::info + +Schedule a [meeting with us to get your Enterprise License](https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat) + +::: + +##### Create Key +Create Key with with `permissions={"get_spend_routes": true}` +```shell +curl --location 'http://0.0.0.0:4000/key/generate' \ + --header 'Authorization: Bearer sk-1234' \ + --header 'Content-Type: application/json' \ + --data '{ + "permissions": {"get_spend_routes": true} + }' +``` + +##### Use generated key on `/spend` endpoints + +Access spend Routes with newly generate keys +```shell +curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end_date=2024-06-30' \ + -H 'Authorization: Bearer sk-H16BKvrSNConSsBYLGc_7A' +``` + + + +#### Reset Team, API Key Spend - MASTER KEY ONLY + +Use `/global/spend/reset` if you want to: +- Reset the Spend for all API Keys, Teams. The `spend` for ALL Teams and Keys in `LiteLLM_TeamTable` and `LiteLLM_VerificationToken` will be set to `spend=0` + +- LiteLLM will maintain all the logs in `LiteLLMSpendLogs` for Auditing Purposes + +##### Request +Only the `LITELLM_MASTER_KEY` you set can access this route +```shell +curl -X POST \ + 'http://localhost:4000/global/spend/reset' \ + -H 'Authorization: Bearer sk-1234' \ + -H 'Content-Type: application/json' +``` + +##### Expected Responses + +```shell +{"message":"Spend for all API Keys and Teams reset successfully","status":"success"} +``` + +## Daily Spend Breakdown API + +Retrieve granular daily usage data for a user (by model, provider, and API key) with a single endpoint. + +Example Request: + +```shell title="Daily Spend Breakdown API" showLineNumbers +curl -L -X GET 'http://localhost:4000/user/daily/activity?start_date=2025-03-20&end_date=2025-03-27' \ +-H 'Authorization: Bearer sk-...' +``` + +```json title="Daily Spend Breakdown API Response" showLineNumbers +{ + "results": [ + { + "date": "2025-03-27", + "metrics": { + "spend": 0.0177072, + "prompt_tokens": 111, + "completion_tokens": 1711, + "total_tokens": 1822, + "api_requests": 11 + }, + "breakdown": { + "models": { + "gpt-4o-mini": { + "spend": 1.095e-05, + "prompt_tokens": 37, + "completion_tokens": 9, + "total_tokens": 46, + "api_requests": 1 + }, + "providers": { "openai": { ... }, "azure_ai": { ... } }, + "api_keys": { "3126b6eaf1...": { ... } } + } + } + ], + "metadata": { + "total_spend": 0.7274667, + "total_prompt_tokens": 280990, + "total_completion_tokens": 376674, + "total_api_requests": 14 + } +} +``` + +### API Reference + +See our [Swagger API](https://litellm-api.up.railway.app/#/Budget%20%26%20Spend%20Tracking/get_user_daily_activity_user_daily_activity_get) for more details on the `/user/daily/activity` endpoint + +## ✨ (Enterprise) Generate Spend Reports + +Use this to charge other teams, customers, users Use the `/global/spend/report` endpoint to get spend reports @@ -470,105 +576,6 @@ curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end -### Allowing Non-Proxy Admins to access `/spend` endpoints - -Use this when you want non-proxy admins to access `/spend` endpoints - -:::info - -Schedule a [meeting with us to get your Enterprise License](https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat) - -::: - -##### Create Key -Create Key with with `permissions={"get_spend_routes": true}` -```shell -curl --location 'http://0.0.0.0:4000/key/generate' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "permissions": {"get_spend_routes": true} - }' -``` - -##### Use generated key on `/spend` endpoints - -Access spend Routes with newly generate keys -```shell -curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end_date=2024-06-30' \ - -H 'Authorization: Bearer sk-H16BKvrSNConSsBYLGc_7A' -``` - - - -#### Reset Team, API Key Spend - MASTER KEY ONLY - -Use `/global/spend/reset` if you want to: -- Reset the Spend for all API Keys, Teams. The `spend` for ALL Teams and Keys in `LiteLLM_TeamTable` and `LiteLLM_VerificationToken` will be set to `spend=0` - -- LiteLLM will maintain all the logs in `LiteLLMSpendLogs` for Auditing Purposes - -##### Request -Only the `LITELLM_MASTER_KEY` you set can access this route -```shell -curl -X POST \ - 'http://localhost:4000/global/spend/reset' \ - -H 'Authorization: Bearer sk-1234' \ - -H 'Content-Type: application/json' -``` - -##### Expected Responses - -```shell -{"message":"Spend for all API Keys and Teams reset successfully","status":"success"} -``` - - - - -## Spend Tracking for Azure OpenAI Models - -Set base model for cost tracking azure image-gen call - -#### Image Generation - -```yaml -model_list: - - model_name: dall-e-3 - litellm_params: - model: azure/dall-e-3-test - api_version: 2023-06-01-preview - api_base: https://openai-gpt-4-test-v-1.openai.azure.com/ - api_key: os.environ/AZURE_API_KEY - base_model: dall-e-3 # 👈 set dall-e-3 as base model - model_info: - mode: image_generation -``` - -#### Chat Completions / Embeddings - -**Problem**: Azure returns `gpt-4` in the response when `azure/gpt-4-1106-preview` is used. This leads to inaccurate cost tracking - -**Solution** ✅ : Set `base_model` on your config so litellm uses the correct model for calculating azure cost - -Get the base model name from [here](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) - -Example config with `base_model` -```yaml -model_list: - - model_name: azure-gpt-3.5 - litellm_params: - model: azure/chatgpt-v-2 - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY - api_version: "2023-07-01-preview" - model_info: - base_model: azure/gpt-4-1106-preview -``` - -## Custom Input/Output Pricing - -👉 Head to [Custom Input/Output Pricing](https://docs.litellm.ai/docs/proxy/custom_pricing) to setup custom pricing or your models ## ✨ Custom Spend Log metadata @@ -587,4 +594,5 @@ Logging specific key,value pairs in spend logs metadata is an enterprise feature Tracking spend with Custom tags is an enterprise feature. [See here](./enterprise.md#tracking-spend-for-custom-tags) -::: \ No newline at end of file +::: + diff --git a/docs/my-website/docs/proxy/custom_pricing.md b/docs/my-website/docs/proxy/custom_pricing.md index 16d634dee47..e2df7721bfb 100644 --- a/docs/my-website/docs/proxy/custom_pricing.md +++ b/docs/my-website/docs/proxy/custom_pricing.md @@ -26,10 +26,12 @@ model_list: - model_name: sagemaker-completion-model litellm_params: model: sagemaker/berri-benchmarking-Llama-2-70b-chat-hf-4 + model_info: input_cost_per_second: 0.000420 - model_name: sagemaker-embedding-model litellm_params: model: sagemaker/berri-benchmarking-gpt-j-6b-fp16 + model_info: input_cost_per_second: 0.000420 ``` @@ -54,12 +56,56 @@ model_list: model: azure/ api_key: os.environ/AZURE_API_KEY api_base: os.environ/AZURE_API_BASE - api_version: os.envrion/AZURE_API_VERSION + api_version: os.environ/AZURE_API_VERSION + model_info: input_cost_per_token: 0.000421 # 👈 ONLY to track cost per token output_cost_per_token: 0.000520 # 👈 ONLY to track cost per token ``` -### Debugging +## Override Model Cost Map + +You can override [our model cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) with your own custom pricing for a mapped model. + +Just add a `model_info` key to your model in the config, and override the desired keys. + +Example: Override Anthropic's model cost map for the `prod/claude-3-5-sonnet-20241022` model. + +```yaml +model_list: + - model_name: "prod/claude-3-5-sonnet-20241022" + litellm_params: + model: "anthropic/claude-3-5-sonnet-20241022" + api_key: os.environ/ANTHROPIC_PROD_API_KEY + model_info: + input_cost_per_token: 0.000006 + output_cost_per_token: 0.00003 + cache_creation_input_token_cost: 0.0000075 + cache_read_input_token_cost: 0.0000006 +``` + +## Set 'base_model' for Cost Tracking (e.g. Azure deployments) + +**Problem**: Azure returns `gpt-4` in the response when `azure/gpt-4-1106-preview` is used. This leads to inaccurate cost tracking + +**Solution** ✅ : Set `base_model` on your config so litellm uses the correct model for calculating azure cost + +Get the base model name from [here](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) + +Example config with `base_model` +```yaml +model_list: + - model_name: azure-gpt-3.5 + litellm_params: + model: azure/chatgpt-v-2 + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY + api_version: "2023-07-01-preview" + model_info: + base_model: azure/gpt-4-1106-preview +``` + + +## Debugging If you're custom pricing is not being used or you're seeing errors, please check the following: @@ -87,4 +133,4 @@ acompletion( If these keys are not present, LiteLLM will not use your custom pricing. -If the problem persists, please file an issue on [GitHub](https://github.com/BerriAI/litellm/issues). \ No newline at end of file +If the problem persists, please file an issue on [GitHub](https://github.com/BerriAI/litellm/issues). diff --git a/docs/my-website/docs/proxy/custom_prompt_management.md b/docs/my-website/docs/proxy/custom_prompt_management.md new file mode 100644 index 00000000000..72a73332768 --- /dev/null +++ b/docs/my-website/docs/proxy/custom_prompt_management.md @@ -0,0 +1,194 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Custom Prompt Management + +Connect LiteLLM to your prompt management system with custom hooks. + +## Overview + + + + + +## How it works + +## Quick Start + +### 1. Create Your Custom Prompt Manager + +Create a class that inherits from `CustomPromptManagement` to handle prompt retrieval and formatting: + +**Example Implementation** + +Create a new file called `custom_prompt.py` and add this code. The key method here is `get_chat_completion_prompt` you can implement custom logic to retrieve and format prompts based on the `prompt_id` and `prompt_variables`. + +```python +from typing import List, Tuple, Optional +from litellm.integrations.custom_prompt_management import CustomPromptManagement +from litellm.types.llms.openai import AllMessageValues +from litellm.types.utils import StandardCallbackDynamicParams + +class MyCustomPromptManagement(CustomPromptManagement): + def get_chat_completion_prompt( + self, + model: str, + messages: List[AllMessageValues], + non_default_params: dict, + prompt_id: str, + prompt_variables: Optional[dict], + dynamic_callback_params: StandardCallbackDynamicParams, + ) -> Tuple[str, List[AllMessageValues], dict]: + """ + Retrieve and format prompts based on prompt_id. + + Returns: + - model: The model to use + - messages: The formatted messages + - non_default_params: Optional parameters like temperature + """ + # Example matching the diagram: Add system message for prompt_id "1234" + if prompt_id == "1234": + # Prepend system message while preserving existing messages + new_messages = [ + {"role": "system", "content": "Be a good Bot!"}, + ] + messages + return model, new_messages, non_default_params + + # Default: Return original messages if no prompt_id match + return model, messages, non_default_params + +prompt_management = MyCustomPromptManagement() +``` + +### 2. Configure Your Prompt Manager in LiteLLM `config.yaml` + +```yaml +model_list: + - model_name: gpt-4 + litellm_params: + model: openai/gpt-4 + api_key: os.environ/OPENAI_API_KEY + +litellm_settings: + callbacks: custom_prompt.prompt_management # sets litellm.callbacks = [prompt_management] +``` + +### 3. Start LiteLLM Gateway + + + + +Mount your `custom_logger.py` on the LiteLLM Docker container. + +```shell +docker run -d \ + -p 4000:4000 \ + -e OPENAI_API_KEY=$OPENAI_API_KEY \ + --name my-app \ + -v $(pwd)/my_config.yaml:/app/config.yaml \ + -v $(pwd)/custom_logger.py:/app/custom_logger.py \ + my-app:latest \ + --config /app/config.yaml \ + --port 4000 \ + --detailed_debug \ +``` + + + + + +```shell +litellm --config config.yaml --detailed_debug +``` + + + + +### 4. Test Your Custom Prompt Manager + +When you pass `prompt_id="1234"`, the custom prompt manager will add a system message "Be a good Bot!" to your conversation: + + + + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000" +) + +response = client.chat.completions.create( + model="gemini-1.5-pro", + messages=[{"role": "user", "content": "hi"}], + prompt_id="1234" +) + +print(response.choices[0].message.content) +``` + + + + +```python +from langchain.chat_models import ChatOpenAI +from langchain.schema import HumanMessage + +chat = ChatOpenAI( + model="gpt-4", + openai_api_key="sk-1234", + openai_api_base="http://0.0.0.0:4000", + extra_body={ + "prompt_id": "1234" + } +) + +messages = [] +response = chat(messages) + +print(response.content) +``` + + + + +```shell +curl -X POST http://0.0.0.0:4000/v1/chat/completions \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer sk-1234" \ +-d '{ + "model": "gemini-1.5-pro", + "messages": [{"role": "user", "content": "hi"}], + "prompt_id": "1234" +}' +``` + + + +The request will be transformed from: +```json +{ + "model": "gemini-1.5-pro", + "messages": [{"role": "user", "content": "hi"}], + "prompt_id": "1234" +} +``` + +To: +```json +{ + "model": "gemini-1.5-pro", + "messages": [ + {"role": "system", "content": "Be a good Bot!"}, + {"role": "user", "content": "hi"} + ] +} +``` + + diff --git a/docs/my-website/docs/proxy/db_deadlocks.md b/docs/my-website/docs/proxy/db_deadlocks.md new file mode 100644 index 00000000000..0eee928fa64 --- /dev/null +++ b/docs/my-website/docs/proxy/db_deadlocks.md @@ -0,0 +1,86 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# High Availability Setup (Resolve DB Deadlocks) + +Resolve any Database Deadlocks you see in high traffic by using this setup + +## What causes the problem? + +LiteLLM writes `UPDATE` and `UPSERT` queries to the DB. When using 10+ instances of LiteLLM, these queries can cause deadlocks since each instance could simultaneously attempt to update the same `user_id`, `team_id`, `key` etc. + +## How the high availability setup fixes the problem +- All instances will write to a Redis queue instead of the DB. +- A single instance will acquire a lock on the DB and flush the redis queue to the DB. + + +## How it works + +### Stage 1. Each instance writes updates to redis + +Each instance will accumulate the spend updates for a key, user, team, etc and write the updates to a redis queue. + + +

+Each instance writes updates to redis +

+ + +### Stage 2. A single instance flushes the redis queue to the DB + +A single instance will acquire a lock on the DB and flush all elements in the redis queue to the DB. + +- 1 instance will attempt to acquire the lock for the DB update job +- The status of the lock is stored in redis +- If the instance acquires the lock to write to DB + - It will read all updates from redis + - Aggregate all updates into 1 transaction + - Write updates to DB + - Release the lock +- Note: Only 1 instance can acquire the lock at a time, this limits the number of instances that can write to the DB at once + + + +

+A single instance flushes the redis queue to the DB +

+ + +## Usage + +### Required components + +- Redis +- Postgres + +### Setup on LiteLLM config + +You can enable using the redis buffer by setting `use_redis_transaction_buffer: true` in the `general_settings` section of your `proxy_config.yaml` file. + +Note: This setup requires litellm to be connected to a redis instance. + +```yaml showLineNumbers title="litellm proxy_config.yaml" +general_settings: + use_redis_transaction_buffer: true + +litellm_settings: + cache: True + cache_params: + type: redis + supported_call_types: [] # Optional: Set cache for proxy, but not on the actual llm api call +``` + +## Monitoring + +LiteLLM emits the following prometheus metrics to monitor the health/status of the in memory buffer and redis buffer. + + +| Metric Name | Description | Storage Type | +|-----------------------------------------------------|-----------------------------------------------------------------------------|--------------| +| `litellm_pod_lock_manager_size` | Indicates which pod has the lock to write updates to the database. | Redis | +| `litellm_in_memory_daily_spend_update_queue_size` | Number of items in the in-memory daily spend update queue. These are the aggregate spend logs for each user. | In-Memory | +| `litellm_redis_daily_spend_update_queue_size` | Number of items in the Redis daily spend update queue. These are the aggregate spend logs for each user. | Redis | +| `litellm_in_memory_spend_update_queue_size` | In-memory aggregate spend values for keys, users, teams, team members, etc.| In-Memory | +| `litellm_redis_spend_update_queue_size` | Redis aggregate spend values for keys, users, teams, etc. | Redis | + diff --git a/docs/my-website/docs/proxy/db_info.md b/docs/my-website/docs/proxy/db_info.md index 1b87aa1e548..946089bf147 100644 --- a/docs/my-website/docs/proxy/db_info.md +++ b/docs/my-website/docs/proxy/db_info.md @@ -46,18 +46,17 @@ You can see the full DB Schema [here](https://github.com/BerriAI/litellm/blob/ma | Table Name | Description | Row Insert Frequency | |------------|-------------|---------------------| -| LiteLLM_SpendLogs | Detailed logs of all API requests. Records token usage, spend, and timing information. Tracks which models and keys were used. | **High - every LLM API request** | -| LiteLLM_ErrorLogs | Captures failed requests and errors. Stores exception details and request information. Helps with debugging and monitoring. | **Medium - on errors only** | +| LiteLLM_SpendLogs | Detailed logs of all API requests. Records token usage, spend, and timing information. Tracks which models and keys were used. | **High - every LLM API request - Success or Failure** | | LiteLLM_AuditLog | Tracks changes to system configuration. Records who made changes and what was modified. Maintains history of updates to teams, users, and models. | **Off by default**, **High - when enabled** | -## Disable `LiteLLM_SpendLogs` & `LiteLLM_ErrorLogs` +## Disable `LiteLLM_SpendLogs` You can disable spend_logs and error_logs by setting `disable_spend_logs` and `disable_error_logs` to `True` on the `general_settings` section of your proxy_config.yaml file. ```yaml general_settings: disable_spend_logs: True # Disable writing spend logs to DB - disable_error_logs: True # Disable writing error logs to DB + disable_error_logs: True # Only disable writing error logs to DB, regular spend logs will still be written unless `disable_spend_logs: True` ``` ### What is the impact of disabling these logs? diff --git a/docs/my-website/docs/proxy/deploy.md b/docs/my-website/docs/proxy/deploy.md index 011778f5841..511a9dda087 100644 --- a/docs/my-website/docs/proxy/deploy.md +++ b/docs/my-website/docs/proxy/deploy.md @@ -22,7 +22,7 @@ echo 'LITELLM_MASTER_KEY="sk-1234"' > .env # Add the litellm salt key - you cannot change this after adding a model # It is used to encrypt / decrypt your LLM API Key credentials -# We recommned - https://1password.com/password-generator/ +# We recommend - https://1password.com/password-generator/ # password generator to get a random hash for litellm salt key echo 'LITELLM_SALT_KEY="sk-1234"' >> .env @@ -125,7 +125,7 @@ CMD ["--port", "4000", "--config", "config.yaml", "--detailed_debug"] ### Build from litellm `pip` package -Follow these instructons to build a docker container from the litellm pip package. If your company has a strict requirement around security / building images you can follow these steps. +Follow these instructions to build a docker container from the litellm pip package. If your company has a strict requirement around security / building images you can follow these steps. Dockerfile @@ -999,7 +999,7 @@ services: - "4000:4000" # Map the container port to the host, change the host port if necessary volumes: - ./litellm-config.yaml:/app/config.yaml # Mount the local configuration file - # You can change the port or number of workers as per your requirements or pass any new supported CLI augument. Make sure the port passed here matches with the container port defined above in `ports` value + # You can change the port or number of workers as per your requirements or pass any new supported CLI argument. Make sure the port passed here matches with the container port defined above in `ports` value command: [ "--config", "/app/config.yaml", "--port", "4000", "--num_workers", "8" ] # ...rest of your docker-compose config if any @@ -1049,3 +1049,25 @@ export DATABASE_SCHEMA="schema-name" # skip to use the default "public" schema litellm --config /path/to/config.yaml --iam_token_db_auth ``` +### ✨ Blocking web crawlers + +Note: This is an [enterprise only feature](https://docs.litellm.ai/docs/enterprise). + +To block web crawlers from indexing the proxy server endpoints, set the `block_robots` setting to `true` in your `litellm_config.yaml` file. + +```yaml showLineNumbers title="litellm_config.yaml" +general_settings: + block_robots: true +``` + +#### How it works + +When this is enabled, the `/robots.txt` endpoint will return a 200 status code with the following content: + +```shell showLineNumbers title="robots.txt" +User-agent: * +Disallow: / +``` + + + diff --git a/docs/my-website/docs/proxy/email.md b/docs/my-website/docs/proxy/email.md index a3f3a41694e..4eb35367dbe 100644 --- a/docs/my-website/docs/proxy/email.md +++ b/docs/my-website/docs/proxy/email.md @@ -1,35 +1,130 @@ import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; # Email Notifications -Send an Email to your users when: -- A Proxy API Key is created for them -- Their API Key crosses it's Budget -- All Team members of a LiteLLM Team -> when the team crosses it's budget + +

+ LiteLLM Email Notifications +

- +## Overview -## Quick Start +Send LiteLLM Proxy users emails for specific events. + +| Category | Details | +|----------|---------| +| Supported Events | • User added as a user on LiteLLM Proxy
• Proxy API Key created for user | +| Supported Email Integrations | • Resend API
• SMTP | + +## Usage + +:::info + +LiteLLM Cloud: This feature is enabled for all LiteLLM Cloud users, there's no need to configure anything. + +::: + +### 1. Configure email integration + + + Get SMTP credentials to set this up + +```yaml showLineNumbers title="proxy_config.yaml" +litellm_settings: + callbacks: ["smtp_email"] +``` + Add the following to your proxy env -```shell +```shell showLineNumbers SMTP_HOST="smtp.resend.com" +SMTP_TLS="True" +SMTP_PORT="587" SMTP_USERNAME="resend" -SMTP_PASSWORD="*******" -SMTP_SENDER_EMAIL="support@alerts.litellm.ai" # email to send alerts from: `support@alerts.litellm.ai` +SMTP_SENDER_EMAIL="notifications@alerts.litellm.ai" +SMTP_PASSWORD="xxxxx" ``` -Add `email` to your proxy config.yaml under `general_settings` + + -```yaml -general_settings: - master_key: sk-1234 - alerting: ["email"] +Add `resend_email` to your proxy config.yaml under `litellm_settings` + +set the following env variables + +```shell showLineNumbers +RESEND_API_KEY="re_1234" ``` -That's it ! start your proxy +```yaml showLineNumbers title="proxy_config.yaml" +litellm_settings: + callbacks: ["resend_email"] +``` + + + + +### 2. Create a new user + +On the LiteLLM Proxy UI, go to users > create a new user. + +After creating a new user, they will receive an email invite a the email you specified when creating the user. + +## Email Templates + + +### 1. User added as a user on LiteLLM Proxy + +This email is send when you create a new user on LiteLLM Proxy. + + + +**How to trigger this event** + +On the LiteLLM Proxy UI, go to Users > Create User > Enter the user's email address > Create User. + + + +### 2. Proxy API Key created for user + +This email is sent when you create a new API key for a user on LiteLLM Proxy. + + + +**How to trigger this event** + +On the LiteLLM Proxy UI, go to Virtual Keys > Create API Key > Select User ID + + + +On the Create Key Modal, Select Advanced Settings > Set Send Email to True. + + + + + ## Customizing Email Branding diff --git a/docs/my-website/docs/proxy/enterprise.md b/docs/my-website/docs/proxy/enterprise.md index a5988cab8e8..6789fb6ef2f 100644 --- a/docs/my-website/docs/proxy/enterprise.md +++ b/docs/my-website/docs/proxy/enterprise.md @@ -14,7 +14,7 @@ Features: - **Security** - ✅ [SSO for Admin UI](./ui.md#✨-enterprise-features) - ✅ [Audit Logs with retention policy](#audit-logs) - - ✅ [JWT-Auth](../docs/proxy/token_auth.md) + - ✅ [JWT-Auth](./token_auth.md) - ✅ [Control available public, private routes (Restrict certain endpoints on proxy)](#control-available-public-private-routes) - ✅ [Control available public, private routes](#control-available-public-private-routes) - ✅ [Secret Managers - AWS Key Manager, Google Secret Manager, Azure Key, Hashicorp Vault](../secret) @@ -40,10 +40,12 @@ Features: - **Control Guardrails per API Key** - **Custom Branding** - ✅ [Custom Branding + Routes on Swagger Docs](#swagger-docs---custom-routes--branding) - - ✅ [Public Model Hub](../docs/proxy/enterprise.md#public-model-hub) - - ✅ [Custom Email Branding](../docs/proxy/email.md#customizing-email-branding) + - ✅ [Public Model Hub](#public-model-hub) + - ✅ [Custom Email Branding](./email.md#customizing-email-branding) -## Audit Logs +## Security + +### Audit Logs Store Audit logs for **Create, Update Delete Operations** done on `Teams` and `Virtual Keys` @@ -95,7 +97,295 @@ curl --location 'http://0.0.0.0:4000/team/new' \ ``` -## Tracking Spend for Custom Tags +### Blocking web crawlers + +To block web crawlers from indexing the proxy server endpoints, set the `block_robots` setting to `true` in your `litellm_config.yaml` file. + +```yaml showLineNumbers title="litellm_config.yaml" +general_settings: + block_robots: true +``` + +#### How it works + +When this is enabled, the `/robots.txt` endpoint will return a 200 status code with the following content: + +```shell showLineNumbers title="robots.txt" +User-agent: * +Disallow: / +``` + + + +### Required Params for LLM Requests +Use this when you want to enforce all requests to include certain params. Example you need all requests to include the `user` and `["metadata]["generation_name"]` params. + + + + + + +**Step 1** Define all Params you want to enforce on config.yaml + +This means `["user"]` and `["metadata]["generation_name"]` are required in all LLM Requests to LiteLLM + +```yaml +general_settings: + master_key: sk-1234 + enforced_params: + - user + - metadata.generation_name +``` + + + + +```bash +curl -L -X POST 'http://0.0.0.0:4000/key/generate' \ +-H 'Authorization: Bearer sk-1234' \ +-H 'Content-Type: application/json' \ +-d '{ + "enforced_params": ["user", "metadata.generation_name"] +}' +``` + + + + +**Step 2 Verify if this works** + + + + + +```shell +curl --location 'http://localhost:4000/chat/completions' \ + --header 'Authorization: Bearer sk-5fmYeaUEbAMpwBNT-QpxyA' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "hi" + } + ] +}' +``` + +Expected Response + +```shell +{"error":{"message":"Authentication Error, BadRequest please pass param=user in request body. This is a required param","type":"auth_error","param":"None","code":401}}% +``` + + + + + +```shell +curl --location 'http://localhost:4000/chat/completions' \ + --header 'Authorization: Bearer sk-5fmYeaUEbAMpwBNT-QpxyA' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "gpt-3.5-turbo", + "user": "gm", + "messages": [ + { + "role": "user", + "content": "hi" + } + ], + "metadata": {} +}' +``` + +Expected Response + +```shell +{"error":{"message":"Authentication Error, BadRequest please pass param=[metadata][generation_name] in request body. This is a required param","type":"auth_error","param":"None","code":401}}% +``` + + + + + +```shell +curl --location 'http://localhost:4000/chat/completions' \ + --header 'Authorization: Bearer sk-5fmYeaUEbAMpwBNT-QpxyA' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "gpt-3.5-turbo", + "user": "gm", + "messages": [ + { + "role": "user", + "content": "hi" + } + ], + "metadata": {"generation_name": "prod-app"} +}' +``` + +Expected Response + +```shell +{"id":"chatcmpl-9XALnHqkCBMBKrOx7Abg0hURHqYtY","choices":[{"finish_reason":"stop","index":0,"message":{"content":"Hello! How can I assist you today?","role":"assistant"}}],"created":1717691639,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"usage":{"completion_tokens":9,"prompt_tokens":8,"total_tokens":17}}% +``` + + + + + + +### Control available public, private routes + +**Restrict certain endpoints of proxy** + +:::info + +❓ Use this when you want to: +- make an existing private route -> public +- set certain routes as admin_only routes + +::: + +#### Usage - Define public, admin only routes + +**Step 1** - Set on config.yaml + + +| Route Type | Optional | Requires Virtual Key Auth | Admin Can Access | All Roles Can Access | Description | +|------------|----------|---------------------------|-------------------|----------------------|-------------| +| `public_routes` | ✅ | ❌ | ✅ | ✅ | Routes that can be accessed without any authentication | +| `admin_only_routes` | ✅ | ✅ | ✅ | ❌ | Routes that can only be accessed by [Proxy Admin](./self_serve#available-roles) | +| `allowed_routes` | ✅ | ✅ | ✅ | ✅ | Routes are exposed on the proxy. If not set then all routes exposed. | + +`LiteLLMRoutes.public_routes` is an ENUM corresponding to the default public routes on LiteLLM. [You can see this here](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/_types.py) + +```yaml +general_settings: + master_key: sk-1234 + public_routes: ["LiteLLMRoutes.public_routes", "/spend/calculate"] # routes that can be accessed without any auth + admin_only_routes: ["/key/generate"] # Optional - routes that can only be accessed by Proxy Admin + allowed_routes: ["/chat/completions", "/spend/calculate", "LiteLLMRoutes.public_routes"] # Optional - routes that can be accessed by anyone after Authentication +``` + +**Step 2** - start proxy + +```shell +litellm --config config.yaml +``` + +**Step 3** - Test it + + + + + +```shell +curl --request POST \ + --url 'http://localhost:4000/spend/calculate' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "Hey, how'\''s it going?"}] + }' +``` + +🎉 Expect this endpoint to work without an `Authorization / Bearer Token` + + + + + + +**Successful Request** + +```shell +curl --location 'http://0.0.0.0:4000/key/generate' \ +--header 'Authorization: Bearer ' \ +--header 'Content-Type: application/json' \ +--data '{}' +``` + + +**Un-successfull Request** + +```shell + curl --location 'http://0.0.0.0:4000/key/generate' \ +--header 'Authorization: Bearer ' \ +--header 'Content-Type: application/json' \ +--data '{"user_role": "internal_user"}' +``` + +**Expected Response** + +```json +{ + "error": { + "message": "user not allowed to access this route. Route=/key/generate is an admin only route", + "type": "auth_error", + "param": "None", + "code": "403" + } +} +``` + + + + + + + +**Successful Request** + +```shell +curl http://localhost:4000/chat/completions \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer sk-1234" \ +-d '{ +"model": "fake-openai-endpoint", +"messages": [ + {"role": "user", "content": "Hello, Claude"} +] +}' +``` + + +**Un-successfull Request** + +```shell +curl --location 'http://0.0.0.0:4000/embeddings' \ +--header 'Content-Type: application/json' \ +-H "Authorization: Bearer sk-1234" \ +--data ' { +"model": "text-embedding-ada-002", +"input": ["write a litellm poem"] +}' +``` + +**Expected Response** + +```json +{ + "error": { + "message": "Route /embeddings not allowed", + "type": "auth_error", + "param": "None", + "code": "403" + } +} +``` + + + + + + +## Spend Tracking + +### Custom Tags Requirements: @@ -294,7 +584,7 @@ curl -X GET "http://0.0.0.0:4000/spend/tags" \ ``` -## Tracking Spend with custom metadata +### Tracking Spend with custom metadata Requirements: @@ -506,278 +796,6 @@ curl -X GET "http://0.0.0.0:4000/spend/logs?request_id= - - - -**Step 1** Define all Params you want to enforce on config.yaml - -This means `["user"]` and `["metadata]["generation_name"]` are required in all LLM Requests to LiteLLM - -```yaml -general_settings: - master_key: sk-1234 - enforced_params: - - user - - metadata.generation_name -``` - - - - -```bash -curl -L -X POST 'http://0.0.0.0:4000/key/generate' \ --H 'Authorization: Bearer sk-1234' \ --H 'Content-Type: application/json' \ --d '{ - "enforced_params": ["user", "metadata.generation_name"] -}' -``` - - - - -**Step 2 Verify if this works** - - - - - -```shell -curl --location 'http://localhost:4000/chat/completions' \ - --header 'Authorization: Bearer sk-5fmYeaUEbAMpwBNT-QpxyA' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "gpt-3.5-turbo", - "messages": [ - { - "role": "user", - "content": "hi" - } - ] -}' -``` - -Expected Response - -```shell -{"error":{"message":"Authentication Error, BadRequest please pass param=user in request body. This is a required param","type":"auth_error","param":"None","code":401}}% -``` - - - - - -```shell -curl --location 'http://localhost:4000/chat/completions' \ - --header 'Authorization: Bearer sk-5fmYeaUEbAMpwBNT-QpxyA' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "gpt-3.5-turbo", - "user": "gm", - "messages": [ - { - "role": "user", - "content": "hi" - } - ], - "metadata": {} -}' -``` - -Expected Response - -```shell -{"error":{"message":"Authentication Error, BadRequest please pass param=[metadata][generation_name] in request body. This is a required param","type":"auth_error","param":"None","code":401}}% -``` - - - - - -```shell -curl --location 'http://localhost:4000/chat/completions' \ - --header 'Authorization: Bearer sk-5fmYeaUEbAMpwBNT-QpxyA' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "gpt-3.5-turbo", - "user": "gm", - "messages": [ - { - "role": "user", - "content": "hi" - } - ], - "metadata": {"generation_name": "prod-app"} -}' -``` - -Expected Response - -```shell -{"id":"chatcmpl-9XALnHqkCBMBKrOx7Abg0hURHqYtY","choices":[{"finish_reason":"stop","index":0,"message":{"content":"Hello! How can I assist you today?","role":"assistant"}}],"created":1717691639,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"usage":{"completion_tokens":9,"prompt_tokens":8,"total_tokens":17}}% -``` - - - - - - -## Control available public, private routes - -**Restrict certain endpoints of proxy** - -:::info - -❓ Use this when you want to: -- make an existing private route -> public -- set certain routes as admin_only routes - -::: - -#### Usage - Define public, admin only routes - -**Step 1** - Set on config.yaml - - -| Route Type | Optional | Requires Virtual Key Auth | Admin Can Access | All Roles Can Access | Description | -|------------|----------|---------------------------|-------------------|----------------------|-------------| -| `public_routes` | ✅ | ❌ | ✅ | ✅ | Routes that can be accessed without any authentication | -| `admin_only_routes` | ✅ | ✅ | ✅ | ❌ | Routes that can only be accessed by [Proxy Admin](./self_serve#available-roles) | -| `allowed_routes` | ✅ | ✅ | ✅ | ✅ | Routes are exposed on the proxy. If not set then all routes exposed. | - -`LiteLLMRoutes.public_routes` is an ENUM corresponding to the default public routes on LiteLLM. [You can see this here](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/_types.py) - -```yaml -general_settings: - master_key: sk-1234 - public_routes: ["LiteLLMRoutes.public_routes", "/spend/calculate"] # routes that can be accessed without any auth - admin_only_routes: ["/key/generate"] # Optional - routes that can only be accessed by Proxy Admin - allowed_routes: ["/chat/completions", "/spend/calculate", "LiteLLMRoutes.public_routes"] # Optional - routes that can be accessed by anyone after Authentication -``` - -**Step 2** - start proxy - -```shell -litellm --config config.yaml -``` - -**Step 3** - Test it - - - - - -```shell -curl --request POST \ - --url 'http://localhost:4000/spend/calculate' \ - --header 'Content-Type: application/json' \ - --data '{ - "model": "gpt-4", - "messages": [{"role": "user", "content": "Hey, how'\''s it going?"}] - }' -``` - -🎉 Expect this endpoint to work without an `Authorization / Bearer Token` - - - - - - -**Successfull Request** - -```shell -curl --location 'http://0.0.0.0:4000/key/generate' \ ---header 'Authorization: Bearer ' \ ---header 'Content-Type: application/json' \ ---data '{}' -``` - - -**Un-successfull Request** - -```shell - curl --location 'http://0.0.0.0:4000/key/generate' \ ---header 'Authorization: Bearer ' \ ---header 'Content-Type: application/json' \ ---data '{"user_role": "internal_user"}' -``` - -**Expected Response** - -```json -{ - "error": { - "message": "user not allowed to access this route. Route=/key/generate is an admin only route", - "type": "auth_error", - "param": "None", - "code": "403" - } -} -``` - - - - - - - -**Successfull Request** - -```shell -curl http://localhost:4000/chat/completions \ --H "Content-Type: application/json" \ --H "Authorization: Bearer sk-1234" \ --d '{ -"model": "fake-openai-endpoint", -"messages": [ - {"role": "user", "content": "Hello, Claude"} -] -}' -``` - - -**Un-successfull Request** - -```shell -curl --location 'http://0.0.0.0:4000/embeddings' \ ---header 'Content-Type: application/json' \ --H "Authorization: Bearer sk-1234" \ ---data ' { -"model": "text-embedding-ada-002", -"input": ["write a litellm poem"] -}' -``` - -**Expected Response** - -```json -{ - "error": { - "message": "Route /embeddings not allowed", - "type": "auth_error", - "param": "None", - "code": "403" - } -} -``` - - - - - - - - - - ## Guardrails - Secret Detection/Redaction ❓ Use this to REDACT API Keys, Secrets sent in requests to an LLM. diff --git a/docs/my-website/docs/proxy/guardrails/aim_security.md b/docs/my-website/docs/proxy/guardrails/aim_security.md index d588afa424a..d76c4e0c1c5 100644 --- a/docs/my-website/docs/proxy/guardrails/aim_security.md +++ b/docs/my-website/docs/proxy/guardrails/aim_security.md @@ -23,6 +23,12 @@ In the newly created guard's page, you can find a reference to the prompt policy You can decide which detections will be enabled, and set the threshold for each detection. +:::info +When using LiteLLM with virtual keys, key-specific policies can be set directly in Aim's guards page by specifying the virtual key alias when creating the guard. + +Only the aliases of your virtual keys (and not the actual key secrets) will be sent to Aim. +::: + ### 3. Add Aim Guardrail on your LiteLLM config.yaml Define your guardrails under the `guardrails` section @@ -37,7 +43,7 @@ guardrails: - guardrail_name: aim-protected-app litellm_params: guardrail: aim - mode: pre_call + mode: [pre_call, post_call] # "During_call" is also available api_key: os.environ/AIM_API_KEY api_base: os.environ/AIM_API_BASE # Optional, use only when using a self-hosted Aim Outpost ``` @@ -134,7 +140,7 @@ The above request should not be blocked, and you should receive a regular LLM re -# Advanced +## Advanced Aim Guard provides user-specific Guardrail policies, enabling you to apply tailored policies to individual users. To utilize this feature, include the end-user's email in the request payload by setting the `x-aim-user-email` header of your request. diff --git a/docs/my-website/docs/proxy/guardrails/bedrock.md b/docs/my-website/docs/proxy/guardrails/bedrock.md index 0da2238bcf0..a0c43d47dec 100644 --- a/docs/my-website/docs/proxy/guardrails/bedrock.md +++ b/docs/my-website/docs/proxy/guardrails/bedrock.md @@ -2,7 +2,7 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Bedrock +# Bedrock Guardrails LiteLLM supports Bedrock guardrails via the [Bedrock ApplyGuardrail API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ApplyGuardrail.html). @@ -135,3 +135,48 @@ curl -i http://localhost:4000/v1/chat/completions \ +## PII Masking with Bedrock Guardrails + +Bedrock guardrails support PII detection and masking capabilities. To enable this feature, you need to: + +1. Set `mode` to `pre_call` to run the guardrail check before the LLM call +2. Enable masking by setting `mask_request_content` and/or `mask_response_content` to `true` + +Here's how to configure it in your config.yaml: + +```yaml showLineNumbers title="litellm proxy config.yaml" +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: openai/gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + +guardrails: + - guardrail_name: "bedrock-pre-guard" + litellm_params: + guardrail: bedrock + mode: "pre_call" # Important: must use pre_call mode for masking + guardrailIdentifier: wf0hkdb5x07f + guardrailVersion: "DRAFT" + mask_request_content: true # Enable masking in user requests + mask_response_content: true # Enable masking in model responses +``` + +With this configuration, when the bedrock guardrail intervenes, litellm will read the masked output from the guardrail and send it to the model. + +### Example Usage + +When enabled, PII will be automatically masked in the text. For example, if a user sends: + +``` +My email is john.doe@example.com and my phone number is 555-123-4567 +``` + +The text sent to the model might be masked as: + +``` +My email is [EMAIL] and my phone number is [PHONE_NUMBER] +``` + +This helps protect sensitive information while still allowing the model to understand the context of the request. + diff --git a/docs/my-website/docs/proxy/guardrails/custom_guardrail.md b/docs/my-website/docs/proxy/guardrails/custom_guardrail.md index 50deac511fb..657ccab68e4 100644 --- a/docs/my-website/docs/proxy/guardrails/custom_guardrail.md +++ b/docs/my-website/docs/proxy/guardrails/custom_guardrail.md @@ -10,10 +10,12 @@ Use this is you want to write code to run a custom guardrail ### 1. Write a `CustomGuardrail` Class -A CustomGuardrail has 3 methods to enforce guardrails +A CustomGuardrail has 4 methods to enforce guardrails - `async_pre_call_hook` - (Optional) modify input or reject request before making LLM API call - `async_moderation_hook` - (Optional) reject request, runs while making LLM API call (help to lower latency) - `async_post_call_success_hook`- (Optional) apply guardrail on input/output, runs after making LLM API call +- `async_post_call_streaming_iterator_hook` - (Optional) pass the entire stream to the guardrail + **[See detailed spec of methods here](#customguardrail-methods)** @@ -128,6 +130,23 @@ class myCustomGuardrail(CustomGuardrail): ): raise ValueError("Guardrail failed Coffee Detected") + async def async_post_call_streaming_iterator_hook( + self, + user_api_key_dict: UserAPIKeyAuth, + response: Any, + request_data: dict, + ) -> AsyncGenerator[ModelResponseStream, None]: + """ + Passes the entire stream to the guardrail + + This is useful for guardrails that need to see the entire response, such as PII masking. + + See Aim guardrail implementation for an example - https://github.com/BerriAI/litellm/blob/d0e022cfacb8e9ebc5409bb652059b6fd97b45c0/litellm/proxy/guardrails/guardrail_hooks/aim.py#L168 + + Triggered by mode: 'post_call' + """ + async for item in response: + yield item ``` diff --git a/docs/my-website/docs/proxy/guardrails/lakera_ai.md b/docs/my-website/docs/proxy/guardrails/lakera_ai.md index ba1ca0b2183..e66329dcb0c 100644 --- a/docs/my-website/docs/proxy/guardrails/lakera_ai.md +++ b/docs/my-website/docs/proxy/guardrails/lakera_ai.md @@ -8,7 +8,8 @@ import TabItem from '@theme/TabItem'; ### 1. Define Guardrails on your LiteLLM config.yaml Define your guardrails under the `guardrails` section -```yaml + +```yaml showLineNumbers title="litellm config.yaml" model_list: - model_name: gpt-3.5-turbo litellm_params: @@ -18,13 +19,13 @@ model_list: guardrails: - guardrail_name: "lakera-guard" litellm_params: - guardrail: lakera # supported values: "aporia", "bedrock", "lakera" + guardrail: lakera_v2 # supported values: "aporia", "bedrock", "lakera" mode: "during_call" api_key: os.environ/LAKERA_API_KEY api_base: os.environ/LAKERA_API_BASE - guardrail_name: "lakera-pre-guard" litellm_params: - guardrail: lakera # supported values: "aporia", "bedrock", "lakera" + guardrail: lakera_v2 # supported values: "aporia", "bedrock", "lakera" mode: "pre_call" api_key: os.environ/LAKERA_API_KEY api_base: os.environ/LAKERA_API_BASE @@ -53,7 +54,7 @@ litellm --config config.yaml --detailed_debug Expect this to fail since since `ishaan@berri.ai` in the request is PII -```shell +```shell showLineNumbers title="Curl Request" curl -i http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-npnwjPQciVRok5yNZgKmFQ" \ @@ -108,7 +109,7 @@ Expected response on failure -```shell +```shell showLineNumbers title="Curl Request" curl -i http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-npnwjPQciVRok5yNZgKmFQ" \ @@ -125,31 +126,3 @@ curl -i http://localhost:4000/v1/chat/completions \ - -## Advanced -### Set category-based thresholds. - -Lakera has 2 categories for prompt_injection attacks: -- jailbreak -- prompt_injection - -```yaml -model_list: - - model_name: fake-openai-endpoint - litellm_params: - model: openai/fake - api_key: fake-key - api_base: https://exampleopenaiendpoint-production.up.railway.app/ - -guardrails: - - guardrail_name: "lakera-guard" - litellm_params: - guardrail: lakera # supported values: "aporia", "bedrock", "lakera" - mode: "during_call" - api_key: os.environ/LAKERA_API_KEY - api_base: os.environ/LAKERA_API_BASE - category_thresholds: - prompt_injection: 0.1 - jailbreak: 0.1 - -``` \ No newline at end of file diff --git a/docs/my-website/docs/proxy/guardrails/pii_masking_v2.md b/docs/my-website/docs/proxy/guardrails/pii_masking_v2.md index 59690666ee4..427308cf221 100644 --- a/docs/my-website/docs/proxy/guardrails/pii_masking_v2.md +++ b/docs/my-website/docs/proxy/guardrails/pii_masking_v2.md @@ -2,16 +2,60 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# PII Masking - Presidio +# PII, PHI Masking - Presidio + +## Overview + +| Property | Details | +|-------|-------| +| Description | Use this guardrail to mask PII (Personally Identifiable Information), PHI (Protected Health Information), and other sensitive data. | +| Provider | [Microsoft Presidio](https://github.com/microsoft/presidio/) | +| Supported Entity Types | All Presidio Entity Types | +| Supported Actions | `MASK`, `BLOCK` | +| Supported Modes | `pre_call`, `during_call`, `post_call`, `logging_only` | + +## Deployment options + +For this guardrail you need a deployed Presidio Analyzer and Presido Anonymizer containers. + +| Deployment Option | Details | +|------------------|----------| +| Deploy Presidio Docker Containers | - [Presidio Analyzer Docker Container](https://hub.docker.com/r/microsoft/presidio-analyzer)
- [Presidio Anonymizer Docker Container](https://hub.docker.com/r/microsoft/presidio-anonymizer) | ## Quick Start -LiteLLM supports [Microsoft Presidio](https://github.com/microsoft/presidio/) for PII masking. + + -### 1. Define Guardrails on your LiteLLM config.yaml +### 1. Create a PII, PHI Masking Guardrail + +On the LiteLLM UI, navigate to Guardrails. Click "Add Guardrail". On this dropdown select "Presidio PII" and enter your presidio analyzer and anonymizer endpoints. + + + +
+
+ +#### 1.2 Configure Entity Types + +Now select the entity types you want to mask. See the [supported actions here](#supported-actions) + + + +
+ + + Define your guardrails under the `guardrails` section -```yaml + +```yaml title="config.yaml" showLineNumbers model_list: - model_name: gpt-3.5-turbo litellm_params: @@ -19,7 +63,7 @@ model_list: api_key: os.environ/OPENAI_API_KEY guardrails: - - guardrail_name: "presidio-pre-guard" + - guardrail_name: "presidio-pii" litellm_params: guardrail: presidio # supported values: "aporia", "bedrock", "lakera", "presidio" mode: "pre_call" @@ -27,7 +71,7 @@ guardrails: Set the following env vars -```bash +```bash title="Setup Environment Variables" showLineNumbers export PRESIDIO_ANALYZER_API_BASE="http://localhost:5002" export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" ``` @@ -38,15 +82,36 @@ export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" - `post_call` Run **after** LLM call, on **input & output** - `logging_only` Run **after** LLM call, only apply PII Masking before logging to Langfuse, etc. Not on the actual llm api request / response. - ### 2. Start LiteLLM Gateway - -```shell +```shell title="Start Gateway" showLineNumbers litellm --config config.yaml --detailed_debug ``` -### 3. Test request + +
+ + +### 3. Test it! + +#### 3.1 LiteLLM UI + +On the litellm UI, navigate to the 'Test Keys' page, select the guardrail you created and send the following messaged filled with PII data. + +```text title="PII Request" showLineNumbers +My credit card is 4111-1111-1111-1111 and my email is test@example.com. +``` + + + +
+ +#### 3.2 Test in code + +In order to apply a guardrail for a request send `guardrails=["presidio-pii"]` in the request body. **[Langchain, OpenAI SDK Usage Examples](../proxy/user_keys#request-format)** @@ -55,7 +120,7 @@ litellm --config config.yaml --detailed_debug Expect this to mask `Jane Doe` since it's PII -```shell +```shell title="Masked PII Request" showLineNumbers curl http://localhost:4000/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ @@ -64,13 +129,13 @@ curl http://localhost:4000/chat/completions \ "messages": [ {"role": "user", "content": "Hello my name is Jane Doe"} ], - "guardrails": ["presidio-pre-guard"], + "guardrails": ["presidio-pii"], }' ``` Expected response on failure -```shell +```shell title="Response with Masked PII" showLineNumbers { "id": "chatcmpl-A3qSC39K7imjGbZ8xCDacGJZBoTJQ", "choices": [ @@ -102,7 +167,7 @@ Expected response on failure -```shell +```shell title="No PII Request" showLineNumbers curl http://localhost:4000/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ @@ -111,13 +176,150 @@ curl http://localhost:4000/chat/completions \ "messages": [ {"role": "user", "content": "Hello good morning"} ], - "guardrails": ["presidio-pre-guard"], + "guardrails": ["presidio-pii"], }' ``` + +## Tracing Guardrail requests + +Once your guardrail is live in production, you will also be able to trace your guardrail on LiteLLM Logs, Langfuse, Arize Phoenix, etc, all LiteLLM logging integrations. + +### LiteLLM UI + +On the LiteLLM logs page you can see that the PII content was masked for this specific request. And you can see detailed tracing for the guardrail. This allows you to monitor entity types masked with their corresponding confidence score and the duration of the guardrail execution. + + + +### Langfuse + +When connecting Litellm to Langfuse, you can see the guardrail information on the Langfuse Trace. + + + +## Entity Type Configuration + +You can configure specific entity types for PII detection and decide how to handle each entity type (mask or block). + +### Configure Entity Types in config.yaml + +Define your guardrails with specific entity type configuration: + +```yaml title="config.yaml with Entity Types" showLineNumbers +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: openai/gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + +guardrails: + - guardrail_name: "presidio-mask-guard" + litellm_params: + guardrail: presidio + mode: "pre_call" + pii_entities_config: + CREDIT_CARD: "MASK" # Will mask credit card numbers + EMAIL_ADDRESS: "MASK" # Will mask email addresses + + - guardrail_name: "presidio-block-guard" + litellm_params: + guardrail: presidio + mode: "pre_call" + pii_entities_config: + CREDIT_CARD: "BLOCK" # Will block requests containing credit card numbers +``` + +### Supported Entity Types + +LiteLLM Supports all Presidio entity types. See the complete list of presidio entity types [here](https://microsoft.github.io/presidio/supported_entities/). + +### Supported Actions + +For each entity type, you can specify one of the following actions: + +- `MASK`: Replace the entity with a placeholder (e.g., ``) +- `BLOCK`: Block the request entirely if this entity type is detected + +### Test request with Entity Type Configuration + + + + +When using the masking configuration, entities will be replaced with placeholders: + +```shell title="Masking PII Request" showLineNumbers +curl http://localhost:4000/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "messages": [ + {"role": "user", "content": "My credit card is 4111-1111-1111-1111 and my email is test@example.com"} + ], + "guardrails": ["presidio-mask-guard"] + }' +``` + +Example response with masked entities: + +```json +{ + "id": "chatcmpl-123abc", + "choices": [ + { + "message": { + "content": "I can see you provided a and an . For security reasons, I recommend not sharing this sensitive information.", + "role": "assistant" + }, + "index": 0, + "finish_reason": "stop" + } + ], + // ... other response fields +} +``` + + + + + +When using the blocking configuration, requests containing the configured entity types will be blocked completely with an exception: + +```shell title="Blocking PII Request" showLineNumbers +curl http://localhost:4000/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "gpt-3.5-turbo", + "messages": [ + {"role": "user", "content": "My credit card is 4111-1111-1111-1111"} + ], + "guardrails": ["presidio-block-guard"] + }' +``` + +When running this request, the proxy will raise a `BlockedPiiEntityError` exception. + +```json +{ + "error": { + "message": "Blocked PII entity detected: CREDIT_CARD by Guardrail: presidio-block-guard." + } +} +``` + +The exception includes the entity type that was blocked (`CREDIT_CARD` in this case) and the guardrail name that caused the blocking. + + ## Advanced @@ -129,7 +331,7 @@ The Presidio API [supports passing the `language` param](https://microsoft.githu -```shell +```shell title="Language Parameter - curl" showLineNumbers curl http://localhost:4000/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ @@ -148,8 +350,7 @@ curl http://localhost:4000/chat/completions \ -```python - +```python title="Language Parameter - Python" showLineNumbers import openai client = openai.OpenAI( api_key="anything", @@ -179,7 +380,6 @@ print(response) - ### Output parsing @@ -188,7 +388,7 @@ LLM responses can sometimes contain the masked tokens. For presidio 'replace' operations, LiteLLM can check the LLM response and replace the masked token with the user-submitted values. Define your guardrails under the `guardrails` section -```yaml +```yaml title="Output Parsing Config" showLineNumbers model_list: - model_name: gpt-3.5-turbo litellm_params: @@ -223,7 +423,7 @@ Send ad-hoc recognizers to presidio `/analyze` by passing a json file to the pro #### Define ad-hoc recognizer on your LiteLLM config.yaml Define your guardrails under the `guardrails` section -```yaml +```yaml title="Ad Hoc Recognizers Config" showLineNumbers model_list: - model_name: gpt-3.5-turbo litellm_params: @@ -240,7 +440,7 @@ guardrails: Set the following env vars -```bash +```bash title="Ad Hoc Recognizers Environment Variables" showLineNumbers export PRESIDIO_ANALYZER_API_BASE="http://localhost:5002" export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" ``` @@ -248,13 +448,13 @@ export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" You can see this working, when you run the proxy: -```bash +```bash title="Run Proxy with Debug" showLineNumbers litellm --config /path/to/config.yaml --debug ``` Make a chat completions request, example: -``` +```json title="Custom PII Request" showLineNumbers { "model": "azure-gpt-3.5", "messages": [{"role": "user", "content": "John Smith AHV number is 756.3026.0705.92. Zip code: 1334023"}] @@ -262,7 +462,7 @@ Make a chat completions request, example: ``` And search for any log starting with `Presidio PII Masking`, example: -``` +```text title="PII Masking Log" showLineNumbers Presidio PII Masking: Redacted pii message: AHV number is . Zip code: ``` @@ -283,7 +483,7 @@ This is currently only applied for 1. Define mode: `logging_only` on your LiteLLM config.yaml Define your guardrails under the `guardrails` section -```yaml +```yaml title="Logging Only Config" showLineNumbers model_list: - model_name: gpt-3.5-turbo litellm_params: @@ -299,7 +499,7 @@ guardrails: Set the following env vars -```bash +```bash title="Logging Only Environment Variables" showLineNumbers export PRESIDIO_ANALYZER_API_BASE="http://localhost:5002" export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" ``` @@ -307,13 +507,13 @@ export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" 2. Start proxy -```bash +```bash title="Start Proxy" showLineNumbers litellm --config /path/to/config.yaml ``` 3. Test it! -```bash +```bash title="Test Logging Only" showLineNumbers curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ @@ -331,7 +531,7 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ **Expected Logged Response** -``` +```text title="Logged Response with Masked PII" showLineNumbers Hi, my name is ! ``` diff --git a/docs/my-website/docs/prompt_injection.md b/docs/my-website/docs/proxy/guardrails/prompt_injection.md similarity index 100% rename from docs/my-website/docs/prompt_injection.md rename to docs/my-website/docs/proxy/guardrails/prompt_injection.md diff --git a/docs/my-website/docs/proxy/guardrails/quick_start.md b/docs/my-website/docs/proxy/guardrails/quick_start.md index 35f720bf7e8..55cfa98d486 100644 --- a/docs/my-website/docs/proxy/guardrails/quick_start.md +++ b/docs/my-website/docs/proxy/guardrails/quick_start.md @@ -17,6 +17,14 @@ model_list: api_key: os.environ/OPENAI_API_KEY guardrails: + - guardrail_name: general-guard + litellm_params: + guardrail: aim + mode: [pre_call, post_call] + api_key: os.environ/AIM_API_KEY + api_base: os.environ/AIM_API_BASE + default_on: true # Optional + - guardrail_name: "aporia-pre-guard" litellm_params: guardrail: aporia # supported values: "aporia", "lakera" @@ -45,6 +53,7 @@ guardrails: - `pre_call` Run **before** LLM call, on **input** - `post_call` Run **after** LLM call, on **input & output** - `during_call` Run **during** LLM call, on **input** Same as `pre_call` but runs in parallel as LLM call. Response not returned until guardrail check completes +- A list of the above values to run multiple modes, e.g. `mode: [pre_call, post_call]` ## 2. Start LiteLLM Gateway @@ -155,7 +164,7 @@ curl -i http://localhost:4000/v1/chat/completions \ **Expected response** -Your response headers will incude `x-litellm-applied-guardrails` with the guardrail applied +Your response headers will include `x-litellm-applied-guardrails` with the guardrail applied ``` x-litellm-applied-guardrails: aporia-pre-guard @@ -524,7 +533,7 @@ guardrails: - guardrail_name: string # Required: Name of the guardrail litellm_params: # Required: Configuration parameters guardrail: string # Required: One of "aporia", "bedrock", "guardrails_ai", "lakera", "presidio", "hide-secrets" - mode: string # Required: One of "pre_call", "post_call", "during_call", "logging_only" + mode: Union[string, List[string]] # Required: One or more of "pre_call", "post_call", "during_call", "logging_only" api_key: string # Required: API key for the guardrail service api_base: string # Optional: Base URL for the guardrail service default_on: boolean # Optional: Default False. When set to True, will run on every request, does not need client to specify guardrail in request @@ -569,4 +578,4 @@ guardrails: Union[ class DynamicGuardrailParams: extra_body: Dict[str, Any] # Additional parameters for the guardrail -``` \ No newline at end of file +``` diff --git a/docs/my-website/docs/proxy/image_handling.md b/docs/my-website/docs/proxy/image_handling.md new file mode 100644 index 00000000000..300ab0bc386 --- /dev/null +++ b/docs/my-website/docs/proxy/image_handling.md @@ -0,0 +1,21 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Image URL Handling + + + +Some LLM API's don't support url's for images, but do support base-64 strings. + +For those, LiteLLM will: + +1. Detect a URL being passed +2. Check if the LLM API supports a URL +3. Else, will download the base64 +4. Send the provider a base64 string. + + +LiteLLM also caches this result, in-memory to reduce latency for subsequent calls. + +The limit for an in-memory cache is 1MB. \ No newline at end of file diff --git a/docs/my-website/docs/proxy/litellm_managed_files.md b/docs/my-website/docs/proxy/litellm_managed_files.md new file mode 100644 index 00000000000..de4bd1b9bfc --- /dev/null +++ b/docs/my-website/docs/proxy/litellm_managed_files.md @@ -0,0 +1,287 @@ +import TabItem from '@theme/TabItem'; +import Tabs from '@theme/Tabs'; +import Image from '@theme/IdealImage'; + +# [BETA] LiteLLM Managed Files + +Reuse the same file across different providers. + +:::info + +This is a free LiteLLM Enterprise feature. + +Available via the `litellm[proxy]` package or any `litellm` docker image. + +::: + + +| Feature | Description | Comments | +| --- | --- | --- | +| Proxy | ✅ | | +| SDK | ❌ | Requires postgres DB for storing file ids | +| Available across all providers | ✅ | | + + + +Limitations of LiteLLM Managed Files: +- Only works for `/chat/completions` and `/batch` requests. + +Follow [here](https://github.com/BerriAI/litellm/discussions/9632) for multiple models, batches support. + +### 1. Setup config.yaml + +``` +model_list: + - model_name: "gemini-2.0-flash" + litellm_params: + model: vertex_ai/gemini-2.0-flash + vertex_project: my-project-id + vertex_location: us-central1 + - model_name: "gpt-4o-mini-openai" + litellm_params: + model: gpt-4o-mini + api_key: os.environ/OPENAI_API_KEY +``` + +### 2. Start proxy + +```bash +litellm --config /path/to/config.yaml +``` + +### 3. Test it! + +Specify `target_model_names` to use the same file id across different providers. This is the list of model_names set via config.yaml (or 'public_model_names' on UI). + +```python +target_model_names="gpt-4o-mini-openai, gemini-2.0-flash" # 👈 Specify model_names +``` + +Check `/v1/models` to see the list of available model names for a key. + +#### **Store a PDF file** + +```python +from openai import OpenAI + +client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-1234", max_retries=0) + + +# Download and save the PDF locally +url = ( + "https://storage.googleapis.com/cloud-samples-data/generative-ai/pdf/2403.05530.pdf" +) +response = requests.get(url) +response.raise_for_status() + +# Save the PDF locally +with open("2403.05530.pdf", "wb") as f: + f.write(response.content) + +file = client.files.create( + file=open("2403.05530.pdf", "rb"), + purpose="user_data", # can be any openai 'purpose' value + extra_body={"target_model_names": "gpt-4o-mini-openai, gemini-2.0-flash"}, # 👈 Specify model_names +) + +print(f"file id={file.id}") +``` + +#### **Use the same file id across different providers** + + + + +```python +completion = client.chat.completions.create( + model="gpt-4o-mini-openai", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What is in this recording?"}, + { + "type": "file", + "file": { + "file_id": file.id, + }, + }, + ], + }, + ] +) + +print(completion.choices[0].message) +``` + + + + + +```python +completion = client.chat.completions.create( + model="gemini-2.0-flash", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What is in this recording?"}, + { + "type": "file", + "file": { + "file_id": file.id, + }, + }, + ], + }, + ] +) + +print(completion.choices[0].message) + +``` + + + + +### Complete Example + +```python +import base64 +import requests +from openai import OpenAI + +client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-1234", max_retries=0) + + +# Download and save the PDF locally +url = ( + "https://storage.googleapis.com/cloud-samples-data/generative-ai/pdf/2403.05530.pdf" +) +response = requests.get(url) +response.raise_for_status() + +# Save the PDF locally +with open("2403.05530.pdf", "wb") as f: + f.write(response.content) + +# Read the local PDF file +file = client.files.create( + file=open("2403.05530.pdf", "rb"), + purpose="user_data", # can be any openai 'purpose' value + extra_body={"target_model_names": "gpt-4o-mini-openai, vertex_ai/gemini-2.0-flash"}, +) + +print(f"file.id: {file.id}") # 👈 Unified file id + +## GEMINI CALL ### +completion = client.chat.completions.create( + model="gemini-2.0-flash", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What is in this recording?"}, + { + "type": "file", + "file": { + "file_id": file.id, + }, + }, + ], + }, + ] +) + +print(completion.choices[0].message) + + +### OPENAI CALL ### +completion = client.chat.completions.create( + model="gpt-4o-mini-openai", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What is in this recording?"}, + { + "type": "file", + "file": { + "file_id": file.id, + }, + }, + ], + }, + ], +) + +print(completion.choices[0].message) + +``` + + +### Supported Endpoints + +#### Create a file - `/files` + +```python +from openai import OpenAI + +client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-1234", max_retries=0) + +# Download and save the PDF locally +url = ( + "https://storage.googleapis.com/cloud-samples-data/generative-ai/pdf/2403.05530.pdf" +) +response = requests.get(url) +response.raise_for_status() + +# Save the PDF locally +with open("2403.05530.pdf", "wb") as f: + f.write(response.content) + +# Read the local PDF file +file = client.files.create( + file=open("2403.05530.pdf", "rb"), + purpose="user_data", # can be any openai 'purpose' value + extra_body={"target_model_names": "gpt-4o-mini-openai, vertex_ai/gemini-2.0-flash"}, +) +``` + +#### Retrieve a file - `/files/{file_id}` + +```python +client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-1234", max_retries=0) + +file = client.files.retrieve(file_id=file.id) +``` + +#### Delete a file - `/files/{file_id}/delete` + +```python +client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-1234", max_retries=0) + +file = client.files.delete(file_id=file.id) +``` + +### FAQ + +**1. Does LiteLLM store the file?** + +No, LiteLLM does not store the file. It only stores the file id's in the postgres DB. + +**2. How does LiteLLM know which file to use for a given file id?** + +LiteLLM stores a mapping of the litellm file id to the model-specific file id in the postgres DB. When a request comes in, LiteLLM looks up the model-specific file id and uses it in the request to the provider. + +**3. How do file deletions work?** + +When a file is deleted, LiteLLM deletes the mapping from the postgres DB, and the files on each provider. + +### Architecture + + + + + + \ No newline at end of file diff --git a/docs/my-website/docs/proxy/logging.md b/docs/my-website/docs/proxy/logging.md index 1a541820ae2..e6285ec31ee 100644 --- a/docs/my-website/docs/proxy/logging.md +++ b/docs/my-website/docs/proxy/logging.md @@ -1,3 +1,7 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # Logging Log Proxy input, output, and exceptions using: @@ -7,15 +11,13 @@ Log Proxy input, output, and exceptions using: - GCS, s3, Azure (Blob) Buckets - Lunary - MLflow -- Custom Callbacks +- Custom Callbacks - Custom code and API endpoints - Langsmith - DataDog - DynamoDB - etc. -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; + ## Getting the LiteLLM Call ID @@ -77,10 +79,13 @@ litellm_settings: ### Redact Messages, Response Content -Set `litellm.turn_off_message_logging=True` This will prevent the messages and responses from being logged to your logging provider, but request metadata will still be logged. +Set `litellm.turn_off_message_logging=True` This will prevent the messages and responses from being logged to your logging provider, but request metadata - e.g. spend, will still be tracked. + -Example config.yaml + + +**1. Setup config.yaml ** ```yaml model_list: - model_name: gpt-3.5-turbo @@ -91,9 +96,87 @@ litellm_settings: turn_off_message_logging: True # 👈 Key Change ``` -If you have this feature turned on, you can override it for specific requests by +**2. Send request** +```shell +curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ] +}' +``` + + + + + + +:::info + +Dynamic request message redaction is in BETA. + +::: + +Pass in a request header to enable message redaction for a request. + +``` +x-litellm-enable-message-redaction: true +``` + +Example config.yaml + +**1. Setup config.yaml ** + +```yaml +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: gpt-3.5-turbo +``` + +**2. Setup per request header** + +```shell +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-zV5HlSIm8ihj1F9C_ZbB1g' \ +-H 'x-litellm-enable-message-redaction: true' \ +-d '{ + "model": "gpt-3.5-turbo-testing", + "messages": [ + { + "role": "user", + "content": "Hey, how'\''s it going 1234?" + } + ] +}' +``` + + + + +**3. Check Logging Tool + Spend Logs** + +**Logging Tool** + + + +**Spend Logs** + + + + +### Disable Message Redaction + +If you have `litellm.turn_on_message_logging` turned on, you can override it for specific requests by setting a request header `LiteLLM-Disable-Message-Redaction: true`. + ```shell curl --location 'http://0.0.0.0:4000/chat/completions' \ --header 'Content-Type: application/json' \ @@ -109,8 +192,6 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \ }' ``` -Removes any field with `user_api_key_*` from metadata. - ### Turn off all tracking/logging @@ -196,7 +277,7 @@ Found under `kwargs["standard_logging_object"]`. This is a standard payload, log ## Langfuse -We will use the `--config` to set `litellm.success_callback = ["langfuse"]` this will log all successfull LLM calls to langfuse. Make sure to set `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` in your environment +We will use the `--config` to set `litellm.success_callback = ["langfuse"]` this will log all successful LLM calls to langfuse. Make sure to set `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` in your environment **Step 1** Install langfuse @@ -453,15 +534,15 @@ print(response) Use this if you want to control which LiteLLM-specific fields are logged as tags by the LiteLLM proxy. By default LiteLLM Proxy logs no LiteLLM-specific fields -| LiteLLM specific field | Description | Example Value | -|------------------------|-------------------------------------------------------|------------------------------------------------| -| `cache_hit` | Indicates whether a cache hit occured (True) or not (False) | `true`, `false` | -| `cache_key` | The Cache key used for this request | `d2b758c****`| -| `proxy_base_url` | The base URL for the proxy server, the value of env var `PROXY_BASE_URL` on your server | `https://proxy.example.com`| -| `user_api_key_alias` | An alias for the LiteLLM Virtual Key.| `prod-app1` | -| `user_api_key_user_id` | The unique ID associated with a user's API key. | `user_123`, `user_456` | -| `user_api_key_user_email` | The email associated with a user's API key. | `user@example.com`, `admin@example.com` | -| `user_api_key_team_alias` | An alias for a team associated with an API key. | `team_alpha`, `dev_team` | +| LiteLLM specific field | Description | Example Value | +|---------------------------|-----------------------------------------------------------------------------------------|------------------------------------------------| +| `cache_hit` | Indicates whether a cache hit occurred (True) or not (False) | `true`, `false` | +| `cache_key` | The Cache key used for this request | `d2b758c****` | +| `proxy_base_url` | The base URL for the proxy server, the value of env var `PROXY_BASE_URL` on your server | `https://proxy.example.com` | +| `user_api_key_alias` | An alias for the LiteLLM Virtual Key. | `prod-app1` | +| `user_api_key_user_id` | The unique ID associated with a user's API key. | `user_123`, `user_456` | +| `user_api_key_user_email` | The email associated with a user's API key. | `user@example.com`, `admin@example.com` | +| `user_api_key_team_alias` | An alias for a team associated with an API key. | `team_alpha`, `dev_team` | **Usage** @@ -781,7 +862,7 @@ Add the following to your env ```shell OTEL_EXPORTER="otlp_http" -OTEL_ENDPOINT="http:/0.0.0.0:4317" +OTEL_ENDPOINT="http://0.0.0.0:4317" OTEL_HEADERS="x-honeycomb-team=" # Optional ``` @@ -1109,7 +1190,7 @@ We will use the `--config` to set - `litellm.success_callback = ["s3"]` -This will log all successfull LLM calls to s3 Bucket +This will log all successful LLM calls to s3 Bucket **Step 1** Set AWS Credentials in .env @@ -1198,7 +1279,7 @@ Log LLM Logs to [Azure Data Lake Storage](https://learn.microsoft.com/en-us/azur | Property | Details | |----------|---------| -| Description | Log LLM Input/Output to Azure Blob Storag (Bucket) | +| Description | Log LLM Input/Output to Azure Blob Storage (Bucket) | | Azure Docs on Data Lake Storage | [Azure Data Lake Storage](https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction) | @@ -1279,7 +1360,7 @@ LiteLLM Supports logging to the following Datdog Integrations: -We will use the `--config` to set `litellm.callbacks = ["datadog"]` this will log all successfull LLM calls to DataDog +We will use the `--config` to set `litellm.callbacks = ["datadog"]` this will log all successful LLM calls to DataDog **Step 1**: Create a `config.yaml` file and set `litellm_settings`: `success_callback` @@ -1555,7 +1636,7 @@ class MyCustomHandler(CustomLogger): litellm_params = kwargs.get("litellm_params", {}) metadata = litellm_params.get("metadata", {}) # headers passed to LiteLLM proxy, can be found here - # Acess Exceptions & Traceback + # Access Exceptions & Traceback exception_event = kwargs.get("exception", None) traceback_event = kwargs.get("traceback_exception", None) @@ -1769,103 +1850,88 @@ ModelResponse( ## Custom Callback APIs [Async] + +

+ Send LiteLLM logs to a custom API endpoint +

+ :::info This is an Enterprise only feature [Get Started with Enterprise here](https://github.com/BerriAI/litellm/tree/main/enterprise) ::: +| Property | Details | +|----------|---------| +| Description | Log LLM Input/Output to a custom API endpoint | +| Logged Payload | `List[StandardLoggingPayload]` LiteLLM logs a list of [`StandardLoggingPayload` objects](https://docs.litellm.ai/docs/proxy/logging_spec) to your endpoint | + + + Use this if you: - Want to use custom callbacks written in a non Python programming language - Want your callbacks to run on a different microservice -#### Step 1. Create your generic logging API endpoint +#### Usage -Set up a generic API endpoint that can receive data in JSON format. The data will be included within a "data" field. +1. Set `success_callback: ["generic_api"]` on litellm config.yaml -Your server should support the following Request format: - -```shell -curl --location https://your-domain.com/log-event \ - --request POST \ - --header "Content-Type: application/json" \ - --data '{ - "data": { - "id": "chatcmpl-8sgE89cEQ4q9biRtxMvDfQU1O82PT", - "call_type": "acompletion", - "cache_hit": "None", - "startTime": "2024-02-15 16:18:44.336280", - "endTime": "2024-02-15 16:18:45.045539", - "model": "gpt-3.5-turbo", - "user": "ishaan-2", - "modelParameters": "{'temperature': 0.7, 'max_tokens': 10, 'user': 'ishaan-2', 'extra_body': {}}", - "messages": "[{'role': 'user', 'content': 'This is a test'}]", - "response": "ModelResponse(id='chatcmpl-8sgE89cEQ4q9biRtxMvDfQU1O82PT', choices=[Choices(finish_reason='length', index=0, message=Message(content='Great! How can I assist you with this test', role='assistant'))], created=1708042724, model='gpt-3.5-turbo-0613', object='chat.completion', system_fingerprint=None, usage=Usage(completion_tokens=10, prompt_tokens=11, total_tokens=21))", - "usage": "Usage(completion_tokens=10, prompt_tokens=11, total_tokens=21)", - "metadata": "{}", - "cost": "3.65e-05" - } - }' -``` - -Reference FastAPI Python Server - -Here's a reference FastAPI Server that is compatible with LiteLLM Proxy: - -```python -# this is an example endpoint to receive data from litellm -from fastapi import FastAPI, HTTPException, Request - -app = FastAPI() - - -@app.post("/log-event") -async def log_event(request: Request): - try: - print("Received /log-event request") - # Assuming the incoming request has JSON data - data = await request.json() - print("Received request data:") - print(data) - - # Your additional logic can go here - # For now, just printing the received data - - return {"message": "Request received successfully"} - except Exception as e: - print(f"Error processing request: {str(e)}") - import traceback - - traceback.print_exc() - raise HTTPException(status_code=500, detail="Internal Server Error") - - -if __name__ == "__main__": - import uvicorn - uvicorn.run(app, host="127.0.0.1", port=4000) -``` - -#### Step 2. Set your `GENERIC_LOGGER_ENDPOINT` to the endpoint + route we should send callback logs to - -```shell -os.environ["GENERIC_LOGGER_ENDPOINT"] = "http://localhost:4000/log-event" -``` - -#### Step 3. Create a `config.yaml` file and set `litellm_settings`: `success_callback` = ["generic"] - -Example litellm proxy config.yaml - -```yaml +```yaml showLineNumbers title="litellm config.yaml" model_list: - - model_name: gpt-3.5-turbo + - model_name: openai/gpt-4o litellm_params: - model: gpt-3.5-turbo + model: openai/gpt-4o + api_key: os.environ/OPENAI_API_KEY + litellm_settings: - success_callback: ["generic"] + success_callback: ["generic_api"] ``` -Start the LiteLLM Proxy and make a test request to verify the logs reached your callback API +2. Set Environment Variables for the custom API endpoint + +| Environment Variable | Details | Required | +|----------|---------|----------| +| `GENERIC_LOGGER_ENDPOINT` | The endpoint + route we should send callback logs to | Yes | +| `GENERIC_LOGGER_HEADERS` | Optional: Set headers to be sent to the custom API endpoint | No, this is optional | + +```shell showLineNumbers title=".env" +GENERIC_LOGGER_ENDPOINT="https://webhook-test.com/30343bc33591bc5e6dc44217ceae3e0a" + + +# Optional: Set headers to be sent to the custom API endpoint +GENERIC_LOGGER_HEADERS="Authorization=Bearer " +# if multiple headers, separate by commas +GENERIC_LOGGER_HEADERS="Authorization=Bearer ,X-Custom-Header=custom-header-value" +``` + +3. Start the proxy + +```shell +litellm --config /path/to/config.yaml +``` + +4. Make a test request + +```shell +curl -i --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer sk-1234' \ + --data '{ + "model": "openai/gpt-4o", + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ] +}' +``` + + ## Langsmith @@ -2124,7 +2190,7 @@ We will use the `--config` to set - `litellm.success_callback = ["dynamodb"]` - `litellm.dynamodb_table_name = "your-table-name"` -This will log all successfull LLM calls to DynamoDB +This will log all successful LLM calls to DynamoDB **Step 1** Set AWS Credentials in .env @@ -2289,7 +2355,7 @@ litellm --test [Athina](https://athina.ai/) allows you to log LLM Input/Output for monitoring, analytics, and observability. -We will use the `--config` to set `litellm.success_callback = ["athina"]` this will log all successfull LLM calls to athina +We will use the `--config` to set `litellm.success_callback = ["athina"]` this will log all successful LLM calls to athina **Step 1** Set Athina API key @@ -2420,4 +2486,4 @@ litellm_settings: :::info `thresholds` are not required by default, but you can tune the values to your needs. Default values is `4` for all categories -::: --> \ No newline at end of file +::: --> diff --git a/docs/my-website/docs/proxy/logging_spec.md b/docs/my-website/docs/proxy/logging_spec.md index 86ba907373d..a39a62318e7 100644 --- a/docs/my-website/docs/proxy/logging_spec.md +++ b/docs/my-website/docs/proxy/logging_spec.md @@ -59,6 +59,22 @@ Inherits from `StandardLoggingUserAPIKeyMetadata` and adds: | `spend_logs_metadata` | `Optional[dict]` | Key-value pairs for spend logging | | `requester_ip_address` | `Optional[str]` | Requester's IP address | | `requester_metadata` | `Optional[dict]` | Additional requester metadata | +| `vector_store_request_metadata` | `Optional[List[StandardLoggingVectorStoreRequest]]` | Vector store request metadata | +| `requester_custom_headers` | Dict[str, str] | Any custom (`x-`) headers sent by the client to the proxy. | +| `guardrail_information` | `Optional[StandardLoggingGuardrailInformation]` | Guardrail information | + + +## StandardLoggingVectorStoreRequest + +| Field | Type | Description | +|-------|------|-------------| +| vector_store_id | Optional[str] | ID of the vector store | +| custom_llm_provider | Optional[str] | Custom LLM provider the vector store is associated with (e.g., bedrock, openai, anthropic) | +| query | Optional[str] | Query to the vector store | +| vector_store_search_response | Optional[VectorStoreSearchResponse] | OpenAI format vector store search response | +| start_time | Optional[float] | Start time of the vector store request | +| end_time | Optional[float] | End time of the vector store request | + ## StandardLoggingAdditionalHeaders @@ -78,6 +94,8 @@ Inherits from `StandardLoggingUserAPIKeyMetadata` and adds: | `api_base` | `Optional[str]` | Optional API base URL | | `response_cost` | `Optional[str]` | Optional response cost | | `additional_headers` | `Optional[StandardLoggingAdditionalHeaders]` | Additional headers | +| `batch_models` | `Optional[List[str]]` | Only set for Batches API. Lists the models used for cost calculation | +| `litellm_model_name` | `Optional[str]` | Model name sent in request | ## StandardLoggingModelInformation @@ -111,4 +129,20 @@ Inherits from `StandardLoggingUserAPIKeyMetadata` and adds: A literal type with two possible values: - `"success"` -- `"failure"` \ No newline at end of file +- `"failure"` + +## StandardLoggingGuardrailInformation + +| Field | Type | Description | +|-------|------|-------------| +| `guardrail_name` | `Optional[str]` | Guardrail name | +| `guardrail_mode` | `Optional[Union[GuardrailEventHooks, List[GuardrailEventHooks]]]` | Guardrail mode | +| `guardrail_request` | `Optional[dict]` | Guardrail request | +| `guardrail_response` | `Optional[Union[dict, str, List[dict]]]` | Guardrail response | +| `guardrail_status` | `Literal["success", "failure"]` | Guardrail status | +| `start_time` | `Optional[float]` | Start time of the guardrail | +| `end_time` | `Optional[float]` | End time of the guardrail | +| `duration` | `Optional[float]` | Duration of the guardrail in seconds | +| `masked_entity_count` | `Optional[Dict[str, int]]` | Count of masked entities | + + diff --git a/docs/my-website/docs/proxy/managed_batches.md b/docs/my-website/docs/proxy/managed_batches.md new file mode 100644 index 00000000000..1b9b71c1779 --- /dev/null +++ b/docs/my-website/docs/proxy/managed_batches.md @@ -0,0 +1,263 @@ +# [BETA] LiteLLM Managed Files with Batches + +:::info + +This is a free LiteLLM Enterprise feature. + +Available via the `litellm[proxy]` package or any `litellm` docker image. + +::: + + +| Feature | Description | Comments | +| --- | --- | --- | +| Proxy | ✅ | | +| SDK | ❌ | Requires postgres DB for storing file ids | +| Available across all [Batch providers](../batches#supported-providers) | ✅ | | + + +## Overview + +Use this to: + +- Loadbalance across multiple Azure Batch deployments +- Control batch model access by key/user/team (same as chat completion models) + + +## (Proxy Admin) Usage + +Here's how to give developers access to your Batch models. + +### 1. Setup config.yaml + +- specify `mode: batch` for each model: Allows developers to know this is a batch model. + +```yaml showLineNumbers title="litellm_config.yaml" +model_list: + - model_name: "gpt-4o-batch" + litellm_params: + model: azure/gpt-4o-mini-general-deployment + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY + model_info: + mode: batch # 👈 SPECIFY MODE AS BATCH, to tell user this is a batch model + - model_name: "gpt-4o-batch" + litellm_params: + model: azure/gpt-4o-mini-special-deployment + api_base: os.environ/AZURE_API_BASE_2 + api_key: os.environ/AZURE_API_KEY_2 + model_info: + mode: batch # 👈 SPECIFY MODE AS BATCH, to tell user this is a batch model + +``` + +### 2. Create Virtual Key + +```bash showLineNumbers title="create_virtual_key.sh" +curl -L -X POST 'https://{PROXY_BASE_URL}/key/generate' \ +-H 'Authorization: Bearer ${PROXY_API_KEY}' \ +-H 'Content-Type: application/json' \ +-d '{"models": ["gpt-4o-batch"]}' +``` + + +You can now use the virtual key to access the batch models (See Developer flow). + +## (Developer) Usage + +Here's how to create a LiteLLM managed file and execute Batch CRUD operations with the file. + +### 1. Create request.jsonl + +- Check models available via `/model_group/info` +- See all models with `mode: batch` +- Set `model` in .jsonl to the model from `/model_group/info` + +```json showLineNumbers title="request.jsonl" +{"custom_id": "request-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-batch", "messages": [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "Hello world!"}],"max_tokens": 1000}} +{"custom_id": "request-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-batch", "messages": [{"role": "system", "content": "You are an unhelpful assistant."},{"role": "user", "content": "Hello world!"}],"max_tokens": 1000}} +``` + +Expectation: + +- LiteLLM translates this to the azure deployment specific value (e.g. `gpt-4o-mini-general-deployment`) + +### 2. Upload File + +Specify `target_model_names: ""` to enable LiteLLM managed files and request validation. + +model-name should be the same as the model-name in the request.jsonl + +```python showLineNumbers title="create_batch.py" +from openai import OpenAI + +client = OpenAI( + base_url="http://0.0.0.0:4000", + api_key="sk-1234", +) + +# Upload file +batch_input_file = client.files.create( + file=open("./request.jsonl", "rb"), # {"model": "gpt-4o-batch"} <-> {"model": "gpt-4o-mini-special-deployment"} + purpose="batch", + extra_body={"target_model_names": "gpt-4o-batch"} +) +print(batch_input_file) +``` + + +**Where is the file written?**: + +All gpt-4o-batch deployments (gpt-4o-mini-general-deployment, gpt-4o-mini-special-deployment) will be written to. This enables loadbalancing across all gpt-4o-batch deployments in Step 3. + +### 3. Create + Retrieve the batch + +```python showLineNumbers title="create_batch.py" +... +# Create batch +batch = client.batches.create( + input_file_id=batch_input_file.id, + endpoint="/v1/chat/completions", + completion_window="24h", + metadata={"description": "Test batch job"}, +) +print(batch) + +# Retrieve batch + +batch_response = client.batches.retrieve( + batch_id +) +status = batch_response.status +``` + +### 4. Retrieve Batch Content + +```python showLineNumbers title="create_batch.py" +... + +file_id = batch_response.output_file_id + +file_response = client.files.content(file_id) +print(file_response.text) +``` + +### 5. List batches + +```python showLineNumbers title="create_batch.py" +... + +client.batches.list(limit=10, extra_body={"target_model_names": "gpt-4o-batch"}) +``` + +### [Coming Soon] Cancel a batch + +```python showLineNumbers title="create_batch.py" +... + +client.batches.cancel(batch_id) +``` + + + +## E2E Example + +```python showLineNumbers title="create_batch.py" +import json +from pathlib import Path +from openai import OpenAI + +""" +litellm yaml: + +model_list: + - model_name: gpt-4o-batch + litellm_params: + model: azure/gpt-4o-my-special-deployment + api_key: .. + api_base: .. + +--- +request.jsonl: +{ + { + ..., + "body":{"model": "gpt-4o-batch", ...}} + } +} +""" + +client = OpenAI( + base_url="http://0.0.0.0:4000", + api_key="sk-1234", +) + +# Upload file +batch_input_file = client.files.create( + file=open("./request.jsonl", "rb"), + purpose="batch", + extra_body={"target_model_names": "gpt-4o-batch"} +) +print(batch_input_file) + + +# Create batch +batch = client.batches.create( # UPDATE BATCH ID TO FILE ID + input_file_id=batch_input_file.id, + endpoint="/v1/chat/completions", + completion_window="24h", + metadata={"description": "Test batch job"}, +) +print(batch) +batch_id = batch.id + +# Retrieve batch + +batch_response = client.batches.retrieve( # LOG VIRTUAL MODEL NAME + batch_id +) +status = batch_response.status + +print(f"status: {status}, output_file_id: {batch_response.output_file_id}") + +# Download file +output_file_id = batch_response.output_file_id +print(f"output_file_id: {output_file_id}") +if not output_file_id: + output_file_id = batch_response.error_file_id + +if output_file_id: + file_response = client.files.content( + output_file_id + ) + raw_responses = file_response.text.strip().split("\n") + + with open( + Path.cwd().parent / "unified_batch_output.json", "w" + ) as output_file: + for raw_response in raw_responses: + json.dump(json.loads(raw_response), output_file) + output_file.write("\n") +## List Batch + +list_batch_response = client.batches.list( # LOG VIRTUAL MODEL NAME + extra_query={"target_model_names": "gpt-4o-batch"} +) + +## Cancel Batch + +batch_response = client.batches.cancel( # LOG VIRTUAL MODEL NAME + batch_id +) +status = batch_response.status + +print(f"status: {status}") +``` + +## FAQ + +### Where are my files written? + +When a `target_model_names` is specified, the file is written to all deployments that match the `target_model_names`. + +No additional infrastructure is required. \ No newline at end of file diff --git a/docs/my-website/docs/proxy/management_cli.md b/docs/my-website/docs/proxy/management_cli.md new file mode 100644 index 00000000000..962831f6a35 --- /dev/null +++ b/docs/my-website/docs/proxy/management_cli.md @@ -0,0 +1,275 @@ +# LiteLLM Proxy CLI + +The `litellm-proxy` CLI is a command-line tool for managing your LiteLLM proxy +server. It provides commands for managing models, credentials, API keys, users, +and more, as well as making chat and HTTP requests to the proxy server. + +| Feature | What you can do | +|------------------------|-------------------------------------------------| +| Models Management | List, add, update, and delete models | +| Credentials Management | Manage provider credentials | +| Keys Management | Generate, list, and delete API keys | +| User Management | Create, list, and delete users | +| Chat Completions | Run chat completions | +| HTTP Requests | Make custom HTTP requests to the proxy server | + +## Quick Start + +1. **Install the CLI** + + If you have [uv](https://github.com/astral-sh/uv) installed, you can try this: + + ```shell + uvx --from=litellm[proxy] litellm-proxy + ``` + + and if things are working, you should see something like this: + + ```shell + Usage: litellm-proxy [OPTIONS] COMMAND [ARGS]... + + LiteLLM Proxy CLI - Manage your LiteLLM proxy server + + Options: + --base-url TEXT Base URL of the LiteLLM proxy server [env var: + LITELLM_PROXY_URL] + --api-key TEXT API key for authentication [env var: + LITELLM_PROXY_API_KEY] + --help Show this message and exit. + + Commands: + chat Chat with models through the LiteLLM proxy server + credentials Manage credentials for the LiteLLM proxy server + http Make HTTP requests to the LiteLLM proxy server + keys Manage API keys for the LiteLLM proxy server + models Manage models on your LiteLLM proxy server + ``` + + If this works, you can make use of the tool more convenient by doing: + + ```shell + uv tool install litellm[proxy] + ``` + + If that works, you'll see something like this: + + ```shell + ... + Installed 2 executables: litellm, litellm-proxy + ``` + + and now you can use the tool by just typing `litellm-proxy` in your terminal: + + ```shell + litellm-proxy + ``` + + In the future if you want to upgrade, you can do so with: + + ```shell + uv tool upgrade litellm[proxy] + ``` + + or if you want to uninstall, you can do so with: + + ```shell + uv tool uninstall litellm + ``` + + If you don't have uv or otherwise want to use pip, you can activate a virtual + environment and install the package manually: + + ```bash + pip install 'litellm[proxy]' + ``` + +2. **Set up environment variables** + + ```bash + export LITELLM_PROXY_URL=http://localhost:4000 + export LITELLM_PROXY_API_KEY=sk-your-key + ``` + + *(Replace with your actual proxy URL and API key)* + +3. **Make your first request (list models)** + + ```bash + litellm-proxy models list + ``` + + If the CLI is set up correctly, you should see a list of available models or a table output. + +4. **Troubleshooting** + + - If you see an error, check your environment variables and proxy server status. + +## Configuration + +You can configure the CLI using environment variables or command-line options: + +- `LITELLM_PROXY_URL`: Base URL of the LiteLLM proxy server (default: http://localhost:4000) +- `LITELLM_PROXY_API_KEY`: API key for authentication + +## Main Commands + +### Models Management + +- List, add, update, get, and delete models on the proxy. +- Example: + + ```bash + litellm-proxy models list + litellm-proxy models add gpt-4 \ + --param api_key=sk-123 \ + --param max_tokens=2048 + litellm-proxy models update -p temperature=0.7 + litellm-proxy models delete + ``` + + [API used (OpenAPI)](https://litellm-api.up.railway.app/#/model%20management) + +### Credentials Management + +- List, create, get, and delete credentials for LLM providers. +- Example: + + ```bash + litellm-proxy credentials list + litellm-proxy credentials create azure-prod \ + --info='{"custom_llm_provider": "azure"}' \ + --values='{"api_key": "sk-123", "api_base": "https://prod.azure.openai.com"}' + litellm-proxy credentials get azure-cred + litellm-proxy credentials delete azure-cred + ``` + + [API used (OpenAPI)](https://litellm-api.up.railway.app/#/credential%20management) + +### Keys Management + +- List, generate, get info, and delete API keys. +- Example: + + ```bash + litellm-proxy keys list + litellm-proxy keys generate \ + --models=gpt-4 \ + --spend=100 \ + --duration=24h \ + --key-alias=my-key + litellm-proxy keys info --key sk-key1 + litellm-proxy keys delete --keys sk-key1,sk-key2 --key-aliases alias1,alias2 + ``` + + [API used (OpenAPI)](https://litellm-api.up.railway.app/#/key%20management) + +### User Management + +- List, create, get info, and delete users. +- Example: + + ```bash + litellm-proxy users list + litellm-proxy users create \ + --email=user@example.com \ + --role=internal_user \ + --alias="Alice" \ + --team=team1 \ + --max-budget=100.0 + litellm-proxy users get --id + litellm-proxy users delete + ``` + + [API used (OpenAPI)](https://litellm-api.up.railway.app/#/Internal%20User%20management) + +### Chat Completions + +- Ask for chat completions from the proxy server. +- Example: + + ```bash + litellm-proxy chat completions gpt-4 -m "user:Hello, how are you?" + ``` + + [API used (OpenAPI)](https://litellm-api.up.railway.app/#/chat%2Fcompletions) + +### General HTTP Requests + +- Make direct HTTP requests to the proxy server. +- Example: + + ```bash + litellm-proxy http request \ + POST /chat/completions \ + --json '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}' + ``` + + [All APIs (OpenAPI)](https://litellm-api.up.railway.app/#/) + +## Environment Variables + +- `LITELLM_PROXY_URL`: Base URL of the proxy server +- `LITELLM_PROXY_API_KEY`: API key for authentication + +## Examples + +1. **List all models:** + + ```bash + litellm-proxy models list + ``` + +2. **Add a new model:** + + ```bash + litellm-proxy models add gpt-4 \ + --param api_key=sk-123 \ + --param max_tokens=2048 + ``` + +3. **Create a credential:** + + ```bash + litellm-proxy credentials create azure-prod \ + --info='{"custom_llm_provider": "azure"}' \ + --values='{"api_key": "sk-123", "api_base": "https://prod.azure.openai.com"}' + ``` + +4. **Generate an API key:** + + ```bash + litellm-proxy keys generate \ + --models=gpt-4 \ + --spend=100 \ + --duration=24h \ + --key-alias=my-key + ``` + +5. **Chat completion:** + + ```bash + litellm-proxy chat completions gpt-4 \ + -m "user:Write a story" + ``` + +6. **Custom HTTP request:** + + ```bash + litellm-proxy http request \ + POST /chat/completions \ + --json '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}' + ``` + +## Error Handling + +The CLI will display error messages for: + +- Server not accessible +- Authentication failures +- Invalid parameters or JSON +- Nonexistent models/credentials +- Any other operation failures + +Use the `--debug` flag for detailed debugging output. + +For full command reference and advanced usage, see the [CLI README](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/client/cli/README.md). diff --git a/docs/my-website/docs/proxy/master_key_rotations.md b/docs/my-website/docs/proxy/master_key_rotations.md new file mode 100644 index 00000000000..1713679863a --- /dev/null +++ b/docs/my-website/docs/proxy/master_key_rotations.md @@ -0,0 +1,53 @@ +# Rotating Master Key + +Here are our recommended steps for rotating your master key. + + +**1. Backup your DB** +In case of any errors during the encryption/de-encryption process, this will allow you to revert back to current state without issues. + +**2. Call `/key/regenerate` with the new master key** + +```bash +curl -L -X POST 'http://localhost:4000/key/regenerate' \ +-H 'Authorization: Bearer sk-1234' \ +-H 'Content-Type: application/json' \ +-d '{ + "key": "sk-1234", + "new_master_key": "sk-PIp1h0RekR" +}' +``` + +This will re-encrypt any models in your Proxy_ModelTable with the new master key. + +Expect to start seeing decryption errors in logs, as your old master key is no longer able to decrypt the new values. + +```bash + raise Exception("Unable to decrypt value={}".format(v)) +Exception: Unable to decrypt value= +``` + +**3. Update LITELLM_MASTER_KEY** + +In your environment variables update the value of LITELLM_MASTER_KEY to the new_master_key from Step 2. + +This ensures the key used for decryption from db is the new key. + +**4. Test it** + +Make a test request to a model stored on proxy with a litellm key (new master key or virtual key) and see if it works + +```bash + curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gpt-4o-mini", # 👈 REPLACE with 'public model name' for any db-model + "messages": [ + { + "content": "Hey, how's it going", + "role": "user" + } + ], +}' +``` \ No newline at end of file diff --git a/docs/my-website/docs/proxy/model_discovery.md b/docs/my-website/docs/proxy/model_discovery.md new file mode 100644 index 00000000000..5790dfc5200 --- /dev/null +++ b/docs/my-website/docs/proxy/model_discovery.md @@ -0,0 +1,108 @@ +# Model Discovery + +Use this to give users an accurate list of models available behind provider endpoint, when calling `/v1/models` for wildcard models. + +## Supported Models + +- Fireworks AI +- OpenAI +- Gemini +- LiteLLM Proxy +- Topaz +- Anthropic +- XAI +- VLLM +- Vertex AI + +### Usage + +**1. Setup config.yaml** + +```yaml +model_list: + - model_name: xai/* + litellm_params: + model: xai/* + api_key: os.environ/XAI_API_KEY + +litellm_settings: + check_provider_endpoint: true # 👈 Enable checking provider endpoint for wildcard models +``` + +**2. Start proxy** + +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +**3. Call `/v1/models`** + +```bash +curl -X GET "http://localhost:4000/v1/models" -H "Authorization: Bearer $LITELLM_KEY" +``` + +Expected response + +```json +{ + "data": [ + { + "id": "xai/grok-2-1212", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-2-vision-1212", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-3-beta", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-3-fast-beta", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-3-mini-beta", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-3-mini-fast-beta", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-beta", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-vision-beta", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + }, + { + "id": "xai/grok-2-image-1212", + "object": "model", + "created": 1677610602, + "owned_by": "openai" + } + ], + "object": "list" +} +``` \ No newline at end of file diff --git a/docs/my-website/docs/proxy/pii_masking.md b/docs/my-website/docs/proxy/pii_masking.md deleted file mode 100644 index 83e4965a495..00000000000 --- a/docs/my-website/docs/proxy/pii_masking.md +++ /dev/null @@ -1,246 +0,0 @@ -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# PII Masking - LiteLLM Gateway (Deprecated Version) - -:::warning - -This is deprecated, please use [our new Presidio pii masking integration](./guardrails/pii_masking_v2) - -::: - -LiteLLM supports [Microsoft Presidio](https://github.com/microsoft/presidio/) for PII masking. - - -## Quick Start -### Step 1. Add env - -```bash -export PRESIDIO_ANALYZER_API_BASE="http://localhost:5002" -export PRESIDIO_ANONYMIZER_API_BASE="http://localhost:5001" -``` - -### Step 2. Set it as a callback in config.yaml - -```yaml -litellm_settings: - callbacks = ["presidio", ...] # e.g. ["presidio", custom_callbacks.proxy_handler_instance] -``` - -### Step 3. Start proxy - - -``` -litellm --config /path/to/config.yaml -``` - - -This will mask the input going to the llm provider - - - -## Output parsing - -LLM responses can sometimes contain the masked tokens. - -For presidio 'replace' operations, LiteLLM can check the LLM response and replace the masked token with the user-submitted values. - -Just set `litellm.output_parse_pii = True`, to enable this. - - -```yaml -litellm_settings: - output_parse_pii: true -``` - -**Expected Flow: ** - -1. User Input: "hello world, my name is Jane Doe. My number is: 034453334" - -2. LLM Input: "hello world, my name is [PERSON]. My number is: [PHONE_NUMBER]" - -3. LLM Response: "Hey [PERSON], nice to meet you!" - -4. User Response: "Hey Jane Doe, nice to meet you!" - -## Ad-hoc recognizers - -Send ad-hoc recognizers to presidio `/analyze` by passing a json file to the proxy - -[**Example** ad-hoc recognizer](../../../../litellm/proxy/hooks/example_presidio_ad_hoc_recognizer.json) - -```yaml -litellm_settings: - callbacks: ["presidio"] - presidio_ad_hoc_recognizers: "./hooks/example_presidio_ad_hoc_recognizer.json" -``` - -You can see this working, when you run the proxy: - -```bash -litellm --config /path/to/config.yaml --debug -``` - -Make a chat completions request, example: - -``` -{ - "model": "azure-gpt-3.5", - "messages": [{"role": "user", "content": "John Smith AHV number is 756.3026.0705.92. Zip code: 1334023"}] -} -``` - -And search for any log starting with `Presidio PII Masking`, example: -``` -Presidio PII Masking: Redacted pii message: AHV number is . Zip code: -``` - - -## Turn on/off per key - -Turn off PII masking for a given key. - -Do this by setting `permissions: {"pii": false}`, when generating a key. - -```shell -curl --location 'http://0.0.0.0:4000/key/generate' \ ---header 'Authorization: Bearer sk-1234' \ ---header 'Content-Type: application/json' \ ---data '{ - "permissions": {"pii": false} -}' -``` - - -## Turn on/off per request - -The proxy support 2 request-level PII controls: - -- *no-pii*: Optional(bool) - Allow user to turn off pii masking per request. -- *output_parse_pii*: Optional(bool) - Allow user to turn off pii output parsing per request. - -### Usage - -**Step 1. Create key with pii permissions** - -Set `allow_pii_controls` to true for a given key. This will allow the user to set request-level PII controls. - -```bash -curl --location 'http://0.0.0.0:4000/key/generate' \ ---header 'Authorization: Bearer my-master-key' \ ---header 'Content-Type: application/json' \ ---data '{ - "permissions": {"allow_pii_controls": true} -}' -``` - -**Step 2. Turn off pii output parsing** - -```python -import os -from openai import OpenAI - -client = OpenAI( - # This is the default and can be omitted - api_key=os.environ.get("OPENAI_API_KEY"), - base_url="http://0.0.0.0:4000" -) - -chat_completion = client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "My name is Jane Doe, my number is 8382043839", - } - ], - model="gpt-3.5-turbo", - extra_body={ - "content_safety": {"output_parse_pii": False} - } -) -``` - -**Step 3: See response** - -``` -{ - "id": "chatcmpl-8c5qbGTILZa1S4CK3b31yj5N40hFN", - "choices": [ - { - "finish_reason": "stop", - "index": 0, - "message": { - "content": "Hi [PERSON], what can I help you with?", - "role": "assistant" - } - } - ], - "created": 1704089632, - "model": "gpt-35-turbo", - "object": "chat.completion", - "system_fingerprint": null, - "usage": { - "completion_tokens": 47, - "prompt_tokens": 12, - "total_tokens": 59 - }, - "_response_ms": 1753.426 -} -``` - - -## Turn on for logging only - -Only apply PII Masking before logging to Langfuse, etc. - -Not on the actual llm api request / response. - -:::note -This is currently only applied for -- `/chat/completion` requests -- on 'success' logging - -::: - -1. Setup config.yaml -```yaml -litellm_settings: - presidio_logging_only: true - -model_list: - - model_name: gpt-3.5-turbo - litellm_params: - model: gpt-3.5-turbo - api_key: os.environ/OPENAI_API_KEY -``` - -2. Start proxy - -```bash -litellm --config /path/to/config.yaml -``` - -3. Test it! - -```bash -curl -X POST 'http://0.0.0.0:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-1234' \ --D '{ - "model": "gpt-3.5-turbo", - "messages": [ - { - "role": "user", - "content": "Hi, my name is Jane!" - } - ] - }' -``` - - -**Expected Logged Response** - -``` -Hi, my name is ! -``` \ No newline at end of file diff --git a/docs/my-website/docs/proxy/prod.md b/docs/my-website/docs/proxy/prod.md index d0b8c48174a..c696bce8ca6 100644 --- a/docs/my-website/docs/proxy/prod.md +++ b/docs/my-website/docs/proxy/prod.md @@ -61,7 +61,7 @@ CMD ["--port", "4000", "--config", "./proxy_server_config.yaml"] ## 3. Use Redis 'port','host', 'password'. NOT 'redis_url' -If you decide to use Redis, DO NOT use 'redis_url'. We recommend usig redis port, host, and password params. +If you decide to use Redis, DO NOT use 'redis_url'. We recommend using redis port, host, and password params. `redis_url`is 80 RPS slower @@ -94,22 +94,38 @@ This disables the load_dotenv() functionality, which will automatically load you ## 5. If running LiteLLM on VPC, gracefully handle DB unavailability -This will allow LiteLLM to continue to process requests even if the DB is unavailable. This is better handling for DB unavailability. +When running LiteLLM on a VPC (and inaccessible from the public internet), you can enable graceful degradation so that request processing continues even if the database is temporarily unavailable. + **WARNING: Only do this if you're running LiteLLM on VPC, that cannot be accessed from the public internet.** -```yaml +#### Configuration + +```yaml showLineNumbers title="litellm config.yaml" general_settings: allow_requests_on_db_unavailable: True ``` +#### Expected Behavior + +When `allow_requests_on_db_unavailable` is set to `true`, LiteLLM will handle errors as follows: + +| Type of Error | Expected Behavior | Details | +|---------------|-------------------|----------------| +| Prisma Errors | ✅ Request will be allowed | Covers issues like DB connection resets or rejections from the DB via Prisma, the ORM used by LiteLLM. | +| Httpx Errors | ✅ Request will be allowed | Occurs when the database is unreachable, allowing the request to proceed despite the DB outage. | +| Pod Startup Behavior | ✅ Pods start regardless | LiteLLM Pods will start even if the database is down or unreachable, ensuring higher uptime guarantees for deployments. | +| Health/Readiness Check | ✅ Always returns 200 OK | The /health/readiness endpoint returns a 200 OK status to ensure that pods remain operational even when the database is unavailable. +| LiteLLM Budget Errors or Model Errors | ❌ Request will be blocked | Triggered when the DB is reachable but the authentication token is invalid, lacks access, or exceeds budget limits. | + + ## 6. Disable spend_logs & error_logs if not using the LiteLLM UI By default, LiteLLM writes several types of logs to the database: - Every LLM API request to the `LiteLLM_SpendLogs` table -- LLM Exceptions to the `LiteLLM_LogsErrors` table +- LLM Exceptions to the `LiteLLM_SpendLogs` table -If you're not viewing these logs on the LiteLLM UI (most users use Prometheus for monitoring), you can disable them by setting the following flags to `True`: +If you're not viewing these logs on the LiteLLM UI, you can disable them by setting the following flags to `True`: ```yaml general_settings: @@ -153,7 +169,7 @@ If you plan on using the DB, set a salt key for encrypting/decrypting variables Do not change this after adding a model. It is used to encrypt / decrypt your LLM API Key credentials -We recommned - https://1password.com/password-generator/ password generator to get a random hash for litellm salt key. +We recommend - https://1password.com/password-generator/ password generator to get a random hash for litellm salt key. ```bash export LITELLM_SALT_KEY="sk-1234" @@ -161,6 +177,56 @@ export LITELLM_SALT_KEY="sk-1234" [**See Code**](https://github.com/BerriAI/litellm/blob/036a6821d588bd36d170713dcf5a72791a694178/litellm/proxy/common_utils/encrypt_decrypt_utils.py#L15) + +## 9. Use `prisma migrate deploy` + +Use this to handle db migrations across LiteLLM versions in production + + + + +```bash +USE_PRISMA_MIGRATE="True" +``` + + + + + +```bash +litellm --use_prisma_migrate +``` + + + + +Benefits: + +The migrate deploy command: + +- **Does not** issue a warning if an already applied migration is missing from migration history +- **Does not** detect drift (production database schema differs from migration history end state - for example, due to a hotfix) +- **Does not** reset the database or generate artifacts (such as Prisma Client) +- **Does not** rely on a shadow database + + +### How does LiteLLM handle DB migrations in production? + +1. A new migration file is written to our `litellm-proxy-extras` package. [See all](https://github.com/BerriAI/litellm/tree/main/litellm-proxy-extras/litellm_proxy_extras/migrations) + +2. The core litellm pip package is bumped to point to the new `litellm-proxy-extras` package. This ensures, older versions of LiteLLM will continue to use the old migrations. [See code](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/pyproject.toml#L58) + +3. When you upgrade to a new version of LiteLLM, the migration file is applied to the database. [See code](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/litellm-proxy-extras/litellm_proxy_extras/utils.py#L42) + + +### Read-only File System + +If you see a `Permission denied` error, it means the LiteLLM pod is running with a read-only file system. + +To fix this, just set `LITELLM_MIGRATION_DIR="/path/to/writeable/directory"` in your environment. + +LiteLLM will use this directory to write migration files. + ## Extras ### Expected Performance in Production @@ -182,94 +248,4 @@ You should only see the following level of details in logs on the proxy server # INFO: 192.168.2.205:11774 - "POST /chat/completions HTTP/1.1" 200 OK # INFO: 192.168.2.205:34717 - "POST /chat/completions HTTP/1.1" 200 OK # INFO: 192.168.2.205:29734 - "POST /chat/completions HTTP/1.1" 200 OK -``` - - -### Machine Specifications to Deploy LiteLLM - -| Service | Spec | CPUs | Memory | Architecture | Version| -| --- | --- | --- | --- | --- | --- | -| Server | `t2.small`. | `1vCPUs` | `8GB` | `x86` | -| Redis Cache | - | - | - | - | 7.0+ Redis Engine| - - -### Reference Kubernetes Deployment YAML - -Reference Kubernetes `deployment.yaml` that was load tested by us - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: litellm-deployment -spec: - replicas: 3 - selector: - matchLabels: - app: litellm - template: - metadata: - labels: - app: litellm - spec: - containers: - - name: litellm-container - image: ghcr.io/berriai/litellm:main-latest - imagePullPolicy: Always - env: - - name: AZURE_API_KEY - value: "d6******" - - name: AZURE_API_BASE - value: "https://ope******" - - name: LITELLM_MASTER_KEY - value: "sk-1234" - - name: DATABASE_URL - value: "po**********" - args: - - "--config" - - "/app/proxy_config.yaml" # Update the path to mount the config file - volumeMounts: # Define volume mount for proxy_config.yaml - - name: config-volume - mountPath: /app - readOnly: true - livenessProbe: - httpGet: - path: /health/liveliness - port: 4000 - initialDelaySeconds: 120 - periodSeconds: 15 - successThreshold: 1 - failureThreshold: 3 - timeoutSeconds: 10 - readinessProbe: - httpGet: - path: /health/readiness - port: 4000 - initialDelaySeconds: 120 - periodSeconds: 15 - successThreshold: 1 - failureThreshold: 3 - timeoutSeconds: 10 - volumes: # Define volume to mount proxy_config.yaml - - name: config-volume - configMap: - name: litellm-config - -``` - - -Reference Kubernetes `service.yaml` that was load tested by us -```yaml -apiVersion: v1 -kind: Service -metadata: - name: litellm-service -spec: - selector: - app: litellm - ports: - - protocol: TCP - port: 4000 - targetPort: 4000 - type: LoadBalancer -``` +``` \ No newline at end of file diff --git a/docs/my-website/docs/proxy/prometheus.md b/docs/my-website/docs/proxy/prometheus.md index 8dff527ae53..0ce94ab9627 100644 --- a/docs/my-website/docs/proxy/prometheus.md +++ b/docs/my-website/docs/proxy/prometheus.md @@ -95,7 +95,14 @@ Use this for for tracking per [user, key, team, etc.](virtual_keys) ### Initialize Budget Metrics on Startup -If you want to initialize the key/team budget metrics on startup, you can set the `prometheus_initialize_budget_metrics` to `true` in the `config.yaml` +If you want litellm to emit the budget metrics for all keys, teams irrespective of whether they are getting requests or not, set `prometheus_initialize_budget_metrics` to `true` in the `config.yaml` + +**How this works:** + +- If the `prometheus_initialize_budget_metrics` is set to `true` + - Every 5 minutes litellm runs a cron job to read all keys, teams from the database + - It then emits the budget metrics for each key, team + - This is used to populate the budget metrics on the `/metrics` endpoint ```yaml litellm_settings: @@ -242,6 +249,19 @@ litellm_settings: | `litellm_redis_fails` | Number of failed redis calls | | `litellm_self_latency` | Histogram latency for successful litellm api call | +#### DB Transaction Queue Health Metrics + +Use these metrics to monitor the health of the DB Transaction Queue. Eg. Monitoring the size of the in-memory and redis buffers. + +| Metric Name | Description | Storage Type | +|-----------------------------------------------------|-----------------------------------------------------------------------------|--------------| +| `litellm_pod_lock_manager_size` | Indicates which pod has the lock to write updates to the database. | Redis | +| `litellm_in_memory_daily_spend_update_queue_size` | Number of items in the in-memory daily spend update queue. These are the aggregate spend logs for each user. | In-Memory | +| `litellm_redis_daily_spend_update_queue_size` | Number of items in the Redis daily spend update queue. These are the aggregate spend logs for each user. | Redis | +| `litellm_in_memory_spend_update_queue_size` | In-memory aggregate spend values for keys, users, teams, team members, etc.| In-Memory | +| `litellm_redis_spend_update_queue_size` | Redis aggregate spend values for keys, users, teams, etc. | Redis | + + ## **🔥 LiteLLM Maintained Grafana Dashboards ** @@ -268,6 +288,17 @@ Here is a screenshot of the metrics you can monitor with the LiteLLM Grafana Das +## Add authentication on /metrics endpoint + +**By default /metrics endpoint is unauthenticated.** + +You can opt into running litellm authentication on the /metrics endpoint by setting the following on the config + +```yaml +litellm_settings: + require_auth_for_metrics_endpoint: true +``` + ## FAQ ### What are `_created` vs. `_total` metrics? diff --git a/docs/my-website/docs/proxy/prompt_management.md b/docs/my-website/docs/proxy/prompt_management.md index 980043f4555..8ea17425c82 100644 --- a/docs/my-website/docs/proxy/prompt_management.md +++ b/docs/my-website/docs/proxy/prompt_management.md @@ -2,19 +2,14 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# [BETA] Prompt Management - -:::info - -This feature is currently in beta, and might change unexpectedly. We expect this to be more stable by next month (February 2025). - -::: +# Prompt Management Run experiments or change the specific model (e.g. from gpt-4o to gpt4o-mini finetune) from your prompt management tool (e.g. Langfuse) instead of making changes in the application. -Supported Integrations: -- [Langfuse](https://langfuse.com/docs/prompts/get-started) -- [Humanloop](../observability/humanloop) +| Supported Integrations | Link | +|------------------------|------| +| Langfuse | [Get Started](https://langfuse.com/docs/prompts/get-started) | +| Humanloop | [Get Started](../observability/humanloop) | ## Quick Start diff --git a/docs/my-website/docs/proxy/release_cycle.md b/docs/my-website/docs/proxy/release_cycle.md new file mode 100644 index 00000000000..10dd6d8b3c5 --- /dev/null +++ b/docs/my-website/docs/proxy/release_cycle.md @@ -0,0 +1,25 @@ +# Release Cycle + +Litellm Proxy has the following release cycle: + +- `v1.x.x-nightly`: These are releases which pass ci/cd. +- `v1.x.x.rc`: These are releases which pass ci/cd + [manual review](https://github.com/BerriAI/litellm/discussions/8495#discussioncomment-12180711). +- `v1.x.x:main-stable`: These are releases which pass ci/cd + manual review + 3 days of production testing. + +In production, we recommend using the latest `v1.x.x:main-stable` release. + + +Follow our release notes [here](https://github.com/BerriAI/litellm/releases). + + +## FAQ + +### Is there a release schedule for LiteLLM stable release? + +Stable releases come out every week (typically Sunday) + +### What is considered a 'minor' bump vs. 'patch' bump? + +- 'patch' bumps: extremely minor addition that doesn't affect any existing functionality or add any user-facing features. (e.g. a 'created_at' column in a database table) +- 'minor' bumps: add a new feature or a new database table that is backward compatible. +- 'major' bumps: break backward compatibility. \ No newline at end of file diff --git a/docs/my-website/docs/proxy/reliability.md b/docs/my-website/docs/proxy/reliability.md index 654c2618c2e..32b35e4bd24 100644 --- a/docs/my-website/docs/proxy/reliability.md +++ b/docs/my-website/docs/proxy/reliability.md @@ -117,7 +117,7 @@ response = router.completion( curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ --D '{ +-d '{ "model": "my-bad-model", "messages": [ { @@ -628,7 +628,7 @@ litellm_settings: curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ --D '{ +-d '{ "model": "gpt-4", "messages": [ { @@ -655,7 +655,7 @@ Check if your fallbacks are working as expected. curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ --D '{ +-d '{ "model": "my-bad-model", "messages": [ { @@ -674,7 +674,7 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ --D '{ +-d '{ "model": "my-bad-model", "messages": [ { @@ -693,7 +693,7 @@ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ curl -X POST 'http://0.0.0.0:4000/chat/completions' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer sk-1234' \ --D '{ +-d '{ "model": "my-bad-model", "messages": [ { @@ -1050,4 +1050,4 @@ curl -L -X POST 'http://0.0.0.0:4000/key/generate' \ ```
-
\ No newline at end of file + diff --git a/docs/my-website/docs/proxy/request_headers.md b/docs/my-website/docs/proxy/request_headers.md index d3ccb544359..79bcea2c866 100644 --- a/docs/my-website/docs/proxy/request_headers.md +++ b/docs/my-website/docs/proxy/request_headers.md @@ -6,7 +6,18 @@ Special headers that are supported by LiteLLM. `x-litellm-timeout` Optional[float]: The timeout for the request in seconds. +`x-litellm-enable-message-redaction`: Optional[bool]: Don't log the message content to logging integrations. Just track spend. [Learn More](./logging#redact-messages-response-content) + +`x-litellm-tags`: Optional[str]: A comma separated list (e.g. `tag1,tag2,tag3`) of tags to use for [tag-based routing](./tag_routing) **OR** [spend-tracking](./enterprise.md#tracking-spend-for-custom-tags). + ## Anthropic Headers `anthropic-version` Optional[str]: The version of the Anthropic API to use. -`anthropic-beta` Optional[str]: The beta version of the Anthropic API to use. \ No newline at end of file +`anthropic-beta` Optional[str]: The beta version of the Anthropic API to use. + +## OpenAI Headers + +`openai-organization` Optional[str]: The organization to use for the OpenAI API. (currently needs to be enabled via `general_settings::forward_openai_org_id: true`) + + + diff --git a/docs/my-website/docs/proxy/response_headers.md b/docs/my-website/docs/proxy/response_headers.md index c066df1e029..32f09fab42e 100644 --- a/docs/my-website/docs/proxy/response_headers.md +++ b/docs/my-website/docs/proxy/response_headers.md @@ -1,17 +1,20 @@ -# Rate Limit Headers +# Response Headers -When you make a request to the proxy, the proxy will return the following [OpenAI-compatible headers](https://platform.openai.com/docs/guides/rate-limits/rate-limits-in-headers): +When you make a request to the proxy, the proxy will return the following headers: -- `x-ratelimit-remaining-requests` - Optional[int]: The remaining number of requests that are permitted before exhausting the rate limit. -- `x-ratelimit-remaining-tokens` - Optional[int]: The remaining number of tokens that are permitted before exhausting the rate limit. -- `x-ratelimit-limit-requests` - Optional[int]: The maximum number of requests that are permitted before exhausting the rate limit. -- `x-ratelimit-limit-tokens` - Optional[int]: The maximum number of tokens that are permitted before exhausting the rate limit. -- `x-ratelimit-reset-requests` - Optional[int]: The time at which the rate limit will reset. -- `x-ratelimit-reset-tokens` - Optional[int]: The time at which the rate limit will reset. +## Rate Limit Headers +[OpenAI-compatible headers](https://platform.openai.com/docs/guides/rate-limits/rate-limits-in-headers): -These headers are useful for clients to understand the current rate limit status and adjust their request rate accordingly. +| Header | Type | Description | +|--------|------|-------------| +| `x-ratelimit-remaining-requests` | Optional[int] | The remaining number of requests that are permitted before exhausting the rate limit | +| `x-ratelimit-remaining-tokens` | Optional[int] | The remaining number of tokens that are permitted before exhausting the rate limit | +| `x-ratelimit-limit-requests` | Optional[int] | The maximum number of requests that are permitted before exhausting the rate limit | +| `x-ratelimit-limit-tokens` | Optional[int] | The maximum number of tokens that are permitted before exhausting the rate limit | +| `x-ratelimit-reset-requests` | Optional[int] | The time at which the rate limit will reset | +| `x-ratelimit-reset-tokens` | Optional[int] | The time at which the rate limit will reset | -## How are these headers calculated? +### How Rate Limit Headers work **If key has rate limits set** @@ -19,6 +22,50 @@ The proxy will return the [remaining rate limits for that key](https://github.co **If key does not have rate limits set** -The proxy returns the remaining requests/tokens returned by the backend provider. +The proxy returns the remaining requests/tokens returned by the backend provider. (LiteLLM will standardize the backend provider's response headers to match the OpenAI format) If the backend provider does not return these headers, the value will be `None`. + +These headers are useful for clients to understand the current rate limit status and adjust their request rate accordingly. + + +## Latency Headers +| Header | Type | Description | +|--------|------|-------------| +| `x-litellm-response-duration-ms` | float | Total duration of the API response in milliseconds | +| `x-litellm-overhead-duration-ms` | float | LiteLLM processing overhead in milliseconds | + +## Retry, Fallback Headers +| Header | Type | Description | +|--------|------|-------------| +| `x-litellm-attempted-retries` | int | Number of retry attempts made | +| `x-litellm-attempted-fallbacks` | int | Number of fallback attempts made | +| `x-litellm-max-fallbacks` | int | Maximum number of fallback attempts allowed | + +## Cost Tracking Headers +| Header | Type | Description | Available on Pass-Through Endpoints | +|--------|------|-------------|-------------| +| `x-litellm-response-cost` | float | Cost of the API call | | +| `x-litellm-key-spend` | float | Total spend for the API key | ✅ | + +## LiteLLM Specific Headers +| Header | Type | Description | Available on Pass-Through Endpoints | +|--------|------|-------------|-------------| +| `x-litellm-call-id` | string | Unique identifier for the API call | ✅ | +| `x-litellm-model-id` | string | Unique identifier for the model used | | +| `x-litellm-model-api-base` | string | Base URL of the API endpoint | ✅ | +| `x-litellm-version` | string | Version of LiteLLM being used | | +| `x-litellm-model-group` | string | Model group identifier | | + +## Response headers from LLM providers + +LiteLLM also returns the original response headers from the LLM provider. These headers are prefixed with `llm_provider-` to distinguish them from LiteLLM's headers. + +Example response headers: +``` +llm_provider-openai-processing-ms: 256 +llm_provider-openai-version: 2020-10-01 +llm_provider-x-ratelimit-limit-requests: 30000 +llm_provider-x-ratelimit-limit-tokens: 150000000 +``` + diff --git a/docs/my-website/docs/proxy/self_serve.md b/docs/my-website/docs/proxy/self_serve.md index 604ceee3e5b..a1e7c64cd9b 100644 --- a/docs/my-website/docs/proxy/self_serve.md +++ b/docs/my-website/docs/proxy/self_serve.md @@ -161,6 +161,83 @@ Here's the available UI roles for a LiteLLM Internal User: - `internal_user`: can login, view/create/delete their own keys, view their spend. **Cannot** add new users. - `internal_user_viewer`: can login, view their own keys, view their own spend. **Cannot** create/delete keys, add new users. +## Auto-add SSO users to teams + +This walks through setting up sso auto-add for **Okta, Google SSO** + +### Okta, Google SSO + +1. Specify the JWT field that contains the team ids, that the user belongs to. + +```yaml +general_settings: + master_key: sk-1234 + litellm_jwtauth: + team_ids_jwt_field: "groups" # 👈 CAN BE ANY FIELD +``` + +This is assuming your SSO token looks like this. **If you need to inspect the JWT fields received from your SSO provider by LiteLLM, follow these instructions [here](#debugging-sso-jwt-fields)** + +``` +{ + ..., + "groups": ["team_id_1", "team_id_2"] +} +``` + +2. Create the teams on LiteLLM + +```bash +curl -X POST '/team/new' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +-D '{ + "team_alias": "team_1", + "team_id": "team_id_1" # 👈 MUST BE THE SAME AS THE SSO GROUP ID +}' +``` + +3. Test the SSO flow + +Here's a walkthrough of [how it works](https://www.loom.com/share/8959be458edf41fd85937452c29a33f3?sid=7ebd6d37-569a-4023-866e-e0cde67cb23e) + +### Microsoft Entra ID SSO group assignment + +Follow this [tutorial for auto-adding sso users to teams with Microsoft Entra ID](https://docs.litellm.ai/docs/tutorials/msft_sso) + +### Debugging SSO JWT fields + +If you need to inspect the JWT fields received from your SSO provider by LiteLLM, follow these instructions. This guide walks you through setting up a debug callback to view the JWT data during the SSO process. + + + +
+ +1. Add `/sso/debug/callback` as a redirect URL in your SSO provider + + In your SSO provider's settings, add the following URL as a new redirect (callback) URL: + + ```bash showLineNumbers title="Redirect URL" + http:///sso/debug/callback + ``` + + +2. Navigate to the debug login page on your browser + + Navigate to the following URL on your browser: + + ```bash showLineNumbers title="URL to navigate to" + https:///sso/debug/login + ``` + + This will initiate the standard SSO flow. You will be redirected to your SSO provider's login screen, and after successful authentication, you will be redirected back to LiteLLM's debug callback route. + + +3. View the JWT fields + +Once redirected, you should see a page called "SSO Debug Information". This page displays the JWT fields received from your SSO provider (as shown in the image above) + + ## Advanced ### Setting custom logout URLs @@ -196,40 +273,26 @@ This budget does not apply to keys created under non-default teams. [**Go Here**](./team_budgets.md) -### Auto-add SSO users to teams +### Set default params for new teams -1. Specify the JWT field that contains the team ids, that the user belongs to. +When you connect litellm to your SSO provider, litellm can auto-create teams. Use this to set the default `models`, `max_budget`, `budget_duration` for these auto-created teams. -```yaml -general_settings: - master_key: sk-1234 - litellm_jwtauth: - team_ids_jwt_field: "groups" # 👈 CAN BE ANY FIELD +**How it works** + +1. When litellm fetches `groups` from your SSO provider, it will check if the corresponding group_id exists as a `team_id` in litellm. +2. If the team_id does not exist, litellm will auto-create a team with the default params you've set. +3. If the team_id already exist, litellm will not apply any settings on the team. + +**Usage** + +```yaml showLineNumbers title="Default Params for new teams" +litellm_settings: + default_team_params: # Default Params to apply when litellm auto creates a team from SSO IDP provider + max_budget: 100 # Optional[float], optional): $100 budget for the team + budget_duration: 30d # Optional[str], optional): 30 days budget_duration for the team + models: ["gpt-3.5-turbo"] # Optional[List[str]], optional): models to be used by the team ``` -This is assuming your SSO token looks like this: -``` -{ - ..., - "groups": ["team_id_1", "team_id_2"] -} -``` - -2. Create the teams on LiteLLM - -```bash -curl -X POST '/team/new' \ --H 'Authorization: Bearer ' \ --H 'Content-Type: application/json' \ --D '{ - "team_alias": "team_1", - "team_id": "team_id_1" # 👈 MUST BE THE SAME AS THE SSO GROUP ID -}' -``` - -3. Test the SSO flow - -Here's a walkthrough of [how it works](https://www.loom.com/share/8959be458edf41fd85937452c29a33f3?sid=7ebd6d37-569a-4023-866e-e0cde67cb23e) ### Restrict Users from creating personal keys @@ -241,7 +304,7 @@ This will also prevent users from using their session tokens on the test keys ch ## **All Settings for Self Serve / SSO Flow** -```yaml +```yaml showLineNumbers title="All Settings for Self Serve / SSO Flow" litellm_settings: max_internal_user_budget: 10 # max budget for internal users internal_user_budget_duration: "1mo" # reset every month @@ -251,6 +314,11 @@ litellm_settings: max_budget: 100 # Optional[float], optional): $100 budget for a new SSO sign in user budget_duration: 30d # Optional[str], optional): 30 days budget_duration for a new SSO sign in user models: ["gpt-3.5-turbo"] # Optional[List[str]], optional): models to be used by a new SSO sign in user + + default_team_params: # Default Params to apply when litellm auto creates a team from SSO IDP provider + max_budget: 100 # Optional[float], optional): $100 budget for the team + budget_duration: 30d # Optional[str], optional): 30 days budget_duration for the team + models: ["gpt-3.5-turbo"] # Optional[List[str]], optional): models to be used by the team upperbound_key_generate_params: # Upperbound for /key/generate requests when self-serve flow is on diff --git a/docs/my-website/docs/proxy/spend_logs_deletion.md b/docs/my-website/docs/proxy/spend_logs_deletion.md new file mode 100644 index 00000000000..5b980e61eac --- /dev/null +++ b/docs/my-website/docs/proxy/spend_logs_deletion.md @@ -0,0 +1,91 @@ +# ✨ Maximum Retention Period for Spend Logs + +This walks through how to set the maximum retention period for spend logs. This helps manage database size by deleting old logs automatically. + +:::info + +✨ This is on LiteLLM Enterprise + +[Enterprise Pricing](https://www.litellm.ai/#pricing) + +[Get free 7-day trial key](https://www.litellm.ai/#trial) + +::: + +### Requirements + +- **Postgres** (for log storage) +- **Redis** *(optional)* — required only if you're running multiple proxy instances and want to enable distributed locking + +## Usage + +### Setup + +Add this to your `proxy_config.yaml` under `general_settings`: + +```yaml title="proxy_config.yaml" +general_settings: + maximum_spend_logs_retention_period: "7d" # Keep logs for 7 days + + # Optional: set how frequently cleanup should run - default is daily + maximum_spend_logs_retention_interval: "1d" # Run cleanup daily + +litellm_settings: + cache: true + cache_params: + type: redis +``` + +### Configuration Options + +#### `maximum_spend_logs_retention_period` (required) + +How long logs should be kept before deletion. Supported formats: + +- `"7d"` – 7 days +- `"24h"` – 24 hours +- `"60m"` – 60 minutes +- `"3600s"` – 3600 seconds + +#### `maximum_spend_logs_retention_interval` (optional) + +How often the cleanup job should run. Uses the same format as above. If not set, cleanup will run every 24 hours if and only if `maximum_spend_logs_retention_period` is set. + +## How it works + +### Step 1. Lock Acquisition (Optional with Redis) + +If Redis is enabled, LiteLLM uses it to make sure only one instance runs the cleanup at a time. + +- If the lock is acquired: + - This instance proceeds with cleanup + - Others skip it +- If no lock is present: + - Cleanup still runs (useful for single-node setups) + +![Working of spend log deletions](../../img/spend_log_deletion_working.png) +*Working of spend log deletions* + +### Step 2. Batch Deletion + +Once cleanup starts: + +- It calculates the cutoff date using the configured retention period +- Deletes logs older than the cutoff in **batches of 1000** +- Adds a short delay between batches to avoid overloading the database + +### Default settings: +- **Batch size**: 1000 logs +- **Max batches per run**: 500 +- **Max deletions per run**: 500,000 logs + +You can change the number of batches using an environment variable: + +```bash +SPEND_LOG_RUN_LOOPS=200 +``` + +This would allow up to 200,000 logs to be deleted in one run. + +![Batch deletion of old logs](../../img/spend_log_deletion_multi_pod.jpg) +*Batch deletion of old logs* diff --git a/docs/my-website/docs/proxy/tag_routing.md b/docs/my-website/docs/proxy/tag_routing.md index 4b2621fa8ce..23715e77f81 100644 --- a/docs/my-website/docs/proxy/tag_routing.md +++ b/docs/my-website/docs/proxy/tag_routing.md @@ -143,6 +143,26 @@ Response } ``` +## Calling via Request Header + +You can also call via request header `x-litellm-tags` + +```shell +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-H 'x-litellm-tags: free,my-custom-tag' \ +-d '{ + "model": "gpt-4", + "messages": [ + { + "role": "user", + "content": "Hey, how'\''s it going 123456?" + } + ] +}' +``` + ## Setting Default Tags Use this if you want all untagged requests to be routed to specific deployments diff --git a/docs/my-website/docs/proxy/temporary_budget_increase.md b/docs/my-website/docs/proxy/temporary_budget_increase.md index 917ff0d6b57..de985eb9bd3 100644 --- a/docs/my-website/docs/proxy/temporary_budget_increase.md +++ b/docs/my-website/docs/proxy/temporary_budget_increase.md @@ -3,7 +3,7 @@ Set temporary budget increase for a LiteLLM Virtual Key. Use this if you get asked to increase the budget for a key temporarily. -| Heirarchy | Supported | +| Hierarchy | Supported | |-----------|-----------| | LiteLLM Virtual Key | ✅ | | User | ❌ | diff --git a/docs/my-website/docs/proxy/timeout.md b/docs/my-website/docs/proxy/timeout.md index 2bf93298fec..85428ae53e2 100644 --- a/docs/my-website/docs/proxy/timeout.md +++ b/docs/my-website/docs/proxy/timeout.md @@ -166,7 +166,7 @@ response = client.chat.completions.create( {"role": "user", "content": "what color is red"} ], logit_bias={12481: 100}, - timeout=1 + extra_body={"timeout": 1} # 👈 KEY CHANGE ) print(response) diff --git a/docs/my-website/docs/proxy/token_auth.md b/docs/my-website/docs/proxy/token_auth.md index e18f883ac96..c562c7fb713 100644 --- a/docs/my-website/docs/proxy/token_auth.md +++ b/docs/my-website/docs/proxy/token_auth.md @@ -3,7 +3,7 @@ import TabItem from '@theme/TabItem'; # OIDC - JWT-based Auth -Use JWT's to auth admins / projects into the proxy. +Use JWT's to auth admins / users / projects into the proxy. :::info @@ -102,7 +102,19 @@ curl --location 'http://0.0.0.0:4000/v1/chat/completions' \
-## Advanced - Set Accepted JWT Scope Names +## Advanced + +### Multiple OIDC providers + +Use this if you want LiteLLM to validate your JWT against multiple OIDC providers (e.g. Google Cloud, GitHub Auth) + +Set `JWT_PUBLIC_KEY_URL` in your environment to a comma-separated list of URLs for your OIDC providers. + +```bash +export JWT_PUBLIC_KEY_URL="https://demo.duendesoftware.com/.well-known/openid-configuration/jwks,https://accounts.google.com/.well-known/openid-configuration/jwks" +``` + +### Set Accepted JWT Scope Names Change the string in JWT 'scopes', that litellm evaluates to see if a user has admin access. @@ -114,7 +126,7 @@ general_settings: admin_jwt_scope: "litellm-proxy-admin" ``` -## Tracking End-Users / Internal Users / Team / Org +### Tracking End-Users / Internal Users / Team / Org Set the field in the jwt token, which corresponds to a litellm user / team / org. @@ -156,38 +168,19 @@ scope: ["litellm-proxy-admin",...] scope: "litellm-proxy-admin ..." ``` -## Control Model Access with Roles - -Reject a JWT token if it's valid but doesn't have the required scopes / fields. - -Only tokens which with valid Admin (`admin_jwt_scope`), User (`user_id_jwt_field`), Team (`team_id_jwt_field`) are allowed. - -```yaml -general_settings: - enable_jwt_auth: True - litellm_jwtauth: - user_roles_jwt_field: "resource_access.litellm-test-client-id.roles" - user_allowed_roles: ["basic_user"] # roles that map to an 'internal_user' role on LiteLLM - enforce_rbac: true # if true, will check if the user has the correct role to access the model + endpoint - - role_permissions: # control what models + endpointsare allowed for each role - - role: internal_user - models: ["anthropic-claude"] -``` - -**[Architecture Diagram (Control Model Access)](./jwt_auth_arch)** - -## Control model access with Teams +### Control model access with Teams 1. Specify the JWT field that contains the team ids, that the user belongs to. ```yaml general_settings: - master_key: sk-1234 + enable_jwt_auth: True litellm_jwtauth: user_id_jwt_field: "sub" team_ids_jwt_field: "groups" + user_id_upsert: true # add user_id to the db if they don't exist + enforce_team_based_model_access: true # don't allow users to access models unless the team has access ``` This is assuming your token looks like this: @@ -226,7 +219,65 @@ OIDC Auth for API: [**See Walkthrough**](https://www.loom.com/share/00fe2deab59a - If all checks pass, allow the request -## Advanced - Allowed Routes +### Custom JWT Validate + +Validate a JWT Token using custom logic, if you need an extra way to verify if tokens are valid for LiteLLM Proxy. + +#### 1. Setup custom validate function + +```python +from typing import Literal + +def my_custom_validate(token: str) -> Literal[True]: + """ + Only allow tokens with tenant-id == "my-unique-tenant", and claims == ["proxy-admin"] + """ + allowed_tenants = ["my-unique-tenant"] + allowed_claims = ["proxy-admin"] + + if token["tenant_id"] not in allowed_tenants: + raise Exception("Invalid JWT token") + if token["claims"] not in allowed_claims: + raise Exception("Invalid JWT token") + return True +``` + +#### 2. Setup config.yaml + +```yaml +general_settings: + master_key: sk-1234 + enable_jwt_auth: True + litellm_jwtauth: + user_id_jwt_field: "sub" + team_id_jwt_field: "tenant_id" + user_id_upsert: True + custom_validate: custom_validate.my_custom_validate # 👈 custom validate function +``` + +#### 3. Test the flow + +**Expected JWT** + +``` +{ + "sub": "my-unique-user", + "tenant_id": "INVALID_TENANT", + "claims": ["proxy-admin"] +} +``` + +**Expected Response** + +``` +{ + "error": "Invalid JWT token" +} +``` + + + +### Allowed Routes Configure which routes a JWT can access via the config. @@ -258,7 +309,7 @@ general_settings: team_allowed_routes: ["/v1/chat/completions"] # 👈 Set accepted routes ``` -## Advanced - Caching Public Keys +### Caching Public Keys Control how long public keys are cached for (in seconds). @@ -272,7 +323,7 @@ general_settings: public_key_ttl: 600 # 👈 KEY CHANGE ``` -## Advanced - Custom JWT Field +### Custom JWT Field Set a custom field in which the team_id exists. By default, the 'client_id' field is checked. @@ -284,14 +335,7 @@ general_settings: team_id_jwt_field: "client_id" # 👈 KEY CHANGE ``` -## All Params - -[**See Code**](https://github.com/BerriAI/litellm/blob/b204f0c01c703317d812a1553363ab0cb989d5b6/litellm/proxy/_types.py#L95) - - - - -## Advanced - Block Teams +### Block Teams To block all requests for a certain team id, use `/team/block` @@ -318,7 +362,7 @@ curl --location 'http://0.0.0.0:4000/team/unblock' \ ``` -## Advanced - Upsert Users + Allowed Email Domains +### Upsert Users + Allowed Email Domains Allow users who belong to a specific email domain, automatic access to the proxy. @@ -330,4 +374,135 @@ general_settings: user_email_jwt_field: "email" # 👈 checks 'email' field in jwt payload user_allowed_email_domain: "my-co.com" # allows user@my-co.com to call proxy user_id_upsert: true # 👈 upserts the user to db, if valid email but not in db -``` \ No newline at end of file +``` + +## [BETA] Control Access with OIDC Roles + +Allow JWT tokens with supported roles to access the proxy. + +Let users and teams access the proxy, without needing to add them to the DB. + + +Very important, set `enforce_rbac: true` to ensure that the RBAC system is enabled. + +**Note:** This is in beta and might change unexpectedly. + +```yaml +general_settings: + enable_jwt_auth: True + litellm_jwtauth: + object_id_jwt_field: "oid" # can be either user / team, inferred from the role mapping + roles_jwt_field: "roles" + role_mappings: + - role: litellm.api.consumer + internal_role: "team" + enforce_rbac: true # 👈 VERY IMPORTANT + + role_permissions: # default model + endpoint permissions for a role. + - role: team + models: ["anthropic-claude"] + routes: ["/v1/chat/completions"] + +environment_variables: + JWT_AUDIENCE: "api://LiteLLM_Proxy" # ensures audience is validated +``` + +- `object_id_jwt_field`: The field in the JWT token that contains the object id. This id can be either a user id or a team id. Use this instead of `user_id_jwt_field` and `team_id_jwt_field`. If the same field could be both. + +- `roles_jwt_field`: The field in the JWT token that contains the roles. This field is a list of roles that the user has. To index into a nested field, use dot notation - eg. `resource_access.litellm-test-client-id.roles`. + +- `role_mappings`: A list of role mappings. Map the received role in the JWT token to an internal role on LiteLLM. + +- `JWT_AUDIENCE`: The audience of the JWT token. This is used to validate the audience of the JWT token. Set via an environment variable. + +### Example Token + +```bash +{ + "aud": "api://LiteLLM_Proxy", + "oid": "eec236bd-0135-4b28-9354-8fc4032d543e", + "roles": ["litellm.api.consumer"] +} +``` + +### Role Mapping Spec + +- `role`: The expected role in the JWT token. +- `internal_role`: The internal role on LiteLLM that will be used to control access. + +Supported internal roles: +- `team`: Team object will be used for RBAC spend tracking. Use this for tracking spend for a 'use case'. +- `internal_user`: User object will be used for RBAC spend tracking. Use this for tracking spend for an 'individual user'. +- `proxy_admin`: Proxy admin will be used for RBAC spend tracking. Use this for granting admin access to a token. + +### [Architecture Diagram (Control Model Access)](./jwt_auth_arch) + +## [BETA] Control Model Access with Scopes + +Control which models a JWT can access. Set `enforce_scope_based_access: true` to enforce scope-based access control. + +### 1. Setup config.yaml with scope mappings. + + +```yaml +model_list: + - model_name: anthropic-claude + litellm_params: + model: anthropic/claude-3-5-sonnet + api_key: os.environ/ANTHROPIC_API_KEY + - model_name: gpt-3.5-turbo-testing + litellm_params: + model: gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + +general_settings: + enable_jwt_auth: True + litellm_jwtauth: + team_id_jwt_field: "client_id" # 👈 set the field in the JWT token that contains the team id + team_id_upsert: true # 👈 upsert the team to db, if team id is not found in db + scope_mappings: + - scope: litellm.api.consumer + models: ["anthropic-claude"] + - scope: litellm.api.gpt_3_5_turbo + models: ["gpt-3.5-turbo-testing"] + enforce_scope_based_access: true # 👈 enforce scope-based access control + enforce_rbac: true # 👈 enforces only a Team/User/ProxyAdmin can access the proxy. +``` + +#### Scope Mapping Spec + +- `scope`: The scope to be used for the JWT token. +- `models`: The models that the JWT token can access. Value is the `model_name` in `model_list`. Note: Wildcard routes are not currently supported. + +### 2. Create a JWT with the correct scopes. + +Expected Token: + +```bash +{ + "scope": ["litellm.api.consumer", "litellm.api.gpt_3_5_turbo"] # can be a list or a space-separated string +} +``` + +### 3. Test the flow. + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer eyJhbGci...' \ +-d '{ + "model": "gpt-3.5-turbo-testing", + "messages": [ + { + "role": "user", + "content": "Hey, how'\''s it going 1234?" + } + ] +}' +``` + +## All JWT Params + +[**See Code**](https://github.com/BerriAI/litellm/blob/b204f0c01c703317d812a1553363ab0cb989d5b6/litellm/proxy/_types.py#L95) + + diff --git a/docs/my-website/docs/proxy/ui_credentials.md b/docs/my-website/docs/proxy/ui_credentials.md new file mode 100644 index 00000000000..40db5368596 --- /dev/null +++ b/docs/my-website/docs/proxy/ui_credentials.md @@ -0,0 +1,55 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Adding LLM Credentials + +You can add LLM provider credentials on the UI. Once you add credentials you can reuse them when adding new models + +## Add a credential + model + +### 1. Navigate to LLM Credentials page + +Go to Models -> LLM Credentials -> Add Credential + + + +### 2. Add credentials + +Select your LLM provider, enter your API Key and click "Add Credential" + +**Note: Credentials are based on the provider, if you select Vertex AI then you will see `Vertex Project`, `Vertex Location` and `Vertex Credentials` fields** + + + + +### 3. Use credentials when adding a model + +Go to Add Model -> Existing Credentials -> Select your credential in the dropdown + + + + +## Create a Credential from an existing model + +Use this if you have already created a model and want to store the model credentials for future use + +### 1. Select model to create a credential from + +Go to Models -> Select your model -> Credential -> Create Credential + + + +### 2. Use new credential when adding a model + +Go to Add Model -> Existing Credentials -> Select your credential in the dropdown + + + +## Frequently Asked Questions + + +How are credentials stored? +Credentials in the DB are encrypted/decrypted using `LITELLM_SALT_KEY`, if set. If not, then they are encrypted using `LITELLM_MASTER_KEY`. These keys should be kept secret and not shared with others. + + diff --git a/docs/my-website/docs/proxy/ui_logs.md b/docs/my-website/docs/proxy/ui_logs.md new file mode 100644 index 00000000000..bca50a2165b --- /dev/null +++ b/docs/my-website/docs/proxy/ui_logs.md @@ -0,0 +1,81 @@ + +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Getting Started with UI Logs + +View Spend, Token Usage, Key, Team Name for Each Request to LiteLLM + + + + + +## Overview + +| Log Type | Tracked by Default | +|----------|-------------------| +| Success Logs | ✅ Yes | +| Error Logs | ✅ Yes | +| Request/Response Content Stored | ❌ No by Default, **opt in with `store_prompts_in_spend_logs`** | + + + +**By default LiteLLM does not track the request and response content.** + +## Tracking - Request / Response Content in Logs Page + +If you want to view request and response content on LiteLLM Logs, you need to opt in with this setting + +```yaml +general_settings: + store_prompts_in_spend_logs: true +``` + + + + +## Stop storing Error Logs in DB + +If you do not want to store error logs in DB, you can opt out with this setting + +```yaml +general_settings: + disable_error_logs: True # Only disable writing error logs to DB, regular spend logs will still be written unless `disable_spend_logs: True` +``` + +## Stop storing Spend Logs in DB + +If you do not want to store spend logs in DB, you can opt out with this setting + +```yaml +general_settings: + disable_spend_logs: True # Disable writing spend logs to DB +``` + +## Automatically Deleting Old Spend Logs + +If you're storing spend logs, it might be a good idea to delete them regularly to keep the database fast. + +LiteLLM lets you configure this in your `proxy_config.yaml`: + +```yaml +general_settings: + maximum_spend_logs_retention_period: "7d" # Delete logs older than 7 days + + # Optional: how often to run cleanup + maximum_spend_logs_retention_interval: "1d" # Run once per day +``` + +You can control how many logs are deleted per run using this environment variable: + +`SPEND_LOG_RUN_LOOPS=200 # Deletes up to 200,000 logs in one run (batch size = 1000)` + +For detailed architecture and how it works, see [Spend Logs Deletion](../proxy/spend_logs_deletion). + + + + + + + diff --git a/docs/my-website/docs/proxy/ui_logs_sessions.md b/docs/my-website/docs/proxy/ui_logs_sessions.md new file mode 100644 index 00000000000..a1a3003478b --- /dev/null +++ b/docs/my-website/docs/proxy/ui_logs_sessions.md @@ -0,0 +1,320 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Session Logs + +Group requests into sessions. This allows you to group related requests together. + + + + +## Usage + +### `/chat/completions` + +To group multiple requests into a single session, pass the same `litellm_session_id` in the metadata for each request. Here's how to do it: + + + + +**Request 1** +Create a new session with a unique ID and make the first request. The session ID will be used to track all related requests. + +```python showLineNumbers +import openai +import uuid + +# Create a session ID +session_id = str(uuid.uuid4()) + +client = openai.OpenAI( + api_key="", + base_url="http://0.0.0.0:4000" +) + +# First request in session +response1 = client.chat.completions.create( + model="gpt-4o", + messages=[ + { + "role": "user", + "content": "Write a short story about a robot" + } + ], + extra_body={ + "metadata": { + "litellm_session_id": session_id # Pass the session ID + } + } +) +``` + +**Request 2** +Make another request using the same session ID to link it with the previous request. This allows tracking related requests together. + +```python showLineNumbers +# Second request using same session ID +response2 = client.chat.completions.create( + model="gpt-4o", + messages=[ + { + "role": "user", + "content": "Now write a poem about that robot" + } + ], + extra_body={ + "metadata": { + "litellm_session_id": session_id # Reuse the same session ID + } + } +) +``` + + + + +**Request 1** +Initialize a new session with a unique ID and create a chat model instance for making requests. The session ID is embedded in the model's configuration. + +```python showLineNumbers +from langchain.chat_models import ChatOpenAI +import uuid + +# Create a session ID +session_id = str(uuid.uuid4()) + +chat = ChatOpenAI( + openai_api_base="http://0.0.0.0:4000", + api_key="", + model="gpt-4o", + extra_body={ + "metadata": { + "litellm_session_id": session_id # Pass the session ID + } + } +) + +# First request in session +response1 = chat.invoke("Write a short story about a robot") +``` + +**Request 2** +Use the same chat model instance to make another request, automatically maintaining the session context through the previously configured session ID. + +```python showLineNumbers +# Second request using same chat object and session ID +response2 = chat.invoke("Now write a poem about that robot") +``` + + + + +**Request 1** +Generate a new session ID and make the initial API call. The session ID in the metadata will be used to track this conversation. + +```bash showLineNumbers +# Create a session ID +SESSION_ID=$(uuidgen) + +# Store your API key +API_KEY="" + +# First request in session +curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $API_KEY" \ + --data '{ + "model": "gpt-4o", + "messages": [ + { + "role": "user", + "content": "Write a short story about a robot" + } + ], + "metadata": { + "litellm_session_id": "'$SESSION_ID'" + } +}' +``` + +**Request 2** +Make a follow-up request using the same session ID to maintain conversation context and tracking. + +```bash showLineNumbers +# Second request using same session ID +curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $API_KEY" \ + --data '{ + "model": "gpt-4o", + "messages": [ + { + "role": "user", + "content": "Now write a poem about that robot" + } + ], + "metadata": { + "litellm_session_id": "'$SESSION_ID'" + } +}' +``` + + + + +**Request 1** +Start a new session by creating a unique ID and making the initial request. This session ID will be used to group related requests together. + +```python showLineNumbers +import litellm +import uuid + +# Create a session ID +session_id = str(uuid.uuid4()) + +# First request in session +response1 = litellm.completion( + model="gpt-4o", + messages=[{"role": "user", "content": "Write a short story about a robot"}], + api_base="http://0.0.0.0:4000", + api_key="", + metadata={ + "litellm_session_id": session_id # Pass the session ID + } +) +``` + +**Request 2** +Continue the conversation by making another request with the same session ID, linking it to the previous interaction. + +```python showLineNumbers +# Second request using same session ID +response2 = litellm.completion( + model="gpt-4o", + messages=[{"role": "user", "content": "Now write a poem about that robot"}], + api_base="http://0.0.0.0:4000", + api_key="", + metadata={ + "litellm_session_id": session_id # Reuse the same session ID + } +) +``` + + + + +### `/responses` + +For the `/responses` endpoint, use `previous_response_id` to group requests into a session. The `previous_response_id` is returned in the response of each request. + + + + +**Request 1** +Make the initial request and store the response ID for linking follow-up requests. + +```python showLineNumbers +from openai import OpenAI + +client = OpenAI( + api_key="", + base_url="http://0.0.0.0:4000" +) + +# First request in session +response1 = client.responses.create( + model="anthropic/claude-3-sonnet-20240229-v1:0", + input="Write a short story about a robot" +) + +# Store the response ID for the next request +response_id = response1.id +``` + +**Request 2** +Make a follow-up request using the previous response ID to maintain the conversation context. + +```python showLineNumbers +# Second request using previous response ID +response2 = client.responses.create( + model="anthropic/claude-3-sonnet-20240229-v1:0", + input="Now write a poem about that robot", + previous_response_id=response_id # Link to previous request +) +``` + + + + +**Request 1** +Make the initial request. The response will include an ID that can be used to link follow-up requests. + +```bash showLineNumbers +# Store your API key +API_KEY="" + +# First request in session +curl http://localhost:4000/v1/responses \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $API_KEY" \ + --data '{ + "model": "anthropic/claude-3-sonnet-20240229-v1:0", + "input": "Write a short story about a robot" + }' + +# Response will include an 'id' field that you'll use in the next request +``` + +**Request 2** +Make a follow-up request using the previous response ID to maintain the conversation context. + +```bash showLineNumbers +# Second request using previous response ID +curl http://localhost:4000/v1/responses \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $API_KEY" \ + --data '{ + "model": "anthropic/claude-3-sonnet-20240229-v1:0", + "input": "Now write a poem about that robot", + "previous_response_id": "resp_abc123..." # Replace with actual response ID from previous request + }' +``` + + + + +**Request 1** +Make the initial request and store the response ID for linking follow-up requests. + +```python showLineNumbers +import litellm + +# First request in session +response1 = litellm.responses( + model="anthropic/claude-3-sonnet-20240229-v1:0", + input="Write a short story about a robot", + api_base="http://0.0.0.0:4000", + api_key="" +) + +# Store the response ID for the next request +response_id = response1.id +``` + +**Request 2** +Make a follow-up request using the previous response ID to maintain the conversation context. + +```python showLineNumbers +# Second request using previous response ID +response2 = litellm.responses( + model="anthropic/claude-3-sonnet-20240229-v1:0", + input="Now write a poem about that robot", + api_base="http://0.0.0.0:4000", + api_key="", + previous_response_id=response_id # Link to previous request +) +``` + + + \ No newline at end of file diff --git a/docs/my-website/docs/proxy/user_management_heirarchy.md b/docs/my-website/docs/proxy/user_management_heirarchy.md index 5f3e83ae350..3565c9d257d 100644 --- a/docs/my-website/docs/proxy/user_management_heirarchy.md +++ b/docs/my-website/docs/proxy/user_management_heirarchy.md @@ -1,11 +1,11 @@ import Image from '@theme/IdealImage'; -# User Management Heirarchy +# User Management Hierarchy -LiteLLM supports a heirarchy of users, teams, organizations, and budgets. +LiteLLM supports a hierarchy of users, teams, organizations, and budgets. - Organizations can have multiple teams. [API Reference](https://litellm-api.up.railway.app/#/organization%20management) - Teams can have multiple users. [API Reference](https://litellm-api.up.railway.app/#/team%20management) diff --git a/docs/my-website/docs/proxy/users.md b/docs/my-website/docs/proxy/users.md index 92ea73b9d2e..b4457b8d553 100644 --- a/docs/my-website/docs/proxy/users.md +++ b/docs/my-website/docs/proxy/users.md @@ -786,6 +786,17 @@ Expected Response: } } ``` + +### [BETA] Multi-instance rate limiting + +Enable multi-instance rate limiting with the env var `EXPERIMENTAL_MULTI_INSTANCE_RATE_LIMITING="True"` + +Changes: +- This moves to using async_increment instead of async_set_cache when updating current requests/tokens. +- The in-memory cache is synced with redis every 0.01s, to avoid calling redis for every request. +- In testing, this was found to be 2x faster than the previous implementation, and reduced drift between expected and actual fails to at most 10 requests at high-traffic (100 RPS across 3 instances). + + ## Grant Access to new model Use model access groups to give users access to select models, and add new ones to it over time (e.g. mistral, llama-2, etc.). diff --git a/docs/my-website/docs/proxy/virtual_keys.md b/docs/my-website/docs/proxy/virtual_keys.md index 04be4ade482..26ec69b30dc 100644 --- a/docs/my-website/docs/proxy/virtual_keys.md +++ b/docs/my-website/docs/proxy/virtual_keys.md @@ -23,7 +23,7 @@ Requirements: - ** Set on config.yaml** set your master key under `general_settings:master_key`, example below - ** Set env variable** set `LITELLM_MASTER_KEY` -(the proxy Dockerfile checks if the `DATABASE_URL` is set and then intializes the DB connection) +(the proxy Dockerfile checks if the `DATABASE_URL` is set and then initializes the DB connection) ```shell export DATABASE_URL=postgresql://:@:/ @@ -333,7 +333,7 @@ curl http://localhost:4000/v1/chat/completions \ **Expected Response** -Expect to see a successfull response from the litellm proxy since the key passed in `X-Litellm-Key` is valid +Expect to see a successful response from the litellm proxy since the key passed in `X-Litellm-Key` is valid ```shell {"id":"chatcmpl-f9b2b79a7c30477ab93cd0e717d1773e","choices":[{"finish_reason":"stop","index":0,"message":{"content":"\n\nHello there, how may I assist you today?","role":"assistant","tool_calls":null,"function_call":null}}],"created":1677652288,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":"fp_44709d6fcb","usage":{"completion_tokens":12,"prompt_tokens":9,"total_tokens":21} ``` diff --git a/docs/my-website/docs/proxy_server.md b/docs/my-website/docs/proxy_server.md index 0d08db7444e..e23d64e443b 100644 --- a/docs/my-website/docs/proxy_server.md +++ b/docs/my-website/docs/proxy_server.md @@ -337,7 +337,7 @@ export OPENAI_API_KEY="sk-1234" ``` ```shell -export OPENAI_API_BASE="http://0.0.0.0:8000" +export OPENAI_BASE_URL="http://0.0.0.0:8000" ``` ```shell python3 run.py --task "a script that says hello world" --name "hello world" @@ -572,7 +572,7 @@ export OPENAI_API_KEY="sk-1234" ``` ```shell -export OPENAI_API_BASE="http://0.0.0.0:8000" +export OPENAI_BASE_URL="http://0.0.0.0:8000" ``` ```shell python3 run.py --task "a script that says hello world" --name "hello world" diff --git a/docs/my-website/docs/realtime.md b/docs/my-website/docs/realtime.md index 28697f44b90..7a6143dd028 100644 --- a/docs/my-website/docs/realtime.md +++ b/docs/my-website/docs/realtime.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Realtime Endpoints +# /realtime Use this to loadbalance across Azure + OpenAI. @@ -19,6 +19,8 @@ model_list: litellm_params: model: openai/gpt-4o-realtime-preview-2024-10-01 api_key: os.environ/OPENAI_API_KEY + model_info: + mode: realtime ``` diff --git a/docs/my-website/docs/reasoning_content.md b/docs/my-website/docs/reasoning_content.md new file mode 100644 index 00000000000..12a0f17ba0b --- /dev/null +++ b/docs/my-website/docs/reasoning_content.md @@ -0,0 +1,489 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# 'Thinking' / 'Reasoning Content' + +:::info + +Requires LiteLLM v1.63.0+ + +::: + +Supported Providers: +- Deepseek (`deepseek/`) +- Anthropic API (`anthropic/`) +- Bedrock (Anthropic + Deepseek) (`bedrock/`) +- Vertex AI (Anthropic) (`vertexai/`) +- OpenRouter (`openrouter/`) +- XAI (`xai/`) +- Google AI Studio (`google/`) +- Vertex AI (`vertex_ai/`) + +LiteLLM will standardize the `reasoning_content` in the response and `thinking_blocks` in the assistant message. + +```python title="Example response from litellm" +"message": { + ... + "reasoning_content": "The capital of France is Paris.", + "thinking_blocks": [ # only returned for Anthropic models + { + "type": "thinking", + "thinking": "The capital of France is Paris.", + "signature": "EqoBCkgIARABGAIiQL2UoU0b1OHYi+..." + } + ] +} +``` + +## Quick Start + + + + +```python showLineNumbers +from litellm import completion +import os + +os.environ["ANTHROPIC_API_KEY"] = "" + +response = completion( + model="anthropic/claude-3-7-sonnet-20250219", + messages=[ + {"role": "user", "content": "What is the capital of France?"}, + ], + reasoning_effort="low", +) +print(response.choices[0].message.content) +``` + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "anthropic/claude-3-7-sonnet-20250219", + "messages": [ + { + "role": "user", + "content": "What is the capital of France?" + } + ], + "reasoning_effort": "low" +}' +``` + + + +**Expected Response** + +```bash +{ + "id": "3b66124d79a708e10c603496b363574c", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": " won the FIFA World Cup in 2022.", + "role": "assistant", + "tool_calls": null, + "function_call": null + } + } + ], + "created": 1723323084, + "model": "deepseek/deepseek-chat", + "object": "chat.completion", + "system_fingerprint": "fp_7e0991cad4", + "usage": { + "completion_tokens": 12, + "prompt_tokens": 16, + "total_tokens": 28, + }, + "service_tier": null +} +``` + +## Tool Calling with `thinking` + +Here's how to use `thinking` blocks by Anthropic with tool calling. + + + + +```python showLineNumbers +litellm._turn_on_debug() +litellm.modify_params = True +model = "anthropic/claude-3-7-sonnet-20250219" # works across Anthropic, Bedrock, Vertex AI +# Step 1: send the conversation and available functions to the model +messages = [ + { + "role": "user", + "content": "What's the weather like in San Francisco, Tokyo, and Paris? - give me 3 responses", + } +] +tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state", + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"], + }, + }, + "required": ["location"], + }, + }, + } +] +response = litellm.completion( + model=model, + messages=messages, + tools=tools, + tool_choice="auto", # auto is default, but we'll be explicit + reasoning_effort="low", +) +print("Response\n", response) +response_message = response.choices[0].message +tool_calls = response_message.tool_calls + +print("Expecting there to be 3 tool calls") +assert ( + len(tool_calls) > 0 +) # this has to call the function for SF, Tokyo and paris + +# Step 2: check if the model wanted to call a function +print(f"tool_calls: {tool_calls}") +if tool_calls: + # Step 3: call the function + # Note: the JSON response may not always be valid; be sure to handle errors + available_functions = { + "get_current_weather": get_current_weather, + } # only one function in this example, but you can have multiple + messages.append( + response_message + ) # extend conversation with assistant's reply + print("Response message\n", response_message) + # Step 4: send the info for each function call and function response to the model + for tool_call in tool_calls: + function_name = tool_call.function.name + if function_name not in available_functions: + # the model called a function that does not exist in available_functions - don't try calling anything + return + function_to_call = available_functions[function_name] + function_args = json.loads(tool_call.function.arguments) + function_response = function_to_call( + location=function_args.get("location"), + unit=function_args.get("unit"), + ) + messages.append( + { + "tool_call_id": tool_call.id, + "role": "tool", + "name": function_name, + "content": function_response, + } + ) # extend conversation with function response + print(f"messages: {messages}") + second_response = litellm.completion( + model=model, + messages=messages, + seed=22, + reasoning_effort="low", + # tools=tools, + drop_params=True, + ) # get a new response from the model where it can see the function response + print("second response\n", second_response) +``` + + + + +1. Setup config.yaml + +```yaml showLineNumbers +model_list: + - model_name: claude-3-7-sonnet-thinking + litellm_params: + model: anthropic/claude-3-7-sonnet-20250219 + api_key: os.environ/ANTHROPIC_API_KEY + thinking: { + "type": "enabled", + "budget_tokens": 1024 + } +``` + +2. Run proxy + +```bash showLineNumbers +litellm --config config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +3. Make 1st call + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "claude-3-7-sonnet-thinking", + "messages": [ + {"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris? - give me 3 responses"}, + ], + "tools": [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state", + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"], + }, + }, + "required": ["location"], + }, + }, + } + ], + "tool_choice": "auto" + }' +``` + +4. Make 2nd call with tool call results + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "claude-3-7-sonnet-thinking", + "messages": [ + { + "role": "user", + "content": "What\'s the weather like in San Francisco, Tokyo, and Paris? - give me 3 responses" + }, + { + "role": "assistant", + "content": "I\'ll check the current weather for these three cities for you:", + "tool_calls": [ + { + "index": 2, + "function": { + "arguments": "{\"location\": \"San Francisco\"}", + "name": "get_current_weather" + }, + "id": "tooluse_mnqzmtWYRjCxUInuAdK7-w", + "type": "function" + } + ], + "function_call": null, + "reasoning_content": "The user is asking for the current weather in three different locations: San Francisco, Tokyo, and Paris. I have access to the `get_current_weather` function that can provide this information.\n\nThe function requires a `location` parameter, and has an optional `unit` parameter. The user hasn't specified which unit they prefer (celsius or fahrenheit), so I'll use the default provided by the function.\n\nI need to make three separate function calls, one for each location:\n1. San Francisco\n2. Tokyo\n3. Paris\n\nThen I'll compile the results into a response with three distinct weather reports as requested by the user.", + "thinking_blocks": [ + { + "type": "thinking", + "thinking": "The user is asking for the current weather in three different locations: San Francisco, Tokyo, and Paris. I have access to the `get_current_weather` function that can provide this information.\n\nThe function requires a `location` parameter, and has an optional `unit` parameter. The user hasn't specified which unit they prefer (celsius or fahrenheit), so I'll use the default provided by the function.\n\nI need to make three separate function calls, one for each location:\n1. San Francisco\n2. Tokyo\n3. Paris\n\nThen I'll compile the results into a response with three distinct weather reports as requested by the user.", + "signature": "EqoBCkgIARABGAIiQCkBXENoyB+HstUOs/iGjG+bvDbIQRrxPsPpOSt5yDxX6iulZ/4K/w9Rt4J5Nb2+3XUYsyOH+CpZMfADYvItFR4SDPb7CmzoGKoolCMAJRoM62p1ZRASZhrD3swqIjAVY7vOAFWKZyPEJglfX/60+bJphN9W1wXR6rWrqn3MwUbQ5Mb/pnpeb10HMploRgUqEGKOd6fRKTkUoNDuAnPb55c=" + } + ], + "provider_specific_fields": { + "reasoningContentBlocks": [ + { + "reasoningText": { + "signature": "EqoBCkgIARABGAIiQCkBXENoyB+HstUOs/iGjG+bvDbIQRrxPsPpOSt5yDxX6iulZ/4K/w9Rt4J5Nb2+3XUYsyOH+CpZMfADYvItFR4SDPb7CmzoGKoolCMAJRoM62p1ZRASZhrD3swqIjAVY7vOAFWKZyPEJglfX/60+bJphN9W1wXR6rWrqn3MwUbQ5Mb/pnpeb10HMploRgUqEGKOd6fRKTkUoNDuAnPb55c=", + "text": "The user is asking for the current weather in three different locations: San Francisco, Tokyo, and Paris. I have access to the `get_current_weather` function that can provide this information.\n\nThe function requires a `location` parameter, and has an optional `unit` parameter. The user hasn't specified which unit they prefer (celsius or fahrenheit), so I'll use the default provided by the function.\n\nI need to make three separate function calls, one for each location:\n1. San Francisco\n2. Tokyo\n3. Paris\n\nThen I'll compile the results into a response with three distinct weather reports as requested by the user." + } + } + ] + } + }, + { + "tool_call_id": "tooluse_mnqzmtWYRjCxUInuAdK7-w", + "role": "tool", + "name": "get_current_weather", + "content": "{\"location\": \"San Francisco\", \"temperature\": \"72\", \"unit\": \"fahrenheit\"}" + } + ] + }' +``` + + + + +## Switching between Anthropic + Deepseek models + +Set `drop_params=True` to drop the 'thinking' blocks when swapping from Anthropic to Deepseek models. Suggest improvements to this approach [here](https://github.com/BerriAI/litellm/discussions/8927). + +```python showLineNumbers +litellm.drop_params = True # 👈 EITHER GLOBALLY or per request + +# or per request +## Anthropic +response = litellm.completion( + model="anthropic/claude-3-7-sonnet-20250219", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", + drop_params=True, +) + +## Deepseek +response = litellm.completion( + model="deepseek/deepseek-chat", + messages=[{"role": "user", "content": "What is the capital of France?"}], + reasoning_effort="low", + drop_params=True, +) +``` + +## Spec + + +These fields can be accessed via `response.choices[0].message.reasoning_content` and `response.choices[0].message.thinking_blocks`. + +- `reasoning_content` - str: The reasoning content from the model. Returned across all providers. +- `thinking_blocks` - Optional[List[Dict[str, str]]]: A list of thinking blocks from the model. Only returned for Anthropic models. + - `type` - str: The type of thinking block. + - `thinking` - str: The thinking from the model. + - `signature` - str: The signature delta from the model. + + + +## Pass `thinking` to Anthropic models + +You can also pass the `thinking` parameter to Anthropic models. + + + + +```python showLineNumbers +response = litellm.completion( + model="anthropic/claude-3-7-sonnet-20250219", + messages=[{"role": "user", "content": "What is the capital of France?"}], + thinking={"type": "enabled", "budget_tokens": 1024}, +) +``` + + + + +```bash +curl http://0.0.0.0:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LITELLM_KEY" \ + -d '{ + "model": "anthropic/claude-3-7-sonnet-20250219", + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "thinking": {"type": "enabled", "budget_tokens": 1024} + }' +``` + + + + +## Checking if a model supports reasoning + + + + +Use `litellm.supports_reasoning(model="")` -> returns `True` if model supports reasoning and `False` if not. + +```python showLineNumbers title="litellm.supports_reasoning() usage" +import litellm + +# Example models that support reasoning +assert litellm.supports_reasoning(model="anthropic/claude-3-7-sonnet-20250219") == True +assert litellm.supports_reasoning(model="deepseek/deepseek-chat") == True + +# Example models that do not support reasoning +assert litellm.supports_reasoning(model="openai/gpt-3.5-turbo") == False +``` + + + + +1. Define models that support reasoning in your `config.yaml`. You can optionally add `supports_reasoning: True` to the `model_info` if LiteLLM does not automatically detect it for your custom model. + +```yaml showLineNumbers title="litellm proxy config.yaml" +model_list: + - model_name: claude-3-sonnet-reasoning + litellm_params: + model: anthropic/claude-3-7-sonnet-20250219 + api_key: os.environ/ANTHROPIC_API_KEY + - model_name: deepseek-reasoning + litellm_params: + model: deepseek/deepseek-chat + api_key: os.environ/DEEPSEEK_API_KEY + # Example for a custom model where detection might be needed + - model_name: my-custom-reasoning-model + litellm_params: + model: openai/my-custom-model # Assuming it's OpenAI compatible + api_base: http://localhost:8000 + api_key: fake-key + model_info: + supports_reasoning: True # Explicitly mark as supporting reasoning +``` + +2. Run the proxy server: + +```bash showLineNumbers title="litellm --config config.yaml" +litellm --config config.yaml +``` + +3. Call `/model_group/info` to check if your model supports `reasoning` + +```shell showLineNumbers title="curl /model_group/info" +curl -X 'GET' \ + 'http://localhost:4000/model_group/info' \ + -H 'accept: application/json' \ + -H 'x-api-key: sk-1234' +``` + +Expected Response + +```json showLineNumbers title="response from /model_group/info" +{ + "data": [ + { + "model_group": "claude-3-sonnet-reasoning", + "providers": ["anthropic"], + "mode": "chat", + "supports_reasoning": true, + }, + { + "model_group": "deepseek-reasoning", + "providers": ["deepseek"], + "supports_reasoning": true, + }, + { + "model_group": "my-custom-reasoning-model", + "providers": ["openai"], + "supports_reasoning": true, + } + ] +} +```` + + + + diff --git a/docs/my-website/docs/rerank.md b/docs/my-website/docs/rerank.md index 598c6729424..1e3cfd0fa5c 100644 --- a/docs/my-website/docs/rerank.md +++ b/docs/my-website/docs/rerank.md @@ -1,4 +1,4 @@ -# Rerank +# /rerank :::tip @@ -111,7 +111,7 @@ curl http://0.0.0.0:4000/rerank \ | Provider | Link to Usage | |-------------|--------------------| -| Cohere | [Usage](#quick-start) | +| Cohere (v1 + v2 clients) | [Usage](#quick-start) | | Together AI| [Usage](../docs/providers/togetherai) | | Azure AI| [Usage](../docs/providers/azure_ai) | | Jina AI| [Usage](../docs/providers/jina_ai) | diff --git a/docs/my-website/docs/response_api.md b/docs/my-website/docs/response_api.md new file mode 100644 index 00000000000..26c0081be2d --- /dev/null +++ b/docs/my-website/docs/response_api.md @@ -0,0 +1,937 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# /responses [Beta] + +LiteLLM provides a BETA endpoint in the spec of [OpenAI's `/responses` API](https://platform.openai.com/docs/api-reference/responses) + +| Feature | Supported | Notes | +|---------|-----------|--------| +| Cost Tracking | ✅ | Works with all supported models | +| Logging | ✅ | Works across all integrations | +| End-user Tracking | ✅ | | +| Streaming | ✅ | | +| Fallbacks | ✅ | Works between supported models | +| Loadbalancing | ✅ | Works between supported models | +| Supported operations | Create a response, Get a response, Delete a response | | +| Supported LiteLLM Versions | 1.63.8+ | | +| Supported LLM providers | **All LiteLLM supported providers** | `openai`, `anthropic`, `bedrock`, `vertex_ai`, `gemini`, `azure`, `azure_ai` etc. | + +## Usage + +### LiteLLM Python SDK + + + + +#### Non-streaming +```python showLineNumbers title="OpenAI Non-streaming Response" +import litellm + +# Non-streaming response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="OpenAI Streaming Response" +import litellm + +# Streaming response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + +#### GET a Response +```python showLineNumbers title="Get Response by ID" +import litellm + +# First, create a response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +# Get the response ID +response_id = response.id + +# Retrieve the response by ID +retrieved_response = litellm.get_responses( + response_id=response_id +) + +print(retrieved_response) + +# For async usage +# retrieved_response = await litellm.aget_responses(response_id=response_id) +``` + +#### DELETE a Response +```python showLineNumbers title="Delete Response by ID" +import litellm + +# First, create a response +response = litellm.responses( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +# Get the response ID +response_id = response.id + +# Delete the response by ID +delete_response = litellm.delete_responses( + response_id=response_id +) + +print(delete_response) + +# For async usage +# delete_response = await litellm.adelete_responses(response_id=response_id) +``` + + + + + +#### Non-streaming +```python showLineNumbers title="Anthropic Non-streaming Response" +import litellm +import os + +# Set API key +os.environ["ANTHROPIC_API_KEY"] = "your-anthropic-api-key" + +# Non-streaming response +response = litellm.responses( + model="anthropic/claude-3-5-sonnet-20240620", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="Anthropic Streaming Response" +import litellm +import os + +# Set API key +os.environ["ANTHROPIC_API_KEY"] = "your-anthropic-api-key" + +# Streaming response +response = litellm.responses( + model="anthropic/claude-3-5-sonnet-20240620", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + + +#### Non-streaming +```python showLineNumbers title="Vertex AI Non-streaming Response" +import litellm +import os + +# Set credentials - Vertex AI uses application default credentials +# Run 'gcloud auth application-default login' to authenticate +os.environ["VERTEXAI_PROJECT"] = "your-gcp-project-id" +os.environ["VERTEXAI_LOCATION"] = "us-central1" + +# Non-streaming response +response = litellm.responses( + model="vertex_ai/gemini-1.5-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="Vertex AI Streaming Response" +import litellm +import os + +# Set credentials - Vertex AI uses application default credentials +# Run 'gcloud auth application-default login' to authenticate +os.environ["VERTEXAI_PROJECT"] = "your-gcp-project-id" +os.environ["VERTEXAI_LOCATION"] = "us-central1" + +# Streaming response +response = litellm.responses( + model="vertex_ai/gemini-1.5-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + + +#### Non-streaming +```python showLineNumbers title="AWS Bedrock Non-streaming Response" +import litellm +import os + +# Set AWS credentials +os.environ["AWS_ACCESS_KEY_ID"] = "your-access-key-id" +os.environ["AWS_SECRET_ACCESS_KEY"] = "your-secret-access-key" +os.environ["AWS_REGION_NAME"] = "us-west-2" # or your AWS region + +# Non-streaming response +response = litellm.responses( + model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="AWS Bedrock Streaming Response" +import litellm +import os + +# Set AWS credentials +os.environ["AWS_ACCESS_KEY_ID"] = "your-access-key-id" +os.environ["AWS_SECRET_ACCESS_KEY"] = "your-secret-access-key" +os.environ["AWS_REGION_NAME"] = "us-west-2" # or your AWS region + +# Streaming response +response = litellm.responses( + model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + + +#### Non-streaming +```python showLineNumbers title="Google AI Studio Non-streaming Response" +import litellm +import os + +# Set API key for Google AI Studio +os.environ["GEMINI_API_KEY"] = "your-gemini-api-key" + +# Non-streaming response +response = litellm.responses( + model="gemini/gemini-1.5-flash", + input="Tell me a three sentence bedtime story about a unicorn.", + max_output_tokens=100 +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="Google AI Studio Streaming Response" +import litellm +import os + +# Set API key for Google AI Studio +os.environ["GEMINI_API_KEY"] = "your-gemini-api-key" + +# Streaming response +response = litellm.responses( + model="gemini/gemini-1.5-flash", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + +### LiteLLM Proxy with OpenAI SDK + +First, set up and start your LiteLLM proxy server. + +```bash title="Start LiteLLM Proxy Server" +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + + + + +First, add this to your litellm proxy config.yaml: +```yaml showLineNumbers title="OpenAI Proxy Configuration" +model_list: + - model_name: openai/o1-pro + litellm_params: + model: openai/o1-pro + api_key: os.environ/OPENAI_API_KEY +``` + +#### Non-streaming +```python showLineNumbers title="OpenAI Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="OpenAI Proxy Streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + +#### GET a Response +```python showLineNumbers title="Get Response by ID with OpenAI SDK" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# First, create a response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +# Get the response ID +response_id = response.id + +# Retrieve the response by ID +retrieved_response = client.responses.retrieve(response_id) + +print(retrieved_response) +``` + +#### DELETE a Response +```python showLineNumbers title="Delete Response by ID with OpenAI SDK" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# First, create a response +response = client.responses.create( + model="openai/o1-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +# Get the response ID +response_id = response.id + +# Delete the response by ID +delete_response = client.responses.delete(response_id) + +print(delete_response) +``` + + + + + +First, add this to your litellm proxy config.yaml: +```yaml showLineNumbers title="Anthropic Proxy Configuration" +model_list: + - model_name: anthropic/claude-3-5-sonnet-20240620 + litellm_params: + model: anthropic/claude-3-5-sonnet-20240620 + api_key: os.environ/ANTHROPIC_API_KEY +``` + +#### Non-streaming +```python showLineNumbers title="Anthropic Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="anthropic/claude-3-5-sonnet-20240620", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="Anthropic Proxy Streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="anthropic/claude-3-5-sonnet-20240620", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + + +First, add this to your litellm proxy config.yaml: +```yaml showLineNumbers title="Vertex AI Proxy Configuration" +model_list: + - model_name: vertex_ai/gemini-1.5-pro + litellm_params: + model: vertex_ai/gemini-1.5-pro + vertex_project: your-gcp-project-id + vertex_location: us-central1 +``` + +#### Non-streaming +```python showLineNumbers title="Vertex AI Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="vertex_ai/gemini-1.5-pro", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="Vertex AI Proxy Streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="vertex_ai/gemini-1.5-pro", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + + +First, add this to your litellm proxy config.yaml: +```yaml showLineNumbers title="AWS Bedrock Proxy Configuration" +model_list: + - model_name: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 + litellm_params: + model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 + aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID + aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY + aws_region_name: us-west-2 +``` + +#### Non-streaming +```python showLineNumbers title="AWS Bedrock Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="AWS Bedrock Proxy Streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + + +First, add this to your litellm proxy config.yaml: +```yaml showLineNumbers title="Google AI Studio Proxy Configuration" +model_list: + - model_name: gemini/gemini-1.5-flash + litellm_params: + model: gemini/gemini-1.5-flash + api_key: os.environ/GEMINI_API_KEY +``` + +#### Non-streaming +```python showLineNumbers title="Google AI Studio Proxy Non-streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.responses.create( + model="gemini/gemini-1.5-flash", + input="Tell me a three sentence bedtime story about a unicorn." +) + +print(response) +``` + +#### Streaming +```python showLineNumbers title="Google AI Studio Proxy Streaming Response" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-api-key" # Your proxy API key +) + +# Streaming response +response = client.responses.create( + model="gemini/gemini-1.5-flash", + input="Tell me a three sentence bedtime story about a unicorn.", + stream=True +) + +for event in response: + print(event) +``` + + + + +## Supported Responses API Parameters + +| Provider | Supported Parameters | +|----------|---------------------| +| `openai` | [All Responses API parameters are supported](https://github.com/BerriAI/litellm/blob/7c3df984da8e4dff9201e4c5353fdc7a2b441831/litellm/llms/openai/responses/transformation.py#L23) | +| `azure` | [All Responses API parameters are supported](https://github.com/BerriAI/litellm/blob/7c3df984da8e4dff9201e4c5353fdc7a2b441831/litellm/llms/openai/responses/transformation.py#L23) | +| `anthropic` | [See supported parameters here](https://github.com/BerriAI/litellm/blob/f39d9178868662746f159d5ef642c7f34f9bfe5f/litellm/responses/litellm_completion_transformation/transformation.py#L57) | +| `bedrock` | [See supported parameters here](https://github.com/BerriAI/litellm/blob/f39d9178868662746f159d5ef642c7f34f9bfe5f/litellm/responses/litellm_completion_transformation/transformation.py#L57) | +| `gemini` | [See supported parameters here](https://github.com/BerriAI/litellm/blob/f39d9178868662746f159d5ef642c7f34f9bfe5f/litellm/responses/litellm_completion_transformation/transformation.py#L57) | +| `vertex_ai` | [See supported parameters here](https://github.com/BerriAI/litellm/blob/f39d9178868662746f159d5ef642c7f34f9bfe5f/litellm/responses/litellm_completion_transformation/transformation.py#L57) | +| `azure_ai` | [See supported parameters here](https://github.com/BerriAI/litellm/blob/f39d9178868662746f159d5ef642c7f34f9bfe5f/litellm/responses/litellm_completion_transformation/transformation.py#L57) | +| All other llm api providers | [See supported parameters here](https://github.com/BerriAI/litellm/blob/f39d9178868662746f159d5ef642c7f34f9bfe5f/litellm/responses/litellm_completion_transformation/transformation.py#L57) | + +## Load Balancing with Session Continuity. + +When using the Responses API with multiple deployments of the same model (e.g., multiple Azure OpenAI endpoints), LiteLLM provides session continuity. This ensures that follow-up requests using a `previous_response_id` are routed to the same deployment that generated the original response. + + +#### Example Usage + + + + +```python showLineNumbers title="Python SDK with Session Continuity" +import litellm + +# Set up router with multiple deployments of the same model +router = litellm.Router( + model_list=[ + { + "model_name": "azure-gpt4-turbo", + "litellm_params": { + "model": "azure/gpt-4-turbo", + "api_key": "your-api-key-1", + "api_version": "2024-06-01", + "api_base": "https://endpoint1.openai.azure.com", + }, + }, + { + "model_name": "azure-gpt4-turbo", + "litellm_params": { + "model": "azure/gpt-4-turbo", + "api_key": "your-api-key-2", + "api_version": "2024-06-01", + "api_base": "https://endpoint2.openai.azure.com", + }, + }, + ], + optional_pre_call_checks=["responses_api_deployment_check"], +) + +# Initial request +response = await router.aresponses( + model="azure-gpt4-turbo", + input="Hello, who are you?", + truncation="auto", +) + +# Store the response ID +response_id = response.id + +# Follow-up request - will be automatically routed to the same deployment +follow_up = await router.aresponses( + model="azure-gpt4-turbo", + input="Tell me more about yourself", + truncation="auto", + previous_response_id=response_id # This ensures routing to the same deployment +) +``` + + + + +#### 1. Setup session continuity on proxy config.yaml + +To enable session continuity for Responses API in your LiteLLM proxy, set `optional_pre_call_checks: ["responses_api_deployment_check"]` in your proxy config.yaml. + +```yaml showLineNumbers title="config.yaml with Session Continuity" +model_list: + - model_name: azure-gpt4-turbo + litellm_params: + model: azure/gpt-4-turbo + api_key: your-api-key-1 + api_version: 2024-06-01 + api_base: https://endpoint1.openai.azure.com + - model_name: azure-gpt4-turbo + litellm_params: + model: azure/gpt-4-turbo + api_key: your-api-key-2 + api_version: 2024-06-01 + api_base: https://endpoint2.openai.azure.com + +router_settings: + optional_pre_call_checks: ["responses_api_deployment_check"] +``` + +#### 2. Use the OpenAI Python SDK to make requests to LiteLLM Proxy + +```python showLineNumbers title="OpenAI Client with Proxy Server" +from openai import OpenAI + +client = OpenAI( + base_url="http://localhost:4000", + api_key="your-api-key" +) + +# Initial request +response = client.responses.create( + model="azure-gpt4-turbo", + input="Hello, who are you?" +) + +response_id = response.id + +# Follow-up request - will be automatically routed to the same deployment +follow_up = client.responses.create( + model="azure-gpt4-turbo", + input="Tell me more about yourself", + previous_response_id=response_id # This ensures routing to the same deployment +) +``` + + + + +## Session Management - Non-OpenAI Models + +LiteLLM Proxy supports session management for non-OpenAI models. This allows you to store and fetch conversation history (state) in LiteLLM Proxy. + +#### Usage + +1. Enable storing request / response content in the database + +Set `store_prompts_in_spend_logs: true` in your proxy config.yaml. When this is enabled, LiteLLM will store the request and response content in the database. + +```yaml +general_settings: + store_prompts_in_spend_logs: true +``` + +2. Make request 1 with no `previous_response_id` (new session) + +Start a new conversation by making a request without specifying a previous response ID. + + + + +```curl +curl http://localhost:4000/v1/responses \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "anthropic/claude-3-5-sonnet-latest", + "input": "who is Michael Jordan" + }' +``` + + + + +```python +from openai import OpenAI + +# Initialize the client with your LiteLLM proxy URL +client = OpenAI( + base_url="http://localhost:4000", + api_key="sk-1234" +) + +# Make initial request to start a new conversation +response = client.responses.create( + model="anthropic/claude-3-5-sonnet-latest", + input="who is Michael Jordan" +) + +print(response.id) # Store this ID for future requests in same session +print(response.output[0].content[0].text) +``` + + + + +Response: + +```json +{ + "id":"resp_123abc", + "model":"claude-3-5-sonnet-20241022", + "output":[{ + "type":"message", + "content":[{ + "type":"output_text", + "text":"Michael Jordan is widely considered one of the greatest basketball players of all time. He played for the Chicago Bulls (1984-1993, 1995-1998) and Washington Wizards (2001-2003), winning 6 NBA Championships with the Bulls." + }] + }] +} +``` + +3. Make request 2 with `previous_response_id` (same session) + +Continue the conversation by referencing the previous response ID to maintain conversation context. + + + + +```curl +curl http://localhost:4000/v1/responses \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "anthropic/claude-3-5-sonnet-latest", + "input": "can you tell me more about him", + "previous_response_id": "resp_123abc" + }' +``` + + + + +```python +from openai import OpenAI + +# Initialize the client with your LiteLLM proxy URL +client = OpenAI( + base_url="http://localhost:4000", + api_key="sk-1234" +) + +# Make follow-up request in the same conversation session +follow_up_response = client.responses.create( + model="anthropic/claude-3-5-sonnet-latest", + input="can you tell me more about him", + previous_response_id="resp_123abc" # ID from the previous response +) + +print(follow_up_response.output[0].content[0].text) +``` + + + + +Response: + +```json +{ + "id":"resp_456def", + "model":"claude-3-5-sonnet-20241022", + "output":[{ + "type":"message", + "content":[{ + "type":"output_text", + "text":"Michael Jordan was born February 17, 1963. He attended University of North Carolina before being drafted 3rd overall by the Bulls in 1984. Beyond basketball, he built the Air Jordan brand with Nike and later became owner of the Charlotte Hornets." + }] + }] +} +``` + +4. Make request 3 with no `previous_response_id` (new session) + +Start a brand new conversation without referencing previous context to demonstrate how context is not maintained between sessions. + + + + +```curl +curl http://localhost:4000/v1/responses \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "anthropic/claude-3-5-sonnet-latest", + "input": "can you tell me more about him" + }' +``` + + + + +```python +from openai import OpenAI + +# Initialize the client with your LiteLLM proxy URL +client = OpenAI( + base_url="http://localhost:4000", + api_key="sk-1234" +) + +# Make a new request without previous context +new_session_response = client.responses.create( + model="anthropic/claude-3-5-sonnet-latest", + input="can you tell me more about him" + # No previous_response_id means this starts a new conversation +) + +print(new_session_response.output[0].content[0].text) +``` + + + + +Response: + +```json +{ + "id":"resp_789ghi", + "model":"claude-3-5-sonnet-20241022", + "output":[{ + "type":"message", + "content":[{ + "type":"output_text", + "text":"I don't see who you're referring to in our conversation. Could you let me know which person you'd like to learn more about?" + }] + }] +} +``` + + + + + + + + + + + + + diff --git a/docs/my-website/docs/routing.md b/docs/my-website/docs/routing.md index 308b850e45e..fa784a719c2 100644 --- a/docs/my-website/docs/routing.md +++ b/docs/my-website/docs/routing.md @@ -25,7 +25,7 @@ If you want a server to load balance across different LLM APIs, use our [LiteLLM ### Quick Start -Loadbalance across multiple [azure](./providers/azure.md)/[bedrock](./providers/bedrock.md)/[provider](./providers/) deployments. LiteLLM will handle retrying in different regions if a call fails. +Loadbalance across multiple [azure](./providers/azure)/[bedrock](./providers/bedrock.md)/[provider](./providers/) deployments. LiteLLM will handle retrying in different regions if a call fails. @@ -826,6 +826,65 @@ asyncio.run(router_acompletion()) ## Basic Reliability +### Weighted Deployments + +Set `weight` on a deployment to pick one deployment more often than others. + +This works across **simple-shuffle** routing strategy (this is the default, if no routing strategy is selected). + + + + +```python +from litellm import Router + +model_list = [ + { + "model_name": "o1", + "litellm_params": { + "model": "o1-preview", + "api_key": os.getenv("OPENAI_API_KEY"), + "weight": 1 + }, + }, + { + "model_name": "o1", + "litellm_params": { + "model": "o1-preview", + "api_key": os.getenv("OPENAI_API_KEY"), + "weight": 2 # 👈 PICK THIS DEPLOYMENT 2x MORE OFTEN THAN o1-preview + }, + }, +] + +router = Router(model_list=model_list, routing_strategy="cost-based-routing") + +response = await router.acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hey, how's it going?"}] +) +print(response) +``` + + + +```yaml +model_list: + - model_name: o1 + litellm_params: + model: o1 + api_key: os.environ/OPENAI_API_KEY + weight: 1 + - model_name: o1 + litellm_params: + model: o1-preview + api_key: os.environ/OPENAI_API_KEY + weight: 2 # 👈 PICK THIS DEPLOYMENT 2x MORE OFTEN THAN o1-preview +``` + + + + ### Max Parallel Requests (ASYNC) Used in semaphore for async requests on router. Limit the max concurrent calls made to a deployment. Useful in high-traffic scenarios. @@ -893,8 +952,8 @@ router_settings: ``` Defaults: -- allowed_fails: 0 -- cooldown_time: 60s +- allowed_fails: 3 +- cooldown_time: 5s (`DEFAULT_COOLDOWN_TIME_SECONDS` in constants.py) **Set Per Model** diff --git a/docs/my-website/docs/secret.md b/docs/my-website/docs/secret.md index a65c696f367..9f0ff7059cd 100644 --- a/docs/my-website/docs/secret.md +++ b/docs/my-website/docs/secret.md @@ -96,6 +96,33 @@ litellm --config /path/to/config.yaml ``` +#### Using K/V pairs in 1 AWS Secret + +You can read multiple keys from a single AWS Secret using the `primary_secret_name` parameter: + +```yaml +general_settings: + key_management_system: "aws_secret_manager" + key_management_settings: + hosted_keys: [ + "OPENAI_API_KEY_MODEL_1", + "OPENAI_API_KEY_MODEL_2", + ] + primary_secret_name: "litellm_secrets" # 👈 Read multiple keys from one JSON secret +``` + +The `primary_secret_name` allows you to read multiple keys from a single AWS Secret as a JSON object. For example, the "litellm_secrets" would contain: + +```json +{ + "OPENAI_API_KEY_MODEL_1": "sk-key1...", + "OPENAI_API_KEY_MODEL_2": "sk-key2..." +} +``` + +This reduces the number of AWS Secrets you need to manage. + + ## Hashicorp Vault @@ -353,4 +380,7 @@ general_settings: # Hosted Keys Settings hosted_keys: ["litellm_master_key"] # OPTIONAL. Specify which env keys you stored on AWS + + # K/V pairs in 1 AWS Secret Settings + primary_secret_name: "litellm_secrets" # OPTIONAL. Read multiple keys from one JSON secret on AWS Secret Manager ``` \ No newline at end of file diff --git a/docs/my-website/docs/set_keys.md b/docs/my-website/docs/set_keys.md index 7e63b5a888b..295d9ec5501 100644 --- a/docs/my-website/docs/set_keys.md +++ b/docs/my-website/docs/set_keys.md @@ -30,6 +30,7 @@ import os # Set OpenAI API key os.environ["OPENAI_API_KEY"] = "Your API Key" os.environ["ANTHROPIC_API_KEY"] = "Your API Key" +os.environ["XAI_API_KEY"] = "Your API Key" os.environ["REPLICATE_API_KEY"] = "Your API Key" os.environ["TOGETHERAI_API_KEY"] = "Your API Key" ``` @@ -43,7 +44,7 @@ os.environ['AZURE_API_VERSION'] = "2023-05-15" # [OPTIONAL] os.environ['AZURE_API_TYPE'] = "azure" # [OPTIONAL] # for openai -os.environ['OPENAI_API_BASE'] = "https://openai-gpt-4-test2-v-12.openai.azure.com/" +os.environ['OPENAI_BASE_URL'] = "https://your_host/v1" ``` ### Setting Project, Location, Token @@ -187,7 +188,13 @@ Currently implemented for: - OpenAI (if OPENAI_API_KEY is set) - Fireworks AI (if FIREWORKS_AI_API_KEY is set) - LiteLLM Proxy (if LITELLM_PROXY_API_KEY is set) +- Gemini (if GEMINI_API_KEY is set) +- XAI (if XAI_API_KEY is set) +- Anthropic (if ANTHROPIC_API_KEY is set) +You can also specify a custom provider to check: + +**All providers**: ```python from litellm import get_valid_models @@ -195,6 +202,14 @@ valid_models = get_valid_models(check_provider_endpoint=True) print(valid_models) ``` +**Specific provider**: +```python +from litellm import get_valid_models + +valid_models = get_valid_models(check_provider_endpoint=True, custom_llm_provider="openai") +print(valid_models) +``` + ### `validate_environment(model: str)` This helper tells you if you have all the required environment variables for a model, and if not - what's missing. diff --git a/docs/my-website/docs/simple_proxy_old_doc.md b/docs/my-website/docs/simple_proxy_old_doc.md index 64491b1ea8f..730fd0aab42 100644 --- a/docs/my-website/docs/simple_proxy_old_doc.md +++ b/docs/my-website/docs/simple_proxy_old_doc.md @@ -994,16 +994,16 @@ litellm --health ## Logging Proxy Input/Output - OpenTelemetry -### Step 1 Start OpenTelemetry Collecter Docker Container +### Step 1 Start OpenTelemetry Collector Docker Container This container sends logs to your selected destination -#### Install OpenTelemetry Collecter Docker Image +#### Install OpenTelemetry Collector Docker Image ```shell docker pull otel/opentelemetry-collector:0.90.0 docker run -p 127.0.0.1:4317:4317 -p 127.0.0.1:55679:55679 otel/opentelemetry-collector:0.90.0 ``` -#### Set Destination paths on OpenTelemetry Collecter +#### Set Destination paths on OpenTelemetry Collector Here's the OpenTelemetry yaml config to use with Elastic Search ```yaml @@ -1077,7 +1077,7 @@ general_settings: LiteLLM will read the `OTEL_ENDPOINT` environment variable to send data to your OTEL collector ```python -os.environ['OTEL_ENDPOINT'] # defauls to 127.0.0.1:4317 if not provided +os.environ['OTEL_ENDPOINT'] # defaults to 127.0.0.1:4317 if not provided ``` #### Start LiteLLM Proxy @@ -1101,8 +1101,8 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \ ``` -#### Test & View Logs on OpenTelemetry Collecter -On successfull logging you should be able to see this log on your `OpenTelemetry Collecter` Docker Container +#### Test & View Logs on OpenTelemetry Collector +On successful logging you should be able to see this log on your `OpenTelemetry Collector` Docker Container ```shell Events: SpanEvent #0 @@ -1149,7 +1149,7 @@ Here's the log view on Elastic Search. You can see the request `input`, `output` ## Logging Proxy Input/Output - Langfuse -We will use the `--config` to set `litellm.success_callback = ["langfuse"]` this will log all successfull LLM calls to langfuse +We will use the `--config` to set `litellm.success_callback = ["langfuse"]` this will log all successful LLM calls to langfuse **Step 1** Install langfuse diff --git a/docs/my-website/docs/text_completion.md b/docs/my-website/docs/text_completion.md index 8be40dfdcd2..cbf2db00a0a 100644 --- a/docs/my-website/docs/text_completion.md +++ b/docs/my-website/docs/text_completion.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Text Completion +# /completions ### Usage diff --git a/docs/my-website/docs/text_to_speech.md b/docs/my-website/docs/text_to_speech.md index 0e7b436a3fd..e7e5c6d1638 100644 --- a/docs/my-website/docs/text_to_speech.md +++ b/docs/my-website/docs/text_to_speech.md @@ -1,4 +1,8 @@ -# Text to Speech +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# /audio/speech ## **LiteLLM Python SDK Usage** ### Quick Start diff --git a/docs/my-website/docs/tutorials/compare_llms.md b/docs/my-website/docs/tutorials/compare_llms.md index a7eda2c85fd..d7fdf8d7d93 100644 --- a/docs/my-website/docs/tutorials/compare_llms.md +++ b/docs/my-website/docs/tutorials/compare_llms.md @@ -117,7 +117,7 @@ response = completion("command-nightly", messages) """ -# qustions/logs you want to run the LLM on +# questions/logs you want to run the LLM on questions = [ "what is litellm?", "why should I use LiteLLM", diff --git a/docs/my-website/docs/tutorials/gemini_realtime_with_audio.md b/docs/my-website/docs/tutorials/gemini_realtime_with_audio.md new file mode 100644 index 00000000000..e6814c56900 --- /dev/null +++ b/docs/my-website/docs/tutorials/gemini_realtime_with_audio.md @@ -0,0 +1,136 @@ +# Call Gemini Realtime API with Audio Input/Output + +:::info +Requires LiteLLM Proxy v1.70.1+ +::: + +1. Setup config.yaml for LiteLLM Proxy + +```yaml +model_list: + - model_name: "gemini-2.0-flash" + litellm_params: + model: gemini/gemini-2.0-flash-live-001 + model_info: + mode: realtime +``` + +2. Start LiteLLM Proxy + +```bash +litellm-proxy start +``` + +3. Run test script + +```python +import asyncio +import websockets +import json +import base64 +from dotenv import load_dotenv +import wave +import base64 +import soundfile as sf +import sounddevice as sd +import io +import numpy as np + +# Load environment variables + +OPENAI_API_KEY = "sk-1234" # Replace with your LiteLLM API key +OPENAI_API_URL = 'ws://{PROXY_URL}/v1/realtime?model=gemini-2.0-flash' # REPLACE WITH `wss://{PROXY_URL}/v1/realtime?model=gemini-2.0-flash` for secure connection +WAV_FILE_PATH = "/path/to/audio.wav" # Replace with your .wav file path + +async def send_session_update(ws): + session_update = { + "type": "session.update", + "session": { + "conversation_id": "123456", + "language": "en-US", + "transcription_mode": "fast", + "modalities": ["text"] + } + } + await ws.send(json.dumps(session_update)) + +async def send_audio_file(ws, file_path): + with wave.open(file_path, 'rb') as wav_file: + chunk_size = 1024 # Adjust as needed + while True: + chunk = wav_file.readframes(chunk_size) + if not chunk: + break + base64_audio = base64.b64encode(chunk).decode('utf-8') + audio_message = { + "type": "input_audio_buffer.append", + "audio": base64_audio + } + await ws.send(json.dumps(audio_message)) + await asyncio.sleep(0.1) # Add a small delay to simulate real-time streaming + + # Send end of audio stream message + await ws.send(json.dumps({"type": "input_audio_buffer.end"})) + +def play_base64_audio(base64_string, sample_rate=24000, channels=1): + # Decode the base64 string + audio_data = base64.b64decode(base64_string) + + # Convert to numpy array + audio_np = np.frombuffer(audio_data, dtype=np.int16) + + # Reshape if stereo + if channels == 2: + audio_np = audio_np.reshape(-1, 2) + + # Normalize + audio_float = audio_np.astype(np.float32) / 32768.0 + + # Play the audio + sd.play(audio_float, sample_rate) + sd.wait() + + +def combine_base64_audio(base64_strings): + # Step 1: Decode base64 strings to binary + binary_data = [base64.b64decode(s) for s in base64_strings] + + # Step 2: Concatenate binary data + combined_binary = b''.join(binary_data) + + # Step 3: Encode combined binary back to base64 + combined_base64 = base64.b64encode(combined_binary).decode('utf-8') + + return combined_base64 + +async def listen_in_background(ws): + combined_b64_audio_str = [] + try: + while True: + response = await ws.recv() + message_json = json.loads(response) + print(f"message_json: {message_json}") + + if message_json['type'] == 'response.audio.delta' and message_json.get('delta'): + play_base64_audio(message_json["delta"]) + except Exception: + print("END OF STREAM") + +async def main(): + async with websockets.connect( + OPENAI_API_URL, + additional_headers={ + "Authorization": f"Bearer {OPENAI_API_KEY}", + "OpenAI-Beta": "realtime=v1" + } + ) as ws: + asyncio.create_task(listen_in_background(ws=ws)) + await send_session_update(ws) + await send_audio_file(ws, WAV_FILE_PATH) + + + +if __name__ == "__main__": + asyncio.run(main()) +``` + diff --git a/docs/my-website/docs/tutorials/google_adk.md b/docs/my-website/docs/tutorials/google_adk.md new file mode 100644 index 00000000000..81a3dacc153 --- /dev/null +++ b/docs/my-website/docs/tutorials/google_adk.md @@ -0,0 +1,324 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; + + +# Google ADK with LiteLLM + + +

+ Use Google ADK with LiteLLM Python SDK, LiteLLM Proxy +

+ + +This tutorial shows you how to create intelligent agents using Agent Development Kit (ADK) with support for multiple Large Language Model (LLM) providers with LiteLLM. + + + +## Overview + +ADK (Agent Development Kit) allows you to build intelligent agents powered by LLMs. By integrating with LiteLLM, you can: + +- Use multiple LLM providers (OpenAI, Anthropic, Google, etc.) +- Switch easily between models from different providers +- Connect to a LiteLLM proxy for centralized model management + +## Prerequisites + +- Python environment setup +- API keys for model providers (OpenAI, Anthropic, Google AI Studio) +- Basic understanding of LLMs and agent concepts + +## Installation + +```bash showLineNumbers title="Install dependencies" +pip install google-adk litellm +``` + +## 1. Setting Up Environment + +First, import the necessary libraries and set up your API keys: + +```python showLineNumbers title="Setup environment and API keys" +import os +import asyncio +from google.adk.agents import Agent +from google.adk.models.lite_llm import LiteLlm # For multi-model support +from google.adk.sessions import InMemorySessionService +from google.adk.runners import Runner +from google.genai import types +import litellm # Import for proxy configuration + +# Set your API keys +os.environ["GOOGLE_API_KEY"] = "your-google-api-key" # For Gemini models +os.environ["OPENAI_API_KEY"] = "your-openai-api-key" # For OpenAI models +os.environ["ANTHROPIC_API_KEY"] = "your-anthropic-api-key" # For Claude models + +# Define model constants for cleaner code +MODEL_GEMINI_PRO = "gemini-1.5-pro" +MODEL_GPT_4O = "openai/gpt-4o" +MODEL_CLAUDE_SONNET = "anthropic/claude-3-sonnet-20240229" +``` + +## 2. Define a Simple Tool + +Create a tool that your agent can use: + +```python showLineNumbers title="Weather tool implementation" +def get_weather(city: str) -> dict: + """Retrieves the current weather report for a specified city. + + Args: + city (str): The name of the city (e.g., "New York", "London", "Tokyo"). + + Returns: + dict: A dictionary containing the weather information. + Includes a 'status' key ('success' or 'error'). + If 'success', includes a 'report' key with weather details. + If 'error', includes an 'error_message' key. + """ + print(f"Tool: get_weather called for city: {city}") + + # Mock weather data + mock_weather_db = { + "newyork": {"status": "success", "report": "The weather in New York is sunny with a temperature of 25°C."}, + "london": {"status": "success", "report": "It's cloudy in London with a temperature of 15°C."}, + "tokyo": {"status": "success", "report": "Tokyo is experiencing light rain and a temperature of 18°C."}, + } + + city_normalized = city.lower().replace(" ", "") + + if city_normalized in mock_weather_db: + return mock_weather_db[city_normalized] + else: + return {"status": "error", "error_message": f"Sorry, I don't have weather information for '{city}'."} +``` + +## 3. Helper Function for Agent Interaction + +Create a helper function to facilitate agent interaction: + +```python showLineNumbers title="Agent interaction helper function" +async def call_agent_async(query: str, runner, user_id, session_id): + """Sends a query to the agent and prints the final response.""" + print(f"\n>>> User Query: {query}") + + # Prepare the user's message in ADK format + content = types.Content(role='user', parts=[types.Part(text=query)]) + + final_response_text = "Agent did not produce a final response." + + # Execute the agent and find the final response + async for event in runner.run_async( + user_id=user_id, + session_id=session_id, + new_message=content + ): + if event.is_final_response(): + if event.content and event.content.parts: + final_response_text = event.content.parts[0].text + break + + print(f"<<< Agent Response: {final_response_text}") +``` + +## 4. Using Different Model Providers with ADK + +### 4.1 Using OpenAI Models + +```python showLineNumbers title="OpenAI model implementation" +# Create an agent powered by OpenAI's GPT model +weather_agent_gpt = Agent( + name="weather_agent_gpt", + model=LiteLlm(model=MODEL_GPT_4O), # Use OpenAI's GPT model + description="Provides weather information using OpenAI's GPT.", + instruction="You are a helpful weather assistant powered by GPT-4o. " + "Use the 'get_weather' tool for city weather requests. " + "Present information clearly.", + tools=[get_weather], +) + +# Set up session and runner +session_service_gpt = InMemorySessionService() +session_gpt = session_service_gpt.create_session( + app_name="weather_app", + user_id="user_1", + session_id="session_gpt" +) + +runner_gpt = Runner( + agent=weather_agent_gpt, + app_name="weather_app", + session_service=session_service_gpt +) + +# Test the GPT agent +async def test_gpt_agent(): + print("\n--- Testing GPT Agent ---") + await call_agent_async( + "What's the weather in London?", + runner=runner_gpt, + user_id="user_1", + session_id="session_gpt" + ) + +# Execute the conversation with the GPT agent +await test_gpt_agent() + +# Or if running as a standard Python script: +# if __name__ == "__main__": +# asyncio.run(test_gpt_agent()) +``` + +### 4.2 Using Anthropic Models + +```python showLineNumbers title="Anthropic model implementation" +# Create an agent powered by Anthropic's Claude model +weather_agent_claude = Agent( + name="weather_agent_claude", + model=LiteLlm(model=MODEL_CLAUDE_SONNET), # Use Anthropic's Claude model + description="Provides weather information using Anthropic's Claude.", + instruction="You are a helpful weather assistant powered by Claude Sonnet. " + "Use the 'get_weather' tool for city weather requests. " + "Present information clearly.", + tools=[get_weather], +) + +# Set up session and runner +session_service_claude = InMemorySessionService() +session_claude = session_service_claude.create_session( + app_name="weather_app", + user_id="user_1", + session_id="session_claude" +) + +runner_claude = Runner( + agent=weather_agent_claude, + app_name="weather_app", + session_service=session_service_claude +) + +# Test the Claude agent +async def test_claude_agent(): + print("\n--- Testing Claude Agent ---") + await call_agent_async( + "What's the weather in Tokyo?", + runner=runner_claude, + user_id="user_1", + session_id="session_claude" + ) + +# Execute the conversation with the Claude agent +await test_claude_agent() + +# Or if running as a standard Python script: +# if __name__ == "__main__": +# asyncio.run(test_claude_agent()) +``` + +### 4.3 Using Google's Gemini Models + +```python showLineNumbers title="Gemini model implementation" +# Create an agent powered by Google's Gemini model +weather_agent_gemini = Agent( + name="weather_agent_gemini", + model=MODEL_GEMINI_PRO, # Use Gemini model directly (no LiteLlm wrapper needed) + description="Provides weather information using Google's Gemini.", + instruction="You are a helpful weather assistant powered by Gemini Pro. " + "Use the 'get_weather' tool for city weather requests. " + "Present information clearly.", + tools=[get_weather], +) + +# Set up session and runner +session_service_gemini = InMemorySessionService() +session_gemini = session_service_gemini.create_session( + app_name="weather_app", + user_id="user_1", + session_id="session_gemini" +) + +runner_gemini = Runner( + agent=weather_agent_gemini, + app_name="weather_app", + session_service=session_service_gemini +) + +# Test the Gemini agent +async def test_gemini_agent(): + print("\n--- Testing Gemini Agent ---") + await call_agent_async( + "What's the weather in New York?", + runner=runner_gemini, + user_id="user_1", + session_id="session_gemini" + ) + +# Execute the conversation with the Gemini agent +await test_gemini_agent() + +# Or if running as a standard Python script: +# if __name__ == "__main__": +# asyncio.run(test_gemini_agent()) +``` + +## 5. Using LiteLLM Proxy with ADK + +LiteLLM proxy provides a unified API endpoint for multiple models, simplifying deployment and centralized management. + +Required settings for using litellm proxy + +| Variable | Description | +|----------|-------------| +| `LITELLM_PROXY_API_KEY` | The API key for the LiteLLM proxy | +| `LITELLM_PROXY_API_BASE` | The base URL for the LiteLLM proxy | +| `USE_LITELLM_PROXY` or `litellm.use_litellm_proxy` | When set to True, your request will be sent to litellm proxy. | + +```python showLineNumbers title="LiteLLM proxy integration" +# Set your LiteLLM Proxy credentials as environment variables +os.environ["LITELLM_PROXY_API_KEY"] = "your-litellm-proxy-api-key" +os.environ["LITELLM_PROXY_API_BASE"] = "your-litellm-proxy-url" # e.g., "http://localhost:4000" +# Enable the use_litellm_proxy flag +litellm.use_litellm_proxy = True + +# Create a proxy-enabled agent (using environment variables) +weather_agent_proxy_env = Agent( + name="weather_agent_proxy_env", + model=LiteLlm(model="gpt-4o"), # this will call the `gpt-4o` model on LiteLLM proxy + description="Provides weather information using a model from LiteLLM proxy.", + instruction="You are a helpful weather assistant. " + "Use the 'get_weather' tool for city weather requests. " + "Present information clearly.", + tools=[get_weather], +) + +# Set up session and runner +session_service_proxy_env = InMemorySessionService() +session_proxy_env = session_service_proxy_env.create_session( + app_name="weather_app", + user_id="user_1", + session_id="session_proxy_env" +) + +runner_proxy_env = Runner( + agent=weather_agent_proxy_env, + app_name="weather_app", + session_service=session_service_proxy_env +) + +# Test the proxy-enabled agent (environment variables method) +async def test_proxy_env_agent(): + print("\n--- Testing Proxy-enabled Agent (Environment Variables) ---") + await call_agent_async( + "What's the weather in London?", + runner=runner_proxy_env, + user_id="user_1", + session_id="session_proxy_env" + ) + +# Execute the conversation +await test_proxy_env_agent() +``` diff --git a/docs/my-website/docs/tutorials/gradio_integration.md b/docs/my-website/docs/tutorials/gradio_integration.md index 4854fc2ac95..021815d9372 100644 --- a/docs/my-website/docs/tutorials/gradio_integration.md +++ b/docs/my-website/docs/tutorials/gradio_integration.md @@ -30,7 +30,7 @@ def inference(message, history): yield partial_message except Exception as e: print("Exception encountered:", str(e)) - yield f"An Error occured please 'Clear' the error and try your question again" + yield f"An Error occurred please 'Clear' the error and try your question again" ``` ### Define Chat Interface diff --git a/docs/my-website/docs/tutorials/instructor.md b/docs/my-website/docs/tutorials/instructor.md index d972aff9151..073215b47be 100644 --- a/docs/my-website/docs/tutorials/instructor.md +++ b/docs/my-website/docs/tutorials/instructor.md @@ -1,80 +1,73 @@ -# Instructor - Function Calling +# Instructor -Use LiteLLM with [jxnl's instructor library](https://github.com/jxnl/instructor) for function calling in prod. +Combine LiteLLM with [jxnl's instructor library](https://github.com/jxnl/instructor) for more robust structured outputs. Outputs are automatically validated into Pydantic types and validation errors are provided back to the model to increase the chance of a successful response in the retries. -## Usage +## Usage (Sync) ```python -import os - import instructor from litellm import completion from pydantic import BaseModel -os.environ["LITELLM_LOG"] = "DEBUG" # 👈 print DEBUG LOGS client = instructor.from_litellm(completion) -# import dotenv -# dotenv.load_dotenv() - -class UserDetail(BaseModel): +class User(BaseModel): name: str age: int -user = client.chat.completions.create( - model="gpt-4o-mini", - response_model=UserDetail, - messages=[ - {"role": "user", "content": "Extract Jason is 25 years old"}, - ], -) +def extract_user(text: str): + return client.chat.completions.create( + model="gpt-4o-mini", + response_model=User, + messages=[ + {"role": "user", "content": text}, + ], + max_retries=3, + ) -assert isinstance(user, UserDetail) +user = extract_user("Jason is 25 years old") + +assert isinstance(user, User) assert user.name == "Jason" assert user.age == 25 - -print(f"user: {user}") +print(f"{user=}") ``` -## Async Calls +## Usage (Async) ```python import asyncio + import instructor -from litellm import Router +from litellm import acompletion from pydantic import BaseModel -aclient = instructor.patch( - Router( - model_list=[ - { - "model_name": "gpt-4o-mini", - "litellm_params": {"model": "gpt-4o-mini"}, - } - ], - default_litellm_params={"acompletion": True}, # 👈 IMPORTANT - tells litellm to route to async completion function. - ) -) + +client = instructor.from_litellm(acompletion) -class UserExtract(BaseModel): +class User(BaseModel): name: str age: int -async def main(): - model = await aclient.chat.completions.create( +async def extract(text: str) -> User: + return await client.chat.completions.create( model="gpt-4o-mini", - response_model=UserExtract, + response_model=User, messages=[ - {"role": "user", "content": "Extract jason is 25 years old"}, + {"role": "user", "content": text}, ], + max_retries=3, ) - print(f"model: {model}") +user = asyncio.run(extract("Alice is 30 years old")) -asyncio.run(main()) -``` \ No newline at end of file +assert isinstance(user, User) +assert user.name == "Alice" +assert user.age == 30 +print(f"{user=}") +``` diff --git a/docs/my-website/docs/tutorials/litellm_proxy_aporia.md b/docs/my-website/docs/tutorials/litellm_proxy_aporia.md index 3b5bada2bce..143512f99c2 100644 --- a/docs/my-website/docs/tutorials/litellm_proxy_aporia.md +++ b/docs/my-website/docs/tutorials/litellm_proxy_aporia.md @@ -2,9 +2,9 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Use LiteLLM AI Gateway with Aporia Guardrails +# Aporia Guardrails with LiteLLM Gateway -In this tutorial we will use LiteLLM Proxy with Aporia to detect PII in requests and profanity in responses +In this tutorial we will use LiteLLM AI Gateway with Aporia to detect PII in requests and profanity in responses ## 1. Setup guardrails on Aporia diff --git a/docs/my-website/docs/tutorials/lm_evaluation_harness.md b/docs/my-website/docs/tutorials/lm_evaluation_harness.md index c28f2dac775..01fdb4b304c 100644 --- a/docs/my-website/docs/tutorials/lm_evaluation_harness.md +++ b/docs/my-website/docs/tutorials/lm_evaluation_harness.md @@ -39,7 +39,7 @@ pip install openai==0.28.01 **Step 3: Set OpenAI API Base & Key** ```shell -$ export OPENAI_API_BASE=http://0.0.0.0:8000 +$ export OPENAI_BASE_URL=http://0.0.0.0:8000 ``` LM Harness requires you to set an OpenAI API key `OPENAI_API_SECRET_KEY` for running benchmarks @@ -74,7 +74,7 @@ $ litellm --model huggingface/bigcode/starcoder **Step 2: Set OpenAI API Base & Key** ```shell -$ export OPENAI_API_BASE=http://0.0.0.0:8000 +$ export OPENAI_BASE_URL=http://0.0.0.0:8000 ``` Set this to anything since the proxy has the credentials @@ -93,12 +93,12 @@ cd FastEval **Set API Base on FastEval** -On FastEval make the following **2 line code change** to set `OPENAI_API_BASE` +On FastEval make the following **2 line code change** to set `OPENAI_BASE_URL` https://github.com/FastEval/FastEval/pull/90/files ```python try: - api_base = os.environ["OPENAI_API_BASE"] #changed: read api base from .env + api_base = os.environ["OPENAI_BASE_URL"] #changed: read api base from .env if api_base == None: api_base = "https://api.openai.com/v1" response = await self.reply_two_attempts_with_different_max_new_tokens( @@ -130,7 +130,7 @@ $ litellm --model huggingface/bigcode/starcoder **Step 2: Set OpenAI API Base & Key** ```shell -$ export OPENAI_API_BASE=http://0.0.0.0:8000 +$ export OPENAI_BASE_URL=http://0.0.0.0:8000 ``` **Step 3 Run with FLASK** diff --git a/docs/my-website/docs/tutorials/msft_sso.md b/docs/my-website/docs/tutorials/msft_sso.md new file mode 100644 index 00000000000..f7ad6440f2e --- /dev/null +++ b/docs/my-website/docs/tutorials/msft_sso.md @@ -0,0 +1,162 @@ +import Image from '@theme/IdealImage'; + +# Microsoft SSO: Sync Groups, Members with LiteLLM + +Sync Microsoft SSO Groups, Members with LiteLLM Teams. + + + +
+
+ + +## Prerequisites + +- An Azure Entra ID account with administrative access +- A LiteLLM Enterprise App set up in your Azure Portal +- Access to Microsoft Entra ID (Azure AD) + + +## Overview of this tutorial + +1. Auto-Create Entra ID Groups on LiteLLM Teams +2. Sync Entra ID Team Memberships +3. Set default params for new teams and users auto-created on LiteLLM + +## 1. Auto-Create Entra ID Groups on LiteLLM Teams + +In this step, our goal is to have LiteLLM automatically create a new team on the LiteLLM DB when there is a new Group Added to the LiteLLM Enterprise App on Azure Entra ID. + +### 1.1 Create a new group in Entra ID + + +Navigate to [your Azure Portal](https://portal.azure.com/) > Groups > New Group. Create a new group. + + + +### 1.2 Assign the group to your LiteLLM Enterprise App + +On your Azure Portal, navigate to `Enterprise Applications` > Select your litellm app + + + +
+
+ +Once you've selected your litellm app, click on `Users and Groups` > `Add user/group` + + + +
+ +Now select the group you created in step 1.1. And add it to the LiteLLM Enterprise App. At this point we have added `Production LLM Evals Group` to the LiteLLM Enterprise App. The next steps is having LiteLLM automatically create the `Production LLM Evals Group` on the LiteLLM DB when a new user signs in. + + + + +### 1.3 Sign in to LiteLLM UI via SSO + +Sign into the LiteLLM UI via SSO. You should be redirected to the Entra ID SSO page. This SSO sign in flow will trigger LiteLLM to fetch the latest Groups and Members from Azure Entra ID. + + + +### 1.4 Check the new team on LiteLLM UI + +On the LiteLLM UI, Navigate to `Teams`, You should see the new team `Production LLM Evals Group` auto-created on LiteLLM. + + + +#### How this works + +When a SSO user signs in to LiteLLM: +- LiteLLM automatically fetches the Groups under the LiteLLM Enterprise App +- It finds the Production LLM Evals Group assigned to the LiteLLM Enterprise App +- LiteLLM checks if this group's ID exists in the LiteLLM Teams Table +- Since the ID doesn't exist, LiteLLM automatically creates a new team with: + - Name: Production LLM Evals Group + - ID: Same as the Entra ID group's ID + +## 2. Sync Entra ID Team Memberships + +In this step, we will have LiteLLM automatically add a user to the `Production LLM Evals` Team on the LiteLLM DB when a new user is added to the `Production LLM Evals` Group in Entra ID. + +### 2.1 Navigate to the `Production LLM Evals` Group in Entra ID + +Navigate to the `Production LLM Evals` Group in Entra ID. + + + + +### 2.2 Add a member to the group in Entra ID + +Select `Members` > `Add members` + +In this stage you should add the user you want to add to the `Production LLM Evals` Team. + + + + + +### 2.3 Sign in as the new user on LiteLLM UI + +Sign in as the new user on LiteLLM UI. You should be redirected to the Entra ID SSO page. This SSO sign in flow will trigger LiteLLM to fetch the latest Groups and Members from Azure Entra ID. During this step LiteLLM sync it's teams, team members with what is available from Entra ID + + + + + +### 2.4 Check the team membership on LiteLLM UI + +On the LiteLLM UI, Navigate to `Teams`, You should see the new team `Production LLM Evals Group`. Since your are now a member of the `Production LLM Evals Group` in Entra ID, you should see the new team `Production LLM Evals Group` on the LiteLLM UI. + + + +## 3. Set default params for new teams auto-created on LiteLLM + +Since litellm auto creates a new team on the LiteLLM DB when there is a new Group Added to the LiteLLM Enterprise App on Azure Entra ID, we can set default params for new teams created. + +This allows you to set a default budget, models, etc for new teams created. + +### 3.1 Set `default_team_params` on litellm + +Navigate to your litellm config file and set the following params + +```yaml showLineNumbers title="litellm config with default_team_params" +litellm_settings: + default_team_params: # Default Params to apply when litellm auto creates a team from SSO IDP provider + max_budget: 100 # Optional[float], optional): $100 budget for the team + budget_duration: 30d # Optional[str], optional): 30 days budget_duration for the team + models: ["gpt-3.5-turbo"] # Optional[List[str]], optional): models to be used by the team +``` + +### 3.2 Auto-create a new team on LiteLLM + +- In this step you should add a new group to the LiteLLM Enterprise App on Azure Entra ID (like we did in step 1.1). We will call this group `Default LiteLLM Prod Team` on Azure Entra ID. +- Start litellm proxy server with your config +- Sign into LiteLLM UI via SSO +- Navigate to `Teams` and you should see the new team `Default LiteLLM Prod Team` auto-created on LiteLLM +- Note LiteLLM will set the default params for this new team. + + + + +## Video Walkthrough + +This walks through setting up sso auto-add for **Microsoft Entra ID** + +Follow along this video for a walkthrough of how to set this up with Microsoft Entra ID + + + + + + + + + + + + + + + diff --git a/docs/my-website/docs/tutorials/openai_codex.md b/docs/my-website/docs/tutorials/openai_codex.md new file mode 100644 index 00000000000..bb5af956b0c --- /dev/null +++ b/docs/my-website/docs/tutorials/openai_codex.md @@ -0,0 +1,146 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Using LiteLLM with OpenAI Codex + +This guide walks you through connecting OpenAI Codex to LiteLLM. Using LiteLLM with Codex allows teams to: +- Access 100+ LLMs through the Codex interface +- Use powerful models like Gemini through a familiar interface +- Track spend and usage with LiteLLM's built-in analytics +- Control model access with virtual keys + + + +## Quickstart + +:::info + +Requires LiteLLM v1.66.3.dev5 and higher + +::: + + +Make sure to set up LiteLLM with the [LiteLLM Getting Started Guide](../proxy/docker_quick_start.md). + +## 1. Install OpenAI Codex + +Install the OpenAI Codex CLI tool globally using npm: + + + + +```bash showLineNumbers +npm i -g @openai/codex +``` + + + + +```bash showLineNumbers +yarn global add @openai/codex +``` + + + + +## 2. Start LiteLLM Proxy + + + + +```bash showLineNumbers +docker run \ + -v $(pwd)/litellm_config.yaml:/app/config.yaml \ + -p 4000:4000 \ + ghcr.io/berriai/litellm:main-latest \ + --config /app/config.yaml +``` + + + + +```bash showLineNumbers +litellm --config /path/to/config.yaml +``` + + + + +LiteLLM should now be running on [http://localhost:4000](http://localhost:4000) + +## 3. Configure LiteLLM for Model Routing + +Ensure your LiteLLM Proxy is properly configured to route to your desired models. Create a `litellm_config.yaml` file with the following content: + +```yaml showLineNumbers +model_list: + - model_name: o3-mini + litellm_params: + model: openai/o3-mini + api_key: os.environ/OPENAI_API_KEY + - model_name: claude-3-7-sonnet-latest + litellm_params: + model: anthropic/claude-3-7-sonnet-latest + api_key: os.environ/ANTHROPIC_API_KEY + - model_name: gemini-2.0-flash + litellm_params: + model: gemini/gemini-2.0-flash + api_key: os.environ/GEMINI_API_KEY + +litellm_settings: + drop_params: true +``` + +This configuration enables routing to specific OpenAI, Anthropic, and Gemini models with explicit names. + +## 4. Configure Codex to Use LiteLLM Proxy + +Set the required environment variables to point Codex to your LiteLLM Proxy: + +```bash +# Point to your LiteLLM Proxy server +export OPENAI_BASE_URL=http://0.0.0.0:4000 + +# Use your LiteLLM API key (if you've set up authentication) +export OPENAI_API_KEY="sk-1234" +``` + +## 5. Run Codex with Gemini + +With everything configured, you can now run Codex with Gemini: + +```bash showLineNumbers +codex --model gemini-2.0-flash --full-auto +``` + + + +The `--full-auto` flag allows Codex to automatically generate code without additional prompting. + +## 6. Advanced Options + +### Using Different Models + +You can use any model configured in your LiteLLM proxy: + +```bash +# Use Claude models +codex --model claude-3-7-sonnet-latest + +# Use Google AI Studio Gemini models +codex --model gemini/gemini-2.0-flash +``` + +## Troubleshooting + +- If you encounter connection issues, ensure your LiteLLM Proxy is running and accessible at the specified URL +- Verify your LiteLLM API key is valid if you're using authentication +- Check that your model routing configuration is correct +- For model-specific errors, ensure the model is properly configured in your LiteLLM setup + +## Additional Resources + +- [LiteLLM Docker Quick Start Guide](../proxy/docker_quick_start.md) +- [OpenAI Codex GitHub Repository](https://github.com/openai/codex) +- [LiteLLM Virtual Keys and Authentication](../proxy/virtual_keys.md) diff --git a/docs/my-website/docs/tutorials/openweb_ui.md b/docs/my-website/docs/tutorials/openweb_ui.md new file mode 100644 index 00000000000..82ff475add9 --- /dev/null +++ b/docs/my-website/docs/tutorials/openweb_ui.md @@ -0,0 +1,137 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Open WebUI with LiteLLM + +This guide walks you through connecting Open WebUI to LiteLLM. Using LiteLLM with Open WebUI allows teams to +- Access 100+ LLMs on Open WebUI +- Track Spend / Usage, Set Budget Limits +- Send Request/Response Logs to logging destinations like langfuse, s3, gcs buckets, etc. +- Set access controls eg. Control what models Open WebUI can access. + +## Quickstart + +- Make sure to setup LiteLLM with the [LiteLLM Getting Started Guide](https://docs.litellm.ai/docs/proxy/docker_quick_start) + + +## 1. Start LiteLLM & Open WebUI + +- Open WebUI starts running on [http://localhost:3000](http://localhost:3000) +- LiteLLM starts running on [http://localhost:4000](http://localhost:4000) + + +## 2. Create a Virtual Key on LiteLLM + +Virtual Keys are API Keys that allow you to authenticate to LiteLLM Proxy. We will create a Virtual Key that will allow Open WebUI to access LiteLLM. + +### 2.1 LiteLLM User Management Hierarchy + +On LiteLLM, you can create Organizations, Teams, Users and Virtual Keys. For this tutorial, we will create a Team and a Virtual Key. + +- `Organization` - An Organization is a group of Teams. (US Engineering, EU Developer Tools) +- `Team` - A Team is a group of Users. (Open WebUI Team, Data Science Team, etc.) +- `User` - A User is an individual user (employee, developer, eg. `krrish@litellm.ai`) +- `Virtual Key` - A Virtual Key is an API Key that allows you to authenticate to LiteLLM Proxy. A Virtual Key is associated with a User or Team. + +Once the Team is created, you can invite Users to the Team. You can read more about LiteLLM's User Management [here](https://docs.litellm.ai/docs/proxy/user_management_heirarchy). + +### 2.2 Create a Team on LiteLLM + +Navigate to [http://localhost:4000/ui](http://localhost:4000/ui) and create a new team. + + + +### 2.2 Create a Virtual Key on LiteLLM + +Navigate to [http://localhost:4000/ui](http://localhost:4000/ui) and create a new virtual Key. + +LiteLLM allows you to specify what models are available on Open WebUI (by specifying the models the key will have access to). + + + +## 3. Connect Open WebUI to LiteLLM + +On Open WebUI, navigate to Settings -> Connections and create a new connection to LiteLLM + +Enter the following details: +- URL: `http://localhost:4000` (your litellm proxy base url) +- Key: `your-virtual-key` (the key you created in the previous step) + + + +### 3.1 Test Request + +On the top left corner, select models you should only see the models you gave the key access to in Step 2. + +Once you selected a model, enter your message content and click on `Submit` + + + +### 3.2 Tracking Usage & Spend + +#### Basic Tracking + +After making requests, navigate to the `Logs` section in the LiteLLM UI to view Model, Usage and Cost information. + +#### Per-User Tracking + +To track spend and usage for each Open WebUI user, configure both Open WebUI and LiteLLM: + +1. **Enable User Info Headers in Open WebUI** + + Set the following environment variable for Open WebUI to enable user information in request headers: + ```dotenv + ENABLE_FORWARD_USER_INFO_HEADERS=True + ``` + + For more details, see the [Environment Variable Configuration Guide](https://docs.openwebui.com/getting-started/env-configuration/#enable_forward_user_info_headers). + +2. **Configure LiteLLM to Parse User Headers** + + Add the following to your LiteLLM `config.yaml` to specify a header to use for user tracking: + + ```yaml + general_settings: + user_header_name: X-OpenWebUI-User-Id + ``` + + ⓘ Available tracking options + + You can use any of the following headers for `user_header_name`: + - `X-OpenWebUI-User-Id` + - `X-OpenWebUI-User-Email` + - `X-OpenWebUI-User-Name` + + These may offer better readability and easier mental attribution when hosting for a small group of users that you know well. + + Choose based on your needs, but note that in Open WebUI: + - Users can modify their own usernames + - Administrators can modify both usernames and emails of any account + + + +## Render `thinking` content on Open WebUI + +Open WebUI requires reasoning/thinking content to be rendered with `` tags. In order to render this for specific models, you can use the `merge_reasoning_content_in_choices` litellm parameter. + +Example litellm config.yaml: + +```yaml +model_list: + - model_name: thinking-anthropic-claude-3-7-sonnet + litellm_params: + model: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0 + thinking: {"type": "enabled", "budget_tokens": 1024} + max_tokens: 1080 + merge_reasoning_content_in_choices: true +``` + +### Test it on Open WebUI + +On the models dropdown select `thinking-anthropic-claude-3-7-sonnet` + + + +## Additional Resources +- Running LiteLLM and Open WebUI on Windows Localhost: A Comprehensive Guide [https://www.tanyongsheng.com/note/running-litellm-and-openwebui-on-windows-localhost-a-comprehensive-guide/](https://www.tanyongsheng.com/note/running-litellm-and-openwebui-on-windows-localhost-a-comprehensive-guide/) diff --git a/docs/my-website/docs/tutorials/prompt_caching.md b/docs/my-website/docs/tutorials/prompt_caching.md new file mode 100644 index 00000000000..bf3d5a8dda7 --- /dev/null +++ b/docs/my-website/docs/tutorials/prompt_caching.md @@ -0,0 +1,128 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Auto-Inject Prompt Caching Checkpoints + +Reduce costs by up to 90% by using LiteLLM to auto-inject prompt caching checkpoints. + + + + +## How it works + +LiteLLM can automatically inject prompt caching checkpoints into your requests to LLM providers. This allows: + +- **Cost Reduction**: Long, static parts of your prompts can be cached to avoid repeated processing +- **No need to modify your application code**: You can configure the auto-caching behavior in the LiteLLM UI or in the `litellm config.yaml` file. + +## Configuration + +You need to specify `cache_control_injection_points` in your model configuration. This tells LiteLLM: +1. Where to add the caching directive (`location`) +2. Which message to target (`role`) + +LiteLLM will then automatically add a `cache_control` directive to the specified messages in your requests: + +```json +"cache_control": { + "type": "ephemeral" +} +``` + +## Usage Example + +In this example, we'll configure caching for system messages by adding the directive to all messages with `role: system`. + + + + +```yaml showLineNumbers title="litellm config.yaml" +model_list: + - model_name: anthropic-auto-inject-cache-system-message + litellm_params: + model: anthropic/claude-3-5-sonnet-20240620 + api_key: os.environ/ANTHROPIC_API_KEY + cache_control_injection_points: + - location: message + role: system +``` + + + + +On the LiteLLM UI, you can specify the `cache_control_injection_points` in the `Advanced Settings` tab when adding a model. + + + + + + +## Detailed Example + +### 1. Original Request to LiteLLM + +In this example, we have a very long, static system message and a varying user message. It's efficient to cache the system message since it rarely changes. + +```json +{ + "messages": [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": "You are a helpful assistant. This is a set of very long instructions that you will follow. Here is a legal document that you will use to answer the user's question." + } + ] + }, + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What is the main topic of this legal document?" + } + ] + } + ] +} +``` + +### 2. LiteLLM's Modified Request + +LiteLLM auto-injects the caching directive into the system message based on our configuration: + +```json +{ + "messages": [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": "You are a helpful assistant. This is a set of very long instructions that you will follow. Here is a legal document that you will use to answer the user's question.", + "cache_control": {"type": "ephemeral"} + } + ] + }, + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What is the main topic of this legal document?" + } + ] + } + ] +} +``` + +When the model provider processes this request, it will recognize the caching directive and only process the system message once, caching it for subsequent requests. + + + + + + diff --git a/docs/my-website/docs/tutorials/scim_litellm.md b/docs/my-website/docs/tutorials/scim_litellm.md new file mode 100644 index 00000000000..c744abe4b49 --- /dev/null +++ b/docs/my-website/docs/tutorials/scim_litellm.md @@ -0,0 +1,74 @@ + +import Image from '@theme/IdealImage'; + +# SCIM with LiteLLM + +Enables identity providers (Okta, Azure AD, OneLogin, etc.) to automate user and team (group) provisioning, updates, and deprovisioning on LiteLLM. + + +This tutorial will walk you through the steps to connect your IDP to LiteLLM SCIM Endpoints. + +### Supported SSO Providers for SCIM +Below is a list of supported SSO providers for connecting to LiteLLM SCIM Endpoints. +- Microsoft Entra ID (Azure AD) +- Okta +- Google Workspace +- OneLogin +- Keycloak +- Auth0 + + +## 1. Get your SCIM Tenant URL and Bearer Token + +On LiteLLM, navigate to the Settings > Admin Settings > SCIM. On this page you will create a SCIM Token, this allows your IDP to authenticate to litellm `/scim` endpoints. + + + +## 2. Connect your IDP to LiteLLM SCIM Endpoints + +On your IDP provider, navigate to your SSO application and select `Provisioning` > `New provisioning configuration`. + +On this page, paste in your litellm scim tenant url and bearer token. + +Once this is pasted in, click on `Test Connection` to ensure your IDP can authenticate to the LiteLLM SCIM endpoints. + + + + +## 3. Test SCIM Connection + +### 3.1 Assign the group to your LiteLLM Enterprise App + +On your IDP Portal, navigate to `Enterprise Applications` > Select your litellm app + + + +
+
+ +Once you've selected your litellm app, click on `Users and Groups` > `Add user/group` + + + +
+ +Now select the group you created in step 1.1. And add it to the LiteLLM Enterprise App. At this point we have added `Production LLM Evals Group` to the LiteLLM Enterprise App. The next step is having LiteLLM automatically create the `Production LLM Evals Group` on the LiteLLM DB when a new user signs in. + + + + +### 3.2 Sign in to LiteLLM UI via SSO + +Sign into the LiteLLM UI via SSO. You should be redirected to the Entra ID SSO page. This SSO sign in flow will trigger LiteLLM to fetch the latest Groups and Members from Azure Entra ID. + + + +### 3.3 Check the new team on LiteLLM UI + +On the LiteLLM UI, Navigate to `Teams`, You should see the new team `Production LLM Evals Group` auto-created on LiteLLM. + + + + + + diff --git a/docs/my-website/docs/tutorials/tag_management.md b/docs/my-website/docs/tutorials/tag_management.md new file mode 100644 index 00000000000..9b00db47d14 --- /dev/null +++ b/docs/my-website/docs/tutorials/tag_management.md @@ -0,0 +1,145 @@ +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# [Beta] Routing based on request metadata + +Create routing rules based on request metadata. + +## Setup + +Add the following to your litellm proxy config yaml file. + +```yaml showLineNumbers title="litellm proxy config.yaml" +router_settings: + enable_tag_filtering: True # 👈 Key Change +``` + +## 1. Create a tag + +On the LiteLLM UI, navigate to Experimental > Tag Management > Create Tag. + +Create a tag called `private-data` and only select the allowed models for requests with this tag. Once created, you will see the tag in the Tag Management page. + + + + +## 2. Test Tag Routing + +Now we will test the tag based routing rules. + +### 2.1 Invalid model + +This request will fail since we send `tags=private-data` but the model `gpt-4o` is not in the allowed models for the `private-data` tag. + + + +
+ +Here is an example sending the same request using the OpenAI Python SDK. + + + +```python showLineNumbers +from openai import OpenAI + +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000/v1/" +) + +response = client.chat.completions.create( + model="gpt-4o", + messages=[ + {"role": "user", "content": "Hello, how are you?"} + ], + extra_body={ + "tags": "private-data" + } +) +``` + + + + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "gpt-4o", + "messages": [ + { + "role": "user", + "content": "Hello, how are you?" + } + ], + "tags": "private-data" +}' +``` + + + + +
+ +### 2.2 Valid model + +This request will succeed since we send `tags=private-data` and the model `us.anthropic.claude-3-7-sonnet-20250219-v1:0` is in the allowed models for the `private-data` tag. + + + +Here is an example sending the same request using the OpenAI Python SDK. + + + + +```python showLineNumbers +from openai import OpenAI + +client = OpenAI( + api_key="sk-1234", + base_url="http://0.0.0.0:4000/v1/" +) + +response = client.chat.completions.create( + model="us.anthropic.claude-3-7-sonnet-20250219-v1:0", + messages=[ + {"role": "user", "content": "Hello, how are you?"} + ], + extra_body={ + "tags": "private-data" + } +) +``` + + + + +```bash +curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer sk-1234' \ +-d '{ + "model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0", + "messages": [ + { + "role": "user", + "content": "Hello, how are you?" + } + ], + "tags": "private-data" +}' +``` + + + + + + +## Additional Tag Features +- [Sending tags in request headers](https://docs.litellm.ai/docs/proxy/tag_routing#calling-via-request-header) +- [Tag based routing](https://docs.litellm.ai/docs/proxy/tag_routing) +- [Track spend per tag](cost_tracking#-custom-tags) +- [Setup Budgets per Virtual Key, Team](users) + diff --git a/docs/my-website/docusaurus.config.js b/docs/my-website/docusaurus.config.js index cf20dfcd70c..8d480131ff3 100644 --- a/docs/my-website/docusaurus.config.js +++ b/docs/my-website/docusaurus.config.js @@ -44,7 +44,7 @@ const config = { path: './release_notes', routeBasePath: 'release_notes', blogTitle: 'Release Notes', - blogSidebarTitle: 'All Releases', + blogSidebarTitle: 'Releases', blogSidebarCount: 'ALL', postsPerPage: 'ALL', showReadingTime: false, diff --git a/docs/my-website/img/arize.png b/docs/my-website/img/arize.png new file mode 100644 index 00000000000..45d6dacda90 Binary files /dev/null and b/docs/my-website/img/arize.png differ diff --git a/docs/my-website/img/auto_prompt_caching.png b/docs/my-website/img/auto_prompt_caching.png new file mode 100644 index 00000000000..6cd37855126 Binary files /dev/null and b/docs/my-website/img/auto_prompt_caching.png differ diff --git a/docs/my-website/img/basic_litellm.gif b/docs/my-website/img/basic_litellm.gif new file mode 100644 index 00000000000..d4cf9fd52af Binary files /dev/null and b/docs/my-website/img/basic_litellm.gif differ diff --git a/docs/my-website/img/callback_api.png b/docs/my-website/img/callback_api.png new file mode 100644 index 00000000000..b123dae2620 Binary files /dev/null and b/docs/my-website/img/callback_api.png differ diff --git a/docs/my-website/img/create_key_in_team_oweb.gif b/docs/my-website/img/create_key_in_team_oweb.gif new file mode 100644 index 00000000000..d24849b259c Binary files /dev/null and b/docs/my-website/img/create_key_in_team_oweb.gif differ diff --git a/docs/my-website/img/custom_prompt_management.png b/docs/my-website/img/custom_prompt_management.png new file mode 100644 index 00000000000..2c96e0d116e Binary files /dev/null and b/docs/my-website/img/custom_prompt_management.png differ diff --git a/docs/my-website/img/deadlock_fix_1.png b/docs/my-website/img/deadlock_fix_1.png new file mode 100644 index 00000000000..df651f440c4 Binary files /dev/null and b/docs/my-website/img/deadlock_fix_1.png differ diff --git a/docs/my-website/img/deadlock_fix_2.png b/docs/my-website/img/deadlock_fix_2.png new file mode 100644 index 00000000000..0f139d84e55 Binary files /dev/null and b/docs/my-website/img/deadlock_fix_2.png differ diff --git a/docs/my-website/img/debug_sso.png b/docs/my-website/img/debug_sso.png new file mode 100644 index 00000000000..d7dde368920 Binary files /dev/null and b/docs/my-website/img/debug_sso.png differ diff --git a/docs/my-website/img/delete_spend_logs.jpg b/docs/my-website/img/delete_spend_logs.jpg new file mode 100644 index 00000000000..6fa0f04b657 Binary files /dev/null and b/docs/my-website/img/delete_spend_logs.jpg differ diff --git a/docs/my-website/img/email_2.png b/docs/my-website/img/email_2.png new file mode 100644 index 00000000000..d686022824e Binary files /dev/null and b/docs/my-website/img/email_2.png differ diff --git a/docs/my-website/img/email_2_0.png b/docs/my-website/img/email_2_0.png new file mode 100644 index 00000000000..3e2c5d59db9 Binary files /dev/null and b/docs/my-website/img/email_2_0.png differ diff --git a/docs/my-website/img/email_event_1.png b/docs/my-website/img/email_event_1.png new file mode 100644 index 00000000000..edbb0a80931 Binary files /dev/null and b/docs/my-website/img/email_event_1.png differ diff --git a/docs/my-website/img/email_event_2.png b/docs/my-website/img/email_event_2.png new file mode 100644 index 00000000000..b4ef1f49c2e Binary files /dev/null and b/docs/my-website/img/email_event_2.png differ diff --git a/docs/my-website/img/enterprise_vs_oss.png b/docs/my-website/img/enterprise_vs_oss.png new file mode 100644 index 00000000000..f2b58fbc14a Binary files /dev/null and b/docs/my-website/img/enterprise_vs_oss.png differ diff --git a/docs/my-website/img/entra_create_team.png b/docs/my-website/img/entra_create_team.png new file mode 100644 index 00000000000..223a897d879 Binary files /dev/null and b/docs/my-website/img/entra_create_team.png differ diff --git a/docs/my-website/img/gemini_realtime.png b/docs/my-website/img/gemini_realtime.png new file mode 100644 index 00000000000..2311a63f7d3 Binary files /dev/null and b/docs/my-website/img/gemini_realtime.png differ diff --git a/docs/my-website/img/hf_filter_inference_providers.png b/docs/my-website/img/hf_filter_inference_providers.png new file mode 100644 index 00000000000..d4c71889198 Binary files /dev/null and b/docs/my-website/img/hf_filter_inference_providers.png differ diff --git a/docs/my-website/img/image_handling.png b/docs/my-website/img/image_handling.png new file mode 100644 index 00000000000..bd56206911c Binary files /dev/null and b/docs/my-website/img/image_handling.png differ diff --git a/docs/my-website/img/kb.png b/docs/my-website/img/kb.png new file mode 100644 index 00000000000..ba35e7a8a0f Binary files /dev/null and b/docs/my-website/img/kb.png differ diff --git a/docs/my-website/img/kb_2.png b/docs/my-website/img/kb_2.png new file mode 100644 index 00000000000..0cce544a9fe Binary files /dev/null and b/docs/my-website/img/kb_2.png differ diff --git a/docs/my-website/img/kb_3.png b/docs/my-website/img/kb_3.png new file mode 100644 index 00000000000..5e169e16f40 Binary files /dev/null and b/docs/my-website/img/kb_3.png differ diff --git a/docs/my-website/img/kb_4.png b/docs/my-website/img/kb_4.png new file mode 100644 index 00000000000..7927a7f2e1d Binary files /dev/null and b/docs/my-website/img/kb_4.png differ diff --git a/docs/my-website/img/key_email.png b/docs/my-website/img/key_email.png new file mode 100644 index 00000000000..c4108b7a743 Binary files /dev/null and b/docs/my-website/img/key_email.png differ diff --git a/docs/my-website/img/key_email_2.png b/docs/my-website/img/key_email_2.png new file mode 100644 index 00000000000..d591ce03e8a Binary files /dev/null and b/docs/my-website/img/key_email_2.png differ diff --git a/docs/my-website/img/litellm_adk.png b/docs/my-website/img/litellm_adk.png new file mode 100644 index 00000000000..7d79b94f3b1 Binary files /dev/null and b/docs/my-website/img/litellm_adk.png differ diff --git a/docs/my-website/img/litellm_codex.gif b/docs/my-website/img/litellm_codex.gif new file mode 100644 index 00000000000..04332b5053d Binary files /dev/null and b/docs/my-website/img/litellm_codex.gif differ diff --git a/docs/my-website/img/litellm_create_team.gif b/docs/my-website/img/litellm_create_team.gif new file mode 100644 index 00000000000..e2f12613ec0 Binary files /dev/null and b/docs/my-website/img/litellm_create_team.gif differ diff --git a/docs/my-website/img/litellm_entra_id.png b/docs/my-website/img/litellm_entra_id.png new file mode 100644 index 00000000000..4cfbd0747fc Binary files /dev/null and b/docs/my-website/img/litellm_entra_id.png differ diff --git a/docs/my-website/img/litellm_mcp.png b/docs/my-website/img/litellm_mcp.png new file mode 100644 index 00000000000..cef822eeb22 Binary files /dev/null and b/docs/my-website/img/litellm_mcp.png differ diff --git a/docs/my-website/img/litellm_setup_openweb.gif b/docs/my-website/img/litellm_setup_openweb.gif new file mode 100644 index 00000000000..5618660d6c4 Binary files /dev/null and b/docs/my-website/img/litellm_setup_openweb.gif differ diff --git a/docs/my-website/img/litellm_thinking_openweb.gif b/docs/my-website/img/litellm_thinking_openweb.gif new file mode 100644 index 00000000000..385db583a42 Binary files /dev/null and b/docs/my-website/img/litellm_thinking_openweb.gif differ diff --git a/docs/my-website/img/litellm_user_heirarchy.png b/docs/my-website/img/litellm_user_heirarchy.png index 63dba72c21d..591b36add70 100644 Binary files a/docs/my-website/img/litellm_user_heirarchy.png and b/docs/my-website/img/litellm_user_heirarchy.png differ diff --git a/docs/my-website/img/managed_files_arch.png b/docs/my-website/img/managed_files_arch.png new file mode 100644 index 00000000000..e49c47334d0 Binary files /dev/null and b/docs/my-website/img/managed_files_arch.png differ diff --git a/docs/my-website/img/mcp_2.png b/docs/my-website/img/mcp_2.png new file mode 100644 index 00000000000..98e063efc5d Binary files /dev/null and b/docs/my-website/img/mcp_2.png differ diff --git a/docs/my-website/img/mcp_ui.png b/docs/my-website/img/mcp_ui.png new file mode 100644 index 00000000000..6731fba71be Binary files /dev/null and b/docs/my-website/img/mcp_ui.png differ diff --git a/docs/my-website/img/message_redaction_logging.png b/docs/my-website/img/message_redaction_logging.png new file mode 100644 index 00000000000..6e210ad182e Binary files /dev/null and b/docs/my-website/img/message_redaction_logging.png differ diff --git a/docs/my-website/img/message_redaction_spend_logs.png b/docs/my-website/img/message_redaction_spend_logs.png new file mode 100644 index 00000000000..eacfac2ece1 Binary files /dev/null and b/docs/my-website/img/message_redaction_spend_logs.png differ diff --git a/docs/my-website/img/msft_auto_team.png b/docs/my-website/img/msft_auto_team.png new file mode 100644 index 00000000000..a50c5bbfbd1 Binary files /dev/null and b/docs/my-website/img/msft_auto_team.png differ diff --git a/docs/my-website/img/msft_default_settings.png b/docs/my-website/img/msft_default_settings.png new file mode 100644 index 00000000000..0caa60b1f53 Binary files /dev/null and b/docs/my-website/img/msft_default_settings.png differ diff --git a/docs/my-website/img/msft_enterprise_app.png b/docs/my-website/img/msft_enterprise_app.png new file mode 100644 index 00000000000..0a8c849a5cd Binary files /dev/null and b/docs/my-website/img/msft_enterprise_app.png differ diff --git a/docs/my-website/img/msft_enterprise_assign_group.png b/docs/my-website/img/msft_enterprise_assign_group.png new file mode 100644 index 00000000000..d43e1c66845 Binary files /dev/null and b/docs/my-website/img/msft_enterprise_assign_group.png differ diff --git a/docs/my-website/img/msft_enterprise_select_group.png b/docs/my-website/img/msft_enterprise_select_group.png new file mode 100644 index 00000000000..e49032db9f4 Binary files /dev/null and b/docs/my-website/img/msft_enterprise_select_group.png differ diff --git a/docs/my-website/img/msft_member_1.png b/docs/my-website/img/msft_member_1.png new file mode 100644 index 00000000000..2fe627f773e Binary files /dev/null and b/docs/my-website/img/msft_member_1.png differ diff --git a/docs/my-website/img/msft_member_2.png b/docs/my-website/img/msft_member_2.png new file mode 100644 index 00000000000..9757aa9cea9 Binary files /dev/null and b/docs/my-website/img/msft_member_2.png differ diff --git a/docs/my-website/img/msft_member_3.png b/docs/my-website/img/msft_member_3.png new file mode 100644 index 00000000000..783a4a1dd84 Binary files /dev/null and b/docs/my-website/img/msft_member_3.png differ diff --git a/docs/my-website/img/msft_sso_sign_in.png b/docs/my-website/img/msft_sso_sign_in.png new file mode 100644 index 00000000000..43c5173295c Binary files /dev/null and b/docs/my-website/img/msft_sso_sign_in.png differ diff --git a/docs/my-website/img/multi_instance_rate_limiting.png b/docs/my-website/img/multi_instance_rate_limiting.png new file mode 100644 index 00000000000..56e944ddbf1 Binary files /dev/null and b/docs/my-website/img/multi_instance_rate_limiting.png differ diff --git a/docs/my-website/img/new_user_email.png b/docs/my-website/img/new_user_email.png new file mode 100644 index 00000000000..1a4d44523b2 Binary files /dev/null and b/docs/my-website/img/new_user_email.png differ diff --git a/docs/my-website/img/pii_masking_v2.png b/docs/my-website/img/pii_masking_v2.png new file mode 100644 index 00000000000..597dc403fa6 Binary files /dev/null and b/docs/my-website/img/pii_masking_v2.png differ diff --git a/docs/my-website/img/presidio_1.png b/docs/my-website/img/presidio_1.png new file mode 100644 index 00000000000..6cc13cfacf2 Binary files /dev/null and b/docs/my-website/img/presidio_1.png differ diff --git a/docs/my-website/img/presidio_2.png b/docs/my-website/img/presidio_2.png new file mode 100644 index 00000000000..2bdab8821bd Binary files /dev/null and b/docs/my-website/img/presidio_2.png differ diff --git a/docs/my-website/img/presidio_3.png b/docs/my-website/img/presidio_3.png new file mode 100644 index 00000000000..7e6e0039d3a Binary files /dev/null and b/docs/my-website/img/presidio_3.png differ diff --git a/docs/my-website/img/presidio_4.png b/docs/my-website/img/presidio_4.png new file mode 100644 index 00000000000..b7732ba0fe1 Binary files /dev/null and b/docs/my-website/img/presidio_4.png differ diff --git a/docs/my-website/img/presidio_5.png b/docs/my-website/img/presidio_5.png new file mode 100644 index 00000000000..a0d903f8edc Binary files /dev/null and b/docs/my-website/img/presidio_5.png differ diff --git a/docs/my-website/img/prevent_deadlocks.jpg b/docs/my-website/img/prevent_deadlocks.jpg new file mode 100644 index 00000000000..2807f327d12 Binary files /dev/null and b/docs/my-website/img/prevent_deadlocks.jpg differ diff --git a/docs/my-website/img/realtime_api.png b/docs/my-website/img/realtime_api.png new file mode 100644 index 00000000000..798525278c9 Binary files /dev/null and b/docs/my-website/img/realtime_api.png differ diff --git a/docs/my-website/img/release_notes/anthropic_thinking.jpg b/docs/my-website/img/release_notes/anthropic_thinking.jpg new file mode 100644 index 00000000000..f10de06deca Binary files /dev/null and b/docs/my-website/img/release_notes/anthropic_thinking.jpg differ diff --git a/docs/my-website/img/release_notes/bedrock_kb.png b/docs/my-website/img/release_notes/bedrock_kb.png new file mode 100644 index 00000000000..86efa5ecb6c Binary files /dev/null and b/docs/my-website/img/release_notes/bedrock_kb.png differ diff --git a/docs/my-website/img/release_notes/chat_metrics.png b/docs/my-website/img/release_notes/chat_metrics.png new file mode 100644 index 00000000000..2e45392cd6b Binary files /dev/null and b/docs/my-website/img/release_notes/chat_metrics.png differ diff --git a/docs/my-website/img/release_notes/credentials.jpg b/docs/my-website/img/release_notes/credentials.jpg new file mode 100644 index 00000000000..1f11c67f054 Binary files /dev/null and b/docs/my-website/img/release_notes/credentials.jpg differ diff --git a/docs/my-website/img/release_notes/error_logs.jpg b/docs/my-website/img/release_notes/error_logs.jpg new file mode 100644 index 00000000000..6f2767e1fba Binary files /dev/null and b/docs/my-website/img/release_notes/error_logs.jpg differ diff --git a/docs/my-website/img/release_notes/lb_batch.png b/docs/my-website/img/release_notes/lb_batch.png new file mode 100644 index 00000000000..05e430ef49f Binary files /dev/null and b/docs/my-website/img/release_notes/lb_batch.png differ diff --git a/docs/my-website/img/release_notes/litellm_test_connection.gif b/docs/my-website/img/release_notes/litellm_test_connection.gif new file mode 100644 index 00000000000..2c8ea45ab43 Binary files /dev/null and b/docs/my-website/img/release_notes/litellm_test_connection.gif differ diff --git a/docs/my-website/img/release_notes/mcp_ui.png b/docs/my-website/img/release_notes/mcp_ui.png new file mode 100644 index 00000000000..8f4cd4ea198 Binary files /dev/null and b/docs/my-website/img/release_notes/mcp_ui.png differ diff --git a/docs/my-website/img/release_notes/new_activity_tab.png b/docs/my-website/img/release_notes/new_activity_tab.png new file mode 100644 index 00000000000..e8cea22a906 Binary files /dev/null and b/docs/my-website/img/release_notes/new_activity_tab.png differ diff --git a/docs/my-website/img/release_notes/new_tag_usage.png b/docs/my-website/img/release_notes/new_tag_usage.png new file mode 100644 index 00000000000..4188cbc2459 Binary files /dev/null and b/docs/my-website/img/release_notes/new_tag_usage.png differ diff --git a/docs/my-website/img/release_notes/new_team_usage.png b/docs/my-website/img/release_notes/new_team_usage.png new file mode 100644 index 00000000000..5fea2506d95 Binary files /dev/null and b/docs/my-website/img/release_notes/new_team_usage.png differ diff --git a/docs/my-website/img/release_notes/new_team_usage_highlight.jpg b/docs/my-website/img/release_notes/new_team_usage_highlight.jpg new file mode 100644 index 00000000000..05dbf4b9181 Binary files /dev/null and b/docs/my-website/img/release_notes/new_team_usage_highlight.jpg differ diff --git a/docs/my-website/img/release_notes/responses_api.png b/docs/my-website/img/release_notes/responses_api.png new file mode 100644 index 00000000000..045d86825de Binary files /dev/null and b/docs/my-website/img/release_notes/responses_api.png differ diff --git a/docs/my-website/img/release_notes/spend_by_model.jpg b/docs/my-website/img/release_notes/spend_by_model.jpg new file mode 100644 index 00000000000..2584949efff Binary files /dev/null and b/docs/my-website/img/release_notes/spend_by_model.jpg differ diff --git a/docs/my-website/img/release_notes/sso_sync.png b/docs/my-website/img/release_notes/sso_sync.png new file mode 100644 index 00000000000..a7bf6b838b2 Binary files /dev/null and b/docs/my-website/img/release_notes/sso_sync.png differ diff --git a/docs/my-website/img/release_notes/tag_management.png b/docs/my-website/img/release_notes/tag_management.png new file mode 100644 index 00000000000..eca7b8cbb1b Binary files /dev/null and b/docs/my-website/img/release_notes/tag_management.png differ diff --git a/docs/my-website/img/release_notes/team_filters.png b/docs/my-website/img/release_notes/team_filters.png new file mode 100644 index 00000000000..1ee339939dc Binary files /dev/null and b/docs/my-website/img/release_notes/team_filters.png differ diff --git a/docs/my-website/img/release_notes/team_model_add.png b/docs/my-website/img/release_notes/team_model_add.png new file mode 100644 index 00000000000..f548469846b Binary files /dev/null and b/docs/my-website/img/release_notes/team_model_add.png differ diff --git a/docs/my-website/img/release_notes/ui_responses_lb.png b/docs/my-website/img/release_notes/ui_responses_lb.png new file mode 100644 index 00000000000..e0063959244 Binary files /dev/null and b/docs/my-website/img/release_notes/ui_responses_lb.png differ diff --git a/docs/my-website/img/release_notes/ui_search_users.png b/docs/my-website/img/release_notes/ui_search_users.png new file mode 100644 index 00000000000..42be8d6f607 Binary files /dev/null and b/docs/my-website/img/release_notes/ui_search_users.png differ diff --git a/docs/my-website/img/release_notes/ui_usage.png b/docs/my-website/img/release_notes/ui_usage.png new file mode 100644 index 00000000000..ac39ffb9189 Binary files /dev/null and b/docs/my-website/img/release_notes/ui_usage.png differ diff --git a/docs/my-website/img/release_notes/unified_responses_api_rn.png b/docs/my-website/img/release_notes/unified_responses_api_rn.png new file mode 100644 index 00000000000..60ede0e211b Binary files /dev/null and b/docs/my-website/img/release_notes/unified_responses_api_rn.png differ diff --git a/docs/my-website/img/release_notes/user_filters.png b/docs/my-website/img/release_notes/user_filters.png new file mode 100644 index 00000000000..357c1cdb353 Binary files /dev/null and b/docs/my-website/img/release_notes/user_filters.png differ diff --git a/docs/my-website/img/release_notes/v1632_release.jpg b/docs/my-website/img/release_notes/v1632_release.jpg new file mode 100644 index 00000000000..1770460b2ad Binary files /dev/null and b/docs/my-website/img/release_notes/v1632_release.jpg differ diff --git a/docs/my-website/img/scim_0.png b/docs/my-website/img/scim_0.png new file mode 100644 index 00000000000..265271b78c6 Binary files /dev/null and b/docs/my-website/img/scim_0.png differ diff --git a/docs/my-website/img/scim_1.png b/docs/my-website/img/scim_1.png new file mode 100644 index 00000000000..c6d64b5d111 Binary files /dev/null and b/docs/my-website/img/scim_1.png differ diff --git a/docs/my-website/img/scim_2.png b/docs/my-website/img/scim_2.png new file mode 100644 index 00000000000..c96cf9f0b58 Binary files /dev/null and b/docs/my-website/img/scim_2.png differ diff --git a/docs/my-website/img/scim_3.png b/docs/my-website/img/scim_3.png new file mode 100644 index 00000000000..5ecd3906bde Binary files /dev/null and b/docs/my-website/img/scim_3.png differ diff --git a/docs/my-website/img/scim_4.png b/docs/my-website/img/scim_4.png new file mode 100644 index 00000000000..b4b484418c8 Binary files /dev/null and b/docs/my-website/img/scim_4.png differ diff --git a/docs/my-website/img/scim_integration.png b/docs/my-website/img/scim_integration.png new file mode 100644 index 00000000000..2cfeb872bfd Binary files /dev/null and b/docs/my-website/img/scim_integration.png differ diff --git a/docs/my-website/img/spend_log_deletion_multi_pod.jpg b/docs/my-website/img/spend_log_deletion_multi_pod.jpg new file mode 100644 index 00000000000..52cf22c1a35 Binary files /dev/null and b/docs/my-website/img/spend_log_deletion_multi_pod.jpg differ diff --git a/docs/my-website/img/spend_log_deletion_working.png b/docs/my-website/img/spend_log_deletion_working.png new file mode 100644 index 00000000000..f0dca082611 Binary files /dev/null and b/docs/my-website/img/spend_log_deletion_working.png differ diff --git a/docs/my-website/img/tag_create.png b/docs/my-website/img/tag_create.png new file mode 100644 index 00000000000..d515b3a9f48 Binary files /dev/null and b/docs/my-website/img/tag_create.png differ diff --git a/docs/my-website/img/tag_invalid.png b/docs/my-website/img/tag_invalid.png new file mode 100644 index 00000000000..e12f7197b10 Binary files /dev/null and b/docs/my-website/img/tag_invalid.png differ diff --git a/docs/my-website/img/tag_valid.png b/docs/my-website/img/tag_valid.png new file mode 100644 index 00000000000..3b6e121d126 Binary files /dev/null and b/docs/my-website/img/tag_valid.png differ diff --git a/docs/my-website/img/ui_add_cred_2.png b/docs/my-website/img/ui_add_cred_2.png new file mode 100644 index 00000000000..199a15e1787 Binary files /dev/null and b/docs/my-website/img/ui_add_cred_2.png differ diff --git a/docs/my-website/img/ui_auto_prompt_caching.png b/docs/my-website/img/ui_auto_prompt_caching.png new file mode 100644 index 00000000000..e6f48e48d09 Binary files /dev/null and b/docs/my-website/img/ui_auto_prompt_caching.png differ diff --git a/docs/my-website/img/ui_cred_3.png b/docs/my-website/img/ui_cred_3.png new file mode 100644 index 00000000000..67a614d51bf Binary files /dev/null and b/docs/my-website/img/ui_cred_3.png differ diff --git a/docs/my-website/img/ui_cred_4.png b/docs/my-website/img/ui_cred_4.png new file mode 100644 index 00000000000..84e70e03479 Binary files /dev/null and b/docs/my-website/img/ui_cred_4.png differ diff --git a/docs/my-website/img/ui_cred_add.png b/docs/my-website/img/ui_cred_add.png new file mode 100644 index 00000000000..7b03270b3c7 Binary files /dev/null and b/docs/my-website/img/ui_cred_add.png differ diff --git a/docs/my-website/img/ui_request_logs.png b/docs/my-website/img/ui_request_logs.png new file mode 100644 index 00000000000..912123522bd Binary files /dev/null and b/docs/my-website/img/ui_request_logs.png differ diff --git a/docs/my-website/img/ui_request_logs_content.png b/docs/my-website/img/ui_request_logs_content.png new file mode 100644 index 00000000000..74673b55535 Binary files /dev/null and b/docs/my-website/img/ui_request_logs_content.png differ diff --git a/docs/my-website/img/ui_session_logs.png b/docs/my-website/img/ui_session_logs.png new file mode 100644 index 00000000000..5463d6b1dae Binary files /dev/null and b/docs/my-website/img/ui_session_logs.png differ diff --git a/docs/my-website/img/use_model_cred.png b/docs/my-website/img/use_model_cred.png new file mode 100644 index 00000000000..35d42485557 Binary files /dev/null and b/docs/my-website/img/use_model_cred.png differ diff --git a/docs/my-website/package-lock.json b/docs/my-website/package-lock.json index b5392b32b4f..5c619ad2c28 100644 --- a/docs/my-website/package-lock.json +++ b/docs/my-website/package-lock.json @@ -706,12 +706,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "license": "MIT", "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" @@ -796,11 +797,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.26.10" }, "bin": { "parser": "bin/babel-parser.js" @@ -2146,9 +2148,10 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2157,9 +2160,10 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.0.tgz", - "integrity": "sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.10.tgz", + "integrity": "sha512-uITFQYO68pMEYR46AHgQoyBg7KPPJDAbGn4jUTIRgCFJIp88MIBUianVOplhZDEec07bp9zIyr4Kp0FCyQzmWg==", + "license": "MIT", "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -2169,13 +2173,14 @@ } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" @@ -2199,9 +2204,10 @@ } }, "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -12449,9 +12455,10 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", - "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -12554,9 +12561,10 @@ } }, "node_modules/image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", "dependencies": { "queue": "6.0.2" }, @@ -21063,9 +21071,9 @@ } }, "node_modules/undici": { - "version": "6.21.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", - "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", "license": "MIT", "engines": { "node": ">=18.17" diff --git a/docs/my-website/release_notes/v1.55.10/index.md b/docs/my-website/release_notes/v1.55.10/index.md index 7f9839c2b53..2b5ce75cf09 100644 --- a/docs/my-website/release_notes/v1.55.10/index.md +++ b/docs/my-website/release_notes/v1.55.10/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.55.8-stable/index.md b/docs/my-website/release_notes/v1.55.8-stable/index.md index 7e82e947475..38c78eb5372 100644 --- a/docs/my-website/release_notes/v1.55.8-stable/index.md +++ b/docs/my-website/release_notes/v1.55.8-stable/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.56.1/index.md b/docs/my-website/release_notes/v1.56.1/index.md index 7c4ccc74eaf..74f3606b90d 100644 --- a/docs/my-website/release_notes/v1.56.1/index.md +++ b/docs/my-website/release_notes/v1.56.1/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.56.3/index.md b/docs/my-website/release_notes/v1.56.3/index.md index 95205633ea6..3d996ba5b88 100644 --- a/docs/my-website/release_notes/v1.56.3/index.md +++ b/docs/my-website/release_notes/v1.56.3/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.56.4/index.md b/docs/my-website/release_notes/v1.56.4/index.md index 93f87256321..bf9cc2d94e4 100644 --- a/docs/my-website/release_notes/v1.56.4/index.md +++ b/docs/my-website/release_notes/v1.56.4/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.57.3/index.md b/docs/my-website/release_notes/v1.57.3/index.md index 3bee71a8e14..ab1154a0a8c 100644 --- a/docs/my-website/release_notes/v1.57.3/index.md +++ b/docs/my-website/release_notes/v1.57.3/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.57.7/index.md b/docs/my-website/release_notes/v1.57.7/index.md index ce987baf779..4da2402efa8 100644 --- a/docs/my-website/release_notes/v1.57.7/index.md +++ b/docs/my-website/release_notes/v1.57.7/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.57.8-stable/index.md b/docs/my-website/release_notes/v1.57.8-stable/index.md index 9787444fde5..78fe13f2ed7 100644 --- a/docs/my-website/release_notes/v1.57.8-stable/index.md +++ b/docs/my-website/release_notes/v1.57.8-stable/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ @@ -18,13 +18,6 @@ hide_table_of_contents: false `alerting`, `prometheus`, `secret management`, `management endpoints`, `ui`, `prompt management`, `finetuning`, `batch` -:::note - -v1.57.8-stable, is currently being tested. It will be released on 2025-01-12. - -::: - - ## New / Updated Models 1. Mistral large pricing - https://github.com/BerriAI/litellm/pull/7452 @@ -45,7 +38,7 @@ v1.57.8-stable, is currently being tested. It will be released on 2025-01-12. 2. OpenAI Moderations - `omni-moderation-latest` support. [Start Here](https://docs.litellm.ai/docs/moderation) 3. Azure O1 - fake streaming support. This ensures if a `stream=true` is passed, the response is streamed. [Start Here](https://docs.litellm.ai/docs/providers/azure) 4. Anthropic - non-whitespace char stop sequence handling - [PR](https://github.com/BerriAI/litellm/pull/7484) -5. Azure OpenAI - support entrata id username + password based auth. [Start Here](https://docs.litellm.ai/docs/providers/azure#entrata-id---use-tenant_id-client_id-client_secret) +5. Azure OpenAI - support Entra ID username + password based auth. [Start Here](https://docs.litellm.ai/docs/providers/azure#entra-id---use-tenant_id-client_id-client_secret) 6. LM Studio - embedding route support. [Start Here](https://docs.litellm.ai/docs/providers/lm-studio) 7. WatsonX - ZenAPIKeyAuth support. [Start Here](https://docs.litellm.ai/docs/providers/watsonx) diff --git a/docs/my-website/release_notes/v1.59.0/index.md b/docs/my-website/release_notes/v1.59.0/index.md index 5343ba49adb..2699e42020a 100644 --- a/docs/my-website/release_notes/v1.59.0/index.md +++ b/docs/my-website/release_notes/v1.59.0/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.59.8-stable/index.md b/docs/my-website/release_notes/v1.59.8-stable/index.md index fa9825fb667..023f284ad50 100644 --- a/docs/my-website/release_notes/v1.59.8-stable/index.md +++ b/docs/my-website/release_notes/v1.59.8-stable/index.md @@ -6,7 +6,7 @@ authors: - name: Krrish Dholakia title: CEO, LiteLLM url: https://www.linkedin.com/in/krish-d/ - image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1743638400&v=beta&t=39KOXMUFedvukiWWVPHf3qI45fuQD7lNglICwN31DrI + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 - name: Ishaan Jaffer title: CTO, LiteLLM url: https://www.linkedin.com/in/reffajnaahsi/ diff --git a/docs/my-website/release_notes/v1.61.20-stable/index.md b/docs/my-website/release_notes/v1.61.20-stable/index.md new file mode 100644 index 00000000000..5012e2aa90a --- /dev/null +++ b/docs/my-website/release_notes/v1.61.20-stable/index.md @@ -0,0 +1,103 @@ +--- +title: v1.61.20-stable +slug: v1.61.20-stable +date: 2025-03-01T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGiM7ZrUwqu_Q/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1675971026692?e=1741824000&v=beta&t=eQnRdXPJo4eiINWTZARoYTfqh064pgZ-E21pQTSy8jc +tags: [llm translation, rerank, ui, thinking, reasoning_content, claude-3-7-sonnet] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; + +# v1.61.20-stable + + +These are the changes since `v1.61.13-stable`. + +This release is primarily focused on: +- LLM Translation improvements (claude-3-7-sonnet + 'thinking'/'reasoning_content' support) +- UI improvements (add model flow, user management, etc) + +## Demo Instance + +Here's a Demo Instance to test changes: +- Instance: https://demo.litellm.ai/ +- Login Credentials: + - Username: admin + - Password: sk-1234 + +## New Models / Updated Models + +1. Anthropic 3-7 sonnet support + cost tracking (Anthropic API + Bedrock + Vertex AI + OpenRouter) + 1. Anthropic API [Start here](https://docs.litellm.ai/docs/providers/anthropic#usage---thinking--reasoning_content) + 2. Bedrock API [Start here](https://docs.litellm.ai/docs/providers/bedrock#usage---thinking--reasoning-content) + 3. Vertex AI API [See here](../../docs/providers/vertex#usage---thinking--reasoning_content) + 4. OpenRouter [See here](https://github.com/BerriAI/litellm/blob/ba5bdce50a0b9bc822de58c03940354f19a733ed/model_prices_and_context_window.json#L5626) +2. Gpt-4.5-preview support + cost tracking [See here](https://github.com/BerriAI/litellm/blob/ba5bdce50a0b9bc822de58c03940354f19a733ed/model_prices_and_context_window.json#L79) +3. Azure AI - Phi-4 cost tracking [See here](https://github.com/BerriAI/litellm/blob/ba5bdce50a0b9bc822de58c03940354f19a733ed/model_prices_and_context_window.json#L1773) +4. Claude-3.5-sonnet - vision support updated on Anthropic API [See here](https://github.com/BerriAI/litellm/blob/ba5bdce50a0b9bc822de58c03940354f19a733ed/model_prices_and_context_window.json#L2888) +5. Bedrock llama vision support [See here](https://github.com/BerriAI/litellm/blob/ba5bdce50a0b9bc822de58c03940354f19a733ed/model_prices_and_context_window.json#L7714) +6. Cerebras llama3.3-70b pricing [See here](https://github.com/BerriAI/litellm/blob/ba5bdce50a0b9bc822de58c03940354f19a733ed/model_prices_and_context_window.json#L2697) + +## LLM Translation + +1. Infinity Rerank - support returning documents when return_documents=True [Start here](../../docs/providers/infinity#usage---returning-documents) +2. Amazon Deepseek - `` param extraction into ‘reasoning_content’ [Start here](https://docs.litellm.ai/docs/providers/bedrock#bedrock-imported-models-deepseek-deepseek-r1) +3. Amazon Titan Embeddings - filter out ‘aws_’ params from request body [Start here](https://docs.litellm.ai/docs/providers/bedrock#bedrock-embedding) +4. Anthropic ‘thinking’ + ‘reasoning_content’ translation support (Anthropic API, Bedrock, Vertex AI) [Start here](https://docs.litellm.ai/docs/reasoning_content) +5. VLLM - support ‘video_url’ [Start here](../../docs/providers/vllm#send-video-url-to-vllm) +6. Call proxy via litellm SDK: Support `litellm_proxy/` for embedding, image_generation, transcription, speech, rerank [Start here](https://docs.litellm.ai/docs/providers/litellm_proxy) +7. OpenAI Pass-through - allow using Assistants GET, DELETE on /openai pass through routes [Start here](https://docs.litellm.ai/docs/pass_through/openai_passthrough) +8. Message Translation - fix openai message for assistant msg if role is missing - openai allows this +9. O1/O3 - support ‘drop_params’ for o3-mini and o1 parallel_tool_calls param (not supported currently) [See here](https://docs.litellm.ai/docs/completion/drop_params) + +## Spend Tracking Improvements + +1. Cost tracking for rerank via Bedrock [See PR](https://github.com/BerriAI/litellm/commit/b682dc4ec8fd07acf2f4c981d2721e36ae2a49c5) +2. Anthropic pass-through - fix race condition causing cost to not be tracked [See PR](https://github.com/BerriAI/litellm/pull/8874) +3. Anthropic pass-through: Ensure accurate token counting [See PR](https://github.com/BerriAI/litellm/pull/8880) + +## Management Endpoints / UI + +1. Models Page - Allow sorting models by ‘created at’ +2. Models Page - Edit Model Flow Improvements +3. Models Page - Fix Adding Azure, Azure AI Studio models on UI +4. Internal Users Page - Allow Bulk Adding Internal Users on UI +5. Internal Users Page - Allow sorting users by ‘created at’ +6. Virtual Keys Page - Allow searching for UserIDs on the dropdown when assigning a user to a team [See PR](https://github.com/BerriAI/litellm/pull/8844) +7. Virtual Keys Page - allow creating a user when assigning keys to users [See PR](https://github.com/BerriAI/litellm/pull/8844) +8. Model Hub Page - fix text overflow issue [See PR](https://github.com/BerriAI/litellm/pull/8749) +9. Admin Settings Page - Allow adding MSFT SSO on UI +10. Backend - don't allow creating duplicate internal users in DB + +## Helm + +1. support ttlSecondsAfterFinished on the migration job - [See PR](https://github.com/BerriAI/litellm/pull/8593) +2. enhance migrations job with additional configurable properties - [See PR](https://github.com/BerriAI/litellm/pull/8636) + +## Logging / Guardrail Integrations + +1. Arize Phoenix support +2. ‘No-log’ - fix ‘no-log’ param support on embedding calls + +## Performance / Loadbalancing / Reliability improvements + +1. Single Deployment Cooldown logic - Use allowed_fails or allowed_fail_policy if set [Start here](https://docs.litellm.ai/docs/routing#advanced-custom-retries-cooldowns-based-on-error-type) + +## General Proxy Improvements + +1. Hypercorn - fix reading / parsing request body +2. Windows - fix running proxy in windows +3. DD-Trace - fix dd-trace enablement on proxy + +## Complete Git Diff + +View the complete git diff [here](https://github.com/BerriAI/litellm/compare/v1.61.13-stable...v1.61.20-stable). \ No newline at end of file diff --git a/docs/my-website/release_notes/v1.63.0/index.md b/docs/my-website/release_notes/v1.63.0/index.md new file mode 100644 index 00000000000..ab74b11b4d0 --- /dev/null +++ b/docs/my-website/release_notes/v1.63.0/index.md @@ -0,0 +1,40 @@ +--- +title: v1.63.0 - Anthropic 'thinking' response update +slug: v1.63.0 +date: 2025-03-05T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGiM7ZrUwqu_Q/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1675971026692?e=1741824000&v=beta&t=eQnRdXPJo4eiINWTZARoYTfqh064pgZ-E21pQTSy8jc +tags: [llm translation, thinking, reasoning_content, claude-3-7-sonnet] +hide_table_of_contents: false +--- + +v1.63.0 fixes Anthropic 'thinking' response on streaming to return the `signature` block. [Github Issue](https://github.com/BerriAI/litellm/issues/8964) + + + +It also moves the response structure from `signature_delta` to `signature` to be the same as Anthropic. [Anthropic Docs](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#implementing-extended-thinking) + + +## Diff + +```bash +"message": { + ... + "reasoning_content": "The capital of France is Paris.", + "thinking_blocks": [ + { + "type": "thinking", + "thinking": "The capital of France is Paris.", +- "signature_delta": "EqoBCkgIARABGAIiQL2UoU0b1OHYi+..." # 👈 OLD FORMAT ++ "signature": "EqoBCkgIARABGAIiQL2UoU0b1OHYi+..." # 👈 KEY CHANGE + } + ] +} +``` diff --git a/docs/my-website/release_notes/v1.63.11-stable/index.md b/docs/my-website/release_notes/v1.63.11-stable/index.md new file mode 100644 index 00000000000..882747a07b3 --- /dev/null +++ b/docs/my-website/release_notes/v1.63.11-stable/index.md @@ -0,0 +1,172 @@ +--- +title: v1.63.11-stable +slug: v1.63.11-stable +date: 2025-03-15T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +tags: [credential management, thinking content, responses api, snowflake] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; + +These are the changes since `v1.63.2-stable`. + +This release is primarily focused on: +- [Beta] Responses API Support +- Snowflake Cortex Support, Amazon Nova Image Generation +- UI - Credential Management, re-use credentials when adding new models +- UI - Test Connection to LLM Provider before adding a model + +## Known Issues +- 🚨 Known issue on Azure OpenAI - We don't recommend upgrading if you use Azure OpenAI. This version failed our Azure OpenAI load test + + +## Docker Run LiteLLM Proxy + +``` +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.63.11-stable +``` + +## Demo Instance + +Here's a Demo Instance to test changes: +- Instance: https://demo.litellm.ai/ +- Login Credentials: + - Username: admin + - Password: sk-1234 + + + +## New Models / Updated Models + +- Image Generation support for Amazon Nova Canvas [Getting Started](https://docs.litellm.ai/docs/providers/bedrock#image-generation) +- Add pricing for Jamba new models [PR](https://github.com/BerriAI/litellm/pull/9032/files) +- Add pricing for Amazon EU models [PR](https://github.com/BerriAI/litellm/pull/9056/files) +- Add Bedrock Deepseek R1 model pricing [PR](https://github.com/BerriAI/litellm/pull/9108/files) +- Update Gemini pricing: Gemma 3, Flash 2 thinking update, LearnLM [PR](https://github.com/BerriAI/litellm/pull/9190/files) +- Mark Cohere Embedding 3 models as Multimodal [PR](https://github.com/BerriAI/litellm/pull/9176/commits/c9a576ce4221fc6e50dc47cdf64ab62736c9da41) +- Add Azure Data Zone pricing [PR](https://github.com/BerriAI/litellm/pull/9185/files#diff-19ad91c53996e178c1921cbacadf6f3bae20cfe062bd03ee6bfffb72f847ee37) + - LiteLLM Tracks cost for `azure/eu` and `azure/us` models + + + +## LLM Translation + + + +1. **New Endpoints** +- [Beta] POST `/responses` API. [Getting Started](https://docs.litellm.ai/docs/response_api) + +2. **New LLM Providers** +- Snowflake Cortex [Getting Started](https://docs.litellm.ai/docs/providers/snowflake) + +3. **New LLM Features** + +- Support OpenRouter `reasoning_content` on streaming [Getting Started](https://docs.litellm.ai/docs/reasoning_content) + +4. **Bug Fixes** + +- OpenAI: Return `code`, `param` and `type` on bad request error [More information on litellm exceptions](https://docs.litellm.ai/docs/exception_mapping) +- Bedrock: Fix converse chunk parsing to only return empty dict on tool use [PR](https://github.com/BerriAI/litellm/pull/9166) +- Bedrock: Support extra_headers [PR](https://github.com/BerriAI/litellm/pull/9113) +- Azure: Fix Function Calling Bug & Update Default API Version to `2025-02-01-preview` [PR](https://github.com/BerriAI/litellm/pull/9191) +- Azure: Fix AI services URL [PR](https://github.com/BerriAI/litellm/pull/9185) +- Vertex AI: Handle HTTP 201 status code in response [PR](https://github.com/BerriAI/litellm/pull/9193) +- Perplexity: Fix incorrect streaming response [PR](https://github.com/BerriAI/litellm/pull/9081) +- Triton: Fix streaming completions bug [PR](https://github.com/BerriAI/litellm/pull/8386) +- Deepgram: Support bytes.IO when handling audio files for transcription [PR](https://github.com/BerriAI/litellm/pull/9071) +- Ollama: Fix "system" role has become unacceptable [PR](https://github.com/BerriAI/litellm/pull/9261) +- All Providers (Streaming): Fix String `data:` stripped from entire content in streamed responses [PR](https://github.com/BerriAI/litellm/pull/9070) + + + +## Spend Tracking Improvements + +1. Support Bedrock converse cache token tracking [Getting Started](https://docs.litellm.ai/docs/completion/prompt_caching) +2. Cost Tracking for Responses API [Getting Started](https://docs.litellm.ai/docs/response_api) +3. Fix Azure Whisper cost tracking [Getting Started](https://docs.litellm.ai/docs/audio_transcription) + + +## UI + +### Re-Use Credentials on UI + +You can now onboard LLM provider credentials on LiteLLM UI. Once these credentials are added you can re-use them when adding new models [Getting Started](https://docs.litellm.ai/docs/proxy/ui_credentials) + + + + +### Test Connections before adding models + +Before adding a model you can test the connection to the LLM provider to verify you have setup your API Base + API Key correctly + + + +### General UI Improvements +1. Add Models Page + - Allow adding Cerebras, Sambanova, Perplexity, Fireworks, Openrouter, TogetherAI Models, Text-Completion OpenAI on Admin UI + - Allow adding EU OpenAI models + - Fix: Instantly show edit + deletes to models +2. Keys Page + - Fix: Instantly show newly created keys on Admin UI (don't require refresh) + - Fix: Allow clicking into Top Keys when showing users Top API Key + - Fix: Allow Filter Keys by Team Alias, Key Alias and Org + - UI Improvements: Show 100 Keys Per Page, Use full height, increase width of key alias +3. Users Page + - Fix: Show correct count of internal user keys on Users Page + - Fix: Metadata not updating in Team UI +4. Logs Page + - UI Improvements: Keep expanded log in focus on LiteLLM UI + - UI Improvements: Minor improvements to logs page + - Fix: Allow internal user to query their own logs + - Allow switching off storing Error Logs in DB [Getting Started](https://docs.litellm.ai/docs/proxy/ui_logs) +5. Sign In/Sign Out + - Fix: Correctly use `PROXY_LOGOUT_URL` when set [Getting Started](https://docs.litellm.ai/docs/proxy/self_serve#setting-custom-logout-urls) + + +## Security + +1. Support for Rotating Master Keys [Getting Started](https://docs.litellm.ai/docs/proxy/master_key_rotations) +2. Fix: Internal User Viewer Permissions, don't allow `internal_user_viewer` role to see `Test Key Page` or `Create Key Button` [More information on role based access controls](https://docs.litellm.ai/docs/proxy/access_control) +3. Emit audit logs on All user + model Create/Update/Delete endpoints [Getting Started](https://docs.litellm.ai/docs/proxy/multiple_admins) +4. JWT + - Support multiple JWT OIDC providers [Getting Started](https://docs.litellm.ai/docs/proxy/token_auth) + - Fix JWT access with Groups not working when team is assigned All Proxy Models access +5. Using K/V pairs in 1 AWS Secret [Getting Started](https://docs.litellm.ai/docs/secret#using-kv-pairs-in-1-aws-secret) + + +## Logging Integrations + +1. Prometheus: Track Azure LLM API latency metric [Getting Started](https://docs.litellm.ai/docs/proxy/prometheus#request-latency-metrics) +2. Athina: Added tags, user_feedback and model_options to additional_keys which can be sent to Athina [Getting Started](https://docs.litellm.ai/docs/observability/athina_integration) + + +## Performance / Reliability improvements + +1. Redis + litellm router - Fix Redis cluster mode for litellm router [PR](https://github.com/BerriAI/litellm/pull/9010) + + +## General Improvements + +1. OpenWebUI Integration - display `thinking` tokens +- Guide on getting started with LiteLLM x OpenWebUI. [Getting Started](https://docs.litellm.ai/docs/tutorials/openweb_ui) +- Display `thinking` tokens on OpenWebUI (Bedrock, Anthropic, Deepseek) [Getting Started](https://docs.litellm.ai/docs/tutorials/openweb_ui#render-thinking-content-on-openweb-ui) + + + + +## Complete Git Diff + +[Here's the complete git diff](https://github.com/BerriAI/litellm/compare/v1.63.2-stable...v1.63.11-stable) \ No newline at end of file diff --git a/docs/my-website/release_notes/v1.63.14/index.md b/docs/my-website/release_notes/v1.63.14/index.md new file mode 100644 index 00000000000..ff2630468c5 --- /dev/null +++ b/docs/my-website/release_notes/v1.63.14/index.md @@ -0,0 +1,131 @@ +--- +title: v1.63.14-stable +slug: v1.63.14-stable +date: 2025-03-22T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +tags: [credential management, thinking content, responses api, snowflake] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; + +These are the changes since `v1.63.11-stable`. + +This release brings: +- LLM Translation Improvements (MCP Support and Bedrock Application Profiles) +- Perf improvements for Usage-based Routing +- Streaming guardrail support via websockets +- Azure OpenAI client perf fix (from previous release) + +## Docker Run LiteLLM Proxy + +``` +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.63.14-stable.patch1 +``` + +## Demo Instance + +Here's a Demo Instance to test changes: +- Instance: https://demo.litellm.ai/ +- Login Credentials: + - Username: admin + - Password: sk-1234 + + + +## New Models / Updated Models + +- Azure gpt-4o - fixed pricing to latest global pricing - [PR](https://github.com/BerriAI/litellm/pull/9361) +- O1-Pro - add pricing + model information - [PR](https://github.com/BerriAI/litellm/pull/9397) +- Azure AI - mistral 3.1 small pricing added - [PR](https://github.com/BerriAI/litellm/pull/9453) +- Azure - gpt-4.5-preview pricing added - [PR](https://github.com/BerriAI/litellm/pull/9453) + + + +## LLM Translation + +1. **New LLM Features** + +- Bedrock: Support bedrock application inference profiles [Docs](https://docs.litellm.ai/docs/providers/bedrock#bedrock-application-inference-profile) + - Infer aws region from bedrock application profile id - (`arn:aws:bedrock:us-east-1:...`) +- Ollama - support calling via `/v1/completions` [Get Started](../../docs/providers/ollama#using-ollama-fim-on-v1completions) +- Bedrock - support `us.deepseek.r1-v1:0` model name [Docs](../../docs/providers/bedrock#supported-aws-bedrock-models) +- OpenRouter - `OPENROUTER_API_BASE` env var support [Docs](../../docs/providers/openrouter.md) +- Azure - add audio model parameter support - [Docs](../../docs/providers/azure#azure-audio-model) +- OpenAI - PDF File support [Docs](../../docs/completion/document_understanding#openai-file-message-type) +- OpenAI - o1-pro Responses API streaming support [Docs](../../docs/response_api.md#streaming) +- [BETA] MCP - Use MCP Tools with LiteLLM SDK [Docs](../../docs/mcp) + +2. **Bug Fixes** + +- Voyage: prompt token on embedding tracking fix - [PR](https://github.com/BerriAI/litellm/commit/56d3e75b330c3c3862dc6e1c51c1210e48f1068e) +- Sagemaker - Fix ‘Too little data for declared Content-Length’ error - [PR](https://github.com/BerriAI/litellm/pull/9326) +- OpenAI-compatible models - fix issue when calling openai-compatible models w/ custom_llm_provider set - [PR](https://github.com/BerriAI/litellm/pull/9355) +- VertexAI - Embedding ‘outputDimensionality’ support - [PR](https://github.com/BerriAI/litellm/commit/437dbe724620675295f298164a076cbd8019d304) +- Anthropic - return consistent json response format on streaming/non-streaming - [PR](https://github.com/BerriAI/litellm/pull/9437) + +## Spend Tracking Improvements + +- `litellm_proxy/` - support reading litellm response cost header from proxy, when using client sdk +- Reset Budget Job - fix budget reset error on keys/teams/users [PR](https://github.com/BerriAI/litellm/pull/9329) +- Streaming - Prevents final chunk w/ usage from being ignored (impacted bedrock streaming + cost tracking) [PR](https://github.com/BerriAI/litellm/pull/9314) + + +## UI + +1. Users Page + - Feature: Control default internal user settings [PR](https://github.com/BerriAI/litellm/pull/9328) +2. Icons: + - Feature: Replace external "artificialanalysis.ai" icons by local svg [PR](https://github.com/BerriAI/litellm/pull/9374) +3. Sign In/Sign Out + - Fix: Default login when `default_user_id` user does not exist in DB [PR](https://github.com/BerriAI/litellm/pull/9395) + + +## Logging Integrations + +- Support post-call guardrails for streaming responses [Get Started](../../docs/proxy/guardrails/custom_guardrail#1-write-a-customguardrail-class) +- Arize [Get Started](../../docs/observability/arize_integration) + - fix invalid package import [PR](https://github.com/BerriAI/litellm/pull/9338) + - migrate to using standardloggingpayload for metadata, ensures spans land successfully [PR](https://github.com/BerriAI/litellm/pull/9338) + - fix logging to just log the LLM I/O [PR](https://github.com/BerriAI/litellm/pull/9353) + - Dynamic API Key/Space param support [Get Started](../../docs/observability/arize_integration#pass-arize-spacekey-per-request) +- StandardLoggingPayload - Log litellm_model_name in payload. Allows knowing what the model sent to API provider was [Get Started](../../docs/proxy/logging_spec#standardlogginghiddenparams) +- Prompt Management - Allow building custom prompt management integration [Get Started](../../docs/proxy/custom_prompt_management.md) + +## Performance / Reliability improvements + +- Redis Caching - add 5s default timeout, prevents hanging redis connection from impacting llm calls [PR](https://github.com/BerriAI/litellm/commit/db92956ae33ed4c4e3233d7e1b0c7229817159bf) +- Allow disabling all spend updates / writes to DB - patch to allow disabling all spend updates to DB with a flag [PR](https://github.com/BerriAI/litellm/pull/9331) +- Azure OpenAI - correctly re-use azure openai client, fixes perf issue from previous Stable release [PR](https://github.com/BerriAI/litellm/commit/f2026ef907c06d94440930917add71314b901413) +- Azure OpenAI - uses litellm.ssl_verify on Azure/OpenAI clients [PR](https://github.com/BerriAI/litellm/commit/f2026ef907c06d94440930917add71314b901413) +- Usage-based routing - Wildcard model support [Get Started](../../docs/proxy/usage_based_routing#wildcard-model-support) +- Usage-based routing - Support batch writing increments to redis - reduces latency to same as ‘simple-shuffle’ [PR](https://github.com/BerriAI/litellm/pull/9357) +- Router - show reason for model cooldown on ‘no healthy deployments available error’ [PR](https://github.com/BerriAI/litellm/pull/9438) +- Caching - add max value limit to an item in in-memory cache (1MB) - prevents OOM errors on large image url’s being sent through proxy [PR](https://github.com/BerriAI/litellm/pull/9448) + + +## General Improvements + +- Passthrough Endpoints - support returning api-base on pass-through endpoints Response Headers [Docs](../../docs/proxy/response_headers#litellm-specific-headers) +- SSL - support reading ssl security level from env var - Allows user to specify lower security settings [Get Started](../../docs/guides/security_settings) +- Credentials - only poll Credentials table when `STORE_MODEL_IN_DB` is True [PR](https://github.com/BerriAI/litellm/pull/9376) +- Image URL Handling - new architecture doc on image url handling [Docs](../../docs/proxy/image_handling) +- OpenAI - bump to pip install "openai==1.68.2" [PR](https://github.com/BerriAI/litellm/commit/e85e3bc52a9de86ad85c3dbb12d87664ee567a5a) +- Gunicorn - security fix - bump gunicorn==23.0.0 [PR](https://github.com/BerriAI/litellm/commit/7e9fc92f5c7fea1e7294171cd3859d55384166eb) + + +## Complete Git Diff + +[Here's the complete git diff](https://github.com/BerriAI/litellm/compare/v1.63.11-stable...v1.63.14.rc) \ No newline at end of file diff --git a/docs/my-website/release_notes/v1.63.2-stable/index.md b/docs/my-website/release_notes/v1.63.2-stable/index.md new file mode 100644 index 00000000000..3d47e02ac17 --- /dev/null +++ b/docs/my-website/release_notes/v1.63.2-stable/index.md @@ -0,0 +1,112 @@ +--- +title: v1.63.2-stable +slug: v1.63.2-stable +date: 2025-03-08T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGiM7ZrUwqu_Q/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1675971026692?e=1741824000&v=beta&t=eQnRdXPJo4eiINWTZARoYTfqh064pgZ-E21pQTSy8jc +tags: [llm translation, thinking, reasoning_content, claude-3-7-sonnet] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; + + +These are the changes since `v1.61.20-stable`. + +This release is primarily focused on: +- LLM Translation improvements (more `thinking` content improvements) +- UI improvements (Error logs now shown on UI) + + +:::info + +This release will be live on 03/09/2025 + +::: + + + + +## Demo Instance + +Here's a Demo Instance to test changes: +- Instance: https://demo.litellm.ai/ +- Login Credentials: + - Username: admin + - Password: sk-1234 + + +## New Models / Updated Models + +1. Add `supports_pdf_input` for specific Bedrock Claude models [PR](https://github.com/BerriAI/litellm/commit/f63cf0030679fe1a43d03fb196e815a0f28dae92) +2. Add pricing for amazon `eu` models [PR](https://github.com/BerriAI/litellm/commits/main/model_prices_and_context_window.json) +3. Fix Azure O1 mini pricing [PR](https://github.com/BerriAI/litellm/commit/52de1949ef2f76b8572df751f9c868a016d4832c) + +## LLM Translation + + + +1. Support `/openai/` passthrough for Assistant endpoints. [Get Started](https://docs.litellm.ai/docs/pass_through/openai_passthrough) +2. Bedrock Claude - fix tool calling transformation on invoke route. [Get Started](../../docs/providers/bedrock#usage---function-calling--tool-calling) +3. Bedrock Claude - response_format support for claude on invoke route. [Get Started](../../docs/providers/bedrock#usage---structured-output--json-mode) +4. Bedrock - pass `description` if set in response_format. [Get Started](../../docs/providers/bedrock#usage---structured-output--json-mode) +5. Bedrock - Fix passing response_format: {"type": "text"}. [PR](https://github.com/BerriAI/litellm/commit/c84b489d5897755139aa7d4e9e54727ebe0fa540) +6. OpenAI - Handle sending image_url as str to openai. [Get Started](https://docs.litellm.ai/docs/completion/vision) +7. Deepseek - return 'reasoning_content' missing on streaming. [Get Started](https://docs.litellm.ai/docs/reasoning_content) +8. Caching - Support caching on reasoning content. [Get Started](https://docs.litellm.ai/docs/proxy/caching) +9. Bedrock - handle thinking blocks in assistant message. [Get Started](https://docs.litellm.ai/docs/providers/bedrock#usage---thinking--reasoning-content) +10. Anthropic - Return `signature` on streaming. [Get Started](https://docs.litellm.ai/docs/providers/bedrock#usage---thinking--reasoning-content) +- Note: We've also migrated from `signature_delta` to `signature`. [Read more](https://docs.litellm.ai/release_notes/v1.63.0) +11. Support format param for specifying image type. [Get Started](../../docs/completion/vision.md#explicitly-specify-image-type) +12. Anthropic - `/v1/messages` endpoint - `thinking` param support. [Get Started](../../docs/anthropic_unified.md) +- Note: this refactors the [BETA] unified `/v1/messages` endpoint, to just work for the Anthropic API. +13. Vertex AI - handle $id in response schema when calling vertex ai. [Get Started](https://docs.litellm.ai/docs/providers/vertex#json-schema) + +## Spend Tracking Improvements + +1. Batches API - Fix cost calculation to run on retrieve_batch. [Get Started](https://docs.litellm.ai/docs/batches) +2. Batches API - Log batch models in spend logs / standard logging payload. [Get Started](../../docs/proxy/logging_spec.md#standardlogginghiddenparams) + +## Management Endpoints / UI + + + +1. Virtual Keys Page + - Allow team/org filters to be searchable on the Create Key Page + - Add created_by and updated_by fields to Keys table + - Show 'user_email' on key table + - Show 100 Keys Per Page, Use full height, increase width of key alias +2. Logs Page + - Show Error Logs on LiteLLM UI + - Allow Internal Users to View their own logs +3. Internal Users Page + - Allow admin to control default model access for internal users +7. Fix session handling with cookies + +## Logging / Guardrail Integrations + +1. Fix prometheus metrics w/ custom metrics, when keys containing team_id make requests. [PR](https://github.com/BerriAI/litellm/pull/8935) + +## Performance / Loadbalancing / Reliability improvements + +1. Cooldowns - Support cooldowns on models called with client side credentials. [Get Started](https://docs.litellm.ai/docs/proxy/clientside_auth#pass-user-llm-api-keys--api-base) +2. Tag-based Routing - ensures tag-based routing across all endpoints (`/embeddings`, `/image_generation`, etc.). [Get Started](https://docs.litellm.ai/docs/proxy/tag_routing) + +## General Proxy Improvements + +1. Raise BadRequestError when unknown model passed in request +2. Enforce model access restrictions on Azure OpenAI proxy route +3. Reliability fix - Handle emoji’s in text - fix orjson error +4. Model Access Patch - don't overwrite litellm.anthropic_models when running auth checks +5. Enable setting timezone information in docker image + +## Complete Git Diff + +[Here's the complete git diff](https://github.com/BerriAI/litellm/compare/v1.61.20-stable...v1.63.2-stable) \ No newline at end of file diff --git a/docs/my-website/release_notes/v1.65.0-stable/index.md b/docs/my-website/release_notes/v1.65.0-stable/index.md new file mode 100644 index 00000000000..3696f5023c4 --- /dev/null +++ b/docs/my-website/release_notes/v1.65.0-stable/index.md @@ -0,0 +1,160 @@ +--- +title: v1.65.0-stable - Model Context Protocol +slug: v1.65.0-stable +date: 2025-03-30T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +tags: [mcp, custom_prompt_management] +hide_table_of_contents: false +--- +import Image from '@theme/IdealImage'; + +v1.65.0-stable is live now. Here are the key highlights of this release: +- **MCP Support**: Support for adding and using MCP servers on the LiteLLM proxy. +- **UI view total usage after 1M+ logs**: You can now view usage analytics after crossing 1M+ logs in DB. + +## Model Context Protocol (MCP) + +This release introduces support for centrally adding MCP servers on LiteLLM. This allows you to add MCP server endpoints and your developers can `list` and `call` MCP tools through LiteLLM. + +Read more about MCP [here](https://docs.litellm.ai/docs/mcp). + + +

+ Expose and use MCP servers through LiteLLM +

+ +## UI view total usage after 1M+ logs + +This release brings the ability to view total usage analytics even after exceeding 1M+ logs in your database. We've implemented a scalable architecture that stores only aggregate usage data, resulting in significantly more efficient queries and reduced database CPU utilization. + + + +

+ View total usage after 1M+ logs +

+ + +- How this works: + - We now aggregate usage data into a dedicated DailyUserSpend table, significantly reducing query load and CPU usage even beyond 1M+ logs. + +- Daily Spend Breakdown API: + + - Retrieve granular daily usage data (by model, provider, and API key) with a single endpoint. + Example Request: + + ```shell title="Daily Spend Breakdown API" showLineNumbers + curl -L -X GET 'http://localhost:4000/user/daily/activity?start_date=2025-03-20&end_date=2025-03-27' \ + -H 'Authorization: Bearer sk-...' + ``` + + ```json title="Daily Spend Breakdown API Response" showLineNumbers + { + "results": [ + { + "date": "2025-03-27", + "metrics": { + "spend": 0.0177072, + "prompt_tokens": 111, + "completion_tokens": 1711, + "total_tokens": 1822, + "api_requests": 11 + }, + "breakdown": { + "models": { + "gpt-4o-mini": { + "spend": 1.095e-05, + "prompt_tokens": 37, + "completion_tokens": 9, + "total_tokens": 46, + "api_requests": 1 + }, + "providers": { "openai": { ... }, "azure_ai": { ... } }, + "api_keys": { "3126b6eaf1...": { ... } } + } + } + ], + "metadata": { + "total_spend": 0.7274667, + "total_prompt_tokens": 280990, + "total_completion_tokens": 376674, + "total_api_requests": 14 + } + } + ``` + + + + +## New Models / Updated Models +- Support for Vertex AI gemini-2.0-flash-lite & Google AI Studio gemini-2.0-flash-lite [PR](https://github.com/BerriAI/litellm/pull/9523) +- Support for Vertex AI Fine-Tuned LLMs [PR](https://github.com/BerriAI/litellm/pull/9542) +- Nova Canvas image generation support [PR](https://github.com/BerriAI/litellm/pull/9525) +- OpenAI gpt-4o-transcribe support [PR](https://github.com/BerriAI/litellm/pull/9517) +- Added new Vertex AI text embedding model [PR](https://github.com/BerriAI/litellm/pull/9476) + +## LLM Translation +- OpenAI Web Search Tool Call Support [PR](https://github.com/BerriAI/litellm/pull/9465) +- Vertex AI topLogprobs support [PR](https://github.com/BerriAI/litellm/pull/9518) +- Support for sending images and video to Vertex AI multimodal embedding [Doc](https://docs.litellm.ai/docs/providers/vertex#multi-modal-embeddings) +- Support litellm.api_base for Vertex AI + Gemini across completion, embedding, image_generation [PR](https://github.com/BerriAI/litellm/pull/9516) +- Bug fix for returning `response_cost` when using litellm python SDK with LiteLLM Proxy [PR](https://github.com/BerriAI/litellm/commit/6fd18651d129d606182ff4b980e95768fc43ca3d) +- Support for `max_completion_tokens` on Mistral API [PR](https://github.com/BerriAI/litellm/pull/9606) +- Refactored Vertex AI passthrough routes - fixes unpredictable behaviour with auto-setting default_vertex_region on router model add [PR](https://github.com/BerriAI/litellm/pull/9467) + +## Spend Tracking Improvements +- Log 'api_base' on spend logs [PR](https://github.com/BerriAI/litellm/pull/9509) +- Support for Gemini audio token cost tracking [PR](https://github.com/BerriAI/litellm/pull/9535) +- Fixed OpenAI audio input token cost tracking [PR](https://github.com/BerriAI/litellm/pull/9535) + +## UI + +### Model Management +- Allowed team admins to add/update/delete models on UI [PR](https://github.com/BerriAI/litellm/pull/9572) +- Added render supports_web_search on model hub [PR](https://github.com/BerriAI/litellm/pull/9469) + +### Request Logs +- Show API base and model ID on request logs [PR](https://github.com/BerriAI/litellm/pull/9572) +- Allow viewing keyinfo on request logs [PR](https://github.com/BerriAI/litellm/pull/9568) + +### Usage Tab +- Added Daily User Spend Aggregate view - allows UI Usage tab to work > 1m rows [PR](https://github.com/BerriAI/litellm/pull/9538) +- Connected UI to "LiteLLM_DailyUserSpend" spend table [PR](https://github.com/BerriAI/litellm/pull/9603) + +## Logging Integrations +- Fixed StandardLoggingPayload for GCS Pub Sub Logging Integration [PR](https://github.com/BerriAI/litellm/pull/9508) +- Track `litellm_model_name` on `StandardLoggingPayload` [Docs](https://docs.litellm.ai/docs/proxy/logging_spec#standardlogginghiddenparams) + +## Performance / Reliability Improvements +- LiteLLM Redis semantic caching implementation [PR](https://github.com/BerriAI/litellm/pull/9356) +- Gracefully handle exceptions when DB is having an outage [PR](https://github.com/BerriAI/litellm/pull/9533) +- Allow Pods to startup + passing /health/readiness when allow_requests_on_db_unavailable: True and DB is down [PR](https://github.com/BerriAI/litellm/pull/9569) + + +## General Improvements +- Support for exposing MCP tools on litellm proxy [PR](https://github.com/BerriAI/litellm/pull/9426) +- Support discovering Gemini, Anthropic, xAI models by calling their /v1/model endpoint [PR](https://github.com/BerriAI/litellm/pull/9530) +- Fixed route check for non-proxy admins on JWT auth [PR](https://github.com/BerriAI/litellm/pull/9454) +- Added baseline Prisma database migrations [PR](https://github.com/BerriAI/litellm/pull/9565) +- View all wildcard models on /model/info [PR](https://github.com/BerriAI/litellm/pull/9572) + + +## Security +- Bumped next from 14.2.21 to 14.2.25 in UI dashboard [PR](https://github.com/BerriAI/litellm/pull/9458) + +## Complete Git Diff + +[Here's the complete git diff](https://github.com/BerriAI/litellm/compare/v1.63.14-stable.patch1...v1.65.0-stable) diff --git a/docs/my-website/release_notes/v1.65.0/index.md b/docs/my-website/release_notes/v1.65.0/index.md new file mode 100644 index 00000000000..84276c997da --- /dev/null +++ b/docs/my-website/release_notes/v1.65.0/index.md @@ -0,0 +1,34 @@ +--- +title: v1.65.0 - Team Model Add - update +slug: v1.65.0 +date: 2025-03-28T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +tags: [management endpoints, team models, ui] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; + +v1.65.0 updates the `/model/new` endpoint to prevent non-team admins from creating team models. + +This means that only proxy admins or team admins can create team models. + +## Additional Changes + +- Allows team admins to call `/model/update` to update team models. +- Allows team admins to call `/model/delete` to delete team models. +- Introduces new `user_models_only` param to `/v2/model/info` - only return models added by this user. + + +These changes enable team admins to add and manage models for their team on the LiteLLM UI + API. + + + \ No newline at end of file diff --git a/docs/my-website/release_notes/v1.65.4-stable/index.md b/docs/my-website/release_notes/v1.65.4-stable/index.md new file mode 100644 index 00000000000..872024a47ab --- /dev/null +++ b/docs/my-website/release_notes/v1.65.4-stable/index.md @@ -0,0 +1,176 @@ +--- +title: v1.65.4-stable +slug: v1.65.4-stable +date: 2025-04-05T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +tags: [] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.65.4-stable +``` + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.65.4.post1 +``` + + + +v1.65.4-stable is live. Here are the improvements since v1.65.0-stable. + +## Key Highlights +- **Preventing DB Deadlocks**: Fixes a high-traffic issue when multiple instances were writing to the DB at the same time. +- **New Usage Tab**: Enables viewing spend by model and customizing date range + +Let's dive in. + +### Preventing DB Deadlocks + + + +This release fixes the DB deadlocking issue that users faced in high traffic (10K+ RPS). This is great because it enables user/key/team spend tracking works at that scale. + +Read more about the new architecture [here](https://docs.litellm.ai/docs/proxy/db_deadlocks) + + +### New Usage Tab + + + +The new Usage tab now brings the ability to track daily spend by model. This makes it easier to catch any spend tracking or token counting errors, when combined with the ability to view successful requests, and token usage. + +To test this out, just go to Experimental > New Usage > Activity. + + +## New Models / Updated Models + +1. Databricks - claude-3-7-sonnet cost tracking [PR](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/model_prices_and_context_window.json#L10350) +2. VertexAI - `gemini-2.5-pro-exp-03-25` cost tracking [PR](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/model_prices_and_context_window.json#L4492) +3. VertexAI - `gemini-2.0-flash` cost tracking [PR](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/model_prices_and_context_window.json#L4689) +4. Groq - add whisper ASR models to model cost map [PR](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/model_prices_and_context_window.json#L3324) +5. IBM - Add watsonx/ibm/granite-3-8b-instruct to model cost map [PR](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/model_prices_and_context_window.json#L91) +6. Google AI Studio - add gemini/gemini-2.5-pro-preview-03-25 to model cost map [PR](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/model_prices_and_context_window.json#L4850) + +## LLM Translation +1. Vertex AI - Support anyOf param for OpenAI json schema translation [Get Started](https://docs.litellm.ai/docs/providers/vertex#json-schema) +2. Anthropic- response_format + thinking param support (works across Anthropic API, Bedrock, Vertex) [Get Started](https://docs.litellm.ai/docs/reasoning_content) +3. Anthropic - if thinking token is specified and max tokens is not - ensure max token to anthropic is higher than thinking tokens (works across Anthropic API, Bedrock, Vertex) [PR](https://github.com/BerriAI/litellm/pull/9594) +4. Bedrock - latency optimized inference support [Get Started](https://docs.litellm.ai/docs/providers/bedrock#usage---latency-optimized-inference) +5. Sagemaker - handle special tokens + multibyte character code in response [Get Started](https://docs.litellm.ai/docs/providers/aws_sagemaker) +6. MCP - add support for using SSE MCP servers [Get Started](https://docs.litellm.ai/docs/mcp#usage) +8. Anthropic - new `litellm.messages.create` interface for calling Anthropic `/v1/messages` via passthrough [Get Started](https://docs.litellm.ai/docs/anthropic_unified#usage) +11. Anthropic - support ‘file’ content type in message param (works across Anthropic API, Bedrock, Vertex) [Get Started](https://docs.litellm.ai/docs/providers/anthropic#usage---pdf) +12. Anthropic - map openai 'reasoning_effort' to anthropic 'thinking' param (works across Anthropic API, Bedrock, Vertex) [Get Started](https://docs.litellm.ai/docs/providers/anthropic#usage---thinking--reasoning_content) +13. Google AI Studio (Gemini) - [BETA] `/v1/files` upload support [Get Started](../../docs/providers/google_ai_studio/files) +14. Azure - fix o-series tool calling [Get Started](../../docs/providers/azure#tool-calling--function-calling) +15. Unified file id - [ALPHA] allow calling multiple providers with same file id [PR](https://github.com/BerriAI/litellm/pull/9718) + - This is experimental, and not recommended for production use. + - We plan to have a production-ready implementation by next week. +16. Google AI Studio (Gemini) - return logprobs [PR](https://github.com/BerriAI/litellm/pull/9713) +17. Anthropic - Support prompt caching for Anthropic tool calls [Get Started](https://docs.litellm.ai/docs/completion/prompt_caching) +18. OpenRouter - unwrap extra body on open router calls [PR](https://github.com/BerriAI/litellm/pull/9747) +19. VertexAI - fix credential caching issue [PR](https://github.com/BerriAI/litellm/pull/9756) +20. XAI - filter out 'name' param for XAI [PR](https://github.com/BerriAI/litellm/pull/9761) +21. Gemini - image generation output support [Get Started](../../docs/providers/gemini#image-generation) +22. Databricks - support claude-3-7-sonnet w/ thinking + response_format [Get Started](../../docs/providers/databricks#usage---thinking--reasoning_content) + +## Spend Tracking Improvements +1. Reliability fix - Check sent and received model for cost calculation [PR](https://github.com/BerriAI/litellm/pull/9669) +2. Vertex AI - Multimodal embedding cost tracking [Get Started](https://docs.litellm.ai/docs/providers/vertex#multi-modal-embeddings), [PR](https://github.com/BerriAI/litellm/pull/9623) + +## Management Endpoints / UI + + + +1. New Usage Tab + - Report 'total_tokens' + report success/failure calls + - Remove double bars on scroll + - Ensure ‘daily spend’ chart ordered from earliest to latest date + - showing spend per model per day + - show key alias on usage tab + - Allow non-admins to view their activity + - Add date picker to new usage tab +2. Virtual Keys Tab + - remove 'default key' on user signup + - fix showing user models available for personal key creation +3. Test Key Tab + - Allow testing image generation models +4. Models Tab + - Fix bulk adding models + - support reusable credentials for passthrough endpoints + - Allow team members to see team models +5. Teams Tab + - Fix json serialization error on update team metadata +6. Request Logs Tab + - Add reasoning_content token tracking across all providers on streaming +7. API + - return key alias on /user/daily/activity [Get Started](../../docs/proxy/cost_tracking#daily-spend-breakdown-api) +8. SSO + - Allow assigning SSO users to teams on MSFT SSO [PR](https://github.com/BerriAI/litellm/pull/9745) + +## Logging / Guardrail Integrations + +1. Console Logs - Add json formatting for uncaught exceptions [PR](https://github.com/BerriAI/litellm/pull/9619) +2. Guardrails - AIM Guardrails support for virtual key based policies [Get Started](../../docs/proxy/guardrails/aim_security) +3. Logging - fix completion start time tracking [PR](https://github.com/BerriAI/litellm/pull/9688) +4. Prometheus + - Allow adding authentication on Prometheus /metrics endpoints [PR](https://github.com/BerriAI/litellm/pull/9766) + - Distinguish LLM Provider Exception vs. LiteLLM Exception in metric naming [PR](https://github.com/BerriAI/litellm/pull/9760) + - Emit operational metrics for new DB Transaction architecture [PR](https://github.com/BerriAI/litellm/pull/9719) + +## Performance / Loadbalancing / Reliability improvements +1. Preventing Deadlocks + - Reduce DB Deadlocks by storing spend updates in Redis and then committing to DB [PR](https://github.com/BerriAI/litellm/pull/9608) + - Ensure no deadlocks occur when updating DailyUserSpendTransaction [PR](https://github.com/BerriAI/litellm/pull/9690) + - High Traffic fix - ensure new DB + Redis architecture accurately tracks spend [PR](https://github.com/BerriAI/litellm/pull/9673) + - Use Redis for PodLock Manager instead of PG (ensures no deadlocks occur) [PR](https://github.com/BerriAI/litellm/pull/9715) + - v2 DB Deadlock Reduction Architecture – Add Max Size for In-Memory Queue + Backpressure Mechanism [PR](https://github.com/BerriAI/litellm/pull/9759) + +2. Prisma Migrations [Get Started](../../docs/proxy/prod#9-use-prisma-migrate-deploy) + - connects litellm proxy to litellm's prisma migration files + - Handle db schema updates from new `litellm-proxy-extras` sdk +3. Redis - support password for sync sentinel clients [PR](https://github.com/BerriAI/litellm/pull/9622) +4. Fix "Circular reference detected" error when max_parallel_requests = 0 [PR](https://github.com/BerriAI/litellm/pull/9671) +5. Code QA - Ban hardcoded numbers [PR](https://github.com/BerriAI/litellm/pull/9709) + +## Helm +1. fix: wrong indentation of ttlSecondsAfterFinished in chart [PR](https://github.com/BerriAI/litellm/pull/9611) + +## General Proxy Improvements +1. Fix - only apply service_account_settings.enforced_params on service accounts [PR](https://github.com/BerriAI/litellm/pull/9683) +2. Fix - handle metadata null on `/chat/completion` [PR](https://github.com/BerriAI/litellm/issues/9717) +3. Fix - Move daily user transaction logging outside of 'disable_spend_logs' flag, as they’re unrelated [PR](https://github.com/BerriAI/litellm/pull/9772) + +## Demo + +Try this on the demo instance [today](https://docs.litellm.ai/docs/proxy/demo) + +## Complete Git Diff + +See the complete git diff since v1.65.0-stable, [here](https://github.com/BerriAI/litellm/releases/tag/v1.65.4-stable) + diff --git a/docs/my-website/release_notes/v1.66.0-stable/index.md b/docs/my-website/release_notes/v1.66.0-stable/index.md new file mode 100644 index 00000000000..939322e0317 --- /dev/null +++ b/docs/my-website/release_notes/v1.66.0-stable/index.md @@ -0,0 +1,197 @@ +--- +title: v1.66.0-stable - Realtime API Cost Tracking +slug: v1.66.0-stable +date: 2025-04-12T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +tags: ["sso", "unified_file_id", "cost_tracking", "security"] +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.66.0-stable +``` + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.66.0.post1 +``` + + + +v1.66.0-stable is live now, here are the key highlights of this release + +## Key Highlights +- **Realtime API Cost Tracking**: Track cost of realtime API calls +- **Microsoft SSO Auto-sync**: Auto-sync groups and group members from Azure Entra ID to LiteLLM +- **xAI grok-3**: Added support for `xai/grok-3` models +- **Security Fixes**: Fixed [CVE-2025-0330](https://www.cve.org/CVERecord?id=CVE-2025-0330) and [CVE-2024-6825](https://www.cve.org/CVERecord?id=CVE-2024-6825) vulnerabilities + +Let's dive in. + +## Realtime API Cost Tracking + + + + +This release adds Realtime API logging + cost tracking. +- **Logging**: LiteLLM now logs the complete response from realtime calls to all logging integrations (DB, S3, Langfuse, etc.) +- **Cost Tracking**: You can now set 'base_model' and custom pricing for realtime models. [Custom Pricing](../../docs/proxy/custom_pricing) +- **Budgets**: Your key/user/team budgets now work for realtime models as well. + +Start [here](https://docs.litellm.ai/docs/realtime) + + + +## Microsoft SSO Auto-sync + + +

+ Auto-sync groups and members from Azure Entra ID to LiteLLM +

+ +This release adds support for auto-syncing groups and members on Microsoft Entra ID with LiteLLM. This means that LiteLLM proxy administrators can spend less time managing teams and members and LiteLLM handles the following: + +- Auto-create teams that exist on Microsoft Entra ID +- Sync team members on Microsoft Entra ID with LiteLLM teams + +Get started with this [here](https://docs.litellm.ai/docs/tutorials/msft_sso) + + +## New Models / Updated Models + +- **xAI** + 1. Added reasoning_effort support for `xai/grok-3-mini-beta` [Get Started](https://docs.litellm.ai/docs/providers/xai#reasoning-usage) + 2. Added cost tracking for `xai/grok-3` models [PR](https://github.com/BerriAI/litellm/pull/9920) + +- **Hugging Face** + 1. Added inference providers support [Get Started](https://docs.litellm.ai/docs/providers/huggingface#serverless-inference-providers) + +- **Azure** + 1. Added azure/gpt-4o-realtime-audio cost tracking [PR](https://github.com/BerriAI/litellm/pull/9893) + +- **VertexAI** + 1. Added enterpriseWebSearch tool support [Get Started](https://docs.litellm.ai/docs/providers/vertex#grounding---web-search) + 2. Moved to only passing keys accepted by the Vertex AI response schema [PR](https://github.com/BerriAI/litellm/pull/8992) + +- **Google AI Studio** + 1. Added cost tracking for `gemini-2.5-pro` [PR](https://github.com/BerriAI/litellm/pull/9837) + 2. Fixed pricing for 'gemini/gemini-2.5-pro-preview-03-25' [PR](https://github.com/BerriAI/litellm/pull/9896) + 3. Fixed handling file_data being passed in [PR](https://github.com/BerriAI/litellm/pull/9786) + +- **Azure** + 1. Updated Azure Phi-4 pricing [PR](https://github.com/BerriAI/litellm/pull/9862) + 2. Added azure/gpt-4o-realtime-audio cost tracking [PR](https://github.com/BerriAI/litellm/pull/9893) + +- **Databricks** + 1. Removed reasoning_effort from parameters [PR](https://github.com/BerriAI/litellm/pull/9811) + 2. Fixed custom endpoint check for Databricks [PR](https://github.com/BerriAI/litellm/pull/9925) + +- **General** + 1. Added litellm.supports_reasoning() util to track if an llm supports reasoning [Get Started](https://docs.litellm.ai/docs/providers/anthropic#reasoning) + 2. Function Calling - Handle pydantic base model in message tool calls, handle tools = [], and support fake streaming on tool calls for meta.llama3-3-70b-instruct-v1:0 [PR](https://github.com/BerriAI/litellm/pull/9774) + 3. LiteLLM Proxy - Allow passing `thinking` param to litellm proxy via client sdk [PR](https://github.com/BerriAI/litellm/pull/9386) + 4. Fixed correctly translating 'thinking' param for litellm [PR](https://github.com/BerriAI/litellm/pull/9904) + + +## Spend Tracking Improvements +- **OpenAI, Azure** + 1. Realtime API Cost tracking with token usage metrics in spend logs [Get Started](https://docs.litellm.ai/docs/realtime) +- **Anthropic** + 1. Fixed Claude Haiku cache read pricing per token [PR](https://github.com/BerriAI/litellm/pull/9834) + 2. Added cost tracking for Claude responses with base_model [PR](https://github.com/BerriAI/litellm/pull/9897) + 3. Fixed Anthropic prompt caching cost calculation and trimmed logged message in db [PR](https://github.com/BerriAI/litellm/pull/9838) +- **General** + 1. Added token tracking and log usage object in spend logs [PR](https://github.com/BerriAI/litellm/pull/9843) + 2. Handle custom pricing at deployment level [PR](https://github.com/BerriAI/litellm/pull/9855) + + +## Management Endpoints / UI + +- **Test Key Tab** + 1. Added rendering of Reasoning content, ttft, usage metrics on test key page [PR](https://github.com/BerriAI/litellm/pull/9931) + + +

+ View input, output, reasoning tokens, ttft metrics. +

+- **Tag / Policy Management** + 1. Added Tag/Policy Management. Create routing rules based on request metadata. This allows you to enforce that requests with `tags="private"` only go to specific models. [Get Started](https://docs.litellm.ai/docs/tutorials/tag_management) + +
+ + +

+ Create and manage tags. +

+- **Redesigned Login Screen** + 1. Polished login screen [PR](https://github.com/BerriAI/litellm/pull/9778) +- **Microsoft SSO Auto-Sync** + 1. Added debug route to allow admins to debug SSO JWT fields [PR](https://github.com/BerriAI/litellm/pull/9835) + 2. Added ability to use MSFT Graph API to assign users to teams [PR](https://github.com/BerriAI/litellm/pull/9865) + 3. Connected litellm to Azure Entra ID Enterprise Application [PR](https://github.com/BerriAI/litellm/pull/9872) + 4. Added ability for admins to set `default_team_params` for when litellm SSO creates default teams [PR](https://github.com/BerriAI/litellm/pull/9895) + 5. Fixed MSFT SSO to use correct field for user email [PR](https://github.com/BerriAI/litellm/pull/9886) + 6. Added UI support for setting Default Team setting when litellm SSO auto creates teams [PR](https://github.com/BerriAI/litellm/pull/9918) +- **UI Bug Fixes** + 1. Prevented team, key, org, model numerical values changing on scrolling [PR](https://github.com/BerriAI/litellm/pull/9776) + 2. Instantly reflect key and team updates in UI [PR](https://github.com/BerriAI/litellm/pull/9825) + +## Logging / Guardrail Improvements + +- **Prometheus** + 1. Emit Key and Team Budget metrics on a cron job schedule [Get Started](https://docs.litellm.ai/docs/proxy/prometheus#initialize-budget-metrics-on-startup) + +## Security Fixes + +- Fixed [CVE-2025-0330](https://www.cve.org/CVERecord?id=CVE-2025-0330) - Leakage of Langfuse API keys in team exception handling [PR](https://github.com/BerriAI/litellm/pull/9830) +- Fixed [CVE-2024-6825](https://www.cve.org/CVERecord?id=CVE-2024-6825) - Remote code execution in post call rules [PR](https://github.com/BerriAI/litellm/pull/9826) + +## Helm + +- Added service annotations to litellm-helm chart [PR](https://github.com/BerriAI/litellm/pull/9840) +- Added extraEnvVars to the helm deployment [PR](https://github.com/BerriAI/litellm/pull/9292) + +## Demo + +Try this on the demo instance [today](https://docs.litellm.ai/docs/proxy/demo) + +## Complete Git Diff + +See the complete git diff since v1.65.4-stable, [here](https://github.com/BerriAI/litellm/releases/tag/v1.66.0-stable) + + diff --git a/docs/my-website/release_notes/v1.67.0-stable/index.md b/docs/my-website/release_notes/v1.67.0-stable/index.md new file mode 100644 index 00000000000..cb7938fce57 --- /dev/null +++ b/docs/my-website/release_notes/v1.67.0-stable/index.md @@ -0,0 +1,153 @@ +--- +title: v1.67.0-stable - SCIM Integration +slug: v1.67.0-stable +date: 2025-04-19T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +tags: ["sso", "unified_file_id", "cost_tracking", "security"] +hide_table_of_contents: false +--- +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## Key Highlights + +- **SCIM Integration**: Enables identity providers (Okta, Azure AD, OneLogin, etc.) to automate user and team (group) provisioning, updates, and deprovisioning +- **Team and Tag based usage tracking**: You can now see usage and spend by team and tag at 1M+ spend logs. +- **Unified Responses API**: Support for calling Anthropic, Gemini, Groq, etc. via OpenAI's new Responses API. + +Let's dive in. + +## SCIM Integration + + + +This release adds SCIM support to LiteLLM. This allows your SSO provider (Okta, Azure AD, etc) to automatically create/delete users, teams, and memberships on LiteLLM. This means that when you remove a team on your SSO provider, your SSO provider will automatically delete the corresponding team on LiteLLM. + +[Read more](../../docs/tutorials/scim_litellm) +## Team and Tag based usage tracking + + + + +This release improves team and tag based usage tracking at 1m+ spend logs, making it easy to monitor your LLM API Spend in production. This covers: + +- View **daily spend** by teams + tags +- View **usage / spend by key**, within teams +- View **spend by multiple tags** +- Allow **internal users** to view spend of teams they're a member of + +[Read more](#management-endpoints--ui) + +## Unified Responses API + +This release allows you to call Azure OpenAI, Anthropic, AWS Bedrock, and Google Vertex AI models via the POST /v1/responses endpoint on LiteLLM. This means you can now use popular tools like [OpenAI Codex](https://docs.litellm.ai/docs/tutorials/openai_codex) with your own models. + + + + +[Read more](https://docs.litellm.ai/docs/response_api) + + +## New Models / Updated Models + +- **OpenAI** + 1. gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, o3, o3-mini, o4-mini pricing - [Get Started](../../docs/providers/openai#usage), [PR](https://github.com/BerriAI/litellm/pull/9990) + 2. o4 - correctly map o4 to openai o_series model +- **Azure AI** + 1. Phi-4 output cost per token fix - [PR](https://github.com/BerriAI/litellm/pull/9880) + 2. Responses API support [Get Started](../../docs/providers/azure#azure-responses-api),[PR](https://github.com/BerriAI/litellm/pull/10116) +- **Anthropic** + 1. redacted message thinking support - [Get Started](../../docs/providers/anthropic#usage---thinking--reasoning_content),[PR](https://github.com/BerriAI/litellm/pull/10129) +- **Cohere** + 1. `/v2/chat` Passthrough endpoint support w/ cost tracking - [Get Started](../../docs/pass_through/cohere), [PR](https://github.com/BerriAI/litellm/pull/9997) +- **Azure** + 1. Support azure tenant_id/client_id env vars - [Get Started](../../docs/providers/azure#entra-id---use-tenant_id-client_id-client_secret), [PR](https://github.com/BerriAI/litellm/pull/9993) + 2. Fix response_format check for 2025+ api versions - [PR](https://github.com/BerriAI/litellm/pull/9993) + 3. Add gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, o3, o3-mini, o4-mini pricing +- **VLLM** + 1. Files - Support 'file' message type for VLLM video url's - [Get Started](../../docs/providers/vllm#send-video-url-to-vllm), [PR](https://github.com/BerriAI/litellm/pull/10129) + 2. Passthrough - new `/vllm/` passthrough endpoint support [Get Started](../../docs/pass_through/vllm), [PR](https://github.com/BerriAI/litellm/pull/10002) +- **Mistral** + 1. new `/mistral` passthrough endpoint support [Get Started](../../docs/pass_through/mistral), [PR](https://github.com/BerriAI/litellm/pull/10002) +- **AWS** + 1. New mapped bedrock regions - [PR](https://github.com/BerriAI/litellm/pull/9430) +- **VertexAI / Google AI Studio** + 1. Gemini - Response format - Retain schema field ordering for google gemini and vertex by specifying propertyOrdering - [Get Started](../../docs/providers/vertex#json-schema), [PR](https://github.com/BerriAI/litellm/pull/9828) + 2. Gemini-2.5-flash - return reasoning content [Google AI Studio](../../docs/providers/gemini#usage---thinking--reasoning_content), [Vertex AI](../../docs/providers/vertex#thinking--reasoning_content) + 3. Gemini-2.5-flash - pricing + model information [PR](https://github.com/BerriAI/litellm/pull/10125) + 4. Passthrough - new `/vertex_ai/discovery` route - enables calling AgentBuilder API routes [Get Started](../../docs/pass_through/vertex_ai#supported-api-endpoints), [PR](https://github.com/BerriAI/litellm/pull/10084) +- **Fireworks AI** + 1. return tool calling responses in `tool_calls` field (fireworks incorrectly returns this as a json str in content) [PR](https://github.com/BerriAI/litellm/pull/10130) +- **Triton** + 1. Remove fixed remove bad_words / stop words from `/generate` call - [Get Started](../../docs/providers/triton-inference-server#triton-generate---chat-completion), [PR](https://github.com/BerriAI/litellm/pull/10163) +- **Other** + 1. Support for all litellm providers on Responses API (works with Codex) - [Get Started](../../docs/tutorials/openai_codex), [PR](https://github.com/BerriAI/litellm/pull/10132) + 2. Fix combining multiple tool calls in streaming response - [Get Started](../../docs/completion/stream#helper-function), [PR](https://github.com/BerriAI/litellm/pull/10040) + + +## Spend Tracking Improvements + +- **Cost Control** - inject cache control points in prompt for cost reduction [Get Started](../../docs/tutorials/prompt_caching), [PR](https://github.com/BerriAI/litellm/pull/10000) +- **Spend Tags** - spend tags in headers - support x-litellm-tags even if tag based routing not enabled [Get Started](../../docs/proxy/request_headers#litellm-headers), [PR](https://github.com/BerriAI/litellm/pull/10000) +- **Gemini-2.5-flash** - support cost calculation for reasoning tokens [PR](https://github.com/BerriAI/litellm/pull/10141) + +## Management Endpoints / UI +- **Users** + 1. Show created_at and updated_at on users page - [PR](https://github.com/BerriAI/litellm/pull/10033) +- **Virtual Keys** + 1. Filter by key alias - https://github.com/BerriAI/litellm/pull/10085 +- **Usage Tab** + + 1. Team based usage + + - New `LiteLLM_DailyTeamSpend` Table for aggregate team based usage logging - [PR](https://github.com/BerriAI/litellm/pull/10039) + + - New Team based usage dashboard + new `/team/daily/activity` API - [PR](https://github.com/BerriAI/litellm/pull/10081) + - Return team alias on /team/daily/activity API - [PR](https://github.com/BerriAI/litellm/pull/10157) + - allow internal user view spend for teams they belong to - [PR](https://github.com/BerriAI/litellm/pull/10157) + - allow viewing top keys by team - [PR](https://github.com/BerriAI/litellm/pull/10157) + + + + 2. Tag Based Usage + - New `LiteLLM_DailyTagSpend` Table for aggregate tag based usage logging - [PR](https://github.com/BerriAI/litellm/pull/10071) + - Restrict to only Proxy Admins - [PR](https://github.com/BerriAI/litellm/pull/10157) + - allow viewing top keys by tag + - Return tags passed in request (i.e. dynamic tags) on `/tag/list` API - [PR](https://github.com/BerriAI/litellm/pull/10157) + + 3. Track prompt caching metrics in daily user, team, tag tables - [PR](https://github.com/BerriAI/litellm/pull/10029) + 4. Show usage by key (on all up, team, and tag usage dashboards) - [PR](https://github.com/BerriAI/litellm/pull/10157) + 5. swap old usage with new usage tab +- **Models** + 1. Make columns resizable/hideable - [PR](https://github.com/BerriAI/litellm/pull/10119) +- **API Playground** + 1. Allow internal user to call api playground - [PR](https://github.com/BerriAI/litellm/pull/10157) +- **SCIM** + 1. Add LiteLLM SCIM Integration for Team and User management - [Get Started](../../docs/tutorials/scim_litellm), [PR](https://github.com/BerriAI/litellm/pull/10072) + + +## Logging / Guardrail Integrations +- **GCS** + 1. Fix gcs pub sub logging with env var GCS_PROJECT_ID - [Get Started](../../docs/observability/gcs_bucket_integration#usage), [PR](https://github.com/BerriAI/litellm/pull/10042) +- **AIM** + 1. Add litellm call id passing to Aim guardrails on pre and post-hooks calls - [Get Started](../../docs/proxy/guardrails/aim_security), [PR](https://github.com/BerriAI/litellm/pull/10021) +- **Azure blob storage** + 1. Ensure logging works in high throughput scenarios - [Get Started](../../docs/proxy/logging#azure-blob-storage), [PR](https://github.com/BerriAI/litellm/pull/9962) + +## General Proxy Improvements + +- **Support setting `litellm.modify_params` via env var** [PR](https://github.com/BerriAI/litellm/pull/9964) +- **Model Discovery** - Check provider’s `/models` endpoints when calling proxy’s `/v1/models` endpoint - [Get Started](../../docs/proxy/model_discovery), [PR](https://github.com/BerriAI/litellm/pull/9958) +- **`/utils/token_counter`** - fix retrieving custom tokenizer for db models - [Get Started](../../docs/proxy/configs#set-custom-tokenizer), [PR](https://github.com/BerriAI/litellm/pull/10047) +- **Prisma migrate** - handle existing columns in db table - [PR](https://github.com/BerriAI/litellm/pull/10138) + diff --git a/docs/my-website/release_notes/v1.67.4-stable/index.md b/docs/my-website/release_notes/v1.67.4-stable/index.md new file mode 100644 index 00000000000..6750ced47c7 --- /dev/null +++ b/docs/my-website/release_notes/v1.67.4-stable/index.md @@ -0,0 +1,197 @@ +--- +title: v1.67.4-stable - Improved User Management +slug: v1.67.4-stable +date: 2025-04-26T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +tags: ["responses_api", "ui_improvements", "security", "session_management"] +hide_table_of_contents: false +--- +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.67.4-stable +``` + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.67.4.post1 +``` + + + +## Key Highlights + +- **Improved User Management**: This release enables search and filtering across users, keys, teams, and models. +- **Responses API Load Balancing**: Route requests across provider regions and ensure session continuity. +- **UI Session Logs**: Group several requests to LiteLLM into a session. + +## Improved User Management + + +
+ +This release makes it easier to manage users and keys on LiteLLM. You can now search and filter across users, keys, teams, and models, and control user settings more easily. + +New features include: + +- Search for users by email, ID, role, or team. +- See all of a user's models, teams, and keys in one place. +- Change user roles and model access right from the Users Tab. + +These changes help you spend less time on user setup and management on LiteLLM. + +## Responses API Load Balancing + + +
+ +This release introduces load balancing for the Responses API, allowing you to route requests across provider regions and ensure session continuity. It works as follows: + +- If a `previous_response_id` is provided, LiteLLM will route the request to the original deployment that generated the prior response — ensuring session continuity. +- If no `previous_response_id` is provided, LiteLLM will load-balance requests across your available deployments. + +[Read more](https://docs.litellm.ai/docs/response_api#load-balancing-with-session-continuity) + +## UI Session Logs + + +
+ +This release allow you to group requests to LiteLLM proxy into a session. If you specify a litellm_session_id in your request LiteLLM will automatically group all logs in the same session. This allows you to easily track usage and request content per session. + +[Read more](https://docs.litellm.ai/docs/proxy/ui_logs_sessions) + +## New Models / Updated Models + +- **OpenAI** + 1. Added `gpt-image-1` cost tracking [Get Started](https://docs.litellm.ai/docs/image_generation) + 2. Bug fix: added cost tracking for gpt-image-1 when quality is unspecified [PR](https://github.com/BerriAI/litellm/pull/10247) +- **Azure** + 1. Fixed timestamp granularities passing to whisper in Azure [Get Started](https://docs.litellm.ai/docs/audio_transcription) + 2. Added azure/gpt-image-1 pricing [Get Started](https://docs.litellm.ai/docs/image_generation), [PR](https://github.com/BerriAI/litellm/pull/10327) + 3. Added cost tracking for `azure/computer-use-preview`, `azure/gpt-4o-audio-preview-2024-12-17`, `azure/gpt-4o-mini-audio-preview-2024-12-17` [PR](https://github.com/BerriAI/litellm/pull/10178) +- **Bedrock** + 1. Added support for all compatible Bedrock parameters when model="arn:.." (Bedrock application inference profile models) [Get started](https://docs.litellm.ai/docs/providers/bedrock#bedrock-application-inference-profile), [PR](https://github.com/BerriAI/litellm/pull/10256) + 2. Fixed wrong system prompt transformation [PR](https://github.com/BerriAI/litellm/pull/10120) +- **VertexAI / Google AI Studio** + 1. Allow setting `budget_tokens=0` for `gemini-2.5-flash` [Get Started](https://docs.litellm.ai/docs/providers/gemini#usage---thinking--reasoning_content),[PR](https://github.com/BerriAI/litellm/pull/10198) + 2. Ensure returned `usage` includes thinking token usage [PR](https://github.com/BerriAI/litellm/pull/10198) + 3. Added cost tracking for `gemini-2.5-pro-preview-03-25` [PR](https://github.com/BerriAI/litellm/pull/10178) +- **Cohere** + 1. Added support for cohere command-a-03-2025 [Get Started](https://docs.litellm.ai/docs/providers/cohere), [PR](https://github.com/BerriAI/litellm/pull/10295) +- **SageMaker** + 1. Added support for max_completion_tokens parameter [Get Started](https://docs.litellm.ai/docs/providers/sagemaker), [PR](https://github.com/BerriAI/litellm/pull/10300) +- **Responses API** + 1. Added support for GET and DELETE operations - `/v1/responses/{response_id}` [Get Started](../../docs/response_api) + 2. Added session management support for non-OpenAI models [PR](https://github.com/BerriAI/litellm/pull/10321) + 3. Added routing affinity to maintain model consistency within sessions [Get Started](https://docs.litellm.ai/docs/response_api#load-balancing-with-routing-affinity), [PR](https://github.com/BerriAI/litellm/pull/10193) + + +## Spend Tracking Improvements + +- **Bug Fix**: Fixed spend tracking bug, ensuring default litellm params aren't modified in memory [PR](https://github.com/BerriAI/litellm/pull/10167) +- **Deprecation Dates**: Added deprecation dates for Azure, VertexAI models [PR](https://github.com/BerriAI/litellm/pull/10308) + +## Management Endpoints / UI + +#### Users +- **Filtering and Searching**: + - Filter users by user_id, role, team, sso_id + - Search users by email + +
+ + + +- **User Info Panel**: Added a new user information pane [PR](https://github.com/BerriAI/litellm/pull/10213) + - View teams, keys, models associated with User + - Edit user role, model permissions + + + +#### Teams +- **Filtering and Searching**: + - Filter teams by Organization, Team ID [PR](https://github.com/BerriAI/litellm/pull/10324) + - Search teams by Team Name [PR](https://github.com/BerriAI/litellm/pull/10324) + +
+ + + + + +#### Keys +- **Key Management**: + - Support for cross-filtering and filtering by key hash [PR](https://github.com/BerriAI/litellm/pull/10322) + - Fixed key alias reset when resetting filters [PR](https://github.com/BerriAI/litellm/pull/10099) + - Fixed table rendering on key creation [PR](https://github.com/BerriAI/litellm/pull/10224) + +#### UI Logs Page + +- **Session Logs**: Added UI Session Logs [Get Started](https://docs.litellm.ai/docs/proxy/ui_logs_sessions) + + +#### UI Authentication & Security +- **Required Authentication**: Authentication now required for all dashboard pages [PR](https://github.com/BerriAI/litellm/pull/10229) +- **SSO Fixes**: Fixed SSO user login invalid token error [PR](https://github.com/BerriAI/litellm/pull/10298) +- [BETA] **Encrypted Tokens**: Moved UI to encrypted token usage [PR](https://github.com/BerriAI/litellm/pull/10302) +- **Token Expiry**: Support token refresh by re-routing to login page (fixes issue where expired token would show a blank page) [PR](https://github.com/BerriAI/litellm/pull/10250) + +#### UI General fixes +- **Fixed UI Flicker**: Addressed UI flickering issues in Dashboard [PR](https://github.com/BerriAI/litellm/pull/10261) +- **Improved Terminology**: Better loading and no-data states on Keys and Tools pages [PR](https://github.com/BerriAI/litellm/pull/10253) +- **Azure Model Support**: Fixed editing Azure public model names and changing model names after creation [PR](https://github.com/BerriAI/litellm/pull/10249) +- **Team Model Selector**: Bug fix for team model selection [PR](https://github.com/BerriAI/litellm/pull/10171) + + +## Logging / Guardrail Integrations + +- **Datadog**: + 1. Fixed Datadog LLM observability logging [Get Started](https://docs.litellm.ai/docs/proxy/logging#datadog), [PR](https://github.com/BerriAI/litellm/pull/10206) +- **Prometheus / Grafana**: + 1. Enable datasource selection on LiteLLM Grafana Template [Get Started](https://docs.litellm.ai/docs/proxy/prometheus#-litellm-maintained-grafana-dashboards-), [PR](https://github.com/BerriAI/litellm/pull/10257) +- **AgentOps**: + 1. Added AgentOps Integration [Get Started](https://docs.litellm.ai/docs/observability/agentops_integration), [PR](https://github.com/BerriAI/litellm/pull/9685) +- **Arize**: + 1. Added missing attributes for Arize & Phoenix Integration [Get Started](https://docs.litellm.ai/docs/observability/arize_integration), [PR](https://github.com/BerriAI/litellm/pull/10215) + + +## General Proxy Improvements + +- **Caching**: Fixed caching to account for `thinking` or `reasoning_effort` when calculating cache key [PR](https://github.com/BerriAI/litellm/pull/10140) +- **Model Groups**: Fixed handling for cases where user sets model_group inside model_info [PR](https://github.com/BerriAI/litellm/pull/10191) +- **Passthrough Endpoints**: Ensured `PassthroughStandardLoggingPayload` is logged with method, URL, request/response body [PR](https://github.com/BerriAI/litellm/pull/10194) +- **Fix SQL Injection**: Fixed potential SQL injection vulnerability in spend_management_endpoints.py [PR](https://github.com/BerriAI/litellm/pull/9878) + + + +## Helm + +- Fixed serviceAccountName on migration job [PR](https://github.com/BerriAI/litellm/pull/10258) + +## Full Changelog + +The complete list of changes can be found in the [GitHub release notes](https://github.com/BerriAI/litellm/compare/v1.67.0-stable...v1.67.4-stable). \ No newline at end of file diff --git a/docs/my-website/release_notes/v1.68.0-stable/index.md b/docs/my-website/release_notes/v1.68.0-stable/index.md new file mode 100644 index 00000000000..4d456d9c853 --- /dev/null +++ b/docs/my-website/release_notes/v1.68.0-stable/index.md @@ -0,0 +1,182 @@ +--- +title: v1.68.0-stable +slug: v1.68.0-stable +date: 2025-05-03T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +hide_table_of_contents: false +--- +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.68.0-stable +``` + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.68.0.post1 +``` + + + +## Key Highlights + +LiteLLM v1.68.0-stable will be live soon. Here are the key highlights of this release: + +- **Bedrock Knowledge Base**: You can now call query your Bedrock Knowledge Base with all LiteLLM models via `/chat/completion` or `/responses` API. +- **Rate Limits**: This release brings accurate rate limiting across multiple instances, reducing spillover to at most 10 additional requests in high traffic. +- **Meta Llama API**: Added support for Meta Llama API [Get Started](https://docs.litellm.ai/docs/providers/meta_llama) +- **LlamaFile**: Added support for LlamaFile [Get Started](https://docs.litellm.ai/docs/providers/llamafile) + +## Bedrock Knowledge Base (Vector Store) + + +
+ +This release adds support for Bedrock vector stores (knowledge bases) in LiteLLM. With this update, you can: + +- Use Bedrock vector stores in the OpenAI /chat/completions spec with all LiteLLM supported models. +- View all available vector stores through the LiteLLM UI or API. +- Configure vector stores to be always active for specific models. +- Track vector store usage in LiteLLM Logs. + +For the next release we plan on allowing you to set key, user, team, org permissions for vector stores. + +[Read more here](https://docs.litellm.ai/docs/completion/knowledgebase) + +## Rate Limiting + + +
+ + +This release brings accurate multi-instance rate limiting across keys/users/teams. Outlining key engineering changes below: + +- **Change**: Instances now increment cache value instead of setting it. To avoid calling Redis on each request, this is synced every 0.01s. +- **Accuracy**: In testing, we saw a maximum spill over from expected of 10 requests, in high traffic (100 RPS, 3 instances), vs. current 189 request spillover +- **Performance**: Our load tests show this to reduce median response time by 100ms in high traffic  + +This is currently behind a feature flag, and we plan to have this be the default by next week. To enable this today, just add this environment variable: + +``` +export LITELLM_RATE_LIMIT_ACCURACY=true +``` + +[Read more here](../../docs/proxy/users#beta-multi-instance-rate-limiting) + + + +## New Models / Updated Models +- **Gemini ([VertexAI](https://docs.litellm.ai/docs/providers/vertex#usage-with-litellm-proxy-server) + [Google AI Studio](https://docs.litellm.ai/docs/providers/gemini))** + - Handle more json schema - openapi schema conversion edge cases [PR](https://github.com/BerriAI/litellm/pull/10351) + - Tool calls - return ‘finish_reason=“tool_calls”’ on gemini tool calling response [PR](https://github.com/BerriAI/litellm/pull/10485) +- **[VertexAI](../../docs/providers/vertex#metallama-api)** + - Meta/llama-4 model support [PR](https://github.com/BerriAI/litellm/pull/10492) + - Meta/llama3 - handle tool call result in content [PR](https://github.com/BerriAI/litellm/pull/10492) + - Meta/* - return ‘finish_reason=“tool_calls”’ on tool calling response [PR](https://github.com/BerriAI/litellm/pull/10492) +- **[Bedrock](../../docs/providers/bedrock#litellm-proxy-usage)** + - [Image Generation](../../docs/providers/bedrock#image-generation) - Support new ‘stable-image-core’ models - [PR](https://github.com/BerriAI/litellm/pull/10351) + - [Knowledge Bases](../../docs/completion/knowledgebase) - support using Bedrock knowledge bases with `/chat/completions` [PR](https://github.com/BerriAI/litellm/pull/10413) + - [Anthropic](../../docs/providers/bedrock#litellm-proxy-usage) - add ‘supports_pdf_input’ for claude-3.7-bedrock models [PR](https://github.com/BerriAI/litellm/pull/9917), [Get Started](../../docs/completion/document_understanding#checking-if-a-model-supports-pdf-input) +- **[OpenAI](../../docs/providers/openai)** + - Support OPENAI_BASE_URL in addition to OPENAI_API_BASE [PR](https://github.com/BerriAI/litellm/pull/10423) + - Correctly re-raise 504 timeout errors [PR](https://github.com/BerriAI/litellm/pull/10462) + - Native Gpt-4o-mini-tts support [PR](https://github.com/BerriAI/litellm/pull/10462) +- 🆕 **[Meta Llama API](../../docs/providers/meta_llama)** provider [PR](https://github.com/BerriAI/litellm/pull/10451) +- 🆕 **[LlamaFile](../../docs/providers/llamafile)** provider [PR](https://github.com/BerriAI/litellm/pull/10482) + +## LLM API Endpoints +- **[Response API](../../docs/response_api)** + - Fix for handling multi turn sessions [PR](https://github.com/BerriAI/litellm/pull/10415) +- **[Embeddings](../../docs/embedding/supported_embedding)** + - Caching fixes - [PR](https://github.com/BerriAI/litellm/pull/10424) + - handle str -> list cache + - Return usage tokens for cache hit + - Combine usage tokens on partial cache hits +- 🆕 **[Vector Stores](../../docs/completion/knowledgebase)** + - Allow defining Vector Store Configs - [PR](https://github.com/BerriAI/litellm/pull/10448) + - New StandardLoggingPayload field for requests made when a vector store is used - [PR](https://github.com/BerriAI/litellm/pull/10509) + - Show Vector Store / KB Request on LiteLLM Logs Page - [PR](https://github.com/BerriAI/litellm/pull/10514) + - Allow using vector store in OpenAI API spec with tools - [PR](https://github.com/BerriAI/litellm/pull/10516) +- **[MCP](../../docs/mcp)** + - Ensure Non-Admin virtual keys can access /mcp routes - [PR](https://github.com/BerriAI/litellm/pull/10473) + + **Note:** Currently, all Virtual Keys are able to access the MCP endpoints. We are working on a feature to allow restricting MCP access by keys/teams/users/orgs. Follow [here](https://github.com/BerriAI/litellm/discussions/9891) for updates. +- **Moderations** + - Add logging callback support for `/moderations` API - [PR](https://github.com/BerriAI/litellm/pull/10390) + + +## Spend Tracking / Budget Improvements +- **[OpenAI](../../docs/providers/openai)** + - [computer-use-preview](../../docs/providers/openai/responses_api#computer-use) cost tracking / pricing [PR](https://github.com/BerriAI/litellm/pull/10422) + - [gpt-4o-mini-tts](../../docs/providers/openai/text_to_speech) input cost tracking - [PR](https://github.com/BerriAI/litellm/pull/10462) +- **[Fireworks AI](../../docs/providers/fireworks_ai)** - pricing updates - new `0-4b` model pricing tier + llama4 model pricing +- **[Budgets](../../docs/proxy/users#set-budgets)** + - [Budget resets](../../docs/proxy/users#reset-budgets) now happen as start of day/week/month - [PR](https://github.com/BerriAI/litellm/pull/10333) + - Trigger [Soft Budget Alerts](../../docs/proxy/alerting#soft-budget-alerts-for-virtual-keys) When Key Crosses Threshold - [PR](https://github.com/BerriAI/litellm/pull/10491) +- **[Token Counting](../../docs/completion/token_usage#3-token_counter)** + - Rewrite of token_counter() function to handle to prevent undercounting tokens - [PR](https://github.com/BerriAI/litellm/pull/10409) + + +## Management Endpoints / UI +- **Virtual Keys** + - Fix filtering on key alias - [PR](https://github.com/BerriAI/litellm/pull/10455) + - Support global filtering on keys - [PR](https://github.com/BerriAI/litellm/pull/10455) + - Pagination - fix clicking on next/back buttons on table - [PR](https://github.com/BerriAI/litellm/pull/10528) +- **Models** + - Triton - Support adding model/provider on UI - [PR](https://github.com/BerriAI/litellm/pull/10456) + - VertexAI - Fix adding vertex models with reusable credentials - [PR](https://github.com/BerriAI/litellm/pull/10528) + - LLM Credentials - show existing credentials for easy editing - [PR](https://github.com/BerriAI/litellm/pull/10519) +- **Teams** + - Allow reassigning team to other org - [PR](https://github.com/BerriAI/litellm/pull/10527) +- **Organizations** + - Fix showing org budget on table - [PR](https://github.com/BerriAI/litellm/pull/10528) + + + +## Logging / Guardrail Integrations +- **[Langsmith](../../docs/observability/langsmith_integration)** + - Respect [langsmith_batch_size](../../docs/observability/langsmith_integration#local-testing---control-batch-size) param - [PR](https://github.com/BerriAI/litellm/pull/10411) + +## Performance / Loadbalancing / Reliability improvements +- **[Redis](../../docs/proxy/caching)** + - Ensure all redis queues are periodically flushed, this fixes an issue where redis queue size was growing indefinitely when request tags were used - [PR](https://github.com/BerriAI/litellm/pull/10393) +- **[Rate Limits](../../docs/proxy/users#set-rate-limit)** + - [Multi-instance rate limiting](../../docs/proxy/users#beta-multi-instance-rate-limiting) support across keys/teams/users/customers - [PR](https://github.com/BerriAI/litellm/pull/10458), [PR](https://github.com/BerriAI/litellm/pull/10497), [PR](https://github.com/BerriAI/litellm/pull/10500) +- **[Azure OpenAI OIDC](../../docs/providers/azure#entra-id---use-azure_ad_token)** + - allow using litellm defined params for [OIDC Auth](../../docs/providers/azure#entra-id---use-azure_ad_token) - [PR](https://github.com/BerriAI/litellm/pull/10394) + + +## General Proxy Improvements +- **Security** + - Allow [blocking web crawlers](../../docs/proxy/enterprise#blocking-web-crawlers) - [PR](https://github.com/BerriAI/litellm/pull/10420) +- **Auth** + - Support [`x-litellm-api-key` header param by default](../../docs/pass_through/vertex_ai#use-with-virtual-keys), this fixes an issue from the prior release where `x-litellm-api-key` was not being used on vertex ai passthrough requests - [PR](https://github.com/BerriAI/litellm/pull/10392) + - Allow key at max budget to call non-llm api endpoints - [PR](https://github.com/BerriAI/litellm/pull/10392) +- 🆕 **[Python Client Library](../../docs/proxy/management_cli) for LiteLLM Proxy management endpoints** + - Initial PR - [PR](https://github.com/BerriAI/litellm/pull/10445) + - Support for doing HTTP requests - [PR](https://github.com/BerriAI/litellm/pull/10452) +- **Dependencies** + - Don’t require uvloop for windows - [PR](https://github.com/BerriAI/litellm/pull/10483) diff --git a/docs/my-website/release_notes/v1.69.0-stable/index.md b/docs/my-website/release_notes/v1.69.0-stable/index.md new file mode 100644 index 00000000000..3f8ce7a29c4 --- /dev/null +++ b/docs/my-website/release_notes/v1.69.0-stable/index.md @@ -0,0 +1,200 @@ +--- +title: v1.69.0-stable - Loadbalance Batch API Models +slug: v1.69.0-stable +date: 2025-05-10T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +hide_table_of_contents: false +--- +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.69.0-stable +``` + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.69.0.post1 +``` + + + +## Key Highlights + +LiteLLM v1.69.0-stable brings the following key improvements: + +- **Loadbalance Batch API Models**: Easily loadbalance across multiple azure batch deployments using LiteLLM Managed Files +- **Email Invites 2.0**: Send new users onboarded to LiteLLM an email invite. +- **Nscale**: LLM API for compliance with European regulations. +- **Bedrock /v1/messages**: Use Bedrock Anthropic models with Anthropic's /v1/messages. + +## Batch API Load Balancing + + + + +This release brings LiteLLM Managed File support to Batches. This is great for: + +- Proxy Admins: You can now control which Batch models users can call. +- Developers: You no longer need to know the Azure deployment name when creating your batch .jsonl files - just specify the model your LiteLLM key has access to. + +Over time, we expect LiteLLM Managed Files to be the way most teams use Files across `/chat/completions`, `/batch`, `/fine_tuning` endpoints. + +[Read more here](https://docs.litellm.ai/docs/proxy/managed_batches) + + +## Email Invites + + + +This release brings the following improvements to our email invite integration: +- New templates for user invited and key created events. +- Fixes for using SMTP email providers. +- Native support for Resend API. +- Ability for Proxy Admins to control email events. + +For LiteLLM Cloud Users, please reach out to us if you want this enabled for your instance. + +[Read more here](https://docs.litellm.ai/docs/proxy/email) + + +## New Models / Updated Models +- **Gemini ([VertexAI](https://docs.litellm.ai/docs/providers/vertex#usage-with-litellm-proxy-server) + [Google AI Studio](https://docs.litellm.ai/docs/providers/gemini))** + - Added `gemini-2.5-pro-preview-05-06` models with pricing and context window info - [PR](https://github.com/BerriAI/litellm/pull/10597) + - Set correct context window length for all Gemini 2.5 variants - [PR](https://github.com/BerriAI/litellm/pull/10690) +- **[Perplexity](../../docs/providers/perplexity)**: + - Added new Perplexity models - [PR](https://github.com/BerriAI/litellm/pull/10652) + - Added sonar-deep-research model pricing - [PR](https://github.com/BerriAI/litellm/pull/10537) +- **[Azure OpenAI](../../docs/providers/azure)**: + - Fixed passing through of azure_ad_token_provider parameter - [PR](https://github.com/BerriAI/litellm/pull/10694) +- **[OpenAI](../../docs/providers/openai)**: + - Added support for pdf url's in 'file' parameter - [PR](https://github.com/BerriAI/litellm/pull/10640) +- **[Sagemaker](../../docs/providers/aws_sagemaker)**: + - Fix content length for `sagemaker_chat` provider - [PR](https://github.com/BerriAI/litellm/pull/10607) +- **[Azure AI Foundry](../../docs/providers/azure_ai)**: + - Added cost tracking for the following models [PR](https://github.com/BerriAI/litellm/pull/9956) + - DeepSeek V3 0324 + - Llama 4 Scout + - Llama 4 Maverick +- **[Bedrock](../../docs/providers/bedrock)**: + - Added cost tracking for Bedrock Llama 4 models - [PR](https://github.com/BerriAI/litellm/pull/10582) + - Fixed template conversion for Llama 4 models in Bedrock - [PR](https://github.com/BerriAI/litellm/pull/10582) + - Added support for using Bedrock Anthropic models with /v1/messages format - [PR](https://github.com/BerriAI/litellm/pull/10681) + - Added streaming support for Bedrock Anthropic models with /v1/messages format - [PR](https://github.com/BerriAI/litellm/pull/10710) +- **[OpenAI](../../docs/providers/openai)**: Added `reasoning_effort` support for `o3` models - [PR](https://github.com/BerriAI/litellm/pull/10591) +- **[Databricks](../../docs/providers/databricks)**: + - Fixed issue when Databricks uses external model and delta could be empty - [PR](https://github.com/BerriAI/litellm/pull/10540) +- **[Cerebras](../../docs/providers/cerebras)**: Fixed Llama-3.1-70b model pricing and context window - [PR](https://github.com/BerriAI/litellm/pull/10648) +- **[Ollama](../../docs/providers/ollama)**: + - Fixed custom price cost tracking and added 'max_completion_token' support - [PR](https://github.com/BerriAI/litellm/pull/10636) + - Fixed KeyError when using JSON response format - [PR](https://github.com/BerriAI/litellm/pull/10611) +- 🆕 **[Nscale](../../docs/providers/nscale)**: + - Added support for chat, image generation endpoints - [PR](https://github.com/BerriAI/litellm/pull/10638) + +## LLM API Endpoints +- **[Messages API](../../docs/anthropic_unified)**: + - 🆕 Added support for using Bedrock Anthropic models with /v1/messages format - [PR](https://github.com/BerriAI/litellm/pull/10681) and streaming support - [PR](https://github.com/BerriAI/litellm/pull/10710) +- **[Moderations API](../../docs/moderations)**: + - Fixed bug to allow using LiteLLM UI credentials for /moderations API - [PR](https://github.com/BerriAI/litellm/pull/10723) +- **[Realtime API](../../docs/realtime)**: + - Fixed setting 'headers' in scope for websocket auth requests and infinite loop issues - [PR](https://github.com/BerriAI/litellm/pull/10679) +- **[Files API](../../docs/proxy/litellm_managed_files)**: + - Unified File ID output support - [PR](https://github.com/BerriAI/litellm/pull/10713) + - Support for writing files to all deployments - [PR](https://github.com/BerriAI/litellm/pull/10708) + - Added target model name validation - [PR](https://github.com/BerriAI/litellm/pull/10722) +- **[Batches API](../../docs/batches)**: + - Complete unified batch ID support - replacing model in jsonl to be deployment model name - [PR](https://github.com/BerriAI/litellm/pull/10719) + - Beta support for unified file ID (managed files) for batches - [PR](https://github.com/BerriAI/litellm/pull/10650) + + +## Spend Tracking / Budget Improvements +- Bug Fix - PostgreSQL Integer Overflow Error in DB Spend Tracking - [PR](https://github.com/BerriAI/litellm/pull/10697) + +## Management Endpoints / UI +- **Models** + - Fixed model info overwriting when editing a model on UI - [PR](https://github.com/BerriAI/litellm/pull/10726) + - Fixed team admin model updates and organization creation with specific models - [PR](https://github.com/BerriAI/litellm/pull/10539) +- **Logs**: + - Bug Fix - copying Request/Response on Logs Page - [PR](https://github.com/BerriAI/litellm/pull/10720) + - Bug Fix - log did not remain in focus on QA Logs page + text overflow on error logs - [PR](https://github.com/BerriAI/litellm/pull/10725) + - Added index for session_id on LiteLLM_SpendLogs for better query performance - [PR](https://github.com/BerriAI/litellm/pull/10727) +- **User Management**: + - Added user management functionality to Python client library & CLI - [PR](https://github.com/BerriAI/litellm/pull/10627) + - Bug Fix - Fixed SCIM token creation on Admin UI - [PR](https://github.com/BerriAI/litellm/pull/10628) + - Bug Fix - Added 404 response when trying to delete verification tokens that don't exist - [PR](https://github.com/BerriAI/litellm/pull/10605) + +## Logging / Guardrail Integrations +- **Custom Logger API**: v2 Custom Callback API (send llm logs to custom api) - [PR](https://github.com/BerriAI/litellm/pull/10575), [Get Started](https://docs.litellm.ai/docs/proxy/logging#custom-callback-apis-async) +- **OpenTelemetry**: + - Fixed OpenTelemetry to follow genai semantic conventions + support for 'instructions' param for TTS - [PR](https://github.com/BerriAI/litellm/pull/10608) +- ** Bedrock PII**: + - Add support for PII Masking with bedrock guardrails - [Get Started](https://docs.litellm.ai/docs/proxy/guardrails/bedrock#pii-masking-with-bedrock-guardrails), [PR](https://github.com/BerriAI/litellm/pull/10608) +- **Documentation**: + - Added documentation for StandardLoggingVectorStoreRequest - [PR](https://github.com/BerriAI/litellm/pull/10535) + +## Performance / Reliability Improvements +- **Python Compatibility**: + - Added support for Python 3.11- (fixed datetime UTC handling) - [PR](https://github.com/BerriAI/litellm/pull/10701) + - Fixed UnicodeDecodeError: 'charmap' on Windows during litellm import - [PR](https://github.com/BerriAI/litellm/pull/10542) +- **Caching**: + - Fixed embedding string caching result - [PR](https://github.com/BerriAI/litellm/pull/10700) + - Fixed cache miss for Gemini models with response_format - [PR](https://github.com/BerriAI/litellm/pull/10635) + +## General Proxy Improvements +- **Proxy CLI**: + - Added `--version` flag to `litellm-proxy` CLI - [PR](https://github.com/BerriAI/litellm/pull/10704) + - Added dedicated `litellm-proxy` CLI - [PR](https://github.com/BerriAI/litellm/pull/10578) +- **Alerting**: + - Fixed Slack alerting not working when using a DB - [PR](https://github.com/BerriAI/litellm/pull/10370) +- **Email Invites**: + - Added V2 Emails with fixes for sending emails when creating keys + Resend API support - [PR](https://github.com/BerriAI/litellm/pull/10602) + - Added user invitation emails - [PR](https://github.com/BerriAI/litellm/pull/10615) + - Added endpoints to manage email settings - [PR](https://github.com/BerriAI/litellm/pull/10646) +- **General**: + - Fixed bug where duplicate JSON logs were getting emitted - [PR](https://github.com/BerriAI/litellm/pull/10580) + + +## New Contributors +- [@zoltan-ongithub](https://github.com/zoltan-ongithub) made their first contribution in [PR #10568](https://github.com/BerriAI/litellm/pull/10568) +- [@mkavinkumar1](https://github.com/mkavinkumar1) made their first contribution in [PR #10548](https://github.com/BerriAI/litellm/pull/10548) +- [@thomelane](https://github.com/thomelane) made their first contribution in [PR #10549](https://github.com/BerriAI/litellm/pull/10549) +- [@frankzye](https://github.com/frankzye) made their first contribution in [PR #10540](https://github.com/BerriAI/litellm/pull/10540) +- [@aholmberg](https://github.com/aholmberg) made their first contribution in [PR #10591](https://github.com/BerriAI/litellm/pull/10591) +- [@aravindkarnam](https://github.com/aravindkarnam) made their first contribution in [PR #10611](https://github.com/BerriAI/litellm/pull/10611) +- [@xsg22](https://github.com/xsg22) made their first contribution in [PR #10648](https://github.com/BerriAI/litellm/pull/10648) +- [@casparhsws](https://github.com/casparhsws) made their first contribution in [PR #10635](https://github.com/BerriAI/litellm/pull/10635) +- [@hypermoose](https://github.com/hypermoose) made their first contribution in [PR #10370](https://github.com/BerriAI/litellm/pull/10370) +- [@tomukmatthews](https://github.com/tomukmatthews) made their first contribution in [PR #10638](https://github.com/BerriAI/litellm/pull/10638) +- [@keyute](https://github.com/keyute) made their first contribution in [PR #10652](https://github.com/BerriAI/litellm/pull/10652) +- [@GPTLocalhost](https://github.com/GPTLocalhost) made their first contribution in [PR #10687](https://github.com/BerriAI/litellm/pull/10687) +- [@husnain7766](https://github.com/husnain7766) made their first contribution in [PR #10697](https://github.com/BerriAI/litellm/pull/10697) +- [@claralp](https://github.com/claralp) made their first contribution in [PR #10694](https://github.com/BerriAI/litellm/pull/10694) +- [@mollux](https://github.com/mollux) made their first contribution in [PR #10690](https://github.com/BerriAI/litellm/pull/10690) diff --git a/docs/my-website/release_notes/v1.70.1-stable/index.md b/docs/my-website/release_notes/v1.70.1-stable/index.md new file mode 100644 index 00000000000..c55ac8b9c61 --- /dev/null +++ b/docs/my-website/release_notes/v1.70.1-stable/index.md @@ -0,0 +1,248 @@ +--- +title: v1.70.1-stable - Gemini Realtime API Support +slug: v1.70.1-stable +date: 2025-05-17T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://media.licdn.com/dms/image/v2/D4D03AQGrlsJ3aqpHmQ/profile-displayphoto-shrink_400_400/B4DZSAzgP7HYAg-/0/1737327772964?e=1749686400&v=beta&t=Hkl3U8Ps0VtvNxX0BNNq24b4dtX5wQaPFp6oiKCIHD8 + - name: Ishaan Jaffer + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg + +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run +-e STORE_MODEL_IN_DB=True +-p 4000:4000 +ghcr.io/berriai/litellm:main-v1.70.1-stable +``` + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.70.1 +``` + + + + +## Key Highlights + +LiteLLM v1.70.1-stable is live now. Here are the key highlights of this release: + +- **Gemini Realtime API**: You can now call Gemini's Live API via the OpenAI /v1/realtime API +- **Spend Logs Retention Period**: Enable deleting spend logs older than a certain period. +- **PII Masking 2.0**: Easily configure masking or blocking specific PII/PHI entities on the UI + +## Gemini Realtime API + + + + +This release brings support for calling Gemini's realtime models (e.g. gemini-2.0-flash-live) via OpenAI's /v1/realtime API. This is great for developers as it lets them easily switch from OpenAI to Gemini by just changing the model name. + +Key Highlights: +- Support for text + audio input/output +- Support for setting session configurations (modality, instructions, activity detection) in the OpenAI format +- Support for logging + usage tracking for realtime sessions + +This is currently supported via Google AI Studio. We plan to release VertexAI support over the coming week. + +[**Read more**](../../docs/providers/google_ai_studio/realtime) + +## Spend Logs Retention Period + + + + + +This release enables deleting LiteLLM Spend Logs older than a certain period. Since we now enable storing the raw request/response in the logs, deleting old logs ensures the database remains performant in production. + +[**Read more**](../../docs/proxy/spend_logs_deletion) + +## PII Masking 2.0 + + + +This release brings improvements to our Presidio PII Integration. As a Proxy Admin, you now have the ability to: + +- Mask or block specific entities (e.g., block medical licenses while masking other entities like emails). +- Monitor guardrails in production. LiteLLM Logs will now show you the guardrail run, the entities it detected, and its confidence score for each entity. + +[**Read more**](../../docs/proxy/guardrails/pii_masking_v2) + +## New Models / Updated Models + +- **Gemini ([VertexAI](https://docs.litellm.ai/docs/providers/vertex#usage-with-litellm-proxy-server) + [Google AI Studio](https://docs.litellm.ai/docs/providers/gemini))** + - `/chat/completion` + - Handle audio input - [PR](https://github.com/BerriAI/litellm/pull/10739) + - Fixes maximum recursion depth issue when using deeply nested response schemas with Vertex AI by Increasing DEFAULT_MAX_RECURSE_DEPTH from 10 to 100 in constants. [PR](https://github.com/BerriAI/litellm/pull/10798) + - Capture reasoning tokens in streaming mode - [PR](https://github.com/BerriAI/litellm/pull/10789) +- **[Google AI Studio](../../docs/providers/google_ai_studio/realtime)** + - `/realtime` + - Gemini Multimodal Live API support + - Audio input/output support, optional param mapping, accurate usage calculation - [PR](https://github.com/BerriAI/litellm/pull/10909) +- **[VertexAI](../../docs/providers/vertex#metallama-api)** + - `/chat/completion` + - Fix llama streaming error - where model response was nested in returned streaming chunk - [PR](https://github.com/BerriAI/litellm/pull/10878) +- **[Ollama](../../docs/providers/ollama)** + - `/chat/completion` + - structure responses fix - [PR](https://github.com/BerriAI/litellm/pull/10617) +- **[Bedrock](../../docs/providers/bedrock#litellm-proxy-usage)** + - [`/chat/completion`](../../docs/providers/bedrock#litellm-proxy-usage) + - Handle thinking_blocks when assistant.content is None - [PR](https://github.com/BerriAI/litellm/pull/10688) + - Fixes to only allow accepted fields for tool json schema - [PR](https://github.com/BerriAI/litellm/pull/10062) + - Add bedrock sonnet prompt caching cost information + - Mistral Pixtral support - [PR](https://github.com/BerriAI/litellm/pull/10439) + - Tool caching support - [PR](https://github.com/BerriAI/litellm/pull/10897) + - [`/messages`](../../docs/anthropic_unified) + - allow using dynamic AWS Params - [PR](https://github.com/BerriAI/litellm/pull/10769) +- **[Nvidia NIM](../../docs/providers/nvidia_nim)** + - [`/chat/completion`](../../docs/providers/nvidia_nim#usage---litellm-proxy-server) + - Add tools, tool_choice, parallel_tool_calls support - [PR](https://github.com/BerriAI/litellm/pull/10763) +- **[Novita AI](../../docs/providers/novita)** + - New Provider added for `/chat/completion` routes - [PR](https://github.com/BerriAI/litellm/pull/9527) +- **[Azure](../../docs/providers/azure)** + - [`/image/generation`](../../docs/providers/azure#image-generation) + - Fix azure dall e 3 call with custom model name - [PR](https://github.com/BerriAI/litellm/pull/10776) +- **[Cohere](../../docs/providers/cohere)** + - [`/embeddings`](../../docs/providers/cohere#embedding) + - Migrate embedding to use `/v2/embed` - adds support for output_dimensions param - [PR](https://github.com/BerriAI/litellm/pull/10809) +- **[Anthropic](../../docs/providers/anthropic)** + - [`/chat/completion`](../../docs/providers/anthropic#usage-with-litellm-proxy) + - Web search tool support - native + openai format - [Get Started](../../docs/providers/anthropic#anthropic-hosted-tools-computer-text-editor-web-search) +- **[VLLM](../../docs/providers/vllm)** + - [`/embeddings`](../../docs/providers/vllm#embeddings) + - Support embedding input as list of integers +- **[OpenAI](../../docs/providers/openai)** + - [`/chat/completion`](../../docs/providers/openai#usage---litellm-proxy-server) + - Fix - b64 file data input handling - [Get Started](../../docs/providers/openai#pdf-file-parsing) + - Add ‘supports_pdf_input’ to all vision models - [PR](https://github.com/BerriAI/litellm/pull/10897) + +## LLM API Endpoints +- [**Responses API**](../../docs/response_api) + - Fix delete API support - [PR](https://github.com/BerriAI/litellm/pull/10845) +- [**Rerank API**](../../docs/rerank) + - `/v2/rerank` now registered as ‘llm_api_route’ - enabling non-admins to call it - [PR](https://github.com/BerriAI/litellm/pull/10861) + +## Spend Tracking Improvements +- **`/chat/completion`, `/messages`** + - Anthropic - web search tool cost tracking - [PR](https://github.com/BerriAI/litellm/pull/10846) + - Groq - update model max tokens + cost information - [PR](https://github.com/BerriAI/litellm/pull/10077) +- **`/audio/transcription`** + - Azure - Add gpt-4o-mini-tts pricing - [PR](https://github.com/BerriAI/litellm/pull/10807) + - Proxy - Fix tracking spend by tag - [PR](https://github.com/BerriAI/litellm/pull/10832) +- **`/embeddings`** + - Azure AI - Add cohere embed v4 pricing - [PR](https://github.com/BerriAI/litellm/pull/10806) + +## Management Endpoints / UI +- **Models** + - Ollama - adds api base param to UI +- **Logs** + - Add team id, key alias, key hash filter on logs - https://github.com/BerriAI/litellm/pull/10831 + - Guardrail tracing now in Logs UI - https://github.com/BerriAI/litellm/pull/10893 +- **Teams** + - Patch for updating team info when team in org and members not in org - https://github.com/BerriAI/litellm/pull/10835 +- **Guardrails** + - Add Bedrock, Presidio, Lakers guardrails on UI - https://github.com/BerriAI/litellm/pull/10874 + - See guardrail info page - https://github.com/BerriAI/litellm/pull/10904 + - Allow editing guardrails on UI - https://github.com/BerriAI/litellm/pull/10907 +- **Test Key** + - select guardrails to test on UI + + + +## Logging / Alerting Integrations +- **[StandardLoggingPayload](../../docs/proxy/logging_spec)** + - Log any `x-` headers in requester metadata - [Get Started](../../docs/proxy/logging_spec#standardloggingmetadata) + - Guardrail tracing now in standard logging payload - [Get Started](../../docs/proxy/logging_spec#standardloggingguardrailinformation) +- **[Generic API Logger](../../docs/proxy/logging#custom-callback-apis-async)** + - Support passing application/json header +- **[Arize Phoenix](../../docs/observability/phoenix_integration)** + - fix: URL encode OTEL_EXPORTER_OTLP_TRACES_HEADERS for Phoenix Integration - [PR](https://github.com/BerriAI/litellm/pull/10654) + - add guardrail tracing to OTEL, Arize phoenix - [PR](https://github.com/BerriAI/litellm/pull/10896) +- **[PagerDuty](../../docs/proxy/pagerduty)** + - Pagerduty is now a free feature - [PR](https://github.com/BerriAI/litellm/pull/10857) +- **[Alerting](../../docs/proxy/alerting)** + - Sending slack alerts on virtual key/user/team updates is now free - [PR](https://github.com/BerriAI/litellm/pull/10863) + + +## Guardrails +- **Guardrails** + - New `/apply_guardrail` endpoint for directly testing a guardrail - [PR](https://github.com/BerriAI/litellm/pull/10867) +- **[Lakera](../../docs/proxy/guardrails/lakera_ai)** + - `/v2` endpoints support - [PR](https://github.com/BerriAI/litellm/pull/10880) +- **[Presidio](../../docs/proxy/guardrails/pii_masking_v2)** + - Fixes handling of message content on presidio guardrail integration - [PR](https://github.com/BerriAI/litellm/pull/10197) + - Allow specifying PII Entities Config - [PR](https://github.com/BerriAI/litellm/pull/10810) +- **[Aim Security](../../docs/proxy/guardrails/aim_security)** + - Support for anonymization in AIM Guardrails - [PR](https://github.com/BerriAI/litellm/pull/10757) + + + +## Performance / Loadbalancing / Reliability improvements +- **Allow overriding all constants using a .env variable** - [PR](https://github.com/BerriAI/litellm/pull/10803) +- **[Maximum retention period for spend logs](../../docs/proxy/spend_logs_deletion)** + - Add retention flag to config - [PR](https://github.com/BerriAI/litellm/pull/10815) + - Support for cleaning up logs based on configured time period - [PR](https://github.com/BerriAI/litellm/pull/10872) + +## General Proxy Improvements +- **Authentication** + - Handle Bearer $LITELLM_API_KEY in x-litellm-api-key custom header [PR](https://github.com/BerriAI/litellm/pull/10776) +- **New Enterprise pip package** - `litellm-enterprise` - fixes issue where `enterprise` folder was not found when using pip package +- **[Proxy CLI](../../docs/proxy/management_cli)** + - Add `models import` command - [PR](https://github.com/BerriAI/litellm/pull/10581) +- **[OpenWebUI](../../docs/tutorials/openweb_ui#per-user-tracking)** + - Configure LiteLLM to Parse User Headers from Open Web UI +- **[LiteLLM Proxy w/ LiteLLM SDK](../../docs/providers/litellm_proxy#send-all-sdk-requests-to-litellm-proxy)** + - Option to force/always use the litellm proxy when calling via LiteLLM SDK + + +## New Contributors +* [@imdigitalashish](https://github.com/imdigitalashish) made their first contribution in PR [#10617](https://github.com/BerriAI/litellm/pull/10617) +* [@LouisShark](https://github.com/LouisShark) made their first contribution in PR [#10688](https://github.com/BerriAI/litellm/pull/10688) +* [@OscarSavNS](https://github.com/OscarSavNS) made their first contribution in PR [#10764](https://github.com/BerriAI/litellm/pull/10764) +* [@arizedatngo](https://github.com/arizedatngo) made their first contribution in PR [#10654](https://github.com/BerriAI/litellm/pull/10654) +* [@jugaldb](https://github.com/jugaldb) made their first contribution in PR [#10805](https://github.com/BerriAI/litellm/pull/10805) +* [@daikeren](https://github.com/daikeren) made their first contribution in PR [#10781](https://github.com/BerriAI/litellm/pull/10781) +* [@naliotopier](https://github.com/naliotopier) made their first contribution in PR [#10077](https://github.com/BerriAI/litellm/pull/10077) +* [@damienpontifex](https://github.com/damienpontifex) made their first contribution in PR [#10813](https://github.com/BerriAI/litellm/pull/10813) +* [@Dima-Mediator](https://github.com/Dima-Mediator) made their first contribution in PR [#10789](https://github.com/BerriAI/litellm/pull/10789) +* [@igtm](https://github.com/igtm) made their first contribution in PR [#10814](https://github.com/BerriAI/litellm/pull/10814) +* [@shibaboy](https://github.com/shibaboy) made their first contribution in PR [#10752](https://github.com/BerriAI/litellm/pull/10752) +* [@camfarineau](https://github.com/camfarineau) made their first contribution in PR [#10629](https://github.com/BerriAI/litellm/pull/10629) +* [@ajac-zero](https://github.com/ajac-zero) made their first contribution in PR [#10439](https://github.com/BerriAI/litellm/pull/10439) +* [@damgem](https://github.com/damgem) made their first contribution in PR [#9802](https://github.com/BerriAI/litellm/pull/9802) +* [@hxdror](https://github.com/hxdror) made their first contribution in PR [#10757](https://github.com/BerriAI/litellm/pull/10757) +* [@wwwillchen](https://github.com/wwwillchen) made their first contribution in PR [#10894](https://github.com/BerriAI/litellm/pull/10894) + + +## Demo Instance + +Here's a Demo Instance to test changes: + +- Instance: https://demo.litellm.ai/ +- Login Credentials: + - Username: admin + - Password: sk-1234 + + +## [Git Diff](https://github.com/BerriAI/litellm/releases) + diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js index 5324d50ed40..59bf42c9302 100644 --- a/docs/my-website/sidebars.js +++ b/docs/my-website/sidebars.js @@ -18,6 +18,7 @@ const sidebars = { // But you can create a sidebar manually tutorialSidebar: [ { type: "doc", id: "index" }, // NEW + { type: "category", label: "LiteLLM Proxy Server", @@ -41,17 +42,19 @@ const sidebars = { "proxy/deploy", "proxy/prod", "proxy/cli", + "proxy/release_cycle", "proxy/model_management", "proxy/health", "proxy/debugging", "proxy/spending_monitoring", - ], + "proxy/master_key_rotations", + ], }, "proxy/demo", { type: "category", label: "Architecture", - items: ["proxy/architecture", "proxy/db_info", "router_architecture", "proxy/user_management_heirarchy", "proxy/jwt_auth_arch"], + items: ["proxy/architecture", "proxy/db_info", "proxy/db_deadlocks", "router_architecture", "proxy/user_management_heirarchy", "proxy/jwt_auth_arch", "proxy/image_handling", "proxy/spend_logs_deletion"], }, { type: "link", @@ -59,14 +62,16 @@ const sidebars = { href: "https://litellm-api.up.railway.app/", }, "proxy/enterprise", + "proxy/management_cli", { type: "category", label: "Making LLM Requests", items: [ "proxy/user_keys", "proxy/clientside_auth", - "proxy/response_headers", "proxy/request_headers", + "proxy/response_headers", + "proxy/model_discovery", ], }, { @@ -99,7 +104,17 @@ const sidebars = { "proxy/admin_ui_sso", "proxy/self_serve", "proxy/public_teams", - "proxy/custom_sso" + "tutorials/scim_litellm", + "proxy/custom_sso", + "proxy/ui_credentials", + { + type: "category", + label: "UI Logs", + items: [ + "proxy/ui_logs", + "proxy/ui_logs_sessions" + ] + } ], }, { @@ -133,16 +148,18 @@ const sidebars = { label: "[Beta] Guardrails", items: [ "proxy/guardrails/quick_start", - "proxy/guardrails/aim_security", - "proxy/guardrails/aporia_api", - "proxy/guardrails/bedrock", - "proxy/guardrails/guardrails_ai", - "proxy/guardrails/lakera_ai", - "proxy/guardrails/pii_masking_v2", - "proxy/guardrails/secret_detection", - "proxy/guardrails/custom_guardrail", - "prompt_injection" - ], + ...[ + "proxy/guardrails/aim_security", + "proxy/guardrails/aporia_api", + "proxy/guardrails/bedrock", + "proxy/guardrails/guardrails_ai", + "proxy/guardrails/lakera_ai", + "proxy/guardrails/pii_masking_v2", + "proxy/guardrails/secret_detection", + "proxy/guardrails/custom_guardrail", + "proxy/guardrails/prompt_injection", + ].sort(), + ], }, { type: "category", @@ -162,9 +179,98 @@ const sidebars = { ] }, "proxy/caching", - ] }, + { + type: "category", + label: "Supported Endpoints", + link: { + type: "generated-index", + title: "Supported Endpoints", + description: + "Learn how to deploy + call models from different providers on LiteLLM", + slug: "/supported_endpoints", + }, + items: [ + { + type: "category", + label: "/chat/completions", + link: { + type: "generated-index", + title: "Chat Completions", + description: "Details on the completion() function", + slug: "/completion", + }, + items: [ + "completion/input", + "completion/output", + "completion/usage", + ], + }, + "response_api", + "text_completion", + "embedding/supported_embedding", + "anthropic_unified", + "mcp", + { + type: "category", + label: "/images", + items: [ + "image_generation", + "image_variations", + ] + }, + { + type: "category", + label: "/audio", + "items": [ + "audio_transcription", + "text_to_speech", + ] + }, + { + type: "category", + label: "Pass-through Endpoints (Anthropic SDK, etc.)", + items: [ + "pass_through/intro", + "pass_through/vertex_ai", + "pass_through/google_ai_studio", + "pass_through/cohere", + "pass_through/vllm", + "pass_through/mistral", + "pass_through/openai_passthrough", + "pass_through/anthropic_completion", + "pass_through/bedrock", + "pass_through/assembly_ai", + "pass_through/langfuse", + "proxy/pass_through", + ], + }, + "rerank", + "assistants", + + { + type: "category", + label: "/files", + items: [ + "files_endpoints", + "proxy/litellm_managed_files", + ], + }, + { + type: "category", + label: "/batches", + items: [ + "batches", + "proxy/managed_batches", + ] + }, + "realtime", + "fine_tuning", + "moderation", + "apply_guardrail", + ], + }, { type: "category", label: "Supported Models & Providers", @@ -176,17 +282,49 @@ const sidebars = { slug: "/providers", }, items: [ - "providers/openai", + { + type: "category", + label: "OpenAI", + items: [ + "providers/openai", + "providers/openai/responses_api", + "providers/openai/text_to_speech", + ] + }, "providers/text_completion_openai", "providers/openai_compatible", - "providers/azure", + { + type: "category", + label: "Azure OpenAI", + items: [ + "providers/azure/azure", + "providers/azure/azure_embedding", + ] + }, "providers/azure_ai", + "providers/aiml", "providers/vertex", - "providers/gemini", + { + type: "category", + label: "Google AI Studio", + items: [ + "providers/gemini", + "providers/google_ai_studio/files", + "providers/google_ai_studio/realtime", + ] + }, "providers/anthropic", "providers/aws_sagemaker", - "providers/bedrock", + { + type: "category", + label: "Bedrock", + items: [ + "providers/bedrock", + "providers/bedrock_vector_store", + ] + }, "providers/litellm_proxy", + "providers/meta_llama", "providers/mistral", "providers/codestral", "providers/cohere", @@ -197,6 +335,7 @@ const sidebars = { "providers/watsonx", "providers/predibase", "providers/nvidia_nim", + { type: "doc", id: "providers/nscale", label: "Nscale (EU Sovereign)" }, "providers/xai", "providers/lm_studio", "providers/cerebras", @@ -213,6 +352,7 @@ const sidebars = { "providers/fireworks_ai", "providers/clarifai", "providers/vllm", + "providers/llamafile", "providers/infinity", "providers/xinference", "providers/cloudflare_workers", @@ -221,6 +361,7 @@ const sidebars = { "providers/nlp_cloud", "providers/replicate", "providers/togetherai", + "providers/novita", "providers/voyage", "providers/jina_ai", "providers/aleph_alpha", @@ -229,6 +370,8 @@ const sidebars = { "providers/sambanova", "providers/custom_llm_server", "providers/petals", + "providers/snowflake", + "providers/featherless_ai" ], }, { @@ -238,12 +381,16 @@ const sidebars = { "exception_mapping", "completion/provider_specific_params", "guides/finetuned_models", + "guides/security_settings", "completion/audio", + "completion/web_search", "completion/document_understanding", "completion/vision", "completion/json_mode", + "reasoning_content", "completion/prompt_caching", "completion/predict_outputs", + "completion/knowledgebase", "completion/prefix", "completion/drop_params", "completion/prompt_formatting", @@ -254,70 +401,10 @@ const sidebars = { "completion/batching", "completion/mock_requests", "completion/reliable_completions", - 'tutorials/litellm_proxy_aporia', ] }, - { - type: "category", - label: "Supported Endpoints", - items: [ - { - type: "category", - label: "Chat", - link: { - type: "generated-index", - title: "Chat Completions", - description: "Details on the completion() function", - slug: "/completion", - }, - items: [ - "completion/input", - "completion/output", - "completion/usage", - ], - }, - "text_completion", - "embedding/supported_embedding", - { - type: "category", - label: "Image", - items: [ - "image_generation", - "image_variations", - ] - }, - { - type: "category", - label: "Audio", - "items": [ - "audio_transcription", - "text_to_speech", - ] - }, - { - type: "category", - label: "Pass-through Endpoints (Anthropic SDK, etc.)", - items: [ - "pass_through/intro", - "pass_through/vertex_ai", - "pass_through/google_ai_studio", - "pass_through/cohere", - "pass_through/anthropic_completion", - "pass_through/bedrock", - "pass_through/langfuse", - "proxy/pass_through", - ], - }, - "rerank", - "assistants", - "files_endpoints", - "batches", - "realtime", - "fine_tuning", - "moderation", - ], - }, + { type: "category", label: "Routing, Loadbalancing & Fallbacks", @@ -327,7 +414,7 @@ const sidebars = { description: "Learn how to load balance, route, and set fallbacks for your LLM requests", slug: "/routing-load-balancing", }, - items: ["routing", "scheduler", "proxy/load_balancing", "proxy/reliability", "proxy/timeout", "proxy/tag_routing", "proxy/provider_budget_routing", "wildcard_routing"], + items: ["routing", "scheduler", "proxy/load_balancing", "proxy/reliability", "proxy/timeout", "proxy/tag_routing", "proxy/provider_budget_routing", "wildcard_routing"], }, { type: "category", @@ -346,28 +433,15 @@ const sidebars = { label: "LangChain, LlamaIndex, Instructor Integration", items: ["langchain/langchain", "tutorials/instructor"], }, - { - type: "category", - label: "Tutorials", - items: [ - - 'tutorials/azure_openai', - 'tutorials/instructor', - "tutorials/gradio_integration", - "tutorials/huggingface_codellama", - "tutorials/huggingface_tutorial", - "tutorials/TogetherAI_liteLLM", - "tutorials/finetuned_chat_gpt", - "tutorials/text_completion", - "tutorials/first_playground", - "tutorials/model_fallbacks", - ], - }, ], }, { - type: "doc", - id: "proxy/prompt_management" + type: "category", + label: "[Beta] Prompt Management", + items: [ + "proxy/prompt_management", + "proxy/custom_prompt_management" + ], }, { type: "category", @@ -379,20 +453,14 @@ const sidebars = { "load_test_rpm", ] }, - { - type: "category", - label: "Adding Providers", - items: [ - "adding_provider/directory_structure", - "adding_provider/new_rerank_provider"], - }, { type: "category", label: "Logging & Observability", items: [ + "observability/agentops_integration", + "observability/langfuse_integration", "observability/lunary_integration", "observability/mlflow", - "observability/langfuse_integration", "observability/gcs_bucket_integration", "observability/langsmith_integration", "observability/literalai_integration", @@ -400,6 +468,7 @@ const sidebars = { "observability/logfire_integration", "observability/argilla", "observability/arize_integration", + "observability/phoenix_integration", "debugging/local_debugging", "observability/raw_request_response", "observability/custom_callback", @@ -420,12 +489,56 @@ const sidebars = { "observability/opik_integration", ], }, - + { + type: "category", + label: "Tutorials", + items: [ + "tutorials/openweb_ui", + "tutorials/openai_codex", + "tutorials/msft_sso", + "tutorials/prompt_caching", + "tutorials/tag_management", + 'tutorials/litellm_proxy_aporia', + "tutorials/gemini_realtime_with_audio", + { + type: "category", + label: "LiteLLM Python SDK Tutorials", + items: [ + 'tutorials/google_adk', + 'tutorials/azure_openai', + 'tutorials/instructor', + "tutorials/gradio_integration", + "tutorials/huggingface_codellama", + "tutorials/huggingface_tutorial", + "tutorials/TogetherAI_liteLLM", + "tutorials/finetuned_chat_gpt", + "tutorials/text_completion", + "tutorials/first_playground", + "tutorials/model_fallbacks", + ], + }, + ] + }, + { + type: "category", + label: "Contributing", + items: [ + "extras/contributing_code", + { + type: "category", + label: "Adding Providers", + items: [ + "adding_provider/directory_structure", + "adding_provider/new_rerank_provider"], + }, + "extras/contributing", + "contributing", + ] + }, { type: "category", label: "Extras", items: [ - "extras/contributing", "data_security", "data_retention", "migration_policy", @@ -442,7 +555,9 @@ const sidebars = { items: [ "projects/smolagents", "projects/Docq.AI", + "projects/PDL", "projects/OpenInterpreter", + "projects/Elroy", "projects/dbally", "projects/FastREPL", "projects/PROMPTMETHEUS", @@ -456,10 +571,10 @@ const sidebars = { "projects/YiVal", "projects/LiteLLM Proxy", "projects/llm_cord", + "projects/pgai", + "projects/GPTLocalhost", ], }, - "contributing", - "proxy/pii_masking", "extras/code_quality", "rules", "proxy/team_based_routing", diff --git a/docs/my-website/src/components/TransformRequestPlayground.tsx b/docs/my-website/src/components/TransformRequestPlayground.tsx new file mode 100644 index 00000000000..8f22e5e1984 --- /dev/null +++ b/docs/my-website/src/components/TransformRequestPlayground.tsx @@ -0,0 +1,161 @@ +import React, { useState } from 'react'; +import styles from './transform_request.module.css'; + +const DEFAULT_REQUEST = { + "model": "bedrock/gpt-4", + "messages": [ + { + "role": "system", + "content": "You are a helpful assistant." + }, + { + "role": "user", + "content": "Explain quantum computing in simple terms" + } + ], + "temperature": 0.7, + "max_tokens": 500, + "stream": true +}; + +type ViewMode = 'split' | 'request' | 'transformed'; + +const TransformRequestPlayground: React.FC = () => { + const [request, setRequest] = useState(JSON.stringify(DEFAULT_REQUEST, null, 2)); + const [transformedRequest, setTransformedRequest] = useState(''); + const [viewMode, setViewMode] = useState('split'); + + const handleTransform = async () => { + try { + // Here you would make the actual API call to transform the request + // For now, we'll just set a sample response + const sampleResponse = `curl -X POST \\ + https://api.openai.com/v1/chat/completions \\ + -H 'Authorization: Bearer sk-xxx' \\ + -H 'Content-Type: application/json' \\ + -d '{ + "model": "gpt-4", + "messages": [ + { + "role": "system", + "content": "You are a helpful assistant." + } + ], + "temperature": 0.7 + }'`; + setTransformedRequest(sampleResponse); + } catch (error) { + console.error('Error transforming request:', error); + } + }; + + const handleCopy = () => { + navigator.clipboard.writeText(transformedRequest); + }; + + const renderContent = () => { + switch (viewMode) { + case 'request': + return ( +
+
+

Original Request

+

The request you would send to LiteLLM /chat/completions endpoint.

+
+