Repository navigation
feat(databricks): price Unity Catalog system.ai model services - #44839
Conversation
Databricks exposes every pay-per-token foundation model as a ready-to-use model service in the Unity Catalog system.ai schema, named like system.ai.claude-opus-5 (the databricks- prefix dropped). Requests sent as databricks/system.ai.<name> previously had no model info, so cost tracking and capability lookups failed. Add a databricks/system.ai.<name> entry for every databricks/databricks-<name> entry, identical to its endpoint twin, and a test that keeps the two sets in sync. The published-rate audit test now iterates endpoint names only, since the twins are covered by the sync test. Co-authored-by: Claude <noreply@anthropic.com>
|
…ates Four databricks gemini entries (3.7 flash, 3.8 flash, 3.1 flash image, 3 pro image) carried endpoint metadata only, so their system.ai twins also tracked $0 spend. Databricks has not published DBU rates for them yet, so copy the standard-tier token, cache read, reasoning and image rates from the matching gemini/ entry, bill cache creation at the input rate, and record that provenance in the entry notes and source. The published-rate audit test skips these entries and a new test pins each one to its gemini/ twin so the two cannot drift apart. Co-authored-by: Claude <noreply@anthropic.com>
…Gateway Unity Catalog model services (system.ai.<name>) are served by the AI Gateway at /ai-gateway/mlflow/v1. The chat adapter already switched to that base for two-dot model names, but the Responses adapter and the embeddings handler kept appending /responses and /embeddings to the legacy /serving-endpoints base, so a Unity GPT or embedding deployment hit the wrong URL. Share the detection in one helper and apply it in all three paths. The Responses URL builder now receives the model name from the handler, since it had no other way to tell a Unity name from an endpoint name. Databricks has since published DBU rates for Gemini 3.7 Flash, 3.8 Flash, 3 Pro Image and 3.1 Flash Image, so those four entries and their twins now follow the usual DBU times $0.070 convention instead of the Google list rate added in the previous commit. The Flash rates carry Databricks' 50% promotion note; at the promotional rate they equal Google's list price. Co-authored-by: Claude <noreply@anthropic.com>
|
@greptileai please re-review. Routing for Unity Responses and embeddings fixed, and Gemini rows now use Databricks DBU rates. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-authored-by: Claude <noreply@anthropic.com>
|
@greptileai please re-review. Added source and date beside the new DBU rows; promotional rate kept deliberately, see reply. |
The embedding routing test patched the parent handler and only inspected the mock's call, which the test-quality gate flags as mock-echo. Fake the workspace with an httpx MockTransport instead and assert the URL it received plus the embedding the caller gets back. Co-authored-by: Claude <noreply@anthropic.com>
|
Any updates on this? The existing Databricks provider does not work. |
|
I can workaround this by adding the databricks/databricks-xx model name under "base_model" for now. |
TLDR
Problem this solves:
system.ai.<name>databricks/system.ai.claude-opus-5had no pricing, so spend tracked as $0/serving-endpointsURLHow it solves it:
databricks/system.ai.<name>twin for all 62databricks/databricks-<name>entries/ai-gateway/mlflow/v1like chat already didUser Flow
Before: a proxy admin who points deployments at Unity Catalog model services sees $0 spend and failing Responses and embedding calls
model: databricks/system.ai.claude-opus-5andmodel: databricks/system.ai.bge-large-ento their config and start the proxy/serving-endpoints/embeddingsAfter: the same deployments show real Databricks pay-per-token pricing and every request reaches the Unity gateway
/ai-gateway/mlflow/v1/embeddingsPre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/unit/<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. No Databricks workspace credentials were available, so a tiny local HTTP server on port 4011 stands in for the workspace: it logs the path and model of every POST and returns a minimal OpenAI-shaped body. Everything else is the real proxy. Config used for both runs:
Started with
python litellm/proxy/proxy_cli.py --config proxy_config.yaml --port 4010. Before runs from a worktree checked out at the merge base with the default remote cost map. After runs from this branch withLITELLM_LOCAL_MODEL_COST_MAP=Trueso the proxy reads this branch's JSON.Before (18c3118)
Model info shows pricing for the four Unity deployments
curl -s http://localhost:4010/model/info -H "Authorization: Bearer $LITELLM_MASTER_KEY"(trimmed to the pricing fields)[ { "model": "databricks/system.ai.claude-opus-5", "input_cost_per_token": null, "output_cost_per_token": null, "cache_creation_input_token_cost": null, "cache_read_input_token_cost": null, "max_input_tokens": 200000 }, { "model": "databricks/system.ai.gemini-3-8-flash", "input_cost_per_token": null, "output_cost_per_token": null, "cache_creation_input_token_cost": null, "cache_read_input_token_cost": null, "max_input_tokens": null }, { "model": "databricks/system.ai.gpt-5-5", "input_cost_per_token": null, "output_cost_per_token": null, "cache_creation_input_token_cost": null, "cache_read_input_token_cost": null, "max_input_tokens": null }, { "model": "databricks/system.ai.bge-large-en", "input_cost_per_token": null, "output_cost_per_token": null, "cache_creation_input_token_cost": null, "cache_read_input_token_cost": null, "max_input_tokens": null } ]Spend for claude-opus-5
curl -s -X POST http://localhost:4010/spend/calculate -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"completion_response":{"model":"databricks/system.ai.claude-opus-5","usage":{"prompt_tokens":1000000,"completion_tokens":1000000,"total_tokens":2000000}}}'{"cost":0.0}Spend for gemini-3-8-flash
curl -s -X POST http://localhost:4010/spend/calculate -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"completion_response":{"model":"databricks/system.ai.gemini-3-8-flash","usage":{"prompt_tokens":1000000,"completion_tokens":1000000,"total_tokens":2000000}}}'{"cost":0.0}Chat, Responses and embeddings reach the right upstream URL
curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:4010/v1/chat/completions -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"model":"claude-opus-5","messages":[{"role":"user","content":"hi"}]}'givesHTTP 200curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:4010/v1/responses -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"model":"gpt-5-5","input":"hi"}'givesHTTP 200curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:4010/v1/embeddings -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"model":"bge-large-en","input":"hi"}'givesHTTP 200system.ainame.After (a7a6043)
Model info shows pricing for the four Unity deployments
curl -s http://localhost:4010/model/info -H "Authorization: Bearer $LITELLM_MASTER_KEY"(trimmed to the pricing fields)[ { "model": "databricks/system.ai.claude-opus-5", "input_cost_per_token": 5.00003e-06, "output_cost_per_token": 2.500001e-05, "cache_creation_input_token_cost": 6.25002e-06, "cache_read_input_token_cost": 5.0001e-07, "max_input_tokens": 1000000 }, { "model": "databricks/system.ai.gemini-3-8-flash", "input_cost_per_token": 7.4998e-07, "output_cost_per_token": 3.74997e-06, "cache_creation_input_token_cost": 7.4998e-07, "cache_read_input_token_cost": 7.497e-08, "max_input_tokens": 1048576 }, { "model": "databricks/system.ai.gpt-5-5", "input_cost_per_token": 5.00003e-06, "output_cost_per_token": 2.999997e-05, "cache_creation_input_token_cost": 5.00003e-06, "cache_read_input_token_cost": 5.0001e-07, "max_input_tokens": 922000 }, { "model": "databricks/system.ai.bge-large-en", "input_cost_per_token": 1.0003e-07, "output_cost_per_token": 0.0, "cache_creation_input_token_cost": 1.0003e-07, "cache_read_input_token_cost": 1.0003e-07, "max_input_tokens": 512 } ]Spend for claude-opus-5
curl -s -X POST http://localhost:4010/spend/calculate -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"completion_response":{"model":"databricks/system.ai.claude-opus-5","usage":{"prompt_tokens":1000000,"completion_tokens":1000000,"total_tokens":2000000}}}'{"cost":30.00004}Spend for gemini-3-8-flash
curl -s -X POST http://localhost:4010/spend/calculate -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"completion_response":{"model":"databricks/system.ai.gemini-3-8-flash","usage":{"prompt_tokens":1000000,"completion_tokens":1000000,"total_tokens":2000000}}}'{"cost":4.49995}Chat, Responses and embeddings reach the right upstream URL
curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:4010/v1/chat/completions -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"model":"claude-opus-5","messages":[{"role":"user","content":"hi"}]}'givesHTTP 200curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:4010/v1/responses -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"model":"gpt-5-5","input":"hi"}'givesHTTP 200curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST http://localhost:4010/v1/embeddings -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"model":"bge-large-en","input":"hi"}'givesHTTP 200/ai-gateway/mlflow/v1.Type
🆕 New Feature
🐛 Bug Fix
Caveats (if any)
Medium
system.ai.<name>form is added. One Databricks docs page also showssystem.ai.databricks-<name>; add those if a workspace exposes that formLow
documentationandcode-qualitychecks fail onmainas well:DEFER_PYDANTIC_BUILD(added in perf(types): defer pydantic schema builds via shared LiteLLMBaseModel #44720) is not yet documented in litellm-docs, which those checks read. Nothing in this PR touches itlitellm_params, which the handler now adds at the four call sites that create a response. Get, delete, list and cancel paths have no model and keep the legacy baseFinal Attestation
Co-authored-by: Claude noreply@anthropic.com