Skip to content

fix(azure_ai): bill FLUX.2 by the megapixels Azure reports in request_meta - #43094

Draft
devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
litellm_lit8140_flux2_input_image_billing
Draft

devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
litellm_lit8140_flux2_input_image_billing

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

what to review

FLUX.2 edits on Azure logged about half of what Azure bills. LiteLLM now bills the megapixels Azure itself reports on every response

summary

  • Only changes cost for Azure AI FLUX.2 generations and edits
  • Other models and providers keep their old cost
  • A response without valid request_meta keeps the old output-only cost
  • Proxy image edits now honor a deployment's own input_cost_per_pixel
  • Live proxy A/B against a real Azure FLUX.2-flex deployment below

decisions

  • Azure's reported input_mp + output_mp is the billed quantity, so no image parsing and no per-image count
  • One shared input_cost_per_pixel rate for input and output megapixels, since Azure prices both at $0.05/MP
  • Flex rate is $0.05 / 2^20 pixels, because Azure reports a 640x640 image as 0.39 MP and 1024x1024 as 1.0 MP

TLDR

Problem this solves:

  • Azure bills FLUX.2 reference images, LiteLLM priced only the output
  • Spend logs, budgets and chargeback undercounted every edit
  • Proxy image edits ignored a deployment's custom pixel rate
  • Flex rate used 10^6 pixels per MP, overbilling output 4.9%

How it solves it:

  • Keep Azure's request_meta.input_mp and output_mp from the response
  • Cost is input_cost_per_pixel * 2^20 * (input_mp + output_mp)
  • Image edits pass deployment pricing through to cost tracking
  • Flex catalog rate is now $0.05 / 1,048,576 pixels

User Flow

Before: a team editing images through Azure FLUX.2-flex sees LiteLLM spend well below their Azure invoice

  1. They send POST http://localhost:4000/v1/images/edits with one or more reference images and size=1024x1024
  2. The response header reads x-litellm-response-cost: 0.0524288 whatever they uploaded, even a 12 MP photo
  3. Azure bills every reference megapixel on top of the output, so budgets and chargeback drift from the invoice

After: the same edit is priced from Azure's own measurement of the call

  1. They send the same POST http://localhost:4000/v1/images/edits
  2. The header reads 0.1 for one 1024x1024 reference and 0.6315 for one 4032x3024 photo, which Azure measured at 11.63 MP
  3. The spend log row for the call carries the same number

Relevant issues

Affected release

Linear ticket

Resolves LIT-8140

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. 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
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to 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

Both proxies run the same config against a real Azure AI Foundry FLUX.2-flex deployment: azure_ai/FLUX.2-flex at the catalog rate, flux-flex-override with input_cost_per_pixel: 1.5e-07, and flux-flex-zeroref with input_cost_per_pixel: 0.0. Base runs on port 4100, tip on 4200. The reference images are PNGs of the size in each case name

Edits are sent as curl -s -D - -o /dev/null localhost:$PORT/v1/images/edits -H "Authorization: Bearer $KEY" -F model=$MODEL -F prompt="make it a watercolor" -F size=1024x1024 -F "image[]=@ref.png" (one -F "image[]=..." per reference). Generations are curl -s -D - -o /dev/null localhost:$PORT/v1/images/generations -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"model":"azure_ai/FLUX.2-flex","prompt":"a watercolor fox","size":"<size>"}'

Azure's own request_meta for these calls, from direct calls to the deployment: 640x640 generation 0 in / 0.39 out, one 640x640 ref 0.39 / 1.0, one 1024x1024 ref 1.0 / 1.0, one 1280x720 ref 0.88 / 1.0, three 1024x1024 refs 3.0 / 1.0, one 4032x3024 ref 11.63 / 1.0, one 8000x6000 ref 45.78 / 1.0, 4032x3024 plus 640x640 refs 2.0 / 1.0

Before (37f5267)

x-litellm-response-cost per call

  1. gen 640x640 returns HTTP 200, 0.02048
  2. gen 1024x1024 returns HTTP 200, 0.0524288
  3. edit 1 ref 640x640 returns HTTP 200, 0.0524288
  4. edit 1 ref 1024x1024 returns HTTP 200, 0.0524288
  5. edit 1 ref 1280x720 returns HTTP 200, 0.0524288
  6. edit 3 refs 1024x1024 returns HTTP 200, 0.0524288
  7. edit 1 ref 4032x3024 returns HTTP 200, 0.0524288
  8. edit 1 ref 8000x6000 returns HTTP 200, 0.0524288
  9. edit 2 refs 4032x3024 + 640x640 returns HTTP 200, 0.0524288
  10. flux-flex-override, 1 ref 4032x3024 returns HTTP 200, 0.0524288
  11. flux-flex-zeroref, 1 ref 4032x3024 returns HTTP 200, 0.0524288

After (61a361a)

x-litellm-response-cost per call

  1. gen 640x640 returns HTTP 200, 0.0195
  2. gen 1024x1024 returns HTTP 200, 0.05
  3. edit 1 ref 640x640 returns HTTP 200, 0.0695
  4. edit 1 ref 1024x1024 returns HTTP 200, 0.1
  5. edit 1 ref 1280x720 returns HTTP 200, 0.094
  6. edit 3 refs 1024x1024 returns HTTP 200, 0.2
  7. edit 1 ref 4032x3024 returns HTTP 200, 0.6315
  8. edit 1 ref 8000x6000 returns HTTP 200, 2.339
  9. edit 2 refs 4032x3024 + 640x640 returns HTTP 200, 0.15
  10. flux-flex-override, 1 ref 4032x3024 returns HTTP 200, 1.986527232
  11. flux-flex-zeroref, 1 ref 4032x3024 returns HTTP 200, no cost header (the image endpoints already omit a zero cost header)

Every After number is rate * 2^20 * (input_mp + output_mp) for Azure's measurement of that call

Type

🐛 Bug Fix

Caveats (if any)

Medium

  • FLUX.2-pro prices per image, so its references are still unbilled

Low

  • Image endpoints omit x-litellm-response-cost when the cost is exactly 0
    • Pre-existing, the spend log still records 0

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Link to Devin session: https://app.devin.ai/sessions/70b30e9f289d49e08561526f9110a933
Open in Devin Desktop: https://app.devin.ai/desktop/session/70b30e9f289d49e08561526f9110a933?variant=devin
Requested by: @shreshth-berri


Note

Medium Risk
Changes spend calculation and proxy cost headers for Azure FLUX.2 only, with fallback when request_meta is absent; incorrect parsing would mis-bill budgets and chargeback.

Overview
Azure AI FLUX.2 image generation and edits were undercounting spend because LiteLLM priced mostly from output dimensions and ignored reference-image megapixels Azure bills separately.

Responses now parse request_meta.input_mp and output_mp, store the sum on ImageResponse.provider_billed_megapixels, and the Azure AI cost path charges input_cost_per_pixel × 2²⁰ × (input_mp + output_mp) when that metadata is valid. Invalid or missing metadata keeps the previous dimension-based pixel pricing.

The FLUX.2-flex catalog input_cost_per_pixel is adjusted so one megapixel matches Azure’s $0.05/MP (using 1,048,576 pixels per MP). Proxy image edits merge deployment CustomPricingLiteLLMParams (e.g. override input_cost_per_pixel) into pre-call logging so spend headers and logs respect deployment rates. Azure image generation routing applies the FLUX.2 response transformer where needed.

Reviewed by Cursor Bugbot for commit 3608ba3. Bugbot is set up for automated code reviews on this repo. Configure here.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@codecov

codecov Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed

codspeed Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_lit8140_flux2_input_image_billing (3608ba3) with main (5a75f09)

Open in CodSpeed

@devin-ai-integration devin-ai-integration Bot changed the title fix(azure_ai): bill FLUX.2-flex edit reference images as one megapixel each fix(azure_ai): bill FLUX.2 by the megapixels Azure reports in request_meta Sep 25, 2026

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Critical risk] Changes how image generation costs are calculated and billed.

The PR appears safe to merge based on the reviewed changes.

Summary

This PR prices Azure AI FLUX.2 images using Azure-reported megapixels and passes deployment pixel pricing through proxy image edits. The latest change rejects non-finite megapixel totals and tests the fallback.

Reviews (2) · Last reviewed commit: "fix(azure_ai): ignore non-finite FLUX.2 ..."

Comment thread litellm/llms/azure_ai/image_generation/flux_transformation.py Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3608ba3. Configure here.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants