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.6.29.tar.gz (21.5 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.6.29-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: rakam_frugal_ai-2026.6.29.tar.gz
  • Upload date:
  • Size: 21.5 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.6.29.tar.gz
Algorithm Hash digest
SHA256 6987ee33882dd0531bade16b9dbc324f8758a65f404958ef9818ffd997203c2a
MD5 c9b1429af78f22f18270d6b68cf794f7
BLAKE2b-256 f22f15d0f749ebeed20dfff7a6d026e7c7c17b7420635105185bb1649437dd97

See more details on using hashes here.

Provenance

The following attestation bundles were made for rakam_frugal_ai-2026.6.29.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.6.29-py3-none-any.whl.

File metadata

File hashes

Hashes for rakam_frugal_ai-2026.6.29-py3-none-any.whl
Algorithm Hash digest
SHA256 52e755b6e1faac49e4ba6322b12cef0dfddc35d1d6217dd1515a0509a8a9dfbb
MD5 5c6014b8f77ce924309676410931c246
BLAKE2b-256 82d6ce78f1d0df74b0c7a7e04bd0c84b57be94ffa7e53aac9943d5adb663b966

See more details on using hashes here.

Provenance

The following attestation bundles were made for rakam_frugal_ai-2026.6.29-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