diff --git a/ui/litellm-dashboard/src/components/model_info_view.tsx b/ui/litellm-dashboard/src/components/model_info_view.tsx
index 205998476c2..66a00b9bbe3 100644
--- a/ui/litellm-dashboard/src/components/model_info_view.tsx
+++ b/ui/litellm-dashboard/src/components/model_info_view.tsx
@@ -253,10 +253,57 @@ export default function ModelInfoView({
max_retries: values.max_retries,
timeout: values.timeout,
stream_timeout: values.stream_timeout,
- input_cost_per_token: values.input_cost / 1_000_000,
- output_cost_per_token: values.output_cost / 1_000_000,
tags: values.tags,
};
+
+ if (form.isFieldTouched("input_cost")) {
+ if (values.input_cost !== undefined && values.input_cost !== null && values.input_cost !== "") {
+ updatedLitellmParams.input_cost_per_token = Number(values.input_cost) / 1_000_000;
+ } else {
+ // Explicit null signals the backend to remove the pricing override.
+ updatedLitellmParams.input_cost_per_token = null;
+ }
+ }
+ if (form.isFieldTouched("output_cost")) {
+ if (values.output_cost !== undefined && values.output_cost !== null && values.output_cost !== "") {
+ updatedLitellmParams.output_cost_per_token = Number(values.output_cost) / 1_000_000;
+ } else {
+ updatedLitellmParams.output_cost_per_token = null;
+ }
+ }
+
+ // Cache Read Cost:
+ // - explicit value provided → use it
+ // - field touched but empty → explicit null (signals backend to remove override)
+ // - only input_cost touched → fall back to input_cost (guarded against null)
+ if (form.isFieldTouched("cache_read_cost") || form.isFieldTouched("input_cost")) {
+ if (values.cache_read_cost !== undefined && values.cache_read_cost !== null && values.cache_read_cost !== "") {
+ updatedLitellmParams.cache_read_input_token_cost = Number(values.cache_read_cost) / 1_000_000;
+ } else if (form.isFieldTouched("cache_read_cost")) {
+ updatedLitellmParams.cache_read_input_token_cost = null;
+ } else if (
+ updatedLitellmParams.input_cost_per_token !== undefined &&
+ updatedLitellmParams.input_cost_per_token !== null
+ ) {
+ updatedLitellmParams.cache_read_input_token_cost = updatedLitellmParams.input_cost_per_token;
+ }
+ }
+
+ // Cache Write Cost: explicit value if provided, else explicit null so the
+ // backend removes the override and falls back to the model-level default.
+ // Sending 0 here would persist a zero rate even when the user intended to unset it.
+ if (form.isFieldTouched("cache_write_cost")) {
+ if (
+ values.cache_write_cost !== undefined &&
+ values.cache_write_cost !== null &&
+ values.cache_write_cost !== ""
+ ) {
+ updatedLitellmParams.cache_creation_input_token_cost = Number(values.cache_write_cost) / 1_000_000;
+ } else {
+ updatedLitellmParams.cache_creation_input_token_cost = null;
+ }
+ }
+
if (values.litellm_credential_name) {
updatedLitellmParams.litellm_credential_name = values.litellm_credential_name;
} else {
@@ -373,6 +420,12 @@ export default function ModelInfoView({
model: localModelData.litellm_model_name,
},
{
+ // `id` is required to disambiguate when multiple deployments
+ // share the same model_name (e.g. wildcard `openai/*` with two
+ // different `api_base` values for failover). Without it the
+ // backend silently falls back to deployments[0] and probes
+ // the wrong endpoint.
+ id: localModelData.model_info?.id,
mode: localModelData.model_info?.mode,
},
localModelData.model_info?.mode,
@@ -449,10 +502,11 @@ export default function ModelInfoView({
size="small"
icon={copiedStates["model-id"] ?