DEV Community

shashank ms
shashank ms

Posted on

The Role of LLMs in Energy Systems and Climate Strategies

We are building a building energy audit agent that reads a facility profile and local climate targets, then returns prioritized retrofit recommendations with estimated carbon reductions. It helps sustainability engineers and building operators move from raw utility data to actionable decarbonization plans without building a custom ML pipeline.

What you'll need

Step 1: Configure the Oxlo.ai client

I start every project by verifying the client connection so I do not debug network issues later in the stack. The snippet below initializes the OpenAI SDK pointing at Oxlo.ai and sends a smoke test.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key="YOUR_OXLO_API_KEY"
)

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "user", "content": "Say OK"}
    ],
    max_tokens=10,
)
print(response.choices[0].message.content)

Step 2: Write the system prompt

The system prompt is the only training this agent gets. I keep it tight: define the persona, require structured output, and forbid hallucinated efficiency metrics.

SYSTEM_PROMPT = """You are an energy systems analyst. A user will paste a building profile and a climate target. Your job is to recommend up to three retrofits or operational changes.

Rules:
- Use only the emission factors and utility costs provided below.
- Output raw JSON. No markdown fences.
- Include keys: recommendations, total_estimated_co2_reduction_kg_yr, total_estimated_cost_usd, payback_years.
- Each recommendation must have: measure, estimated_co2_reduction_kg_yr, estimated_cost_usd, rationale.

Emission factors:
- Grid electricity: 0.4 kg CO2 / kWh
- Natural gas: 2.1 kg CO2 / therm

Utility costs (national averages):
- Electricity: $0.14 / kWh
- Natural gas: $1.20 / therm
"""

Step 3: Build the audit runner

I wrap the API call in a small Python function so the rest of the codebase does not know about LLM internals. The function assembles the user message from a building dictionary and returns the parsed JSON.

import json

def run_energy_audit(building_profile: dict, climate_target: str) -> dict:
    user_message = f"""
Building profile:
{json.dumps(building_profile, indent=2)}

Climate target:
{climate_target}

Return the audit as JSON.
"""
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
        temperature=0.2,
        max_tokens=1200,
    )
    raw = response.choices[0].message.content.strip()
    return json.loads(raw)

Step 4: Ground the math with baseline calculations

Raw LLM arithmetic drifts on large numbers. I add a lightweight preprocessor that calculates baseline emissions from the profile so the model can validate its own totals. This step is optional but I always include it in production agents to reduce reasoning errors.

def enrich_profile(building_profile: dict) -> dict:
    enriched = dict(building_profile)
    elec_kwh = enriched.get("annual_electricity_kwh", 0)
    gas_therms = enriched.get("annual_natural_gas_therms", 0)
    enriched["baseline_co2_kg_yr"] = round(
        elec_kwh * 0.4 + gas_therms * 2.1, 2
    )
    enriched["baseline_energy_cost_usd"] = round(
        elec_kwh * 0.14 + gas_therms * 1.20, 2
    )
    return enriched

def run_energy_audit(building_profile: dict, climate_target: str) -> dict:
    profile = enrich_profile(building_profile)
    user_message = f"""
Building profile:
{json.dumps(profile, indent=2)}

Climate target:
{climate_target}

Return the audit as JSON.
"""
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
        temperature=0.2,
        max_tokens=1200,
    )
    raw = response.choices[0].message.content.strip()
    if raw.startswith("

```"):
        raw = raw.split("\n", 1)[1].rsplit("```

", 1)[0].strip()
    return json.loads(raw)

Run it

Pass a real building profile and a climate target. The agent returns structured recommendations you can log to a database or render in a dashboard.

if __name__ == "__main__":
    building = {
        "name": "Westside Office",
        "type": "office",
        "sqft": 45000,
        "annual_electricity_kwh": 580000,
        "annual_natural_gas_therms": 8200,
        "hvac_type": "variable air volume",
        "lighting": "T8 fluorescent",
    }
    target = "Reduce scope 1 and 2 emissions 40 percent by 2030."

    result = run_energy_audit(building, target)
    print(json.dumps(result, indent=2))

Example output:

{
  "recommendations": [
    {
      "measure": "LED lighting retrofit",
      "estimated_co2_reduction_kg_yr": 46400,
      "estimated_cost_usd": 31500,
      "rationale": "Replacing T8 fluorescent with LED cuts lighting load by 40 percent, saving 116000 kWh annually."
    },
    {
      "measure": "Heat pump VAV replacement",
      "estimated_co2_reduction_kg_yr": 52000,
      "estimated_cost_usd": 120000,
      "rationale": "Electrifying heating with high efficiency heat pumps displaces 24762 therms of gas."
    },
    {
      "measure": "Smart HVAC scheduling",
      "estimated_co2_reduction_kg_yr": 18500,
      "estimated_cost_usd": 8000,
      "rationale": "Night and weekend setbacks reduce runtime by 8 percent."
    }
  ],
  "total_estimated_co2_reduction_kg_yr": 116900,
  "total_estimated_cost_usd": 159500,
  "payback_years": 4.2
}

Wrap up

This agent turns unstructured building data into a structured decarbonization roadmap in seconds. Two concrete next steps: wire it to weekly AMI smart meter feeds to flag anomalies automatically, or swap to deepseek-v3.2 or qwen-3-32b on Oxlo.ai when you start passing entire portfolio CSVs, because Oxlo.ai request-based pricing does not scale with input length. You can explore plans at https://oxlo.ai/pricing.

Top comments (0)