Skip to main content

Carbon intensity data registry for LLM and embedding models with live Electricity Maps updates

Project description

Rakam-frugal-ai

Carbon intensity and per-request CO₂ estimates for LLM and embedding models. Ships a precomputed, weighted-by-region probability table and parameter-size estimates for popular models (GPT-4o, GPT-4o-mini, Claude, embedding models, …). Carbon intensity values are refreshed weekly from Electricity Maps; no API key is needed at call time.

Install

pip install rakam-frugal-ai
# Optional, for accurate token counting on text fallbacks:
pip install "rakam-frugal-ai[tiktoken]"

Carbon intensity registry (the original API)

import rakam_frugal_ai as ci

m = ci.model("gpt-4o")
m.CI              # CarbonIntensityValue(260.735 gCO2eq/kWh)
float(m.CI)       # 260.735 — raw gCO2eq/kWh, weighted across the model's regions
m.size            # SizeValue(200.00B params)
float(m.size)     # 200.0 — raw billion params
m.provider        # 'openai'
m.type            # <ModelType.LLM: 'llm'>

CI values are weighted across each model's known datacenter regions (the weights are rakam's estimate of how traffic distributes). The number you see is Σ P(zone) × CI(zone) over those regions.

CO₂ per request

Three entry points, all zero-network at call time:

ci.get_co2_for_model(model_name, region=None)             # → Co2Result, grams/token
ci.get_co2_for_query(query=None, *, model_name,
                     input_tokens=None, output_tokens=None,
                     region=None)                          # → Co2Result, grams for the call
ci.get_co2_for_pipeline(steps, region=None)               # → Co2Result, summed grams

Co2Result is a float subclass — float(r) gives the central (mean) value, r.detail carries provenance. Arithmetic on a Co2Result returns a plain float; .detail is meaningful only on the original lib-returned value.

Token rules — applied automatically by m.type

You don't have to reason about which tokens count:

Model type What counts toward energy Notes
LLM (generation) input_tokens + output_tokens For RAG, input_tokens MUST be the full assembled prompt (system + retrieved chunks + history + query), not just the user query — the library can't infer this; pass response.usage.prompt_tokens.
EMBEDDING input_tokens only The output is a vector, not generated tokens. If you pass a non-zero output_tokens for an embedding model it is ignored with a warning note.

Region routing

region= What it does ci_model_confidence.source ci_model_confidence.level
None (default) Use the model's region-weighted CI from the bundled registry "rakam_default_weighted" graded — "high" / "medium" / "low" from the model's location_confidence
Any EM zone code, e.g. "FR" Look up that zone's CI directly in the bundled zone_ci.json (zero network) "electricitymaps:FR" "measured" (it's a real reading, not a judgment)
Unknown zone KeyError listing available zones

The asymmetry is deliberate: a direct zone reading is measured; a weighted blend is a judgment graded on its quality.

Example — single call

r = ci.get_co2_for_query(
    query=None,                 # using real counts from response.usage
    model_name="gpt-4o",
    input_tokens=3000,          # full assembled RAG prompt
    output_tokens=800,
    region="FR",
)

float(r)
# 0.011 g CO2eq for the call

r.detail
# {
#   "co2_grams_mean": 0.0111...,
#   "co2_grams_min":  0.0111...,
#   "co2_grams_max":  0.0111...,   # degenerate range — EcoLogits methodology
#                                  # produces a deterministic point; range is
#                                  # the source's intrinsic range as-is.
#   "model_name": "gpt-4o",
#   "model_type": "llm",
#   "ci_gco2_per_kwh": 19.0,
#   "ci_model_confidence": {"level": "measured", "source": "electricitymaps:FR"},
#   "energy_per_token_kwh": 1.54e-07,
#   "energy_source": "ecologits_estimate",
#   "energy_source_confidence": "estimated",
#   "modelsize_confidence": {
#     "level":               "medium",
#     "source":              "Microsoft/Univ. Washington MEDEC paper (Dec 2024) ...",
#     "used_in_calculation": True,    # EcoLogits fallback → size fed the number
#   },
#   "input_tokens": 3000,
#   "output_tokens": 800,
#   "energy_tokens": 3800,
#   "notes": (
#     "energy estimated via EcoLogits param→energy methodology (size 200B params, "
#     "size_confidence=medium)",
#     "energy estimated from an unverified parameter count; treat this value as a "
#     "soft estimate — the EcoLogits methodology does not publish an uncertainty "
#     "band, so the range here is degenerate (min == mean == max)",
#   ),
# }

Example — full RAG pipeline

# Real counts from your provider SDKs:
embedding_response = client.embeddings.create(input=user_query, model="text-embedding-3-small")
chat_response      = client.chat.completions.create(
    model="gpt-4o",
    messages=full_assembled_prompt,
)

result = ci.get_co2_for_pipeline(
    [
        {
            "model_name":    "text-embedding-3-small",
            "input_tokens":  embedding_response.usage.prompt_tokens,
            "output_tokens": 0,                                    # ignored anyway for embeddings
        },
        {
            "model_name":    "gpt-4o",
            "input_tokens":  chat_response.usage.prompt_tokens,    # FULL assembled prompt
            "output_tokens": chat_response.usage.completion_tokens,
        },
    ],
    region="FR",
)

float(result)                # 0.0115 g CO2eq for the whole request
result.detail["range_method"]    # "naive_sum"
result.detail["steps"]            # list of per-step .detail dicts

Energy resolution — measured vs estimated vs unknown

Each result's energy_source_confidence is one of:

  • "measured" — energy from AI Energy Score (benchmark data, when the model is in the dataset). energy_source == "ai_energy_score". modelsize_confidence.used_in_calculation == False (size didn't feed the number). The shipped data/ai_energy_score.json is currently an empty stub; will be populated by the weekly build hook.
  • "estimated" — energy via the EcoLogits methodology (param→energy function), reimplemented in energy.py (no ecologits runtime dependency). energy_source == "ecologits_estimate". modelsize_confidence.used_in_calculation == True. The two real RAG targets (gpt-4o and text-embedding-3-small) currently fall here.
  • "unknown" — no AI Energy Score entry AND size_billion_params is None. get_co2_for_* raises ValueError rather than producing a silent guess.

Pipeline uncertainty band combination

get_co2_for_pipeline combines per-step uncertainty bands by naive sum: total_min = Σ step_min, total_max = Σ step_max. This implicitly assumes the steps' errors are perfectly correlated — pessimistic in the sense that it overestimates combined uncertainty. We pick it on purpose for v1 as a conservative upper bound; better to over-report uncertainty than to under-report it. The statistically correct method for independent errors is sum-in-quadrature on the half-widths: half_total = sqrt(Σ ((max_i − min_i) / 2)²). The combination is isolated in _combine_step_ranges in rakam_frugal_ai/co2.py, so switching is a one-function change. Every pipeline result carries result.detail["range_method"] == "naive_sum" so it is self-describing.

Freshness

There is no date= parameter. Electricity Maps without a key provides no usable historical data, so we'd be accepting an arg we couldn't honor. Instead, freshness is the build's responsibility — the wheel is republished weekly with refreshed data. Inspect via:

ci.__version__       # e.g. "2026.6.15.2" — CalVer
ci.__data_date__     # date the bundled data was fetched

Single source of truth

data/zone_ci.json is the authoritative per-zone CI table. The model-level carbon_intensity field in data/models.json is derived from that table at build time (and re-derived at load time as a consistency check). Per-region CI is no longer persisted on disk — it's back-filled in memory when the registry loads. Net effect: no zone's CI is independently fetched twice.

Scope

The library does not:

  • Provide live network lookups at call time (everything reads frozen data bundled in the wheel).
  • Account for datacenter PUE, network transit, training amortization, or embodied hardware emissions.
  • Replace dedicated tools like CodeCarbon for measuring your own inference runs — it gives you a model-aware figure when you don't have power telemetry.

Python support

Python 3.10, 3.11, 3.12.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rakam_frugal_ai-2026.7.13.tar.gz (23.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rakam_frugal_ai-2026.7.13-py3-none-any.whl (28.8 kB view details)

Uploaded Python 3

File details

Details for the file rakam_frugal_ai-2026.7.13.tar.gz.

File metadata

  • Download URL: rakam_frugal_ai-2026.7.13.tar.gz
  • Upload date:
  • Size: 23.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rakam_frugal_ai-2026.7.13.tar.gz
Algorithm Hash digest
SHA256 a79a90a66439524d38faf3afb55ac17e3a96b4b5d9136c788dc20001375119bf
MD5 7a0e4ce5ffc21be618868e758cfbcfb9
BLAKE2b-256 af6a68f97d9ca6ca6fe6a2cf4f092fbcacabce0cb6498d5bc2e75f8907bf2056

See more details on using hashes here.

Provenance

The following attestation bundles were made for rakam_frugal_ai-2026.7.13.tar.gz:

Publisher: weekly-data-refresh.yml on Rakam-AI/rakam-frugal-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rakam_frugal_ai-2026.7.13-py3-none-any.whl.

File metadata

File hashes

Hashes for rakam_frugal_ai-2026.7.13-py3-none-any.whl
Algorithm Hash digest
SHA256 15ff8257fcbf13d806f4dca51300563348f7c7dc75bf0c9bc65ee3b292575ad4
MD5 0f2afc3fa28ac5f8f65afd41ed3bd012
BLAKE2b-256 ab05a819d9fe0d87a428ea3e8e9b62e76154f731d068c8934a0ad2c9978f36ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for rakam_frugal_ai-2026.7.13-py3-none-any.whl:

Publisher: weekly-data-refresh.yml on Rakam-AI/rakam-frugal-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page