litellm - 💡(How to fix) Fix Azure Model Router: /spend/logs stores router model instead of actual selected model

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Root Cause Analysis

Code Example

{
     "model": "azure_ai/gpt-5.4-mini-2026-03-17"
   }

---

{
     "model": "azure_ai/model_router/model-router",
     "model_group": "model-router",
     "custom_llm_provider": "azure_ai",
     "metadata": {
       "model_map_information": {
         "model_map_key": "azure_ai/model_router"
       },
       "cost_breakdown": {
         "additional_costs": {
           "Azure Model Router Flat Cost": ...
         }
       }
     }
   }

---

- model_name: model-router
     litellm_params:
       model: azure_ai/model_router/model-router
       api_base: https://<foundry>.services.ai.azure.com
       api_key: os.environ/AZURE_API_KEY
     model_info:
       base_model: azure_ai/model_router

---

curl -s http://<proxy>/v1/chat/completions \
     -H "Authorization: Bearer $LITELLM_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "model": "model-router",
       "messages": [{"role":"user","content":"Reply with just pong"}],
       "max_tokens": 16,
       "stream": false
     }'

---

{
     "id": "chatcmpl-...",
     "model": "azure_ai/gpt-5.4-mini-2026-03-17"
   }

---

{
     "model": "azure_ai/model_router/model-router"
   }

---

custom_llm_provider = kwargs.get("custom_llm_provider")
   raw_model = cast(str, kwargs.get("model") or "")
   model_name = reconstruct_model_name(raw_model, custom_llm_provider, metadata or {})

---

if standard_logging_payload is not None and standard_logging_payload.get("model"):
       model_name = standard_logging_payload["model"]
   else:
       custom_llm_provider = kwargs.get("custom_llm_provider")
       raw_model = cast(str, kwargs.get("model") or "")
       model_name = reconstruct_model_name(raw_model, custom_llm_provider, metadata or {})

---
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

When using azure_ai/model_router/..., LiteLLM correctly returns the actual selected model in the API response, but /spend/logs stores the router deployment model instead.

Example:

  • actual response model:
    • azure_ai/gpt-5.4-mini-2026-03-17
  • spend log stored model:
    • azure_ai/model_router/model-router

This makes spend logs inconsistent with the user-facing response and hides which Azure model was actually selected by Azure Model Router.

────────────────────────────────────────────────────────────────────────────────

LiteLLM Version

Observed on:

  • ghcr.io/berriai/litellm-database:main-v1.83.14-stable

Also traced in source history in local clone.

────────────────────────────────────────────────────────────────────────────────

Expected Behavior

For Azure Model Router requests, /spend/logs should store the same effective model that LiteLLM preserves in the response / standard logging flow, e.g.:

  {
    "model": "azure_ai/gpt-5.4-mini-2026-03-17"
  }

model_map_information can still point to:

  • azure_ai/model_router

and cost breakdown can still include:

  • Azure Model Router Flat Cost

but top-level spend-log model should reflect the actual model selected by Azure.

────────────────────────────────────────────────────────────────────────────────

Actual Behavior

/v1/chat/completions response shows the actual selected model correctly, but /spend/logs for the same request stores:

  {
    "model": "azure_ai/model_router/model-router",
    "model_group": "model-router",
    "custom_llm_provider": "azure_ai",
    "metadata": {
      "model_map_information": {
        "model_map_key": "azure_ai/model_router"
      },
      "cost_breakdown": {
        "additional_costs": {
          "Azure Model Router Flat Cost": ...
        }
      }
    }
  }

So the selected downstream model is lost in spend tracking.

Steps to Reproduce

Config

Using a model group configured like:

  - model_name: model-router
    litellm_params:
      model: azure_ai/model_router/model-router
      api_base: https://<foundry>.services.ai.azure.com
      api_key: os.environ/AZURE_API_KEY
    model_info:
      base_model: azure_ai/model_router

Request

  curl -s http://<proxy>/v1/chat/completions \
    -H "Authorization: Bearer $LITELLM_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "model-router",
      "messages": [{"role":"user","content":"Reply with just pong"}],
      "max_tokens": 16,
      "stream": false
    }'

Response

The response correctly contains something like:

  {
    "id": "chatcmpl-...",
    "model": "azure_ai/gpt-5.4-mini-2026-03-17"
  }

Spend log lookup

Then query /spend/logs?request_id=<response id>.

Observed spend log row contains:

  {
    "model": "azure_ai/model_router/model-router"
  }

instead of the actual selected model.

────────────────────────────────────────────────────────────────────────────────

Root Cause Analysis

The issue appears to be in:

  • litellm/proxy/spend_tracking/spend_tracking_utils.py

Inside get_logging_payload() the spend log model is derived from the request kwargs:

  custom_llm_provider = kwargs.get("custom_llm_provider")
  raw_model = cast(str, kwargs.get("model") or "")
  model_name = reconstruct_model_name(raw_model, custom_llm_provider, metadata or {})

So spend logs use the requested model (model-router) rather than the actual model already preserved earlier in the pipeline.

This is inconsistent with:

  • litellm/llms/azure_ai/azure_model_router/transformation.py
  • litellm/proxy/common_request_processing.py
  • litellm/litellm_core_utils/litellm_logging.py

which already preserve the actual selected model for Azure Model Router responses / standard logging.

────────────────────────────────────────────────────────────────────────────────

Suggested Fix

In get_logging_payload(), prefer the model already present in standard_logging_payload["model"] when available.

Something like:

  if standard_logging_payload is not None and standard_logging_payload.get("model"):
      model_name = standard_logging_payload["model"]
  else:
      custom_llm_provider = kwargs.get("custom_llm_provider")
      raw_model = cast(str, kwargs.get("model") or "")
      model_name = reconstruct_model_name(raw_model, custom_llm_provider, metadata or {})

This would keep spend logs aligned with the already-correct response behavior.

────────────────────────────────────────────────────────────────────────────────

Git History Notes

This inconsistency seems related to:

  • f7241a7905 — fix: unify model names to provider-defined names
  • 5b83aae715 — feat(azure_ai): show actual model used in Azure Model Router response

The latter fixed the response path, but spend log generation still reconstructs the model from request kwargs.

────────────────────────────────────────────────────────────────────────────────

Additional Notes

  • model_map_information being azure_ai/model_router is fine
  • Azure Model Router Flat Cost in additional_costs is also fine
  • the issue is specifically that spend-log top-level model does not reflect the actual selected Azure model

Relevant log output

What part of LiteLLM is this about?

No response

What LiteLLM version are you on ?

v1.83.14

Twitter / LinkedIn details

No response

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

litellm - 💡(How to fix) Fix Azure Model Router: /spend/logs stores router model instead of actual selected model