Skip to content

fix(fal_ai): price gpt-image-2 per size and quality from request params - #37751

Merged
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_fal_gpt_image_2_keyed_pricing
Aug 21, 2026
Merged

fix(fal_ai): price gpt-image-2 per size and quality from request params#37751
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_fal_gpt_image_2_keyed_pricing

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • fal bills gpt-image-2 per size and quality, litellm charged flat $0.145
  • a $0.006 low-quality image was logged as $0.145, 24x over
  • a $0.211 high-quality 1024x1024 image was logged 31% under
  • the edit endpoint was priced at the generation rate

How it solves it:

  • adds fal's published price table as keyed cost-map entries
  • cost calculator picks the entry from the request's size and quality
  • unlisted sizes and missing params fall back to the flat entry

User Flow

Before: a developer generating a high-quality 1024x1024 image with fal gpt-image-2 sees $0.145 in spend logs while fal bills them $0.211

  1. They send POST http://litellm-domain/v1/images/generations with {"model": "fal_ai/openai/gpt-image-2", "prompt": "a red bicycle", "size": "1024x1024", "quality": "hd"}
  2. The image comes back 200, and the x-litellm-response-cost header reads 0.145
  3. They open http://litellm-domain/ui/?page=logs and the request shows $0.145 spend, though fal's dashboard bills the same call at $0.211

After: the same request is logged at fal's actual $0.211 price

  1. They send POST http://litellm-domain/v1/images/generations with {"model": "fal_ai/openai/gpt-image-2", "prompt": "a red bicycle", "size": "1024x1024", "quality": "hd"}
  2. The image comes back 200, and the x-litellm-response-cost header reads 0.211
  3. They open http://litellm-domain/ui/?page=logs and the request shows $0.211 spend, matching fal's bill

Relevant issues

Follow-up to #37729, which added fal gpt-image-2 support with a single flat price

Linear ticket

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 legs boot a real DB-backed proxy from the exact commit under test (own Postgres, random free ports, LITELLM_LOCAL_MODEL_COST_MAP=True) and hit the real fal API with the same two requests, differing only in the commit the proxy was booted from

Before (987478a)

Tree proof

/private/tmp/falqa37751-before
987478abe48ecec29d32c8f60ebbe49acfb83c80
/private/tmp/falqa37751-before/litellm/__init__.py
  1. hd 1024x1024
curl -sS -m 180 -X POST http://127.0.0.1:41983/v1/images/generations \
  -H "Authorization: Bearer sk-falqa-before" -H "Content-Type: application/json" \
  -d '{"model": "fal_ai/openai/gpt-image-2", "prompt": "a red bicycle", "size": "1024x1024", "quality": "hd"}'
HTTP/1.1 200 OK
x-litellm-call-id: 46c6dc33-d1ab-4cb7-bc81-b905ab44f0b1
x-litellm-response-cost: 0.145

Image (verified live, image/png): https://v3b.fal.media/files/b/0aa72a6b/eQv-lG5O96zx7i7Qn6qhW_SHEPbKvK.png

curl -s "http://127.0.0.1:41983/spend/logs?request_id=46c6dc33-d1ab-4cb7-bc81-b905ab44f0b1" -H "Authorization: Bearer sk-falqa-before"
{"request_id": "46c6dc33-d1ab-4cb7-bc81-b905ab44f0b1", "call_type": "aimage_generation", "spend": 0.145, "model": "fal_ai/openai/gpt-image-2", "custom_llm_provider": "fal_ai", "api_base": "https://fal.run/openai/gpt-image-2", "status": "success"}
  1. low 1024x1024
curl -sS -m 180 -X POST http://127.0.0.1:41983/v1/images/generations \
  -H "Authorization: Bearer sk-falqa-before" -H "Content-Type: application/json" \
  -d '{"model": "fal_ai/openai/gpt-image-2", "prompt": "a red bicycle", "size": "1024x1024", "quality": "low"}'
HTTP/1.1 200 OK
x-litellm-call-id: aa6ba115-5b75-48d0-b487-46d8327e39d2
x-litellm-response-cost: 0.145

Image (verified live, image/png): https://v3b.fal.media/files/b/0aa72a7b/OyUU7fZeWk4EtaIydEEVB_bq4RstLp.png

curl -s "http://127.0.0.1:41983/spend/logs?request_id=aa6ba115-5b75-48d0-b487-46d8327e39d2" -H "Authorization: Bearer sk-falqa-before"
{"request_id": "aa6ba115-5b75-48d0-b487-46d8327e39d2", "call_type": "aimage_generation", "spend": 0.145, "model": "fal_ai/openai/gpt-image-2", "custom_llm_provider": "fal_ai", "api_base": "https://fal.run/openai/gpt-image-2", "status": "success"}

Both qualities billed the flat $0.145: the low image is overcharged 24x and the hd image undercharged 31%, even though fal really rendered different qualities upstream

After (d5e6a0c)

Tree proof

/private/tmp/falprice37738
d5e6a0c9b8b262e097033f56e2aa4a8d5275bd22
/private/tmp/falprice37738/litellm/__init__.py
  1. hd 1024x1024
curl -sS -m 300 -X POST http://127.0.0.1:18734/v1/images/generations \
  -H "Authorization: Bearer sk-falqa-after2" -H "Content-Type: application/json" \
  -d '{"model": "fal_ai/openai/gpt-image-2", "prompt": "a red bicycle", "size": "1024x1024", "quality": "hd"}'
HTTP/1.1 200 OK
x-litellm-call-id: 7daa6ad4-76b1-46bc-8474-638091e70a1c
x-litellm-response-cost: 0.211

Image (verified live, image/png): https://v3b.fal.media/files/b/0aa72b03/5BWQE6p0ULdTRT1BcrvwP_8zGtRjC9.png

curl -s "http://127.0.0.1:18734/spend/logs?request_id=7daa6ad4-76b1-46bc-8474-638091e70a1c" -H "Authorization: Bearer sk-falqa-after2"
{"request_id": "7daa6ad4-76b1-46bc-8474-638091e70a1c", "call_type": "aimage_generation", "spend": 0.211, "model": "fal_ai/openai/gpt-image-2", "custom_llm_provider": "fal_ai", "status": "success"}
  1. low 1024x1024
curl -sS -m 300 -X POST http://127.0.0.1:18734/v1/images/generations \
  -H "Authorization: Bearer sk-falqa-after2" -H "Content-Type: application/json" \
  -d '{"model": "fal_ai/openai/gpt-image-2", "prompt": "a red bicycle", "size": "1024x1024", "quality": "low"}'
HTTP/1.1 200 OK
x-litellm-call-id: 476058c0-b355-41ba-8de3-41f99114a9fc
x-litellm-response-cost: 0.006

Image (verified live, image/png): https://v3b.fal.media/files/b/0aa72b13/W5u_yHg0GF1VIFxdEDCSY_2PLUZKpz.png

curl -s "http://127.0.0.1:18734/spend/logs?request_id=476058c0-b355-41ba-8de3-41f99114a9fc" -H "Authorization: Bearer sk-falqa-after2"
{"request_id": "476058c0-b355-41ba-8de3-41f99114a9fc", "call_type": "aimage_generation", "spend": 0.006, "model": "fal_ai/openai/gpt-image-2", "custom_llm_provider": "fal_ai", "status": "success"}

The hd request is billed $0.211 and the low request $0.006, matching fal's price table, and the totals agree end to end:

curl -s http://127.0.0.1:18734/global/spend -H "Authorization: Bearer sk-falqa-after2"
{"spend":0.217,"max_budget":0.0}

Notes from the runs, all pre-existing behavior this PR leaves alone:

  • response body echoes quality and size as null
  • image-generation spend rows carry no cost_breakdown
  • x-litellm-key-spend header lags one request

Type

🐛 Bug Fix

Caveats (if any)

  • quality auto is priced as high, fal's documented default
  • unlisted or custom sizes fall back to the flat entry
  • flat edit price corrected from $0.145 to $0.151

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

  • d5e6a0c passes /live-pr-risk


Note

Medium Risk
Changes spend/cost calculation for fal gpt-image-2 (including edit), so logged spend and budgets can shift vs the previous flat $0.145 rate. Unlisted sizes still fall back to the flat entry.

Overview
Prices fal.ai gpt-image-2 (and /edit) from the request's quality and size instead of always charging the default flat per-image rate.

The fal cost calculator now looks up keyed cost-map entries fal_ai/{quality}/{width}-x-{height}/… from optional_params (named fal sizes, width/height maps, quality=auto as high). Missing params or unlisted sizes still use the flat model entry. Edit fallback is corrected to $0.151. Generation and alias models keep $0.145 as the unmatched default.

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

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds request-sensitive fal.ai GPT Image 2 cost calculation using normalized image size and quality, while retaining flat fallback prices.

  • Passes transformed image request parameters into the fal.ai cost calculator.
  • Adds generation and edit pricing entries for supported size and quality combinations.
  • Adds focused tests for keyed prices, aliases, defaults, fallbacks, and multiple-image responses.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
litellm/llms/fal_ai/cost_calculator.py Adds keyed size-and-quality pricing selection, provider-prefix normalization, and flat-price fallback behavior.
litellm/litellm_core_utils/llm_cost_calc/utils.py Forwards transformed image-generation parameters to the fal.ai calculator.
model_prices_and_context_window.json Adds canonical generation and edit prices for supported GPT Image 2 size and quality combinations.
litellm/model_prices_and_context_window_backup.json Keeps the backup cost map synchronized with the canonical pricing data.
tests/test_litellm/llms/fal_ai/test_cost_calculator.py Covers keyed pricing, aliases, defaults, edit pricing, fallback behavior, and image-count multiplication.
tests/test_litellm/llms/fal_ai/image_generation/test_fal_ai_gpt_image_2_transformation.py Updates registry-price expectations for generation and edit models.

Reviews (3): Last reviewed commit: "fix(fal_ai): strip provider prefix befor..." | Re-trigger Greptile

Comment thread model_prices_and_context_window.json
@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.50000% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/llms/fal_ai/cost_calculator.py 92.50% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ mateo-berri
❌ github-actions[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@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 d5e6a0c. Configure here.

@codspeed-hq

codspeed-hq Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_fal_gpt_image_2_keyed_pricing (d5e6a0c) with litellm_internal_staging (e07a712)1

Open in CodSpeed

Footnotes

  1. No successful run was found on litellm_internal_staging (dad4c1a) during the generation of this report, so e07a712 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@mateo-berri
mateo-berri enabled auto-merge August 21, 2026 02:22

@tin-berri tin-berri 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.

Solid fix, and well-proven — the PR body includes live before/after curl proof against the real fal API for 2 of the 96 new keyed entries (hd 1024x1024: $0.211, low 1024x1024: $0.006), both matching exactly. Cost-calculator selection logic correctly mirrors the existing FalAIGPTImage2Config.map_openai_params key shapes (image_size dict → WIDTH-x-HEIGHT, quality normalization including the autohigh caveat), and every fallback path (unlisted size/quality, missing params, size="auto" on edit) degrades to the flat entry rather than $0 or a crash — confirmed by dedicated tests. No regression risk to other fal models or other providers' cost paths.

One thing worth a quick sanity check before/after merge: fal_ai/high/1920-x-1080/openai/gpt-image-2/edit is priced identically to its generation counterpart ($0.158), where every other size/quality combination shows a small nonzero edit increment (+$0.006 to +$0.013) for the extra input-image cost. Could be a genuine copy-paste slip in transcribing fal's price table — worth a 30-second look, but even if wrong it undercharges by a few cents on that one row, same direction as the bug this PR fixes and far smaller magnitude. Not a blocker. CI green (70/70, including validate-model-prices-json). Approved.

@mateo-berri
mateo-berri merged commit 354f497 into litellm_internal_staging Aug 21, 2026
74 checks passed
@mateo-berri
mateo-berri deleted the litellm_fal_gpt_image_2_keyed_pricing branch August 21, 2026 02:51
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.

3 participants