Estimate LLM inference impacts from Azure Foundry token meters - #267
Merged
Conversation
AzureFoundryTokenEcoLogits is the Azure counterpart of BedrockEcoLogits: it recognises the token meters billed under the Azure OpenAI / Foundry Models category, extracts the model label and the token direction from MeterName, maps the label to the EcoLogits coefficients via mapping.csv and estimates the energy and embodied emissions of the output-token rows. Quantity (ConsumedQuantity in FOCUS reports) already holds the consumed token count: the 1K/1M unit only describes the pricing block, as per the FOCUS conversion rules published by Microsoft, so it is not used to scale the quantity. Unknown models, input and cached tokens, PTU, hosting and fine-tuning meters are left untouched. Ships with the Azure OpenAI aliases covered by the bundled coefficients and is enabled in both Azure default configurations. Fixes #264
Minimal native and FOCUS exports go through the default configurations and the EnrichmentPipeline: the same inference must yield the same impacts in both formats, the module must run before the factor and impact modules, and input, unmapped, non-token and non-usage rows must stay untouched.
jnioche
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #264
The EcoLogits lookup is provider-neutral but only Bedrock had a billing adapter, so LLM usage on Azure stayed unestimated. This adds
AzureFoundryTokenEcoLogits, the Azure counterpart ofBedrockEcoLogits: it recognises the token meters billed under theAzure OpenAI/Foundry Modelscategory, extracts the model label and the token direction fromMeterName, maps the label to the EcoLogits coefficients viamapping.csvand estimates energy and embodied emissions for the output-token rows. The rows then flow through PWUE, carbon intensity, operational emissions and water like any other usage. First step towards theecologits.azuresplit sketched in #143.One thing worth calling out:
Quantity(andConsumedQuantityin FOCUS reports) already holds the consumed token count. The1K/1MinUnitOfMeasureonly describes the pricing block — Microsoft's FOCUS conversion rules defineConsumedQuantity = QuantityandContractedCost = UnitPrice × Quantity / x_PricingBlockSize— so, unlike the Bedrock adapter withpricing_unit, no unit normalisation is applied. The issue text ("normalise the 1K/1M units") predates that finding.Changes
ecologits/AzureFoundryTokenEcoLogits: filters on the meter category, parsesMeterName(input markersInp/inpt/input, output markersOutp/outpt/opt/out/output; deployment and pricing qualifiers such asBatch,cchd,pp,ShortCoare dropped from the label), scores output tokens only and leaves everything else untouched: unknown labels (warned once byEcoLogits), input and cached tokens, meters without a direction marker (reasoning, embeddings), non-token meters. Native and FOCUS bindings (MeterCategory/MeterName/Quantity↔x_SkuMeterCategory/x_SkuMeterName/ConsumedQuantity).ecologits/mapping.csv: ten Azure OpenAI labels (gpt 5,5,5 mini,5 nano,5.1,5.1 codex,5.4,gpt 4.1,o1,o1 1217), each checked against the bundledcoefficients.csv. Meter names taken from the Azure Retail Prices API.default-config-azure.jsonanddefault-config-azure-focus.json, beforePWUEas Bedrock is in the AWS one.AzureFoundryTokenEcoLogitsTest(parser cases use real meter names, e.g.GPT 5 outpt Glbl 1M Tokens,5.1 codex opt Gl 1M Tokens,5.6 terra ShortCo Cd Inp PP Gl 1M Tokens; native/FOCUS invariant: the same inference in both formats yields the same impacts) andAzureFoundryTokenEndToEndTest, which runs two minimal exports through the real default configurations and theEnrichmentPipeline.Verification
350 tests pass. Also ran the job in the Docker image with a fresh jar on the native fixture:
GPT 5 outpt Glbl 1M Tokensgpt 4.1 Outp regnl TokensNo file overlaps with #266, so the two can be merged in either order.
Left out deliberately
3.3 70b Outp FT DZ Tokens,4.3 Outp Glbl L Tokens, unit1K), so they only needmapping.csventries verified against real exports; DeepSeek, Grok and Qwen have no EcoLogits coefficients anyway. Separate issue once this lands.gpt-5.4 pro/nanoandgpt-5.5aliases: need the refreshed coefficients from Refresh the EcoLogits coefficients from the API #266; three lines once both are merged.gpt-5.6is not in the EcoLogits API yet.A real export would help
The parser is validated against the Retail Prices catalogue and synthetic rows, not against an actual EA/MCA or FOCUS export. If anyone has Azure OpenAI usage, a redacted tuple is enough to confirm the contract — export type plus
MeterCategory,MeterName,UnitOfMeasure,Quantity(no cost or identifiers).