{"id":49887069,"url":"https://github.com/akorablov/hiking_agent_eu","last_synced_at":"2026-05-15T18:36:30.699Z","repository":{"id":352217447,"uuid":"1214316127","full_name":"akorablov/hiking_agent_eu","owner":"akorablov","description":"Discover the best places to walk near you. No API keys. No cost. No tracking.","archived":false,"fork":false,"pushed_at":"2026-05-13T20:56:34.000Z","size":139,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T22:37:27.213Z","etag":null,"topics":["ai-agent","api-requests","genai","geocoder","gpt-oss","llm","ollama","python"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akorablov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-18T12:06:27.000Z","updated_at":"2026-05-13T20:56:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/akorablov/hiking_agent_eu","commit_stats":null,"previous_names":["akorablov/hiking_agent_eu"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/akorablov/hiking_agent_eu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akorablov%2Fhiking_agent_eu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akorablov%2Fhiking_agent_eu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akorablov%2Fhiking_agent_eu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akorablov%2Fhiking_agent_eu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akorablov","download_url":"https://codeload.github.com/akorablov/hiking_agent_eu/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akorablov%2Fhiking_agent_eu/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33074906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","api-requests","genai","geocoder","gpt-oss","llm","ollama","python"],"created_at":"2026-05-15T18:36:29.546Z","updated_at":"2026-05-15T18:36:30.694Z","avatar_url":"https://github.com/akorablov.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Hiking%20boot/3D/hiking_boot_3d.png\" width=\"96\" alt=\"hiking boot\"/\u003e\n\n# Hiking \u0026 Walking Finder\n### AI-powered walk recommendations · Anywhere in the world · Zero cost\n\n[![Live Demo](https://img.shields.io/badge/Live%20Demo-Hugging%20Face-yellow?style=flat-square)](https://huggingface.co/spaces/akorablov/trail-finder)\n\n*Detects your location \u003e checks today's weather \u003e discovers every walkable green area nearby \u003e recommends the best outing for the day.*\n\n\u003c/div\u003e\n\n---\n\n## What it does\n\nRun one command. The agent handles everything:\n\n| Step | What happens |\n|------|-------------|\n| 📍 **Locate** | Detects your city from your IP address - no GPS, no permissions |\n| 🌤 **Weather** | Fetches a live forecast for your exact coordinates |\n| 🤖 **Decide** | Asks the LLM *\"is it a good day to go outside?\"* - exits early if not |\n| 🗺 **Discover** | Finds every walkable green area within 25 km via OpenStreetMap |\n| 🥾 **Trails** | Fetches hiking routes for all areas in a single efficient request |\n| 💬 **Recommend** | Returns top 2-3 picks with practical, local-guide-style reasons |\n| 🔁 **Chat** | Answers follow-up questions with full conversation memory |\n\nWhen running **locally** via [main_eu.py](hiking_agent/main_eu.py), location is detected automatically from your public IP address, no permissions needed.\n\nWhen using the [**live demo**](https://huggingface.co/spaces/akorablov/trail-finder) on Hugging Face, your browser will show a *\"Wants to know your location\"* popup. Click **Allow**, this is expected and necessary. The reason: Hugging Face servers are hosted in Virginia, USA, so server-side IP geolocation would always return Virginia rather than your actual location. The browser's GPS bypasses this entirely and gives your real position directly.\n\nThe coordinates are used only to find nearby green areas. Nothing is stored or tracked.\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────────────┐\n│                         PIPELINE OVERVIEW                               │\n├─────────┬─────────┬──────────┬─────────┬─────────┬─────────┬──────────┤\n│ STEP 1  │ STEP 2  │  STEP 3  │ STEP 4  │ STEP 5  │ STEP 6  │  STEP 7  │\n│         │         │          │         │         │         │          │\n│ Detect  │  Fetch  │  LLM ①   │  Query  │  Fetch  │  LLM ②  │  Chat    │\n│Location │ Weather │ Go/No-Go │  Areas  │  Trails │  Picks  │  Loop    │\n│ via IP  │  Open-  │  yes/no  │Overpass │  batch  │  + why  │  Q\u0026A     │\n│         │  Meteo  │          │   OSM   │  query  │         │          │\n└─────────┴─────────┴──────────┴─────────┴─────────┴─────────┴──────────┘\n                           │ if \"no\"\n                           ▼\n                     Agent exits early\n                  (skips all API calls)\n```\n\n### Data sources - all free, no keys required\n\n| Source | Provides | Cost |\n|--------|----------|------|\n| [geocoder](https://geocoder.readthedocs.io) | IP \u003e lat/lon/city/country | Free · no key |\n| [Open-Meteo](https://open-meteo.com) | Hourly weather forecast, global | Free · no key |\n| [Overpass API](https://overpass-api.de) / OSM | Parks, reserves, forests, trails | Free · no key |\n| [Ollama (local/online)](https://ollama.ai) / [Groq API](https://console.groq.com) | Cloud LLM inference | Free ~ 14,400 req/day |\n\u003e **Total running cost: €0**\n\n---\n\n## Project structure\n\n```\nhiking-agent/\n├── main_eu.py             # Entry point for local use\n├── parks_eu.py            # Overpass queries, dedup, distance sorting, fallback\n├── location_eu.py         # IP geolocation\n├── weather.py             # Open-Meteo forecast + WMO weather code lookup\n├── hiking_agent.ipynb     # Annotated walkthrough notebook with 11 live tests\n├── *app.py                # Deployment. Streamlit web UI (Hugging Face Spaces / Docker)\n├── *Dockerfile            # Deployment. Docker build instructions for HF Spaces\n├── *requirements.txt      # Deployment. Python dependencies for cloud deploy\n└── *README.md\n```\n---\n\n## Quick start\n\n### 1 · Install Ollama\n\nOllama runs LLMs locally - no cloud account needed.\n\n| Platform | Command / Installer |\n|----------|-------------------|\n| **macOS** | Download `.dmg` from [ollama.ai](https://ollama.ai) |\n| **Linux** | `curl -fsSL https://ollama.com/install.sh \\| sh` |\n| **Windows** | Download `.exe` from [ollama.ai](https://ollama.ai) |\n\nVerify the installation:\n\n```bash\nollama --version\n```\n\n\u003e Ollama starts as a background service automatically. If you ever need to start it manually: `ollama serve`\n\n---\n\n### 2 · Pull a model\n\n```bash\nollama pull llama3\n```\n\nChoose based on your hardware:\n\n| Model | Size | Notes |\n|-------|------|-------|\n| `phi3` | 2.3 GB | Best for low-spec laptops |\n| `mistral` | 4.1 GB | Fast, good all-rounder |\n| `llama3` | 4.7 GB | **Recommended starting point** |\n| `llama3:70b` | 40 GB | Best quality - needs 48 GB+ RAM |\n\nCheck what you have installed:\n\n```bash\nollama list\n```\n\n---\n\n### 3 · Install Python dependencies\n\n```bash\npip install geocoder requests ollama\n```\n\n\u003e Requires **Python 3.9+**. Use a virtual environment if you prefer:\n\u003e `python -m venv venv \u0026\u0026 source venv/bin/activate` (Linux/macOS)\n\u003e or `venv\\Scripts\\activate` (Windows)\n\n---\n\n### 4 · Set your model\n\nOpen `main_eu.py` and update line 6:\n\n```python\nMODEL = \"llama3\"   # must match exactly what `ollama list` shows\n```\n\n---\n\n### 5 · Run\n\n```bash\npython main_eu.py\n```\n\n**Example session:**\n\n```\n📍 Location detected: Prague, CZ (50.0880, 14.4208)\n🌤 Today's forecast: Partly cloudy, average 13°C, max precip 0%.\n✅ Weather approved - searching for nearby areas...\n\n🌲 Found 6 nearest area(s):\n     0.7 km  [Park]            Františkánská zahrada\n     0.8 km  [Nature Reserve]  Letenský profil\n     1.0 km  [Park]            Kampa\n     1.1 km  [Park]            Vrchlického sady\n     1.4 km  [Forest]          Divoká Šárka\n     2.1 km  [Protected Area]  Prokopské údolí\n\n--- Walking \u0026 Hiking Recommendations ---\n\n1. Kampa (1.0 km) - A beautiful island park on the Vltava with riverside paths\n   and views of Charles Bridge. Perfect 30-45 min stroll. Flat, paved, dog-friendly.\n\n2. Divoká Šárka (1.4 km) - Prague's wildest green valley. Forested ravines,\n   a natural swimming lake in summer. Allow 1-2 hours. Mostly easy terrain.\n\nYou \u003e Which one is better for dogs?\nAgent \u003e Both are excellent for dogs, but Kampa edges it...\n```\n- #### *View my notebook with detailed steps here \u003e [hiking_agent.ipynb](hiking_agent/hiking_agent.ipynb)**\n\n- #### *Try it live \u003e [huggingface.co/spaces/akorablov/trail-finder](https://huggingface.co/spaces/akorablov/trail-finder)**\n\n\n---\n\n## Configuration\n\nAll settings live at the top of `main_eu.py` and `parks_eu.py`:\n\n| Setting | Default | Effect |\n|---------|---------|--------|\n| `MODEL` | `llama3` | Ollama model name - must match `ollama list` |\n| `MAX_PARKS` | `6` | Maximum number of areas returned |\n| `SEARCH_RADIUS_KM` | `25` | How far to look for green areas (km) |\n| `TRAIL_RADIUS_KM` | `10` | Trail search radius around each area centre (km) |\n| `FALLBACK_RADIUS_KM` | `300` | Max distance for offline fallback parks (km) |\n| `MAX_HISTORY` | `20` | Sliding window size for conversation memory |\n\n---\n\n## How it works\n\n### 📍 Location detection\n\n`location_eu.py` resolves your public IP to a lat/lon coordinate using the `geocoder` library. Accuracy is typically 10-50 km, more than sufficient for a 25 km search radius. No GPS, no browser permissions, no personal data stored.\n\n### 🌤 Weather\n\n`weather.py` queries Open-Meteo for an hourly forecast at your exact coordinates and extracts the **08:00-17:00 daylight window**, summarising it into one sentence:\n\n\u003e *\"Today's forecast: Partly cloudy, average 13°C, max precipitation probability 0%.\"*\n\nThis is passed verbatim to the LLM as the go/no-go input.\n\n### 🗺 Area discovery\n\n`parks_eu.py` queries the Overpass API with **deliberately broad OSM tags** - national parks, nature reserves, protected areas, named forests, regional parks, and local parks. Small and obscure local spots are included intentionally.\n\nResults are then:\n- **Sorted by real haversine distance** from your position\n- **Deduplicated by proximity** - OSM sometimes tags the same physical place twice with slightly different names (e.g. `\"Letenský profil\"` and `\"přírodní památka Letenský profil\"`). Any two entries within 100 m of each other are collapsed into one, keeping the higher-priority type label and the shorter name\n\n### 🛡 Resilience\n\n| Layer | Mechanism |\n|-------|-----------|\n| **Mirror failover** | 3 public Overpass endpoints tried in sequence |\n| **Retry logic** | Timeouts and 504s skip to the next mirror automatically |\n| **Hardcoded fallback** | ~70 curated national parks across every continent, distance-filtered to your actual position |\n| **Graceful degradation** | If trails fail, areas are still recommended; if weather fails, the agent exits cleanly with a message |\n\n### 🥾 Trail fetching\n\nRather than one Overpass HTTP request per park (which caused cascading 429 rate-limit errors), all trails for all parks are fetched in **a single batched union query**. Each trail is then assigned to its nearest park centre.\n\n### 🧠 Conversation memory\n\n`main_eu.py` maintains memory at two levels:\n\n- **Sliding window** - conversation history is trimmed to `MAX_HISTORY` messages so the LLM context window never overflows across long sessions\n- **Pinned facts** - type `remember: I prefer flat walks` to pin a preference that survives history trimming and is injected into every subsequent prompt\n---\n## ⚠️ Limitations\n\n| Area | Detail |\n|------|--------|\n| **IP geolocation** | City-level accuracy (~10-50 km). Rural users may get the nearest town as their position |\n| **OSM coverage** | Western Europe and North America are very well mapped. Parts of Africa, Central Asia, and rural South America have sparser data |\n| **Overpass availability** | Public mirrors are best-effort. The fallback list covers major parks on every continent but cannot replicate live OSM richness |\n| **Trail difficulty** | Relies on the `sac_scale` OSM tag, which is not universally applied. `Unknown` difficulty means unrated in OSM, not dangerous |\n| **Language** | Area and trail names are returned in the local OSM language (Czech, German, etc.) - the LLM handles translation in its response |\n\n---\n\n## License\n\nMIT. Do whatever you like with it. Contributions welcome.\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\u003csub\u003eBuilt with OpenStreetMap · Open-Meteo · Groq · Python · Docker\u003c/sub\u003e\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakorablov%2Fhiking_agent_eu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakorablov%2Fhiking_agent_eu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakorablov%2Fhiking_agent_eu/lists"}