This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
What I Built
I love hiking, but I hate getting to a trailhead, losing my cell signal, and realizing I forgot to download the trail details or check the sunset time. So, I built TrailCompanion.
It’s a simple Python tool that runs entirely offline. You give it your location and how far you want to hike, and it filters a downloaded dataset of local trails. Then, it uses a tiny local AI model (Gemma 1B) to look at the trail stats and give you a quick, contextual safety check.
The whole point is to spend 30 seconds looking at your laptop in the trunk of your car, get the info you need, close the lid, and actually go outside! It's built for hikers, backpackers, and campers who want to explore off-grid without compromising on preparation.
Demo
I usually run it straight from the terminal right before hitting the trail.
Command:
python companion.py --location "Pine Barrens" --distance 8km
Output:
🌿 TRAILCOMPANION OFFLINE BRIEFING
Selected Route: Stump Pond Loop (7.8 km, 140m gain)
Estimated Duration: 2h 45m (excluding breaks)
[Local AI Tip]: "Sunset is at 6:18 PM today. If you step off
by 2:30 PM, you'll have plenty of buffer daylight. The trail
gets muddy after rain, so wear proper boots."
Code
Here is the main script. I didn't want anything bloated, so it's just standard Python and Pandas filtering a local CSV before handing the context over to the local AI.
import argparse
import sys
from pathlib import Path
import pandas as pd
def load_offline_trails(csv_path):
if not Path(csv_path).exists():
print("Error: Where is your trail CSV? Download it first!")
sys.exit(1)
return pd.read_csv(csv_path)
def get_ai_safety_tip(prompt_context):
try:
# Running Gemma locally so we don't need Wi-Fi
from llama_cpp import Llama
llm = Llama(model_path="./models/gemma-3-1b-it.gguf", n_ctx=512, verbose=False)
output = llm(prompt_context, max_tokens=60, stop=["\n"], echo=False)
return output["choices"][0]["text"].strip()
except Exception:
return "Couldn't load AI. Standard tip: bring extra water and watch the sun."
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Offline Trail Guide")
parser.add_argument("--location", required=True, help="Where are you?")
parser.add_argument("--distance", required=True, help="How far in km?")
args = parser.parse_args()
trails = load_offline_trails("data/trails.csv")
match = trails[trails['region'].str.contains(args.location, case=False, na=False)]
if match.empty:
print(f"No offline trails found for {args.location}. Check the map.")
else:
print(match.iloc[0])
nudge = get_ai_safety_tip(f"Give a short 1-sentence safety tip for hiking a {args.distance} loop.")
print(f"\n[Local AI Tip]: {nudge}")
How I Built It
I used Google's Gemma 1B instruction-tuned model because it's small enough to run effortlessly on a standard laptop without making the hardware overheat or draining the battery in the field. I'm running it completely locally using llama.cpp and the llama-cpp-python bindings.
The app itself relies on a lightweight Python logic architecture. The script handles the hard conditional sorting of the local CSV data, and the local LLM acts as an edge-computing assistant to evaluate the trail stats and generate an immediate safety warning. No web frameworks, no cloud hosting, and zero network calls—just a raw script you can execute anywhere from a backpack.
Why Does Open Innovation Matter?
Closed APIs like OpenAI or Claude are great, but they are completely useless when you're 10 miles deep in a state park with zero bars of service.
Having an open-weight model I can run locally means this tool actually works where I need it to—in the middle of nowhere. It doesn't rely on the cloud, it doesn't cost money per query, and it respects privacy by keeping location data completely local. Without access to open-weight models like Gemma, building a truly disconnected, offline outdoor utility like this wouldn't be possible for an independent developer.
My Agent Session
I utilized a local AI coding assistant to help me figure out the correct llama-cpp-python bindings and argument syntax. This allowed me to suppress the verbose model loading logs directly from the Python script, ensuring the final terminal interface remained perfectly clean for outdoor usage.
Prize Categories
- Best Use of Gemma
Top comments (0)