Skip to content

Latest commit

 

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Trailhead

A local, zero-cost hiking day planner built with LangChain 1.x create_agent.

Give it a location and your preferences. It searches the web for trails and current weather, suggests options, and adapts as your constraints change across the conversation. You can also drop in a photo of your gear and it will identify the items and offer general readiness tips.

The planning agent runs fully local at no cost: trails, weather, and memory all work offline. The optional gear-photo feature is the one part that uses a free cloud vision model. Because every model is created through a provider-agnostic factory, swapping any of them is a one-line change in .env with no code touched.

Demo

One-shot hike planning grounded in live web search Interactive chat that remembers earlier turns
Plan a hike in one shot, grounded in live web search. Interactive chat: follow-ups remember the conversation.
Structured typed JSON output with the json flag Gear-photo identification with the gear flag
--json returns a validated, typed plan. --gear identifies gear in a photo and gives tips.

(Recorded against a cloud model for a snappy demo; the same commands run locally on Ollama.)

How it works

One small agent, assembled from a few building blocks:

  • a provider-agnostic model (init_chat_model)
  • a hiking-guide system prompt
  • a web search tool (Tavily) for live trails and weather
  • short-term memory (a LangGraph checkpointer + thread id) so follow-ups make sense
  • image input for the gear photo, handled by a separate vision model

The chat is wrapped by a single create_agent, which runs the tool-calling loop automatically.

Local agent, cloud vision

The planning agent runs entirely on a local model. Reading an image is the only step that needs a vision model, and capable vision models are large and memory-hungry to run locally alongside everything else, so that single step uses a small free cloud vision model for reliability while the rest stays local and free. Swapping either side is just a .env edit, thanks to the provider-agnostic factory.

Typed output on a local model

--json returns a validated schema via response_format. Hosted models emit strict schemas reliably, so one call is enough; a small local model usually complies but occasionally finishes without the structured result, so the JSON mode retries a few times before giving up (and never crashes on a miss). Pointing LLM_* at a cloud model removes the need for the retry.

Design: why it stays small

Trailhead is a handful of small modules instead of a pile of plumbing, because LangChain 1.x does the heavy lifting:

  • create_agent runs the tool-calling loop for you (decide -> call the tool -> feed the result back -> answer). There is no hand-written loop translating tool calls and re-invoking the model.
  • init_chat_model is provider-agnostic. You choose a model with a string plus a base URL, so switching between local and cloud is a .env edit. There is no separate provider-routing layer to build and maintain.
  • The building blocks are explicit: one agent, one tool, one prompt, one checkpointer. The wiring is a few readable lines, not a framework of scripts.

Quick start

Prerequisites: Python 3.12+, uv, and Ollama: Setup the environment here with a tool-capable model pulled:

ollama pull qwen2.5:7b

Web search needs a free Tavily key. The optional gear-photo feature uses a local vision model served over an OpenAI-compatible endpoint (for example LM Studio running a vision model).

uv sync
cp .env.example .env      # set TAVILY_API_KEY (and a Gemini key for the gear photo)
uv run trailhead "easy day hikes near Seattle today"   # plan a hike
uv run trailhead --gear samples/gear.jpg               # identify gear in a photo

Configuration

All settings live in .env (copy from .env.example):

Variable Purpose Default
LLM_MODEL agent model tag qwen2.5:7b
LLM_MODEL_PROVIDER dialect the endpoint speaks openai
LLM_BASE_URL model server URL http://localhost:11434/v1
LLM_API_KEY ignored locally; any non-empty value ollama
TAVILY_API_KEY web search key (free tier) (yours)

.env.example also lists free OpenAI-compatible cloud backends you can point LLM_* at for faster responses.

Results

The same agent (web search + planning) run across a few providers, to show the trade-off behind the "build local, run on a fast free tier when you want speed" design. Small samples on a single machine, so treat these as indicative, not a rigorous benchmark.

Provider (model) Median latency/turn Tool-calls
Local — Ollama qwen2.5:7b (CPU) ~75 s 5/5
Gemini 2.5 Flash ~6 s 3/3
GitHub Models gpt-4o-mini ~11 s 2/2
Groq llama-3.3-70b-versatile ~4 s (fastest) 1/3

The local model is free and fully offline but roughly 10x slower on CPU. Groq had the lowest raw latency but its strict tool-call validation rejected 2 of 3 runs; Gemini and gpt-4o-mini were both fast and reliable. Method: N=5 local and N=2-3 per cloud provider, one warm-up call excluded, medians reported; switching providers is a .env change only.

Credits

Inspired by Introduction to LangChain from LangChain Academy and the official LangChain documentation, which are where the concepts behind this project came from. Everything here was then built entirely from scratch: the agent, its tools and its prompts are all original work.

The sample gear photo (samples/gear.jpg) is "A backpack with trekking poles and shoes" by SGrabarczuk (WMF), licensed under CC BY-SA 4.0, from Wikimedia Commons. See samples/NOTICE.md.

License

The code is released under the MIT License. The bundled sample image keeps its own license (see Credits).

About

Local, zero-cost hiking day planner built with LangChain 1.x create_agent: web-grounded trail + weather search, short-term memory, typed JSON output, and multimodal gear-photo ID. Runs on a local Ollama model, swappable to any OpenAI-compatible cloud model via .env.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages