DEV Community

Aakash Singh
Aakash Singh

Posted on

DataAfterlife: giving a forgotten CSV a voice with local Gemma

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

I built DataAfterlife to help someone find the shape of a story in an old CSV. A file of dates and amounts can hold a period of decline, a recovery, or a quiet turning point, but a table alone makes those patterns hard to see. My interpretation of Ghost in the Machine is to let dormant records speak again while keeping the original evidence close enough to check.

For the demo I created a fictional community cinema ledger covering 1999 and 2000. Its 72 records span screenings, memberships, and concessions. The app calculates a low monthly total of 541 units in April 2000, a high of 7,199 in October 2000, and a total of 62,477 across the archive. Those facts become charts and the anchors for a short, evidence-linked story.

You can choose or drop your own CSV, map its amount, date, and category columns, switch chart types, ask questions in plain language, and save a PDF report. Parsing and calculations run in a browser Web Worker so the interface remains responsive. The UI shows parsing warnings, excluded numeric values, and progress while an answer is being prepared.

Demo

Video walkthrough (54 seconds): [https://youtu.be/9Y6sBCYAt1I]

The narrated walkthrough uses captures from a local run of the app. It shows the cinema totals and trend, the fact packet preview, Gemma's evidence-linked story, a natural-language question with its loading state and computed answer, and the chart selector. The app runs locally with Ollama; the video is the demo because the current server routes cannot reach a visitor's local Ollama from a static hosted site.

DataAfterlife showing the cinema archive and its evidence-linked story

One useful question to show is “Which year has the highest amount?” The answer is 2000: 32,033 units. DataAfterlife groups the dates by year and sums the amounts. It does not confuse the largest single entry with the largest yearly total.

Code

The source and setup instructions are in the DataAfterlife GitHub repository. The application lives in its data-afterlife directory.

To run it locally, you need Node.js 20+, npm, and Ollama:

git clone https://github.com/frannkenstein/data-afterlife.git
cd data-afterlife/data-afterlife
npm install
ollama pull gemma3:4b
cp .env.example .env.local
npm run dev
Enter fullscreen mode Exit fullscreen mode

Make sure Ollama is running, then open http://localhost:3000 and click Explore the cinema archive. The charts and summary work without Ollama; the story and natural-language questions need the model.

How I Built It

The interface uses Next.js, React, TypeScript, Tailwind CSS, and canvas charts with Chart.js. Papa Parse reads the CSV in a Web Worker. The browser calculates totals, averages, extrema, monthly and category summaries, and row-level answers. Zod constrains the plans that cross the model boundary.

I use Gemma 3 4B through local Ollama in two places:

  1. Ask DataAfterlife: Gemma sees the question and column names, then proposes a structured calculation plan. The app validates the plan against the question and known columns and executes it against the rows in the browser. Plans can filter, rank, or group by category, year, quarter, or month. A clear time-grouping mismatch is corrected, and another mismatch can be sent back to the model for one revision. Unsupported questions can receive an explicit unsupported result.
  2. What this data remembers: Gemma sees a small packet of computed facts and selects an additional story beat. The app anchors the low point, largest consecutive monthly rise, and high point when available. It writes the final figures from verified facts and links each card to the relevant chart or summary.

The arithmetic boundary became important during development. An early answer to “half of the total” resembled an average. First and second place once pointed to the same month. A year question once returned the maximum row amount rather than the maximum yearly total. These failures led me to make the model propose a plan while deterministic code checks and performs the calculation. The app still cannot answer every conceivable question, and it does not claim that an event note caused a numerical change.

Why Does Open Innovation Matter?

Running an open-weight model locally makes this kind of archive exploration possible without sending every historical row to a hosted model. The CSV stays in browser memory; the local AI routes receive only column metadata and a question, or a small packet of aggregate facts. A question or category label can itself be sensitive, so the story flow shows the fact packet before sending it to local Ollama.

The model and prompt are inspectable and replaceable. That matters for records whose meaning is uncertain: a reader can inspect how a question became a calculation and follow a story card back to its evidence. Local inference also lets someone run the complete demo on a laptop without a paid API. The trade-off is that the person running the app must install and start Ollama, and a hosted version would need a separate model and privacy design.

The Spirit of It

The fictional ledger includes an October 2000 “Archive revival festival” entry. The chart shows a sharp recovery around that time, while the earlier April low is stark. DataAfterlife puts those moments in view and invites a person to investigate the surrounding records. It does not present the event note as proof of what caused the rise. For me, that restraint is part of giving the archive a second life: keeping the mystery visible without inventing an explanation.

Prize Categories

  • Best Use of Gemma: Gemma 3 runs locally through Ollama to interpret natural-language questions and select an evidence-backed story beat. The browser validates and computes the displayed results.

Top comments (0)