mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
merge origin/main, resolve test file conflicts
Resolved conflicts in ScoreChart.test.tsx and HelpLink.test.tsx by preferring origin/main's renderWithProviders pattern and merging unique tests from both branches. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
b75266d254
1861 changed files with 58190 additions and 30131 deletions
1096
.circleci/config.yml
1096
.circleci/config.yml
File diff suppressed because it is too large
Load diff
|
|
@ -17,4 +17,5 @@ mcp==1.25.0 # for MCP server
|
|||
semantic_router==0.1.10 # for auto-routing with litellm
|
||||
fastuuid==0.12.0
|
||||
responses==0.25.7 # for proxy client tests
|
||||
pytest-retry==1.6.3 # for automatic test retries
|
||||
pytest-retry==1.6.3 # for automatic test retries
|
||||
litellm-proxy-extras # for prisma migrations
|
||||
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
|
|
@ -11,6 +11,10 @@
|
|||
- [ ] My PR's scope is as isolated as possible, it only solves 1 specific problem
|
||||
- [ ] I have requested a Greptile review by commenting `@greptileai` and received a **Confidence Score of at least 4/5** before requesting a maintainer review
|
||||
|
||||
## Delays in PR merge?
|
||||
|
||||
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on [Slack (#pr-review)](https://join.slack.com/t/litellmossslack/shared_invite/zt-3o7nkuyfr-p_kbNJj8taRfXGgQI1~YyA).
|
||||
|
||||
## CI (LiteLLM team)
|
||||
|
||||
> **CI status guideline:**
|
||||
|
|
|
|||
44
.github/workflows/codspeed.yml
vendored
Normal file
44
.github/workflows/codspeed.yml
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
name: CodSpeed Benchmarks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# Allow CodSpeed to trigger backtest performance analysis
|
||||
# in order to generate initial data
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
benchmarks:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -e "."
|
||||
pip install pytest pytest-codspeed==4.3.0
|
||||
|
||||
- name: Run benchmarks
|
||||
uses: CodSpeedHQ/action@v4
|
||||
with:
|
||||
mode: simulation
|
||||
run: pytest tests/benchmarks/ --codspeed
|
||||
3
.github/workflows/ghcr_deploy.yml
vendored
3
.github/workflows/ghcr_deploy.yml
vendored
|
|
@ -369,7 +369,8 @@ jobs:
|
|||
release:
|
||||
name: "New LiteLLM Release"
|
||||
needs: [docker-hub-deploy, build-and-push-image, build-and-push-image-database]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: "ubuntu-latest"
|
||||
|
||||
steps:
|
||||
|
|
|
|||
4
.github/workflows/test-linting.yml
vendored
4
.github/workflows/test-linting.yml
vendored
|
|
@ -33,10 +33,10 @@ jobs:
|
|||
poetry lock
|
||||
poetry install --with dev
|
||||
|
||||
- name: Run Black formatting
|
||||
- name: Check Black formatting
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run black .
|
||||
poetry run black --check --exclude '/enterprise/' .
|
||||
cd ..
|
||||
|
||||
- name: Debug - Check file state
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
|
|||
- Async/await patterns throughout
|
||||
- Type hints required for all public APIs
|
||||
- **Avoid imports within methods** — place all imports at the top of the file (module-level). Inline imports inside functions/methods make dependencies harder to trace and hurt readability. The only exception is avoiding circular imports where absolutely necessary.
|
||||
- **Use dict spread for immutable copies** — prefer `{**original, "key": new_value}` over `dict(obj)` + mutation. The spread produces the final dict in one step and makes intent clear.
|
||||
- **Guard at resolution time** — when resolving an optional value through a fallback chain (`a or b or ""`), raise immediately if the resolved result being empty is an error. Don't pass empty strings or sentinel values downstream for the callee to deal with.
|
||||
- **Extract complex comprehensions to named helpers** — a set/dict comprehension that calls into the DB or manager (e.g. "which of these server IDs are OAuth2?") belongs in a named helper function, not inline in the caller.
|
||||
- **FastAPI parameter declarations** — mark required query/form params with `= Query(...)` / `= Form(...)` explicitly when other params in the same handler are optional. Mixing `str` (required) with `Optional[str] = None` in the same signature causes silent 422s when the required param is missing.
|
||||
|
||||
### Testing Strategy
|
||||
- Unit tests in `tests/test_litellm/`
|
||||
|
|
@ -98,6 +102,8 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
|
|||
- Proxy tests in `tests/proxy_unit_tests/`
|
||||
- Load tests in `tests/load_tests/`
|
||||
- **Always add tests when adding new entity types or features** — if the existing test file covers other entity types, add corresponding tests for the new one
|
||||
- **Keep monkeypatch stubs in sync with real signatures** — when a function gains a new optional parameter, update every `fake_*` / `stub_*` in tests that patch it to also accept that kwarg (even as `**kwargs`). Stale stubs fail with `unexpected keyword argument` and mask real bugs.
|
||||
- **Test all branches of name→ID resolution** — when adding server/resource lookup that resolves names to UUIDs, test: (1) name resolves and UUID is allowed, (2) name resolves but UUID is not allowed, (3) name does not resolve at all. The silent-fallback path is where access-control bugs hide.
|
||||
|
||||
### UI / Backend Consistency
|
||||
- When wiring a new UI entity type to an existing backend endpoint, verify the backend API contract (single value vs. array, required vs. optional params) and ensure the UI controls match — e.g., use a single-select dropdown when the backend accepts a single value, not a multi-select
|
||||
|
|
@ -150,4 +156,4 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
|
|||
**Fix options:**
|
||||
1. **Create a Prisma migration** (permanent) — run `prisma migrate dev --name <description>` in the worktree. The generated file will be picked up by `prisma migrate deploy` on next startup.
|
||||
2. **Apply manually for local dev** — `psql -d litellm -c "ALTER TABLE ... ADD COLUMN IF NOT EXISTS ..."` after each proxy start. Fine for dev, not for production.
|
||||
3. **Update litellm-proxy-extras** — if the package is installed from PyPI, its migration directory must include the new file. Either update the package or run the migration manually until the next release ships it.
|
||||
3. **Update litellm-proxy-extras** — if the package is installed from PyPI, its migration directory must include the new file. Either update the package or run the migration manually until the next release ships it.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt
|
|||
# ensure pyjwt is used, not jwt
|
||||
RUN pip uninstall jwt -y
|
||||
RUN pip uninstall PyJWT -y
|
||||
RUN pip install PyJWT==2.9.0 --no-cache-dir
|
||||
RUN pip install PyJWT==2.12.0 --no-cache-dir
|
||||
|
||||
# Runtime stage
|
||||
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
||||
|
|
@ -49,7 +49,7 @@ USER root
|
|||
|
||||
# Install runtime dependencies (libsndfile needed for audio processing on ARM64)
|
||||
RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \
|
||||
npm install -g npm@latest tar@7.5.10 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
# SECURITY FIX: npm bundles tar, glob, and brace-expansion at multiple nested
|
||||
# levels inside its dependency tree. `npm install -g <pkg>` only creates a
|
||||
# SEPARATE global package, it does NOT replace npm's internal copies.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
<a href="https://www.litellm.ai/support">
|
||||
<img src="https://img.shields.io/static/v1?label=Chat%20on&message=Slack&color=black&logo=Slack&style=flat-square" alt="Slack">
|
||||
</a>
|
||||
<a href="https://codspeed.io/BerriAI/litellm?utm_source=badge">
|
||||
<img src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" alt="CodSpeed"/>
|
||||
</a>
|
||||
</h4>
|
||||
|
||||
<img width="2688" height="1600" alt="Group 7154 (1)" src="https://github.com/user-attachments/assets/c5ee0412-6fb5-4fb6-ab5b-bafae4209ca6" />
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ echo "Starting security scans for LiteLLM..."
|
|||
install_trivy() {
|
||||
echo "Installing Trivy and required tools..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y wget apt-transport-https gnupg lsb-release jq curl
|
||||
sudo apt-get install -y wget apt-transport-https gnupg lsb-release jq curl bsdmainutils
|
||||
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
|
||||
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
|
||||
sudo apt-get update
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ spec:
|
|||
selector:
|
||||
matchLabels:
|
||||
{{- include "litellm.selectorLabels" . | nindent 6 }}
|
||||
{{- if .Values.deploymentMinReadySeconds }}
|
||||
minReadySeconds: {{ .Values.deploymentMinReadySeconds }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
|
|
|
|||
|
|
@ -306,3 +306,16 @@ tests:
|
|||
- equal:
|
||||
path: spec.template.spec.containers[0].resources
|
||||
value: {}
|
||||
- it: should be able to set minReadySeconds
|
||||
template: deployment.yaml
|
||||
set:
|
||||
deploymentMinReadySeconds: 5
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.minReadySeconds
|
||||
value: 5
|
||||
- it: should have minReadySeconds absent when deploymentMinReadySeconds is not set
|
||||
template: deployment.yaml
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.minReadySeconds
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ serviceAccount:
|
|||
# annotations for litellm deployment
|
||||
deploymentAnnotations: {}
|
||||
deploymentLabels: {}
|
||||
deploymentMinReadySeconds: 0
|
||||
|
||||
# annotations for litellm pods
|
||||
podAnnotations: {}
|
||||
podLabels: {}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ RUN apt-get update && apt-get upgrade -y \
|
|||
libgnutls30 \
|
||||
libc6 && \
|
||||
apt-get install -y nodejs npm && \
|
||||
npm install -g npm@latest tar@7.5.10 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
GLOBAL="$(npm root -g)" && \
|
||||
find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ USER root
|
|||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \
|
||||
npm install -g npm@latest tar@7.5.10 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \
|
||||
GLOBAL="$(npm root -g)" && \
|
||||
find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
|
|
@ -112,7 +112,7 @@ RUN sed -i 's/\r$//' docker/install_auto_router.sh && chmod +x docker/install_au
|
|||
# ensure pyjwt is used, not jwt
|
||||
RUN pip uninstall jwt -y
|
||||
RUN pip uninstall PyJWT -y
|
||||
RUN pip install PyJWT==2.9.0 --no-cache-dir
|
||||
RUN pip install PyJWT==2.12.0 --no-cache-dir
|
||||
|
||||
# Build Admin UI (runtime stage)
|
||||
# Convert Windows line endings to Unix and make executable
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ RUN --mount=type=cache,target=/root/.cache/pip \
|
|||
# Fix JWT dependency conflicts early
|
||||
RUN pip uninstall jwt -y || true && \
|
||||
pip uninstall PyJWT -y || true && \
|
||||
pip install PyJWT==2.9.0 --no-cache-dir
|
||||
pip install PyJWT==2.12.0 --no-cache-dir
|
||||
|
||||
# Copy only necessary files for build
|
||||
COPY pyproject.toml README.md schema.prisma poetry.lock ./
|
||||
|
|
@ -75,7 +75,7 @@ RUN apt-get update && apt-get upgrade -y \
|
|||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& npm install -g npm@latest tar@7.5.10 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \
|
||||
&& npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \
|
||||
&& GLOBAL="$(npm root -g)" \
|
||||
&& find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ RUN for i in 1 2 3; do \
|
|||
# Cache Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt \
|
||||
&& pip wheel --no-cache-dir --wheel-dir=/wheels/ "semantic_router==0.1.11" "aurelio-sdk==0.0.19" "PyJWT==2.9.0"
|
||||
&& pip wheel --no-cache-dir --wheel-dir=/wheels/ "semantic_router==0.1.11" "aurelio-sdk==0.0.19" "PyJWT==2.12.0"
|
||||
|
||||
# Copy source after dependency layers
|
||||
COPY . .
|
||||
|
|
@ -106,7 +106,7 @@ RUN for i in 1 2 3; do \
|
|||
apk add --no-cache python3 py3-pip bash openssl tzdata nodejs npm supervisor && break || sleep 5; \
|
||||
done \
|
||||
&& apk upgrade --no-cache nodejs \
|
||||
&& npm install -g npm@latest tar@7.5.10 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \
|
||||
&& npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \
|
||||
&& GLOBAL="$(npm root -g)" \
|
||||
&& find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \
|
||||
rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \
|
||||
|
|
@ -198,7 +198,7 @@ RUN sed -i 's/\r$//' docker/entrypoint.sh && \
|
|||
chown -R nobody:nogroup /app /var/lib/litellm/ui /var/lib/litellm/assets /nonexistent /.npm && \
|
||||
pip uninstall jwt -y || true && \
|
||||
pip uninstall PyJWT -y || true && \
|
||||
pip install --no-index --find-links=/wheels/ PyJWT==2.10.1 --no-cache-dir && \
|
||||
pip install --no-index --find-links=/wheels/ PyJWT==2.12.0 --no-cache-dir && \
|
||||
rm -rf /wheels && \
|
||||
PRISMA_PATH=$(python -c "import os, prisma; print(os.path.dirname(prisma.__file__))") && \
|
||||
chown -R nobody:nogroup $PRISMA_PATH && \
|
||||
|
|
|
|||
119
docs/my-website/blog/realtime_webrtc_http_endpoints/index.md
Normal file
119
docs/my-website/blog/realtime_webrtc_http_endpoints/index.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
slug: realtime_webrtc_http_endpoints
|
||||
title: "Realtime WebRTC HTTP Endpoints"
|
||||
date: 2026-03-12T10:00:00
|
||||
authors:
|
||||
- name: Sameer Kankute
|
||||
title: SWE @ LiteLLM (LLM Translation)
|
||||
url: https://www.linkedin.com/in/sameer-kankute/
|
||||
image_url: https://pbs.twimg.com/profile_images/2001352686994907136/ONgNuSk5_400x400.jpg
|
||||
- name: Krrish Dholakia
|
||||
title: "CEO, LiteLLM"
|
||||
url: https://www.linkedin.com/in/krish-d/
|
||||
image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg
|
||||
- name: Ishaan Jaff
|
||||
title: "CTO, LiteLLM"
|
||||
url: https://www.linkedin.com/in/reffajnaahsi/
|
||||
image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg
|
||||
description: "Use the LiteLLM proxy to route OpenAI-style WebRTC realtime via HTTP: client_secrets and SDP exchange."
|
||||
tags: [realtime, webrtc, proxy, openai]
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
import WebRTCTester from '@site/src/components/WebRTCTester';
|
||||
|
||||
Connect to the Realtime API via WebRTC from browser/mobile clients. LiteLLM handles auth and key management.
|
||||
|
||||
## How it works
|
||||
|
||||

|
||||
|
||||
**Flow of generating ephemeral token**
|
||||
|
||||

|
||||
|
||||
|
||||
## Proxy Setup
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: gpt-4o-realtime
|
||||
litellm_params:
|
||||
model: openai/gpt-4o-realtime-preview-2024-12-17
|
||||
api_key: os.environ/OPENAI_API_KEY
|
||||
model_info:
|
||||
mode: realtime
|
||||
```
|
||||
|
||||
**Azure:** use `model: azure/gpt-4o-realtime-preview`, `api_key`, `api_base`.
|
||||
|
||||
```bash
|
||||
litellm --config /path/to/config.yaml
|
||||
```
|
||||
|
||||
## Try it live
|
||||
|
||||
<WebRTCTester />
|
||||
|
||||
## Client Usage
|
||||
|
||||
**1. Get token** - `POST /v1/realtime/client_secrets` with LiteLLM API key and `{ model }`.
|
||||
|
||||
**2. WebRTC handshake** - Create `RTCPeerConnection`, add mic track, create data channel `oai-events`, send SDP offer to `POST /v1/realtime/calls` with `Authorization: Bearer <encrypted_token>` and `Content-Type: application/sdp`.
|
||||
|
||||
**3. Events** - Use the data channel for `session.update` and other events.
|
||||
|
||||
<details>
|
||||
<summary>Full code example</summary>
|
||||
|
||||
```javascript
|
||||
// 1. Token
|
||||
const r = await fetch("http://proxy:4000/v1/realtime/client_secrets", {
|
||||
method: "POST",
|
||||
headers: { "Authorization": "Bearer sk-litellm-key", "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ model: "gpt-4o-realtime" }),
|
||||
});
|
||||
const { client_secret } = await r.json();
|
||||
const token = client_secret.value;
|
||||
|
||||
// 2. WebRTC
|
||||
const pc = new RTCPeerConnection();
|
||||
const audio = document.createElement("audio");
|
||||
audio.autoplay = true;
|
||||
pc.ontrack = (e) => (audio.srcObject = e.streams[0]);
|
||||
const ms = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
pc.addTrack(ms.getTracks()[0]);
|
||||
const dc = pc.createDataChannel("oai-events");
|
||||
const offer = await pc.createOffer();
|
||||
await pc.setLocalDescription(offer);
|
||||
|
||||
const sdpRes = await fetch("http://proxy:4000/v1/realtime/calls", {
|
||||
method: "POST",
|
||||
headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/sdp" },
|
||||
body: offer.sdp,
|
||||
});
|
||||
await pc.setRemoteDescription({ type: "answer", sdp: await sdpRes.text() });
|
||||
|
||||
// 3. Events
|
||||
dc.send(JSON.stringify({ type: "session.update", session: { instructions: "..." } }));
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: What do I do if I get a 401 Token expired error?**
|
||||
A: Tokens are short-lived. Get a fresh token right before creating the WebRTC offer.
|
||||
|
||||
**Q: Which key should I use for `/v1/realtime/calls`?**
|
||||
A: Use the **encrypted token** from `client_secrets`, not your raw API key.
|
||||
|
||||
**Q: Should I pass the `model` parameter when making the call?**
|
||||
A: No, the encrypted token already encodes all routing information including model.
|
||||
|
||||
**Q: How do I resolve Azure `api-version` errors?**
|
||||
A: Set the correct `api_version` in `litellm_params` (or via the `AZURE_API_VERSION` environment variable), along with the right `api_base` and deployment values.
|
||||
|
||||
**Q: What if I get no audio?**
|
||||
A: Make sure you grant microphone permission, ensure `pc.ontrack` assigns the audio element with `autoplay` enabled, check your network/firewall for WebRTC traffic, and inspect the browser console for ICE or SDP errors.
|
||||
|
||||
128
docs/my-website/blog/video_characters_litellm/index.md
Normal file
128
docs/my-website/blog/video_characters_litellm/index.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
---
|
||||
slug: video_characters_api
|
||||
title: "New Video Characters, Edit and Extension API support"
|
||||
date: 2026-03-16T10:00:00
|
||||
authors:
|
||||
- name: Sameer Kankute
|
||||
title: SWE @ LiteLLM
|
||||
url: https://www.linkedin.com/in/sameer-kankute/
|
||||
image_url: https://pbs.twimg.com/profile_images/2001352686994907136/ONgNuSk5_400x400.jpg
|
||||
- name: Krrish Dholakia
|
||||
title: "CEO, LiteLLM"
|
||||
url: https://www.linkedin.com/in/krish-d/
|
||||
image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg
|
||||
- name: Ishaan Jaff
|
||||
title: "CTO, LiteLLM"
|
||||
url: https://www.linkedin.com/in/reffajnaahsi/
|
||||
image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg
|
||||
description: "LiteLLM now supports creating, retrieving, and managing reusable video characters across multiple video generations."
|
||||
tags: [videos, characters, proxy, routing]
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
LiteLLM now supoports videos character, edit and extension apis.
|
||||
|
||||
## What's New
|
||||
|
||||
Four new endpoints for video character operations:
|
||||
- **Create character** - Upload a video to create a reusable asset
|
||||
- **Get character** - Retrieve character metadata
|
||||
- **Edit video** - Modify generated videos
|
||||
- **Extend video** - Continue clips with character consistency
|
||||
|
||||
**Available from:** LiteLLM v1.83.0+
|
||||
|
||||
## Quick Example
|
||||
|
||||
```python
|
||||
import litellm
|
||||
|
||||
# Create character from video
|
||||
character = litellm.avideo_create_character(
|
||||
name="Luna",
|
||||
video=open("luna.mp4", "rb"),
|
||||
custom_llm_provider="openai",
|
||||
model="sora-2"
|
||||
)
|
||||
print(f"Character: {character.id}")
|
||||
|
||||
# Use in generation
|
||||
video = litellm.avideo(
|
||||
model="sora-2",
|
||||
prompt="Luna dances through a magical forest.",
|
||||
characters=[{"id": character.id}],
|
||||
seconds="8"
|
||||
)
|
||||
|
||||
# Get character info
|
||||
fetched = litellm.avideo_get_character(
|
||||
character_id=character.id,
|
||||
custom_llm_provider="openai"
|
||||
)
|
||||
|
||||
# Edit with character preserved
|
||||
edited = litellm.avideo_edit(
|
||||
video_id=video.id,
|
||||
prompt="Add warm golden lighting"
|
||||
)
|
||||
|
||||
# Extend sequence
|
||||
extended = litellm.avideo_extension(
|
||||
video_id=video.id,
|
||||
prompt="Luna waves goodbye",
|
||||
seconds="5"
|
||||
)
|
||||
```
|
||||
|
||||
## Via Proxy
|
||||
|
||||
```bash
|
||||
# Create character
|
||||
curl -X POST "http://localhost:4000/v1/videos/characters" \
|
||||
-H "Authorization: Bearer sk-litellm-key" \
|
||||
-F "video=@luna.mp4" \
|
||||
-F "name=Luna"
|
||||
|
||||
# Get character
|
||||
curl -X GET "http://localhost:4000/v1/videos/characters/char_abc123def456" \
|
||||
-H "Authorization: Bearer sk-litellm-key"
|
||||
|
||||
# Edit video
|
||||
curl -X POST "http://localhost:4000/v1/videos/edits" \
|
||||
-H "Authorization: Bearer sk-litellm-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"video": {"id": "video_xyz789"},
|
||||
"prompt": "Add warm golden lighting and enhance colors"
|
||||
}'
|
||||
|
||||
# Extend video
|
||||
curl -X POST "http://localhost:4000/v1/videos/extensions" \
|
||||
-H "Authorization: Bearer sk-litellm-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"video": {"id": "video_xyz789"},
|
||||
"prompt": "Luna waves goodbye and walks into the sunset",
|
||||
"seconds": "5"
|
||||
}'
|
||||
```
|
||||
|
||||
## Managed Character IDs
|
||||
|
||||
LiteLLM automatically encodes provider and model metadata into character IDs:
|
||||
|
||||
**What happens:**
|
||||
```
|
||||
Upload character "Luna" with model "sora-2" on OpenAI
|
||||
↓
|
||||
LiteLLM creates: char_abc123def456 (contains provider + model_id)
|
||||
↓
|
||||
When you reference it later, LiteLLM decodes automatically
|
||||
↓
|
||||
Router knows exactly which deployment to use
|
||||
```
|
||||
|
||||
**Behind the scenes:**
|
||||
- Character ID format: `character_<base64_encoded_metadata>`
|
||||
- Metadata includes: provider, model_id, original_character_id
|
||||
- Transparent to you - just use the ID, LiteLLM handles routing
|
||||
|
|
@ -326,4 +326,10 @@ print("file content=", content.text)
|
|||
|
||||
### [Bedrock](./providers/bedrock_batches#4-retrieve-batch-results)
|
||||
|
||||
### [Anthropic](./providers/anthropic#files-api)
|
||||
|
||||
:::note
|
||||
Anthropic Files API has a different purpose than OpenAI's. It's **not** for Batches or Fine-tuning—it's for uploading files once and referencing them by `file_id` in multiple messages, avoiding re-uploads. File API operations are free — file content used in Messages requests is priced as input tokens.
|
||||
:::
|
||||
|
||||
## [Swagger API Reference](https://litellm-api.up.railway.app/#/files)
|
||||
|
|
|
|||
294
docs/my-website/docs/mcp_zero_trust.md
Normal file
294
docs/my-website/docs/mcp_zero_trust.md
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# MCP Zero Trust Auth (JWT Signer)
|
||||
|
||||

|
||||
|
||||
MCP servers have no built-in way to verify that a request actually came through LiteLLM. Without this guardrail, any client that can reach your MCP server directly can call tools — bypassing your access controls entirely.
|
||||
|
||||
`MCPJWTSigner` fixes this. It signs every outbound tool call with a short-lived RS256 JWT. Your MCP server verifies the signature against LiteLLM's public key. Requests that didn't go through LiteLLM have no valid signature and are rejected.
|
||||
|
||||
---
|
||||
|
||||
## Basic setup
|
||||
|
||||
Add the guardrail to your config and point your MCP server at LiteLLM's JWKS endpoint. Every tool call gets a signed JWT automatically — no changes needed on the client side.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
mcp_servers:
|
||||
- server_name: weather
|
||||
url: http://localhost:8000/mcp
|
||||
transport: http
|
||||
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
issuer: "https://my-litellm.example.com" # defaults to request base URL
|
||||
audience: "mcp" # default: "mcp"
|
||||
ttl_seconds: 300 # default: 300
|
||||
```
|
||||
|
||||
**Bring your own signing key** — recommended for production. Auto-generated keys are lost on restart.
|
||||
|
||||
```bash
|
||||
export MCP_JWT_SIGNING_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."
|
||||
# or point to a file
|
||||
export MCP_JWT_SIGNING_KEY="file:///secrets/mcp-signing-key.pem"
|
||||
```
|
||||
|
||||
**Build a verified MCP server with [FastMCP](https://gofastmcp.com):**
|
||||
|
||||
```python title="weather_server.py"
|
||||
from fastmcp import FastMCP, Context
|
||||
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
||||
|
||||
auth = JWTVerifier(
|
||||
jwks_uri="https://my-litellm.example.com/.well-known/jwks.json",
|
||||
issuer="https://my-litellm.example.com",
|
||||
audience="mcp",
|
||||
algorithm="RS256",
|
||||
)
|
||||
|
||||
mcp = FastMCP("weather-server", auth=auth)
|
||||
|
||||
@mcp.tool()
|
||||
async def get_weather(city: str, ctx: Context) -> str:
|
||||
caller = ctx.client_id # JWT `sub` — the verified user identity
|
||||
return f"Weather in {city}: sunny, 72°F (requested by {caller})"
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="http", host="0.0.0.0", port=8000)
|
||||
```
|
||||
|
||||
FastMCP fetches the JWKS automatically and re-fetches when the signing key changes.
|
||||
|
||||
LiteLLM publishes OIDC discovery so MCP servers find the key without any manual configuration:
|
||||
|
||||
```
|
||||
GET /.well-known/openid-configuration → { "jwks_uri": "https://<litellm>/.well-known/jwks.json" }
|
||||
GET /.well-known/jwks.json → { "keys": [{ "kty": "RSA", "alg": "RS256", ... }] }
|
||||
```
|
||||
|
||||
> **Read further only if you need to:** thread a corporate IdP identity into the JWT, enforce specific claims on callers, add custom metadata, use AWS Bedrock AgentCore Gateway, or debug JWT rejections.
|
||||
|
||||
---
|
||||
|
||||
## Thread IdP identity into MCP JWTs
|
||||
|
||||
By default the outbound JWT `sub` is LiteLLM's internal `user_id`. If your users authenticate with Okta, Azure AD, or another IdP, the MCP server sees a LiteLLM-internal ID — not the user's email or employee ID.
|
||||
|
||||
With verify+re-sign, LiteLLM validates the incoming IdP token first, then builds the outbound JWT using the real identity claims from that token. The MCP server gets the user's actual identity without ever having to trust the original IdP directly.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
issuer: "https://my-litellm.example.com"
|
||||
|
||||
# Validate the incoming Bearer token against the IdP
|
||||
access_token_discovery_uri: "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
|
||||
verify_issuer: "https://login.microsoftonline.com/{tenant}/v2.0"
|
||||
verify_audience: "api://my-app"
|
||||
|
||||
# Which claim to use for `sub` in the outbound JWT — first non-empty value wins
|
||||
end_user_claim_sources:
|
||||
- "token:sub" # from the verified incoming JWT
|
||||
- "token:email" # fallback to email
|
||||
- "litellm:user_id" # last resort: LiteLLM's internal user_id
|
||||
```
|
||||
|
||||
If the incoming token is **opaque** (not a JWT — some IdPs issue these), add an introspection endpoint. LiteLLM will POST the token to it (RFC 7662) and use the returned claims:
|
||||
|
||||
```yaml
|
||||
token_introspection_endpoint: "https://idp.example.com/oauth2/introspect"
|
||||
```
|
||||
|
||||
**Supported `end_user_claim_sources` values:**
|
||||
|
||||
| Source | Resolves to |
|
||||
|--------|-------------|
|
||||
| `token:<claim>` | Any claim from the verified incoming JWT (e.g. `token:sub`, `token:email`, `token:oid`) |
|
||||
| `litellm:user_id` | LiteLLM's internal user ID |
|
||||
| `litellm:email` | User email from LiteLLM auth context |
|
||||
| `litellm:end_user_id` | End-user ID if set separately |
|
||||
| `litellm:team_id` | Team ID from LiteLLM auth context |
|
||||
|
||||
---
|
||||
|
||||
## Block callers missing required attributes
|
||||
|
||||
Some MCP servers expose sensitive operations that should only be reachable by verified employees — not service accounts, not external API keys. You can enforce this at the LiteLLM layer so the MCP server never receives the request at all.
|
||||
|
||||
`required_claims` rejects with `403` if the incoming token is missing any listed claim. `optional_claims` forwards claims that are useful but not mandatory.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
|
||||
access_token_discovery_uri: "https://idp.example.com/.well-known/openid-configuration"
|
||||
|
||||
# Service accounts without `employee_id` are blocked before the tool runs
|
||||
required_claims:
|
||||
- "sub"
|
||||
- "employee_id"
|
||||
|
||||
# Forward these into the outbound JWT when present — skipped silently if absent
|
||||
optional_claims:
|
||||
- "groups"
|
||||
- "department"
|
||||
```
|
||||
|
||||
**What the client sees when blocked:**
|
||||
```json
|
||||
HTTP 403
|
||||
{ "error": "MCPJWTSigner: incoming token is missing required claims: ['employee_id']. Configure the IdP to include these claims." }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Add custom metadata to every JWT
|
||||
|
||||
Your MCP server may need context that LiteLLM doesn't carry natively — which deployment sent the request, a tenant ID, an environment tag. Use claim operations to inject, override, or strip claims from the outbound JWT.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
|
||||
# add: insert only when the key is not already in the JWT
|
||||
add_claims:
|
||||
deployment_id: "prod-us-east-1"
|
||||
tenant_id: "acme-corp"
|
||||
|
||||
# set: always override — even if the claim came from the incoming token
|
||||
set_claims:
|
||||
env: "production"
|
||||
|
||||
# remove: strip claims the MCP server shouldn't see
|
||||
remove_claims:
|
||||
- "nbf" # some validators reject nbf; remove it if yours does
|
||||
```
|
||||
|
||||
Operations run in order — `add_claims` → `set_claims` → `remove_claims`. `set_claims` always wins over `add_claims`; `remove_claims` beats both.
|
||||
|
||||
---
|
||||
|
||||
## AWS Bedrock AgentCore Gateway
|
||||
|
||||
Bedrock AgentCore Gateway uses two separate JWTs: one to authenticate the transport connection and another to authorize tool calls. They need different `aud` values and TTLs — a single JWT won't work for both.
|
||||
|
||||
LiteLLM can issue both in one hook and inject them into separate headers:
|
||||
|
||||
```yaml title="config.yaml"
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
issuer: "https://my-litellm.example.com"
|
||||
audience: "mcp-resource" # for the MCP resource layer
|
||||
ttl_seconds: 300
|
||||
|
||||
# Second JWT for the transport channel — same sub/act/scope, different aud + TTL
|
||||
channel_token_audience: "bedrock-agentcore-gateway"
|
||||
channel_token_ttl: 60 # transport tokens should be short-lived
|
||||
```
|
||||
|
||||
LiteLLM injects two headers on every tool call:
|
||||
- `Authorization: Bearer <resource-token>` — audience `mcp-resource`, TTL 300s
|
||||
- `x-mcp-channel-token: Bearer <channel-token>` — audience `bedrock-agentcore-gateway`, TTL 60s
|
||||
|
||||
Both tokens are signed with the same LiteLLM key, so your MCP server only needs to trust one JWKS endpoint.
|
||||
|
||||
---
|
||||
|
||||
## Control which scopes go into the JWT
|
||||
|
||||
By default LiteLLM generates least-privilege scopes per request:
|
||||
- Tool call → `mcp:tools/call mcp:tools/{name}:call`
|
||||
- List tools → `mcp:tools/call mcp:tools/list`
|
||||
|
||||
If your MCP server does its own scope enforcement and needs a specific format, set `allowed_scopes` to replace auto-generation entirely:
|
||||
|
||||
```yaml title="config.yaml"
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
|
||||
allowed_scopes:
|
||||
- "mcp:tools/call"
|
||||
- "mcp:tools/list"
|
||||
- "mcp:admin"
|
||||
```
|
||||
|
||||
Every JWT carries exactly those scopes regardless of which tool is being called.
|
||||
|
||||
---
|
||||
|
||||
## Debug JWT rejections
|
||||
|
||||
Your MCP server is returning 401 and you're not sure what's in the JWT. Enable `debug_headers` and LiteLLM adds a `x-litellm-mcp-debug` response header with the key claims that were signed:
|
||||
|
||||
```yaml title="config.yaml"
|
||||
guardrails:
|
||||
- guardrail_name: mcp-jwt-signer
|
||||
litellm_params:
|
||||
guardrail: mcp_jwt_signer
|
||||
mode: pre_mcp_call
|
||||
default_on: true
|
||||
debug_headers: true
|
||||
```
|
||||
|
||||
Response header:
|
||||
```
|
||||
x-litellm-mcp-debug: v=1; kid=a3f1b2c4d5e6f708; sub=alice@corp.com; iss=https://my-litellm.example.com; exp=1712345678; scope=mcp:tools/call mcp:tools/get_weather:call
|
||||
```
|
||||
|
||||
Check that `kid` matches what the MCP server fetched from JWKS, `iss`/`aud` match your server's expected values, and `exp` hasn't passed. Disable in production — the header leaks claim metadata.
|
||||
|
||||
---
|
||||
|
||||
## JWT claims reference
|
||||
|
||||
| Claim | Value |
|
||||
|-------|-------|
|
||||
| `iss` | `issuer` config value (or request base URL) |
|
||||
| `aud` | `audience` config value (default: `"mcp"`) |
|
||||
| `sub` | Resolved via `end_user_claim_sources` (default: `user_id` → api-key hash → `"litellm-proxy"`) |
|
||||
| `act.sub` | `team_id` → `org_id` → `"litellm-proxy"` (RFC 8693 delegation) |
|
||||
| `email` | `user_email` from LiteLLM auth context (when available) |
|
||||
| `scope` | Auto-generated per tool call, or `allowed_scopes` when set |
|
||||
| `iat`, `exp`, `nbf` | Standard timing claims (RFC 7519) |
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
- **OpenAPI-backed MCP servers** (`spec_path` set) do not support JWT injection. LiteLLM logs a warning and skips the header. Use SSE/HTTP transport servers to get full JWT injection.
|
||||
- The keypair is **in-memory by default** and rotated on each restart unless `MCP_JWT_SIGNING_KEY` is set. FastMCP's `JWTVerifier` handles key rotation transparently via JWKS key ID matching.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [MCP Guardrails](./mcp_guardrail) — PII masking and blocking for MCP calls
|
||||
- [MCP OAuth](./mcp_oauth) — upstream OAuth2 for MCP server access
|
||||
- [MCP AWS SigV4](./mcp_aws_sigv4) — AWS-signed requests to MCP servers
|
||||
148
docs/my-website/docs/observability/vantage.md
Normal file
148
docs/my-website/docs/observability/vantage.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Vantage Integration
|
||||
|
||||
LiteLLM can export proxy spend data to [Vantage](https://vantage.sh) as [FOCUS 1.2](https://focus.finops.org/) formatted cost reports. This lets you visualize LLM spend alongside your cloud infrastructure costs in the Vantage dashboard.
|
||||
|
||||
## Overview
|
||||
|
||||
| Property | Details |
|
||||
|----------|---------|
|
||||
| Destination | Export LiteLLM usage data to Vantage Custom Provider |
|
||||
| Data format | FOCUS CSV (automatically transformed from LiteLLM spend data) |
|
||||
| Supported operations | Manual export, automatic scheduled export (hourly/daily/interval) |
|
||||
| Authentication | Vantage API key + Custom Provider token |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need two credentials from the [Vantage console](https://console.vantage.sh):
|
||||
|
||||
1. **API Key** — Go to **Settings → API Access Tokens** → Create a token with **Write** scope. The token looks like `vntg_tkn_...`.
|
||||
2. **Custom Provider Token** — Go to **Settings → Integrations** → Create a **Custom Provider** integration → Copy the Provider ID (looks like `accss_crdntl_...`).
|
||||
|
||||
## Setup via API
|
||||
|
||||
The recommended setup uses the proxy admin endpoints. No config file changes needed.
|
||||
|
||||
### 1. Initialize credentials
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:4000/vantage/init \
|
||||
-H "Authorization: Bearer $LITELLM_ADMIN_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"api_key": "vntg_tkn_YOUR_VANTAGE_API_KEY",
|
||||
"integration_token": "accss_crdntl_YOUR_PROVIDER_TOKEN"
|
||||
}'
|
||||
```
|
||||
|
||||
Credentials are encrypted and stored in the proxy database.
|
||||
|
||||
### 2. Preview data (dry run)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:4000/vantage/dry-run \
|
||||
-H "Authorization: Bearer $LITELLM_ADMIN_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 10}'
|
||||
```
|
||||
|
||||
This returns FOCUS-transformed data without sending anything to Vantage. Use it to verify the pipeline works and inspect the data mapping.
|
||||
|
||||
### 3. Export to Vantage
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:4000/vantage/export \
|
||||
-H "Authorization: Bearer $LITELLM_ADMIN_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
Optional parameters:
|
||||
- `limit` — Max number of records to export
|
||||
- `start_time_utc` / `end_time_utc` — Filter by time range (must be provided together)
|
||||
|
||||
### 4. Verify in Vantage
|
||||
|
||||
Go to **Settings → Integrations → your Custom Provider → Import Costs** tab to see uploaded CSVs. Once the status changes from "Importing and Processing" to "Stable", costs appear in **Cost Reporting → All Resources**.
|
||||
|
||||
## Setup via Environment Variables
|
||||
|
||||
For automatic scheduled exports, configure via environment variables and proxy config:
|
||||
|
||||
### Environment variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `VANTAGE_API_KEY` | Yes | Vantage API access token |
|
||||
| `VANTAGE_INTEGRATION_TOKEN` | Yes | Custom Provider token from Vantage dashboard |
|
||||
| `VANTAGE_BASE_URL` | No | API URL override (default: `https://api.vantage.sh`) |
|
||||
| `VANTAGE_EXPORT_FREQUENCY` | No | `hourly` (default), `daily`, or `interval` |
|
||||
| `VANTAGE_EXPORT_INTERVAL_SECONDS` | No | Seconds between exports when frequency is `interval` |
|
||||
|
||||
### Proxy config
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: gpt-4o
|
||||
litellm_params:
|
||||
model: openai/gpt-4o
|
||||
api_key: sk-your-key
|
||||
|
||||
litellm_settings:
|
||||
callbacks: ["vantage"]
|
||||
```
|
||||
|
||||
```bash
|
||||
export VANTAGE_API_KEY="vntg_tkn_..."
|
||||
export VANTAGE_INTEGRATION_TOKEN="accss_crdntl_..."
|
||||
litellm --config /path/to/config.yaml
|
||||
```
|
||||
|
||||
The proxy registers a background job that exports data on the configured schedule.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
All endpoints require admin authentication.
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| `POST` | `/vantage/init` | Store Vantage credentials (encrypted) |
|
||||
| `GET` | `/vantage/settings` | View current config (credentials masked) |
|
||||
| `PUT` | `/vantage/settings` | Update credentials or base URL |
|
||||
| `POST` | `/vantage/dry-run` | Preview FOCUS data without uploading |
|
||||
| `POST` | `/vantage/export` | Upload cost data to Vantage |
|
||||
| `DELETE` | `/vantage/delete` | Remove credentials and stop scheduled exports |
|
||||
|
||||
## FOCUS Field Mapping
|
||||
|
||||
LiteLLM spend data is transformed into the FOCUS 1.2 schema:
|
||||
|
||||
| LiteLLM Field | FOCUS Column | Description |
|
||||
|---------------|-------------|-------------|
|
||||
| `spend` | BilledCost, EffectiveCost | Cost of the usage |
|
||||
| `model` | ChargeDescription, ResourceId | Model identifier |
|
||||
| `model_group` | ServiceName | Model group / deployment |
|
||||
| `custom_llm_provider` | ProviderName, PublisherName | Provider (openai, anthropic, etc.) |
|
||||
| `api_key` | BillingAccountId | Hashed API key |
|
||||
| `api_key_alias` | BillingAccountName | Human-readable key alias |
|
||||
| `team_id` | SubAccountId | Team identifier |
|
||||
| `team_alias` | SubAccountName | Team name |
|
||||
|
||||
Additional metadata (user_id, model_group, etc.) is included in the `Tags` column as JSON.
|
||||
|
||||
## Upload Limits
|
||||
|
||||
Vantage enforces per-upload limits. LiteLLM handles these automatically:
|
||||
|
||||
- **10,000 rows** per upload — large exports are split into batches
|
||||
- **2 MB** per upload — oversized batches are further split by size
|
||||
- **Unsupported columns** are stripped before upload
|
||||
|
||||
## Related Links
|
||||
|
||||
- [Vantage](https://vantage.sh)
|
||||
- [Vantage Custom Providers](https://docs.vantage.sh/connecting_custom_providers)
|
||||
- [FOCUS Specification](https://focus.finops.org/)
|
||||
- [Focus Export (S3/Parquet)](./focus.md)
|
||||
|
|
@ -1965,6 +1965,98 @@ curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \
|
|||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Files API
|
||||
|
||||
Upload files once and reference them by `file_id` in multiple requests—no need to re-upload content each time.
|
||||
|
||||
:::info
|
||||
The `file_id` obtained from Anthropic only works with Anthropic Claude models. You cannot use it with other providers (OpenAI, Bedrock, etc.).
|
||||
:::
|
||||
|
||||
- **Max file size:** 500 MB | **Total storage:** 100 GB per org
|
||||
- **Pricing:** File API operations are free. File content used in Messages requests is priced as input tokens.
|
||||
|
||||
**Supported models by file type:**
|
||||
- **Images:** All Claude 3+ models
|
||||
- **PDFs:** All Claude 3.5+ models
|
||||
- **Other file types** (for code execution): Claude 3.5 Haiku + all Claude 3.7+ models
|
||||
|
||||
### Quick Start
|
||||
|
||||
```python
|
||||
import litellm
|
||||
import os
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."
|
||||
|
||||
# 1. Upload a file once
|
||||
file = litellm.create_file(
|
||||
file=open("document.pdf", "rb"),
|
||||
purpose="messages",
|
||||
custom_llm_provider="anthropic",
|
||||
)
|
||||
|
||||
# 2. Use file_id in messages (no re-upload needed)
|
||||
response = litellm.completion(
|
||||
model="anthropic/claude-sonnet-4-5-20250929",
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "Summarize this document"},
|
||||
{"type": "file", "file": {"file_id": file.id, "format": "application/pdf"}}
|
||||
]
|
||||
}]
|
||||
)
|
||||
```
|
||||
|
||||
### File Operations
|
||||
|
||||
| Operation | Function |
|
||||
|-----------|----------|
|
||||
| Upload | `litellm.create_file(file, purpose="messages", custom_llm_provider="anthropic")` |
|
||||
| List | `litellm.file_list(custom_llm_provider="anthropic")` |
|
||||
| Retrieve | `litellm.file_retrieve(file_id, custom_llm_provider="anthropic")` |
|
||||
| Delete | `litellm.file_delete(file_id, custom_llm_provider="anthropic")` |
|
||||
| Download | `litellm.file_content(file_id, custom_llm_provider="anthropic")` |
|
||||
|
||||
:::note
|
||||
Download only works for files created by the [code execution tool](https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/code-execution-tool), not uploaded files.
|
||||
:::
|
||||
|
||||
### Supported Formats
|
||||
|
||||
| File Type | Format Value |
|
||||
|-----------|-------------|
|
||||
| PDF | `application/pdf` |
|
||||
| Plain text | `text/plain` |
|
||||
| JPEG | `image/jpeg` |
|
||||
| PNG | `image/png` |
|
||||
| GIF | `image/gif` |
|
||||
| WebP | `image/webp` |
|
||||
|
||||
### Using Images
|
||||
|
||||
```python
|
||||
# Upload image
|
||||
image = litellm.create_file(
|
||||
file=open("photo.jpg", "rb"),
|
||||
purpose="messages",
|
||||
custom_llm_provider="anthropic",
|
||||
)
|
||||
|
||||
# Use in message
|
||||
response = litellm.completion(
|
||||
model="anthropic/claude-sonnet-4-5-20250929",
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "What's in this image?"},
|
||||
{"type": "file", "file": {"file_id": image.id, "format": "image/jpeg"}}
|
||||
]
|
||||
}]
|
||||
)
|
||||
```
|
||||
|
||||
## Usage - passing 'user_id' to Anthropic
|
||||
|
||||
LiteLLM translates the OpenAI `user` param to Anthropic's `metadata[user_id]` param.
|
||||
|
|
|
|||
|
|
@ -526,3 +526,98 @@ print(f"response: {response}")
|
|||
```
|
||||
|
||||
|
||||
|
||||
## Nova Models on SageMaker
|
||||
|
||||
LiteLLM supports Amazon Nova models (Nova Micro, Nova Lite, Nova 2 Lite) deployed on SageMaker Inference real-time endpoints. These custom/fine-tuned Nova models use an OpenAI-compatible API format.
|
||||
|
||||
**Reference:** [AWS Blog - Amazon SageMaker Inference for Custom Amazon Nova Models](https://aws.amazon.com/blogs/aws/announcing-amazon-sagemaker-inference-for-custom-amazon-nova-models/)
|
||||
|
||||
### Usage
|
||||
|
||||
Use the `sagemaker_nova/` prefix with your SageMaker endpoint name:
|
||||
|
||||
```python
|
||||
import litellm
|
||||
import os
|
||||
|
||||
os.environ["AWS_ACCESS_KEY_ID"] = ""
|
||||
os.environ["AWS_SECRET_ACCESS_KEY"] = ""
|
||||
os.environ["AWS_REGION_NAME"] = "us-east-1"
|
||||
|
||||
# Basic chat completion
|
||||
response = litellm.completion(
|
||||
model="sagemaker_nova/my-nova-endpoint",
|
||||
messages=[{"role": "user", "content": "Hello, how are you?"}],
|
||||
temperature=0.7,
|
||||
max_tokens=512,
|
||||
)
|
||||
print(response.choices[0].message.content)
|
||||
```
|
||||
|
||||
### Streaming
|
||||
|
||||
```python
|
||||
response = litellm.completion(
|
||||
model="sagemaker_nova/my-nova-endpoint",
|
||||
messages=[{"role": "user", "content": "Write a short poem"}],
|
||||
stream=True,
|
||||
stream_options={"include_usage": True},
|
||||
)
|
||||
for chunk in response:
|
||||
if chunk.choices[0].delta.content:
|
||||
print(chunk.choices[0].delta.content, end="")
|
||||
```
|
||||
|
||||
### Multimodal (Images)
|
||||
|
||||
Nova models on SageMaker support image inputs using base64 data URIs:
|
||||
|
||||
```python
|
||||
response = litellm.completion(
|
||||
model="sagemaker_nova/my-nova-endpoint",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "What's in this image?"},
|
||||
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
### Proxy Config
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: nova-micro
|
||||
litellm_params:
|
||||
model: sagemaker_nova/my-nova-micro-endpoint
|
||||
aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY
|
||||
aws_region_name: us-east-1
|
||||
```
|
||||
|
||||
### Supported Parameters
|
||||
|
||||
All standard OpenAI parameters are supported, plus these Nova-specific parameters:
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `top_k` | integer | Limits token selection to top K most likely tokens |
|
||||
| `reasoning_effort` | `"low"` \| `"high"` | Reasoning effort level (Nova 2 Lite custom models only) |
|
||||
| `allowed_token_ids` | array[int] | Restrict output to specified token IDs |
|
||||
| `truncate_prompt_tokens` | integer | Truncate prompt to N tokens if it exceeds limit |
|
||||
|
||||
```python
|
||||
response = litellm.completion(
|
||||
model="sagemaker_nova/my-nova-endpoint",
|
||||
messages=[{"role": "user", "content": "Think step by step: what is 2+2?"}],
|
||||
top_k=40,
|
||||
reasoning_effort="low",
|
||||
logprobs=True,
|
||||
top_logprobs=2,
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -638,7 +638,9 @@ This is useful when you want to use [Responses API](https://platform.openai.com/
|
|||
|
||||
:::tip gpt-5.4 + reasoning_effort + function tools
|
||||
|
||||
OpenAI does not support `reasoning_effort` with function tools for `gpt-5.4` in `/v1/chat/completions`. Use the responses bridge instead:
|
||||
LiteLLM drops `reasoning_effort` from `gpt-5.4` requests to `litellm.completion()` that include tools, since that combination is supported in the Responses API.
|
||||
|
||||
If you need reasoning **and** tools together, use the responses bridge instead:
|
||||
|
||||
```python
|
||||
response = litellm.completion(
|
||||
|
|
|
|||
|
|
@ -135,6 +135,81 @@ curl --location --request POST 'http://localhost:4000/v1/videos/video_id/remix'
|
|||
}'
|
||||
```
|
||||
|
||||
### Character, Edit, and Extension Routes
|
||||
|
||||
OpenAI video routes supported by LiteLLM proxy:
|
||||
|
||||
- `POST /v1/videos/characters`
|
||||
- `GET /v1/videos/characters/{character_id}`
|
||||
- `POST /v1/videos/edits`
|
||||
- `POST /v1/videos/extensions`
|
||||
|
||||
#### `target_model_names` support on character creation
|
||||
|
||||
`POST /v1/videos/characters` supports `target_model_names` for model-based routing (same behavior as video create).
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/characters' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
-F 'name=hero' \
|
||||
-F 'target_model_names=gpt-4' \
|
||||
-F 'video=@/path/to/character.mp4'
|
||||
```
|
||||
|
||||
When `target_model_names` is used, LiteLLM returns an encoded character ID:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "character_...",
|
||||
"object": "character",
|
||||
"created_at": 1712697600,
|
||||
"name": "hero"
|
||||
}
|
||||
```
|
||||
|
||||
Use that encoded ID directly on get:
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/characters/character_...' \
|
||||
--header 'Authorization: Bearer sk-1234'
|
||||
```
|
||||
|
||||
#### Encoded and non-encoded video IDs for edit/extension
|
||||
|
||||
Both routes accept either plain or encoded `video.id`:
|
||||
|
||||
- `POST /v1/videos/edits`
|
||||
- `POST /v1/videos/extensions`
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/edits' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"prompt": "Make this brighter",
|
||||
"video": { "id": "video_..." }
|
||||
}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/extensions' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"prompt": "Continue this scene",
|
||||
"seconds": "4",
|
||||
"video": { "id": "video_..." }
|
||||
}'
|
||||
```
|
||||
|
||||
#### `custom_llm_provider` input sources
|
||||
|
||||
For these routes, `custom_llm_provider` may be supplied via:
|
||||
|
||||
- header: `custom-llm-provider`
|
||||
- query: `?custom_llm_provider=...`
|
||||
- body: `custom_llm_provider` (and `extra_body.custom_llm_provider` where supported)
|
||||
|
||||
Test OpenAI video generation request
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import TabItem from '@theme/TabItem';
|
|||
|----------|---------------|---------------|
|
||||
| Anthropic (Claude) | `vertex_ai/claude-*` | [Vertex AI - Anthropic Models](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude) |
|
||||
| DeepSeek | `vertex_ai/deepseek-ai/{MODEL}` | [Vertex AI - DeepSeek Models](https://cloud.google.com/vertex-ai/generative-ai/docs/maas/deepseek) |
|
||||
| ZAI (GLM) | `vertex_ai/zai-org/{MODEL}` | [Vertex AI - GLM Models](https://cloud.google.com/vertex-ai/generative-ai/docs/maas/zaiorg/glm-47) |
|
||||
| Meta/Llama | `vertex_ai/meta/{MODEL}` | [Vertex AI - Meta Models](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/llama) |
|
||||
| Mistral | `vertex_ai/mistral-*` | [Vertex AI - Mistral Models](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/mistral) |
|
||||
| AI21 (Jamba) | `vertex_ai/jamba-*` | [Vertex AI - AI21 Models](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/ai21) |
|
||||
|
|
@ -226,6 +227,79 @@ ModelResponse(
|
|||
|------------------|------------------------------|
|
||||
| vertex_ai/deepseek-ai/deepseek-r1-0528-maas | `completion('vertex_ai/deepseek-ai/deepseek-r1-0528-maas', messages)` |
|
||||
|
||||
## VertexAI ZAI (GLM)
|
||||
|
||||
| Property | Details |
|
||||
|----------|---------|
|
||||
| Provider Route | `vertex_ai/zai-org/{MODEL}` |
|
||||
| Vertex Documentation | [Vertex AI - GLM Models](https://cloud.google.com/vertex-ai/generative-ai/docs/maas/zaiorg/glm-47) |
|
||||
|
||||
**LiteLLM Supports all Vertex AI GLM Models.** Ensure you use the `vertex_ai/zai-org/` prefix for all Vertex AI GLM models.
|
||||
|
||||
| Model Name | Usage |
|
||||
|------------|-------|
|
||||
| vertex_ai/zai-org/glm-4.7-maas | `completion('vertex_ai/zai-org/glm-4.7-maas', messages)` |
|
||||
|
||||
#### Usage
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
from litellm import completion
|
||||
import os
|
||||
|
||||
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = ""
|
||||
|
||||
response = completion(
|
||||
model="vertex_ai/zai-org/glm-4.7-maas",
|
||||
messages=[{"role": "user", "content": "hi"}],
|
||||
vertex_project="your-vertex-project",
|
||||
# vertex_location routes to "global"
|
||||
)
|
||||
print("\nModel Response", response)
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="proxy" label="Proxy">
|
||||
|
||||
**1. Add to config**
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: glm-4.7
|
||||
litellm_params:
|
||||
model: vertex_ai/zai-org/glm-4.7-maas
|
||||
vertex_project: "my-project"
|
||||
# vertex_location routes to "global"
|
||||
```
|
||||
|
||||
**2. Start proxy**
|
||||
|
||||
```bash
|
||||
litellm --config /path/to/config.yaml
|
||||
|
||||
# RUNNING at http://0.0.0.0:4000
|
||||
```
|
||||
|
||||
**3. Test it!**
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"model": "glm-4.7",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "what llm are you"
|
||||
}
|
||||
],
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## VertexAI Meta/Llama API
|
||||
|
||||
|
|
|
|||
|
|
@ -778,6 +778,7 @@ router_settings:
|
|||
| LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRIES | Maximum retries for parallel requests in LiteLLM
|
||||
| LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRY_TIMEOUT | Timeout for retries of parallel requests in LiteLLM
|
||||
| LITELLM_DISABLE_LAZY_LOADING | When set to "1", "true", "yes", or "on", disables lazy loading of attributes (currently only affects encoding/tiktoken). This ensures encoding is initialized before VCR starts recording HTTP requests, fixing VCR cassette creation issues. See [issue #18659](https://github.com/BerriAI/litellm/issues/18659)
|
||||
| LITELLM_DISABLE_REDACT_SECRETS | When set to "true", disables automatic redaction of secrets (API keys, tokens, credentials) from proxy log output. Secret redaction is enabled by default.
|
||||
| LITELLM_MIGRATION_DIR | Custom migrations directory for prisma migrations, used for baselining db in read-only file systems.
|
||||
| LITELLM_HOSTED_UI | URL of the hosted UI for LiteLLM
|
||||
| LITELLM_UI_API_DOC_BASE_URL | Optional override for the API Reference base URL (used in sample code/docs) when the admin UI runs on a different host than the proxy. Defaults to `PROXY_BASE_URL` when unset.
|
||||
|
|
@ -910,6 +911,7 @@ router_settings:
|
|||
| PILLAR_API_BASE | Base URL for Pillar API Guardrails
|
||||
| PILLAR_API_KEY | API key for Pillar API Guardrails
|
||||
| PILLAR_ON_FLAGGED_ACTION | Action to take when content is flagged ('block' or 'monitor')
|
||||
| PKCE_STRICT_CACHE_MISS | When set to `true`, the SSO callback will return a 401 error if the PKCE code_verifier is not found in the cache (e.g. due to a cache miss across pods). When `false` (default), it logs a warning and continues without the code_verifier.
|
||||
| POD_NAME | Pod name for the server, this will be [emitted to `datadog` logs](https://docs.litellm.ai/docs/proxy/logging#datadog) as `POD_NAME`
|
||||
| POSTHOG_API_KEY | API key for PostHog analytics integration
|
||||
| POSTHOG_API_URL | Base URL for PostHog API (defaults to https://us.i.posthog.com)
|
||||
|
|
@ -934,6 +936,9 @@ router_settings:
|
|||
| PROXY_BASE_URL | Base URL for proxy service
|
||||
| PROXY_BATCH_WRITE_AT | Time in seconds to wait before batch writing spend logs to the database. Default is 10
|
||||
| PROXY_BATCH_POLLING_INTERVAL | Time in seconds to wait before polling a batch, to check if it's completed. Default is 6000s (1 hour)
|
||||
| PROXY_BATCH_POLLING_ENABLED | Set to `false` to disable the `CheckBatchCost` and `CheckResponsesCost` background polling jobs entirely. Useful for emergency mitigation on installs with large numbers of stale managed objects. Default is `true`
|
||||
| MAX_OBJECTS_PER_POLL_CYCLE | Maximum number of managed objects (batches / responses) fetched per polling cycle. Prevents OOM on installs with many stale rows. Default is `50`
|
||||
| MANAGED_OBJECT_STALENESS_CUTOFF_DAYS | Managed objects older than this many days in a non-terminal state are marked `stale_expired` at the start of each poll cycle and skipped. Default is `7`
|
||||
| PROXY_BUDGET_RESCHEDULER_MAX_TIME | Maximum time in seconds to wait before checking database for budget resets. Default is 605
|
||||
| PROXY_BUDGET_RESCHEDULER_MIN_TIME | Minimum time in seconds to wait before checking database for budget resets. Default is 597
|
||||
| PYTHON_GC_THRESHOLD | GC thresholds ('gen0,gen1,gen2', e.g. '1000,50,50'); defaults to Python’s values.
|
||||
|
|
@ -1017,6 +1022,11 @@ router_settings:
|
|||
| UPSTREAM_LANGFUSE_SECRET_KEY | Secret key for upstream Langfuse authentication
|
||||
| USE_AWS_KMS | Flag to enable AWS Key Management Service for encryption
|
||||
| USE_PRISMA_MIGRATE | Flag to use prisma migrate instead of prisma db push. Recommended for production environments.
|
||||
| VANTAGE_API_KEY | API key for Vantage cost-import integration
|
||||
| VANTAGE_BASE_URL | Base URL for Vantage API. Default is `https://api.vantage.sh`
|
||||
| VANTAGE_EXPORT_FREQUENCY | Export frequency for Vantage — `hourly` (default), `daily`, or `interval`
|
||||
| VANTAGE_EXPORT_INTERVAL_SECONDS | Interval in seconds when VANTAGE_EXPORT_FREQUENCY is `interval`
|
||||
| VANTAGE_INTEGRATION_TOKEN | Vantage integration token for the cost-import endpoint
|
||||
| WANDB_API_KEY | API key for Weights & Biases (W&B) logging integration
|
||||
| WANDB_HOST | Host URL for Weights & Biases (W&B) service
|
||||
| WANDB_PROJECT_ID | Project ID for Weights & Biases (W&B) logging integration
|
||||
|
|
|
|||
84
docs/my-website/docs/proxy/realtime_webrtc.md
Normal file
84
docs/my-website/docs/proxy/realtime_webrtc.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# /realtime - WebRTC Support
|
||||
|
||||
Connect to the Realtime API via WebRTC from browser/mobile clients. LiteLLM handles auth; audio streams directly to OpenAI/Azure.
|
||||
|
||||
**Providers:** OpenAI · Azure
|
||||
|
||||
:::info **WebRTC vs WebSocket**
|
||||
- **WebSocket** (`/v1/realtime`) — server-to-server
|
||||
- **WebRTC** (`/v1/realtime/client_secrets` + `/v1/realtime/calls`) — browser/mobile, lower latency
|
||||
:::
|
||||
|
||||
## How it works
|
||||
|
||||
LiteLLM issues tokens and relays SDP; audio never passes through the proxy.
|
||||
|
||||
```
|
||||
Browser LiteLLM Proxy OpenAI/Azure
|
||||
| | |
|
||||
|-- POST client_secrets --->|-- POST sessions -------->|
|
||||
|<-- encrypted_token -------|<-- ek_... ---------------|
|
||||
|-- POST calls [SDP+token] ->|-- POST calls ----------->|
|
||||
|<-- SDP answer ------------|<-- SDP answer -----------|
|
||||
|===== audio P2P direct ===============================>|
|
||||
```
|
||||
|
||||
## Proxy Setup
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: gpt-4o-realtime
|
||||
litellm_params:
|
||||
model: openai/gpt-4o-realtime-preview-2024-12-17
|
||||
api_key: os.environ/OPENAI_API_KEY
|
||||
model_info:
|
||||
mode: realtime
|
||||
```
|
||||
|
||||
**Azure:** `model: azure/gpt-4o-realtime-preview`, `api_key`, `api_base`.
|
||||
|
||||
```bash
|
||||
litellm --config /path/to/config.yaml
|
||||
```
|
||||
|
||||
## Client Usage
|
||||
|
||||
1. **Token** — `POST /v1/realtime/client_secrets` with LiteLLM key and `{ model }`.
|
||||
2. **WebRTC** — Create `RTCPeerConnection`, add mic, data channel `oai-events`, send SDP offer to `POST /v1/realtime/calls` with `Authorization: Bearer <token>`, `Content-Type: application/sdp`.
|
||||
3. **Events** — Use data channel for `session.update` and other events.
|
||||
|
||||
```javascript
|
||||
const r = await fetch("http://proxy:4000/v1/realtime/client_secrets", {
|
||||
method: "POST",
|
||||
headers: { "Authorization": "Bearer sk-litellm-key", "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ model: "gpt-4o-realtime" }),
|
||||
});
|
||||
const token = (await r.json()).client_secret.value;
|
||||
|
||||
const pc = new RTCPeerConnection();
|
||||
const audio = document.createElement("audio");
|
||||
audio.autoplay = true;
|
||||
pc.ontrack = (e) => (audio.srcObject = e.streams[0]);
|
||||
const ms = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
pc.addTrack(ms.getTracks()[0]);
|
||||
const dc = pc.createDataChannel("oai-events");
|
||||
const offer = await pc.createOffer();
|
||||
await pc.setLocalDescription(offer);
|
||||
|
||||
const sdpRes = await fetch("http://proxy:4000/v1/realtime/calls", {
|
||||
method: "POST",
|
||||
headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/sdp" },
|
||||
body: offer.sdp,
|
||||
});
|
||||
await pc.setRemoteDescription({ type: "answer", sdp: await sdpRes.text() });
|
||||
|
||||
dc.send(JSON.stringify({ type: "session.update", session: { instructions: "..." } }));
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
- **401 Token expired** — Get a fresh token right before creating the WebRTC offer.
|
||||
- **Which key for `/calls`?** — Encrypted token from `client_secrets`, not raw key.
|
||||
- **Pass `model`?** — No. Token encodes routing.
|
||||
- **Azure `api-version`** — Set `api_version` in `litellm_params` and correct `api_base`.
|
||||
- **No audio** — Grant mic; ensure `pc.ontrack` sets autoplay audio; check firewall/WebRTC; inspect console.
|
||||
|
|
@ -209,6 +209,106 @@ Expect to see the following response header when this works
|
|||
x-litellm-model-id: default-model
|
||||
```
|
||||
|
||||
## Regex-based tag routing (`tag_regex`)
|
||||
|
||||
Use `tag_regex` to route requests based on regex patterns matched against request headers, without requiring clients to pass a tag explicitly. This is useful when clients already send a recognisable header, such as `User-Agent`.
|
||||
|
||||
**Use case: route all Claude Code traffic to dedicated AWS accounts**
|
||||
|
||||
Claude Code always sends `User-Agent: claude-code/<version>`. With `tag_regex` you can route that traffic to a dedicated deployment automatically — no per-developer configuration needed.
|
||||
|
||||
### 1. Config
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
# Claude Code traffic → dedicated deployment, matched by User-Agent
|
||||
- model_name: claude-sonnet
|
||||
litellm_params:
|
||||
model: bedrock/converse/anthropic-claude-sonnet-4-6
|
||||
aws_region_name: us-east-1
|
||||
aws_role_name: arn:aws:iam::111122223333:role/LiteLLMClaudeCode
|
||||
tag_regex:
|
||||
- "^User-Agent: claude-code\\/" # matches claude-code/1.x, 2.x, etc.
|
||||
model_info:
|
||||
id: claude-code-deployment
|
||||
|
||||
# All other traffic falls back to the default deployment
|
||||
- model_name: claude-sonnet
|
||||
litellm_params:
|
||||
model: bedrock/converse/anthropic-claude-sonnet-4-6
|
||||
aws_region_name: us-east-1
|
||||
aws_role_name: arn:aws:iam::444455556666:role/LiteLLMDefault
|
||||
tags:
|
||||
- default
|
||||
model_info:
|
||||
id: regular-deployment
|
||||
|
||||
router_settings:
|
||||
enable_tag_filtering: true
|
||||
tag_filtering_match_any: true
|
||||
|
||||
general_settings:
|
||||
master_key: sk-1234
|
||||
```
|
||||
|
||||
### 2. Verify routing
|
||||
|
||||
Claude Code sets `User-Agent: claude-code/<version>` automatically — no client config needed:
|
||||
|
||||
```shell
|
||||
# Claude Code request (User-Agent set automatically by Claude Code)
|
||||
curl http://localhost:4000/v1/chat/completions \
|
||||
-H "Authorization: Bearer sk-1234" \
|
||||
-H "User-Agent: claude-code/1.2.3" \
|
||||
-d '{"model": "claude-sonnet", "messages": [{"role": "user", "content": "hi"}]}'
|
||||
# → x-litellm-model-id: claude-code-deployment
|
||||
|
||||
# Any other client (no matching User-Agent) → default deployment
|
||||
curl http://localhost:4000/v1/chat/completions \
|
||||
-H "Authorization: Bearer sk-1234" \
|
||||
-d '{"model": "claude-sonnet", "messages": [{"role": "user", "content": "hi"}]}'
|
||||
# → x-litellm-model-id: regular-deployment
|
||||
```
|
||||
|
||||
### How matching works
|
||||
|
||||
| Priority | Condition | Result |
|
||||
|----------|-----------|--------|
|
||||
| 1 | Request has `tags` AND deployment has `tags` | Exact tag match (respects `match_any` setting) |
|
||||
| 2 | Deployment has `tag_regex` AND request has a `User-Agent` | Regex match (always OR logic — any pattern match suffices) |
|
||||
| 3 | Deployment has `tags: [default]` | Default fallback |
|
||||
| 4 | No default set | All healthy deployments returned |
|
||||
|
||||
`tag_regex` always uses OR semantics — `tag_filtering_match_any=False` applies only to exact tag matching, not to regex patterns.
|
||||
|
||||
### Observability
|
||||
|
||||
When a regex matches, `tag_routing` is written into request metadata and flows to SpendLogs:
|
||||
|
||||
```json
|
||||
{
|
||||
"tag_routing": {
|
||||
"matched_via": "tag_regex",
|
||||
"matched_value": "^User-Agent: claude-code\\/",
|
||||
"user_agent": "claude-code/1.2.3",
|
||||
"request_tags": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Security note
|
||||
|
||||
:::caution
|
||||
|
||||
**`User-Agent` is a client-supplied header and can be set to any value.** Any API consumer can send `User-Agent: claude-code/1.0` regardless of whether they are actually using Claude Code.
|
||||
|
||||
Do not rely on `tag_regex` routing to enforce access controls or spend limits — use [team/key-based routing](./users) for that. `tag_regex` is a **traffic classification hint** (useful for billing visibility, capacity planning, and routing convenience), not a security boundary.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
---
|
||||
|
||||
## ✨ Team based tag routing (Enterprise)
|
||||
|
||||
LiteLLM Proxy supports team-based tag routing, allowing you to associate specific tags with teams and route requests accordingly. Example **Team A can access gpt-4 deployment A, Team B can access gpt-4 deployment B** (LLM Access Control For Teams)
|
||||
|
|
|
|||
|
|
@ -177,3 +177,7 @@ Expect to see this metric on prometheus to track the Remaining Budget for the te
|
|||
```shell
|
||||
litellm_remaining_team_budget_metric{team_alias="QA Prod Bot",team_id="de35b29e-6ca8-4f47-b804-2b79d07aa99a"} 9.699999999999992e-06
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [Per-model TPM/RPM for teams](./users.md#per-team-model) - Set rate limits per model for all keys in a team
|
||||
|
|
|
|||
138
docs/my-website/docs/proxy/ui/ui_edit_logo.md
Normal file
138
docs/my-website/docs/proxy/ui/ui_edit_logo.md
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
import Image from '@theme/IdealImage';
|
||||
|
||||
# Customize UI Logo
|
||||
|
||||
Personalize your LiteLLM dashboard by replacing the default logo with your own company branding. You can set a custom logo via the UI or the API.
|
||||
|
||||
## Via the UI
|
||||
|
||||
### 1. Navigate to Settings
|
||||
|
||||
Click the **Settings** icon in the sidebar.
|
||||
|
||||

|
||||
|
||||
### 2. Open UI Theme Settings
|
||||
|
||||
Click **UI Theme** from the settings menu.
|
||||
|
||||

|
||||
|
||||
### 3. Click the Logo URL Field
|
||||
|
||||
Click the **Logo URL** text field to start editing.
|
||||
|
||||

|
||||
|
||||
### 4. Find Your Logo Image
|
||||
|
||||
Open a new browser tab and find the logo image you want to use (e.g., search Google Images for your company logo).
|
||||
|
||||

|
||||
|
||||
### 5. Right-Click on the Logo Image
|
||||
|
||||
Right-click the image you want to use as your logo.
|
||||
|
||||

|
||||
|
||||
### 6. Copy the Image Address
|
||||
|
||||
Select **Copy Image Address** from the context menu to copy the URL.
|
||||
|
||||

|
||||
|
||||
### 7. Switch Back to LiteLLM
|
||||
|
||||
Navigate back to the LiteLLM UI tab (e.g., press **Cmd + Left** or click the tab).
|
||||
|
||||

|
||||
|
||||
### 8. Paste the Logo URL
|
||||
|
||||
Paste the copied image URL into the **Logo URL** field with **Cmd + V**.
|
||||
|
||||

|
||||
|
||||
### 9. Save Changes
|
||||
|
||||
Click **Save Changes** to apply your new logo.
|
||||
|
||||

|
||||
|
||||
Your custom logo will now appear in the LiteLLM dashboard sidebar and login page.
|
||||
|
||||
## Via the API
|
||||
|
||||
### Set a Custom Logo
|
||||
|
||||
```bash
|
||||
curl -X PATCH 'http://localhost:4000/settings/update/ui_theme_settings' \
|
||||
-H 'Authorization: Bearer <your-admin-key>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"logo_url": "https://example.com/your-company-logo.png"
|
||||
}'
|
||||
```
|
||||
|
||||
### Set a Custom Favicon
|
||||
|
||||
You can also customize the browser tab favicon:
|
||||
|
||||
```bash
|
||||
curl -X PATCH 'http://localhost:4000/settings/update/ui_theme_settings' \
|
||||
-H 'Authorization: Bearer <your-admin-key>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"logo_url": "https://example.com/your-company-logo.png",
|
||||
"favicon_url": "https://example.com/your-favicon.ico"
|
||||
}'
|
||||
```
|
||||
|
||||
### Get Current Theme Settings
|
||||
|
||||
```bash
|
||||
curl -X GET 'http://localhost:4000/settings/get/ui_theme_settings'
|
||||
```
|
||||
|
||||
### Reset to Default Logo
|
||||
|
||||
Send an empty `logo_url` to restore the default LiteLLM logo:
|
||||
|
||||
```bash
|
||||
curl -X PATCH 'http://localhost:4000/settings/update/ui_theme_settings' \
|
||||
-H 'Authorization: Bearer <your-admin-key>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"logo_url": ""
|
||||
}'
|
||||
```
|
||||
|
||||
## Via `proxy_config.yaml`
|
||||
|
||||
You can also set the logo URL in your proxy configuration file:
|
||||
|
||||
```yaml
|
||||
litellm_settings:
|
||||
ui_theme_config:
|
||||
logo_url: "https://example.com/your-company-logo.png"
|
||||
favicon_url: "https://example.com/your-favicon.ico" # optional
|
||||
```
|
||||
|
||||
Or set it as an environment variable:
|
||||
|
||||
```yaml
|
||||
environment_variables:
|
||||
UI_LOGO_PATH: "https://example.com/your-company-logo.png"
|
||||
```
|
||||
|
||||
## Supported Logo Formats
|
||||
|
||||
| Format | Supported |
|
||||
|--------|-----------|
|
||||
| JPEG / JPG | Yes |
|
||||
| PNG | Yes |
|
||||
| SVG | Yes |
|
||||
| ICO (favicon only) | Yes |
|
||||
| HTTP/HTTPS URL | Yes |
|
||||
| Local file path | Yes |
|
||||
|
|
@ -641,7 +641,7 @@ You can set:
|
|||
- tpm limits (tokens per minute)
|
||||
- rpm limits (requests per minute)
|
||||
- max parallel requests
|
||||
- rpm / tpm limits per model for a given key
|
||||
- rpm / tpm limits per model for a given key or team
|
||||
|
||||
### TPM Rate Limit Type (Input/Output/Total)
|
||||
|
||||
|
|
@ -689,6 +689,62 @@ curl --location 'http://0.0.0.0:4000/team/new' \
|
|||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="per-team-model" label="Per Team Per Model">
|
||||
|
||||
**Set rate limits per model for a team**
|
||||
|
||||
Use `model_rpm_limit` and `model_tpm_limit` to set rate limits per model for all keys belonging to a team. These limits apply across all keys in the team and are inherited by keys unless overridden at the key level.
|
||||
|
||||
Use `/team/new` or `/team/update` with `model_rpm_limit` and `model_tpm_limit` as dictionaries mapping model names to their limits:
|
||||
|
||||
```shell
|
||||
curl --location 'http://0.0.0.0:4000/team/new' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"team_id": "my-prod-team",
|
||||
"model_rpm_limit": {"gpt-4": 100, "gpt-3.5-turbo": 200},
|
||||
"model_tpm_limit": {"gpt-4": 10000, "gpt-3.5-turbo": 20000}
|
||||
}'
|
||||
```
|
||||
|
||||
**Update existing team with per-model limits:**
|
||||
|
||||
```shell
|
||||
curl --location 'http://0.0.0.0:4000/team/update' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"team_id": "my-prod-team",
|
||||
"model_rpm_limit": {"gpt-4": 100, "gpt-3.5-turbo": 200},
|
||||
"model_tpm_limit": {"gpt-4": 10000, "gpt-3.5-turbo": 20000}
|
||||
}'
|
||||
```
|
||||
|
||||
**Alternative: Use metadata**
|
||||
|
||||
You can also pass per-model limits via the `metadata` field:
|
||||
|
||||
```shell
|
||||
curl --location 'http://0.0.0.0:4000/team/update' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"team_id": "my-prod-team",
|
||||
"metadata": {
|
||||
"model_rpm_limit": {"gpt-4": 100, "gpt-3.5-turbo": 200},
|
||||
"model_tpm_limit": {"gpt-4": 10000, "gpt-3.5-turbo": 20000}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**Resolution order:** When a key belongs to a team, rate limits are resolved as: **Key metadata > Key model_max_budget > Team metadata**. Keys can override team-level per-model limits with their own `model_rpm_limit` or `model_tpm_limit`.
|
||||
|
||||
**Verify:** Make a `/chat/completions` request and check response headers `x-litellm-key-remaining-requests-{model}` and `x-litellm-key-remaining-tokens-{model}` for the model-specific limits.
|
||||
|
||||
[**See Swagger**](https://litellm-api.up.railway.app/#/team%20management/new_team_team_new_post)
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="per-user" label="Per Internal User">
|
||||
|
||||
|
|
|
|||
|
|
@ -594,7 +594,9 @@ Expected Response
|
|||
|
||||
:::tip gpt-5.4: reasoning_effort + function tools
|
||||
|
||||
OpenAI does not support `reasoning_effort` with function tools for `gpt-5.4` in `/v1/chat/completions`. Use `openai/responses/gpt-5.4` to route through the Responses API instead. See [Responses API Bridge](/docs/providers/openai#openai-chat-completion-to-responses-api-bridge) for details.
|
||||
LiteLLM drops `reasoning_effort` from `gpt-5.4` requests to `litellm.completion()` that include tools, since that combination is supported in the Responses API.
|
||||
|
||||
If you need reasoning **and** tools together, use `openai/responses/gpt-5.4` to route through the Responses API instead. See [Responses API Bridge](/docs/providers/openai#openai-chat-completion-to-responses-api-bridge) for details.
|
||||
|
||||
:::
|
||||
|
||||
|
|
|
|||
99
docs/my-website/docs/tutorials/claude_code_skills.md
Normal file
99
docs/my-website/docs/tutorials/claude_code_skills.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# LiteLLM Skills
|
||||
|
||||
[litellm-skills](https://github.com/BerriAI/litellm-skills) is a collection of [Agent Skills](https://agentskills.io) for managing a live LiteLLM proxy. Install them once and any agent that supports the Agent Skills standard (Claude Code, OpenCode, OpenClaw, etc.) can create users, teams, keys, models, MCP servers, agents, and query usage — all by running `curl` commands against your proxy.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/BerriAI/litellm-skills/main/install.sh | sh
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- `curl` installed
|
||||
- A running LiteLLM proxy (local or remote)
|
||||
- A proxy admin key — not a virtual key scoped to `llm_api_routes`
|
||||
|
||||
## Available Skills
|
||||
|
||||
### Users
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-user` | Create a user — email, role, budget, model access |
|
||||
| `/update-user` | Update budget, role, or models for an existing user |
|
||||
| `/delete-user` | Delete one or more users |
|
||||
|
||||
### Teams
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-team` | Create a team with budget and model limits |
|
||||
| `/update-team` | Update budget, models, or rate limits |
|
||||
| `/delete-team` | Delete one or more teams |
|
||||
|
||||
### API Keys
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-key` | Generate a key scoped to a user, team, budget, and expiry |
|
||||
| `/update-key` | Update budget, models, or expiry |
|
||||
| `/delete-key` | Delete by key value or alias |
|
||||
|
||||
### Organizations
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-org` | Create an org with budget and model access |
|
||||
| `/delete-org` | Delete one or more orgs |
|
||||
|
||||
### Models
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-model` | Add any provider (OpenAI, Azure, Anthropic, Bedrock, Ollama…) and test it |
|
||||
| `/update-model` | Rotate credentials or swap the underlying deployment |
|
||||
| `/delete-model` | Remove a model |
|
||||
|
||||
### MCP Servers
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-mcp` | Register an MCP server (SSE, HTTP, or stdio) |
|
||||
| `/update-mcp` | Update URL, credentials, or allowed tools |
|
||||
| `/delete-mcp` | Remove an MCP server |
|
||||
|
||||
### Agents
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/add-agent` | Create an agent backed by a model and optional MCP servers |
|
||||
| `/update-agent` | Swap the model or update description and limits |
|
||||
| `/delete-agent` | Remove an agent |
|
||||
|
||||
### Usage
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|-------------|
|
||||
| `/view-usage` | Daily spend and token activity — by user, team, org, or model |
|
||||
|
||||
## How it works
|
||||
|
||||
When you invoke a skill, the agent asks for your `LITELLM_BASE_URL` and admin key, collects the fields needed for that operation, runs the `curl`, and shows the result. For example:
|
||||
|
||||
```
|
||||
/add-model
|
||||
```
|
||||
→ Agent asks: provider, public name, credentials. Adds the model, runs a test completion, reports pass/fail.
|
||||
|
||||
```
|
||||
/view-usage
|
||||
```
|
||||
→ Agent asks: date range (defaults to current month), optional team/model filter. Prints a table of daily requests, tokens, and spend.
|
||||
|
||||
## Related
|
||||
|
||||
- [litellm-skills on GitHub](https://github.com/BerriAI/litellm-skills)
|
||||
- [Virtual Keys](../proxy/virtual_keys.md) — managing API keys on the proxy
|
||||
- [Team-based routing](../proxy/team_based_routing.md) — setting up teams
|
||||
- [Model Management](../proxy/model_management.md) — adding models via config or API
|
||||
|
|
@ -290,6 +290,82 @@ curl --location 'http://localhost:4000/v1/videos' \
|
|||
--header 'custom-llm-provider: azure'
|
||||
```
|
||||
|
||||
### Character, Edit, and Extension Endpoints
|
||||
|
||||
LiteLLM proxy also supports these OpenAI-compatible video routes:
|
||||
|
||||
- `POST /v1/videos/characters`
|
||||
- `GET /v1/videos/characters/{character_id}`
|
||||
- `POST /v1/videos/edits`
|
||||
- `POST /v1/videos/extensions`
|
||||
|
||||
#### Routing Behavior (`target_model_names`, encoded IDs, and provider overrides)
|
||||
|
||||
- `POST /v1/videos/characters` supports `target_model_names` like `POST /v1/videos`.
|
||||
- When `target_model_names` is provided on character creation, LiteLLM encodes the returned `character_id` with routing metadata.
|
||||
- `GET /v1/videos/characters/{character_id}` accepts encoded character IDs directly. LiteLLM decodes the ID internally and routes with the correct model/provider metadata.
|
||||
- `POST /v1/videos/edits` and `POST /v1/videos/extensions` support both:
|
||||
- plain `video.id`
|
||||
- encoded `video.id` values returned by LiteLLM
|
||||
- `custom_llm_provider` can be supplied using the same patterns as other proxy endpoints:
|
||||
- header: `custom-llm-provider`
|
||||
- query: `?custom_llm_provider=...`
|
||||
- body: `custom_llm_provider` (or `extra_body.custom_llm_provider` where applicable)
|
||||
|
||||
#### Character create with `target_model_names`
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/characters' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
-F 'name=hero' \
|
||||
-F 'target_model_names=gpt-4' \
|
||||
-F 'video=@/path/to/character.mp4'
|
||||
```
|
||||
|
||||
Example response (encoded `id`):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "character_...",
|
||||
"object": "character",
|
||||
"created_at": 1712697600,
|
||||
"name": "hero"
|
||||
}
|
||||
```
|
||||
|
||||
#### Get character using encoded `character_id`
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/characters/character_...' \
|
||||
--header 'Authorization: Bearer sk-1234'
|
||||
```
|
||||
|
||||
#### Video edit with encoded `video.id`
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/edits' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"prompt": "Make this brighter",
|
||||
"video": { "id": "video_..." }
|
||||
}'
|
||||
```
|
||||
|
||||
#### Video extension with provider override from `extra_body`
|
||||
|
||||
```bash
|
||||
curl --location 'http://localhost:4000/v1/videos/extensions' \
|
||||
--header 'Authorization: Bearer sk-1234' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"prompt": "Continue this scene",
|
||||
"seconds": "4",
|
||||
"video": { "id": "video_..." },
|
||||
"extra_body": { "custom_llm_provider": "openai" }
|
||||
}'
|
||||
```
|
||||
|
||||
Test Azure video generation request
|
||||
|
||||
```bash
|
||||
|
|
|
|||
BIN
docs/my-website/img/ephemeral_token.png
Normal file
BIN
docs/my-website/img/ephemeral_token.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 290 KiB |
BIN
docs/my-website/img/webrtc_flow.png
Normal file
BIN
docs/my-website/img/webrtc_flow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 238 KiB |
374
docs/my-website/release_notes/v1.82.3.md
Normal file
374
docs/my-website/release_notes/v1.82.3.md
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
---
|
||||
title: "v1.82.3 - Nebius AI, gpt-5.4, Gemini 3.x, FLUX Kontext, and 116 New Models"
|
||||
slug: "v1-82-3"
|
||||
date: 2026-03-16T00:00:00
|
||||
authors:
|
||||
- name: Krrish Dholakia
|
||||
title: CEO, LiteLLM
|
||||
url: https://www.linkedin.com/in/krish-d/
|
||||
image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg
|
||||
- name: Ishaan Jaff
|
||||
title: CTO, LiteLLM
|
||||
url: https://www.linkedin.com/in/reffajnaahsi/
|
||||
image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
## Deploy this version
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="docker" label="Docker">
|
||||
|
||||
``` showLineNumbers title="docker run litellm"
|
||||
docker run \
|
||||
-e STORE_MODEL_IN_DB=True \
|
||||
-p 4000:4000 \
|
||||
ghcr.io/berriai/litellm:main-1.82.3-stable
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="pip" label="Pip">
|
||||
|
||||
``` showLineNumbers title="pip install litellm"
|
||||
pip install litellm==1.82.3
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Key Highlights
|
||||
|
||||
- **Nebius AI — new provider** — [30 models across DeepSeek, Qwen, Llama, Mistral, NVIDIA, and BAAI available via Nebius AI cloud](../../docs/providers/nebius) - [PR #22614](https://github.com/BerriAI/litellm/pull/22614)
|
||||
- **OpenAI gpt-5.4 / gpt-5.4-pro — day 0** — Full pricing and routing support for `gpt-5.4` (1M context, $2.50/$15.00) and `gpt-5.4-pro` ($30.00/$180.00) on OpenAI and Azure
|
||||
- **Gemini 3.x models** — `gemini-3-flash-preview`, `gemini-3.1-pro-preview`, `gemini-3.1-flash-image-preview`, and `gemini-embedding-2-preview` added to cost map for Google AI and Vertex AI
|
||||
- **FLUX Kontext image editing** — `flux-kontext-pro` and `flux-kontext-max` added to Black Forest Labs, alongside `flux-pro-1.0-fill` and `flux-pro-1.0-expand` for inpainting and outpainting
|
||||
- **116 new models, 132 deprecated models cleaned up** — Major model map refresh including Mistral Magistral, Dashscope Qwen3 VL, xAI Grok via Azure AI, ZAI GLM-5, Serper Search; removal of OpenAI GPT-3.5/GPT-4 legacy variants, Gemini 1.5, and Vertex AI PaLM2
|
||||
- **SageMaker Nova provider** — [New `sagemaker_nova` provider for Amazon Nova models on SageMaker](../../docs/providers/aws_sagemaker) - [PR #21542](https://github.com/BerriAI/litellm/pull/21542)
|
||||
- **Secret redaction in logs** — API keys, tokens, and credentials automatically scrubbed from all proxy log output. Enabled by default; opt out with `LITELLM_DISABLE_REDACT_SECRETS=true` - [PR #23668](https://github.com/BerriAI/litellm/pull/23668)
|
||||
- **Streaming stability fix** — Critical fix for `RuntimeError: Cannot send a request, as the client has been closed.` crashes after ~1 hour in production - [PR #22926](https://github.com/BerriAI/litellm/pull/22926)
|
||||
|
||||
---
|
||||
|
||||
## New Providers and Endpoints
|
||||
|
||||
### New Providers (5 new providers)
|
||||
|
||||
| Provider | Supported LiteLLM Endpoints | Description |
|
||||
| -------- | --------------------------- | ----------- |
|
||||
| [Nebius AI](../../docs/providers/nebius) (`nebius/`) | `/chat/completions`, `/embeddings` | EU-based AI cloud with 30+ open models — DeepSeek, Qwen3, Llama 3.1/3.3, NVIDIA Nemotron, BAAI embeddings |
|
||||
| [ZAI](../../docs/providers/zai) (`zai/`) | `/chat/completions` | ZhipuAI GLM-5 models via ZAI cloud |
|
||||
| [Black Forest Labs](../../docs/providers/black_forest_labs) (`black_forest_labs/`) | `/images/generations`, `/images/edits` | FLUX image generation and editing — Kontext Pro/Max, Pro 1.0 Fill/Expand |
|
||||
| [Serper](../../docs/providers/serper) (`serper/`) | `/search` | Web search via Serper API |
|
||||
| [SageMaker Nova](../../docs/providers/aws_sagemaker) (`sagemaker_nova/`) | `/chat/completions` | Amazon Nova models via SageMaker endpoint |
|
||||
|
||||
---
|
||||
|
||||
## New Models / Updated Models
|
||||
|
||||
#### New Model Support (116 new models)
|
||||
|
||||
| Provider | Model | Context Window | Input ($/1M tokens) | Output ($/1M tokens) | Features |
|
||||
| -------- | ----- | -------------- | ------------------- | -------------------- | -------- |
|
||||
| OpenAI | `gpt-5.4` | 1.05M | $2.50 | $15.00 | chat, vision, tools, reasoning |
|
||||
| OpenAI | `gpt-5.4-pro` | 1.05M | $30.00 | $180.00 | responses, vision, tools, reasoning |
|
||||
| OpenAI | `gpt-5.3-chat-latest` | 128K | $1.75 | $14.00 | chat, vision, tools, reasoning |
|
||||
| Azure OpenAI | `azure/gpt-5.4` | 1.05M | $2.50 | $15.00 | chat, vision, tools, reasoning |
|
||||
| Azure OpenAI | `azure/gpt-5.4-pro` | 1.05M | $30.00 | $180.00 | responses, vision, tools, reasoning |
|
||||
| Azure OpenAI | `azure/gpt-5.3-chat` | 128K | $1.75 | $14.00 | chat, vision, tools, reasoning |
|
||||
| Google Gemini | `gemini/gemini-3-flash-preview` | 1M | $0.50 | $3.00 | chat, vision, tools, reasoning |
|
||||
| Google Gemini | `gemini/gemini-3.1-pro-preview` | 1M | $2.00 | $12.00 | chat, vision, tools, reasoning |
|
||||
| Google Gemini | `gemini/gemini-3.1-flash-image-preview` | 65K | $0.25 | $1.50 | image generation, vision |
|
||||
| Google Gemini | `gemini/gemini-3.1-flash-lite-preview` | - | - | - | chat |
|
||||
| Google Gemini | `gemini/gemini-3-pro-image-preview` | - | - | - | image generation |
|
||||
| Google Gemini | `gemini/gemini-embedding-2-preview` | 8K | $0.20 | - | embeddings |
|
||||
| Google Vertex AI | `vertex_ai/gemini-3-flash-preview` | - | - | - | chat |
|
||||
| Google Vertex AI | `vertex_ai/gemini-3.1-pro-preview` | - | - | - | chat |
|
||||
| Google Vertex AI | `vertex_ai/gemini-3.1-flash-lite-preview` | - | - | - | chat |
|
||||
| Google Vertex AI | `vertex_ai/gemini-embedding-2-preview` | - | $0.20 | - | embeddings |
|
||||
| Mistral | `mistral/magistral-medium-1-2-2509` | 40K | $2.00 | $5.00 | chat, tools, reasoning |
|
||||
| Mistral | `mistral/magistral-small-1-2-2509` | 40K | $0.50 | $1.50 | chat, tools, reasoning |
|
||||
| Mistral | `mistral/mistral-large-2512` | 262K | $0.50 | $1.50 | chat, vision, tools |
|
||||
| Mistral | `mistral/mistral-medium-3-1-2508` | - | - | - | chat |
|
||||
| Mistral | `mistral/mistral-small-3-2-2506` | - | - | - | chat |
|
||||
| Mistral | `mistral/ministral-3-3b-2512` | - | - | - | chat |
|
||||
| Mistral | `mistral/ministral-3-8b-2512` | - | - | - | chat |
|
||||
| Mistral | `mistral/ministral-3-14b-2512` | - | - | - | chat |
|
||||
| Black Forest Labs | `black_forest_labs/flux-kontext-pro` | - | - | - | image editing |
|
||||
| Black Forest Labs | `black_forest_labs/flux-kontext-max` | - | - | - | image editing |
|
||||
| Black Forest Labs | `black_forest_labs/flux-pro-1.0-fill` | - | - | - | image editing (inpaint) |
|
||||
| Black Forest Labs | `black_forest_labs/flux-pro-1.0-expand` | - | - | - | image editing (outpaint) |
|
||||
| Black Forest Labs | `black_forest_labs/flux-pro-1.1` | - | - | - | image generation |
|
||||
| Black Forest Labs | `black_forest_labs/flux-pro-1.1-ultra` | - | - | - | image generation |
|
||||
| Black Forest Labs | `black_forest_labs/flux-dev` | - | - | - | image generation |
|
||||
| Black Forest Labs | `black_forest_labs/flux-pro` | - | - | - | image generation |
|
||||
| Azure AI | `azure_ai/grok-4-1-fast-non-reasoning` | 131K | $0.20 | $0.50 | chat, tools |
|
||||
| Azure AI | `azure_ai/grok-4-1-fast-reasoning` | 131K | $0.20 | $0.50 | chat, tools, reasoning |
|
||||
| Azure AI | `azure_ai/mistral-document-ai-2512` | - | - | - | OCR |
|
||||
| Dashscope | `dashscope/qwen3-next-80b-a3b-instruct` | 262K | $0.15 | $1.20 | chat |
|
||||
| Dashscope | `dashscope/qwen3-next-80b-a3b-thinking` | 262K | $0.15 | $1.20 | chat, reasoning |
|
||||
| Dashscope | `dashscope/qwen3-vl-235b-a22b-instruct` | 131K | $0.40 | $1.60 | chat, vision |
|
||||
| Dashscope | `dashscope/qwen3-vl-235b-a22b-thinking` | 131K | $0.40 | $4.00 | chat, vision, reasoning |
|
||||
| Dashscope | `dashscope/qwen3-vl-32b-instruct` | 131K | $0.16 | $0.64 | chat, vision |
|
||||
| Dashscope | `dashscope/qwen3-vl-32b-thinking` | 131K | $0.16 | $2.87 | chat, vision, reasoning |
|
||||
| Dashscope | `dashscope/qwen3-vl-plus` | 260K | - | - | chat, vision |
|
||||
| Dashscope | `dashscope/qwen3.5-plus` | 992K | - | - | chat |
|
||||
| Dashscope | `dashscope/qwen3-max-2026-01-23` | 258K | - | - | chat |
|
||||
| Nebius AI | `nebius/deepseek-ai/DeepSeek-R1` | 128K | $0.80 | $2.40 | chat, reasoning |
|
||||
| Nebius AI | `nebius/deepseek-ai/DeepSeek-R1-0528` | 164K | $0.80 | $2.40 | chat, reasoning |
|
||||
| Nebius AI | `nebius/deepseek-ai/DeepSeek-V3` | 128K | $0.50 | $1.50 | chat |
|
||||
| Nebius AI | `nebius/deepseek-ai/DeepSeek-V3-0324` | 128K | $0.50 | $1.50 | chat |
|
||||
| Nebius AI | `nebius/deepseek-ai/DeepSeek-R1-Distill-Llama-70B` | 128K | $0.25 | $0.75 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen3-235B-A22B` | 262K | $0.20 | $0.60 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen3-32B` | 32K | $0.10 | $0.30 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen3-30B-A3B` | 32K | $0.10 | $0.30 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen3-14B` | 32K | $0.08 | $0.24 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen3-4B` | 32K | $0.08 | $0.24 | chat |
|
||||
| Nebius AI | `nebius/Qwen/QwQ-32B` | 32K | $0.15 | $0.45 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen2.5-72B-Instruct` | 128K | $0.13 | $0.40 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen2.5-32B-Instruct` | 128K | $0.06 | $0.20 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen2.5-VL-72B-Instruct` | 131K | $0.13 | $0.40 | chat, vision |
|
||||
| Nebius AI | `nebius/Qwen/Qwen2-VL-72B-Instruct` | 131K | $0.13 | $0.40 | chat, vision |
|
||||
| Nebius AI | `nebius/Qwen/Qwen2-VL-7B-Instruct` | 131K | $0.02 | $0.06 | chat, vision |
|
||||
| Nebius AI | `nebius/meta-llama/Meta-Llama-3.1-405B-Instruct` | 128K | $1.00 | $3.00 | chat |
|
||||
| Nebius AI | `nebius/meta-llama/Meta-Llama-3.1-70B-Instruct` | 128K | $0.13 | $0.40 | chat |
|
||||
| Nebius AI | `nebius/meta-llama/Meta-Llama-3.1-8B-Instruct` | 128K | $0.02 | $0.06 | chat |
|
||||
| Nebius AI | `nebius/meta-llama/Llama-3.3-70B-Instruct` | 128K | $0.13 | $0.40 | chat |
|
||||
| Nebius AI | `nebius/meta-llama/Llama-Guard-3-8B` | 128K | $0.02 | $0.06 | chat |
|
||||
| Nebius AI | `nebius/nvidia/Llama-3.1-Nemotron-Ultra-253B-v1` | 128K | $0.60 | $1.80 | chat |
|
||||
| Nebius AI | `nebius/nvidia/Llama-3.3-Nemotron-Super-49B-v1` | 131K | $0.10 | $0.40 | chat |
|
||||
| Nebius AI | `nebius/NousResearch/Hermes-3-Llama-3.1-405B` | 128K | $1.00 | $3.00 | chat |
|
||||
| Nebius AI | `nebius/google/gemma-3-27b-it` | 128K | $0.06 | $0.20 | chat |
|
||||
| Nebius AI | `nebius/mistralai/Mistral-Nemo-Instruct-2407` | 128K | $0.04 | $0.12 | chat |
|
||||
| Nebius AI | `nebius/Qwen/Qwen2.5-Coder-7B` | 32K | $0.01 | $0.03 | chat |
|
||||
| Nebius AI | `nebius/BAAI/bge-en-icl` | 32K | $0.01 | - | embeddings |
|
||||
| Nebius AI | `nebius/BAAI/bge-multilingual-gemma2` | 8K | $0.01 | - | embeddings |
|
||||
| Nebius AI | `nebius/intfloat/e5-mistral-7b-instruct` | 32K | $0.01 | - | embeddings |
|
||||
| AWS Bedrock | `mistral.devstral-2-123b` | 256K | $0.40 | $2.00 | chat, tools |
|
||||
| AWS Bedrock | `zai.glm-4.7-flash` | 200K | $0.07 | $0.40 | chat, tools, reasoning |
|
||||
| ZAI | `zai/glm-5` | 200K | $1.00 | $3.20 | chat, tools, reasoning |
|
||||
| ZAI | `zai/glm-5-code` | 200K | $1.20 | $5.00 | chat, tools, reasoning |
|
||||
| OpenRouter | `openrouter/anthropic/claude-sonnet-4.6` | - | - | - | chat |
|
||||
| OpenRouter | `openrouter/google/gemini-3.1-pro-preview` | - | - | - | chat |
|
||||
| OpenRouter | `openrouter/openai/gpt-5.1-codex-max` | - | - | - | chat |
|
||||
| OpenRouter | `openrouter/qwen/qwen3-coder-plus` | - | - | - | chat |
|
||||
| OpenRouter | `openrouter/qwen/qwen3.5-*` (5 models) | - | - | - | chat |
|
||||
| OpenRouter | `openrouter/z-ai/glm-5` | - | - | - | chat |
|
||||
| Together AI | `together_ai/Qwen/Qwen3.5-397B-A17B` | - | - | - | chat |
|
||||
| Perplexity | `perplexity/pplx-embed-v1-0.6b` | 32K | $0.00 | - | embeddings |
|
||||
| Perplexity | `perplexity/pplx-embed-v1-4b` | 32K | $0.03 | - | embeddings |
|
||||
| Serper | `serper/search` | - | - | - | search |
|
||||
|
||||
#### Updated Models
|
||||
|
||||
- **[AWS Bedrock](../../docs/providers/bedrock)**
|
||||
- Add `cache_read_input_token_cost` and `cache_creation_input_token_cost` to Bedrock-hosted Anthropic models (`claude-3-opus`, `claude-3-sonnet`, `claude-3-haiku`, and APAC/EU variants) — prompt caching is now tracked for cost estimation
|
||||
- Rename `apac.anthropic.claude-sonnet-4-6` → `au.anthropic.claude-sonnet-4-6` to reflect correct regional identifier
|
||||
|
||||
- **[Azure OpenAI](../../docs/providers/azure)**
|
||||
- Add `supports_none_reasoning_effort` to all `gpt-5.1-chat`, `gpt-5.1-codex`, and `gpt-5.4` variants (global, EU, standard deployments) — allows passing `reasoning_effort: null` to disable reasoning
|
||||
|
||||
- **[Azure OpenAI](../../docs/providers/azure)** — Removed deprecated models
|
||||
- Remove `azure/gpt-35-turbo-0301` (deprecated 2025-02-13)
|
||||
- Remove `azure/gpt-35-turbo-0613` (deprecated 2025-02-13)
|
||||
|
||||
#### Features
|
||||
|
||||
- **[OpenAI](../../docs/providers/openai)**
|
||||
- Day 0 support for `gpt-5.4` and `gpt-5.4-pro` on OpenAI and Azure
|
||||
|
||||
- **[Google Gemini](../../docs/providers/gemini)**
|
||||
- Add Gemini 3.x model cost map entries — `gemini-3-flash-preview`, `gemini-3.1-pro-preview`, `gemini-3.1-flash-lite-preview`, `gemini-3-pro-image-preview`, `gemini-embedding-2-preview`
|
||||
- Add Gemini 2.0 Flash and Flash Lite to cost map (re-added with updated pricing)
|
||||
|
||||
- **[Google Vertex AI](../../docs/providers/vertex)**
|
||||
- Add `gemini-3-flash-preview`, `gemini-3.1-flash-lite-preview`, `gemini-flash-experimental`, and `gemini-embedding-2-preview` to Vertex AI model cost map
|
||||
|
||||
- **[Mistral](../../docs/providers/mistral)**
|
||||
- Add Magistral reasoning models (`magistral-medium-1-2-2509`, `magistral-small-1-2-2509`)
|
||||
- Add `mistral-large-2512`, `mistral-medium-3-1-2508`, `mistral-small-3-2-2506`, `ministral-3-*` variants
|
||||
|
||||
- **[Dashscope / Qwen](../../docs/providers/dashscope)**
|
||||
- Add Qwen3 VL multimodal models (`qwen3-vl-235b`, `qwen3-vl-32b` — instruct and thinking variants)
|
||||
- Add `qwen3-next-80b-a3b` (instruct + thinking), `qwen3.5-plus`, `qwen3-max-2026-01-23`
|
||||
|
||||
- **[Black Forest Labs](../../docs/providers/black_forest_labs)**
|
||||
- Add FLUX Kontext image editing models (`flux-kontext-pro`, `flux-kontext-max`)
|
||||
- Add FLUX Pro 1.0 Fill (inpainting) and Expand (outpainting)
|
||||
- Add `flux-pro-1.1`, `flux-pro-1.1-ultra`, `flux-dev`, `flux-pro`
|
||||
|
||||
- **[Azure AI](../../docs/providers/azure_ai)**
|
||||
- Add xAI Grok models via Azure AI Foundry (`grok-4-1-fast-non-reasoning`, `grok-4-1-fast-reasoning`)
|
||||
- Add Mistral Document AI (`mistral-document-ai-2512`) — OCR mode
|
||||
|
||||
- **[AWS Bedrock](../../docs/providers/bedrock)**
|
||||
- Add `mistral.devstral-2-123b` (256K context, tools)
|
||||
- Add `zai.glm-4.7-flash` via Bedrock Converse (200K context, tools, reasoning)
|
||||
|
||||
- **[SageMaker](../../docs/providers/aws_sagemaker)**
|
||||
- Add `sagemaker_nova` provider for Amazon Nova models on SageMaker - [PR #21542](https://github.com/BerriAI/litellm/pull/21542)
|
||||
|
||||
#### Deprecated / Removed Models
|
||||
|
||||
**OpenAI** — Legacy models removed from cost map:
|
||||
- `gpt-3.5-turbo-0301`, `gpt-3.5-turbo-0613`, `gpt-3.5-turbo-16k-0613`
|
||||
- `gpt-4-0314`, `gpt-4-32k`, `gpt-4-32k-0314`, `gpt-4-32k-0613`, `gpt-4-1106-vision-preview`, `gpt-4-vision-preview`
|
||||
- `gpt-4.5-preview`, `gpt-4.5-preview-2025-02-27`
|
||||
- `gpt-4o-audio-preview-2024-10-01`, `gpt-4o-realtime-preview-2024-10-01`
|
||||
- `o1-mini`, `o1-mini-2024-09-12`, `o1-preview`, `o1-preview-2024-09-12`
|
||||
|
||||
**Google Gemini** — Gemini 1.5 and legacy 2.0 variants removed:
|
||||
- All `gemini-1.5-*` variants (flash, flash-8b, pro, and dated versions)
|
||||
- `gemini-2.0-flash-exp`, `gemini-2.0-pro-exp-02-05`, `gemini-2.5-flash-preview-04-17`, `gemini-2.5-flash-preview-05-20`
|
||||
|
||||
**Google Vertex AI** — PaLM 2 / legacy models removed:
|
||||
- All `chat-bison`, `text-bison`, `codechat-bison`, `code-bison`, `code-gecko` variants
|
||||
- Gemini 1.0 Pro, 1.5 Flash/Pro, 2.0 Flash experimental, and preview variants
|
||||
|
||||
**Perplexity** — Legacy Llama-sonar models removed:
|
||||
- `llama-3.1-sonar-huge-128k-online`, `llama-3.1-sonar-large/small-128k-chat/online`
|
||||
|
||||
---
|
||||
|
||||
## LLM API Endpoints
|
||||
|
||||
#### Features
|
||||
|
||||
- **[Responses API](../../docs/response_api)**
|
||||
- Handle `response.failed`, `response.incomplete`, and `response.cancelled` terminal event types in background streaming — previously only `response.completed` was handled - [PR #23492](https://github.com/BerriAI/litellm/pull/23492)
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
- **[Anthropic](../../docs/providers/anthropic)**
|
||||
- Preserve native tool format (web_search, bash, tool_search, etc.) when guardrails convert tools for the Anthropic Messages API - [PR #23526](https://github.com/BerriAI/litellm/pull/23526)
|
||||
|
||||
- **[Moonshot / Kimi](../../docs/providers/openai_compatible)**
|
||||
- Auto-fill `reasoning_content` for Moonshot Kimi reasoning models - [PR #23580](https://github.com/BerriAI/litellm/pull/23580)
|
||||
|
||||
- **[HuggingFace](../../docs/providers/huggingface)**
|
||||
- Forward `extra_headers` to HuggingFace embedding API - [PR #23525](https://github.com/BerriAI/litellm/pull/23525)
|
||||
|
||||
- **General**
|
||||
- Normalize `content_filtered` finish reason across providers - [PR #23564](https://github.com/BerriAI/litellm/pull/23564)
|
||||
- Fix custom cost tracking on deployments for `/v1/messages` and `/v1/responses` - [PR #23647](https://github.com/BerriAI/litellm/pull/23647)
|
||||
- Fix per-request custom pricing when `router_model_id` has no pricing data — now falls back to model name
|
||||
|
||||
---
|
||||
|
||||
## Management Endpoints / UI
|
||||
|
||||
#### Features
|
||||
|
||||
- **Virtual Keys**
|
||||
- Add Organization dropdown to Create/Edit Key form — `organization_id` is now a first-class field in Key Ownership - [PR #23595](https://github.com/BerriAI/litellm/pull/23595)
|
||||
- Allow setting `organization_id` on `/key/update` — keys can be assigned or moved to a different organization after creation - [PR #23557](https://github.com/BerriAI/litellm/pull/23557)
|
||||
|
||||
- **Internal Users**
|
||||
- Add/Remove Team Membership directly from the Internal Users info page — includes searchable dropdown and role selector; no longer requires navigating to each team - [PR #23638](https://github.com/BerriAI/litellm/pull/23638)
|
||||
|
||||
- **Default Team Settings**
|
||||
- Modernize page to antd (consistent with rest of app) - [PR #23614](https://github.com/BerriAI/litellm/pull/23614)
|
||||
- Fix: default team params (budget, duration, tpm, rpm, permissions) now correctly applied on `/team/new` - [PR #23614](https://github.com/BerriAI/litellm/pull/23614)
|
||||
- Fix: settings persist across proxy restarts (`default_team_params` added to `LITELLM_SETTINGS_SAFE_DB_OVERRIDES`) - [PR #23614](https://github.com/BerriAI/litellm/pull/23614)
|
||||
- Fix: resolved race condition in `_update_litellm_setting` where `get_config()` could overwrite freshly saved values - [PR #23614](https://github.com/BerriAI/litellm/pull/23614)
|
||||
|
||||
- **Usage**
|
||||
- Auto-paginate daily spend data — all entity views (teams, orgs, customers, tags, agents, users) fetch pages progressively with charts updating after each page - [PR #23622](https://github.com/BerriAI/litellm/pull/23622)
|
||||
|
||||
- **Models / Cost**
|
||||
- Azure Model Router cost breakdown in UI — show per-sub-model `additional_costs` from `hidden_params` in `CostBreakdownViewer` - [PR #23550](https://github.com/BerriAI/litellm/pull/23550)
|
||||
|
||||
- **User Management**
|
||||
- New `/user/info/v2` endpoint — scoped, paginated replacement for the existing god endpoint that caused memory and stability issues on large installs - [PR #23437](https://github.com/BerriAI/litellm/pull/23437)
|
||||
|
||||
#### Bugs
|
||||
|
||||
- Fix Tag list endpoint returning 500 due to invalid Prisma `group_by` kwargs - [PR #23606](https://github.com/BerriAI/litellm/pull/23606)
|
||||
- Fix Team Admin getting 403 on `/user/filter/ui` when `scope_user_search_to_org` is enabled - [PR #23671](https://github.com/BerriAI/litellm/pull/23671)
|
||||
- Fix Public Model Hub not showing config-defined models after save - [PR #23501](https://github.com/BerriAI/litellm/pull/23501)
|
||||
- Fix fallback popup model dropdown z-index issue - [PR #23516](https://github.com/BerriAI/litellm/pull/23516)
|
||||
- Fix double-counting bug in org/team key limit checks on `/key/update`
|
||||
|
||||
---
|
||||
|
||||
## AI Integrations
|
||||
|
||||
### Logging
|
||||
|
||||
- **[Vantage](https://vantage.sh)**
|
||||
- Add Vantage integration for FOCUS 1.2 CSV export — export LiteLLM proxy spend data as FinOps Open Cost & Usage Specification reports, with time-windowed filenames to prevent overwrites - [PR #23333](https://github.com/BerriAI/litellm/pull/23333)
|
||||
|
||||
- **General**
|
||||
- Fix silent metrics race condition causing metric collision across experiments - [PR #23542](https://github.com/BerriAI/litellm/pull/23542)
|
||||
|
||||
### Guardrails
|
||||
|
||||
No major guardrail changes in this release.
|
||||
|
||||
### Prompt Management
|
||||
|
||||
No major prompt management changes in this release.
|
||||
|
||||
### Secret Managers
|
||||
|
||||
No major secret manager changes in this release.
|
||||
|
||||
---
|
||||
|
||||
## Performance / Loadbalancing / Reliability improvements
|
||||
|
||||
- **Fix streaming crashes after ~1 hour** — `LLMClientCache._remove_key()` no longer calls `close()`/`aclose()` on evicted HTTP/SDK clients. In-flight requests were crashing with `RuntimeError: Cannot send a request, as the client has been closed.` after the 1-hour TTL expired. Cleanup now happens only at shutdown via `close_litellm_async_clients()` - [PR #22926](https://github.com/BerriAI/litellm/pull/22926)
|
||||
- **Fix OOM / Prisma connection loss** on large installs — unbounded managed-object poll was exhausting Prisma connections after ~60–70 minutes on instances with 336K+ queued response rows - [PR #23472](https://github.com/BerriAI/litellm/pull/23472)
|
||||
- **Centralize logging kwarg updates** — root cause fix migrating all logging updates to a single function, eliminating kwarg inconsistencies across logging paths - [PR #23659](https://github.com/BerriAI/litellm/pull/23659)
|
||||
- **Fix tiktoken cache for non-root offline containers** — tiktoken cache now works correctly in offline environments running as non-root users - [PR #23498](https://github.com/BerriAI/litellm/pull/23498)
|
||||
- **Add CodSpeed continuous performance benchmarks** — automated performance regression tracking on CI - [PR #23676](https://github.com/BerriAI/litellm/pull/23676)
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
- **Secret redaction in proxy logs** — Adds a `SecretRedactionFilter` to all LiteLLM loggers that scrubs API keys, tokens, and credentials from log messages, format args, exception tracebacks, and extra fields. Enabled by default; opt out with `LITELLM_DISABLE_REDACT_SECRETS=true` - [PR #23668](https://github.com/BerriAI/litellm/pull/23668), [PR #23667](https://github.com/BerriAI/litellm/pull/23667)
|
||||
- **Bump PyJWT to `^2.12.0`** — addresses security vulnerability in `^2.10.1` - [PR #23678](https://github.com/BerriAI/litellm/pull/23678)
|
||||
- **Bump `tar` to 7.5.11 and `tornado` to 6.5.5** — addresses CVEs in transitive dependencies - [PR #23602](https://github.com/BerriAI/litellm/pull/23602)
|
||||
|
||||
---
|
||||
|
||||
## Database / Proxy Operations
|
||||
|
||||
- **Fix Prisma migrate deploy on pre-existing instances** — resolved multiple bugs in migration recovery logic: missing return in the P3018 idempotent error handler and unhandled exceptions in `_roll_back_migration` that caused silent failures even after successful recovery - [PR #23655](https://github.com/BerriAI/litellm/pull/23655)
|
||||
- **Make DB migration failure exit opt-in** — proxy no longer exits on `prisma migrate deploy` failure by default; enable with `--enforce_prisma_migration_check` - [PR #23675](https://github.com/BerriAI/litellm/pull/23675)
|
||||
|
||||
---
|
||||
|
||||
## New Contributors
|
||||
|
||||
* @ryanh-ai made their first contribution in [PR #21542](https://github.com/BerriAI/litellm/pull/21542)
|
||||
* @ryan-crabbe made their first contribution in [PR #23668](https://github.com/BerriAI/litellm/pull/23668)
|
||||
* @Jah-yee made their first contribution in [PR #23525](https://github.com/BerriAI/litellm/pull/23525)
|
||||
* @gambletan made their first contribution in [PR #23516](https://github.com/BerriAI/litellm/pull/23516)
|
||||
* @awais786 made their first contribution in [PR #23183](https://github.com/BerriAI/litellm/pull/23183)
|
||||
* @pradyyadav made their first contribution in [PR #23580](https://github.com/BerriAI/litellm/pull/23580)
|
||||
* @xianzongxie-stripe made their first contribution in [PR #23492](https://github.com/BerriAI/litellm/pull/23492)
|
||||
* @Harshit28j made their first contribution in [PR #23333](https://github.com/BerriAI/litellm/pull/23333)
|
||||
* @codspeed-hq[bot] made their first contribution in [PR #23676](https://github.com/BerriAI/litellm/pull/23676)
|
||||
|
||||
---
|
||||
|
||||
## Diff Summary
|
||||
|
||||
## 03/16/2026
|
||||
* New Providers: 5
|
||||
* New Models / Updated Models: 116 new, 132 removed
|
||||
* LLM API Endpoints: 5
|
||||
* Management Endpoints / UI: 11
|
||||
* AI Integrations: 2
|
||||
* Performance / Reliability: 5
|
||||
* Security: 3
|
||||
* Database / Proxy Operations: 2
|
||||
|
||||
---
|
||||
|
||||
## Full Changelog
|
||||
[v1.82.0-stable...v1.82.3-stable](https://github.com/BerriAI/litellm/compare/v1.82.0-stable...v1.82.3-stable)
|
||||
|
|
@ -195,6 +195,19 @@ const sidebars = {
|
|||
"projects/openai-agents"
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
label: "Manage with AI Agents",
|
||||
link: {
|
||||
type: "generated-index",
|
||||
title: "Manage with AI Agents",
|
||||
description: "Use AI agents to manage your LiteLLM deployment — create users, teams, keys, models, and more via natural language.",
|
||||
slug: "/manage_with_ai_agents"
|
||||
},
|
||||
items: [
|
||||
"tutorials/claude_code_skills",
|
||||
]
|
||||
},
|
||||
|
||||
],
|
||||
// But you can create a sidebar manually
|
||||
|
|
@ -332,6 +345,7 @@ const sidebars = {
|
|||
label: "Setup & SSO",
|
||||
items: [
|
||||
"proxy/admin_ui_sso",
|
||||
"proxy/ui/ui_edit_logo",
|
||||
"proxy/custom_sso",
|
||||
"proxy/custom_root_ui",
|
||||
"tutorials/scim_litellm",
|
||||
|
|
@ -617,6 +631,7 @@ const sidebars = {
|
|||
"mcp_openapi",
|
||||
"mcp_oauth",
|
||||
"mcp_aws_sigv4",
|
||||
"mcp_zero_trust",
|
||||
"mcp_public_internet",
|
||||
"mcp_semantic_filter",
|
||||
"mcp_control",
|
||||
|
|
@ -669,6 +684,7 @@ const sidebars = {
|
|||
"rag_ingest",
|
||||
"rag_query",
|
||||
"realtime",
|
||||
"proxy/realtime_webrtc",
|
||||
"rerank",
|
||||
"response_api",
|
||||
"response_api_compact",
|
||||
|
|
|
|||
83
docs/my-website/src/components/WebRTCTester.jsx
Normal file
83
docs/my-website/src/components/WebRTCTester.jsx
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import DashboardWebRTCTester from "../../../../ui/litellm-dashboard/src/components/WebRTCTester.jsx";
|
||||
|
||||
const LIGHT_MODE_OVERRIDES = `
|
||||
.wrt-wrap {
|
||||
background: #1f2937;
|
||||
border: 1px solid #334155;
|
||||
}
|
||||
.wrt-toggle,
|
||||
.wrt-toggle:hover {
|
||||
background: #111827;
|
||||
}
|
||||
.wrt-toggle-title,
|
||||
.we-msg {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
.wrt-toggle-sub,
|
||||
.wrt-label,
|
||||
.wrt-field label,
|
||||
.wrt-flow-box,
|
||||
.wrt-flow-arrow,
|
||||
.wrt-meta-row span:first-child,
|
||||
.wrt-header-title,
|
||||
.wrt-tab,
|
||||
.we-time {
|
||||
color: #94a3b8;
|
||||
}
|
||||
.wrt-body,
|
||||
.wrt-sidebar,
|
||||
.wrt-main,
|
||||
.wrt-header,
|
||||
.wrt-tabs,
|
||||
.wrt-sdp-box,
|
||||
.wrt-sdp-hdr,
|
||||
.wrt-divider {
|
||||
border-color: #334155;
|
||||
}
|
||||
.wrt-header {
|
||||
background: #111827;
|
||||
}
|
||||
.wrt-field input,
|
||||
.wrt-mic-btn,
|
||||
.wrt-status-pill {
|
||||
background: #0b1220;
|
||||
border-color: #334155;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
.wrt-field input:focus,
|
||||
.wrt-btn-ghost:hover {
|
||||
border-color: #60a5fa;
|
||||
}
|
||||
.wrt-btn-ghost {
|
||||
background: #0b1220;
|
||||
border-color: #334155;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
.wrt-log::-webkit-scrollbar-thumb {
|
||||
background: #475569;
|
||||
}
|
||||
.wrt-tab.active {
|
||||
color: #93c5fd;
|
||||
border-bottom-color: #93c5fd;
|
||||
}
|
||||
.wrt-empty,
|
||||
.wrt-audio-status,
|
||||
.wrt-meta-row span:last-child {
|
||||
color: #cbd5e1;
|
||||
}
|
||||
.wrt-sdp-dot {
|
||||
background: #475569;
|
||||
}
|
||||
.wrt-sdp-pane textarea {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function WebRTCTester() {
|
||||
return (
|
||||
<>
|
||||
<DashboardWebRTCTester />
|
||||
<style>{LIGHT_MODE_OVERRIDES}</style>
|
||||
</>
|
||||
);
|
||||
}
|
||||
BIN
docs/my-website/static/img/mcp_zero_trust_gateway.png
Normal file
BIN
docs/my-website/static/img/mcp_zero_trust_gateway.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 294 KiB |
|
|
@ -2,11 +2,15 @@
|
|||
Polls LiteLLM_ManagedObjectTable to check if the batch job is complete, and if the cost has been tracked.
|
||||
"""
|
||||
|
||||
from litellm._uuid import uuid
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm._uuid import uuid
|
||||
from litellm.constants import (
|
||||
MANAGED_OBJECT_STALENESS_CUTOFF_DAYS,
|
||||
MAX_OBJECTS_PER_POLL_CYCLE,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.proxy.utils import PrismaClient, ProxyLogging
|
||||
|
|
@ -29,6 +33,9 @@ class CheckBatchCost:
|
|||
self.proxy_logging_obj: ProxyLogging = proxy_logging_obj
|
||||
self.prisma_client: PrismaClient = prisma_client
|
||||
self.llm_router: Router = llm_router
|
||||
# Cached after the first poll cycle. Once we know the column is absent we skip
|
||||
# the guaranteed-failing primary query on every subsequent cycle.
|
||||
self._has_batch_processed_column: bool = True
|
||||
|
||||
async def _get_user_info(self, batch_id, user_id) -> dict:
|
||||
"""
|
||||
|
|
@ -49,6 +56,47 @@ class CheckBatchCost:
|
|||
verbose_proxy_logger.error(f"CheckBatchCost: could not look up user {user_id} for batch {batch_id}: {e}")
|
||||
return {}
|
||||
|
||||
async def _cleanup_stale_managed_objects(self) -> None:
|
||||
"""
|
||||
Mark managed objects older than MANAGED_OBJECT_STALENESS_CUTOFF_DAYS days
|
||||
in non-terminal states as 'stale_expired'. These will never complete and
|
||||
should not be polled.
|
||||
"""
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(days=MANAGED_OBJECT_STALENESS_CUTOFF_DAYS)
|
||||
result = await self.prisma_client.db.litellm_managedobjecttable.update_many(
|
||||
where={
|
||||
"file_purpose": "batch",
|
||||
"status": {"not_in": ["completed", "complete", "failed", "expired", "cancelled", "stale_expired"]},
|
||||
"created_at": {"lt": cutoff},
|
||||
},
|
||||
data={"status": "stale_expired"},
|
||||
)
|
||||
if result > 0:
|
||||
verbose_proxy_logger.warning(
|
||||
f"CheckBatchCost: marked {result} stale managed objects "
|
||||
f"(older than {MANAGED_OBJECT_STALENESS_CUTOFF_DAYS} days) as stale_expired"
|
||||
)
|
||||
|
||||
async def _fallback_find_jobs(self) -> list:
|
||||
"""Query batch jobs without the batch_processed filter (for older schemas)."""
|
||||
return await self.prisma_client.db.litellm_managedobjecttable.find_many(
|
||||
where={
|
||||
"file_purpose": "batch",
|
||||
"status": {
|
||||
"not_in": [
|
||||
"failed",
|
||||
"expired",
|
||||
"cancelled",
|
||||
"complete",
|
||||
"completed",
|
||||
"stale_expired",
|
||||
]
|
||||
},
|
||||
},
|
||||
take=MAX_OBJECTS_PER_POLL_CYCLE,
|
||||
order={"created_at": "asc"},
|
||||
)
|
||||
|
||||
async def check_batch_cost(self):
|
||||
"""
|
||||
Check if the batch JOB has been tracked.
|
||||
|
|
@ -70,14 +118,50 @@ class CheckBatchCost:
|
|||
get_model_id_from_unified_batch_id,
|
||||
)
|
||||
|
||||
# Look for all batches that have not yet been processed by CheckBatchCost
|
||||
jobs = await self.prisma_client.db.litellm_managedobjecttable.find_many(
|
||||
where={
|
||||
"file_purpose": "batch",
|
||||
"batch_processed" : False,
|
||||
"status": {"not_in": ["failed", "expired", "cancelled"]}
|
||||
}
|
||||
)
|
||||
try:
|
||||
await self._cleanup_stale_managed_objects()
|
||||
except Exception as cleanup_err:
|
||||
verbose_proxy_logger.warning(
|
||||
f"CheckBatchCost: stale cleanup failed (poll will continue): {cleanup_err}"
|
||||
)
|
||||
|
||||
# Look for all batches that have not yet been processed by CheckBatchCost.
|
||||
# self._has_batch_processed_column is cached after the first probe so that
|
||||
# older schemas don't pay a guaranteed-failing primary query + warning on
|
||||
# every subsequent poll cycle.
|
||||
if self._has_batch_processed_column:
|
||||
try:
|
||||
# Include "complete"/"completed" batches: the retrieve_batch
|
||||
# endpoint may transition a batch to "complete" before
|
||||
# CheckBatchCost runs. The batch_processed=False filter
|
||||
# already prevents reprocessing finished batches.
|
||||
jobs = await self.prisma_client.db.litellm_managedobjecttable.find_many(
|
||||
where={
|
||||
"file_purpose": "batch",
|
||||
"batch_processed": False,
|
||||
"status": {
|
||||
"not_in": [
|
||||
"failed",
|
||||
"expired",
|
||||
"cancelled",
|
||||
"stale_expired",
|
||||
]
|
||||
},
|
||||
},
|
||||
take=MAX_OBJECTS_PER_POLL_CYCLE,
|
||||
order={"created_at": "asc"},
|
||||
)
|
||||
except Exception as query_err:
|
||||
if "batch_processed" not in str(query_err).lower() and "unknown column" not in str(query_err).lower() and "does not exist" not in str(query_err).lower():
|
||||
raise
|
||||
# Permanent schema gap — cache the result so future cycles skip straight to fallback
|
||||
self._has_batch_processed_column = False
|
||||
verbose_proxy_logger.warning(
|
||||
"CheckBatchCost: batch_processed column not found, querying without it"
|
||||
)
|
||||
jobs = await self._fallback_find_jobs()
|
||||
else:
|
||||
jobs = await self._fallback_find_jobs()
|
||||
for job in jobs:
|
||||
# get the model from the job
|
||||
unified_object_id = job.unified_object_id
|
||||
|
|
@ -163,14 +247,14 @@ class CheckBatchCost:
|
|||
|
||||
# Access content - handle both direct attribute and method call
|
||||
if hasattr(_file_content, 'content'):
|
||||
content_bytes = _file_content.content
|
||||
content_bytes = _file_content.content # type: ignore[union-attr]
|
||||
elif hasattr(_file_content, 'read'):
|
||||
content_bytes = await _file_content.read()
|
||||
content_bytes = await _file_content.read() # type: ignore[misc]
|
||||
else:
|
||||
content_bytes = _file_content
|
||||
content_bytes = _file_content # type: ignore[assignment]
|
||||
|
||||
file_content_as_dict = _get_file_content_as_dictionary(
|
||||
content_bytes
|
||||
content_bytes # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
deployment_info = self.llm_router.get_deployment(model_id=model_id)
|
||||
|
|
@ -195,7 +279,7 @@ class CheckBatchCost:
|
|||
file_content_dictionary=file_content_as_dict,
|
||||
custom_llm_provider=llm_provider, # type: ignore
|
||||
model_name=model_name,
|
||||
model_info=deployment_model_info,
|
||||
model_info=deployment_model_info, # type: ignore[arg-type]
|
||||
)
|
||||
)
|
||||
logging_obj = LiteLLMLogging(
|
||||
|
|
@ -236,13 +320,15 @@ class CheckBatchCost:
|
|||
|
||||
# mark the job as complete
|
||||
try:
|
||||
update_data: dict = {
|
||||
"status": "complete",
|
||||
"file_object": response.model_dump_json(),
|
||||
}
|
||||
if self._has_batch_processed_column:
|
||||
update_data["batch_processed"] = True
|
||||
await self.prisma_client.db.litellm_managedobjecttable.update(
|
||||
where={"id": job.id},
|
||||
data={
|
||||
"batch_processed": True,
|
||||
"status": "complete",
|
||||
"file_object": response.model_dump_json(),
|
||||
},
|
||||
data=update_data,
|
||||
)
|
||||
except Exception as db_err:
|
||||
verbose_proxy_logger.error(
|
||||
|
|
|
|||
|
|
@ -3,10 +3,15 @@ Polls LiteLLM_ManagedObjectTable to check if the response is complete.
|
|||
Cost tracking is handled automatically by litellm.aget_responses().
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import litellm
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm.constants import (
|
||||
MANAGED_OBJECT_STALENESS_CUTOFF_DAYS,
|
||||
MAX_OBJECTS_PER_POLL_CYCLE,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.proxy.utils import PrismaClient, ProxyLogging
|
||||
|
|
@ -27,6 +32,27 @@ class CheckResponsesCost:
|
|||
self.prisma_client: PrismaClient = prisma_client
|
||||
self.llm_router: Router = llm_router
|
||||
|
||||
async def _cleanup_stale_managed_objects(self) -> None:
|
||||
"""
|
||||
Mark managed objects older than MANAGED_OBJECT_STALENESS_CUTOFF_DAYS days
|
||||
in non-terminal states as 'stale_expired'. These will never complete and
|
||||
should not be polled.
|
||||
"""
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(days=MANAGED_OBJECT_STALENESS_CUTOFF_DAYS)
|
||||
result = await self.prisma_client.db.litellm_managedobjecttable.update_many(
|
||||
where={
|
||||
"file_purpose": "response",
|
||||
"status": {"not_in": ["completed", "complete", "failed", "expired", "cancelled", "stale_expired"]},
|
||||
"created_at": {"lt": cutoff},
|
||||
},
|
||||
data={"status": "stale_expired"},
|
||||
)
|
||||
if result > 0:
|
||||
verbose_proxy_logger.warning(
|
||||
f"CheckResponsesCost: marked {result} stale managed objects "
|
||||
f"(older than {MANAGED_OBJECT_STALENESS_CUTOFF_DAYS} days) as stale_expired"
|
||||
)
|
||||
|
||||
async def check_responses_cost(self):
|
||||
"""
|
||||
Check if background responses are complete and track their cost.
|
||||
|
|
@ -35,11 +61,20 @@ class CheckResponsesCost:
|
|||
- Cost is automatically tracked by litellm.aget_responses()
|
||||
- Mark completed/failed/cancelled responses as complete in the database
|
||||
"""
|
||||
try:
|
||||
await self._cleanup_stale_managed_objects()
|
||||
except Exception as cleanup_err:
|
||||
verbose_proxy_logger.warning(
|
||||
f"CheckResponsesCost: stale cleanup failed (poll will continue): {cleanup_err}"
|
||||
)
|
||||
|
||||
jobs = await self.prisma_client.db.litellm_managedobjecttable.find_many(
|
||||
where={
|
||||
"status": {"in": ["queued", "in_progress"]},
|
||||
"file_purpose": "response",
|
||||
}
|
||||
},
|
||||
take=MAX_OBJECTS_PER_POLL_CYCLE,
|
||||
order={"created_at": "asc"},
|
||||
)
|
||||
|
||||
verbose_proxy_logger.debug(f"Found {len(jobs)} response jobs to check")
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from litellm.proxy.openai_files_endpoints.common_utils import (
|
|||
get_batch_id_from_unified_batch_id,
|
||||
get_content_type_from_file_object,
|
||||
get_model_id_from_unified_batch_id,
|
||||
get_models_from_unified_file_id,
|
||||
normalize_mime_type_for_provider,
|
||||
)
|
||||
from litellm.types.llms.openai import (
|
||||
|
|
@ -904,6 +905,21 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
|
|||
) # managed batch id
|
||||
model_id = cast(Optional[str], response._hidden_params.get("model_id"))
|
||||
model_name = cast(Optional[str], response._hidden_params.get("model_name"))
|
||||
resolved_model_name = model_name
|
||||
|
||||
# Some providers (e.g. Vertex batch retrieve) do not set model_name on
|
||||
# the response. In that case, recover target_model_names from the input
|
||||
# managed file metadata so unified output IDs preserve routing metadata.
|
||||
if not resolved_model_name and isinstance(unified_file_id, str):
|
||||
decoded_unified_file_id = (
|
||||
_is_base64_encoded_unified_file_id(unified_file_id)
|
||||
or unified_file_id
|
||||
)
|
||||
target_model_names = get_models_from_unified_file_id(
|
||||
decoded_unified_file_id
|
||||
)
|
||||
if target_model_names:
|
||||
resolved_model_name = ",".join(target_model_names)
|
||||
original_response_id = response.id
|
||||
|
||||
if (unified_batch_id or unified_file_id) and model_id:
|
||||
|
|
@ -919,7 +935,7 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
|
|||
unified_file_id = self.get_unified_output_file_id(
|
||||
output_file_id=original_file_id,
|
||||
model_id=model_id,
|
||||
model_name=model_name,
|
||||
model_name=resolved_model_name,
|
||||
)
|
||||
setattr(response, file_attr, unified_file_id)
|
||||
|
||||
|
|
|
|||
8
litellm-js/spend-logs/package-lock.json
generated
8
litellm-js/spend-logs/package-lock.json
generated
|
|
@ -6,7 +6,7 @@
|
|||
"": {
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.10.1",
|
||||
"hono": "^4.10.3"
|
||||
"hono": "^4.12.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.17",
|
||||
|
|
@ -548,9 +548,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.10.6",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.10.6.tgz",
|
||||
"integrity": "sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==",
|
||||
"version": "4.12.7",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
|
||||
"integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.10.1",
|
||||
"hono": "^4.10.3"
|
||||
"hono": "^4.12.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.17",
|
||||
|
|
|
|||
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.56-py3-none-any.whl
vendored
Normal file
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.56-py3-none-any.whl
vendored
Normal file
Binary file not shown.
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.56.tar.gz
vendored
Normal file
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.56.tar.gz
vendored
Normal file
Binary file not shown.
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.57-py3-none-any.whl
vendored
Normal file
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.57-py3-none-any.whl
vendored
Normal file
Binary file not shown.
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.57.tar.gz
vendored
Normal file
BIN
litellm-proxy-extras/dist/litellm_proxy_extras-0.4.57.tar.gz
vendored
Normal file
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_BudgetTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_BudgetTable" (
|
||||
"budget_id" TEXT NOT NULL,
|
||||
"max_budget" DOUBLE PRECISION,
|
||||
"soft_budget" DOUBLE PRECISION,
|
||||
|
|
@ -18,7 +18,7 @@ CREATE TABLE "LiteLLM_BudgetTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_CredentialsTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_CredentialsTable" (
|
||||
"credential_id" TEXT NOT NULL,
|
||||
"credential_name" TEXT NOT NULL,
|
||||
"credential_values" JSONB NOT NULL,
|
||||
|
|
@ -32,7 +32,7 @@ CREATE TABLE "LiteLLM_CredentialsTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ProxyModelTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ProxyModelTable" (
|
||||
"model_id" TEXT NOT NULL,
|
||||
"model_name" TEXT NOT NULL,
|
||||
"litellm_params" JSONB NOT NULL,
|
||||
|
|
@ -46,7 +46,7 @@ CREATE TABLE "LiteLLM_ProxyModelTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_OrganizationTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_OrganizationTable" (
|
||||
"organization_id" TEXT NOT NULL,
|
||||
"organization_alias" TEXT NOT NULL,
|
||||
"budget_id" TEXT NOT NULL,
|
||||
|
|
@ -63,7 +63,7 @@ CREATE TABLE "LiteLLM_OrganizationTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ModelTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ModelTable" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"aliases" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
@ -75,7 +75,7 @@ CREATE TABLE "LiteLLM_ModelTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_TeamTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_TeamTable" (
|
||||
"team_id" TEXT NOT NULL,
|
||||
"team_alias" TEXT,
|
||||
"organization_id" TEXT,
|
||||
|
|
@ -102,7 +102,7 @@ CREATE TABLE "LiteLLM_TeamTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_UserTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_UserTable" (
|
||||
"user_id" TEXT NOT NULL,
|
||||
"user_alias" TEXT,
|
||||
"team_id" TEXT,
|
||||
|
|
@ -131,7 +131,7 @@ CREATE TABLE "LiteLLM_UserTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_VerificationToken" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_VerificationToken" (
|
||||
"token" TEXT NOT NULL,
|
||||
"key_name" TEXT,
|
||||
"key_alias" TEXT,
|
||||
|
|
@ -166,7 +166,7 @@ CREATE TABLE "LiteLLM_VerificationToken" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_EndUserTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_EndUserTable" (
|
||||
"user_id" TEXT NOT NULL,
|
||||
"alias" TEXT,
|
||||
"spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0,
|
||||
|
|
@ -179,7 +179,7 @@ CREATE TABLE "LiteLLM_EndUserTable" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_Config" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_Config" (
|
||||
"param_name" TEXT NOT NULL,
|
||||
"param_value" JSONB,
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ CREATE TABLE "LiteLLM_Config" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_SpendLogs" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_SpendLogs" (
|
||||
"request_id" TEXT NOT NULL,
|
||||
"call_type" TEXT NOT NULL,
|
||||
"api_key" TEXT NOT NULL DEFAULT '',
|
||||
|
|
@ -218,7 +218,7 @@ CREATE TABLE "LiteLLM_SpendLogs" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ErrorLogs" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ErrorLogs" (
|
||||
"request_id" TEXT NOT NULL,
|
||||
"startTime" TIMESTAMP(3) NOT NULL,
|
||||
"endTime" TIMESTAMP(3) NOT NULL,
|
||||
|
|
@ -235,7 +235,7 @@ CREATE TABLE "LiteLLM_ErrorLogs" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_UserNotifications" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_UserNotifications" (
|
||||
"request_id" TEXT NOT NULL,
|
||||
"user_id" TEXT NOT NULL,
|
||||
"models" TEXT[],
|
||||
|
|
@ -246,7 +246,7 @@ CREATE TABLE "LiteLLM_UserNotifications" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_TeamMembership" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_TeamMembership" (
|
||||
"user_id" TEXT NOT NULL,
|
||||
"team_id" TEXT NOT NULL,
|
||||
"spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0,
|
||||
|
|
@ -256,7 +256,7 @@ CREATE TABLE "LiteLLM_TeamMembership" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_OrganizationMembership" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_OrganizationMembership" (
|
||||
"user_id" TEXT NOT NULL,
|
||||
"organization_id" TEXT NOT NULL,
|
||||
"user_role" TEXT,
|
||||
|
|
@ -269,7 +269,7 @@ CREATE TABLE "LiteLLM_OrganizationMembership" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_InvitationLink" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_InvitationLink" (
|
||||
"id" TEXT NOT NULL,
|
||||
"user_id" TEXT NOT NULL,
|
||||
"is_accepted" BOOLEAN NOT NULL DEFAULT false,
|
||||
|
|
@ -284,7 +284,7 @@ CREATE TABLE "LiteLLM_InvitationLink" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_AuditLog" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_AuditLog" (
|
||||
"id" TEXT NOT NULL,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"changed_by" TEXT NOT NULL DEFAULT '',
|
||||
|
|
@ -299,62 +299,132 @@ CREATE TABLE "LiteLLM_AuditLog" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_CredentialsTable_credential_name_key" ON "LiteLLM_CredentialsTable"("credential_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_CredentialsTable_credential_name_key" ON "LiteLLM_CredentialsTable"("credential_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_TeamTable_model_id_key" ON "LiteLLM_TeamTable"("model_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_TeamTable_model_id_key" ON "LiteLLM_TeamTable"("model_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_UserTable_sso_user_id_key" ON "LiteLLM_UserTable"("sso_user_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_UserTable_sso_user_id_key" ON "LiteLLM_UserTable"("sso_user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_SpendLogs_startTime_idx" ON "LiteLLM_SpendLogs"("startTime");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_startTime_idx" ON "LiteLLM_SpendLogs"("startTime");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_SpendLogs_end_user_idx" ON "LiteLLM_SpendLogs"("end_user");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_end_user_idx" ON "LiteLLM_SpendLogs"("end_user");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_OrganizationMembership_user_id_organization_id_key" ON "LiteLLM_OrganizationMembership"("user_id", "organization_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_OrganizationMembership_user_id_organization_id_key" ON "LiteLLM_OrganizationMembership"("user_id", "organization_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_OrganizationTable" ADD CONSTRAINT "LiteLLM_OrganizationTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_OrganizationTable_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_OrganizationTable" ADD CONSTRAINT "LiteLLM_OrganizationTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD CONSTRAINT "LiteLLM_TeamTable_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamTable_organization_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD CONSTRAINT "LiteLLM_TeamTable_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD CONSTRAINT "LiteLLM_TeamTable_model_id_fkey" FOREIGN KEY ("model_id") REFERENCES "LiteLLM_ModelTable"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamTable_model_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD CONSTRAINT "LiteLLM_TeamTable_model_id_fkey" FOREIGN KEY ("model_id") REFERENCES "LiteLLM_ModelTable"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_UserTable" ADD CONSTRAINT "LiteLLM_UserTable_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_UserTable_organization_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_UserTable" ADD CONSTRAINT "LiteLLM_UserTable_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_VerificationToken_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_VerificationToken_organization_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_EndUserTable" ADD CONSTRAINT "LiteLLM_EndUserTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_EndUserTable_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_EndUserTable" ADD CONSTRAINT "LiteLLM_EndUserTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamMembership" ADD CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamMembership_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamMembership" ADD CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_OrganizationMembership" ADD CONSTRAINT "LiteLLM_OrganizationMembership_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_OrganizationMembership_user_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_OrganizationMembership" ADD CONSTRAINT "LiteLLM_OrganizationMembership_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_OrganizationMembership" ADD CONSTRAINT "LiteLLM_OrganizationMembership_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_OrganizationMembership_organization_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_OrganizationMembership" ADD CONSTRAINT "LiteLLM_OrganizationMembership_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "LiteLLM_OrganizationTable"("organization_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_OrganizationMembership" ADD CONSTRAINT "LiteLLM_OrganizationMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_OrganizationMembership_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_OrganizationMembership" ADD CONSTRAINT "LiteLLM_OrganizationMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_InvitationLink" ADD CONSTRAINT "LiteLLM_InvitationLink_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_InvitationLink_user_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_InvitationLink" ADD CONSTRAINT "LiteLLM_InvitationLink_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_InvitationLink" ADD CONSTRAINT "LiteLLM_InvitationLink_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_InvitationLink_created_by_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_InvitationLink" ADD CONSTRAINT "LiteLLM_InvitationLink_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_InvitationLink" ADD CONSTRAINT "LiteLLM_InvitationLink_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_InvitationLink_updated_by_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_InvitationLink" ADD CONSTRAINT "LiteLLM_InvitationLink_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "LiteLLM_UserTable"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_DailyUserSpend" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_DailyUserSpend" (
|
||||
"id" TEXT NOT NULL,
|
||||
"user_id" TEXT NOT NULL,
|
||||
"date" TEXT NOT NULL,
|
||||
|
|
@ -17,17 +17,17 @@ CREATE TABLE "LiteLLM_DailyUserSpend" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyUserSpend_date_idx" ON "LiteLLM_DailyUserSpend"("date");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_date_idx" ON "LiteLLM_DailyUserSpend"("date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyUserSpend_user_id_idx" ON "LiteLLM_DailyUserSpend"("user_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_user_id_idx" ON "LiteLLM_DailyUserSpend"("user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyUserSpend_api_key_idx" ON "LiteLLM_DailyUserSpend"("api_key");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_api_key_idx" ON "LiteLLM_DailyUserSpend"("api_key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyUserSpend_model_idx" ON "LiteLLM_DailyUserSpend"("model");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_model_idx" ON "LiteLLM_DailyUserSpend"("model");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyUserSpend_user_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyUserSpend"("user_id", "date", "api_key", "model", "custom_llm_provider");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_user_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyUserSpend"("user_id", "date", "api_key", "model", "custom_llm_provider");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN "api_requests" INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN IF NOT EXISTS "api_requests" INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
CREATE TYPE "JobStatus" AS ENUM ('ACTIVE', 'INACTIVE');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_CronJob" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_CronJob" (
|
||||
"cronjob_id" TEXT NOT NULL,
|
||||
"pod_id" TEXT NOT NULL,
|
||||
"status" "JobStatus" NOT NULL DEFAULT 'INACTIVE',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN "failed_requests" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN "successful_requests" INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN IF NOT EXISTS "failed_requests" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "successful_requests" INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ManagedFileTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ManagedFileTable" (
|
||||
"id" TEXT NOT NULL,
|
||||
"unified_file_id" TEXT NOT NULL,
|
||||
"file_object" JSONB NOT NULL,
|
||||
|
|
@ -11,8 +11,8 @@ CREATE TABLE "LiteLLM_ManagedFileTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_ManagedFileTable_unified_file_id_key" ON "LiteLLM_ManagedFileTable"("unified_file_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_ManagedFileTable_unified_file_id_key" ON "LiteLLM_ManagedFileTable"("unified_file_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_ManagedFileTable_unified_file_id_idx" ON "LiteLLM_ManagedFileTable"("unified_file_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_ManagedFileTable_unified_file_id_idx" ON "LiteLLM_ManagedFileTable"("unified_file_id");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD COLUMN "team_member_permissions" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD COLUMN IF NOT EXISTS "team_member_permissions" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN "cache_creation_input_tokens" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN "cache_read_input_tokens" INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN IF NOT EXISTS "cache_creation_input_tokens" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "cache_read_input_tokens" INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_DailyTeamSpend" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_DailyTeamSpend" (
|
||||
"id" TEXT NOT NULL,
|
||||
"team_id" TEXT NOT NULL,
|
||||
"date" TEXT NOT NULL,
|
||||
|
|
@ -20,17 +20,17 @@ CREATE TABLE "LiteLLM_DailyTeamSpend" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTeamSpend_date_idx" ON "LiteLLM_DailyTeamSpend"("date");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_date_idx" ON "LiteLLM_DailyTeamSpend"("date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTeamSpend_team_id_idx" ON "LiteLLM_DailyTeamSpend"("team_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_team_id_idx" ON "LiteLLM_DailyTeamSpend"("team_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTeamSpend_api_key_idx" ON "LiteLLM_DailyTeamSpend"("api_key");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_api_key_idx" ON "LiteLLM_DailyTeamSpend"("api_key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTeamSpend_model_idx" ON "LiteLLM_DailyTeamSpend"("model");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_model_idx" ON "LiteLLM_DailyTeamSpend"("model");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyTeamSpend_team_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyTeamSpend"("team_id", "date", "api_key", "model", "custom_llm_provider");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_team_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyTeamSpend"("team_id", "date", "api_key", "model", "custom_llm_provider");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyTeamSpend" ADD COLUMN "cache_creation_input_tokens" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN "cache_read_input_tokens" INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE "LiteLLM_DailyTeamSpend" ADD COLUMN IF NOT EXISTS "cache_creation_input_tokens" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "cache_read_input_tokens" INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_DailyTagSpend" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_DailyTagSpend" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tag" TEXT NOT NULL,
|
||||
"date" TEXT NOT NULL,
|
||||
|
|
@ -26,20 +26,20 @@ CREATE TABLE "LiteLLM_DailyTagSpend" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyTagSpend_tag_key" ON "LiteLLM_DailyTagSpend"("tag");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_tag_key" ON "LiteLLM_DailyTagSpend"("tag");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTagSpend_date_idx" ON "LiteLLM_DailyTagSpend"("date");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_date_idx" ON "LiteLLM_DailyTagSpend"("date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTagSpend_tag_idx" ON "LiteLLM_DailyTagSpend"("tag");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_tag_idx" ON "LiteLLM_DailyTagSpend"("tag");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTagSpend_api_key_idx" ON "LiteLLM_DailyTagSpend"("api_key");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_api_key_idx" ON "LiteLLM_DailyTagSpend"("api_key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTagSpend_model_idx" ON "LiteLLM_DailyTagSpend"("model");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_model_idx" ON "LiteLLM_DailyTagSpend"("model");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyTagSpend_tag_date_api_key_model_custom_llm_pro_key" ON "LiteLLM_DailyTagSpend"("tag", "date", "api_key", "model", "custom_llm_provider");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_tag_date_api_key_model_custom_llm_pro_key" ON "LiteLLM_DailyTagSpend"("tag", "date", "api_key", "model", "custom_llm_provider");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- DropIndex
|
||||
DROP INDEX "LiteLLM_DailyTagSpend_tag_key";
|
||||
DROP INDEX IF EXISTS "LiteLLM_DailyTagSpend_tag_key";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN "allowed_routes" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN IF NOT EXISTS "allowed_routes" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN "proxy_server_request" JSONB DEFAULT '{}',
|
||||
ADD COLUMN "session_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN IF NOT EXISTS "proxy_server_request" JSONB DEFAULT '{}',
|
||||
ADD COLUMN IF NOT EXISTS "session_id" TEXT;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ManagedVectorStoresTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ManagedVectorStoresTable" (
|
||||
"vector_store_id" TEXT NOT NULL,
|
||||
"custom_llm_provider" TEXT NOT NULL,
|
||||
"vector_store_name" TEXT,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_MCPServerTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_MCPServerTable" (
|
||||
"server_id" TEXT NOT NULL,
|
||||
"alias" TEXT,
|
||||
"description" TEXT,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- Add health check fields to MCP server table
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "status" TEXT DEFAULT 'unknown';
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "last_health_check" TIMESTAMP(3);
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "health_check_error" TEXT;
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "status" TEXT DEFAULT 'unknown';
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "last_health_check" TIMESTAMP(3);
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "health_check_error" TEXT;
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_OrganizationTable" ADD COLUMN "object_permission_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_OrganizationTable" ADD COLUMN IF NOT EXISTS "object_permission_id" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD COLUMN "object_permission_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD COLUMN IF NOT EXISTS "object_permission_id" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_UserTable" ADD COLUMN "object_permission_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_UserTable" ADD COLUMN IF NOT EXISTS "object_permission_id" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN "object_permission_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN IF NOT EXISTS "object_permission_id" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ObjectPermissionTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ObjectPermissionTable" (
|
||||
"object_permission_id" TEXT NOT NULL,
|
||||
"mcp_servers" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
|
||||
|
|
@ -19,14 +19,34 @@ CREATE TABLE "LiteLLM_ObjectPermissionTable" (
|
|||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_OrganizationTable" ADD CONSTRAINT "LiteLLM_OrganizationTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_OrganizationTable_object_permission_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_OrganizationTable" ADD CONSTRAINT "LiteLLM_OrganizationTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD CONSTRAINT "LiteLLM_TeamTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamTable_object_permission_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamTable" ADD CONSTRAINT "LiteLLM_TeamTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_UserTable" ADD CONSTRAINT "LiteLLM_UserTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_UserTable_object_permission_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_UserTable" ADD CONSTRAINT "LiteLLM_UserTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_VerificationToken_object_permission_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN "status" TEXT;
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN IF NOT EXISTS "status" TEXT;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_SpendLogs_session_id_idx" ON "LiteLLM_SpendLogs"("session_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_session_id_idx" ON "LiteLLM_SpendLogs"("session_id");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_GuardrailsTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_GuardrailsTable" (
|
||||
"guardrail_id" TEXT NOT NULL,
|
||||
"guardrail_name" TEXT NOT NULL,
|
||||
"litellm_params" JSONB NOT NULL,
|
||||
|
|
@ -11,5 +11,5 @@ CREATE TABLE "LiteLLM_GuardrailsTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_GuardrailsTable_guardrail_name_key" ON "LiteLLM_GuardrailsTable"("guardrail_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_GuardrailsTable_guardrail_name_key" ON "LiteLLM_GuardrailsTable"("guardrail_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ManagedFileTable" ADD COLUMN "created_by" TEXT,
|
||||
ADD COLUMN "flat_model_file_ids" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "updated_by" TEXT;
|
||||
ALTER TABLE "LiteLLM_ManagedFileTable" ADD COLUMN IF NOT EXISTS "created_by" TEXT,
|
||||
ADD COLUMN IF NOT EXISTS "flat_model_file_ids" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN IF NOT EXISTS "updated_by" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ManagedObjectTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ManagedObjectTable" (
|
||||
"id" TEXT NOT NULL,
|
||||
"unified_object_id" TEXT NOT NULL,
|
||||
"model_object_id" TEXT NOT NULL,
|
||||
|
|
@ -19,14 +19,14 @@ CREATE TABLE "LiteLLM_ManagedObjectTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_ManagedObjectTable_unified_object_id_key" ON "LiteLLM_ManagedObjectTable"("unified_object_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_ManagedObjectTable_unified_object_id_key" ON "LiteLLM_ManagedObjectTable"("unified_object_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_ManagedObjectTable_model_object_id_key" ON "LiteLLM_ManagedObjectTable"("model_object_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_ManagedObjectTable_model_object_id_key" ON "LiteLLM_ManagedObjectTable"("model_object_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_ManagedObjectTable_unified_object_id_idx" ON "LiteLLM_ManagedObjectTable"("unified_object_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_ManagedObjectTable_unified_object_id_idx" ON "LiteLLM_ManagedObjectTable"("unified_object_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_ManagedObjectTable_model_object_id_idx" ON "LiteLLM_ManagedObjectTable"("model_object_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_ManagedObjectTable_model_object_id_idx" ON "LiteLLM_ManagedObjectTable"("model_object_id");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ObjectPermissionTable" ADD COLUMN "vector_stores" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "LiteLLM_ObjectPermissionTable" ADD COLUMN IF NOT EXISTS "vector_stores" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
-- DropForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamMembership" DROP CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey";
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamMembership_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamMembership" DROP CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey";
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamMembership" ADD CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamMembership_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamMembership" ADD CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_HealthCheckTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_HealthCheckTable" (
|
||||
"health_check_id" TEXT NOT NULL,
|
||||
"model_name" TEXT NOT NULL,
|
||||
"model_id" TEXT,
|
||||
|
|
@ -18,11 +18,11 @@ CREATE TABLE "LiteLLM_HealthCheckTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_HealthCheckTable_model_name_idx" ON "LiteLLM_HealthCheckTable"("model_name");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_HealthCheckTable_model_name_idx" ON "LiteLLM_HealthCheckTable"("model_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_HealthCheckTable_checked_at_idx" ON "LiteLLM_HealthCheckTable"("checked_at");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_HealthCheckTable_checked_at_idx" ON "LiteLLM_HealthCheckTable"("checked_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_HealthCheckTable_status_idx" ON "LiteLLM_HealthCheckTable"("status");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_HealthCheckTable_status_idx" ON "LiteLLM_HealthCheckTable"("status");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
-- DropForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamMembership" DROP CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey";
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamMembership_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamMembership" DROP CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey";
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ManagedFileTable" ALTER COLUMN "file_object" DROP NOT NULL;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TeamMembership" ADD CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TeamMembership_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TeamMembership" ADD CONSTRAINT "LiteLLM_TeamMembership_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ManagedObjectTable" ADD COLUMN "status" TEXT;
|
||||
ALTER TABLE "LiteLLM_ManagedObjectTable" ADD COLUMN IF NOT EXISTS "status" TEXT;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "mcp_info" JSONB DEFAULT '{}';
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "mcp_info" JSONB DEFAULT '{}';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,42 @@
|
|||
-- DropIndex
|
||||
DROP INDEX "LiteLLM_DailyTagSpend_tag_date_api_key_model_custom_llm_pro_key";
|
||||
DROP INDEX IF EXISTS "LiteLLM_DailyTagSpend_tag_date_api_key_model_custom_llm_pro_key";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "LiteLLM_DailyTeamSpend_team_id_date_api_key_model_custom_ll_key";
|
||||
DROP INDEX IF EXISTS "LiteLLM_DailyTeamSpend_team_id_date_api_key_model_custom_ll_key";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "LiteLLM_DailyUserSpend_user_id_date_api_key_model_custom_ll_key";
|
||||
DROP INDEX IF EXISTS "LiteLLM_DailyUserSpend_user_id_date_api_key_model_custom_ll_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyTagSpend" ADD COLUMN "mcp_namespaced_tool_name" TEXT,
|
||||
ALTER TABLE "LiteLLM_DailyTagSpend" ADD COLUMN IF NOT EXISTS "mcp_namespaced_tool_name" TEXT,
|
||||
ALTER COLUMN "model" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyTeamSpend" ADD COLUMN "mcp_namespaced_tool_name" TEXT,
|
||||
ALTER TABLE "LiteLLM_DailyTeamSpend" ADD COLUMN IF NOT EXISTS "mcp_namespaced_tool_name" TEXT,
|
||||
ALTER COLUMN "model" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN "mcp_namespaced_tool_name" TEXT,
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN IF NOT EXISTS "mcp_namespaced_tool_name" TEXT,
|
||||
ALTER COLUMN "model" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN "mcp_namespaced_tool_name" TEXT;
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN IF NOT EXISTS "mcp_namespaced_tool_name" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTagSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyTagSpend"("mcp_namespaced_tool_name");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyTagSpend"("mcp_namespaced_tool_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyTagSpend_tag_date_api_key_model_custom_llm_pro_key" ON "LiteLLM_DailyTagSpend"("tag", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyTagSpend_tag_date_api_key_model_custom_llm_pro_key" ON "LiteLLM_DailyTagSpend"("tag", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyTeamSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyTeamSpend"("mcp_namespaced_tool_name");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyTeamSpend"("mcp_namespaced_tool_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyTeamSpend_team_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyTeamSpend"("team_id", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyTeamSpend_team_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyTeamSpend"("team_id", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyUserSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyUserSpend"("mcp_namespaced_tool_name");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyUserSpend"("mcp_namespaced_tool_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyUserSpend_user_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyUserSpend"("user_id", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyUserSpend_user_id_date_api_key_model_custom_ll_key" ON "LiteLLM_DailyUserSpend"("user_id", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "args" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "command" TEXT,
|
||||
ADD COLUMN "env" JSONB DEFAULT '{}',
|
||||
ADD COLUMN "mcp_access_groups" TEXT[],
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "args" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN IF NOT EXISTS "command" TEXT,
|
||||
ADD COLUMN IF NOT EXISTS "env" JSONB DEFAULT '{}',
|
||||
ADD COLUMN IF NOT EXISTS "mcp_access_groups" TEXT[],
|
||||
ALTER COLUMN "url" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ObjectPermissionTable" ADD COLUMN "mcp_access_groups" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "LiteLLM_ObjectPermissionTable" ADD COLUMN IF NOT EXISTS "mcp_access_groups" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ManagedVectorStoresTable" ADD COLUMN "litellm_params" JSONB;
|
||||
ALTER TABLE "LiteLLM_ManagedVectorStoresTable" ADD COLUMN IF NOT EXISTS "litellm_params" JSONB;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_PromptTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_PromptTable" (
|
||||
"id" TEXT NOT NULL,
|
||||
"prompt_id" TEXT NOT NULL,
|
||||
"litellm_params" JSONB NOT NULL,
|
||||
|
|
@ -11,5 +11,5 @@ CREATE TABLE "LiteLLM_PromptTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_PromptTable_prompt_id_key" ON "LiteLLM_PromptTable"("prompt_id");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_PromptTable_prompt_id_key" ON "LiteLLM_PromptTable"("prompt_id");
|
||||
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" DROP COLUMN "spec_version";
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" DROP COLUMN IF EXISTS "spec_version";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN "auto_rotate" BOOLEAN DEFAULT false,
|
||||
ADD COLUMN "key_rotation_at" TIMESTAMP(3),
|
||||
ADD COLUMN "last_rotation_at" TIMESTAMP(3),
|
||||
ADD COLUMN "rotation_count" INTEGER DEFAULT 0,
|
||||
ADD COLUMN "rotation_interval" TEXT;
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN IF NOT EXISTS "auto_rotate" BOOLEAN DEFAULT false,
|
||||
ADD COLUMN IF NOT EXISTS "key_rotation_at" TIMESTAMP(3),
|
||||
ADD COLUMN IF NOT EXISTS "last_rotation_at" TIMESTAMP(3),
|
||||
ADD COLUMN IF NOT EXISTS "rotation_count" INTEGER DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "rotation_interval" TEXT;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "allowed_tools" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "allowed_tools" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "extra_headers" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "extra_headers" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_ObjectPermissionTable" ADD COLUMN "mcp_tool_permissions" JSONB;
|
||||
ALTER TABLE "LiteLLM_ObjectPermissionTable" ADD COLUMN IF NOT EXISTS "mcp_tool_permissions" JSONB;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_TagTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_TagTable" (
|
||||
"tag_name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"models" TEXT[],
|
||||
|
|
@ -14,5 +14,10 @@ CREATE TABLE "LiteLLM_TagTable" (
|
|||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_TagTable" ADD CONSTRAINT "LiteLLM_TagTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_TagTable_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_TagTable" ADD CONSTRAINT "LiteLLM_TagTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_SearchToolsTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_SearchToolsTable" (
|
||||
"search_tool_id" TEXT NOT NULL,
|
||||
"search_tool_name" TEXT NOT NULL,
|
||||
"litellm_params" JSONB NOT NULL,
|
||||
|
|
@ -11,5 +11,5 @@ CREATE TABLE "LiteLLM_SearchToolsTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_SearchToolsTable_search_tool_name_key" ON "LiteLLM_SearchToolsTable"("search_tool_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_SearchToolsTable_search_tool_name_key" ON "LiteLLM_SearchToolsTable"("search_tool_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_SSOConfig" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_SSOConfig" (
|
||||
"id" TEXT NOT NULL DEFAULT 'sso_config',
|
||||
"sso_settings" JSONB NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
@ -9,7 +9,7 @@ CREATE TABLE "LiteLLM_SSOConfig" (
|
|||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_CacheConfig" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_CacheConfig" (
|
||||
"id" TEXT NOT NULL DEFAULT 'cache_config',
|
||||
"cache_settings" JSONB NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ManagedVectorStoreIndexTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ManagedVectorStoreIndexTable" (
|
||||
"id" TEXT NOT NULL,
|
||||
"index_name" TEXT NOT NULL,
|
||||
"litellm_params" JSONB NOT NULL,
|
||||
|
|
@ -13,5 +13,5 @@ CREATE TABLE "LiteLLM_ManagedVectorStoreIndexTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_ManagedVectorStoreIndexTable_index_name_key" ON "LiteLLM_ManagedVectorStoreIndexTable"("index_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_ManagedVectorStoreIndexTable_index_name_key" ON "LiteLLM_ManagedVectorStoreIndexTable"("index_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "static_headers" JSONB DEFAULT '{}';
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "static_headers" JSONB DEFAULT '{}';
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN "credentials" JSONB DEFAULT '{}';
|
||||
ALTER TABLE "LiteLLM_MCPServerTable" ADD COLUMN IF NOT EXISTS "credentials" JSONB DEFAULT '{}';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_ProjectTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_ProjectTable" (
|
||||
"project_id" TEXT NOT NULL,
|
||||
"project_alias" TEXT,
|
||||
"team_id" TEXT,
|
||||
|
|
@ -19,17 +19,37 @@ CREATE TABLE "LiteLLM_ProjectTable" (
|
|||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD CONSTRAINT "LiteLLM_ProjectTable_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "LiteLLM_TeamTable"("team_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_ProjectTable_team_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD CONSTRAINT "LiteLLM_ProjectTable_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "LiteLLM_TeamTable"("team_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD CONSTRAINT "LiteLLM_ProjectTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_ProjectTable_budget_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD CONSTRAINT "LiteLLM_ProjectTable_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "LiteLLM_BudgetTable"("budget_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD CONSTRAINT "LiteLLM_ProjectTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_ProjectTable_object_permission_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD CONSTRAINT "LiteLLM_ProjectTable_object_permission_id_fkey" FOREIGN KEY ("object_permission_id") REFERENCES "LiteLLM_ObjectPermissionTable"("object_permission_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- AlterTable: Add project_id to LiteLLM_VerificationToken
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN "project_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD COLUMN IF NOT EXISTS "project_id" TEXT;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "LiteLLM_ProjectTable"("project_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'LiteLLM_VerificationToken_project_id_fkey') THEN
|
||||
ALTER TABLE "LiteLLM_VerificationToken" ADD CONSTRAINT "LiteLLM_VerificationToken_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "LiteLLM_ProjectTable"("project_id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- AlterTable: Add new fields to LiteLLM_ProjectTable
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD COLUMN "description" TEXT;
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD COLUMN "model_rpm_limit" JSONB NOT NULL DEFAULT '{}';
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD COLUMN "model_tpm_limit" JSONB NOT NULL DEFAULT '{}';
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD COLUMN IF NOT EXISTS "description" TEXT;
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD COLUMN IF NOT EXISTS "model_rpm_limit" JSONB NOT NULL DEFAULT '{}';
|
||||
ALTER TABLE "LiteLLM_ProjectTable" ADD COLUMN IF NOT EXISTS "model_tpm_limit" JSONB NOT NULL DEFAULT '{}';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyTagSpend" ADD COLUMN "request_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_DailyTagSpend" ADD COLUMN IF NOT EXISTS "request_id" TEXT;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_DailyOrganizationSpend" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_DailyOrganizationSpend" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organization_id" TEXT,
|
||||
"date" TEXT NOT NULL,
|
||||
|
|
@ -23,20 +23,20 @@ CREATE TABLE "LiteLLM_DailyOrganizationSpend" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyOrganizationSpend_date_idx" ON "LiteLLM_DailyOrganizationSpend"("date");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyOrganizationSpend_date_idx" ON "LiteLLM_DailyOrganizationSpend"("date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyOrganizationSpend_organization_id_idx" ON "LiteLLM_DailyOrganizationSpend"("organization_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyOrganizationSpend_organization_id_idx" ON "LiteLLM_DailyOrganizationSpend"("organization_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyOrganizationSpend_api_key_idx" ON "LiteLLM_DailyOrganizationSpend"("api_key");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyOrganizationSpend_api_key_idx" ON "LiteLLM_DailyOrganizationSpend"("api_key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyOrganizationSpend_model_idx" ON "LiteLLM_DailyOrganizationSpend"("model");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyOrganizationSpend_model_idx" ON "LiteLLM_DailyOrganizationSpend"("model");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_DailyOrganizationSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyOrganizationSpend"("mcp_namespaced_tool_name");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_DailyOrganizationSpend_mcp_namespaced_tool_name_idx" ON "LiteLLM_DailyOrganizationSpend"("mcp_namespaced_tool_name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_DailyOrganizationSpend_organization_id_date_api_key_key" ON "LiteLLM_DailyOrganizationSpend"("organization_id", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_DailyOrganizationSpend_organization_id_date_api_key_key" ON "LiteLLM_DailyOrganizationSpend"("organization_id", "date", "api_key", "model", "custom_llm_provider", "mcp_namespaced_tool_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "LiteLLM_AgentsTable" (
|
||||
CREATE TABLE IF NOT EXISTS "LiteLLM_AgentsTable" (
|
||||
"agent_id" TEXT NOT NULL,
|
||||
"agent_name" TEXT NOT NULL,
|
||||
"litellm_params" JSONB,
|
||||
|
|
@ -13,5 +13,5 @@ CREATE TABLE "LiteLLM_AgentsTable" (
|
|||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_AgentsTable_agent_name_key" ON "LiteLLM_AgentsTable"("agent_name");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_AgentsTable_agent_name_key" ON "LiteLLM_AgentsTable"("agent_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ DROP INDEX IF EXISTS "LiteLLM_PromptTable_prompt_id_key";
|
|||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_PromptTable"
|
||||
ADD COLUMN "version" INTEGER NOT NULL DEFAULT 1;
|
||||
ADD COLUMN IF NOT EXISTS "version" INTEGER NOT NULL DEFAULT 1;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LiteLLM_PromptTable_prompt_id_idx" ON "LiteLLM_PromptTable" ("prompt_id");
|
||||
CREATE INDEX IF NOT EXISTS "LiteLLM_PromptTable_prompt_id_idx" ON "LiteLLM_PromptTable" ("prompt_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LiteLLM_PromptTable_prompt_id_version_key" ON "LiteLLM_PromptTable" ("prompt_id", "version");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "LiteLLM_PromptTable_prompt_id_version_key" ON "LiteLLM_PromptTable" ("prompt_id", "version");
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN "organization_id" TEXT;
|
||||
ALTER TABLE "LiteLLM_SpendLogs" ADD COLUMN IF NOT EXISTS "organization_id" TEXT;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue