DEV Community

Nasir Rehman
Nasir Rehman

Posted on

Ghost Load: A Local AI That Finds the Ghosts in Your Electricity Use

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

What I Built

Ghost Load finds the "ghosts" in your electricity use and tells their stories.

A ghost is something that uses power when it should not: a device left on all night, a mystery spike at 3 AM, or a one-hour surge nobody can explain. You give Ghost Load a CSV of hourly readings. Plain code finds the ghosts, and a local open-weight model writes a short ghost story about each one.

I have worked in IT infrastructure for over 20 years, and a big part of that job is finding strange things in logs. Meter data is just another log. The ghosts in it cost real money, and almost nobody reads it.

Demo

I did not record a video, so here is the real output from my last run. The project runs with three commands (see the README in the repo).

I tested it on a generated month of hourly readings with three ghosts planted on purpose. Ghost Load found all three:

  • The thing that never sleeps: an extra 147 watts, day and night, from 2026-10-09. That is 63.7 kWh and about 19.12 AED in 18 days.
  • The 03:00 visitor: a spike at 3 AM on 28 of 30 nights, adding 24.1 kWh.
  • The poltergeist surge: 4.72 kWh in one hour on 2026-10-16 at 11:00, when about 0.71 kWh is normal.

Two of the stories the model wrote, exactly as printed:

=== 1. The thing that never sleeps ===
The meter ticked relentlessly, registering 147 watts each day and night since 2026-10-09. Over 18 days, it consumed an extra 63.7 kWh, costing 19.12 AED. The current continued, projected to add another 31.86 AED every 30 days. It never stopped, this quiet drain.
Real advice: unplug devices one by one at night and watch your meter. Look for something added around the first day above, such as a new device, charger or router.

=== 3. The poltergeist surge ===
The meter spun wildly at 11:00 on 2026-10-16. It registered 4.72 kWh, a surge far beyond the usual 0.71 kWh. The extra 4.0 kWh flowed, accompanied by a silent, unsettling 1.2 AED.
Real advice: think about what was running at that time. A one-time surge often means a heavy appliance, a fault, or a visitor using many devices.
Enter fullscreen mode Exit fullscreen mode

The cost uses an assumed rate of 0.30 AED per kWh, which you can change. The sample data is generated, not from a real meter.

Code

Ghost Load 👻⚡

Finds the "ghosts" in your electricity use (always-on devices, mystery night-time spikes, one-off surges) and lets a local open-weight model (Gemma via Ollama) tell each one as a short ghost story. Your data never leaves your computer.

Run it

# 1. one-time: install Ollama (ollama.com), then
ollama pull gemma3:1b          # fast; or gemma3:4b for better stories

# 2. make sample data (or use your own CSV with columns: timestamp,kwh)
python3 generate_data.py

# 3. detect ghosts (plain code, no AI)
python3 detect.py data/sample_usage.csv --rate 0.30

# 4. tell the stories (local AI)
python3 story.py findings.json --model gemma3:1b
Enter fullscreen mode Exit fullscreen mode

Use your own tariff for --rate. The default 0.30 is only an assumption.




It uses only the Python standard library, plus Ollama.

How I Built It

Ghost Load has three stages, and the order matters.

  1. Detect (plain code, no AI). detect.py looks for three patterns: a lasting rise in the lowest daily usage, an hour of the day that is always far above its neighbours, and a single hour far above normal for that time of day. Every number comes from checkable code.
  2. Tell (open-weight AI). story.py sends each finding to Gemma through Ollama, running locally. The model only writes the story. It does not find or calculate anything. The "Real advice" line is added by code.
  3. Check (plain code again). Every story must pass checks. It may only use numbers from the facts, must include the key figures as digits, and must not invent places or objects or use phrases that change the meaning. A failed story goes back to the model with the reason it failed. After four failures, the code writes a short fallback story and labels it as code-written.

I built the third stage because of what happened on my first run.

I ran the 4B model five times while tightening the rules. Rejected attempts per run went 3, 1, 5, 0 and 1. In one run, a story failed all four attempts and fell back to a code-written story, and the report labelled it. The rules got stricter over time, so the runs are not directly comparable.

The checks caught every invented number and object they were built to catch. They also missed one false claim: a story said the spike happened "28 nights in a row" when it was 28 of 30 nights. The checker cannot understand meaning, so I added that phrase to the list. That is why every report prints the verified facts next to each story, so a person can check the AI.

Why Does Open Innovation Matter?

It runs on my own machine. I use an Intel MacBook Pro with 16 GB of RAM and no dedicated GPU. Gemma runs on the CPU through Ollama. Home energy data says when you are home, asleep or away, so I do not want to send it to a cloud service. With a local model, nothing leaves the laptop, and once the model is downloaded it works with the internet off.

I could fix the model's behaviour. My first run used gemma3:1b. It invented details. It wrote that a ghost appeared "twice a week" and was "always in the same room", and it told me to check outlets "near the bed". None of that was in the data. It also misread a number. Because the model was mine, I could control the prompt, lower the temperature, and add retries with feedback. A closed API might have given me better stories, but I could not have seen or fixed its mistakes the same way.

Nothing can disappear. The model file, the code and the data are all on my disk. No service can change its terms or shut down on me.

The lesson was this: the model is good at writing, but it cannot be trusted with facts. So the code finds the facts, the model writes around them, and the code checks the result.

The Spirit of It

The moment that landed for me was the first run. The model wrote about a spooky kitchen. There is no kitchen in the data, and the AI had made up a haunting. A ghost story about your house should not contain invented rooms. That is why I added the checks, and why the stories now stay close to the meter, the numbers and the time.

Prize Categories

Best Use of Gemma: the stories are written by Gemma (gemma3:1b and gemma3:4b), running locally through Ollama.

Top comments (0)