feat(ui): edit project input and output TPM limits from the Projects modal - #37676
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
Greptile SummaryThe PR exposes per-model input and output TPM limits in the Projects modal and ensures explicitly cleared limits are sent to
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the previously reported persisted-limit issue is fixed by sending explicit empty maps on advanced updates, with frontend and endpoint regression coverage.
|
| Filename | Overview |
|---|---|
| ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectModals/projectFormUtils.ts | Separates create and update payload construction so updates transmit empty maps needed to clear persisted quotas. |
| ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectModals/EditProjectModal.tsx | Hydrates input/output TPM limits from metadata while preserving untouched-save behavior until Advanced Settings is opened. |
| ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectModals/ProjectBaseForm.tsx | Adds accessible per-model input and output TPM controls to the advanced project form. |
| tests/enterprise/litellm_enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py | Verifies explicit empty maps clear stored limits while omitted limit fields leave metadata untouched. |
Reviews (3): Last reviewed commit: "feat(ui): support project input and outp..." | Re-trigger Greptile
fdc0bfa to
b40a22f
Compare
|
@greptileai please re-review at b40a22f: the cleared-limit path now sends explicitly empty maps on update, with frontend and backend regression tests. |
The Model-Specific Limits rows now carry Input TPM and Output TPM, and a limit the operator removes is sent as an explicitly empty map so /project/update actually drops it instead of leaving the stored quota enforced behind a UI that shows it gone. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
b40a22f to
a037dae
Compare
|
@greptileai re-anchor at a037dae please: pure rebase onto staging to pick up ruff-tests.toml, no code change since your 5/5. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
c74e9e7
into
litellm_internal_staging
TLDR
Problem this solves:
How it solves it:
User Flow
Before: an admin capping input and output tokens separately for an application cannot do it from the Projects page, and cannot take a cap back off once it exists
model_itpm_limitandmodel_otpm_limit, which only accept a single string value, not a per-model mapAfter: the same admin sets and later removes independent input and output caps per model straight from the modal
Relevant issues
Linear ticket
Resolves LIT-4693
Review notes
The Projects modal talks to
/project/update, where an omitted key means "leave the stored value alone". The form used to omit any limit map that came out empty, so removing a quota in the UI sent nothing about it and the proxy kept enforcing the quota the admin believed was gone. Empty metadata behaved the same way.The fix splits the payload builder in two. Create still leaves blanks out, since a new project has nothing to clear. Update sends every map the form knows about, empty included, and an empty map is what makes the stored quota disappear. The absent case is still reachable: the Edit modal submits nothing about guardrails, limits or metadata unless Advanced Settings was opened, so an untouched save is byte for byte what it was before.
Both halves are covered. On the frontend, the modal test removes the row and asserts the payload carries
model_itpm_limit: {}; restoring the omit-when-empty behaviour fails it. On the backend,/project/updateis exercised with an empty map and asserted to write metadata that no longer carries the quota, alongside the counterpart test pinning that an update which says nothing about limits does not touch metadata at all.Pre-Submission checklist
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Shared setup, run against a live proxy on a namespaced port so it does not collide with anything already on 4000:
Every curl below was run live against that proxy and its output is pasted verbatim. The numbered UI steps are the screenshots still to attach: the dashboard is
npm run devinui/litellm-dashboardpointed at the same proxy, and each save it performs sends exactly the payload shown next to itBefore (fdc0bfa)
Clearing a stored input TPM limit
lit-4693-demoproject, expand Advanced Settings, and remove thegpt-4o-minirow. Save, and the modal reports successmodel_itpm_limitat all, so this is what the proxy is asked to act on:After (a037dae)
Clearing a stored input TPM limit
lit-4693-demoproject, expand Advanced Settings, remove thegpt-4o-minirow, and saveowner, and the UI and/project/infonow agree that the quota is goneSetting input and output TPM limits from the modal
gpt-4o-mini, 6000 Input TPM, 4000 Output TPM, and save. The setup above stores that same pair, which is the state the next step reads back:Type
🆕 New Feature
Caveats (if any)
Final Attestation
Link to Devin session: https://app.devin.ai/sessions/ed1e7fcde5704c6485c5eed12930b901
Requested by: @yassin-berriai