TypeScript port of the EcoLogits methodology, which estimates the energy consumption and environmental impacts of using generative AI models through APIs.
The core estimator has been ported to numerical parity with the Python package ecologits
0.11.2. Parity is not just a claim here, it is enforced: the test suite replays 596
estimator cases and 361 high-level cases that were generated by running the real Python
implementation, plus the full comparison matrix of the primitives. See
Numerical parity.
The provider adapters (@genai-impact/ecologits-openai, @genai-impact/ecologits-mistral)
were written against a much older core — roughly Python 0.5.0, from 2024 — and have been
removed from this workspace. They will be rebuilt on top of the current core in a later
phase. The published adapters are unaffected: they depend on
@genai-impact/ecologits.js@^2.0.5, a different package name that this release does not
touch, so they keep resolving to the old core.
What is in scope today, and what is not, is tracked in docs/parity.md.
| Package | Description |
|---|---|
@ecologits/ecologits.js |
Estimator, data layer and the model-name-to-impacts lookup. No provider SDK dependencies. |
The port is validated against the Python implementation rather than against hand-written
numbers, because hand-written numbers would encode the same misunderstanding twice. The
contract itself — independent of either language — lives in spec/, which also
holds the conformance vectors every implementation is measured against.
npm run test # replays every contract and implementation vector
npm run check-spec # validates the data and manifest against spec/schema
npm run check-data # verifies the compiled data matches spec/dataContract vectors live in spec/vectors; the arithmetic and comparison
vectors that pin the port's internals live in packages/ecologits.js/test/vectors. Both are
produced by python spec/scripts/generate-vectors.py, which imports the Python package from a
sibling checkout ($ECOLOGITS_PY_DIR, default ../ecologits) and records the version and
commit it used in spec/manifest.json.
Three upstream defects surfaced while building this, and all are pinned by tests rather than papered over:
- Upstream divides by
deployment.tpswithout a guard. Through 0.11.1 one model shipped withtps: 0and made Python raiseZeroDivisionError; JavaScript would instead have silently produced an infinite latency and returned numbers Python never generates. 0.11.2 corrected that data, and the port still refusestps = 0, pinned by an explicit vector case. - A zero parameter count makes
gpu_required_countevaluatelog2(0), which raisesValueErrorin Python but would silently return0in JavaScript. The port refuses it, pinned by thezero-parametersvector case. Model.from_jsonguards on the singular"source"key but reads"sources", so upstream always drops that field. The port reads it as intended; the field is provenance metadata and does not affect any estimate.
Requires Node.js 20 or newer.
npm install
npm run build # tsup: ESM + CJS + type declarations
npm run typecheck # tsc --noEmit, strict
npm run lint # eslint
npm run test # vitest, includes the parity suiteRegenerating the compiled data requires a checkout of the Python package:
npm run sync-data # refresh spec/data from the Python JSON and recompile the data modules
npm run check-data # verify the committed modules match spec/data (no Python needed)MPL-2.0, as upstream.