Upload 1072 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .circleci/config.yml +2232 -0
- .circleci/requirements.txt +13 -0
- .devcontainer/devcontainer.json +52 -0
- .dockerignore +12 -0
- .env.example +22 -0
- .flake8 +46 -0
- .git-blame-ignore-revs +10 -0
- .gitattributes +5 -35
- .github/FUNDING.yml +13 -0
- .github/ISSUE_TEMPLATE/bug_report.yml +49 -0
- .github/ISSUE_TEMPLATE/config.yml +8 -0
- .github/ISSUE_TEMPLATE/feature_request.yml +42 -0
- .github/actions/helm-oci-chart-releaser/action.yml +77 -0
- .github/dependabot.yaml +10 -0
- .github/pull_request_template.md +29 -0
- .github/template.yaml +94 -0
- .github/workflows/auto_update_price_and_context_window.yml +28 -0
- .github/workflows/auto_update_price_and_context_window_file.py +121 -0
- .github/workflows/ghcr_deploy.yml +374 -0
- .github/workflows/ghcr_helm_deploy.yml +67 -0
- .github/workflows/interpret_load_test.py +113 -0
- .github/workflows/label-mlops.yml +17 -0
- .github/workflows/load_test.yml +59 -0
- .github/workflows/locustfile.py +28 -0
- .github/workflows/main.yml +34 -0
- .github/workflows/read_pyproject_version.yml +31 -0
- .github/workflows/redeploy_proxy.py +20 -0
- .github/workflows/reset_stable.yml +39 -0
- .github/workflows/results_stats.csv +27 -0
- .github/workflows/stale.yml +20 -0
- .github/workflows/update_release.py +54 -0
- .pre-commit-config.yaml +49 -0
- Dockerfile +97 -0
- LICENSE +26 -0
- README.md +5 -8
- ci_cd/check_file_length.py +28 -0
- ci_cd/check_files_match.py +32 -0
- codecov.yaml +32 -0
- db_scripts/create_views.py +209 -0
- db_scripts/update_unassigned_teams.py +34 -0
- deploy/Dockerfile.ghcr_base +17 -0
- deploy/azure_resource_manager/azure_marketplace.zip +0 -0
- deploy/azure_resource_manager/azure_marketplace/createUiDefinition.json +15 -0
- deploy/azure_resource_manager/azure_marketplace/mainTemplate.json +63 -0
- deploy/azure_resource_manager/main.bicep +42 -0
- deploy/charts/litellm-helm/.helmignore +23 -0
- deploy/charts/litellm-helm/Chart.lock +9 -0
- deploy/charts/litellm-helm/Chart.yaml +37 -0
- deploy/charts/litellm-helm/README.md +129 -0
- deploy/charts/litellm-helm/charts/postgresql-14.3.1.tgz +0 -0
.circleci/config.yml
ADDED
@@ -0,0 +1,2232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
version: 2.1
|
2 |
+
orbs:
|
3 |
+
codecov: codecov/[email protected]
|
4 |
+
|
5 |
+
jobs:
|
6 |
+
local_testing:
|
7 |
+
docker:
|
8 |
+
- image: cimg/python:3.11
|
9 |
+
auth:
|
10 |
+
username: ${DOCKERHUB_USERNAME}
|
11 |
+
password: ${DOCKERHUB_PASSWORD}
|
12 |
+
working_directory: ~/project
|
13 |
+
|
14 |
+
steps:
|
15 |
+
- checkout
|
16 |
+
|
17 |
+
- run:
|
18 |
+
name: Show git commit hash
|
19 |
+
command: |
|
20 |
+
echo "Git commit hash: $CIRCLE_SHA1"
|
21 |
+
|
22 |
+
- restore_cache:
|
23 |
+
keys:
|
24 |
+
- v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
25 |
+
- run:
|
26 |
+
name: Install Dependencies
|
27 |
+
command: |
|
28 |
+
python -m pip install --upgrade pip
|
29 |
+
python -m pip install -r .circleci/requirements.txt
|
30 |
+
pip install "pytest==7.3.1"
|
31 |
+
pip install "pytest-retry==1.6.3"
|
32 |
+
pip install "pytest-asyncio==0.21.1"
|
33 |
+
pip install "pytest-cov==5.0.0"
|
34 |
+
pip install mypy
|
35 |
+
pip install "google-generativeai==0.3.2"
|
36 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
37 |
+
pip install pyarrow
|
38 |
+
pip install "boto3==1.34.34"
|
39 |
+
pip install "aioboto3==12.3.0"
|
40 |
+
pip install langchain
|
41 |
+
pip install lunary==0.2.5
|
42 |
+
pip install "azure-identity==1.16.1"
|
43 |
+
pip install "langfuse==2.45.0"
|
44 |
+
pip install "logfire==0.29.0"
|
45 |
+
pip install numpydoc
|
46 |
+
pip install traceloop-sdk==0.21.1
|
47 |
+
pip install opentelemetry-api==1.25.0
|
48 |
+
pip install opentelemetry-sdk==1.25.0
|
49 |
+
pip install opentelemetry-exporter-otlp==1.25.0
|
50 |
+
pip install openai==1.54.0
|
51 |
+
pip install prisma==0.11.0
|
52 |
+
pip install "detect_secrets==1.5.0"
|
53 |
+
pip install "httpx==0.24.1"
|
54 |
+
pip install "respx==0.21.1"
|
55 |
+
pip install fastapi
|
56 |
+
pip install "gunicorn==21.2.0"
|
57 |
+
pip install "anyio==4.2.0"
|
58 |
+
pip install "aiodynamo==23.10.1"
|
59 |
+
pip install "asyncio==3.4.3"
|
60 |
+
pip install "apscheduler==3.10.4"
|
61 |
+
pip install "PyGithub==1.59.1"
|
62 |
+
pip install argon2-cffi
|
63 |
+
pip install "pytest-mock==3.12.0"
|
64 |
+
pip install python-multipart
|
65 |
+
pip install google-cloud-aiplatform
|
66 |
+
pip install prometheus-client==0.20.0
|
67 |
+
pip install "pydantic==2.7.1"
|
68 |
+
pip install "diskcache==5.6.1"
|
69 |
+
pip install "Pillow==10.3.0"
|
70 |
+
pip install "jsonschema==4.22.0"
|
71 |
+
pip install "pytest-xdist==3.6.1"
|
72 |
+
pip install "websockets==10.4"
|
73 |
+
- save_cache:
|
74 |
+
paths:
|
75 |
+
- ./venv
|
76 |
+
key: v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
77 |
+
- run:
|
78 |
+
name: Run prisma ./docker/entrypoint.sh
|
79 |
+
command: |
|
80 |
+
set +e
|
81 |
+
chmod +x docker/entrypoint.sh
|
82 |
+
./docker/entrypoint.sh
|
83 |
+
set -e
|
84 |
+
- run:
|
85 |
+
name: Black Formatting
|
86 |
+
command: |
|
87 |
+
cd litellm
|
88 |
+
python -m pip install black
|
89 |
+
python -m black .
|
90 |
+
cd ..
|
91 |
+
- run:
|
92 |
+
name: Linting Testing
|
93 |
+
command: |
|
94 |
+
cd litellm
|
95 |
+
python -m pip install types-requests types-setuptools types-redis types-PyYAML
|
96 |
+
if ! python -m mypy . --ignore-missing-imports; then
|
97 |
+
echo "mypy detected errors"
|
98 |
+
exit 1
|
99 |
+
fi
|
100 |
+
cd ..
|
101 |
+
|
102 |
+
# Run pytest and generate JUnit XML report
|
103 |
+
- run:
|
104 |
+
name: Run tests
|
105 |
+
command: |
|
106 |
+
pwd
|
107 |
+
ls
|
108 |
+
python -m pytest -vv tests/local_testing --cov=litellm --cov-report=xml -x --junitxml=test-results/junit.xml --durations=5 -k "not test_python_38.py and not test_basic_python_version.py and not router and not assistants and not langfuse and not caching and not cache" -n 4
|
109 |
+
no_output_timeout: 120m
|
110 |
+
- run:
|
111 |
+
name: Rename the coverage files
|
112 |
+
command: |
|
113 |
+
mv coverage.xml local_testing_coverage.xml
|
114 |
+
mv .coverage local_testing_coverage
|
115 |
+
|
116 |
+
# Store test results
|
117 |
+
- store_test_results:
|
118 |
+
path: test-results
|
119 |
+
- persist_to_workspace:
|
120 |
+
root: .
|
121 |
+
paths:
|
122 |
+
- local_testing_coverage.xml
|
123 |
+
- local_testing_coverage
|
124 |
+
langfuse_logging_unit_tests:
|
125 |
+
docker:
|
126 |
+
- image: cimg/python:3.11
|
127 |
+
auth:
|
128 |
+
username: ${DOCKERHUB_USERNAME}
|
129 |
+
password: ${DOCKERHUB_PASSWORD}
|
130 |
+
working_directory: ~/project
|
131 |
+
|
132 |
+
steps:
|
133 |
+
- checkout
|
134 |
+
|
135 |
+
- run:
|
136 |
+
name: Show git commit hash
|
137 |
+
command: |
|
138 |
+
echo "Git commit hash: $CIRCLE_SHA1"
|
139 |
+
|
140 |
+
- restore_cache:
|
141 |
+
keys:
|
142 |
+
- v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
143 |
+
- run:
|
144 |
+
name: Install Dependencies
|
145 |
+
command: |
|
146 |
+
python -m pip install --upgrade pip
|
147 |
+
python -m pip install -r .circleci/requirements.txt
|
148 |
+
pip install "pytest==7.3.1"
|
149 |
+
pip install "pytest-retry==1.6.3"
|
150 |
+
pip install "pytest-asyncio==0.21.1"
|
151 |
+
pip install "pytest-cov==5.0.0"
|
152 |
+
pip install mypy
|
153 |
+
pip install "google-generativeai==0.3.2"
|
154 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
155 |
+
pip install pyarrow
|
156 |
+
pip install "boto3==1.34.34"
|
157 |
+
pip install "aioboto3==12.3.0"
|
158 |
+
pip install langchain
|
159 |
+
pip install lunary==0.2.5
|
160 |
+
pip install "azure-identity==1.16.1"
|
161 |
+
pip install "langfuse==2.45.0"
|
162 |
+
pip install "logfire==0.29.0"
|
163 |
+
pip install numpydoc
|
164 |
+
pip install traceloop-sdk==0.21.1
|
165 |
+
pip install opentelemetry-api==1.25.0
|
166 |
+
pip install opentelemetry-sdk==1.25.0
|
167 |
+
pip install opentelemetry-exporter-otlp==1.25.0
|
168 |
+
pip install openai==1.54.0
|
169 |
+
pip install prisma==0.11.0
|
170 |
+
pip install "detect_secrets==1.5.0"
|
171 |
+
pip install "httpx==0.24.1"
|
172 |
+
pip install "respx==0.21.1"
|
173 |
+
pip install fastapi
|
174 |
+
pip install "gunicorn==21.2.0"
|
175 |
+
pip install "anyio==4.2.0"
|
176 |
+
pip install "aiodynamo==23.10.1"
|
177 |
+
pip install "asyncio==3.4.3"
|
178 |
+
pip install "apscheduler==3.10.4"
|
179 |
+
pip install "PyGithub==1.59.1"
|
180 |
+
pip install argon2-cffi
|
181 |
+
pip install "pytest-mock==3.12.0"
|
182 |
+
pip install python-multipart
|
183 |
+
pip install google-cloud-aiplatform
|
184 |
+
pip install prometheus-client==0.20.0
|
185 |
+
pip install "pydantic==2.7.1"
|
186 |
+
pip install "diskcache==5.6.1"
|
187 |
+
pip install "Pillow==10.3.0"
|
188 |
+
pip install "jsonschema==4.22.0"
|
189 |
+
- save_cache:
|
190 |
+
paths:
|
191 |
+
- ./venv
|
192 |
+
key: v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
193 |
+
- run:
|
194 |
+
name: Run prisma ./docker/entrypoint.sh
|
195 |
+
command: |
|
196 |
+
set +e
|
197 |
+
chmod +x docker/entrypoint.sh
|
198 |
+
./docker/entrypoint.sh
|
199 |
+
set -e
|
200 |
+
|
201 |
+
# Run pytest and generate JUnit XML report
|
202 |
+
- run:
|
203 |
+
name: Run tests
|
204 |
+
command: |
|
205 |
+
pwd
|
206 |
+
ls
|
207 |
+
python -m pytest -vv tests/local_testing --cov=litellm --cov-report=xml -x --junitxml=test-results/junit.xml --durations=5 -k "langfuse"
|
208 |
+
no_output_timeout: 120m
|
209 |
+
- run:
|
210 |
+
name: Rename the coverage files
|
211 |
+
command: |
|
212 |
+
mv coverage.xml langfuse_coverage.xml
|
213 |
+
mv .coverage langfuse_coverage
|
214 |
+
|
215 |
+
# Store test results
|
216 |
+
- store_test_results:
|
217 |
+
path: test-results
|
218 |
+
- persist_to_workspace:
|
219 |
+
root: .
|
220 |
+
paths:
|
221 |
+
- langfuse_coverage.xml
|
222 |
+
- langfuse_coverage
|
223 |
+
caching_unit_tests:
|
224 |
+
docker:
|
225 |
+
- image: cimg/python:3.11
|
226 |
+
auth:
|
227 |
+
username: ${DOCKERHUB_USERNAME}
|
228 |
+
password: ${DOCKERHUB_PASSWORD}
|
229 |
+
working_directory: ~/project
|
230 |
+
|
231 |
+
steps:
|
232 |
+
- checkout
|
233 |
+
|
234 |
+
- run:
|
235 |
+
name: Show git commit hash
|
236 |
+
command: |
|
237 |
+
echo "Git commit hash: $CIRCLE_SHA1"
|
238 |
+
|
239 |
+
- restore_cache:
|
240 |
+
keys:
|
241 |
+
- v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
242 |
+
- run:
|
243 |
+
name: Install Dependencies
|
244 |
+
command: |
|
245 |
+
python -m pip install --upgrade pip
|
246 |
+
python -m pip install -r .circleci/requirements.txt
|
247 |
+
pip install "pytest==7.3.1"
|
248 |
+
pip install "pytest-retry==1.6.3"
|
249 |
+
pip install "pytest-asyncio==0.21.1"
|
250 |
+
pip install "pytest-cov==5.0.0"
|
251 |
+
pip install mypy
|
252 |
+
pip install "google-generativeai==0.3.2"
|
253 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
254 |
+
pip install pyarrow
|
255 |
+
pip install "boto3==1.34.34"
|
256 |
+
pip install "aioboto3==12.3.0"
|
257 |
+
pip install langchain
|
258 |
+
pip install lunary==0.2.5
|
259 |
+
pip install "azure-identity==1.16.1"
|
260 |
+
pip install "langfuse==2.45.0"
|
261 |
+
pip install "logfire==0.29.0"
|
262 |
+
pip install numpydoc
|
263 |
+
pip install traceloop-sdk==0.21.1
|
264 |
+
pip install opentelemetry-api==1.25.0
|
265 |
+
pip install opentelemetry-sdk==1.25.0
|
266 |
+
pip install opentelemetry-exporter-otlp==1.25.0
|
267 |
+
pip install openai==1.54.0
|
268 |
+
pip install prisma==0.11.0
|
269 |
+
pip install "detect_secrets==1.5.0"
|
270 |
+
pip install "httpx==0.24.1"
|
271 |
+
pip install "respx==0.21.1"
|
272 |
+
pip install fastapi
|
273 |
+
pip install "gunicorn==21.2.0"
|
274 |
+
pip install "anyio==4.2.0"
|
275 |
+
pip install "aiodynamo==23.10.1"
|
276 |
+
pip install "asyncio==3.4.3"
|
277 |
+
pip install "apscheduler==3.10.4"
|
278 |
+
pip install "PyGithub==1.59.1"
|
279 |
+
pip install argon2-cffi
|
280 |
+
pip install "pytest-mock==3.12.0"
|
281 |
+
pip install python-multipart
|
282 |
+
pip install google-cloud-aiplatform
|
283 |
+
pip install prometheus-client==0.20.0
|
284 |
+
pip install "pydantic==2.7.1"
|
285 |
+
pip install "diskcache==5.6.1"
|
286 |
+
pip install "Pillow==10.3.0"
|
287 |
+
pip install "jsonschema==4.22.0"
|
288 |
+
- save_cache:
|
289 |
+
paths:
|
290 |
+
- ./venv
|
291 |
+
key: v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
292 |
+
- run:
|
293 |
+
name: Run prisma ./docker/entrypoint.sh
|
294 |
+
command: |
|
295 |
+
set +e
|
296 |
+
chmod +x docker/entrypoint.sh
|
297 |
+
./docker/entrypoint.sh
|
298 |
+
set -e
|
299 |
+
|
300 |
+
# Run pytest and generate JUnit XML report
|
301 |
+
- run:
|
302 |
+
name: Run tests
|
303 |
+
command: |
|
304 |
+
pwd
|
305 |
+
ls
|
306 |
+
python -m pytest -vv tests/local_testing --cov=litellm --cov-report=xml -x --junitxml=test-results/junit.xml --durations=5 -k "caching or cache"
|
307 |
+
no_output_timeout: 120m
|
308 |
+
- run:
|
309 |
+
name: Rename the coverage files
|
310 |
+
command: |
|
311 |
+
mv coverage.xml caching_coverage.xml
|
312 |
+
mv .coverage caching_coverage
|
313 |
+
|
314 |
+
# Store test results
|
315 |
+
- store_test_results:
|
316 |
+
path: test-results
|
317 |
+
- persist_to_workspace:
|
318 |
+
root: .
|
319 |
+
paths:
|
320 |
+
- caching_coverage.xml
|
321 |
+
- caching_coverage
|
322 |
+
auth_ui_unit_tests:
|
323 |
+
docker:
|
324 |
+
- image: cimg/python:3.11
|
325 |
+
auth:
|
326 |
+
username: ${DOCKERHUB_USERNAME}
|
327 |
+
password: ${DOCKERHUB_PASSWORD}
|
328 |
+
working_directory: ~/project
|
329 |
+
|
330 |
+
steps:
|
331 |
+
- checkout
|
332 |
+
- run:
|
333 |
+
name: Install Dependencies
|
334 |
+
command: |
|
335 |
+
python -m pip install --upgrade pip
|
336 |
+
python -m pip install -r requirements.txt
|
337 |
+
pip install "pytest==7.3.1"
|
338 |
+
pip install "pytest-retry==1.6.3"
|
339 |
+
pip install "pytest-asyncio==0.21.1"
|
340 |
+
pip install "pytest-cov==5.0.0"
|
341 |
+
- save_cache:
|
342 |
+
paths:
|
343 |
+
- ./venv
|
344 |
+
key: v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
345 |
+
- run:
|
346 |
+
name: Run prisma ./docker/entrypoint.sh
|
347 |
+
command: |
|
348 |
+
set +e
|
349 |
+
chmod +x docker/entrypoint.sh
|
350 |
+
./docker/entrypoint.sh
|
351 |
+
set -e
|
352 |
+
# Run pytest and generate JUnit XML report
|
353 |
+
- run:
|
354 |
+
name: Run tests
|
355 |
+
command: |
|
356 |
+
pwd
|
357 |
+
ls
|
358 |
+
python -m pytest -vv tests/proxy_admin_ui_tests -x --cov=litellm --cov-report=xml --junitxml=test-results/junit.xml --durations=5
|
359 |
+
no_output_timeout: 120m
|
360 |
+
|
361 |
+
- run:
|
362 |
+
name: Rename the coverage files
|
363 |
+
command: |
|
364 |
+
mv coverage.xml auth_ui_unit_tests_coverage.xml
|
365 |
+
mv .coverage auth_ui_unit_tests_coverage
|
366 |
+
|
367 |
+
# Store test results
|
368 |
+
- store_test_results:
|
369 |
+
path: test-results
|
370 |
+
|
371 |
+
- persist_to_workspace:
|
372 |
+
root: .
|
373 |
+
paths:
|
374 |
+
- auth_ui_unit_tests_coverage.xml
|
375 |
+
- auth_ui_unit_tests_coverage
|
376 |
+
litellm_router_testing: # Runs all tests with the "router" keyword
|
377 |
+
docker:
|
378 |
+
- image: cimg/python:3.11
|
379 |
+
auth:
|
380 |
+
username: ${DOCKERHUB_USERNAME}
|
381 |
+
password: ${DOCKERHUB_PASSWORD}
|
382 |
+
working_directory: ~/project
|
383 |
+
|
384 |
+
steps:
|
385 |
+
- checkout
|
386 |
+
- run:
|
387 |
+
name: Install Dependencies
|
388 |
+
command: |
|
389 |
+
python -m pip install --upgrade pip
|
390 |
+
python -m pip install -r requirements.txt
|
391 |
+
pip install "pytest==7.3.1"
|
392 |
+
pip install "respx==0.21.1"
|
393 |
+
pip install "pytest-cov==5.0.0"
|
394 |
+
pip install "pytest-retry==1.6.3"
|
395 |
+
pip install "pytest-asyncio==0.21.1"
|
396 |
+
# Run pytest and generate JUnit XML report
|
397 |
+
- run:
|
398 |
+
name: Run tests
|
399 |
+
command: |
|
400 |
+
pwd
|
401 |
+
ls
|
402 |
+
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
|
403 |
+
no_output_timeout: 120m
|
404 |
+
- run:
|
405 |
+
name: Rename the coverage files
|
406 |
+
command: |
|
407 |
+
mv coverage.xml litellm_router_coverage.xml
|
408 |
+
mv .coverage litellm_router_coverage
|
409 |
+
# Store test results
|
410 |
+
- store_test_results:
|
411 |
+
path: test-results
|
412 |
+
|
413 |
+
- persist_to_workspace:
|
414 |
+
root: .
|
415 |
+
paths:
|
416 |
+
- litellm_router_coverage.xml
|
417 |
+
- litellm_router_coverage
|
418 |
+
litellm_proxy_unit_testing: # Runs all tests with the "proxy", "key", "jwt" filenames
|
419 |
+
docker:
|
420 |
+
- image: cimg/python:3.11
|
421 |
+
auth:
|
422 |
+
username: ${DOCKERHUB_USERNAME}
|
423 |
+
password: ${DOCKERHUB_PASSWORD}
|
424 |
+
working_directory: ~/project
|
425 |
+
steps:
|
426 |
+
- checkout
|
427 |
+
|
428 |
+
- run:
|
429 |
+
name: Show git commit hash
|
430 |
+
command: |
|
431 |
+
echo "Git commit hash: $CIRCLE_SHA1"
|
432 |
+
|
433 |
+
- restore_cache:
|
434 |
+
keys:
|
435 |
+
- v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
436 |
+
- run:
|
437 |
+
name: Install Dependencies
|
438 |
+
command: |
|
439 |
+
python -m pip install --upgrade pip
|
440 |
+
python -m pip install -r .circleci/requirements.txt
|
441 |
+
pip install "pytest==7.3.1"
|
442 |
+
pip install "pytest-retry==1.6.3"
|
443 |
+
pip install "pytest-asyncio==0.21.1"
|
444 |
+
pip install "pytest-cov==5.0.0"
|
445 |
+
pip install mypy
|
446 |
+
pip install "google-generativeai==0.3.2"
|
447 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
448 |
+
pip install pyarrow
|
449 |
+
pip install "boto3==1.34.34"
|
450 |
+
pip install "aioboto3==12.3.0"
|
451 |
+
pip install langchain
|
452 |
+
pip install lunary==0.2.5
|
453 |
+
pip install "azure-identity==1.16.1"
|
454 |
+
pip install "langfuse==2.45.0"
|
455 |
+
pip install "logfire==0.29.0"
|
456 |
+
pip install numpydoc
|
457 |
+
pip install traceloop-sdk==0.21.1
|
458 |
+
pip install opentelemetry-api==1.25.0
|
459 |
+
pip install opentelemetry-sdk==1.25.0
|
460 |
+
pip install opentelemetry-exporter-otlp==1.25.0
|
461 |
+
pip install openai==1.54.0
|
462 |
+
pip install prisma==0.11.0
|
463 |
+
pip install "detect_secrets==1.5.0"
|
464 |
+
pip install "httpx==0.24.1"
|
465 |
+
pip install "respx==0.21.1"
|
466 |
+
pip install fastapi
|
467 |
+
pip install "gunicorn==21.2.0"
|
468 |
+
pip install "anyio==4.2.0"
|
469 |
+
pip install "aiodynamo==23.10.1"
|
470 |
+
pip install "asyncio==3.4.3"
|
471 |
+
pip install "apscheduler==3.10.4"
|
472 |
+
pip install "PyGithub==1.59.1"
|
473 |
+
pip install argon2-cffi
|
474 |
+
pip install "pytest-mock==3.12.0"
|
475 |
+
pip install python-multipart
|
476 |
+
pip install google-cloud-aiplatform
|
477 |
+
pip install prometheus-client==0.20.0
|
478 |
+
pip install "pydantic==2.7.1"
|
479 |
+
pip install "diskcache==5.6.1"
|
480 |
+
pip install "Pillow==10.3.0"
|
481 |
+
pip install "jsonschema==4.22.0"
|
482 |
+
- save_cache:
|
483 |
+
paths:
|
484 |
+
- ./venv
|
485 |
+
key: v1-dependencies-{{ checksum ".circleci/requirements.txt" }}
|
486 |
+
- run:
|
487 |
+
name: Run prisma ./docker/entrypoint.sh
|
488 |
+
command: |
|
489 |
+
set +e
|
490 |
+
chmod +x docker/entrypoint.sh
|
491 |
+
./docker/entrypoint.sh
|
492 |
+
set -e
|
493 |
+
# Run pytest and generate JUnit XML report
|
494 |
+
- run:
|
495 |
+
name: Run tests
|
496 |
+
command: |
|
497 |
+
pwd
|
498 |
+
ls
|
499 |
+
python -m pytest tests/proxy_unit_tests --cov=litellm --cov-report=xml -vv -x -v --junitxml=test-results/junit.xml --durations=5
|
500 |
+
no_output_timeout: 120m
|
501 |
+
- run:
|
502 |
+
name: Rename the coverage files
|
503 |
+
command: |
|
504 |
+
mv coverage.xml litellm_proxy_unit_tests_coverage.xml
|
505 |
+
mv .coverage litellm_proxy_unit_tests_coverage
|
506 |
+
# Store test results
|
507 |
+
- store_test_results:
|
508 |
+
path: test-results
|
509 |
+
|
510 |
+
- persist_to_workspace:
|
511 |
+
root: .
|
512 |
+
paths:
|
513 |
+
- litellm_proxy_unit_tests_coverage.xml
|
514 |
+
- litellm_proxy_unit_tests_coverage
|
515 |
+
litellm_assistants_api_testing: # Runs all tests with the "assistants" keyword
|
516 |
+
docker:
|
517 |
+
- image: cimg/python:3.11
|
518 |
+
auth:
|
519 |
+
username: ${DOCKERHUB_USERNAME}
|
520 |
+
password: ${DOCKERHUB_PASSWORD}
|
521 |
+
working_directory: ~/project
|
522 |
+
|
523 |
+
steps:
|
524 |
+
- checkout
|
525 |
+
- run:
|
526 |
+
name: Install Dependencies
|
527 |
+
command: |
|
528 |
+
python -m pip install --upgrade pip
|
529 |
+
python -m pip install -r requirements.txt
|
530 |
+
pip install "pytest==7.3.1"
|
531 |
+
pip install "respx==0.21.1"
|
532 |
+
pip install "pytest-retry==1.6.3"
|
533 |
+
pip install "pytest-asyncio==0.21.1"
|
534 |
+
pip install "pytest-cov==5.0.0"
|
535 |
+
# Run pytest and generate JUnit XML report
|
536 |
+
- run:
|
537 |
+
name: Run tests
|
538 |
+
command: |
|
539 |
+
pwd
|
540 |
+
ls
|
541 |
+
python -m pytest tests/local_testing/ -vv -k "assistants" --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
542 |
+
no_output_timeout: 120m
|
543 |
+
- run:
|
544 |
+
name: Rename the coverage files
|
545 |
+
command: |
|
546 |
+
mv coverage.xml litellm_assistants_api_coverage.xml
|
547 |
+
mv .coverage litellm_assistants_api_coverage
|
548 |
+
# Store test results
|
549 |
+
- store_test_results:
|
550 |
+
path: test-results
|
551 |
+
- persist_to_workspace:
|
552 |
+
root: .
|
553 |
+
paths:
|
554 |
+
- litellm_assistants_api_coverage.xml
|
555 |
+
- litellm_assistants_api_coverage
|
556 |
+
load_testing:
|
557 |
+
docker:
|
558 |
+
- image: cimg/python:3.11
|
559 |
+
auth:
|
560 |
+
username: ${DOCKERHUB_USERNAME}
|
561 |
+
password: ${DOCKERHUB_PASSWORD}
|
562 |
+
working_directory: ~/project
|
563 |
+
|
564 |
+
steps:
|
565 |
+
- checkout
|
566 |
+
- run:
|
567 |
+
name: Install Dependencies
|
568 |
+
command: |
|
569 |
+
python -m pip install --upgrade pip
|
570 |
+
python -m pip install -r requirements.txt
|
571 |
+
pip install "pytest==7.3.1"
|
572 |
+
pip install "pytest-retry==1.6.3"
|
573 |
+
pip install "pytest-asyncio==0.21.1"
|
574 |
+
# Run pytest and generate JUnit XML report
|
575 |
+
- run:
|
576 |
+
name: Run tests
|
577 |
+
command: |
|
578 |
+
pwd
|
579 |
+
ls
|
580 |
+
python -m pytest -vv tests/load_tests -x -s -v --junitxml=test-results/junit.xml --durations=5
|
581 |
+
no_output_timeout: 120m
|
582 |
+
|
583 |
+
# Store test results
|
584 |
+
- store_test_results:
|
585 |
+
path: test-results
|
586 |
+
llm_translation_testing:
|
587 |
+
docker:
|
588 |
+
- image: cimg/python:3.11
|
589 |
+
auth:
|
590 |
+
username: ${DOCKERHUB_USERNAME}
|
591 |
+
password: ${DOCKERHUB_PASSWORD}
|
592 |
+
working_directory: ~/project
|
593 |
+
|
594 |
+
steps:
|
595 |
+
- checkout
|
596 |
+
- run:
|
597 |
+
name: Install Dependencies
|
598 |
+
command: |
|
599 |
+
python -m pip install --upgrade pip
|
600 |
+
python -m pip install -r requirements.txt
|
601 |
+
pip install "pytest==7.3.1"
|
602 |
+
pip install "pytest-retry==1.6.3"
|
603 |
+
pip install "pytest-cov==5.0.0"
|
604 |
+
pip install "pytest-asyncio==0.21.1"
|
605 |
+
pip install "respx==0.21.1"
|
606 |
+
# Run pytest and generate JUnit XML report
|
607 |
+
- run:
|
608 |
+
name: Run tests
|
609 |
+
command: |
|
610 |
+
pwd
|
611 |
+
ls
|
612 |
+
python -m pytest -vv tests/llm_translation --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
613 |
+
no_output_timeout: 120m
|
614 |
+
- run:
|
615 |
+
name: Rename the coverage files
|
616 |
+
command: |
|
617 |
+
mv coverage.xml llm_translation_coverage.xml
|
618 |
+
mv .coverage llm_translation_coverage
|
619 |
+
|
620 |
+
# Store test results
|
621 |
+
- store_test_results:
|
622 |
+
path: test-results
|
623 |
+
- persist_to_workspace:
|
624 |
+
root: .
|
625 |
+
paths:
|
626 |
+
- llm_translation_coverage.xml
|
627 |
+
- llm_translation_coverage
|
628 |
+
batches_testing:
|
629 |
+
docker:
|
630 |
+
- image: cimg/python:3.11
|
631 |
+
auth:
|
632 |
+
username: ${DOCKERHUB_USERNAME}
|
633 |
+
password: ${DOCKERHUB_PASSWORD}
|
634 |
+
working_directory: ~/project
|
635 |
+
|
636 |
+
steps:
|
637 |
+
- checkout
|
638 |
+
- run:
|
639 |
+
name: Install Dependencies
|
640 |
+
command: |
|
641 |
+
python -m pip install --upgrade pip
|
642 |
+
python -m pip install -r requirements.txt
|
643 |
+
pip install "respx==0.21.1"
|
644 |
+
pip install "pytest==7.3.1"
|
645 |
+
pip install "pytest-retry==1.6.3"
|
646 |
+
pip install "pytest-asyncio==0.21.1"
|
647 |
+
pip install "pytest-cov==5.0.0"
|
648 |
+
pip install "google-generativeai==0.3.2"
|
649 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
650 |
+
# Run pytest and generate JUnit XML report
|
651 |
+
- run:
|
652 |
+
name: Run tests
|
653 |
+
command: |
|
654 |
+
pwd
|
655 |
+
ls
|
656 |
+
python -m pytest -vv tests/batches_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
657 |
+
no_output_timeout: 120m
|
658 |
+
- run:
|
659 |
+
name: Rename the coverage files
|
660 |
+
command: |
|
661 |
+
mv coverage.xml batches_coverage.xml
|
662 |
+
mv .coverage batches_coverage
|
663 |
+
|
664 |
+
# Store test results
|
665 |
+
- store_test_results:
|
666 |
+
path: test-results
|
667 |
+
- persist_to_workspace:
|
668 |
+
root: .
|
669 |
+
paths:
|
670 |
+
- batches_coverage.xml
|
671 |
+
- batches_coverage
|
672 |
+
litellm_utils_testing:
|
673 |
+
docker:
|
674 |
+
- image: cimg/python:3.11
|
675 |
+
auth:
|
676 |
+
username: ${DOCKERHUB_USERNAME}
|
677 |
+
password: ${DOCKERHUB_PASSWORD}
|
678 |
+
working_directory: ~/project
|
679 |
+
|
680 |
+
steps:
|
681 |
+
- checkout
|
682 |
+
- run:
|
683 |
+
name: Install Dependencies
|
684 |
+
command: |
|
685 |
+
python -m pip install --upgrade pip
|
686 |
+
python -m pip install -r requirements.txt
|
687 |
+
pip install "respx==0.21.1"
|
688 |
+
pip install "pytest==7.3.1"
|
689 |
+
pip install "pytest-retry==1.6.3"
|
690 |
+
pip install "pytest-asyncio==0.21.1"
|
691 |
+
pip install "pytest-cov==5.0.0"
|
692 |
+
pip install "google-generativeai==0.3.2"
|
693 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
694 |
+
pip install numpydoc
|
695 |
+
# Run pytest and generate JUnit XML report
|
696 |
+
- run:
|
697 |
+
name: Run tests
|
698 |
+
command: |
|
699 |
+
pwd
|
700 |
+
ls
|
701 |
+
python -m pytest -vv tests/litellm_utils_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
702 |
+
no_output_timeout: 120m
|
703 |
+
- run:
|
704 |
+
name: Rename the coverage files
|
705 |
+
command: |
|
706 |
+
mv coverage.xml litellm_utils_coverage.xml
|
707 |
+
mv .coverage litellm_utils_coverage
|
708 |
+
|
709 |
+
# Store test results
|
710 |
+
- store_test_results:
|
711 |
+
path: test-results
|
712 |
+
- persist_to_workspace:
|
713 |
+
root: .
|
714 |
+
paths:
|
715 |
+
- litellm_utils_coverage.xml
|
716 |
+
- litellm_utils_coverage
|
717 |
+
|
718 |
+
pass_through_unit_testing:
|
719 |
+
docker:
|
720 |
+
- image: cimg/python:3.11
|
721 |
+
auth:
|
722 |
+
username: ${DOCKERHUB_USERNAME}
|
723 |
+
password: ${DOCKERHUB_PASSWORD}
|
724 |
+
working_directory: ~/project
|
725 |
+
|
726 |
+
steps:
|
727 |
+
- checkout
|
728 |
+
- run:
|
729 |
+
name: Install Dependencies
|
730 |
+
command: |
|
731 |
+
python -m pip install --upgrade pip
|
732 |
+
python -m pip install -r requirements.txt
|
733 |
+
pip install "pytest==7.3.1"
|
734 |
+
pip install "pytest-retry==1.6.3"
|
735 |
+
pip install "pytest-cov==5.0.0"
|
736 |
+
pip install "pytest-asyncio==0.21.1"
|
737 |
+
pip install "respx==0.21.1"
|
738 |
+
# Run pytest and generate JUnit XML report
|
739 |
+
- run:
|
740 |
+
name: Run tests
|
741 |
+
command: |
|
742 |
+
pwd
|
743 |
+
ls
|
744 |
+
python -m pytest -vv tests/pass_through_unit_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
745 |
+
no_output_timeout: 120m
|
746 |
+
- run:
|
747 |
+
name: Rename the coverage files
|
748 |
+
command: |
|
749 |
+
mv coverage.xml pass_through_unit_tests_coverage.xml
|
750 |
+
mv .coverage pass_through_unit_tests_coverage
|
751 |
+
|
752 |
+
# Store test results
|
753 |
+
- store_test_results:
|
754 |
+
path: test-results
|
755 |
+
- persist_to_workspace:
|
756 |
+
root: .
|
757 |
+
paths:
|
758 |
+
- pass_through_unit_tests_coverage.xml
|
759 |
+
- pass_through_unit_tests_coverage
|
760 |
+
image_gen_testing:
|
761 |
+
docker:
|
762 |
+
- image: cimg/python:3.11
|
763 |
+
auth:
|
764 |
+
username: ${DOCKERHUB_USERNAME}
|
765 |
+
password: ${DOCKERHUB_PASSWORD}
|
766 |
+
working_directory: ~/project
|
767 |
+
|
768 |
+
steps:
|
769 |
+
- checkout
|
770 |
+
- run:
|
771 |
+
name: Install Dependencies
|
772 |
+
command: |
|
773 |
+
python -m pip install --upgrade pip
|
774 |
+
python -m pip install -r requirements.txt
|
775 |
+
pip install "pytest==7.3.1"
|
776 |
+
pip install "pytest-retry==1.6.3"
|
777 |
+
pip install "pytest-cov==5.0.0"
|
778 |
+
pip install "pytest-asyncio==0.21.1"
|
779 |
+
pip install "respx==0.21.1"
|
780 |
+
# Run pytest and generate JUnit XML report
|
781 |
+
- run:
|
782 |
+
name: Run tests
|
783 |
+
command: |
|
784 |
+
pwd
|
785 |
+
ls
|
786 |
+
python -m pytest -vv tests/image_gen_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
787 |
+
no_output_timeout: 120m
|
788 |
+
- run:
|
789 |
+
name: Rename the coverage files
|
790 |
+
command: |
|
791 |
+
mv coverage.xml image_gen_coverage.xml
|
792 |
+
mv .coverage image_gen_coverage
|
793 |
+
|
794 |
+
# Store test results
|
795 |
+
- store_test_results:
|
796 |
+
path: test-results
|
797 |
+
- persist_to_workspace:
|
798 |
+
root: .
|
799 |
+
paths:
|
800 |
+
- image_gen_coverage.xml
|
801 |
+
- image_gen_coverage
|
802 |
+
logging_testing:
|
803 |
+
docker:
|
804 |
+
- image: cimg/python:3.11
|
805 |
+
auth:
|
806 |
+
username: ${DOCKERHUB_USERNAME}
|
807 |
+
password: ${DOCKERHUB_PASSWORD}
|
808 |
+
working_directory: ~/project
|
809 |
+
|
810 |
+
steps:
|
811 |
+
- checkout
|
812 |
+
- run:
|
813 |
+
name: Install Dependencies
|
814 |
+
command: |
|
815 |
+
python -m pip install --upgrade pip
|
816 |
+
python -m pip install -r requirements.txt
|
817 |
+
pip install "pytest==7.3.1"
|
818 |
+
pip install "pytest-retry==1.6.3"
|
819 |
+
pip install "pytest-cov==5.0.0"
|
820 |
+
pip install "pytest-asyncio==0.21.1"
|
821 |
+
pip install pytest-mock
|
822 |
+
pip install "respx==0.21.1"
|
823 |
+
pip install "google-generativeai==0.3.2"
|
824 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
825 |
+
pip install "mlflow==2.17.2"
|
826 |
+
# Run pytest and generate JUnit XML report
|
827 |
+
- run:
|
828 |
+
name: Run tests
|
829 |
+
command: |
|
830 |
+
pwd
|
831 |
+
ls
|
832 |
+
python -m pytest -vv tests/logging_callback_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
|
833 |
+
no_output_timeout: 120m
|
834 |
+
- run:
|
835 |
+
name: Rename the coverage files
|
836 |
+
command: |
|
837 |
+
mv coverage.xml logging_coverage.xml
|
838 |
+
mv .coverage logging_coverage
|
839 |
+
|
840 |
+
# Store test results
|
841 |
+
- store_test_results:
|
842 |
+
path: test-results
|
843 |
+
- persist_to_workspace:
|
844 |
+
root: .
|
845 |
+
paths:
|
846 |
+
- logging_coverage.xml
|
847 |
+
- logging_coverage
|
848 |
+
installing_litellm_on_python:
|
849 |
+
docker:
|
850 |
+
- image: circleci/python:3.8
|
851 |
+
auth:
|
852 |
+
username: ${DOCKERHUB_USERNAME}
|
853 |
+
password: ${DOCKERHUB_PASSWORD}
|
854 |
+
working_directory: ~/project
|
855 |
+
|
856 |
+
steps:
|
857 |
+
- checkout
|
858 |
+
- run:
|
859 |
+
name: Install Dependencies
|
860 |
+
command: |
|
861 |
+
python -m pip install --upgrade pip
|
862 |
+
pip install python-dotenv
|
863 |
+
pip install pytest
|
864 |
+
pip install tiktoken
|
865 |
+
pip install aiohttp
|
866 |
+
pip install openai
|
867 |
+
pip install click
|
868 |
+
pip install "boto3==1.34.34"
|
869 |
+
pip install jinja2
|
870 |
+
pip install tokenizers=="0.20.0"
|
871 |
+
pip install uvloop==0.21.0
|
872 |
+
pip install jsonschema
|
873 |
+
- run:
|
874 |
+
name: Run tests
|
875 |
+
command: |
|
876 |
+
pwd
|
877 |
+
ls
|
878 |
+
python -m pytest -vv tests/local_testing/test_basic_python_version.py
|
879 |
+
|
880 |
+
installing_litellm_on_python_3_13:
|
881 |
+
docker:
|
882 |
+
- image: cimg/python:3.13.1
|
883 |
+
auth:
|
884 |
+
username: ${DOCKERHUB_USERNAME}
|
885 |
+
password: ${DOCKERHUB_PASSWORD}
|
886 |
+
working_directory: ~/project
|
887 |
+
|
888 |
+
steps:
|
889 |
+
- checkout
|
890 |
+
- run:
|
891 |
+
name: Install Dependencies
|
892 |
+
command: |
|
893 |
+
python -m pip install --upgrade pip
|
894 |
+
python -m pip install -r requirements.txt
|
895 |
+
pip install "pytest==7.3.1"
|
896 |
+
pip install "pytest-retry==1.6.3"
|
897 |
+
pip install "pytest-asyncio==0.21.1"
|
898 |
+
pip install "pytest-cov==5.0.0"
|
899 |
+
pip install "tomli==2.2.1"
|
900 |
+
- run:
|
901 |
+
name: Run tests
|
902 |
+
command: |
|
903 |
+
pwd
|
904 |
+
ls
|
905 |
+
python -m pytest -vv tests/local_testing/test_basic_python_version.py
|
906 |
+
helm_chart_testing:
|
907 |
+
machine:
|
908 |
+
image: ubuntu-2204:2023.10.1 # Use machine executor instead of docker
|
909 |
+
resource_class: medium
|
910 |
+
working_directory: ~/project
|
911 |
+
|
912 |
+
steps:
|
913 |
+
- checkout
|
914 |
+
# Install Helm
|
915 |
+
- run:
|
916 |
+
name: Install Helm
|
917 |
+
command: |
|
918 |
+
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
919 |
+
|
920 |
+
# Install kind
|
921 |
+
- run:
|
922 |
+
name: Install Kind
|
923 |
+
command: |
|
924 |
+
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
|
925 |
+
chmod +x ./kind
|
926 |
+
sudo mv ./kind /usr/local/bin/kind
|
927 |
+
|
928 |
+
# Install kubectl
|
929 |
+
- run:
|
930 |
+
name: Install kubectl
|
931 |
+
command: |
|
932 |
+
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
933 |
+
chmod +x kubectl
|
934 |
+
sudo mv kubectl /usr/local/bin/
|
935 |
+
|
936 |
+
# Create kind cluster
|
937 |
+
- run:
|
938 |
+
name: Create Kind Cluster
|
939 |
+
command: |
|
940 |
+
kind create cluster --name litellm-test
|
941 |
+
|
942 |
+
# Run helm lint
|
943 |
+
- run:
|
944 |
+
name: Run helm lint
|
945 |
+
command: |
|
946 |
+
helm lint ./deploy/charts/litellm-helm
|
947 |
+
|
948 |
+
# Run helm tests
|
949 |
+
- run:
|
950 |
+
name: Run helm tests
|
951 |
+
command: |
|
952 |
+
helm install litellm ./deploy/charts/litellm-helm -f ./deploy/charts/litellm-helm/ci/test-values.yaml
|
953 |
+
# Wait for pod to be ready
|
954 |
+
echo "Waiting 30 seconds for pod to be ready..."
|
955 |
+
sleep 30
|
956 |
+
|
957 |
+
# Print pod logs before running tests
|
958 |
+
echo "Printing pod logs..."
|
959 |
+
kubectl logs $(kubectl get pods -l app.kubernetes.io/name=litellm -o jsonpath="{.items[0].metadata.name}")
|
960 |
+
|
961 |
+
# Run the helm tests
|
962 |
+
helm test litellm --logs
|
963 |
+
helm test litellm --logs
|
964 |
+
|
965 |
+
# Cleanup
|
966 |
+
- run:
|
967 |
+
name: Cleanup
|
968 |
+
command: |
|
969 |
+
kind delete cluster --name litellm-test
|
970 |
+
when: always # This ensures cleanup runs even if previous steps fail
|
971 |
+
|
972 |
+
|
973 |
+
check_code_and_doc_quality:
|
974 |
+
docker:
|
975 |
+
- image: cimg/python:3.11
|
976 |
+
auth:
|
977 |
+
username: ${DOCKERHUB_USERNAME}
|
978 |
+
password: ${DOCKERHUB_PASSWORD}
|
979 |
+
working_directory: ~/project/litellm
|
980 |
+
|
981 |
+
steps:
|
982 |
+
- checkout
|
983 |
+
- run:
|
984 |
+
name: Install Dependencies
|
985 |
+
command: |
|
986 |
+
python -m pip install --upgrade pip
|
987 |
+
pip install ruff
|
988 |
+
pip install pylint
|
989 |
+
pip install pyright
|
990 |
+
pip install beautifulsoup4
|
991 |
+
pip install .
|
992 |
+
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
993 |
+
- run: python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
|
994 |
+
- run: ruff check ./litellm
|
995 |
+
# - run: python ./tests/documentation_tests/test_general_setting_keys.py
|
996 |
+
- run: python ./tests/code_coverage_tests/router_code_coverage.py
|
997 |
+
- run: python ./tests/code_coverage_tests/callback_manager_test.py
|
998 |
+
- run: python ./tests/code_coverage_tests/recursive_detector.py
|
999 |
+
- run: python ./tests/code_coverage_tests/test_router_strategy_async.py
|
1000 |
+
- run: python ./tests/code_coverage_tests/litellm_logging_code_coverage.py
|
1001 |
+
- run: python ./tests/code_coverage_tests/bedrock_pricing.py
|
1002 |
+
- run: python ./tests/documentation_tests/test_env_keys.py
|
1003 |
+
- run: python ./tests/documentation_tests/test_router_settings.py
|
1004 |
+
- run: python ./tests/documentation_tests/test_api_docs.py
|
1005 |
+
- run: python ./tests/code_coverage_tests/ensure_async_clients_test.py
|
1006 |
+
- run: python ./tests/code_coverage_tests/enforce_llms_folder_style.py
|
1007 |
+
- run: python ./tests/documentation_tests/test_circular_imports.py
|
1008 |
+
- run: helm lint ./deploy/charts/litellm-helm
|
1009 |
+
|
1010 |
+
db_migration_disable_update_check:
|
1011 |
+
machine:
|
1012 |
+
image: ubuntu-2204:2023.10.1
|
1013 |
+
resource_class: xlarge
|
1014 |
+
working_directory: ~/project
|
1015 |
+
steps:
|
1016 |
+
- checkout
|
1017 |
+
- run:
|
1018 |
+
name: Build Docker image
|
1019 |
+
command: |
|
1020 |
+
docker build -t myapp . -f ./docker/Dockerfile.database
|
1021 |
+
- run:
|
1022 |
+
name: Run Docker container
|
1023 |
+
command: |
|
1024 |
+
docker run --name my-app \
|
1025 |
+
-p 4000:4000 \
|
1026 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1027 |
+
-e DISABLE_SCHEMA_UPDATE="True" \
|
1028 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/bad_schema.prisma:/app/schema.prisma \
|
1029 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/bad_schema.prisma:/app/litellm/proxy/schema.prisma \
|
1030 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/disable_schema_update.yaml:/app/config.yaml \
|
1031 |
+
myapp:latest \
|
1032 |
+
--config /app/config.yaml \
|
1033 |
+
--port 4000 > docker_output.log 2>&1 || true
|
1034 |
+
- run:
|
1035 |
+
name: Display Docker logs
|
1036 |
+
command: cat docker_output.log
|
1037 |
+
- run:
|
1038 |
+
name: Check for expected error
|
1039 |
+
command: |
|
1040 |
+
if grep -q "prisma schema out of sync with db. Consider running these sql_commands to sync the two" docker_output.log; then
|
1041 |
+
echo "Expected error found. Test passed."
|
1042 |
+
else
|
1043 |
+
echo "Expected error not found. Test failed."
|
1044 |
+
cat docker_output.log
|
1045 |
+
exit 1
|
1046 |
+
fi
|
1047 |
+
|
1048 |
+
build_and_test:
|
1049 |
+
machine:
|
1050 |
+
image: ubuntu-2204:2023.10.1
|
1051 |
+
resource_class: xlarge
|
1052 |
+
working_directory: ~/project
|
1053 |
+
steps:
|
1054 |
+
- checkout
|
1055 |
+
- run:
|
1056 |
+
name: Install Docker CLI (In case it's not already installed)
|
1057 |
+
command: |
|
1058 |
+
sudo apt-get update
|
1059 |
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
1060 |
+
- run:
|
1061 |
+
name: Install Python 3.9
|
1062 |
+
command: |
|
1063 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1064 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1065 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1066 |
+
conda init bash
|
1067 |
+
source ~/.bashrc
|
1068 |
+
conda create -n myenv python=3.9 -y
|
1069 |
+
conda activate myenv
|
1070 |
+
python --version
|
1071 |
+
- run:
|
1072 |
+
name: Install Dependencies
|
1073 |
+
command: |
|
1074 |
+
pip install "pytest==7.3.1"
|
1075 |
+
pip install "pytest-asyncio==0.21.1"
|
1076 |
+
pip install aiohttp
|
1077 |
+
python -m pip install --upgrade pip
|
1078 |
+
python -m pip install -r .circleci/requirements.txt
|
1079 |
+
pip install "pytest==7.3.1"
|
1080 |
+
pip install "pytest-retry==1.6.3"
|
1081 |
+
pip install "pytest-mock==3.12.0"
|
1082 |
+
pip install "pytest-asyncio==0.21.1"
|
1083 |
+
pip install mypy
|
1084 |
+
pip install "google-generativeai==0.3.2"
|
1085 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
1086 |
+
pip install pyarrow
|
1087 |
+
pip install "boto3==1.34.34"
|
1088 |
+
pip install "aioboto3==12.3.0"
|
1089 |
+
pip install langchain
|
1090 |
+
pip install "langfuse>=2.0.0"
|
1091 |
+
pip install "logfire==0.29.0"
|
1092 |
+
pip install numpydoc
|
1093 |
+
pip install prisma
|
1094 |
+
pip install fastapi
|
1095 |
+
pip install jsonschema
|
1096 |
+
pip install "httpx==0.24.1"
|
1097 |
+
pip install "gunicorn==21.2.0"
|
1098 |
+
pip install "anyio==3.7.1"
|
1099 |
+
pip install "aiodynamo==23.10.1"
|
1100 |
+
pip install "asyncio==3.4.3"
|
1101 |
+
pip install "PyGithub==1.59.1"
|
1102 |
+
pip install "openai==1.54.0 "
|
1103 |
+
- run:
|
1104 |
+
name: Install Grype
|
1105 |
+
command: |
|
1106 |
+
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sudo sh -s -- -b /usr/local/bin
|
1107 |
+
- run:
|
1108 |
+
name: Build and Scan Docker Images
|
1109 |
+
command: |
|
1110 |
+
# Build and scan Dockerfile.database
|
1111 |
+
echo "Building and scanning Dockerfile.database..."
|
1112 |
+
docker build -t litellm-database:latest -f ./docker/Dockerfile.database .
|
1113 |
+
grype litellm-database:latest --fail-on high
|
1114 |
+
|
1115 |
+
# Build and scan main Dockerfile
|
1116 |
+
echo "Building and scanning main Dockerfile..."
|
1117 |
+
docker build -t litellm:latest .
|
1118 |
+
grype litellm:latest --fail-on high
|
1119 |
+
- run:
|
1120 |
+
name: Build Docker image
|
1121 |
+
command: docker build -t my-app:latest -f ./docker/Dockerfile.database .
|
1122 |
+
- run:
|
1123 |
+
name: Run Docker container
|
1124 |
+
command: |
|
1125 |
+
docker run -d \
|
1126 |
+
-p 4000:4000 \
|
1127 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1128 |
+
-e AZURE_API_KEY=$AZURE_API_KEY \
|
1129 |
+
-e REDIS_HOST=$REDIS_HOST \
|
1130 |
+
-e REDIS_PASSWORD=$REDIS_PASSWORD \
|
1131 |
+
-e REDIS_PORT=$REDIS_PORT \
|
1132 |
+
-e AZURE_FRANCE_API_KEY=$AZURE_FRANCE_API_KEY \
|
1133 |
+
-e AZURE_EUROPE_API_KEY=$AZURE_EUROPE_API_KEY \
|
1134 |
+
-e MISTRAL_API_KEY=$MISTRAL_API_KEY \
|
1135 |
+
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
1136 |
+
-e GROQ_API_KEY=$GROQ_API_KEY \
|
1137 |
+
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
1138 |
+
-e COHERE_API_KEY=$COHERE_API_KEY \
|
1139 |
+
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
1140 |
+
-e AWS_REGION_NAME=$AWS_REGION_NAME \
|
1141 |
+
-e AUTO_INFER_REGION=True \
|
1142 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1143 |
+
-e USE_DDTRACE=True \
|
1144 |
+
-e DD_API_KEY=$DD_API_KEY \
|
1145 |
+
-e DD_SITE=$DD_SITE \
|
1146 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1147 |
+
-e LANGFUSE_PROJECT1_PUBLIC=$LANGFUSE_PROJECT1_PUBLIC \
|
1148 |
+
-e LANGFUSE_PROJECT2_PUBLIC=$LANGFUSE_PROJECT2_PUBLIC \
|
1149 |
+
-e LANGFUSE_PROJECT1_SECRET=$LANGFUSE_PROJECT1_SECRET \
|
1150 |
+
-e LANGFUSE_PROJECT2_SECRET=$LANGFUSE_PROJECT2_SECRET \
|
1151 |
+
--name my-app \
|
1152 |
+
-v $(pwd)/proxy_server_config.yaml:/app/config.yaml \
|
1153 |
+
my-app:latest \
|
1154 |
+
--config /app/config.yaml \
|
1155 |
+
--port 4000 \
|
1156 |
+
--detailed_debug \
|
1157 |
+
- run:
|
1158 |
+
name: Install curl and dockerize
|
1159 |
+
command: |
|
1160 |
+
sudo apt-get update
|
1161 |
+
sudo apt-get install -y curl
|
1162 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1163 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1164 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1165 |
+
- run:
|
1166 |
+
name: Start outputting logs
|
1167 |
+
command: docker logs -f my-app
|
1168 |
+
background: true
|
1169 |
+
- run:
|
1170 |
+
name: Wait for app to be ready
|
1171 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1172 |
+
- run:
|
1173 |
+
name: Run tests
|
1174 |
+
command: |
|
1175 |
+
pwd
|
1176 |
+
ls
|
1177 |
+
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
|
1178 |
+
no_output_timeout: 120m
|
1179 |
+
|
1180 |
+
# Store test results
|
1181 |
+
- store_test_results:
|
1182 |
+
path: test-results
|
1183 |
+
e2e_openai_misc_endpoints:
|
1184 |
+
machine:
|
1185 |
+
image: ubuntu-2204:2023.10.1
|
1186 |
+
resource_class: xlarge
|
1187 |
+
working_directory: ~/project
|
1188 |
+
steps:
|
1189 |
+
- checkout
|
1190 |
+
- run:
|
1191 |
+
name: Install Docker CLI (In case it's not already installed)
|
1192 |
+
command: |
|
1193 |
+
sudo apt-get update
|
1194 |
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
1195 |
+
- run:
|
1196 |
+
name: Install Python 3.9
|
1197 |
+
command: |
|
1198 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1199 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1200 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1201 |
+
conda init bash
|
1202 |
+
source ~/.bashrc
|
1203 |
+
conda create -n myenv python=3.9 -y
|
1204 |
+
conda activate myenv
|
1205 |
+
python --version
|
1206 |
+
- run:
|
1207 |
+
name: Install Dependencies
|
1208 |
+
command: |
|
1209 |
+
pip install "pytest==7.3.1"
|
1210 |
+
pip install "pytest-asyncio==0.21.1"
|
1211 |
+
pip install aiohttp
|
1212 |
+
python -m pip install --upgrade pip
|
1213 |
+
python -m pip install -r .circleci/requirements.txt
|
1214 |
+
pip install "pytest==7.3.1"
|
1215 |
+
pip install "pytest-retry==1.6.3"
|
1216 |
+
pip install "pytest-mock==3.12.0"
|
1217 |
+
pip install "pytest-asyncio==0.21.1"
|
1218 |
+
pip install mypy
|
1219 |
+
pip install "jsonlines==4.0.0"
|
1220 |
+
pip install "google-generativeai==0.3.2"
|
1221 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
1222 |
+
pip install pyarrow
|
1223 |
+
pip install "boto3==1.34.34"
|
1224 |
+
pip install "aioboto3==12.3.0"
|
1225 |
+
pip install langchain
|
1226 |
+
pip install "langfuse>=2.0.0"
|
1227 |
+
pip install "logfire==0.29.0"
|
1228 |
+
pip install numpydoc
|
1229 |
+
pip install prisma
|
1230 |
+
pip install fastapi
|
1231 |
+
pip install jsonschema
|
1232 |
+
pip install "httpx==0.24.1"
|
1233 |
+
pip install "gunicorn==21.2.0"
|
1234 |
+
pip install "anyio==3.7.1"
|
1235 |
+
pip install "aiodynamo==23.10.1"
|
1236 |
+
pip install "asyncio==3.4.3"
|
1237 |
+
pip install "PyGithub==1.59.1"
|
1238 |
+
pip install "openai==1.54.0 "
|
1239 |
+
# Run pytest and generate JUnit XML report
|
1240 |
+
- run:
|
1241 |
+
name: Build Docker image
|
1242 |
+
command: docker build -t my-app:latest -f ./docker/Dockerfile.database .
|
1243 |
+
- run:
|
1244 |
+
name: Run Docker container
|
1245 |
+
command: |
|
1246 |
+
docker run -d \
|
1247 |
+
-p 4000:4000 \
|
1248 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1249 |
+
-e AZURE_API_KEY=$AZURE_BATCHES_API_KEY \
|
1250 |
+
-e AZURE_API_BASE=$AZURE_BATCHES_API_BASE \
|
1251 |
+
-e AZURE_API_VERSION="2024-05-01-preview" \
|
1252 |
+
-e REDIS_HOST=$REDIS_HOST \
|
1253 |
+
-e REDIS_PASSWORD=$REDIS_PASSWORD \
|
1254 |
+
-e REDIS_PORT=$REDIS_PORT \
|
1255 |
+
-e AZURE_FRANCE_API_KEY=$AZURE_FRANCE_API_KEY \
|
1256 |
+
-e AZURE_EUROPE_API_KEY=$AZURE_EUROPE_API_KEY \
|
1257 |
+
-e MISTRAL_API_KEY=$MISTRAL_API_KEY \
|
1258 |
+
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
1259 |
+
-e GROQ_API_KEY=$GROQ_API_KEY \
|
1260 |
+
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
1261 |
+
-e COHERE_API_KEY=$COHERE_API_KEY \
|
1262 |
+
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
1263 |
+
-e AWS_REGION_NAME=$AWS_REGION_NAME \
|
1264 |
+
-e AUTO_INFER_REGION=True \
|
1265 |
+
-e USE_DDTRACE=True \
|
1266 |
+
-e DD_API_KEY=$DD_API_KEY \
|
1267 |
+
-e DD_SITE=$DD_SITE \
|
1268 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1269 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1270 |
+
-e LANGFUSE_PROJECT1_PUBLIC=$LANGFUSE_PROJECT1_PUBLIC \
|
1271 |
+
-e LANGFUSE_PROJECT2_PUBLIC=$LANGFUSE_PROJECT2_PUBLIC \
|
1272 |
+
-e LANGFUSE_PROJECT1_SECRET=$LANGFUSE_PROJECT1_SECRET \
|
1273 |
+
-e LANGFUSE_PROJECT2_SECRET=$LANGFUSE_PROJECT2_SECRET \
|
1274 |
+
--name my-app \
|
1275 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/oai_misc_config.yaml:/app/config.yaml \
|
1276 |
+
my-app:latest \
|
1277 |
+
--config /app/config.yaml \
|
1278 |
+
--port 4000 \
|
1279 |
+
--detailed_debug \
|
1280 |
+
- run:
|
1281 |
+
name: Install curl and dockerize
|
1282 |
+
command: |
|
1283 |
+
sudo apt-get update
|
1284 |
+
sudo apt-get install -y curl
|
1285 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1286 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1287 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1288 |
+
- run:
|
1289 |
+
name: Start outputting logs
|
1290 |
+
command: docker logs -f my-app
|
1291 |
+
background: true
|
1292 |
+
- run:
|
1293 |
+
name: Wait for app to be ready
|
1294 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1295 |
+
- run:
|
1296 |
+
name: Run tests
|
1297 |
+
command: |
|
1298 |
+
pwd
|
1299 |
+
ls
|
1300 |
+
python -m pytest -s -vv tests/openai_misc_endpoints_tests --junitxml=test-results/junit.xml --durations=5
|
1301 |
+
no_output_timeout: 120m
|
1302 |
+
|
1303 |
+
# Store test results
|
1304 |
+
- store_test_results:
|
1305 |
+
path: test-results
|
1306 |
+
proxy_logging_guardrails_model_info_tests:
|
1307 |
+
machine:
|
1308 |
+
image: ubuntu-2204:2023.10.1
|
1309 |
+
resource_class: xlarge
|
1310 |
+
working_directory: ~/project
|
1311 |
+
steps:
|
1312 |
+
- checkout
|
1313 |
+
- run:
|
1314 |
+
name: Install Docker CLI (In case it's not already installed)
|
1315 |
+
command: |
|
1316 |
+
sudo apt-get update
|
1317 |
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
1318 |
+
- run:
|
1319 |
+
name: Install Python 3.9
|
1320 |
+
command: |
|
1321 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1322 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1323 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1324 |
+
conda init bash
|
1325 |
+
source ~/.bashrc
|
1326 |
+
conda create -n myenv python=3.9 -y
|
1327 |
+
conda activate myenv
|
1328 |
+
python --version
|
1329 |
+
- run:
|
1330 |
+
name: Install Dependencies
|
1331 |
+
command: |
|
1332 |
+
pip install "pytest==7.3.1"
|
1333 |
+
pip install "pytest-asyncio==0.21.1"
|
1334 |
+
pip install aiohttp
|
1335 |
+
python -m pip install --upgrade pip
|
1336 |
+
python -m pip install -r .circleci/requirements.txt
|
1337 |
+
pip install "pytest==7.3.1"
|
1338 |
+
pip install "pytest-retry==1.6.3"
|
1339 |
+
pip install "pytest-mock==3.12.0"
|
1340 |
+
pip install "pytest-asyncio==0.21.1"
|
1341 |
+
pip install mypy
|
1342 |
+
pip install "google-generativeai==0.3.2"
|
1343 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
1344 |
+
pip install pyarrow
|
1345 |
+
pip install "boto3==1.34.34"
|
1346 |
+
pip install "aioboto3==12.3.0"
|
1347 |
+
pip install langchain
|
1348 |
+
pip install "langfuse>=2.0.0"
|
1349 |
+
pip install "logfire==0.29.0"
|
1350 |
+
pip install numpydoc
|
1351 |
+
pip install prisma
|
1352 |
+
pip install fastapi
|
1353 |
+
pip install jsonschema
|
1354 |
+
pip install "httpx==0.24.1"
|
1355 |
+
pip install "gunicorn==21.2.0"
|
1356 |
+
pip install "anyio==3.7.1"
|
1357 |
+
pip install "aiodynamo==23.10.1"
|
1358 |
+
pip install "asyncio==3.4.3"
|
1359 |
+
pip install "PyGithub==1.59.1"
|
1360 |
+
pip install "openai==1.54.0 "
|
1361 |
+
- run:
|
1362 |
+
name: Build Docker image
|
1363 |
+
command: docker build -t my-app:latest -f ./docker/Dockerfile.database .
|
1364 |
+
- run:
|
1365 |
+
name: Run Docker container
|
1366 |
+
# intentionally give bad redis credentials here
|
1367 |
+
# the OTEL test - should get this as a trace
|
1368 |
+
command: |
|
1369 |
+
docker run -d \
|
1370 |
+
-p 4000:4000 \
|
1371 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1372 |
+
-e REDIS_HOST=$REDIS_HOST \
|
1373 |
+
-e REDIS_PASSWORD=$REDIS_PASSWORD \
|
1374 |
+
-e REDIS_PORT=$REDIS_PORT \
|
1375 |
+
-e LITELLM_MASTER_KEY="sk-1234" \
|
1376 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1377 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1378 |
+
-e OTEL_EXPORTER="in_memory" \
|
1379 |
+
-e APORIA_API_BASE_2=$APORIA_API_BASE_2 \
|
1380 |
+
-e APORIA_API_KEY_2=$APORIA_API_KEY_2 \
|
1381 |
+
-e APORIA_API_BASE_1=$APORIA_API_BASE_1 \
|
1382 |
+
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
1383 |
+
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
1384 |
+
-e USE_DDTRACE=True \
|
1385 |
+
-e DD_API_KEY=$DD_API_KEY \
|
1386 |
+
-e DD_SITE=$DD_SITE \
|
1387 |
+
-e AWS_REGION_NAME=$AWS_REGION_NAME \
|
1388 |
+
-e APORIA_API_KEY_1=$APORIA_API_KEY_1 \
|
1389 |
+
-e COHERE_API_KEY=$COHERE_API_KEY \
|
1390 |
+
-e GCS_FLUSH_INTERVAL="1" \
|
1391 |
+
--name my-app \
|
1392 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/otel_test_config.yaml:/app/config.yaml \
|
1393 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/custom_guardrail.py:/app/custom_guardrail.py \
|
1394 |
+
my-app:latest \
|
1395 |
+
--config /app/config.yaml \
|
1396 |
+
--port 4000 \
|
1397 |
+
--detailed_debug \
|
1398 |
+
- run:
|
1399 |
+
name: Install curl and dockerize
|
1400 |
+
command: |
|
1401 |
+
sudo apt-get update
|
1402 |
+
sudo apt-get install -y curl
|
1403 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1404 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1405 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1406 |
+
- run:
|
1407 |
+
name: Start outputting logs
|
1408 |
+
command: docker logs -f my-app
|
1409 |
+
background: true
|
1410 |
+
- run:
|
1411 |
+
name: Wait for app to be ready
|
1412 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1413 |
+
- run:
|
1414 |
+
name: Run tests
|
1415 |
+
command: |
|
1416 |
+
pwd
|
1417 |
+
ls
|
1418 |
+
python -m pytest -vv tests/otel_tests -x --junitxml=test-results/junit.xml --durations=5
|
1419 |
+
no_output_timeout:
|
1420 |
+
120m
|
1421 |
+
# Clean up first container
|
1422 |
+
- run:
|
1423 |
+
name: Stop and remove first container
|
1424 |
+
command: |
|
1425 |
+
docker stop my-app
|
1426 |
+
docker rm my-app
|
1427 |
+
|
1428 |
+
# Second Docker Container Run with Different Config
|
1429 |
+
# NOTE: We intentionally pass a "bad" license here. We need to ensure proxy starts and serves request even with bad license
|
1430 |
+
- run:
|
1431 |
+
name: Run Second Docker container
|
1432 |
+
command: |
|
1433 |
+
docker run -d \
|
1434 |
+
-p 4000:4000 \
|
1435 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1436 |
+
-e REDIS_HOST=$REDIS_HOST \
|
1437 |
+
-e REDIS_PASSWORD=$REDIS_PASSWORD \
|
1438 |
+
-e REDIS_PORT=$REDIS_PORT \
|
1439 |
+
-e LITELLM_MASTER_KEY="sk-1234" \
|
1440 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1441 |
+
-e LITELLM_LICENSE="bad-license" \
|
1442 |
+
--name my-app-3 \
|
1443 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/enterprise_config.yaml:/app/config.yaml \
|
1444 |
+
my-app:latest \
|
1445 |
+
--config /app/config.yaml \
|
1446 |
+
--port 4000 \
|
1447 |
+
--detailed_debug
|
1448 |
+
|
1449 |
+
- run:
|
1450 |
+
name: Start outputting logs for second container
|
1451 |
+
command: docker logs -f my-app-2
|
1452 |
+
background: true
|
1453 |
+
|
1454 |
+
- run:
|
1455 |
+
name: Wait for second app to be ready
|
1456 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1457 |
+
|
1458 |
+
- run:
|
1459 |
+
name: Run second round of tests
|
1460 |
+
command: |
|
1461 |
+
python -m pytest -vv tests/basic_proxy_startup_tests -x --junitxml=test-results/junit-2.xml --durations=5
|
1462 |
+
no_output_timeout: 120m
|
1463 |
+
|
1464 |
+
# Store test results
|
1465 |
+
- store_test_results:
|
1466 |
+
path: test-results
|
1467 |
+
|
1468 |
+
proxy_store_model_in_db_tests:
|
1469 |
+
machine:
|
1470 |
+
image: ubuntu-2204:2023.10.1
|
1471 |
+
resource_class: xlarge
|
1472 |
+
working_directory: ~/project
|
1473 |
+
steps:
|
1474 |
+
- checkout
|
1475 |
+
- run:
|
1476 |
+
name: Install Docker CLI (In case it's not already installed)
|
1477 |
+
command: |
|
1478 |
+
sudo apt-get update
|
1479 |
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
1480 |
+
- run:
|
1481 |
+
name: Install Python 3.9
|
1482 |
+
command: |
|
1483 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1484 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1485 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1486 |
+
conda init bash
|
1487 |
+
source ~/.bashrc
|
1488 |
+
conda create -n myenv python=3.9 -y
|
1489 |
+
conda activate myenv
|
1490 |
+
python --version
|
1491 |
+
- run:
|
1492 |
+
name: Install Dependencies
|
1493 |
+
command: |
|
1494 |
+
pip install "pytest==7.3.1"
|
1495 |
+
pip install "pytest-asyncio==0.21.1"
|
1496 |
+
pip install aiohttp
|
1497 |
+
python -m pip install --upgrade pip
|
1498 |
+
python -m pip install -r requirements.txt
|
1499 |
+
pip install "pytest==7.3.1"
|
1500 |
+
pip install "pytest-retry==1.6.3"
|
1501 |
+
pip install "pytest-mock==3.12.0"
|
1502 |
+
pip install "pytest-asyncio==0.21.1"
|
1503 |
+
- run:
|
1504 |
+
name: Build Docker image
|
1505 |
+
command: docker build -t my-app:latest -f ./docker/Dockerfile.database .
|
1506 |
+
- run:
|
1507 |
+
name: Run Docker container
|
1508 |
+
# intentionally give bad redis credentials here
|
1509 |
+
# the OTEL test - should get this as a trace
|
1510 |
+
command: |
|
1511 |
+
docker run -d \
|
1512 |
+
-p 4000:4000 \
|
1513 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1514 |
+
-e STORE_MODEL_IN_DB="True" \
|
1515 |
+
-e LITELLM_MASTER_KEY="sk-1234" \
|
1516 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1517 |
+
--name my-app \
|
1518 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/store_model_db_config.yaml:/app/config.yaml \
|
1519 |
+
my-app:latest \
|
1520 |
+
--config /app/config.yaml \
|
1521 |
+
--port 4000 \
|
1522 |
+
--detailed_debug \
|
1523 |
+
- run:
|
1524 |
+
name: Install curl and dockerize
|
1525 |
+
command: |
|
1526 |
+
sudo apt-get update
|
1527 |
+
sudo apt-get install -y curl
|
1528 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1529 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1530 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1531 |
+
- run:
|
1532 |
+
name: Start outputting logs
|
1533 |
+
command: docker logs -f my-app
|
1534 |
+
background: true
|
1535 |
+
- run:
|
1536 |
+
name: Wait for app to be ready
|
1537 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1538 |
+
- run:
|
1539 |
+
name: Run tests
|
1540 |
+
command: |
|
1541 |
+
pwd
|
1542 |
+
ls
|
1543 |
+
python -m pytest -vv tests/store_model_in_db_tests -x --junitxml=test-results/junit.xml --durations=5
|
1544 |
+
no_output_timeout:
|
1545 |
+
120m
|
1546 |
+
# Clean up first container
|
1547 |
+
|
1548 |
+
proxy_build_from_pip_tests:
|
1549 |
+
# Change from docker to machine executor
|
1550 |
+
machine:
|
1551 |
+
image: ubuntu-2204:2023.10.1
|
1552 |
+
resource_class: xlarge
|
1553 |
+
working_directory: ~/project
|
1554 |
+
steps:
|
1555 |
+
- checkout
|
1556 |
+
# Remove Docker CLI installation since it's already available in machine executor
|
1557 |
+
- run:
|
1558 |
+
name: Install Python 3.13
|
1559 |
+
command: |
|
1560 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1561 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1562 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1563 |
+
conda init bash
|
1564 |
+
source ~/.bashrc
|
1565 |
+
conda create -n myenv python=3.13 -y
|
1566 |
+
conda activate myenv
|
1567 |
+
python --version
|
1568 |
+
- run:
|
1569 |
+
name: Install Dependencies
|
1570 |
+
command: |
|
1571 |
+
pip install "pytest==7.3.1"
|
1572 |
+
pip install "pytest-asyncio==0.21.1"
|
1573 |
+
pip install aiohttp
|
1574 |
+
python -m pip install --upgrade pip
|
1575 |
+
pip install "pytest==7.3.1"
|
1576 |
+
pip install "pytest-retry==1.6.3"
|
1577 |
+
pip install "pytest-mock==3.12.0"
|
1578 |
+
pip install "pytest-asyncio==0.21.1"
|
1579 |
+
pip install mypy
|
1580 |
+
- run:
|
1581 |
+
name: Build Docker image
|
1582 |
+
command: |
|
1583 |
+
cd docker/build_from_pip
|
1584 |
+
docker build -t my-app:latest -f Dockerfile.build_from_pip .
|
1585 |
+
- run:
|
1586 |
+
name: Run Docker container
|
1587 |
+
# intentionally give bad redis credentials here
|
1588 |
+
# the OTEL test - should get this as a trace
|
1589 |
+
command: |
|
1590 |
+
cd docker/build_from_pip
|
1591 |
+
docker run -d \
|
1592 |
+
-p 4000:4000 \
|
1593 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1594 |
+
-e REDIS_HOST=$REDIS_HOST \
|
1595 |
+
-e REDIS_PASSWORD=$REDIS_PASSWORD \
|
1596 |
+
-e REDIS_PORT=$REDIS_PORT \
|
1597 |
+
-e LITELLM_MASTER_KEY="sk-1234" \
|
1598 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1599 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1600 |
+
-e OTEL_EXPORTER="in_memory" \
|
1601 |
+
-e APORIA_API_BASE_2=$APORIA_API_BASE_2 \
|
1602 |
+
-e APORIA_API_KEY_2=$APORIA_API_KEY_2 \
|
1603 |
+
-e APORIA_API_BASE_1=$APORIA_API_BASE_1 \
|
1604 |
+
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
1605 |
+
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
1606 |
+
-e AWS_REGION_NAME=$AWS_REGION_NAME \
|
1607 |
+
-e APORIA_API_KEY_1=$APORIA_API_KEY_1 \
|
1608 |
+
-e COHERE_API_KEY=$COHERE_API_KEY \
|
1609 |
+
-e USE_DDTRACE=True \
|
1610 |
+
-e DD_API_KEY=$DD_API_KEY \
|
1611 |
+
-e DD_SITE=$DD_SITE \
|
1612 |
+
-e GCS_FLUSH_INTERVAL="1" \
|
1613 |
+
--name my-app \
|
1614 |
+
-v $(pwd)/litellm_config.yaml:/app/config.yaml \
|
1615 |
+
my-app:latest \
|
1616 |
+
--config /app/config.yaml \
|
1617 |
+
--port 4000 \
|
1618 |
+
--detailed_debug \
|
1619 |
+
- run:
|
1620 |
+
name: Install curl and dockerize
|
1621 |
+
command: |
|
1622 |
+
sudo apt-get update
|
1623 |
+
sudo apt-get install -y curl
|
1624 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1625 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1626 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1627 |
+
- run:
|
1628 |
+
name: Start outputting logs
|
1629 |
+
command: docker logs -f my-app
|
1630 |
+
background: true
|
1631 |
+
- run:
|
1632 |
+
name: Wait for app to be ready
|
1633 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1634 |
+
- run:
|
1635 |
+
name: Run tests
|
1636 |
+
command: |
|
1637 |
+
python -m pytest -vv tests/basic_proxy_startup_tests -x --junitxml=test-results/junit-2.xml --durations=5
|
1638 |
+
no_output_timeout:
|
1639 |
+
120m
|
1640 |
+
# Clean up first container
|
1641 |
+
- run:
|
1642 |
+
name: Stop and remove first container
|
1643 |
+
command: |
|
1644 |
+
docker stop my-app
|
1645 |
+
docker rm my-app
|
1646 |
+
proxy_pass_through_endpoint_tests:
|
1647 |
+
machine:
|
1648 |
+
image: ubuntu-2204:2023.10.1
|
1649 |
+
resource_class: xlarge
|
1650 |
+
working_directory: ~/project
|
1651 |
+
steps:
|
1652 |
+
- checkout
|
1653 |
+
- run:
|
1654 |
+
name: Install Docker CLI (In case it's not already installed)
|
1655 |
+
command: |
|
1656 |
+
sudo apt-get update
|
1657 |
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
1658 |
+
- run:
|
1659 |
+
name: Install Python 3.9
|
1660 |
+
command: |
|
1661 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1662 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1663 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1664 |
+
conda init bash
|
1665 |
+
source ~/.bashrc
|
1666 |
+
conda create -n myenv python=3.9 -y
|
1667 |
+
conda activate myenv
|
1668 |
+
python --version
|
1669 |
+
- run:
|
1670 |
+
name: Install Dependencies
|
1671 |
+
command: |
|
1672 |
+
pip install "pytest==7.3.1"
|
1673 |
+
pip install "pytest-retry==1.6.3"
|
1674 |
+
pip install "pytest-asyncio==0.21.1"
|
1675 |
+
pip install "google-cloud-aiplatform==1.43.0"
|
1676 |
+
pip install aiohttp
|
1677 |
+
pip install "openai==1.54.0 "
|
1678 |
+
pip install "assemblyai==0.37.0"
|
1679 |
+
python -m pip install --upgrade pip
|
1680 |
+
pip install "pydantic==2.7.1"
|
1681 |
+
pip install "pytest==7.3.1"
|
1682 |
+
pip install "pytest-mock==3.12.0"
|
1683 |
+
pip install "pytest-asyncio==0.21.1"
|
1684 |
+
pip install "boto3==1.34.34"
|
1685 |
+
pip install mypy
|
1686 |
+
pip install pyarrow
|
1687 |
+
pip install numpydoc
|
1688 |
+
pip install prisma
|
1689 |
+
pip install fastapi
|
1690 |
+
pip install jsonschema
|
1691 |
+
pip install "httpx==0.24.1"
|
1692 |
+
pip install "anyio==3.7.1"
|
1693 |
+
pip install "asyncio==3.4.3"
|
1694 |
+
pip install "PyGithub==1.59.1"
|
1695 |
+
pip install "google-cloud-aiplatform==1.59.0"
|
1696 |
+
pip install anthropic
|
1697 |
+
# Run pytest and generate JUnit XML report
|
1698 |
+
- run:
|
1699 |
+
name: Build Docker image
|
1700 |
+
command: docker build -t my-app:latest -f ./docker/Dockerfile.database .
|
1701 |
+
- run:
|
1702 |
+
name: Run Docker container
|
1703 |
+
command: |
|
1704 |
+
docker run -d \
|
1705 |
+
-p 4000:4000 \
|
1706 |
+
-e DATABASE_URL=$PROXY_DATABASE_URL \
|
1707 |
+
-e LITELLM_MASTER_KEY="sk-1234" \
|
1708 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1709 |
+
-e GEMINI_API_KEY=$GEMINI_API_KEY \
|
1710 |
+
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
1711 |
+
-e ASSEMBLYAI_API_KEY=$ASSEMBLYAI_API_KEY \
|
1712 |
+
-e USE_DDTRACE=True \
|
1713 |
+
-e DD_API_KEY=$DD_API_KEY \
|
1714 |
+
-e DD_SITE=$DD_SITE \
|
1715 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1716 |
+
--name my-app \
|
1717 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/pass_through_config.yaml:/app/config.yaml \
|
1718 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/custom_auth_basic.py:/app/custom_auth_basic.py \
|
1719 |
+
my-app:latest \
|
1720 |
+
--config /app/config.yaml \
|
1721 |
+
--port 4000 \
|
1722 |
+
--detailed_debug \
|
1723 |
+
- run:
|
1724 |
+
name: Install curl and dockerize
|
1725 |
+
command: |
|
1726 |
+
sudo apt-get update
|
1727 |
+
sudo apt-get install -y curl
|
1728 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1729 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1730 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1731 |
+
- run:
|
1732 |
+
name: Start outputting logs
|
1733 |
+
command: docker logs -f my-app
|
1734 |
+
background: true
|
1735 |
+
- run:
|
1736 |
+
name: Wait for app to be ready
|
1737 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1738 |
+
# New steps to run Node.js test
|
1739 |
+
- run:
|
1740 |
+
name: Install Node.js
|
1741 |
+
command: |
|
1742 |
+
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
1743 |
+
sudo apt-get install -y nodejs
|
1744 |
+
node --version
|
1745 |
+
npm --version
|
1746 |
+
|
1747 |
+
- run:
|
1748 |
+
name: Install Node.js dependencies
|
1749 |
+
command: |
|
1750 |
+
npm install @google-cloud/vertexai
|
1751 |
+
npm install @google/generative-ai
|
1752 |
+
npm install --save-dev jest
|
1753 |
+
|
1754 |
+
- run:
|
1755 |
+
name: Run Vertex AI, Google AI Studio Node.js tests
|
1756 |
+
command: |
|
1757 |
+
npx jest tests/pass_through_tests --verbose
|
1758 |
+
no_output_timeout: 30m
|
1759 |
+
- run:
|
1760 |
+
name: Run tests
|
1761 |
+
command: |
|
1762 |
+
pwd
|
1763 |
+
ls
|
1764 |
+
python -m pytest -vv tests/pass_through_tests/ -x --junitxml=test-results/junit.xml --durations=5
|
1765 |
+
no_output_timeout: 120m
|
1766 |
+
# Store test results
|
1767 |
+
- store_test_results:
|
1768 |
+
path: test-results
|
1769 |
+
|
1770 |
+
upload-coverage:
|
1771 |
+
docker:
|
1772 |
+
- image: cimg/python:3.9
|
1773 |
+
steps:
|
1774 |
+
- checkout
|
1775 |
+
- attach_workspace:
|
1776 |
+
at: .
|
1777 |
+
# Check file locations
|
1778 |
+
- run:
|
1779 |
+
name: Check coverage file location
|
1780 |
+
command: |
|
1781 |
+
echo "Current directory:"
|
1782 |
+
ls -la
|
1783 |
+
echo "\nContents of tests/llm_translation:"
|
1784 |
+
ls -la tests/llm_translation
|
1785 |
+
- run:
|
1786 |
+
name: Combine Coverage
|
1787 |
+
command: |
|
1788 |
+
python -m venv venv
|
1789 |
+
. venv/bin/activate
|
1790 |
+
pip install coverage
|
1791 |
+
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
|
1792 |
+
coverage xml
|
1793 |
+
- codecov/upload:
|
1794 |
+
file: ./coverage.xml
|
1795 |
+
|
1796 |
+
publish_to_pypi:
|
1797 |
+
docker:
|
1798 |
+
- image: cimg/python:3.8
|
1799 |
+
working_directory: ~/project
|
1800 |
+
|
1801 |
+
environment:
|
1802 |
+
TWINE_USERNAME: __token__
|
1803 |
+
|
1804 |
+
steps:
|
1805 |
+
- checkout
|
1806 |
+
|
1807 |
+
- run:
|
1808 |
+
name: Copy model_prices_and_context_window File to model_prices_and_context_window_backup
|
1809 |
+
command: |
|
1810 |
+
cp model_prices_and_context_window.json litellm/model_prices_and_context_window_backup.json
|
1811 |
+
|
1812 |
+
- run:
|
1813 |
+
name: Check if litellm dir, tests dir, or pyproject.toml was modified
|
1814 |
+
command: |
|
1815 |
+
if [ -n "$(git diff --name-only $CIRCLE_SHA1^..$CIRCLE_SHA1 | grep -E 'pyproject\.toml|litellm/|tests/')" ]; then
|
1816 |
+
echo "litellm, tests, or pyproject.toml updated"
|
1817 |
+
else
|
1818 |
+
echo "No changes to litellm, tests, or pyproject.toml. Skipping PyPI publish."
|
1819 |
+
circleci step halt
|
1820 |
+
fi
|
1821 |
+
|
1822 |
+
- run:
|
1823 |
+
name: Checkout code
|
1824 |
+
command: git checkout $CIRCLE_SHA1
|
1825 |
+
|
1826 |
+
# Check if setup.py is modified and publish to PyPI
|
1827 |
+
- run:
|
1828 |
+
name: PyPI publish
|
1829 |
+
command: |
|
1830 |
+
echo "Install TOML package."
|
1831 |
+
python -m pip install toml
|
1832 |
+
VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['version'])")
|
1833 |
+
PACKAGE_NAME=$(python -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['name'])")
|
1834 |
+
if ! pip show -v $PACKAGE_NAME | grep -q "Version: ${VERSION}"; then
|
1835 |
+
echo "pyproject.toml modified"
|
1836 |
+
echo -e "[pypi]\nusername = $PYPI_PUBLISH_USERNAME\npassword = $PYPI_PUBLISH_PASSWORD" > ~/.pypirc
|
1837 |
+
python -m pip install --upgrade pip
|
1838 |
+
pip install build
|
1839 |
+
pip install wheel
|
1840 |
+
pip install --upgrade twine setuptools
|
1841 |
+
rm -rf build dist
|
1842 |
+
|
1843 |
+
echo "Building package"
|
1844 |
+
python -m build
|
1845 |
+
|
1846 |
+
echo "Twine upload to dist"
|
1847 |
+
echo "Contents of dist directory:"
|
1848 |
+
ls dist/
|
1849 |
+
twine upload --verbose dist/*
|
1850 |
+
else
|
1851 |
+
echo "Version ${VERSION} of package is already published on PyPI. Skipping PyPI publish."
|
1852 |
+
circleci step halt
|
1853 |
+
fi
|
1854 |
+
- run:
|
1855 |
+
name: Trigger Github Action for new Docker Container + Trigger Stable Release Testing
|
1856 |
+
command: |
|
1857 |
+
echo "Install TOML package."
|
1858 |
+
python3 -m pip install toml
|
1859 |
+
VERSION=$(python3 -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['version'])")
|
1860 |
+
echo "LiteLLM Version ${VERSION}"
|
1861 |
+
curl -X POST \
|
1862 |
+
-H "Accept: application/vnd.github.v3+json" \
|
1863 |
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
1864 |
+
"https://api.github.com/repos/BerriAI/litellm/actions/workflows/ghcr_deploy.yml/dispatches" \
|
1865 |
+
-d "{\"ref\":\"main\", \"inputs\":{\"tag\":\"v${VERSION}\", \"commit_hash\":\"$CIRCLE_SHA1\"}}"
|
1866 |
+
echo "triggering stable release server for version ${VERSION} and commit ${CIRCLE_SHA1}"
|
1867 |
+
curl -X POST "https://proxyloadtester-production.up.railway.app/start/load/test?version=${VERSION}&commit_hash=${CIRCLE_SHA1}"
|
1868 |
+
|
1869 |
+
e2e_ui_testing:
|
1870 |
+
machine:
|
1871 |
+
image: ubuntu-2204:2023.10.1
|
1872 |
+
resource_class: xlarge
|
1873 |
+
working_directory: ~/project
|
1874 |
+
steps:
|
1875 |
+
- checkout
|
1876 |
+
- run:
|
1877 |
+
name: Install Docker CLI (In case it's not already installed)
|
1878 |
+
command: |
|
1879 |
+
sudo apt-get update
|
1880 |
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
1881 |
+
- run:
|
1882 |
+
name: Install Python 3.9
|
1883 |
+
command: |
|
1884 |
+
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh
|
1885 |
+
bash miniconda.sh -b -p $HOME/miniconda
|
1886 |
+
export PATH="$HOME/miniconda/bin:$PATH"
|
1887 |
+
conda init bash
|
1888 |
+
source ~/.bashrc
|
1889 |
+
conda create -n myenv python=3.9 -y
|
1890 |
+
conda activate myenv
|
1891 |
+
python --version
|
1892 |
+
- run:
|
1893 |
+
name: Install Dependencies
|
1894 |
+
command: |
|
1895 |
+
npm install -D @playwright/test
|
1896 |
+
npm install @google-cloud/vertexai
|
1897 |
+
pip install "pytest==7.3.1"
|
1898 |
+
pip install "pytest-retry==1.6.3"
|
1899 |
+
pip install "pytest-asyncio==0.21.1"
|
1900 |
+
pip install aiohttp
|
1901 |
+
pip install "openai==1.54.0 "
|
1902 |
+
python -m pip install --upgrade pip
|
1903 |
+
pip install "pydantic==2.7.1"
|
1904 |
+
pip install "pytest==7.3.1"
|
1905 |
+
pip install "pytest-mock==3.12.0"
|
1906 |
+
pip install "pytest-asyncio==0.21.1"
|
1907 |
+
pip install mypy
|
1908 |
+
pip install pyarrow
|
1909 |
+
pip install numpydoc
|
1910 |
+
pip install prisma
|
1911 |
+
pip install fastapi
|
1912 |
+
pip install jsonschema
|
1913 |
+
pip install "httpx==0.24.1"
|
1914 |
+
pip install "anyio==3.7.1"
|
1915 |
+
pip install "asyncio==3.4.3"
|
1916 |
+
- run:
|
1917 |
+
name: Install Playwright Browsers
|
1918 |
+
command: |
|
1919 |
+
npx playwright install
|
1920 |
+
- run:
|
1921 |
+
name: Build Docker image
|
1922 |
+
command: docker build -t my-app:latest -f ./docker/Dockerfile.database .
|
1923 |
+
- run:
|
1924 |
+
name: Run Docker container
|
1925 |
+
command: |
|
1926 |
+
docker run -d \
|
1927 |
+
-p 4000:4000 \
|
1928 |
+
-e DATABASE_URL=$SMALL_DATABASE_URL \
|
1929 |
+
-e LITELLM_MASTER_KEY="sk-1234" \
|
1930 |
+
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
1931 |
+
-e UI_USERNAME="admin" \
|
1932 |
+
-e UI_PASSWORD="gm" \
|
1933 |
+
-e LITELLM_LICENSE=$LITELLM_LICENSE \
|
1934 |
+
--name my-app \
|
1935 |
+
-v $(pwd)/litellm/proxy/example_config_yaml/simple_config.yaml:/app/config.yaml \
|
1936 |
+
my-app:latest \
|
1937 |
+
--config /app/config.yaml \
|
1938 |
+
--port 4000 \
|
1939 |
+
--detailed_debug
|
1940 |
+
- run:
|
1941 |
+
name: Install curl and dockerize
|
1942 |
+
command: |
|
1943 |
+
sudo apt-get update
|
1944 |
+
sudo apt-get install -y curl
|
1945 |
+
sudo wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz
|
1946 |
+
sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz
|
1947 |
+
sudo rm dockerize-linux-amd64-v0.6.1.tar.gz
|
1948 |
+
- run:
|
1949 |
+
name: Start outputting logs
|
1950 |
+
command: docker logs -f my-app
|
1951 |
+
background: true
|
1952 |
+
- run:
|
1953 |
+
name: Wait for app to be ready
|
1954 |
+
command: dockerize -wait http://localhost:4000 -timeout 5m
|
1955 |
+
- run:
|
1956 |
+
name: Run Playwright Tests
|
1957 |
+
command: |
|
1958 |
+
npx playwright test e2e_ui_tests/ --reporter=html --output=test-results
|
1959 |
+
no_output_timeout: 120m
|
1960 |
+
- store_test_results:
|
1961 |
+
path: test-results
|
1962 |
+
|
1963 |
+
test_nonroot_image:
|
1964 |
+
machine:
|
1965 |
+
image: ubuntu-2204:2023.10.1
|
1966 |
+
resource_class: xlarge
|
1967 |
+
working_directory: ~/project
|
1968 |
+
steps:
|
1969 |
+
- checkout
|
1970 |
+
- run:
|
1971 |
+
name: Build Docker image
|
1972 |
+
command: |
|
1973 |
+
docker build -t non_root_image:latest . -f ./docker/Dockerfile.non_root
|
1974 |
+
- run:
|
1975 |
+
name: Install Container Structure Test
|
1976 |
+
command: |
|
1977 |
+
curl -LO https://github.com/GoogleContainerTools/container-structure-test/releases/download/v1.19.3/container-structure-test-linux-amd64
|
1978 |
+
chmod +x container-structure-test-linux-amd64
|
1979 |
+
sudo mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test
|
1980 |
+
- run:
|
1981 |
+
name: Run Container Structure Test
|
1982 |
+
command: |
|
1983 |
+
container-structure-test test --image non_root_image:latest --config docker/tests/nonroot.yaml
|
1984 |
+
|
1985 |
+
test_bad_database_url:
|
1986 |
+
machine:
|
1987 |
+
image: ubuntu-2204:2023.10.1
|
1988 |
+
resource_class: xlarge
|
1989 |
+
working_directory: ~/project
|
1990 |
+
steps:
|
1991 |
+
- checkout
|
1992 |
+
- run:
|
1993 |
+
name: Build Docker image
|
1994 |
+
command: |
|
1995 |
+
docker build -t myapp . -f ./docker/Dockerfile.non_root
|
1996 |
+
- run:
|
1997 |
+
name: Run Docker container with bad DATABASE_URL
|
1998 |
+
command: |
|
1999 |
+
docker run --name my-app \
|
2000 |
+
-p 4000:4000 \
|
2001 |
+
-e DATABASE_URL="postgresql://wrong:wrong@wrong:5432/wrong" \
|
2002 |
+
myapp:latest \
|
2003 |
+
--port 4000 > docker_output.log 2>&1 || true
|
2004 |
+
- run:
|
2005 |
+
name: Display Docker logs
|
2006 |
+
command: cat docker_output.log
|
2007 |
+
- run:
|
2008 |
+
name: Check for expected error
|
2009 |
+
command: |
|
2010 |
+
if grep -q "Error: P1001: Can't reach database server at" docker_output.log && \
|
2011 |
+
grep -q "httpx.ConnectError: All connection attempts failed" docker_output.log && \
|
2012 |
+
grep -q "ERROR: Application startup failed. Exiting." docker_output.log; then
|
2013 |
+
echo "Expected error found. Test passed."
|
2014 |
+
else
|
2015 |
+
echo "Expected error not found. Test failed."
|
2016 |
+
cat docker_output.log
|
2017 |
+
exit 1
|
2018 |
+
fi
|
2019 |
+
|
2020 |
+
workflows:
|
2021 |
+
version: 2
|
2022 |
+
build_and_test:
|
2023 |
+
jobs:
|
2024 |
+
- local_testing:
|
2025 |
+
filters:
|
2026 |
+
branches:
|
2027 |
+
only:
|
2028 |
+
- main
|
2029 |
+
- /litellm_.*/
|
2030 |
+
- langfuse_logging_unit_tests:
|
2031 |
+
filters:
|
2032 |
+
branches:
|
2033 |
+
only:
|
2034 |
+
- main
|
2035 |
+
- /litellm_.*/
|
2036 |
+
- caching_unit_tests:
|
2037 |
+
filters:
|
2038 |
+
branches:
|
2039 |
+
only:
|
2040 |
+
- main
|
2041 |
+
- /litellm_.*/
|
2042 |
+
- litellm_proxy_unit_testing:
|
2043 |
+
filters:
|
2044 |
+
branches:
|
2045 |
+
only:
|
2046 |
+
- main
|
2047 |
+
- /litellm_.*/
|
2048 |
+
- litellm_assistants_api_testing:
|
2049 |
+
filters:
|
2050 |
+
branches:
|
2051 |
+
only:
|
2052 |
+
- main
|
2053 |
+
- /litellm_.*/
|
2054 |
+
- litellm_router_testing:
|
2055 |
+
filters:
|
2056 |
+
branches:
|
2057 |
+
only:
|
2058 |
+
- main
|
2059 |
+
- /litellm_.*/
|
2060 |
+
- check_code_and_doc_quality:
|
2061 |
+
filters:
|
2062 |
+
branches:
|
2063 |
+
only:
|
2064 |
+
- main
|
2065 |
+
- /litellm_.*/
|
2066 |
+
- auth_ui_unit_tests:
|
2067 |
+
filters:
|
2068 |
+
branches:
|
2069 |
+
only:
|
2070 |
+
- main
|
2071 |
+
- /litellm_.*/
|
2072 |
+
- e2e_ui_testing:
|
2073 |
+
filters:
|
2074 |
+
branches:
|
2075 |
+
only:
|
2076 |
+
- main
|
2077 |
+
- /litellm_.*/
|
2078 |
+
- build_and_test:
|
2079 |
+
filters:
|
2080 |
+
branches:
|
2081 |
+
only:
|
2082 |
+
- main
|
2083 |
+
- /litellm_.*/
|
2084 |
+
- e2e_openai_misc_endpoints:
|
2085 |
+
filters:
|
2086 |
+
branches:
|
2087 |
+
only:
|
2088 |
+
- main
|
2089 |
+
- /litellm_.*/
|
2090 |
+
- proxy_logging_guardrails_model_info_tests:
|
2091 |
+
filters:
|
2092 |
+
branches:
|
2093 |
+
only:
|
2094 |
+
- main
|
2095 |
+
- /litellm_.*/
|
2096 |
+
- proxy_store_model_in_db_tests:
|
2097 |
+
filters:
|
2098 |
+
branches:
|
2099 |
+
only:
|
2100 |
+
- main
|
2101 |
+
- /litellm_.*/
|
2102 |
+
- proxy_build_from_pip_tests:
|
2103 |
+
filters:
|
2104 |
+
branches:
|
2105 |
+
only:
|
2106 |
+
- main
|
2107 |
+
- /litellm_.*/
|
2108 |
+
- proxy_pass_through_endpoint_tests:
|
2109 |
+
filters:
|
2110 |
+
branches:
|
2111 |
+
only:
|
2112 |
+
- main
|
2113 |
+
- /litellm_.*/
|
2114 |
+
- llm_translation_testing:
|
2115 |
+
filters:
|
2116 |
+
branches:
|
2117 |
+
only:
|
2118 |
+
- main
|
2119 |
+
- /litellm_.*/
|
2120 |
+
- batches_testing:
|
2121 |
+
filters:
|
2122 |
+
branches:
|
2123 |
+
only:
|
2124 |
+
- main
|
2125 |
+
- /litellm_.*/
|
2126 |
+
- litellm_utils_testing:
|
2127 |
+
filters:
|
2128 |
+
branches:
|
2129 |
+
only:
|
2130 |
+
- main
|
2131 |
+
- /litellm_.*/
|
2132 |
+
- pass_through_unit_testing:
|
2133 |
+
filters:
|
2134 |
+
branches:
|
2135 |
+
only:
|
2136 |
+
- main
|
2137 |
+
- /litellm_.*/
|
2138 |
+
- image_gen_testing:
|
2139 |
+
filters:
|
2140 |
+
branches:
|
2141 |
+
only:
|
2142 |
+
- main
|
2143 |
+
- /litellm_.*/
|
2144 |
+
- logging_testing:
|
2145 |
+
filters:
|
2146 |
+
branches:
|
2147 |
+
only:
|
2148 |
+
- main
|
2149 |
+
- /litellm_.*/
|
2150 |
+
- upload-coverage:
|
2151 |
+
requires:
|
2152 |
+
- llm_translation_testing
|
2153 |
+
- batches_testing
|
2154 |
+
- litellm_utils_testing
|
2155 |
+
- pass_through_unit_testing
|
2156 |
+
- image_gen_testing
|
2157 |
+
- logging_testing
|
2158 |
+
- litellm_router_testing
|
2159 |
+
- caching_unit_tests
|
2160 |
+
- litellm_proxy_unit_testing
|
2161 |
+
- langfuse_logging_unit_tests
|
2162 |
+
- local_testing
|
2163 |
+
- litellm_assistants_api_testing
|
2164 |
+
- auth_ui_unit_tests
|
2165 |
+
- db_migration_disable_update_check:
|
2166 |
+
filters:
|
2167 |
+
branches:
|
2168 |
+
only:
|
2169 |
+
- main
|
2170 |
+
- /litellm_.*/
|
2171 |
+
- installing_litellm_on_python:
|
2172 |
+
filters:
|
2173 |
+
branches:
|
2174 |
+
only:
|
2175 |
+
- main
|
2176 |
+
- /litellm_.*/
|
2177 |
+
- installing_litellm_on_python_3_13:
|
2178 |
+
filters:
|
2179 |
+
branches:
|
2180 |
+
only:
|
2181 |
+
- main
|
2182 |
+
- /litellm_.*/
|
2183 |
+
- helm_chart_testing:
|
2184 |
+
filters:
|
2185 |
+
branches:
|
2186 |
+
only:
|
2187 |
+
- main
|
2188 |
+
- /litellm_.*/
|
2189 |
+
- load_testing:
|
2190 |
+
filters:
|
2191 |
+
branches:
|
2192 |
+
only:
|
2193 |
+
- main
|
2194 |
+
- /litellm_.*/
|
2195 |
+
- test_bad_database_url:
|
2196 |
+
filters:
|
2197 |
+
branches:
|
2198 |
+
only:
|
2199 |
+
- main
|
2200 |
+
- /litellm_.*/
|
2201 |
+
- publish_to_pypi:
|
2202 |
+
requires:
|
2203 |
+
- local_testing
|
2204 |
+
- build_and_test
|
2205 |
+
- e2e_openai_misc_endpoints
|
2206 |
+
- load_testing
|
2207 |
+
- test_bad_database_url
|
2208 |
+
- llm_translation_testing
|
2209 |
+
- batches_testing
|
2210 |
+
- litellm_utils_testing
|
2211 |
+
- pass_through_unit_testing
|
2212 |
+
- image_gen_testing
|
2213 |
+
- logging_testing
|
2214 |
+
- litellm_router_testing
|
2215 |
+
- caching_unit_tests
|
2216 |
+
- langfuse_logging_unit_tests
|
2217 |
+
- litellm_assistants_api_testing
|
2218 |
+
- auth_ui_unit_tests
|
2219 |
+
- db_migration_disable_update_check
|
2220 |
+
- e2e_ui_testing
|
2221 |
+
- litellm_proxy_unit_testing
|
2222 |
+
- installing_litellm_on_python
|
2223 |
+
- installing_litellm_on_python_3_13
|
2224 |
+
- proxy_logging_guardrails_model_info_tests
|
2225 |
+
- proxy_store_model_in_db_tests
|
2226 |
+
- proxy_build_from_pip_tests
|
2227 |
+
- proxy_pass_through_endpoint_tests
|
2228 |
+
- check_code_and_doc_quality
|
2229 |
+
filters:
|
2230 |
+
branches:
|
2231 |
+
only:
|
2232 |
+
- main
|
.circleci/requirements.txt
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# used by CI/CD testing
|
2 |
+
openai==1.54.0
|
3 |
+
python-dotenv
|
4 |
+
tiktoken
|
5 |
+
importlib_metadata
|
6 |
+
cohere
|
7 |
+
redis
|
8 |
+
anthropic
|
9 |
+
orjson==3.9.15
|
10 |
+
pydantic==2.7.1
|
11 |
+
google-cloud-aiplatform==1.43.0
|
12 |
+
fastapi-sso==0.10.0
|
13 |
+
uvloop==0.21.0
|
.devcontainer/devcontainer.json
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "Python 3.11",
|
3 |
+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
4 |
+
"image": "mcr.microsoft.com/devcontainers/python:3.11-bookworm",
|
5 |
+
// https://github.com/devcontainers/images/tree/main/src/python
|
6 |
+
// https://mcr.microsoft.com/en-us/product/devcontainers/python/tags
|
7 |
+
|
8 |
+
// "build": {
|
9 |
+
// "dockerfile": "Dockerfile",
|
10 |
+
// "context": ".."
|
11 |
+
// },
|
12 |
+
|
13 |
+
// Features to add to the dev container. More info: https://containers.dev/features.
|
14 |
+
// "features": {},
|
15 |
+
|
16 |
+
// Configure tool-specific properties.
|
17 |
+
"customizations": {
|
18 |
+
// Configure properties specific to VS Code.
|
19 |
+
"vscode": {
|
20 |
+
"settings": {},
|
21 |
+
"extensions": [
|
22 |
+
"ms-python.python",
|
23 |
+
"ms-python.vscode-pylance",
|
24 |
+
"GitHub.copilot",
|
25 |
+
"GitHub.copilot-chat",
|
26 |
+
"ms-python.autopep8"
|
27 |
+
]
|
28 |
+
}
|
29 |
+
},
|
30 |
+
|
31 |
+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
32 |
+
"forwardPorts": [4000],
|
33 |
+
|
34 |
+
"containerEnv": {
|
35 |
+
"LITELLM_LOG": "DEBUG"
|
36 |
+
},
|
37 |
+
|
38 |
+
// Use 'portsAttributes' to set default properties for specific forwarded ports.
|
39 |
+
// More info: https://containers.dev/implementors/json_reference/#port-attributes
|
40 |
+
"portsAttributes": {
|
41 |
+
"4000": {
|
42 |
+
"label": "LiteLLM Server",
|
43 |
+
"onAutoForward": "notify"
|
44 |
+
}
|
45 |
+
},
|
46 |
+
|
47 |
+
// More info: https://aka.ms/dev-containers-non-root.
|
48 |
+
// "remoteUser": "litellm",
|
49 |
+
|
50 |
+
// Use 'postCreateCommand' to run commands after the container is created.
|
51 |
+
"postCreateCommand": "pipx install poetry && poetry install -E extra_proxy -E proxy"
|
52 |
+
}
|
.dockerignore
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
docs
|
2 |
+
cookbook
|
3 |
+
.circleci
|
4 |
+
.github
|
5 |
+
tests
|
6 |
+
.git
|
7 |
+
.github
|
8 |
+
.circleci
|
9 |
+
.devcontainer
|
10 |
+
*.tgz
|
11 |
+
log.txt
|
12 |
+
docker/Dockerfile.*
|
.env.example
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# OpenAI
|
2 |
+
OPENAI_API_KEY = ""
|
3 |
+
OPENAI_API_BASE = ""
|
4 |
+
# Cohere
|
5 |
+
COHERE_API_KEY = ""
|
6 |
+
# OpenRouter
|
7 |
+
OR_SITE_URL = ""
|
8 |
+
OR_APP_NAME = "LiteLLM Example app"
|
9 |
+
OR_API_KEY = ""
|
10 |
+
# Azure API base URL
|
11 |
+
AZURE_API_BASE = ""
|
12 |
+
# Azure API version
|
13 |
+
AZURE_API_VERSION = ""
|
14 |
+
# Azure API key
|
15 |
+
AZURE_API_KEY = ""
|
16 |
+
# Replicate
|
17 |
+
REPLICATE_API_KEY = ""
|
18 |
+
REPLICATE_API_TOKEN = ""
|
19 |
+
# Anthropic
|
20 |
+
ANTHROPIC_API_KEY = ""
|
21 |
+
# Infisical
|
22 |
+
INFISICAL_TOKEN = ""
|
.flake8
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[flake8]
|
2 |
+
ignore =
|
3 |
+
# The following ignores can be removed when formatting using black
|
4 |
+
W191,W291,W292,W293,W391,W504
|
5 |
+
E101,E111,E114,E116,E117,E121,E122,E123,E124,E125,E126,E127,E128,E129,E131,
|
6 |
+
E201,E202,E221,E222,E225,E226,E231,E241,E251,E252,E261,E265,E271,E272,E275,
|
7 |
+
E301,E302,E303,E305,E306,
|
8 |
+
# line break before binary operator
|
9 |
+
W503,
|
10 |
+
# inline comment should start with '# '
|
11 |
+
E262,
|
12 |
+
# too many leading '#' for block comment
|
13 |
+
E266,
|
14 |
+
# multiple imports on one line
|
15 |
+
E401,
|
16 |
+
# module level import not at top of file
|
17 |
+
E402,
|
18 |
+
# Line too long (82 > 79 characters)
|
19 |
+
E501,
|
20 |
+
# comparison to None should be 'if cond is None:'
|
21 |
+
E711,
|
22 |
+
# comparison to True should be 'if cond is True:' or 'if cond:'
|
23 |
+
E712,
|
24 |
+
# do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
|
25 |
+
E721,
|
26 |
+
# do not use bare 'except'
|
27 |
+
E722,
|
28 |
+
# x is imported but unused
|
29 |
+
F401,
|
30 |
+
# 'from . import *' used; unable to detect undefined names
|
31 |
+
F403,
|
32 |
+
# x may be undefined, or defined from star imports:
|
33 |
+
F405,
|
34 |
+
# f-string is missing placeholders
|
35 |
+
F541,
|
36 |
+
# dictionary key '' repeated with different values
|
37 |
+
F601,
|
38 |
+
# redefinition of unused x from line 123
|
39 |
+
F811,
|
40 |
+
# undefined name x
|
41 |
+
F821,
|
42 |
+
# local variable x is assigned to but never used
|
43 |
+
F841,
|
44 |
+
|
45 |
+
# https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#flake8
|
46 |
+
extend-ignore = E203
|
.git-blame-ignore-revs
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Add the commit hash of any commit you want to ignore in `git blame` here.
|
2 |
+
# One commit hash per line.
|
3 |
+
#
|
4 |
+
# The GitHub Blame UI will use this file automatically!
|
5 |
+
#
|
6 |
+
# Run this command to always ignore formatting commits in `git blame`
|
7 |
+
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
8 |
+
|
9 |
+
# Update pydantic code to fix warnings (GH-3600)
|
10 |
+
876840e9957bc7e9f7d6a2b58c4d7c53dad16481
|
.gitattributes
CHANGED
@@ -1,35 +1,5 @@
|
|
1 |
-
*.
|
2 |
-
*.
|
3 |
-
*.
|
4 |
-
|
5 |
-
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
*.ipynb linguist-vendored
|
2 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.gif filter=lfs diff=lfs merge=lfs -text
|
4 |
+
docs/my-website/img/*.png filter=lfs diff=lfs merge=lfs -text
|
5 |
+
docs/my-website/img/*.gif filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.github/FUNDING.yml
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# These are supported funding model platforms
|
2 |
+
|
3 |
+
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
4 |
+
patreon: # Replace with a single Patreon username
|
5 |
+
open_collective: # Replace with a single Open Collective username
|
6 |
+
ko_fi: # Replace with a single Ko-fi username
|
7 |
+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
8 |
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
9 |
+
liberapay: # Replace with a single Liberapay username
|
10 |
+
issuehunt: # Replace with a single IssueHunt username
|
11 |
+
otechie: # Replace with a single Otechie username
|
12 |
+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
13 |
+
custom: https://buy.stripe.com/9AQ03Kd3P91o0Q8bIS
|
.github/ISSUE_TEMPLATE/bug_report.yml
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Bug Report
|
2 |
+
description: File a bug report
|
3 |
+
title: "[Bug]: "
|
4 |
+
labels: ["bug"]
|
5 |
+
body:
|
6 |
+
- type: markdown
|
7 |
+
attributes:
|
8 |
+
value: |
|
9 |
+
Thanks for taking the time to fill out this bug report!
|
10 |
+
- type: textarea
|
11 |
+
id: what-happened
|
12 |
+
attributes:
|
13 |
+
label: What happened?
|
14 |
+
description: Also tell us, what did you expect to happen?
|
15 |
+
placeholder: Tell us what you see!
|
16 |
+
value: "A bug happened!"
|
17 |
+
validations:
|
18 |
+
required: true
|
19 |
+
- type: textarea
|
20 |
+
id: logs
|
21 |
+
attributes:
|
22 |
+
label: Relevant log output
|
23 |
+
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
24 |
+
render: shell
|
25 |
+
- type: dropdown
|
26 |
+
id: ml-ops-team
|
27 |
+
attributes:
|
28 |
+
label: Are you a ML Ops Team?
|
29 |
+
description: This helps us prioritize your requests correctly
|
30 |
+
options:
|
31 |
+
- "No"
|
32 |
+
- "Yes"
|
33 |
+
validations:
|
34 |
+
required: true
|
35 |
+
- type: input
|
36 |
+
id: version
|
37 |
+
attributes:
|
38 |
+
label: What LiteLLM version are you on ?
|
39 |
+
placeholder: v1.53.1
|
40 |
+
validations:
|
41 |
+
required: true
|
42 |
+
- type: input
|
43 |
+
id: contact
|
44 |
+
attributes:
|
45 |
+
label: Twitter / LinkedIn details
|
46 |
+
description: We announce new features on Twitter + LinkedIn. If this issue leads to an announcement, and you'd like a mention, we'll gladly shout you out!
|
47 |
+
placeholder: ex. @krrish_dh / https://www.linkedin.com/in/krish-d/
|
48 |
+
validations:
|
49 |
+
required: false
|
.github/ISSUE_TEMPLATE/config.yml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
blank_issues_enabled: true
|
2 |
+
contact_links:
|
3 |
+
- name: Schedule Demo
|
4 |
+
url: https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat
|
5 |
+
about: Speak directly with Krrish and Ishaan, the founders, to discuss issues, share feedback, or explore improvements for LiteLLM
|
6 |
+
- name: Discord
|
7 |
+
url: https://discord.com/invite/wuPM9dRgDw
|
8 |
+
about: Join 250+ LiteLLM community members!
|
.github/ISSUE_TEMPLATE/feature_request.yml
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: 🚀 Feature Request
|
2 |
+
description: Submit a proposal/request for a new LiteLLM feature.
|
3 |
+
title: "[Feature]: "
|
4 |
+
labels: ["enhancement"]
|
5 |
+
body:
|
6 |
+
- type: markdown
|
7 |
+
attributes:
|
8 |
+
value: |
|
9 |
+
Thanks for making LiteLLM better!
|
10 |
+
- type: textarea
|
11 |
+
id: the-feature
|
12 |
+
attributes:
|
13 |
+
label: The Feature
|
14 |
+
description: A clear and concise description of the feature proposal
|
15 |
+
placeholder: Tell us what you want!
|
16 |
+
validations:
|
17 |
+
required: true
|
18 |
+
- type: textarea
|
19 |
+
id: motivation
|
20 |
+
attributes:
|
21 |
+
label: Motivation, pitch
|
22 |
+
description: Please outline the motivation for the proposal. Is your feature request related to a specific problem? e.g., "I'm working on X and would like Y to be possible". If this is related to another GitHub issue, please link here too.
|
23 |
+
validations:
|
24 |
+
required: true
|
25 |
+
- type: dropdown
|
26 |
+
id: ml-ops-team
|
27 |
+
attributes:
|
28 |
+
label: Are you a ML Ops Team?
|
29 |
+
description: This helps us prioritize your requests correctly
|
30 |
+
options:
|
31 |
+
- "No"
|
32 |
+
- "Yes"
|
33 |
+
validations:
|
34 |
+
required: true
|
35 |
+
- type: input
|
36 |
+
id: contact
|
37 |
+
attributes:
|
38 |
+
label: Twitter / LinkedIn details
|
39 |
+
description: We announce new features on Twitter + LinkedIn. When this is announced, and you'd like a mention, we'll gladly shout you out!
|
40 |
+
placeholder: ex. @krrish_dh / https://www.linkedin.com/in/krish-d/
|
41 |
+
validations:
|
42 |
+
required: false
|
.github/actions/helm-oci-chart-releaser/action.yml
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Helm OCI Chart Releaser
|
2 |
+
description: Push Helm charts to OCI-based (Docker) registries
|
3 |
+
author: sergeyshaykhullin
|
4 |
+
branding:
|
5 |
+
color: yellow
|
6 |
+
icon: upload-cloud
|
7 |
+
inputs:
|
8 |
+
name:
|
9 |
+
required: true
|
10 |
+
description: Chart name
|
11 |
+
repository:
|
12 |
+
required: true
|
13 |
+
description: Chart repository name
|
14 |
+
tag:
|
15 |
+
required: true
|
16 |
+
description: Chart version
|
17 |
+
app_version:
|
18 |
+
required: true
|
19 |
+
description: App version
|
20 |
+
path:
|
21 |
+
required: false
|
22 |
+
description: Chart path (Default 'charts/{name}')
|
23 |
+
registry:
|
24 |
+
required: true
|
25 |
+
description: OCI registry
|
26 |
+
registry_username:
|
27 |
+
required: true
|
28 |
+
description: OCI registry username
|
29 |
+
registry_password:
|
30 |
+
required: true
|
31 |
+
description: OCI registry password
|
32 |
+
update_dependencies:
|
33 |
+
required: false
|
34 |
+
default: 'false'
|
35 |
+
description: Update chart dependencies before packaging (Default 'false')
|
36 |
+
outputs:
|
37 |
+
image:
|
38 |
+
value: ${{ steps.output.outputs.image }}
|
39 |
+
description: Chart image (Default '{registry}/{repository}/{image}:{tag}')
|
40 |
+
runs:
|
41 |
+
using: composite
|
42 |
+
steps:
|
43 |
+
- name: Helm | Login
|
44 |
+
shell: bash
|
45 |
+
run: echo ${{ inputs.registry_password }} | helm registry login -u ${{ inputs.registry_username }} --password-stdin ${{ inputs.registry }}
|
46 |
+
env:
|
47 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
48 |
+
|
49 |
+
- name: Helm | Dependency
|
50 |
+
if: inputs.update_dependencies == 'true'
|
51 |
+
shell: bash
|
52 |
+
run: helm dependency update ${{ inputs.path == null && format('{0}/{1}', 'charts', inputs.name) || inputs.path }}
|
53 |
+
env:
|
54 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
55 |
+
|
56 |
+
- name: Helm | Package
|
57 |
+
shell: bash
|
58 |
+
run: helm package ${{ inputs.path == null && format('{0}/{1}', 'charts', inputs.name) || inputs.path }} --version ${{ inputs.tag }} --app-version ${{ inputs.app_version }}
|
59 |
+
env:
|
60 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
61 |
+
|
62 |
+
- name: Helm | Push
|
63 |
+
shell: bash
|
64 |
+
run: helm push ${{ inputs.name }}-${{ inputs.tag }}.tgz oci://${{ inputs.registry }}/${{ inputs.repository }}
|
65 |
+
env:
|
66 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
67 |
+
|
68 |
+
- name: Helm | Logout
|
69 |
+
shell: bash
|
70 |
+
run: helm registry logout ${{ inputs.registry }}
|
71 |
+
env:
|
72 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
73 |
+
|
74 |
+
- name: Helm | Output
|
75 |
+
id: output
|
76 |
+
shell: bash
|
77 |
+
run: echo "image=${{ inputs.registry }}/${{ inputs.repository }}/${{ inputs.name }}:${{ inputs.tag }}" >> $GITHUB_OUTPUT
|
.github/dependabot.yaml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
version: 2
|
2 |
+
updates:
|
3 |
+
- package-ecosystem: "github-actions"
|
4 |
+
directory: "/"
|
5 |
+
schedule:
|
6 |
+
interval: "daily"
|
7 |
+
groups:
|
8 |
+
github-actions:
|
9 |
+
patterns:
|
10 |
+
- "*"
|
.github/pull_request_template.md
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Title
|
2 |
+
|
3 |
+
<!-- e.g. "Implement user authentication feature" -->
|
4 |
+
|
5 |
+
## Relevant issues
|
6 |
+
|
7 |
+
<!-- e.g. "Fixes #000" -->
|
8 |
+
|
9 |
+
## Type
|
10 |
+
|
11 |
+
<!-- Select the type of Pull Request -->
|
12 |
+
<!-- Keep only the necessary ones -->
|
13 |
+
|
14 |
+
🆕 New Feature
|
15 |
+
🐛 Bug Fix
|
16 |
+
🧹 Refactoring
|
17 |
+
📖 Documentation
|
18 |
+
🚄 Infrastructure
|
19 |
+
✅ Test
|
20 |
+
|
21 |
+
## Changes
|
22 |
+
|
23 |
+
<!-- List of changes -->
|
24 |
+
|
25 |
+
## [REQUIRED] Testing - Attach a screenshot of any new tests passing locally
|
26 |
+
If UI changes, send a screenshot/GIF of working UI fixes
|
27 |
+
|
28 |
+
<!-- Test procedure -->
|
29 |
+
|
.github/template.yaml
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
AWSTemplateFormatVersion: '2010-09-09'
|
2 |
+
Transform: AWS::Serverless-2016-10-31
|
3 |
+
Description: >
|
4 |
+
llmlite-service
|
5 |
+
|
6 |
+
SAM Template for llmlite-service
|
7 |
+
|
8 |
+
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
|
9 |
+
Globals:
|
10 |
+
Function:
|
11 |
+
Timeout: 600
|
12 |
+
MemorySize: 128
|
13 |
+
Environment:
|
14 |
+
Variables:
|
15 |
+
WORKER_CONFIG: !Ref WorkerConfigParameter
|
16 |
+
|
17 |
+
Parameters:
|
18 |
+
AliasParameter:
|
19 |
+
Type: String
|
20 |
+
Default: live
|
21 |
+
WorkerConfigParameter:
|
22 |
+
Type: String
|
23 |
+
Description: Sample environment variable
|
24 |
+
Default: '{"model": null, "alias": null, "api_base": null, "api_version": "2023-07-01-preview", "debug": false, "temperature": null, "max_tokens": null, "request_timeout": 600, "max_budget": null, "telemetry": true, "drop_params": false, "add_function_to_prompt": false, "headers": null, "save": false, "config": null, "use_queue": false}'
|
25 |
+
|
26 |
+
Resources:
|
27 |
+
MyUrlFunctionPermissions:
|
28 |
+
Type: AWS::Lambda::Permission
|
29 |
+
Properties:
|
30 |
+
FunctionName: !Ref URL
|
31 |
+
Action: lambda:InvokeFunctionUrl
|
32 |
+
Principal: "*"
|
33 |
+
FunctionUrlAuthType: NONE
|
34 |
+
|
35 |
+
Function:
|
36 |
+
Type: AWS::Serverless::Function
|
37 |
+
Properties:
|
38 |
+
FunctionName: !Sub "${AWS::StackName}-function"
|
39 |
+
CodeUri: "./litellm"
|
40 |
+
Handler: proxy/lambda.handler
|
41 |
+
Runtime: python3.11
|
42 |
+
AutoPublishAlias: !Ref AliasParameter
|
43 |
+
Architectures:
|
44 |
+
- x86_64
|
45 |
+
DeploymentPreference:
|
46 |
+
Type: AllAtOnce
|
47 |
+
Alarms:
|
48 |
+
- !Ref NewVersionErrorMetricGreaterThanZeroAlarm
|
49 |
+
|
50 |
+
NewVersionErrorMetricGreaterThanZeroAlarm:
|
51 |
+
Type: "AWS::CloudWatch::Alarm"
|
52 |
+
Properties:
|
53 |
+
AlarmDescription: Lambda Function Error > 0
|
54 |
+
ComparisonOperator: GreaterThanThreshold
|
55 |
+
Dimensions:
|
56 |
+
- Name: Resource
|
57 |
+
Value: !Sub "${Function}:live"
|
58 |
+
- Name: FunctionName
|
59 |
+
Value: !Ref Function
|
60 |
+
- Name: ExecutedVersion
|
61 |
+
Value: !GetAtt Function.Version.Version
|
62 |
+
EvaluationPeriods: 1
|
63 |
+
Unit: Count
|
64 |
+
MetricName: Errors
|
65 |
+
Namespace: AWS/Lambda
|
66 |
+
Period: 60
|
67 |
+
Statistic: Sum
|
68 |
+
Threshold: 0
|
69 |
+
|
70 |
+
URL:
|
71 |
+
Type: AWS::Lambda::Url
|
72 |
+
DependsOn: FunctionAliaslive
|
73 |
+
Properties:
|
74 |
+
AuthType: NONE
|
75 |
+
Qualifier: live
|
76 |
+
TargetFunctionArn: !GetAtt Function.Arn
|
77 |
+
|
78 |
+
Outputs:
|
79 |
+
FunctionARN:
|
80 |
+
Description: "Lambda Function ARN"
|
81 |
+
Value: !GetAtt Function.Arn
|
82 |
+
|
83 |
+
FunctionUrl:
|
84 |
+
Description: "Lambda Function URL Endpoint"
|
85 |
+
Value:
|
86 |
+
Fn::GetAtt: URL.FunctionUrl
|
87 |
+
|
88 |
+
FunctionVersion:
|
89 |
+
Description: "Lambda Function Version"
|
90 |
+
Value: !GetAtt Function.Version.Version
|
91 |
+
|
92 |
+
FunctionNewAlarmARN:
|
93 |
+
Description: "Lambda Function New Alarm ARN"
|
94 |
+
Value: !GetAtt NewVersionErrorMetricGreaterThanZeroAlarm.Arn
|
.github/workflows/auto_update_price_and_context_window.yml
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Updates model_prices_and_context_window.json and Create Pull Request
|
2 |
+
|
3 |
+
on:
|
4 |
+
schedule:
|
5 |
+
- cron: "0 0 * * 0" # Run every Sundays at midnight
|
6 |
+
#- cron: "0 0 * * *" # Run daily at midnight
|
7 |
+
|
8 |
+
jobs:
|
9 |
+
auto_update_price_and_context_window:
|
10 |
+
runs-on: ubuntu-latest
|
11 |
+
steps:
|
12 |
+
- uses: actions/checkout@v3
|
13 |
+
- name: Install Dependencies
|
14 |
+
run: |
|
15 |
+
pip install aiohttp
|
16 |
+
- name: Update JSON Data
|
17 |
+
run: |
|
18 |
+
python ".github/workflows/auto_update_price_and_context_window_file.py"
|
19 |
+
- name: Create Pull Request
|
20 |
+
run: |
|
21 |
+
git add model_prices_and_context_window.json
|
22 |
+
git commit -m "Update model_prices_and_context_window.json file: $(date +'%Y-%m-%d')"
|
23 |
+
gh pr create --title "Update model_prices_and_context_window.json file" \
|
24 |
+
--body "Automated update for model_prices_and_context_window.json" \
|
25 |
+
--head auto-update-price-and-context-window-$(date +'%Y-%m-%d') \
|
26 |
+
--base main
|
27 |
+
env:
|
28 |
+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
.github/workflows/auto_update_price_and_context_window_file.py
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import aiohttp
|
3 |
+
import json
|
4 |
+
|
5 |
+
# Asynchronously fetch data from a given URL
|
6 |
+
async def fetch_data(url):
|
7 |
+
try:
|
8 |
+
# Create an asynchronous session
|
9 |
+
async with aiohttp.ClientSession() as session:
|
10 |
+
# Send a GET request to the URL
|
11 |
+
async with session.get(url) as resp:
|
12 |
+
# Raise an error if the response status is not OK
|
13 |
+
resp.raise_for_status()
|
14 |
+
# Parse the response JSON
|
15 |
+
resp_json = await resp.json()
|
16 |
+
print("Fetch the data from URL.")
|
17 |
+
# Return the 'data' field from the JSON response
|
18 |
+
return resp_json['data']
|
19 |
+
except Exception as e:
|
20 |
+
# Print an error message if fetching data fails
|
21 |
+
print("Error fetching data from URL:", e)
|
22 |
+
return None
|
23 |
+
|
24 |
+
# Synchronize local data with remote data
|
25 |
+
def sync_local_data_with_remote(local_data, remote_data):
|
26 |
+
# Update existing keys in local_data with values from remote_data
|
27 |
+
for key in (set(local_data) & set(remote_data)):
|
28 |
+
local_data[key].update(remote_data[key])
|
29 |
+
|
30 |
+
# Add new keys from remote_data to local_data
|
31 |
+
for key in (set(remote_data) - set(local_data)):
|
32 |
+
local_data[key] = remote_data[key]
|
33 |
+
|
34 |
+
# Write data to the json file
|
35 |
+
def write_to_file(file_path, data):
|
36 |
+
try:
|
37 |
+
# Open the file in write mode
|
38 |
+
with open(file_path, "w") as file:
|
39 |
+
# Dump the data as JSON into the file
|
40 |
+
json.dump(data, file, indent=4)
|
41 |
+
print("Values updated successfully.")
|
42 |
+
except Exception as e:
|
43 |
+
# Print an error message if writing to file fails
|
44 |
+
print("Error updating JSON file:", e)
|
45 |
+
|
46 |
+
# Update the existing models and add the missing models
|
47 |
+
def transform_remote_data(data):
|
48 |
+
transformed = {}
|
49 |
+
for row in data:
|
50 |
+
# Add the fields 'max_tokens' and 'input_cost_per_token'
|
51 |
+
obj = {
|
52 |
+
"max_tokens": row["context_length"],
|
53 |
+
"input_cost_per_token": float(row["pricing"]["prompt"]),
|
54 |
+
}
|
55 |
+
|
56 |
+
# Add 'max_output_tokens' as a field if it is not None
|
57 |
+
if "top_provider" in row and "max_completion_tokens" in row["top_provider"] and row["top_provider"]["max_completion_tokens"] is not None:
|
58 |
+
obj['max_output_tokens'] = int(row["top_provider"]["max_completion_tokens"])
|
59 |
+
|
60 |
+
# Add the field 'output_cost_per_token'
|
61 |
+
obj.update({
|
62 |
+
"output_cost_per_token": float(row["pricing"]["completion"]),
|
63 |
+
})
|
64 |
+
|
65 |
+
# Add field 'input_cost_per_image' if it exists and is non-zero
|
66 |
+
if "pricing" in row and "image" in row["pricing"] and float(row["pricing"]["image"]) != 0.0:
|
67 |
+
obj['input_cost_per_image'] = float(row["pricing"]["image"])
|
68 |
+
|
69 |
+
# Add the fields 'litellm_provider' and 'mode'
|
70 |
+
obj.update({
|
71 |
+
"litellm_provider": "openrouter",
|
72 |
+
"mode": "chat"
|
73 |
+
})
|
74 |
+
|
75 |
+
# Add the 'supports_vision' field if the modality is 'multimodal'
|
76 |
+
if row.get('architecture', {}).get('modality') == 'multimodal':
|
77 |
+
obj['supports_vision'] = True
|
78 |
+
|
79 |
+
# Use a composite key to store the transformed object
|
80 |
+
transformed[f'openrouter/{row["id"]}'] = obj
|
81 |
+
|
82 |
+
return transformed
|
83 |
+
|
84 |
+
|
85 |
+
# Load local data from a specified file
|
86 |
+
def load_local_data(file_path):
|
87 |
+
try:
|
88 |
+
# Open the file in read mode
|
89 |
+
with open(file_path, "r") as file:
|
90 |
+
# Load and return the JSON data
|
91 |
+
return json.load(file)
|
92 |
+
except FileNotFoundError:
|
93 |
+
# Print an error message if the file is not found
|
94 |
+
print("File not found:", file_path)
|
95 |
+
return None
|
96 |
+
except json.JSONDecodeError as e:
|
97 |
+
# Print an error message if JSON decoding fails
|
98 |
+
print("Error decoding JSON:", e)
|
99 |
+
return None
|
100 |
+
|
101 |
+
def main():
|
102 |
+
local_file_path = "model_prices_and_context_window.json" # Path to the local data file
|
103 |
+
url = "https://openrouter.ai/api/v1/models" # URL to fetch remote data
|
104 |
+
|
105 |
+
# Load local data from file
|
106 |
+
local_data = load_local_data(local_file_path)
|
107 |
+
# Fetch remote data asynchronously
|
108 |
+
remote_data = asyncio.run(fetch_data(url))
|
109 |
+
# Transform the fetched remote data
|
110 |
+
remote_data = transform_remote_data(remote_data)
|
111 |
+
|
112 |
+
# If both local and remote data are available, synchronize and save
|
113 |
+
if local_data and remote_data:
|
114 |
+
sync_local_data_with_remote(local_data, remote_data)
|
115 |
+
write_to_file(local_file_path, local_data)
|
116 |
+
else:
|
117 |
+
print("Failed to fetch model data from either local file or URL.")
|
118 |
+
|
119 |
+
# Entry point of the script
|
120 |
+
if __name__ == "__main__":
|
121 |
+
main()
|
.github/workflows/ghcr_deploy.yml
ADDED
@@ -0,0 +1,374 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# this workflow is triggered by an API call when there is a new PyPI release of LiteLLM
|
2 |
+
name: Build, Publish LiteLLM Docker Image. New Release
|
3 |
+
on:
|
4 |
+
workflow_dispatch:
|
5 |
+
inputs:
|
6 |
+
tag:
|
7 |
+
description: "The tag version you want to build"
|
8 |
+
release_type:
|
9 |
+
description: "The release type you want to build. Can be 'latest', 'stable', 'dev'"
|
10 |
+
type: string
|
11 |
+
default: "latest"
|
12 |
+
commit_hash:
|
13 |
+
description: "Commit hash"
|
14 |
+
required: true
|
15 |
+
|
16 |
+
# Defines two custom environment variables for the workflow. Used for the Container registry domain, and a name for the Docker image that this workflow builds.
|
17 |
+
env:
|
18 |
+
REGISTRY: ghcr.io
|
19 |
+
IMAGE_NAME: ${{ github.repository }}
|
20 |
+
CHART_NAME: litellm-helm
|
21 |
+
|
22 |
+
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
|
23 |
+
jobs:
|
24 |
+
# print commit hash, tag, and release type
|
25 |
+
print:
|
26 |
+
runs-on: ubuntu-latest
|
27 |
+
steps:
|
28 |
+
- run: |
|
29 |
+
echo "Commit hash: ${{ github.event.inputs.commit_hash }}"
|
30 |
+
echo "Tag: ${{ github.event.inputs.tag }}"
|
31 |
+
echo "Release type: ${{ github.event.inputs.release_type }}"
|
32 |
+
docker-hub-deploy:
|
33 |
+
if: github.repository == 'BerriAI/litellm'
|
34 |
+
runs-on: ubuntu-latest
|
35 |
+
steps:
|
36 |
+
-
|
37 |
+
name: Checkout
|
38 |
+
uses: actions/checkout@v4
|
39 |
+
with:
|
40 |
+
ref: ${{ github.event.inputs.commit_hash }}
|
41 |
+
-
|
42 |
+
name: Set up QEMU
|
43 |
+
uses: docker/setup-qemu-action@v3
|
44 |
+
-
|
45 |
+
name: Set up Docker Buildx
|
46 |
+
uses: docker/setup-buildx-action@v3
|
47 |
+
-
|
48 |
+
name: Login to Docker Hub
|
49 |
+
uses: docker/login-action@v3
|
50 |
+
with:
|
51 |
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
52 |
+
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
53 |
+
-
|
54 |
+
name: Build and push
|
55 |
+
uses: docker/build-push-action@v5
|
56 |
+
with:
|
57 |
+
context: .
|
58 |
+
push: true
|
59 |
+
tags: litellm/litellm:${{ github.event.inputs.tag || 'latest' }}
|
60 |
+
-
|
61 |
+
name: Build and push litellm-database image
|
62 |
+
uses: docker/build-push-action@v5
|
63 |
+
with:
|
64 |
+
context: .
|
65 |
+
push: true
|
66 |
+
file: ./docker/Dockerfile.database
|
67 |
+
tags: litellm/litellm-database:${{ github.event.inputs.tag || 'latest' }}
|
68 |
+
-
|
69 |
+
name: Build and push litellm-spend-logs image
|
70 |
+
uses: docker/build-push-action@v5
|
71 |
+
with:
|
72 |
+
context: .
|
73 |
+
push: true
|
74 |
+
file: ./litellm-js/spend-logs/Dockerfile
|
75 |
+
tags: litellm/litellm-spend_logs:${{ github.event.inputs.tag || 'latest' }}
|
76 |
+
|
77 |
+
build-and-push-image:
|
78 |
+
runs-on: ubuntu-latest
|
79 |
+
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
|
80 |
+
permissions:
|
81 |
+
contents: read
|
82 |
+
packages: write
|
83 |
+
#
|
84 |
+
steps:
|
85 |
+
- name: Checkout repository
|
86 |
+
uses: actions/checkout@v4
|
87 |
+
with:
|
88 |
+
ref: ${{ github.event.inputs.commit_hash }}
|
89 |
+
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
|
90 |
+
- name: Log in to the Container registry
|
91 |
+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
92 |
+
with:
|
93 |
+
registry: ${{ env.REGISTRY }}
|
94 |
+
username: ${{ github.actor }}
|
95 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
96 |
+
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
|
97 |
+
- name: Extract metadata (tags, labels) for Docker
|
98 |
+
id: meta
|
99 |
+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
100 |
+
with:
|
101 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
102 |
+
# Configure multi platform Docker builds
|
103 |
+
- name: Set up QEMU
|
104 |
+
uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
|
105 |
+
- name: Set up Docker Buildx
|
106 |
+
uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345
|
107 |
+
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
|
108 |
+
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
|
109 |
+
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
|
110 |
+
- name: Build and push Docker image
|
111 |
+
uses: docker/build-push-action@4976231911ebf5f32aad765192d35f942aa48cb8
|
112 |
+
with:
|
113 |
+
context: .
|
114 |
+
push: true
|
115 |
+
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'
|
116 |
+
labels: ${{ steps.meta.outputs.labels }}
|
117 |
+
platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
|
118 |
+
|
119 |
+
build-and-push-image-database:
|
120 |
+
runs-on: ubuntu-latest
|
121 |
+
permissions:
|
122 |
+
contents: read
|
123 |
+
packages: write
|
124 |
+
steps:
|
125 |
+
- name: Checkout repository
|
126 |
+
uses: actions/checkout@v4
|
127 |
+
with:
|
128 |
+
ref: ${{ github.event.inputs.commit_hash }}
|
129 |
+
|
130 |
+
- name: Log in to the Container registry
|
131 |
+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
132 |
+
with:
|
133 |
+
registry: ${{ env.REGISTRY }}
|
134 |
+
username: ${{ github.actor }}
|
135 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
136 |
+
|
137 |
+
- name: Extract metadata (tags, labels) for database Dockerfile
|
138 |
+
id: meta-database
|
139 |
+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
140 |
+
with:
|
141 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-database
|
142 |
+
# Configure multi platform Docker builds
|
143 |
+
- name: Set up QEMU
|
144 |
+
uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
|
145 |
+
- name: Set up Docker Buildx
|
146 |
+
uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345
|
147 |
+
|
148 |
+
- name: Build and push Database Docker image
|
149 |
+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
150 |
+
with:
|
151 |
+
context: .
|
152 |
+
file: ./docker/Dockerfile.database
|
153 |
+
push: true
|
154 |
+
tags: ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.release_type }}
|
155 |
+
labels: ${{ steps.meta-database.outputs.labels }}
|
156 |
+
platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
|
157 |
+
|
158 |
+
build-and-push-image-non_root:
|
159 |
+
runs-on: ubuntu-latest
|
160 |
+
permissions:
|
161 |
+
contents: read
|
162 |
+
packages: write
|
163 |
+
steps:
|
164 |
+
- name: Checkout repository
|
165 |
+
uses: actions/checkout@v4
|
166 |
+
with:
|
167 |
+
ref: ${{ github.event.inputs.commit_hash }}
|
168 |
+
|
169 |
+
- name: Log in to the Container registry
|
170 |
+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
171 |
+
with:
|
172 |
+
registry: ${{ env.REGISTRY }}
|
173 |
+
username: ${{ github.actor }}
|
174 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
175 |
+
|
176 |
+
- name: Extract metadata (tags, labels) for non_root Dockerfile
|
177 |
+
id: meta-non_root
|
178 |
+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
179 |
+
with:
|
180 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-non_root
|
181 |
+
# Configure multi platform Docker builds
|
182 |
+
- name: Set up QEMU
|
183 |
+
uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
|
184 |
+
- name: Set up Docker Buildx
|
185 |
+
uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345
|
186 |
+
|
187 |
+
- name: Build and push non_root Docker image
|
188 |
+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
189 |
+
with:
|
190 |
+
context: .
|
191 |
+
file: ./docker/Dockerfile.non_root
|
192 |
+
push: true
|
193 |
+
tags: ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.release_type }}
|
194 |
+
labels: ${{ steps.meta-non_root.outputs.labels }}
|
195 |
+
platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
|
196 |
+
|
197 |
+
build-and-push-image-spend-logs:
|
198 |
+
runs-on: ubuntu-latest
|
199 |
+
permissions:
|
200 |
+
contents: read
|
201 |
+
packages: write
|
202 |
+
steps:
|
203 |
+
- name: Checkout repository
|
204 |
+
uses: actions/checkout@v4
|
205 |
+
with:
|
206 |
+
ref: ${{ github.event.inputs.commit_hash }}
|
207 |
+
|
208 |
+
- name: Log in to the Container registry
|
209 |
+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
210 |
+
with:
|
211 |
+
registry: ${{ env.REGISTRY }}
|
212 |
+
username: ${{ github.actor }}
|
213 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
214 |
+
|
215 |
+
- name: Extract metadata (tags, labels) for spend-logs Dockerfile
|
216 |
+
id: meta-spend-logs
|
217 |
+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
218 |
+
with:
|
219 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-spend_logs
|
220 |
+
# Configure multi platform Docker builds
|
221 |
+
- name: Set up QEMU
|
222 |
+
uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
|
223 |
+
- name: Set up Docker Buildx
|
224 |
+
uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345
|
225 |
+
|
226 |
+
- name: Build and push Database Docker image
|
227 |
+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
228 |
+
with:
|
229 |
+
context: .
|
230 |
+
file: ./litellm-js/spend-logs/Dockerfile
|
231 |
+
push: true
|
232 |
+
tags: ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }}, ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.release_type }}
|
233 |
+
platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
|
234 |
+
|
235 |
+
build-and-push-helm-chart:
|
236 |
+
if: github.event.inputs.release_type != 'dev'
|
237 |
+
needs: [docker-hub-deploy, build-and-push-image, build-and-push-image-database]
|
238 |
+
runs-on: ubuntu-latest
|
239 |
+
steps:
|
240 |
+
- name: Checkout repository
|
241 |
+
uses: actions/checkout@v4
|
242 |
+
with:
|
243 |
+
fetch-depth: 0
|
244 |
+
|
245 |
+
- name: Log in to the Container registry
|
246 |
+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
247 |
+
with:
|
248 |
+
registry: ${{ env.REGISTRY }}
|
249 |
+
username: ${{ github.actor }}
|
250 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
251 |
+
|
252 |
+
- name: lowercase github.repository_owner
|
253 |
+
run: |
|
254 |
+
echo "REPO_OWNER=`echo ${{github.repository_owner}} | tr '[:upper:]' '[:lower:]'`" >>${GITHUB_ENV}
|
255 |
+
|
256 |
+
- name: Get LiteLLM Latest Tag
|
257 |
+
id: current_app_tag
|
258 |
+
shell: bash
|
259 |
+
run: |
|
260 |
+
LATEST_TAG=$(git describe --tags --exclude "*dev*" --abbrev=0)
|
261 |
+
if [ -z "${LATEST_TAG}" ]; then
|
262 |
+
echo "latest_tag=latest" | tee -a $GITHUB_OUTPUT
|
263 |
+
else
|
264 |
+
echo "latest_tag=${LATEST_TAG}" | tee -a $GITHUB_OUTPUT
|
265 |
+
fi
|
266 |
+
|
267 |
+
- name: Get last published chart version
|
268 |
+
id: current_version
|
269 |
+
shell: bash
|
270 |
+
run: |
|
271 |
+
CHART_LIST=$(helm show chart oci://${{ env.REGISTRY }}/${{ env.REPO_OWNER }}/${{ env.CHART_NAME }} 2>/dev/null || true)
|
272 |
+
if [ -z "${CHART_LIST}" ]; then
|
273 |
+
echo "current-version=0.1.0" | tee -a $GITHUB_OUTPUT
|
274 |
+
else
|
275 |
+
printf '%s' "${CHART_LIST}" | grep '^version:' | awk 'BEGIN{FS=":"}{print "current-version="$2}' | tr -d " " | tee -a $GITHUB_OUTPUT
|
276 |
+
fi
|
277 |
+
env:
|
278 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
279 |
+
|
280 |
+
# Automatically update the helm chart version one "patch" level
|
281 |
+
- name: Bump release version
|
282 |
+
id: bump_version
|
283 |
+
uses: christian-draeger/[email protected]
|
284 |
+
with:
|
285 |
+
current-version: ${{ steps.current_version.outputs.current-version || '0.1.0' }}
|
286 |
+
version-fragment: 'bug'
|
287 |
+
|
288 |
+
- uses: ./.github/actions/helm-oci-chart-releaser
|
289 |
+
with:
|
290 |
+
name: ${{ env.CHART_NAME }}
|
291 |
+
repository: ${{ env.REPO_OWNER }}
|
292 |
+
tag: ${{ github.event.inputs.chartVersion || steps.bump_version.outputs.next-version || '0.1.0' }}
|
293 |
+
app_version: ${{ steps.current_app_tag.outputs.latest_tag }}
|
294 |
+
path: deploy/charts/${{ env.CHART_NAME }}
|
295 |
+
registry: ${{ env.REGISTRY }}
|
296 |
+
registry_username: ${{ github.actor }}
|
297 |
+
registry_password: ${{ secrets.GITHUB_TOKEN }}
|
298 |
+
update_dependencies: true
|
299 |
+
|
300 |
+
release:
|
301 |
+
name: "New LiteLLM Release"
|
302 |
+
needs: [docker-hub-deploy, build-and-push-image, build-and-push-image-database]
|
303 |
+
|
304 |
+
runs-on: "ubuntu-latest"
|
305 |
+
|
306 |
+
steps:
|
307 |
+
- name: Display version
|
308 |
+
run: echo "Current version is ${{ github.event.inputs.tag }}"
|
309 |
+
- name: "Set Release Tag"
|
310 |
+
run: echo "RELEASE_TAG=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
|
311 |
+
- name: Display release tag
|
312 |
+
run: echo "RELEASE_TAG is $RELEASE_TAG"
|
313 |
+
- name: "Create release"
|
314 |
+
uses: "actions/github-script@v6"
|
315 |
+
with:
|
316 |
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
317 |
+
script: |
|
318 |
+
const commitHash = "${{ github.event.inputs.commit_hash}}";
|
319 |
+
console.log("Commit Hash:", commitHash); // Add this line for debugging
|
320 |
+
try {
|
321 |
+
const response = await github.rest.repos.createRelease({
|
322 |
+
draft: false,
|
323 |
+
generate_release_notes: true,
|
324 |
+
target_commitish: commitHash,
|
325 |
+
name: process.env.RELEASE_TAG,
|
326 |
+
owner: context.repo.owner,
|
327 |
+
prerelease: false,
|
328 |
+
repo: context.repo.repo,
|
329 |
+
tag_name: process.env.RELEASE_TAG,
|
330 |
+
});
|
331 |
+
|
332 |
+
core.exportVariable('RELEASE_ID', response.data.id);
|
333 |
+
core.exportVariable('RELEASE_UPLOAD_URL', response.data.upload_url);
|
334 |
+
} catch (error) {
|
335 |
+
core.setFailed(error.message);
|
336 |
+
}
|
337 |
+
- name: Fetch Release Notes
|
338 |
+
id: release-notes
|
339 |
+
uses: actions/github-script@v6
|
340 |
+
with:
|
341 |
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
342 |
+
script: |
|
343 |
+
try {
|
344 |
+
const response = await github.rest.repos.getRelease({
|
345 |
+
owner: context.repo.owner,
|
346 |
+
repo: context.repo.repo,
|
347 |
+
release_id: process.env.RELEASE_ID,
|
348 |
+
});
|
349 |
+
const formattedBody = JSON.stringify(response.data.body).slice(1, -1);
|
350 |
+
return formattedBody;
|
351 |
+
} catch (error) {
|
352 |
+
core.setFailed(error.message);
|
353 |
+
}
|
354 |
+
env:
|
355 |
+
RELEASE_ID: ${{ env.RELEASE_ID }}
|
356 |
+
- name: Github Releases To Discord
|
357 |
+
env:
|
358 |
+
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
|
359 |
+
REALEASE_TAG: ${{ env.RELEASE_TAG }}
|
360 |
+
RELEASE_NOTES: ${{ steps.release-notes.outputs.result }}
|
361 |
+
run: |
|
362 |
+
curl -H "Content-Type: application/json" -X POST -d '{
|
363 |
+
"content": "New LiteLLM release '"${RELEASE_TAG}"'",
|
364 |
+
"username": "Release Changelog",
|
365 |
+
"avatar_url": "https://cdn.discordapp.com/avatars/487431320314576937/bd64361e4ba6313d561d54e78c9e7171.png",
|
366 |
+
"embeds": [
|
367 |
+
{
|
368 |
+
"title": "Changelog for LiteLLM '"${RELEASE_TAG}"'",
|
369 |
+
"description": "'"${RELEASE_NOTES}"'",
|
370 |
+
"color": 2105893
|
371 |
+
}
|
372 |
+
]
|
373 |
+
}' $WEBHOOK_URL
|
374 |
+
|
.github/workflows/ghcr_helm_deploy.yml
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# this workflow is triggered by an API call when there is a new PyPI release of LiteLLM
|
2 |
+
name: Build, Publish LiteLLM Helm Chart. New Release
|
3 |
+
on:
|
4 |
+
workflow_dispatch:
|
5 |
+
inputs:
|
6 |
+
chartVersion:
|
7 |
+
description: "Update the helm chart's version to this"
|
8 |
+
|
9 |
+
# Defines two custom environment variables for the workflow. Used for the Container registry domain, and a name for the Docker image that this workflow builds.
|
10 |
+
env:
|
11 |
+
REGISTRY: ghcr.io
|
12 |
+
IMAGE_NAME: ${{ github.repository }}
|
13 |
+
REPO_OWNER: ${{github.repository_owner}}
|
14 |
+
|
15 |
+
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
|
16 |
+
jobs:
|
17 |
+
build-and-push-helm-chart:
|
18 |
+
runs-on: ubuntu-latest
|
19 |
+
steps:
|
20 |
+
- name: Checkout repository
|
21 |
+
uses: actions/checkout@v4
|
22 |
+
|
23 |
+
- name: Log in to the Container registry
|
24 |
+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
25 |
+
with:
|
26 |
+
registry: ${{ env.REGISTRY }}
|
27 |
+
username: ${{ github.actor }}
|
28 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
29 |
+
|
30 |
+
- name: lowercase github.repository_owner
|
31 |
+
run: |
|
32 |
+
echo "REPO_OWNER=`echo ${{github.repository_owner}} | tr '[:upper:]' '[:lower:]'`" >>${GITHUB_ENV}
|
33 |
+
|
34 |
+
- name: Get LiteLLM Latest Tag
|
35 |
+
id: current_app_tag
|
36 |
+
uses: WyriHaximus/[email protected]
|
37 |
+
|
38 |
+
- name: Get last published chart version
|
39 |
+
id: current_version
|
40 |
+
shell: bash
|
41 |
+
run: helm show chart oci://${{ env.REGISTRY }}/${{ env.REPO_OWNER }}/litellm-helm | grep '^version:' | awk 'BEGIN{FS=":"}{print "current-version="$2}' | tr -d " " | tee -a $GITHUB_OUTPUT
|
42 |
+
env:
|
43 |
+
HELM_EXPERIMENTAL_OCI: '1'
|
44 |
+
|
45 |
+
# Automatically update the helm chart version one "patch" level
|
46 |
+
- name: Bump release version
|
47 |
+
id: bump_version
|
48 |
+
uses: christian-draeger/[email protected]
|
49 |
+
with:
|
50 |
+
current-version: ${{ steps.current_version.outputs.current-version || '0.1.0' }}
|
51 |
+
version-fragment: 'bug'
|
52 |
+
|
53 |
+
- name: Lint helm chart
|
54 |
+
run: helm lint deploy/charts/litellm-helm
|
55 |
+
|
56 |
+
- uses: ./.github/actions/helm-oci-chart-releaser
|
57 |
+
with:
|
58 |
+
name: litellm-helm
|
59 |
+
repository: ${{ env.REPO_OWNER }}
|
60 |
+
tag: ${{ github.event.inputs.chartVersion || steps.bump_version.outputs.next-version || '0.1.0' }}
|
61 |
+
app_version: ${{ steps.current_app_tag.outputs.tag || 'latest' }}
|
62 |
+
path: deploy/charts/litellm-helm
|
63 |
+
registry: ${{ env.REGISTRY }}
|
64 |
+
registry_username: ${{ github.actor }}
|
65 |
+
registry_password: ${{ secrets.GITHUB_TOKEN }}
|
66 |
+
update_dependencies: true
|
67 |
+
|
.github/workflows/interpret_load_test.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import csv
|
2 |
+
import os
|
3 |
+
from github import Github
|
4 |
+
|
5 |
+
|
6 |
+
def interpret_results(csv_file):
|
7 |
+
with open(csv_file, newline="") as csvfile:
|
8 |
+
csvreader = csv.DictReader(csvfile)
|
9 |
+
rows = list(csvreader)
|
10 |
+
"""
|
11 |
+
in this csv reader
|
12 |
+
- Create 1 new column "Status"
|
13 |
+
- if a row has a median response time < 300 and an average response time < 300, Status = "Passed ✅"
|
14 |
+
- if a row has a median response time >= 300 or an average response time >= 300, Status = "Failed ❌"
|
15 |
+
- Order the table in this order Name, Status, Median Response Time, Average Response Time, Requests/s,Failures/s, Min Response Time, Max Response Time, all other columns
|
16 |
+
"""
|
17 |
+
|
18 |
+
# Add a new column "Status"
|
19 |
+
for row in rows:
|
20 |
+
median_response_time = float(
|
21 |
+
row["Median Response Time"].strip().rstrip("ms")
|
22 |
+
)
|
23 |
+
average_response_time = float(
|
24 |
+
row["Average Response Time"].strip().rstrip("s")
|
25 |
+
)
|
26 |
+
|
27 |
+
request_count = int(row["Request Count"])
|
28 |
+
failure_count = int(row["Failure Count"])
|
29 |
+
|
30 |
+
failure_percent = round((failure_count / request_count) * 100, 2)
|
31 |
+
|
32 |
+
# Determine status based on conditions
|
33 |
+
if (
|
34 |
+
median_response_time < 300
|
35 |
+
and average_response_time < 300
|
36 |
+
and failure_percent < 5
|
37 |
+
):
|
38 |
+
row["Status"] = "Passed ✅"
|
39 |
+
else:
|
40 |
+
row["Status"] = "Failed ❌"
|
41 |
+
|
42 |
+
# Construct Markdown table header
|
43 |
+
markdown_table = "| Name | Status | Median Response Time (ms) | Average Response Time (ms) | Requests/s | Failures/s | Request Count | Failure Count | Min Response Time (ms) | Max Response Time (ms) |"
|
44 |
+
markdown_table += (
|
45 |
+
"\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |"
|
46 |
+
)
|
47 |
+
|
48 |
+
# Construct Markdown table rows
|
49 |
+
for row in rows:
|
50 |
+
markdown_table += f"\n| {row['Name']} | {row['Status']} | {row['Median Response Time']} | {row['Average Response Time']} | {row['Requests/s']} | {row['Failures/s']} | {row['Request Count']} | {row['Failure Count']} | {row['Min Response Time']} | {row['Max Response Time']} |"
|
51 |
+
print("markdown table: ", markdown_table)
|
52 |
+
return markdown_table
|
53 |
+
|
54 |
+
|
55 |
+
if __name__ == "__main__":
|
56 |
+
csv_file = "load_test_stats.csv" # Change this to the path of your CSV file
|
57 |
+
markdown_table = interpret_results(csv_file)
|
58 |
+
|
59 |
+
# Update release body with interpreted results
|
60 |
+
github_token = os.getenv("GITHUB_TOKEN")
|
61 |
+
g = Github(github_token)
|
62 |
+
repo = g.get_repo(
|
63 |
+
"BerriAI/litellm"
|
64 |
+
) # Replace with your repository's username and name
|
65 |
+
latest_release = repo.get_latest_release()
|
66 |
+
print("got latest release: ", latest_release)
|
67 |
+
print(latest_release.title)
|
68 |
+
print(latest_release.tag_name)
|
69 |
+
|
70 |
+
release_version = latest_release.title
|
71 |
+
|
72 |
+
print("latest release body: ", latest_release.body)
|
73 |
+
print("markdown table: ", markdown_table)
|
74 |
+
|
75 |
+
# check if "Load Test LiteLLM Proxy Results" exists
|
76 |
+
existing_release_body = latest_release.body
|
77 |
+
if "Load Test LiteLLM Proxy Results" in latest_release.body:
|
78 |
+
# find the "Load Test LiteLLM Proxy Results" section and delete it
|
79 |
+
start_index = latest_release.body.find("Load Test LiteLLM Proxy Results")
|
80 |
+
existing_release_body = latest_release.body[:start_index]
|
81 |
+
|
82 |
+
docker_run_command = f"""
|
83 |
+
\n\n
|
84 |
+
## Docker Run LiteLLM Proxy
|
85 |
+
|
86 |
+
```
|
87 |
+
docker run \\
|
88 |
+
-e STORE_MODEL_IN_DB=True \\
|
89 |
+
-p 4000:4000 \\
|
90 |
+
ghcr.io/berriai/litellm:main-{release_version}
|
91 |
+
```
|
92 |
+
"""
|
93 |
+
print("docker run command: ", docker_run_command)
|
94 |
+
|
95 |
+
new_release_body = (
|
96 |
+
existing_release_body
|
97 |
+
+ docker_run_command
|
98 |
+
+ "\n\n"
|
99 |
+
+ "### Don't want to maintain your internal proxy? get in touch 🎉"
|
100 |
+
+ "\nHosted Proxy Alpha: https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat"
|
101 |
+
+ "\n\n"
|
102 |
+
+ "## Load Test LiteLLM Proxy Results"
|
103 |
+
+ "\n\n"
|
104 |
+
+ markdown_table
|
105 |
+
)
|
106 |
+
print("new release body: ", new_release_body)
|
107 |
+
try:
|
108 |
+
latest_release.update_release(
|
109 |
+
name=latest_release.tag_name,
|
110 |
+
message=new_release_body,
|
111 |
+
)
|
112 |
+
except Exception as e:
|
113 |
+
print(e)
|
.github/workflows/label-mlops.yml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Label ML Ops Team Issues
|
2 |
+
|
3 |
+
on:
|
4 |
+
issues:
|
5 |
+
types:
|
6 |
+
- opened
|
7 |
+
|
8 |
+
jobs:
|
9 |
+
add-mlops-label:
|
10 |
+
runs-on: ubuntu-latest
|
11 |
+
steps:
|
12 |
+
- name: Check if ML Ops Team is selected
|
13 |
+
uses: actions-ecosystem/action-add-labels@v1
|
14 |
+
if: contains(github.event.issue.body, '### Are you a ML Ops Team?') && contains(github.event.issue.body, 'Yes')
|
15 |
+
with:
|
16 |
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
17 |
+
labels: "mlops user request"
|
.github/workflows/load_test.yml
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Test Locust Load Test
|
2 |
+
|
3 |
+
on:
|
4 |
+
workflow_run:
|
5 |
+
workflows: ["Build, Publish LiteLLM Docker Image. New Release"]
|
6 |
+
types:
|
7 |
+
- completed
|
8 |
+
workflow_dispatch:
|
9 |
+
|
10 |
+
jobs:
|
11 |
+
build:
|
12 |
+
runs-on: ubuntu-latest
|
13 |
+
steps:
|
14 |
+
- name: Checkout
|
15 |
+
uses: actions/checkout@v1
|
16 |
+
- name: Setup Python
|
17 |
+
uses: actions/setup-python@v2
|
18 |
+
with:
|
19 |
+
python-version: '3.x'
|
20 |
+
|
21 |
+
- name: Install dependencies
|
22 |
+
run: |
|
23 |
+
python -m pip install --upgrade pip
|
24 |
+
pip install PyGithub
|
25 |
+
- name: re-deploy proxy
|
26 |
+
run: |
|
27 |
+
echo "Current working directory: $PWD"
|
28 |
+
ls
|
29 |
+
python ".github/workflows/redeploy_proxy.py"
|
30 |
+
env:
|
31 |
+
LOAD_TEST_REDEPLOY_URL1: ${{ secrets.LOAD_TEST_REDEPLOY_URL1 }}
|
32 |
+
LOAD_TEST_REDEPLOY_URL2: ${{ secrets.LOAD_TEST_REDEPLOY_URL2 }}
|
33 |
+
working-directory: ${{ github.workspace }}
|
34 |
+
- name: Run Load Test
|
35 |
+
id: locust_run
|
36 |
+
uses: BerriAI/locust-github-action@master
|
37 |
+
with:
|
38 |
+
LOCUSTFILE: ".github/workflows/locustfile.py"
|
39 |
+
URL: "https://post-release-load-test-proxy.onrender.com/"
|
40 |
+
USERS: "20"
|
41 |
+
RATE: "20"
|
42 |
+
RUNTIME: "300s"
|
43 |
+
- name: Process Load Test Stats
|
44 |
+
run: |
|
45 |
+
echo "Current working directory: $PWD"
|
46 |
+
ls
|
47 |
+
python ".github/workflows/interpret_load_test.py"
|
48 |
+
env:
|
49 |
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
50 |
+
working-directory: ${{ github.workspace }}
|
51 |
+
- name: Upload CSV as Asset to Latest Release
|
52 |
+
uses: xresloader/upload-to-github-release@v1
|
53 |
+
env:
|
54 |
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
55 |
+
with:
|
56 |
+
file: "load_test_stats.csv;load_test.html"
|
57 |
+
update_latest_release: true
|
58 |
+
tag_name: "load-test"
|
59 |
+
overwrite: true
|
.github/workflows/locustfile.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from locust import HttpUser, task, between
|
2 |
+
|
3 |
+
|
4 |
+
class MyUser(HttpUser):
|
5 |
+
wait_time = between(1, 5)
|
6 |
+
|
7 |
+
@task
|
8 |
+
def chat_completion(self):
|
9 |
+
headers = {
|
10 |
+
"Content-Type": "application/json",
|
11 |
+
"Authorization": "Bearer sk-ZoHqrLIs2-5PzJrqBaviAA",
|
12 |
+
# Include any additional headers you may need for authentication, etc.
|
13 |
+
}
|
14 |
+
|
15 |
+
# Customize the payload with "model" and "messages" keys
|
16 |
+
payload = {
|
17 |
+
"model": "fake-openai-endpoint",
|
18 |
+
"messages": [
|
19 |
+
{"role": "system", "content": "You are a chat bot."},
|
20 |
+
{"role": "user", "content": "Hello, how are you?"},
|
21 |
+
],
|
22 |
+
# Add more data as necessary
|
23 |
+
}
|
24 |
+
|
25 |
+
# Make a POST request to the "chat/completions" endpoint
|
26 |
+
response = self.client.post("chat/completions", json=payload, headers=headers)
|
27 |
+
|
28 |
+
# Print or log the response if needed
|
.github/workflows/main.yml
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Publish Dev Release to PyPI
|
2 |
+
|
3 |
+
on:
|
4 |
+
workflow_dispatch:
|
5 |
+
|
6 |
+
jobs:
|
7 |
+
publish-dev-release:
|
8 |
+
runs-on: ubuntu-latest
|
9 |
+
|
10 |
+
steps:
|
11 |
+
- name: Checkout code
|
12 |
+
uses: actions/checkout@v2
|
13 |
+
|
14 |
+
- name: Set up Python
|
15 |
+
uses: actions/setup-python@v2
|
16 |
+
with:
|
17 |
+
python-version: 3.8 # Adjust the Python version as needed
|
18 |
+
|
19 |
+
- name: Install dependencies
|
20 |
+
run: pip install toml twine
|
21 |
+
|
22 |
+
- name: Read version from pyproject.toml
|
23 |
+
id: read-version
|
24 |
+
run: |
|
25 |
+
version=$(python -c 'import toml; print(toml.load("pyproject.toml")["tool"]["commitizen"]["version"])')
|
26 |
+
printf "LITELLM_VERSION=%s" "$version" >> $GITHUB_ENV
|
27 |
+
|
28 |
+
- name: Check if version exists on PyPI
|
29 |
+
id: check-version
|
30 |
+
run: |
|
31 |
+
set -e
|
32 |
+
if twine check --repository-url https://pypi.org/simple/ "litellm==$LITELLM_VERSION" >/dev/null 2>&1; then
|
33 |
+
echo "Version $LITELLM_VERSION already exists on PyPI. Skipping publish."
|
34 |
+
|
.github/workflows/read_pyproject_version.yml
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Read Version from pyproject.toml
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- main # Change this to the default branch of your repository
|
7 |
+
|
8 |
+
jobs:
|
9 |
+
read-version:
|
10 |
+
runs-on: ubuntu-latest
|
11 |
+
|
12 |
+
steps:
|
13 |
+
- name: Checkout code
|
14 |
+
uses: actions/checkout@v2
|
15 |
+
|
16 |
+
- name: Set up Python
|
17 |
+
uses: actions/setup-python@v2
|
18 |
+
with:
|
19 |
+
python-version: 3.8 # Adjust the Python version as needed
|
20 |
+
|
21 |
+
- name: Install dependencies
|
22 |
+
run: pip install toml
|
23 |
+
|
24 |
+
- name: Read version from pyproject.toml
|
25 |
+
id: read-version
|
26 |
+
run: |
|
27 |
+
version=$(python -c 'import toml; print(toml.load("pyproject.toml")["tool"]["commitizen"]["version"])')
|
28 |
+
printf "LITELLM_VERSION=%s" "$version" >> $GITHUB_ENV
|
29 |
+
|
30 |
+
- name: Display version
|
31 |
+
run: echo "Current version is $LITELLM_VERSION"
|
.github/workflows/redeploy_proxy.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
|
3 |
+
redeploy_proxy.py
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
import requests
|
8 |
+
import time
|
9 |
+
|
10 |
+
# send a get request to this endpoint
|
11 |
+
deploy_hook1 = os.getenv("LOAD_TEST_REDEPLOY_URL1")
|
12 |
+
response = requests.get(deploy_hook1, timeout=20)
|
13 |
+
|
14 |
+
|
15 |
+
deploy_hook2 = os.getenv("LOAD_TEST_REDEPLOY_URL2")
|
16 |
+
response = requests.get(deploy_hook2, timeout=20)
|
17 |
+
|
18 |
+
print("SENT GET REQUESTS to re-deploy proxy")
|
19 |
+
print("sleeeping.... for 60s")
|
20 |
+
time.sleep(60)
|
.github/workflows/reset_stable.yml
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Reset litellm_stable branch
|
2 |
+
|
3 |
+
on:
|
4 |
+
release:
|
5 |
+
types: [published, created]
|
6 |
+
jobs:
|
7 |
+
update-stable-branch:
|
8 |
+
if: ${{ startsWith(github.event.release.tag_name, 'v') && !endsWith(github.event.release.tag_name, '-stable') }}
|
9 |
+
runs-on: ubuntu-latest
|
10 |
+
|
11 |
+
steps:
|
12 |
+
- name: Checkout repository
|
13 |
+
uses: actions/checkout@v3
|
14 |
+
|
15 |
+
- name: Reset litellm_stable_release_branch branch to the release commit
|
16 |
+
env:
|
17 |
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
18 |
+
run: |
|
19 |
+
# Configure Git user
|
20 |
+
git config user.name "github-actions[bot]"
|
21 |
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
22 |
+
|
23 |
+
# Fetch all branches and tags
|
24 |
+
git fetch --all
|
25 |
+
|
26 |
+
# Check if the litellm_stable_release_branch branch exists
|
27 |
+
if git show-ref --verify --quiet refs/remotes/origin/litellm_stable_release_branch; then
|
28 |
+
echo "litellm_stable_release_branch branch exists."
|
29 |
+
git checkout litellm_stable_release_branch
|
30 |
+
else
|
31 |
+
echo "litellm_stable_release_branch branch does not exist. Creating it."
|
32 |
+
git checkout -b litellm_stable_release_branch
|
33 |
+
fi
|
34 |
+
|
35 |
+
# Reset litellm_stable_release_branch branch to the release commit
|
36 |
+
git reset --hard $GITHUB_SHA
|
37 |
+
|
38 |
+
# Push the updated litellm_stable_release_branch branch
|
39 |
+
git push origin litellm_stable_release_branch --force
|
.github/workflows/results_stats.csv
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Date,"Ben
|
2 |
+
Ashley",Tom Brooks,Jimmy Cooney,"Sue
|
3 |
+
Daniels",Berlinda Fong,Terry Jones,Angelina Little,Linda Smith
|
4 |
+
10/1,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE,TRUE
|
5 |
+
10/2,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
6 |
+
10/3,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
7 |
+
10/4,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
8 |
+
10/5,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
9 |
+
10/6,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
10 |
+
10/7,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
11 |
+
10/8,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
12 |
+
10/9,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
13 |
+
10/10,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
14 |
+
10/11,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
15 |
+
10/12,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
16 |
+
10/13,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
17 |
+
10/14,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
18 |
+
10/15,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
19 |
+
10/16,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
20 |
+
10/17,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
21 |
+
10/18,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
22 |
+
10/19,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
23 |
+
10/20,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
24 |
+
10/21,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
25 |
+
10/22,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
26 |
+
10/23,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE
|
27 |
+
Total,0,1,1,1,1,1,0,1
|
.github/workflows/stale.yml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: "Stale Issue Management"
|
2 |
+
|
3 |
+
on:
|
4 |
+
schedule:
|
5 |
+
- cron: '0 0 * * *' # Runs daily at midnight UTC
|
6 |
+
workflow_dispatch:
|
7 |
+
|
8 |
+
jobs:
|
9 |
+
stale:
|
10 |
+
runs-on: ubuntu-latest
|
11 |
+
steps:
|
12 |
+
- uses: actions/stale@v8
|
13 |
+
with:
|
14 |
+
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
15 |
+
stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs."
|
16 |
+
stale-pr-message: "This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs."
|
17 |
+
days-before-stale: 90 # Revert to 60 days
|
18 |
+
days-before-close: 7 # Revert to 7 days
|
19 |
+
stale-issue-label: "stale"
|
20 |
+
operations-per-run: 1000
|
.github/workflows/update_release.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import requests
|
3 |
+
from datetime import datetime
|
4 |
+
|
5 |
+
# GitHub API endpoints
|
6 |
+
GITHUB_API_URL = "https://api.github.com"
|
7 |
+
REPO_OWNER = "BerriAI"
|
8 |
+
REPO_NAME = "litellm"
|
9 |
+
|
10 |
+
# GitHub personal access token (required for uploading release assets)
|
11 |
+
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN")
|
12 |
+
|
13 |
+
# Headers for GitHub API requests
|
14 |
+
headers = {
|
15 |
+
"Accept": "application/vnd.github+json",
|
16 |
+
"Authorization": f"Bearer {GITHUB_ACCESS_TOKEN}",
|
17 |
+
"X-GitHub-Api-Version": "2022-11-28",
|
18 |
+
}
|
19 |
+
|
20 |
+
# Get the latest release
|
21 |
+
releases_url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/releases/latest"
|
22 |
+
response = requests.get(releases_url, headers=headers)
|
23 |
+
latest_release = response.json()
|
24 |
+
print("Latest release:", latest_release)
|
25 |
+
|
26 |
+
# Upload an asset to the latest release
|
27 |
+
upload_url = latest_release["upload_url"].split("{?")[0]
|
28 |
+
asset_name = "results_stats.csv"
|
29 |
+
asset_path = os.path.join(os.getcwd(), asset_name)
|
30 |
+
print("upload_url:", upload_url)
|
31 |
+
|
32 |
+
with open(asset_path, "rb") as asset_file:
|
33 |
+
asset_data = asset_file.read()
|
34 |
+
|
35 |
+
upload_payload = {
|
36 |
+
"name": asset_name,
|
37 |
+
"label": "Load test results",
|
38 |
+
"created_at": datetime.utcnow().isoformat() + "Z",
|
39 |
+
}
|
40 |
+
|
41 |
+
upload_headers = headers.copy()
|
42 |
+
upload_headers["Content-Type"] = "application/octet-stream"
|
43 |
+
|
44 |
+
upload_response = requests.post(
|
45 |
+
upload_url,
|
46 |
+
headers=upload_headers,
|
47 |
+
data=asset_data,
|
48 |
+
params=upload_payload,
|
49 |
+
)
|
50 |
+
|
51 |
+
if upload_response.status_code == 201:
|
52 |
+
print(f"Asset '{asset_name}' uploaded successfully to the latest release.")
|
53 |
+
else:
|
54 |
+
print(f"Failed to upload asset. Response: {upload_response.text}")
|
.pre-commit-config.yaml
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
repos:
|
2 |
+
- repo: local
|
3 |
+
hooks:
|
4 |
+
- id: pyright
|
5 |
+
name: pyright
|
6 |
+
entry: pyright
|
7 |
+
language: system
|
8 |
+
types: [python]
|
9 |
+
files: ^litellm/
|
10 |
+
- id: isort
|
11 |
+
name: isort
|
12 |
+
entry: isort
|
13 |
+
language: system
|
14 |
+
types: [python]
|
15 |
+
files: litellm/.*\.py
|
16 |
+
exclude: ^litellm/__init__.py$
|
17 |
+
- repo: https://github.com/psf/black
|
18 |
+
rev: 24.2.0
|
19 |
+
hooks:
|
20 |
+
- id: black
|
21 |
+
- repo: https://github.com/pycqa/flake8
|
22 |
+
rev: 7.0.0 # The version of flake8 to use
|
23 |
+
hooks:
|
24 |
+
- id: flake8
|
25 |
+
exclude: ^litellm/tests/|^litellm/proxy/tests/
|
26 |
+
additional_dependencies: [flake8-print]
|
27 |
+
files: litellm/.*\.py
|
28 |
+
# - id: flake8
|
29 |
+
# name: flake8 (router.py function length)
|
30 |
+
# files: ^litellm/router\.py$
|
31 |
+
# args: [--max-function-length=40]
|
32 |
+
# # additional_dependencies: [flake8-functions]
|
33 |
+
- repo: https://github.com/python-poetry/poetry
|
34 |
+
rev: 1.8.0
|
35 |
+
hooks:
|
36 |
+
- id: poetry-check
|
37 |
+
- repo: local
|
38 |
+
hooks:
|
39 |
+
- id: check-files-match
|
40 |
+
name: Check if files match
|
41 |
+
entry: python3 ci_cd/check_files_match.py
|
42 |
+
language: system
|
43 |
+
# - id: check-file-length
|
44 |
+
# name: Check file length
|
45 |
+
# entry: python check_file_length.py
|
46 |
+
# args: ["10000"] # set your desired maximum number of lines
|
47 |
+
# language: python
|
48 |
+
# files: litellm/.*\.py
|
49 |
+
# exclude: ^litellm/tests/
|
Dockerfile
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Base image for building
|
2 |
+
ARG LITELLM_BUILD_IMAGE=python:3.13.1-slim
|
3 |
+
|
4 |
+
# Runtime image
|
5 |
+
ARG LITELLM_RUNTIME_IMAGE=python:3.13.1-slim
|
6 |
+
# Builder stage
|
7 |
+
FROM $LITELLM_BUILD_IMAGE AS builder
|
8 |
+
|
9 |
+
# Set the working directory to /app
|
10 |
+
WORKDIR /app
|
11 |
+
|
12 |
+
# Set the shell to bash
|
13 |
+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
14 |
+
|
15 |
+
# Install build dependencies
|
16 |
+
RUN apt-get clean && apt-get update && \
|
17 |
+
apt-get install -y gcc python3-dev && \
|
18 |
+
rm -rf /var/lib/apt/lists/*
|
19 |
+
|
20 |
+
RUN pip install --no-cache-dir --upgrade pip && \
|
21 |
+
pip install --no-cache-dir build
|
22 |
+
|
23 |
+
# Copy the current directory contents into the container at /app
|
24 |
+
COPY . .
|
25 |
+
|
26 |
+
# Build Admin UI
|
27 |
+
RUN chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
28 |
+
|
29 |
+
# Build the package
|
30 |
+
RUN rm -rf dist/* && python -m build
|
31 |
+
|
32 |
+
# There should be only one wheel file now, assume the build only creates one
|
33 |
+
RUN ls -1 dist/*.whl | head -1
|
34 |
+
|
35 |
+
# Install the package
|
36 |
+
RUN pip install dist/*.whl
|
37 |
+
|
38 |
+
# install dependencies as wheels
|
39 |
+
RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt
|
40 |
+
|
41 |
+
# Runtime stage
|
42 |
+
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
43 |
+
|
44 |
+
# Update dependencies and clean up - handles debian security issue
|
45 |
+
RUN apt-get update && apt-get upgrade -y && rm -rf /var/lib/apt/lists/*
|
46 |
+
|
47 |
+
WORKDIR /app
|
48 |
+
# Copy the current directory contents into the container at /app
|
49 |
+
COPY . .
|
50 |
+
RUN ls -la /app
|
51 |
+
|
52 |
+
# Copy the built wheel from the builder stage to the runtime stage; assumes only one wheel file is present
|
53 |
+
COPY --from=builder /app/dist/*.whl .
|
54 |
+
COPY --from=builder /wheels/ /wheels/
|
55 |
+
|
56 |
+
# Install the built wheel using pip; again using a wildcard if it's the only file
|
57 |
+
RUN pip install *.whl /wheels/* --no-index --find-links=/wheels/ && rm -f *.whl && rm -rf /wheels
|
58 |
+
|
59 |
+
# install semantic-cache [Experimental]- we need this here and not in requirements.txt because redisvl pins to pydantic 1.0
|
60 |
+
# ensure pyjwt is used, not jwt
|
61 |
+
RUN pip install redisvl==0.0.7 --no-deps --no-cache-dir && \
|
62 |
+
pip uninstall jwt -y && \
|
63 |
+
pip uninstall PyJWT -y && \
|
64 |
+
pip install PyJWT==2.9.0 --no-cache-dir
|
65 |
+
|
66 |
+
# Build Admin UI
|
67 |
+
RUN chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
68 |
+
|
69 |
+
### Prisma Handling for Non-Root #################################################
|
70 |
+
# Prisma allows you to specify the binary cache directory to use
|
71 |
+
ENV PRISMA_BINARY_CACHE_DIR=/nonexistent
|
72 |
+
|
73 |
+
RUN pip install --no-cache-dir nodejs-bin prisma
|
74 |
+
|
75 |
+
# Make a /non-existent folder and assign chown to nobody
|
76 |
+
RUN mkdir -p /nonexistent && \
|
77 |
+
chown -R nobody:nogroup /app && \
|
78 |
+
chown -R nobody:nogroup /nonexistent && \
|
79 |
+
chown -R nobody:nogroup /usr/local/lib/python3.13/site-packages/prisma/
|
80 |
+
|
81 |
+
RUN chmod +x docker/entrypoint.sh
|
82 |
+
RUN chmod +x docker/prod_entrypoint.sh
|
83 |
+
|
84 |
+
# Run Prisma generate as user = nobody
|
85 |
+
USER nobody
|
86 |
+
|
87 |
+
RUN prisma generate
|
88 |
+
### End of Prisma Handling for Non-Root #########################################
|
89 |
+
|
90 |
+
EXPOSE 4000/tcp
|
91 |
+
|
92 |
+
# # Set your entrypoint and command
|
93 |
+
ENTRYPOINT ["docker/prod_entrypoint.sh"]
|
94 |
+
|
95 |
+
# Append "--detailed_debug" to the end of CMD to view detailed debug logs
|
96 |
+
# CMD ["--port", "4000", "--detailed_debug"]
|
97 |
+
CMD ["--port", "4000"]
|
LICENSE
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Portions of this software are licensed as follows:
|
2 |
+
|
3 |
+
* All content that resides under the "enterprise/" directory of this repository, if that directory exists, is licensed under the license defined in "enterprise/LICENSE".
|
4 |
+
* Content outside of the above mentioned directories or restrictions above is available under the MIT license as defined below.
|
5 |
+
---
|
6 |
+
MIT License
|
7 |
+
|
8 |
+
Copyright (c) 2023 Berri AI
|
9 |
+
|
10 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11 |
+
of this software and associated documentation files (the "Software"), to deal
|
12 |
+
in the Software without restriction, including without limitation the rights
|
13 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14 |
+
copies of the Software, and to permit persons to whom the Software is
|
15 |
+
furnished to do so, subject to the following conditions:
|
16 |
+
|
17 |
+
The above copyright notice and this permission notice shall be included in all
|
18 |
+
copies or substantial portions of the Software.
|
19 |
+
|
20 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26 |
+
SOFTWARE.
|
README.md
CHANGED
@@ -1,11 +1,8 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: docker
|
7 |
-
|
8 |
-
license: mit
|
9 |
---
|
10 |
-
|
11 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: litellm
|
3 |
+
emoji: 🐳
|
4 |
+
colorFrom: purple
|
5 |
+
colorTo: gray
|
6 |
sdk: docker
|
7 |
+
app_port: 4000
|
|
|
8 |
---
|
|
|
|
ci_cd/check_file_length.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
|
3 |
+
|
4 |
+
def check_file_length(max_lines, filenames):
|
5 |
+
bad_files = []
|
6 |
+
for filename in filenames:
|
7 |
+
with open(filename, "r") as file:
|
8 |
+
lines = file.readlines()
|
9 |
+
if len(lines) > max_lines:
|
10 |
+
bad_files.append((filename, len(lines)))
|
11 |
+
return bad_files
|
12 |
+
|
13 |
+
|
14 |
+
if __name__ == "__main__":
|
15 |
+
max_lines = int(sys.argv[1])
|
16 |
+
filenames = sys.argv[2:]
|
17 |
+
|
18 |
+
bad_files = check_file_length(max_lines, filenames)
|
19 |
+
if bad_files:
|
20 |
+
bad_files.sort(
|
21 |
+
key=lambda x: x[1], reverse=True
|
22 |
+
) # Sort files by length in descending order
|
23 |
+
for filename, length in bad_files:
|
24 |
+
print(f"{filename}: {length} lines")
|
25 |
+
|
26 |
+
sys.exit(1)
|
27 |
+
else:
|
28 |
+
sys.exit(0)
|
ci_cd/check_files_match.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
import filecmp
|
3 |
+
import shutil
|
4 |
+
|
5 |
+
|
6 |
+
def main(argv=None):
|
7 |
+
print(
|
8 |
+
"Comparing model_prices_and_context_window and litellm/model_prices_and_context_window_backup.json files... checking if they match."
|
9 |
+
)
|
10 |
+
|
11 |
+
file1 = "model_prices_and_context_window.json"
|
12 |
+
file2 = "litellm/model_prices_and_context_window_backup.json"
|
13 |
+
|
14 |
+
cmp_result = filecmp.cmp(file1, file2, shallow=False)
|
15 |
+
|
16 |
+
if cmp_result:
|
17 |
+
print(f"Passed! Files {file1} and {file2} match.")
|
18 |
+
return 0
|
19 |
+
else:
|
20 |
+
print(
|
21 |
+
f"Failed! Files {file1} and {file2} do not match. Copying content from {file1} to {file2}."
|
22 |
+
)
|
23 |
+
copy_content(file1, file2)
|
24 |
+
return 1
|
25 |
+
|
26 |
+
|
27 |
+
def copy_content(source, destination):
|
28 |
+
shutil.copy2(source, destination)
|
29 |
+
|
30 |
+
|
31 |
+
if __name__ == "__main__":
|
32 |
+
sys.exit(main())
|
codecov.yaml
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
component_management:
|
2 |
+
individual_components:
|
3 |
+
- component_id: "Router"
|
4 |
+
paths:
|
5 |
+
- "router"
|
6 |
+
- component_id: "LLMs"
|
7 |
+
paths:
|
8 |
+
- "*/llms/*"
|
9 |
+
- component_id: "Caching"
|
10 |
+
paths:
|
11 |
+
- "*/caching/*"
|
12 |
+
- ".*redis.*"
|
13 |
+
- component_id: "litellm_logging"
|
14 |
+
paths:
|
15 |
+
- "*/integrations/*"
|
16 |
+
- ".*litellm_logging.*"
|
17 |
+
- component_id: "Proxy_Authentication"
|
18 |
+
paths:
|
19 |
+
- "*/proxy/auth/**"
|
20 |
+
comment:
|
21 |
+
layout: "header, diff, flags, components" # show component info in the PR comment
|
22 |
+
|
23 |
+
coverage:
|
24 |
+
status:
|
25 |
+
project:
|
26 |
+
default:
|
27 |
+
target: auto
|
28 |
+
threshold: 1% # at maximum allow project coverage to drop by 1%
|
29 |
+
patch:
|
30 |
+
default:
|
31 |
+
target: auto
|
32 |
+
threshold: 0% # patch coverage should be 100%
|
db_scripts/create_views.py
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
python script to pre-create all views required by LiteLLM Proxy Server
|
3 |
+
"""
|
4 |
+
|
5 |
+
import asyncio
|
6 |
+
|
7 |
+
# Enter your DATABASE_URL here
|
8 |
+
|
9 |
+
from prisma import Prisma
|
10 |
+
|
11 |
+
db = Prisma(
|
12 |
+
http={
|
13 |
+
"timeout": 60000,
|
14 |
+
},
|
15 |
+
)
|
16 |
+
|
17 |
+
|
18 |
+
async def check_view_exists(): # noqa: PLR0915
|
19 |
+
"""
|
20 |
+
Checks if the LiteLLM_VerificationTokenView and MonthlyGlobalSpend exists in the user's db.
|
21 |
+
|
22 |
+
LiteLLM_VerificationTokenView: This view is used for getting the token + team data in user_api_key_auth
|
23 |
+
|
24 |
+
MonthlyGlobalSpend: This view is used for the admin view to see global spend for this month
|
25 |
+
|
26 |
+
If the view doesn't exist, one will be created.
|
27 |
+
"""
|
28 |
+
|
29 |
+
# connect to dB
|
30 |
+
await db.connect()
|
31 |
+
try:
|
32 |
+
# Try to select one row from the view
|
33 |
+
await db.query_raw("""SELECT 1 FROM "LiteLLM_VerificationTokenView" LIMIT 1""")
|
34 |
+
print("LiteLLM_VerificationTokenView Exists!") # noqa
|
35 |
+
except Exception:
|
36 |
+
# If an error occurs, the view does not exist, so create it
|
37 |
+
await db.execute_raw(
|
38 |
+
"""
|
39 |
+
CREATE VIEW "LiteLLM_VerificationTokenView" AS
|
40 |
+
SELECT
|
41 |
+
v.*,
|
42 |
+
t.spend AS team_spend,
|
43 |
+
t.max_budget AS team_max_budget,
|
44 |
+
t.tpm_limit AS team_tpm_limit,
|
45 |
+
t.rpm_limit AS team_rpm_limit
|
46 |
+
FROM "LiteLLM_VerificationToken" v
|
47 |
+
LEFT JOIN "LiteLLM_TeamTable" t ON v.team_id = t.team_id;
|
48 |
+
"""
|
49 |
+
)
|
50 |
+
|
51 |
+
print("LiteLLM_VerificationTokenView Created!") # noqa
|
52 |
+
|
53 |
+
try:
|
54 |
+
await db.query_raw("""SELECT 1 FROM "MonthlyGlobalSpend" LIMIT 1""")
|
55 |
+
print("MonthlyGlobalSpend Exists!") # noqa
|
56 |
+
except Exception:
|
57 |
+
sql_query = """
|
58 |
+
CREATE OR REPLACE VIEW "MonthlyGlobalSpend" AS
|
59 |
+
SELECT
|
60 |
+
DATE("startTime") AS date,
|
61 |
+
SUM("spend") AS spend
|
62 |
+
FROM
|
63 |
+
"LiteLLM_SpendLogs"
|
64 |
+
WHERE
|
65 |
+
"startTime" >= (CURRENT_DATE - INTERVAL '30 days')
|
66 |
+
GROUP BY
|
67 |
+
DATE("startTime");
|
68 |
+
"""
|
69 |
+
await db.execute_raw(query=sql_query)
|
70 |
+
|
71 |
+
print("MonthlyGlobalSpend Created!") # noqa
|
72 |
+
|
73 |
+
try:
|
74 |
+
await db.query_raw("""SELECT 1 FROM "Last30dKeysBySpend" LIMIT 1""")
|
75 |
+
print("Last30dKeysBySpend Exists!") # noqa
|
76 |
+
except Exception:
|
77 |
+
sql_query = """
|
78 |
+
CREATE OR REPLACE VIEW "Last30dKeysBySpend" AS
|
79 |
+
SELECT
|
80 |
+
L."api_key",
|
81 |
+
V."key_alias",
|
82 |
+
V."key_name",
|
83 |
+
SUM(L."spend") AS total_spend
|
84 |
+
FROM
|
85 |
+
"LiteLLM_SpendLogs" L
|
86 |
+
LEFT JOIN
|
87 |
+
"LiteLLM_VerificationToken" V
|
88 |
+
ON
|
89 |
+
L."api_key" = V."token"
|
90 |
+
WHERE
|
91 |
+
L."startTime" >= (CURRENT_DATE - INTERVAL '30 days')
|
92 |
+
GROUP BY
|
93 |
+
L."api_key", V."key_alias", V."key_name"
|
94 |
+
ORDER BY
|
95 |
+
total_spend DESC;
|
96 |
+
"""
|
97 |
+
await db.execute_raw(query=sql_query)
|
98 |
+
|
99 |
+
print("Last30dKeysBySpend Created!") # noqa
|
100 |
+
|
101 |
+
try:
|
102 |
+
await db.query_raw("""SELECT 1 FROM "Last30dModelsBySpend" LIMIT 1""")
|
103 |
+
print("Last30dModelsBySpend Exists!") # noqa
|
104 |
+
except Exception:
|
105 |
+
sql_query = """
|
106 |
+
CREATE OR REPLACE VIEW "Last30dModelsBySpend" AS
|
107 |
+
SELECT
|
108 |
+
"model",
|
109 |
+
SUM("spend") AS total_spend
|
110 |
+
FROM
|
111 |
+
"LiteLLM_SpendLogs"
|
112 |
+
WHERE
|
113 |
+
"startTime" >= (CURRENT_DATE - INTERVAL '30 days')
|
114 |
+
AND "model" != ''
|
115 |
+
GROUP BY
|
116 |
+
"model"
|
117 |
+
ORDER BY
|
118 |
+
total_spend DESC;
|
119 |
+
"""
|
120 |
+
await db.execute_raw(query=sql_query)
|
121 |
+
|
122 |
+
print("Last30dModelsBySpend Created!") # noqa
|
123 |
+
try:
|
124 |
+
await db.query_raw("""SELECT 1 FROM "MonthlyGlobalSpendPerKey" LIMIT 1""")
|
125 |
+
print("MonthlyGlobalSpendPerKey Exists!") # noqa
|
126 |
+
except Exception:
|
127 |
+
sql_query = """
|
128 |
+
CREATE OR REPLACE VIEW "MonthlyGlobalSpendPerKey" AS
|
129 |
+
SELECT
|
130 |
+
DATE("startTime") AS date,
|
131 |
+
SUM("spend") AS spend,
|
132 |
+
api_key as api_key
|
133 |
+
FROM
|
134 |
+
"LiteLLM_SpendLogs"
|
135 |
+
WHERE
|
136 |
+
"startTime" >= (CURRENT_DATE - INTERVAL '30 days')
|
137 |
+
GROUP BY
|
138 |
+
DATE("startTime"),
|
139 |
+
api_key;
|
140 |
+
"""
|
141 |
+
await db.execute_raw(query=sql_query)
|
142 |
+
|
143 |
+
print("MonthlyGlobalSpendPerKey Created!") # noqa
|
144 |
+
try:
|
145 |
+
await db.query_raw(
|
146 |
+
"""SELECT 1 FROM "MonthlyGlobalSpendPerUserPerKey" LIMIT 1"""
|
147 |
+
)
|
148 |
+
print("MonthlyGlobalSpendPerUserPerKey Exists!") # noqa
|
149 |
+
except Exception:
|
150 |
+
sql_query = """
|
151 |
+
CREATE OR REPLACE VIEW "MonthlyGlobalSpendPerUserPerKey" AS
|
152 |
+
SELECT
|
153 |
+
DATE("startTime") AS date,
|
154 |
+
SUM("spend") AS spend,
|
155 |
+
api_key as api_key,
|
156 |
+
"user" as "user"
|
157 |
+
FROM
|
158 |
+
"LiteLLM_SpendLogs"
|
159 |
+
WHERE
|
160 |
+
"startTime" >= (CURRENT_DATE - INTERVAL '30 days')
|
161 |
+
GROUP BY
|
162 |
+
DATE("startTime"),
|
163 |
+
"user",
|
164 |
+
api_key;
|
165 |
+
"""
|
166 |
+
await db.execute_raw(query=sql_query)
|
167 |
+
|
168 |
+
print("MonthlyGlobalSpendPerUserPerKey Created!") # noqa
|
169 |
+
|
170 |
+
try:
|
171 |
+
await db.query_raw("""SELECT 1 FROM "DailyTagSpend" LIMIT 1""")
|
172 |
+
print("DailyTagSpend Exists!") # noqa
|
173 |
+
except Exception:
|
174 |
+
sql_query = """
|
175 |
+
CREATE OR REPLACE VIEW "DailyTagSpend" AS
|
176 |
+
SELECT
|
177 |
+
jsonb_array_elements_text(request_tags) AS individual_request_tag,
|
178 |
+
DATE(s."startTime") AS spend_date,
|
179 |
+
COUNT(*) AS log_count,
|
180 |
+
SUM(spend) AS total_spend
|
181 |
+
FROM "LiteLLM_SpendLogs" s
|
182 |
+
GROUP BY individual_request_tag, DATE(s."startTime");
|
183 |
+
"""
|
184 |
+
await db.execute_raw(query=sql_query)
|
185 |
+
|
186 |
+
print("DailyTagSpend Created!") # noqa
|
187 |
+
|
188 |
+
try:
|
189 |
+
await db.query_raw("""SELECT 1 FROM "Last30dTopEndUsersSpend" LIMIT 1""")
|
190 |
+
print("Last30dTopEndUsersSpend Exists!") # noqa
|
191 |
+
except Exception:
|
192 |
+
sql_query = """
|
193 |
+
CREATE VIEW "Last30dTopEndUsersSpend" AS
|
194 |
+
SELECT end_user, COUNT(*) AS total_events, SUM(spend) AS total_spend
|
195 |
+
FROM "LiteLLM_SpendLogs"
|
196 |
+
WHERE end_user <> '' AND end_user <> user
|
197 |
+
AND "startTime" >= CURRENT_DATE - INTERVAL '30 days'
|
198 |
+
GROUP BY end_user
|
199 |
+
ORDER BY total_spend DESC
|
200 |
+
LIMIT 100;
|
201 |
+
"""
|
202 |
+
await db.execute_raw(query=sql_query)
|
203 |
+
|
204 |
+
print("Last30dTopEndUsersSpend Created!") # noqa
|
205 |
+
|
206 |
+
return
|
207 |
+
|
208 |
+
|
209 |
+
asyncio.run(check_view_exists())
|
db_scripts/update_unassigned_teams.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from prisma import Prisma
|
2 |
+
from litellm._logging import verbose_logger
|
3 |
+
|
4 |
+
|
5 |
+
async def apply_db_fixes(db: Prisma):
|
6 |
+
"""
|
7 |
+
Do Not Run this in production, only use it as a one-time fix
|
8 |
+
"""
|
9 |
+
verbose_logger.warning(
|
10 |
+
"DO NOT run this in Production....Running update_unassigned_teams"
|
11 |
+
)
|
12 |
+
try:
|
13 |
+
sql_query = """
|
14 |
+
UPDATE "LiteLLM_SpendLogs"
|
15 |
+
SET team_id = (
|
16 |
+
SELECT vt.team_id
|
17 |
+
FROM "LiteLLM_VerificationToken" vt
|
18 |
+
WHERE vt.token = "LiteLLM_SpendLogs".api_key
|
19 |
+
)
|
20 |
+
WHERE team_id IS NULL
|
21 |
+
AND EXISTS (
|
22 |
+
SELECT 1
|
23 |
+
FROM "LiteLLM_VerificationToken" vt
|
24 |
+
WHERE vt.token = "LiteLLM_SpendLogs".api_key
|
25 |
+
);
|
26 |
+
"""
|
27 |
+
response = await db.query_raw(sql_query)
|
28 |
+
print(
|
29 |
+
"Updated unassigned teams, Response=%s",
|
30 |
+
response,
|
31 |
+
)
|
32 |
+
except Exception as e:
|
33 |
+
raise Exception(f"Error apply_db_fixes: {str(e)}")
|
34 |
+
return
|
deploy/Dockerfile.ghcr_base
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use the provided base image
|
2 |
+
FROM ghcr.io/berriai/litellm:main-latest
|
3 |
+
|
4 |
+
# Set the working directory to /app
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Copy the configuration file into the container at /app
|
8 |
+
COPY config.yaml .
|
9 |
+
|
10 |
+
# Make sure your docker/entrypoint.sh is executable
|
11 |
+
RUN chmod +x docker/entrypoint.sh
|
12 |
+
|
13 |
+
# Expose the necessary port
|
14 |
+
EXPOSE 4000/tcp
|
15 |
+
|
16 |
+
# Override the CMD instruction with your desired command and arguments
|
17 |
+
CMD ["--port", "4000", "--config", "config.yaml", "--detailed_debug", "--run_gunicorn"]
|
deploy/azure_resource_manager/azure_marketplace.zip
ADDED
Binary file (2.37 kB). View file
|
|
deploy/azure_resource_manager/azure_marketplace/createUiDefinition.json
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
|
3 |
+
"handler": "Microsoft.Azure.CreateUIDef",
|
4 |
+
"version": "0.1.2-preview",
|
5 |
+
"parameters": {
|
6 |
+
"config": {
|
7 |
+
"isWizard": false,
|
8 |
+
"basics": { }
|
9 |
+
},
|
10 |
+
"basics": [ ],
|
11 |
+
"steps": [ ],
|
12 |
+
"outputs": { },
|
13 |
+
"resourceTypes": [ ]
|
14 |
+
}
|
15 |
+
}
|
deploy/azure_resource_manager/azure_marketplace/mainTemplate.json
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
3 |
+
"contentVersion": "1.0.0.0",
|
4 |
+
"parameters": {
|
5 |
+
"imageName": {
|
6 |
+
"type": "string",
|
7 |
+
"defaultValue": "ghcr.io/berriai/litellm:main-latest"
|
8 |
+
},
|
9 |
+
"containerName": {
|
10 |
+
"type": "string",
|
11 |
+
"defaultValue": "litellm-container"
|
12 |
+
},
|
13 |
+
"dnsLabelName": {
|
14 |
+
"type": "string",
|
15 |
+
"defaultValue": "litellm"
|
16 |
+
},
|
17 |
+
"portNumber": {
|
18 |
+
"type": "int",
|
19 |
+
"defaultValue": 4000
|
20 |
+
}
|
21 |
+
},
|
22 |
+
"resources": [
|
23 |
+
{
|
24 |
+
"type": "Microsoft.ContainerInstance/containerGroups",
|
25 |
+
"apiVersion": "2021-03-01",
|
26 |
+
"name": "[parameters('containerName')]",
|
27 |
+
"location": "[resourceGroup().location]",
|
28 |
+
"properties": {
|
29 |
+
"containers": [
|
30 |
+
{
|
31 |
+
"name": "[parameters('containerName')]",
|
32 |
+
"properties": {
|
33 |
+
"image": "[parameters('imageName')]",
|
34 |
+
"resources": {
|
35 |
+
"requests": {
|
36 |
+
"cpu": 1,
|
37 |
+
"memoryInGB": 2
|
38 |
+
}
|
39 |
+
},
|
40 |
+
"ports": [
|
41 |
+
{
|
42 |
+
"port": "[parameters('portNumber')]"
|
43 |
+
}
|
44 |
+
]
|
45 |
+
}
|
46 |
+
}
|
47 |
+
],
|
48 |
+
"osType": "Linux",
|
49 |
+
"restartPolicy": "Always",
|
50 |
+
"ipAddress": {
|
51 |
+
"type": "Public",
|
52 |
+
"ports": [
|
53 |
+
{
|
54 |
+
"protocol": "tcp",
|
55 |
+
"port": "[parameters('portNumber')]"
|
56 |
+
}
|
57 |
+
],
|
58 |
+
"dnsNameLabel": "[parameters('dnsLabelName')]"
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
]
|
63 |
+
}
|
deploy/azure_resource_manager/main.bicep
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param imageName string = 'ghcr.io/berriai/litellm:main-latest'
|
2 |
+
param containerName string = 'litellm-container'
|
3 |
+
param dnsLabelName string = 'litellm'
|
4 |
+
param portNumber int = 4000
|
5 |
+
|
6 |
+
resource containerGroupName 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = {
|
7 |
+
name: containerName
|
8 |
+
location: resourceGroup().location
|
9 |
+
properties: {
|
10 |
+
containers: [
|
11 |
+
{
|
12 |
+
name: containerName
|
13 |
+
properties: {
|
14 |
+
image: imageName
|
15 |
+
resources: {
|
16 |
+
requests: {
|
17 |
+
cpu: 1
|
18 |
+
memoryInGB: 2
|
19 |
+
}
|
20 |
+
}
|
21 |
+
ports: [
|
22 |
+
{
|
23 |
+
port: portNumber
|
24 |
+
}
|
25 |
+
]
|
26 |
+
}
|
27 |
+
}
|
28 |
+
]
|
29 |
+
osType: 'Linux'
|
30 |
+
restartPolicy: 'Always'
|
31 |
+
ipAddress: {
|
32 |
+
type: 'Public'
|
33 |
+
ports: [
|
34 |
+
{
|
35 |
+
protocol: 'tcp'
|
36 |
+
port: portNumber
|
37 |
+
}
|
38 |
+
]
|
39 |
+
dnsNameLabel: dnsLabelName
|
40 |
+
}
|
41 |
+
}
|
42 |
+
}
|
deploy/charts/litellm-helm/.helmignore
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Patterns to ignore when building packages.
|
2 |
+
# This supports shell glob matching, relative path matching, and
|
3 |
+
# negation (prefixed with !). Only one pattern per line.
|
4 |
+
.DS_Store
|
5 |
+
# Common VCS dirs
|
6 |
+
.git/
|
7 |
+
.gitignore
|
8 |
+
.bzr/
|
9 |
+
.bzrignore
|
10 |
+
.hg/
|
11 |
+
.hgignore
|
12 |
+
.svn/
|
13 |
+
# Common backup files
|
14 |
+
*.swp
|
15 |
+
*.bak
|
16 |
+
*.tmp
|
17 |
+
*.orig
|
18 |
+
*~
|
19 |
+
# Various IDEs
|
20 |
+
.project
|
21 |
+
.idea/
|
22 |
+
*.tmproj
|
23 |
+
.vscode/
|
deploy/charts/litellm-helm/Chart.lock
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
dependencies:
|
2 |
+
- name: postgresql
|
3 |
+
repository: oci://registry-1.docker.io/bitnamicharts
|
4 |
+
version: 14.3.1
|
5 |
+
- name: redis
|
6 |
+
repository: oci://registry-1.docker.io/bitnamicharts
|
7 |
+
version: 18.19.1
|
8 |
+
digest: sha256:8660fe6287f9941d08c0902f3f13731079b8cecd2a5da2fbc54e5b7aae4a6f62
|
9 |
+
generated: "2024-03-10T02:28:52.275022+05:30"
|
deploy/charts/litellm-helm/Chart.yaml
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apiVersion: v2
|
2 |
+
|
3 |
+
# We can't call ourselves just "litellm" because then we couldn't publish to the
|
4 |
+
# same OCI repository as the "litellm" OCI image
|
5 |
+
name: litellm-helm
|
6 |
+
description: Call all LLM APIs using the OpenAI format
|
7 |
+
|
8 |
+
# A chart can be either an 'application' or a 'library' chart.
|
9 |
+
#
|
10 |
+
# Application charts are a collection of templates that can be packaged into versioned archives
|
11 |
+
# to be deployed.
|
12 |
+
#
|
13 |
+
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
14 |
+
# a dependency of application charts to inject those utilities and functions into the rendering
|
15 |
+
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
16 |
+
type: application
|
17 |
+
|
18 |
+
# This is the chart version. This version number should be incremented each time you make changes
|
19 |
+
# to the chart and its templates, including the app version.
|
20 |
+
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
21 |
+
version: 0.3.0
|
22 |
+
|
23 |
+
# This is the version number of the application being deployed. This version number should be
|
24 |
+
# incremented each time you make changes to the application. Versions are not expected to
|
25 |
+
# follow Semantic Versioning. They should reflect the version the application is using.
|
26 |
+
# It is recommended to use it with quotes.
|
27 |
+
appVersion: v1.50.2
|
28 |
+
|
29 |
+
dependencies:
|
30 |
+
- name: "postgresql"
|
31 |
+
version: ">=13.3.0"
|
32 |
+
repository: oci://registry-1.docker.io/bitnamicharts
|
33 |
+
condition: db.deployStandalone
|
34 |
+
- name: redis
|
35 |
+
version: ">=18.0.0"
|
36 |
+
repository: oci://registry-1.docker.io/bitnamicharts
|
37 |
+
condition: redis.enabled
|
deploy/charts/litellm-helm/README.md
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Helm Chart for LiteLLM
|
2 |
+
|
3 |
+
> [!IMPORTANT]
|
4 |
+
> This is community maintained, Please make an issue if you run into a bug
|
5 |
+
> We recommend using [Docker or Kubernetes for production deployments](https://docs.litellm.ai/docs/proxy/prod)
|
6 |
+
|
7 |
+
## Prerequisites
|
8 |
+
|
9 |
+
- Kubernetes 1.21+
|
10 |
+
- Helm 3.8.0+
|
11 |
+
|
12 |
+
If `db.deployStandalone` is used:
|
13 |
+
- PV provisioner support in the underlying infrastructure
|
14 |
+
|
15 |
+
If `db.useStackgresOperator` is used (not yet implemented):
|
16 |
+
- The Stackgres Operator must already be installed in the Kubernetes Cluster. This chart will **not** install the operator if it is missing.
|
17 |
+
|
18 |
+
## Parameters
|
19 |
+
|
20 |
+
### LiteLLM Proxy Deployment Settings
|
21 |
+
|
22 |
+
| Name | Description | Value |
|
23 |
+
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
24 |
+
| `replicaCount` | The number of LiteLLM Proxy pods to be deployed | `1` |
|
25 |
+
| `masterkey` | The Master API Key for LiteLLM. If not specified, a random key is generated. | N/A |
|
26 |
+
| `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. | `[]` |
|
27 |
+
| `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. | `[]` |
|
28 |
+
| `image.repository` | LiteLLM Proxy image repository | `ghcr.io/berriai/litellm` |
|
29 |
+
| `image.pullPolicy` | LiteLLM Proxy image pull policy | `IfNotPresent` |
|
30 |
+
| `image.tag` | Overrides the image tag whose default the latest version of LiteLLM at the time this chart was published. | `""` |
|
31 |
+
| `imagePullSecrets` | Registry credentials for the LiteLLM and initContainer images. | `[]` |
|
32 |
+
| `serviceAccount.create` | Whether or not to create a Kubernetes Service Account for this deployment. The default is `false` because LiteLLM has no need to access the Kubernetes API. | `false` |
|
33 |
+
| `service.type` | Kubernetes Service type (e.g. `LoadBalancer`, `ClusterIP`, etc.) | `ClusterIP` |
|
34 |
+
| `service.port` | TCP port that the Kubernetes Service will listen on. Also the TCP port within the Pod that the proxy will listen on. | `4000` |
|
35 |
+
| `ingress.*` | See [values.yaml](./values.yaml) for example settings | N/A |
|
36 |
+
| `proxy_config.*` | See [values.yaml](./values.yaml) for default settings. See [example_config_yaml](../../../litellm/proxy/example_config_yaml/) for configuration examples. | N/A |
|
37 |
+
| `extraContainers[]` | An array of additional containers to be deployed as sidecars alongside the LiteLLM Proxy. | `[]` |
|
38 |
+
|
39 |
+
#### Example `environmentSecrets` Secret
|
40 |
+
|
41 |
+
```
|
42 |
+
apiVersion: v1
|
43 |
+
kind: Secret
|
44 |
+
metadata:
|
45 |
+
name: litellm-envsecrets
|
46 |
+
data:
|
47 |
+
AZURE_OPENAI_API_KEY: TXlTZWN1cmVLM3k=
|
48 |
+
type: Opaque
|
49 |
+
```
|
50 |
+
|
51 |
+
### Database Settings
|
52 |
+
| Name | Description | Value |
|
53 |
+
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
54 |
+
| `db.useExisting` | Use an existing Postgres database. A Kubernetes Secret object must exist that contains credentials for connecting to the database. An example secret object definition is provided below. | `false` |
|
55 |
+
| `db.endpoint` | If `db.useExisting` is `true`, this is the IP, Hostname or Service Name of the Postgres server to connect to. | `localhost` |
|
56 |
+
| `db.database` | If `db.useExisting` is `true`, the name of the existing database to connect to. | `litellm` |
|
57 |
+
| `db.url` | If `db.useExisting` is `true`, the connection url of the existing database to connect to can be overwritten with this value. | `postgresql://$(DATABASE_USERNAME):$(DATABASE_PASSWORD)@$(DATABASE_HOST)/$(DATABASE_NAME)` |
|
58 |
+
| `db.secret.name` | If `db.useExisting` is `true`, the name of the Kubernetes Secret that contains credentials. | `postgres` |
|
59 |
+
| `db.secret.usernameKey` | If `db.useExisting` is `true`, the name of the key within the Kubernetes Secret that holds the username for authenticating with the Postgres instance. | `username` |
|
60 |
+
| `db.secret.passwordKey` | If `db.useExisting` is `true`, the name of the key within the Kubernetes Secret that holds the password associates with the above user. | `password` |
|
61 |
+
| `db.useStackgresOperator` | Not yet implemented. | `false` |
|
62 |
+
| `db.deployStandalone` | Deploy a standalone, single instance deployment of Postgres, using the Bitnami postgresql chart. This is useful for getting started but doesn't provide HA or (by default) data backups. | `true` |
|
63 |
+
| `postgresql.*` | If `db.deployStandalone` is `true`, configuration passed to the Bitnami postgresql chart. See the [Bitnami Documentation](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) for full configuration details. See [values.yaml](./values.yaml) for the default configuration. | See [values.yaml](./values.yaml) |
|
64 |
+
| `postgresql.auth.*` | If `db.deployStandalone` is `true`, care should be taken to ensure the default `password` and `postgres-password` values are **NOT** used. | `NoTaGrEaTpAsSwOrD` |
|
65 |
+
|
66 |
+
#### Example Postgres `db.useExisting` Secret
|
67 |
+
```yaml
|
68 |
+
apiVersion: v1
|
69 |
+
kind: Secret
|
70 |
+
metadata:
|
71 |
+
name: postgres
|
72 |
+
data:
|
73 |
+
# Password for the "postgres" user
|
74 |
+
postgres-password: <some secure password, base64 encoded>
|
75 |
+
username: litellm
|
76 |
+
password: <some secure password, base64 encoded>
|
77 |
+
type: Opaque
|
78 |
+
```
|
79 |
+
|
80 |
+
#### Examples for `environmentSecrets` and `environemntConfigMaps`
|
81 |
+
|
82 |
+
```yaml
|
83 |
+
# Use config map for not-secret configuration data
|
84 |
+
apiVersion: v1
|
85 |
+
kind: ConfigMap
|
86 |
+
metadata:
|
87 |
+
name: litellm-env-configmap
|
88 |
+
data:
|
89 |
+
SOME_KEY: someValue
|
90 |
+
ANOTHER_KEY: anotherValue
|
91 |
+
```
|
92 |
+
|
93 |
+
```yaml
|
94 |
+
# Use secrets for things which are actually secret like API keys, credentials, etc
|
95 |
+
# Base64 encode the values stored in a Kubernetes Secret: $ pbpaste | base64 | pbcopy
|
96 |
+
# The --decode flag is convenient: $ pbpaste | base64 --decode
|
97 |
+
|
98 |
+
apiVersion: v1
|
99 |
+
kind: Secret
|
100 |
+
metadata:
|
101 |
+
name: litellm-env-secret
|
102 |
+
type: Opaque
|
103 |
+
data:
|
104 |
+
SOME_PASSWORD: cDZbUGVXeU5e0ZW # base64 encoded
|
105 |
+
ANOTHER_PASSWORD: AAZbUGVXeU5e0ZB # base64 encoded
|
106 |
+
```
|
107 |
+
|
108 |
+
Source: [GitHub Gist from troyharvey](https://gist.github.com/troyharvey/4506472732157221e04c6b15e3b3f094)
|
109 |
+
|
110 |
+
## Accessing the Admin UI
|
111 |
+
When browsing to the URL published per the settings in `ingress.*`, you will
|
112 |
+
be prompted for **Admin Configuration**. The **Proxy Endpoint** is the internal
|
113 |
+
(from the `litellm` pod's perspective) URL published by the `<RELEASE>-litellm`
|
114 |
+
Kubernetes Service. If the deployment uses the default settings for this
|
115 |
+
service, the **Proxy Endpoint** should be set to `http://<RELEASE>-litellm:4000`.
|
116 |
+
|
117 |
+
The **Proxy Key** is the value specified for `masterkey` or, if a `masterkey`
|
118 |
+
was not provided to the helm command line, the `masterkey` is a randomly
|
119 |
+
generated string stored in the `<RELEASE>-litellm-masterkey` Kubernetes Secret.
|
120 |
+
|
121 |
+
```bash
|
122 |
+
kubectl -n litellm get secret <RELEASE>-litellm-masterkey -o jsonpath="{.data.masterkey}"
|
123 |
+
```
|
124 |
+
|
125 |
+
## Admin UI Limitations
|
126 |
+
At the time of writing, the Admin UI is unable to add models. This is because
|
127 |
+
it would need to update the `config.yaml` file which is a exposed ConfigMap, and
|
128 |
+
therefore, read-only. This is a limitation of this helm chart, not the Admin UI
|
129 |
+
itself.
|
deploy/charts/litellm-helm/charts/postgresql-14.3.1.tgz
ADDED
Binary file (72.9 kB). View file
|
|