Search by

davidjln / llm-carbon-bundle

DavidJLN

Symfony bundle of davidjln/llm-carbon-php : config tree, DependencyInjection wiring and console command for estimating the carbon footprint of an LLM request.

Package info

github.com/DavidJLN/llm-carbon-bundle

Type:symfony-bundle

pkg:composer/davidjln/llm-carbon-bundle

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-09-12 16:31 UTC

This package is auto-updated.

Last update: 2026-09-12 17:34:10 UTC


README

Symfony integration for davidjln/llm-carbon-php: a typed configuration tree, DependencyInjection wiring, and a console command for estimating the energy consumption and CO2eq emissions of a request to a language model (LLM), following the EcoLogits methodology carried by the library.

This bundle contains no calculation logic of its own: every formula and constant of the methodology lives in LlmCarbon\FootprintCalculatorFull and LlmCarbon\FootprintCalculatorSimplified, in the library. The bundle only builds configuration, the service graph, and a presentation-layer command.

Installation

This package depends on davidjln/llm-carbon-php (^1.0), resolved from Packagist by default — no additional repository needs to be declared: https://packagist.org/packages/davidjln/llm-carbon-php.

Prerequisite: the ^1.0 constraint requires a version >=1.0.0 <2.0.0 published on Packagist. Until a 1.0.0 tag (or higher) has been pushed to the library's GitHub repository (the only version published so far is v0.1.1), composer install for this bundle will not be able to resolve that dependency.

composer install

Configuration

# config/packages/llm_carbon.yaml
llm_carbon:
    default_zone: 'France'   # must be a zone known to EmissionFactor::all(); otherwise container
                              # compilation fails, naming the accepted zones.
    calculator: complete     # 'simplified' or 'complete' (default: 'complete')
    models:                  # additional models, on top of the library's own catalog
        -   name: 'My internal model'
            active_parameters_billions: 12.0
            # total_parameters_billions omitted => dense model (total = active, same provenance)
            provenance:
                type: measured_and_published   # or 'hypothesis'
                url: 'https://example.test/model-announcement'
                year_or_consultation_date: '2026-01-15'
                note: "What the source states exactly."

Application-provided catalog sources

An application class can contribute additional models without going through YAML configuration, by implementing LlmCarbon\Bundle\Catalog\CatalogSourceInterface and marking itself with the #[LlmCarbon\Bundle\Attribute\AsLlmCarbonCatalogSource] attribute:

use LlmCarbon\Bundle\Attribute\AsLlmCarbonCatalogSource;
use LlmCarbon\Bundle\Catalog\CatalogSourceInterface;
use LlmCarbon\LanguageModel;
use LlmCarbon\Provenance;
use LlmCarbon\ProvenanceType;

#[AsLlmCarbonCatalogSource]
final class InternalModelsCatalogSource implements CatalogSourceInterface
{
    public function models(): array
    {
        return [
            LanguageModel::dense('My internal model 2', 8.0, new Provenance(
                ProvenanceType::MeasuredAndPublished,
                'https://example.test/model-announcement-2',
                '2026-02-01',
                "What the source states exactly."
            )),
        ];
    }
}

Important constraint: this class must have a dependency-free constructor. It is not resolved by the container at runtime: CatalogSourceCompilerPass instantiates it directly, once, at container-compile time, and bakes the result into the LlmCarbon\Bundle\Catalog\ModelCatalog service definition. Nothing is re-read on every request.

Console command

php bin/console llm-carbon:estimate "Llama 3.1 70B" 500

Displays a table detailing the energy and emissions calculated for the given model and token count, using the configured zone and calculation mode (simplified or complete).

Testing

tests/ holds the bundle's own test suite, run against a minimal test kernel rather than a full Symfony application skeleton: tests/Fixtures/TestKernel.php registers exactly two bundles (FrameworkBundle, needed for console.command tag processing and the framework.test test container, and LlmCarbonBundle itself) and lets each test case inject its own llm_carbon configuration, debug/test mode, and extra fixture services — no config/ directory, no YAML.

composer install
vendor/bin/phpunit tests

Four scenarios are covered:

  • ContainerCompilationTest — the container compiles with the default configuration and every declared service actually instantiates cleanly (a wrong service class or a forgotten constructor argument only surfaces at instantiation, not at mere compilation).
  • ProductionPrivacyTest — the same private service (ModelCatalog) is reachable through Symfony's debug/test container, but throws ServiceNotFoundException in a realistic production container (debug: false, framework.test disabled) — guarding against a test that would pass in debug and silently break in production.
  • UnknownZoneTest — an unknown default_zone fails container compilation, naming every accepted zone in the exception message.
  • CatalogSourceCompilerPassTest — a model contributed by an application catalog source is present in the compiled catalog, guarding against CatalogSourceCompilerPass silently not being registered (which produces no error — the catalog is simply incomplete).