DEV Community

Adnan Nagariya
Adnan Nagariya

Posted on

Hacktober Fest 2026 Project

Gemma 4 Challenge: Build With Gemma 4 Submission

TerraGuard: Teaching a Local Gemma 4 to Read a Hillside
Published: true
Tags: hf26challenge, open source, ai, devrelay

A tilt sensor trips. Soil moisture is climbing. The ground-distance reading has shifted. Is that one story or three unrelated numbers, and who has time to work it out at 2 a.m.?

That gap is what TerraGuard goes after. It's a local-first environmental monitoring and investigation prototype. A physical ESP32 sensor node feeds a FastAPI backend, and the backend hands an evidence packet to Gemma 4 12B running locally through Ollama. The idea behind the whole build fits in one line: Gemma interprets, and code owns the facts.

TerraGuard is a decision-support prototype. It is not a certified landslide predictor and not an official warning service. The interesting part is the engineering around the model.

🎬 SEE IT IN ACTION

GitHub: [INSERT PUBLIC REPOSITORY URL]
Demo video: [INSERT DEMO VIDEO URL]
Live demo: Local execution only (hardware plus a local model) [confirm]
Build transcript: See the DevRelay section below

What to look for in the demo: readings coming in from the physical node, a Gemma 4 assessment returned as structured JSON, the severity-aware alert flow, and a date-based daily report with its PDF.

🛠️ WHAT WE BUILT

Hillside monitoring is more than displaying numbers. Rainfall, soil moisture, tilt and ground-distance change each mean something only next to the others, next to what happened earlier, and next to how trustworthy the data is. When readings, alerts, forecasts and reports live in separate places, reconstructing an incident is manual work.

TerraGuard puts that workflow in one local system:

Observe: an ESP32 reads soil moisture, rain, tilt and ultrasonic ground distance. Distance change is judged against a recorded baseline.
Interpret: Gemma 4 reads the current readings plus a history summary and returns a structured assessment: risk level, summary and recommended action.
Alert: severity-aware states run SAFE → WATCH → WARNING → CRITICAL. CRITICAL brings a full-screen overlay and a repeating local siren.
Investigate: operators ask questions about retrieved events, and the answers are grounded in stored records.
Report: each day gets an evidence-based report with a timeline, statistics, a Gemma-written narrative and a ReportLab PDF.
Prepare: where a real forecast is available, the system produces qualified next-day monitoring priorities. Forecasts are always kept separate from measurements.

🏗️ UNDER THE HOOD: ENGINEERING WITH GEMMA 4

ESP32 + sensors (+ camera / mic) → FastAPI + local records
→ evidence packet (current + history + data-quality flags)
→ Ollama → Gemma 4 12B → structured output
→ validation + deterministic safeguards
→ alerts + siren │ investigation Q&A │ daily report + PDF
→ React dashboard

Why Gemma 4 12B is central, not decorative

We run gemma4:12b, the 12B Unified model. Per Google's official model card (https://ai.google.dev/gemma/docs/core/model_card_4), it is an open-weight model under Apache 2.0 that accepts text, image and audio input and documents a context window of up to 256K tokens. We chose it because it can run on workstation-class hardware while leaving room for multimodal inputs.

What it does here. Gemma is not a chat box bolted onto a dashboard. The backend gives it task-specific evidence (current readings, relevant history, derived values and data-quality flags) and the model turns that into something an operator can act on: a structured assessment, an explanation, an answer about a recorded event, a report narrative or a preparedness note. That's valuable because the hard part of hillside monitoring is interpreting several imperfect signals together, in context, and saying so clearly. A model that can read mixed evidence and communicate its interpretation fits that job. It does not independently determine ground truth or perform validated landslide prediction.

The path a request takes. React dashboard → FastAPI backend → evidence preparation → Ollama's local API → Gemma 4 12B → output validation and application safeguards → the relevant workflow (assessment, alert, report or Q&A).

That path has practical consequences:

Once Ollama and the model are installed, core inference needs no hosted LLM API call per request.
The backend controls which evidence the model sees. Gemma has no access to the sensors, the database or the browser.
Prompt construction, validation and fallback behavior stay under application control.
Calculations and configured safeguards never depend on trusting fluent model-written prose, so the model can be useful without being treated as an authority.

This is not a fully offline system: fresh weather forecasts need internet, and local inference makes no promise of privacy, accuracy or zero operating cost.

What we do and don't claim:

Google's figures are model specifications, not TerraGuard benchmarks. They say nothing about how accurate the application is, and they don't make it suitable for safety-critical use.
Multimodality is conditional. The prototype includes a camera and a microphone, and the model supports image and audio input. Those inputs are used only on paths where they are actually captured and routed to the model. We don't claim a validated visual or acoustic landslide detector.
We haven't benchmarked Gemma 4 sizes against each other on our hardware.

The model never talks to the browser

React calls FastAPI only. The backend retrieves records, normalizes units and timestamps, calculates numeric deltas, builds a task-specific prompt and calls Ollama's local API. It then validates the response before anything reaches the UI.

That boundary keeps model details, prompts and fallback rules out of the frontend, and it lets conventional code stay accountable for the facts.

Deterministic code: Gemma 4
Parses readings, keeps units and timestamps: Explains what the values mean together
Computes ground-distance change and report statistics: Describes how conditions changed across the day
Flags nulls, stale values and gaps: Explains why those gaps matter
Applies configured thresholds and fallbacks: Supplies the narrative; it never overrides the safety layer
Renders charts and the PDF: Drafts summaries, answers record questions, writes preparedness notes

One Evidence Packet, One Assessment

Synthetic walkthrough. The following was created to explain TerraGuard's architecture. These readings are illustrative, not captured from a real sensor run. The JSON below is a representative example of the intended output shape, not a verified response recorded from Gemma 4. It does not represent a validated hazard assessment.

Step 1: Observe. The ESP32 reports readings, and the backend keeps each one next to a reference and a data-quality note:

Measurement | Earlier reading | Current reading | Data quality
Soil moisture | 42% | 56% | Fresh
Tilt sensor reading | 1.4 | 1.9 | Fresh; units depend on sensor calibration
Ultrasonic ground distance | 180 cm reference | 176 cm | Fresh; 4 cm difference from the reference
Rainfall | Unavailable | null | Stale or unavailable; not equivalent to zero rainfall

Four numbers mean little alone. Next to their references and quality flags, they start to tell a story, and one of them is a gap.

Step 2: Build the evidence packet. FastAPI organizes the current observations, relevant history, timestamps and data-quality flags, and calculates the deltas in code: soil moisture up 14 percentage points, ground distance 4 cm below its reference. The rainfall field stays null. The model never reads the ESP32 and never queries the database freely. It sees only the packet.

Step 3: Interpret with Gemma 4. The model is asked for the structured assessment. A representative response, trimmed to three fields for readability:

{
"risk_level": "WATCH",
"summary": "Illustrative assessment: soil moisture has increased and the supplied tilt and ground-distance readings differ from their reference values. Rainfall data is unavailable, so the evidence is incomplete.",
"recommended_action": "Check sensor and data quality, review the recorded observations, and follow established site-monitoring procedures. This model-generated text is not an official warning."
}

Notice what the model does here: it connects the signals and says the evidence is incomplete, instead of treating missing rainfall as reassuring.

Step 4: Validate in conventional code. The backend checks the required structure and allowed risk labels, rejects malformed responses and applies its fallbacks and configured rules. This checks the format, not the truth. A response can be perfectly valid JSON and still be a poor assessment, which is why the model's output is never the last word.

Step 5: Deliver the result. In the real application, a validated result feeds the assessment, report and alert workflows, subject to the deterministic safeguards. This synthetic example makes no claim that it triggered an alarm or passed a hardware test, and its numbers imply no real hazard level.

The division of labor is the point: the model helps explain the supplied evidence, and conventional software stays responsible for the calculations, validation, configured rules and safeguards.

Three decisions that shaped the system

  1. Model output is untrusted. The backend rejects malformed payloads and falls back. Valid JSON is not the same as a correct assessment, so schema checks only verify shape and allowed values.
  2. Missing data stays missing. Unknown values stay null or are flagged stale, so a missing rain reading never silently becomes "no rain".
  3. Alert lifecycle is separate from the model. Alerts are deduplicated so polling doesn't restart the siren. Alert state, acknowledgement and sound state are tracked separately, and CRITICAL takes precedence.

What's verified

The team reports a working physical prototype where the monitoring, Gemma assessment, alert, report and preparedness workflows run in the current project configuration. Formal benchmarks haven't been run, so there are no latency figures, accuracy scores or false-positive rates, and none are claimed.

📜 DEVRELAY PROOF OF WORK: SHOW THE BUILD, NOT JUST THE RESULT

The finished repository shows what we built, and the DevRelay session shows how: the prompts, the iterations and the debugging along the way.

📜 DEVRELAY PROOF OF WORK: SHOW THE BUILD, NOT JUST THE RESULT

The finished repository shows what we built, and the DevRelay session shows how: the prompts, the iterations, and the development process behind TerraGuard.

DevRelay session: https://dev.to/agent_sessions/building-terraguard-offline-geotechnical-slope-monitoring-with-local-gemma-412b-devrelay-trcerj

(Fallback: View the TerraGuard development session (https://dev.to/agent_sessions/building-terraguard-offline-geotechnical-slope-monitoring-with-local-gemma-412b-devrelay-trcerj))

🧠 THE BUILDER'S WAR STORY: PROMPTING, DEBUGGING, ITERATION

The hardest problem wasn't getting a model to talk. It was stopping a fluent model from sounding more certain than the evidence allowed.

Our answer was architectural. Each task (live assessment, history Q&A, daily report, preparedness) gets its own backend-controlled prompt and output schema. Every prompt carries a structured evidence packet instead of a loose question. The instructions tell the model not to invent readings or forecasts, not to treat correlation as proof, and to say so when evidence is insufficient.

[INSERT ONE REAL BUG OR ITERATION from your DevRelay session: what failed, the actual error or behavior, how you investigated, what you changed and how you verified it.]

The lesson: a local open-weight model is strongest as an interpreter inside a conventional system. Treat its output like any other untrusted input, validate it, and keep the facts in code.

🌍 BEYOND THE BUILD: WHY GEMMA 4 AND OPEN INNOVATION MATTER

TerraGuard's design only works because the model is open-weight. The backend decides when the model loads, which evidence reaches it and what shape its answers must take. Once Gemma 4 and Ollama are installed, the core assessment needs no hosted LLM API call per inference request.

Compare that with the alternative, where every assessment, report and question is sent to a remote model service:

The control point moves outside the system. Model version, availability and pricing belong to the provider, and a connectivity gap at the site means no interpretation.
That setup can be a perfectly reasonable choice, and hosted models are often stronger and easier to operate. It just isn't the shape we wanted for a monitoring tool at a site with patchy connectivity.
With local weights, the model tag, runtime version, prompts and schemas can be documented, so other developers can reproduce the pipeline and adapt it.

Open comes with limits:

Not fully offline. Fresh weather forecasts need internet. The model and its dependencies must already be installed, and Ollama must be running.
Local doesn't mean secure. Storage, network exposure and credentials still need protecting.
Hardware matters. A 12B model needs capable hardware, and speed and memory use depend on quantization, context length and the machine.
Licensing. Apache 2.0 covers Gemma 4, not TerraGuard's code, hardware design or docs. Open weights also don't make the training data public.

Before TerraGuard could be trusted in the field, it needs site-specific calibration, field validation, failure-mode testing and expert review.

What this build shows is that a student team can now attempt a technically serious system: physical sensing, a local multimodal model and open tooling, with no hosted model at the center. The model explains the evidence, and software stays accountable for the evidence, the calculations and the safeguards. That split, more than any single model, is what TerraGuard is worth inspecting for.

Built by Adnan Nagariya and Tatwa Shahare (Bakchod Engineers (https://github.com/Adnannagariya52)).

Top comments (0)