feat(complexity_router): add custom_technical_keywords config - #32262
Conversation
Greptile SummaryThis PR adds a
Confidence Score: 5/5Additive feature with no changes to existing routing logic; safe to merge. The change is purely additive — existing routers with no No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/router_strategy/complexity_router/complexity_router.py | Added _append_custom_keywords helper and wired custom_technical_keywords into ComplexityRouter.__init__. Logic is correct: uses re.escape in matching, preserves insertion order, and deduplicates case-insensitively. |
| litellm/router_strategy/complexity_router/config.py | Added custom_technical_keywords: Optional[list[str]] field with a clear description to ComplexityRouterConfig; additive change with no breaking impact. |
| tests/test_litellm/router_strategy/test_complexity_router.py | Added TestCustomTechnicalKeywords with 5 tests covering append-to-defaults, append-to-override, case-insensitive dedup, absent/null no-op, and scoring behavior. No real network calls; all mocked. |
| ui/litellm-dashboard/src/components/add_model/ComplexityRouterConfig.tsx | Added optional customTechnicalKeywords / onCustomTechnicalKeywordsChange props and a new Ant Design Select tags input UI card; correctly falls back to [] and uses optional chaining for the callback. |
| ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx | Adds customTechnicalKeywords state, passes it to ComplexityRouterConfig, and conditionally spreads it into the submission payload only when non-empty. |
| ui/litellm-dashboard/src/components/add_model/ComplexityRouterConfig.test.tsx | Added 3 tests: field rendering, existing keyword tag display, and change-callback firing. Uses userEvent and within scoping correctly. |
Reviews (2): Last reviewed commit: "feat(complexity_router): add custom_tech..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Relevant issues
Linear ticket
Resolves LIT-3237
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewDelays 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
Verified end to end against a live DB-less proxy hitting the real OpenAI API: fresh Python 3.13 venv with
pip install -e ".[proxy]"in a detached worktree, random port 41624, identical config and identical prompt for both runs, so the only variable is the checked out code (base29035c4a99vs PR headc5813586). The config maps SIMPLE and MEDIUM togpt-5.4-miniand COMPLEX and REASONING togpt-5.5, and setscustom_technical_keywords. The test prompt contains eight custom keywords (kafka, redis, postgresql, mongodb, dns, udp, ssl, ssh) and exactly one built-in keyword ("api"), so it scores 0.150 (MEDIUM, weak model) when the custom list is ignored and 0.400 (COMPLEX, strong model) when it is appliedThe served deployment is identified by the
x-litellm-model-idresponse header;/v1/model/infoon the running proxy maps the ids (same mapping on both SHAs since the hash is derived from litellm_params)Before (base
29035c4a): the prompt full of custom keywords routes to the weak model becausecustom_technical_keywordsis silently ignoredRan the same curl a second time on the base SHA: same
x-litellm-model-idd6a6a3a9...(gpt-5.4-mini) since the router is deterministicAfter (PR head
c5813586): proxy killed,git checkout --detach c5813586334944dcbf1f39da864fc06ed17e2471, proxy restarted with the same config and port, same curl now routes to the strong modelRan the main prompt three times total on the PR head (including across a proxy restart): all three returned
x-litellm-model-id2f96736f...(gpt-5.5). A control prompt with no technical keywords ("Hello, please share a fun fact about the Eiffel Tower.") routed tod6a6a3a9...(gpt-5.4-mini) on both SHAs, confirming the flip is attributable tocustom_technical_keywordsand not a general routing changeType
🆕 New Feature
Changes
Adds a
custom_technical_keywordsoption to the complexity router. Unliketechnical_keywords, which replaces the built-in list entirely, the new field appends domain-specific terms to the effective base list (technical_keywordsif set, otherwiseDEFAULT_TECHNICAL_KEYWORDS), preserving order and deduplicating case-insensitively against the base list and within itself. Custom keywords go through the same case-insensitive word boundary matching as the built-ins. This came out of a report from a customer whose technical prompts routed to weaker models because the default list misses common terms; it contains "tcp" but not "udp", for exampleOn the backend,
ComplexityRouterConfiggains the new field andComplexityRouter.__init__resolves the merged list through a small pure helper. On the Admin UI, the complexity router form in the Add Auto Router flow gets a tags input for custom technical keywords, and the entered terms are submitted ascustom_technical_keywords: string[]insidecomplexity_router_configwhen non-emptyUnit tests cover appending to the defaults, appending to a
technical_keywordsoverride, case-insensitive dedup, unchanged behavior when the option is absent or null, and a scoring-level check that a prompt matching only custom keywords scores higher on the technicalTerms dimension. UI tests cover rendering the new field, displaying existing keywords as tags, and firing the change callback when a keyword is entered