Raju2024 commited on
Commit
e3278e4
·
verified ·
1 Parent(s): 2f1caf5

Upload 1072 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .circleci/config.yml +2232 -0
  2. .circleci/requirements.txt +13 -0
  3. .devcontainer/devcontainer.json +52 -0
  4. .dockerignore +12 -0
  5. .env.example +22 -0
  6. .flake8 +46 -0
  7. .git-blame-ignore-revs +10 -0
  8. .gitattributes +5 -35
  9. .github/FUNDING.yml +13 -0
  10. .github/ISSUE_TEMPLATE/bug_report.yml +49 -0
  11. .github/ISSUE_TEMPLATE/config.yml +8 -0
  12. .github/ISSUE_TEMPLATE/feature_request.yml +42 -0
  13. .github/actions/helm-oci-chart-releaser/action.yml +77 -0
  14. .github/dependabot.yaml +10 -0
  15. .github/pull_request_template.md +29 -0
  16. .github/template.yaml +94 -0
  17. .github/workflows/auto_update_price_and_context_window.yml +28 -0
  18. .github/workflows/auto_update_price_and_context_window_file.py +121 -0
  19. .github/workflows/ghcr_deploy.yml +374 -0
  20. .github/workflows/ghcr_helm_deploy.yml +67 -0
  21. .github/workflows/interpret_load_test.py +113 -0
  22. .github/workflows/label-mlops.yml +17 -0
  23. .github/workflows/load_test.yml +59 -0
  24. .github/workflows/locustfile.py +28 -0
  25. .github/workflows/main.yml +34 -0
  26. .github/workflows/read_pyproject_version.yml +31 -0
  27. .github/workflows/redeploy_proxy.py +20 -0
  28. .github/workflows/reset_stable.yml +39 -0
  29. .github/workflows/results_stats.csv +27 -0
  30. .github/workflows/stale.yml +20 -0
  31. .github/workflows/update_release.py +54 -0
  32. .pre-commit-config.yaml +49 -0
  33. Dockerfile +97 -0
  34. LICENSE +26 -0
  35. README.md +5 -8
  36. ci_cd/check_file_length.py +28 -0
  37. ci_cd/check_files_match.py +32 -0
  38. codecov.yaml +32 -0
  39. db_scripts/create_views.py +209 -0
  40. db_scripts/update_unassigned_teams.py +34 -0
  41. deploy/Dockerfile.ghcr_base +17 -0
  42. deploy/azure_resource_manager/azure_marketplace.zip +0 -0
  43. deploy/azure_resource_manager/azure_marketplace/createUiDefinition.json +15 -0
  44. deploy/azure_resource_manager/azure_marketplace/mainTemplate.json +63 -0
  45. deploy/azure_resource_manager/main.bicep +42 -0
  46. deploy/charts/litellm-helm/.helmignore +23 -0
  47. deploy/charts/litellm-helm/Chart.lock +9 -0
  48. deploy/charts/litellm-helm/Chart.yaml +37 -0
  49. deploy/charts/litellm-helm/README.md +129 -0
  50. 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
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
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: TestLLM
3
- emoji: 🏆
4
- colorFrom: indigo
5
- colorTo: purple
6
  sdk: docker
7
- pinned: false
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