Commit History
-
Gate precision: add nationality adjectives + remaining sentence-starters
Live whack-a-mole tail: "Flemish" (nationality) and "Even" (starter) were still sinking otherwise-grounded narrations. Add a bounded batch of nationality/cultural-style adjectives and common clause-openers to _COMMON. Invented venues and the planted Eiffel Tower still fail. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>14b11e2 -
Gate precision: stop false-positives on art movements / events / starters
With landmarks now allowed, the remaining narration rejections were pure false-positives: capitalized non-places the gate mistook for venues — "Impressionism"/"Impressionist", "French Revolution", "Remember". Add art movements, historical events/periods, and more sentence-starters to _COMMON so grounded prose passes. A real invented venue (Cafe des Mensonges) and the planted Eiffel Tower still fail. Test: test_gate_ignores_art_movements_and_events. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>fb935de -
Narration: expand per-city gazetteer with famous landmarks (loosen gate)
The 1B name-drops real landmarks (Arc de Triomphe, Sacre-Coeur, Edo Castle...) for scene-setting; the strict gate rejected them -> template. Add curated landmark allowlists per pre-baked city so that grounded, vivid prose passes instead. Eiffel Tower stays OFF the list (the planted hallucination the gate must keep catching) and invented venues still fail. Narration prompt realigned: name the 'You may reference' places freely, never anything outside the lists. Test: test_geo_gazetteer_allows_landmarks_but_not_eiffel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>f440fba -
Call-1 weights: drop the parroted example, default to no-think (A/B verdict)
Live A/B on "quiet green wander" was decisive: - No-think: 9.6s, clean JSON — but byte-identical to the worked example in the prompt (the 1B copied the example's numbers verbatim). - Think: 26s (3x slower/quota), and corrupted the JSON (zeroed the matching categories). Reasoning did not help this scoring task. Two parrot traps now removed: the old `0.0-1.0` schema AND the worked JSON example. New prompt gives NO copyable number-set — it states 0..1 in words and teaches the mapping with short word->type cues, so the model scores the actual vibe. Wrong/empty output still falls through to the embed tier (_is_degenerate). Default flag flipped to no-think; thinking stays toggleable via DISCOVERROUTE_VIBE_THINKING=1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>36d6af8 -
Call-1 reasoning budget 1024 + no-think A/B flag; narration name lockdown
Live trace findings drove these: - Call-1 reasoning ran past the 512-token budget without emitting JSON (empty -> fallback). Bump think budget to 1024; no-think stays 256. - Add DISCOVERROUTE_VIBE_THINKING A/B flag (config.VIBE_THINKING, default on) and record the chosen mode on every vibe_extraction trace row so think vs no-think can be compared head-to-head. - Narration kept name-dropping real off-route landmarks (Pont des Arts, Mona Lisa, Sorbonne, Sacre-Coeur) -> gate rejected -> template. Tighten the prompt to a hard allowlist (stops + endpoints + gazetteer only; scene-set without proper names) and fix the literal-"H3" artifact. - Scale narration token budget with route length (600..880) so long routes stop truncating mid-name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>5ef2ba5 -
Call-1 vibe weights: reasoning pass + anti-zero prompt + degenerate guard
Live traces showed MiniCPM5-1B returning an all-zero weighting for "quiet green wander" that passed validation (used_fallback=False), so the router got no taste signal and defaulted to nearby well-tagged POIs (public art) — a green vibe came out "arty". Root causes + fixes: - Prompt showed `"cafe": 0.0-1.0`; the 1B parroted `0.0` as the value. Rewrite states 0..1 in words, forbids all-zero/all-equal, gives one worked example on an unrelated vibe (shape, not value). - run_inference now supports enable_thinking (MiniCPM5-1B is hybrid- reasoning, verified on the model card); vibe->weights runs a reasoning pass and the <think> block is stripped before JSON parse. - _is_degenerate() rejects all-zero/all-equal output so the dispatcher falls through to the bge-small embed tier instead of routing tasteless. Test: test_llm_rejects_degenerate_weights (from the real all-zero trace). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>128e312 -
Remove stale DEPLOY.md runbook + its dead README link
DEPLOY.md was a one-time deploy runbook (Space already live) and had gone stale. Drop it and the now-broken README reference. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>6b41d01 -
Submission: finalize field notes + wire all judge links
- FIELD_NOTES.md rewritten to current build (MiniCPM5-1B, 9 cities, grounding gazetteer, save-taste + Maps/GPX export); numbers verified against data (30,357 POIs, 77,454 nodes / 221,688 edges) - README links block: add GitHub source, demo video, social posts, HF blog Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>330c7c6 -
Narration: remove copyable title examples + deterministic title guard
A 1B model copies any concrete example, so it parroted '### The Quiet Green Mile'. Drop the literal examples and add a guard that swaps in our computed route-title if the model echoes a stock example or omits the heading. Headings are gate-exempt, so the substituted title is always grounded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>f72500e -
Narration: stop the 1B model copying the example title verbatim
It was emitting '### Like This' (my prompt's literal example). Give several varied title examples + 'make up your own, do not reuse these' so it invents one. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>671bd3d -
Narration: kill label-parroting at the source + reduce gate false positives
Traces showed two remaining issues: the model parroted 'park garden'/'place of worship' from the 'Weights extracted:' prompt line (removed it + dropped the now dead _weights_summary), and the gate kept rejecting lone sentence-starters ('Stepping'). Add a comprehensive common-word set instead of a blanket single-word pass (which had let the planted 'Eiffel Tower' through). Guarantee intact: all multi-word invented venues still caught. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>f1b269b -
Narration: stop category-label parroting + force flowing prose
Traces showed the 1B model echoing the raw category ('It's a park garden, exactly as it sounds') and reverting to a numbered list that cut off mid-walk. Fix: feed stop names only (no '(park garden)'), instruct one-heading flowing prose with no numbering, and raise the token budget 480->600 so longer walks finish. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>54646ca -
Narration: stop the gate rejecting the LLM's own title + 'Just' (traces-driven)
Live traces showed the LLM writes great flowing prose but gets rejected over false positives: its evocative title ('### The Quiet Canvas'), the word 'Just' (sentence starter), and a few off-route NYC landmarks. Fix: exempt markdown heading/title lines from grounding, allow 'just'/'main'/evocative prose words, add NYC landmarks to the gazetteer. Planted-hallucination guarantee still holds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>0aa4caf -
Trace: create the dataset repo before pushing (upload_file does not auto-create)
Root cause of the missing trace dataset: upload_file 404s when the repo doesn't exist; only the CLI auto-creates. Add an idempotent create_repo(exist_ok=True) on first push + in the selftest, so the dataset is created and traces actually flow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>d336f72 -
Trace: log push failures + boot self-check for HF_TOKEN write access
The push errors were swallowed by a bare except, so a misconfigured HF_TOKEN secret made the trace dataset silently never appear. Now log the real error and run a boot-time selftest that prints whether the token is present and can write to the trace dataset. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>2b4da11 -
Narration: route titles, varied phrasing, flowing LLM prose, looser gate
- Evocative route-title headline per walk (template + LLM) - Rotating reason variants so repeated categories never read identically - LLM prompt rewritten for a titled, flowing first-person story - Loosen the zero-hallucination gate (token-subset match + more allowed descriptive words) so vivid output survives; no-invented-venue guarantee kept - Gazetteers for San Francisco, Tokyo, Mumbai, Shanghai, Berlin Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>142f66c -
Docs + repo cleanup for submission
- README: Backyard AI (Track 1), origin story, team links, live Space link - Correct claims: achievements (offgrid/offbrand/sharing/fieldnotes) + bonus badges (Off Brand/Tiny Titan/Best Agent); confirmed tag taxonomy - Field notes -> HF blog (TBA link); delete SUBMISSION.md - Remove AI-generated testing/checkpoint clutter + ad-hoc scripts (13 files) - Remove dead UI code (orphaned stepper JS/CSS, unused slider rules) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>8f3773e -
UI: style city dropdown to match, condense sliders to one row, live-map teaser loader
- City <select> now styled like the text inputs (cream, rounded, custom caret) - Detour + Adventurousness sliders condensed to single compact rows with inline captions - Replace static 4-step loader with an animated live-map teaser (route threads between popping pins + a walking dot) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>1e4da49 -
new cities added
1add89c -
fixed the narration+traces
c552106
-
Add submission kit: demo script, social post, badge checklist
Tristan Leduc +1: Claude Opus 4.8 (1M context)Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>ebd7bac -
Docs/UI: reflect multi-city + Off the Grid; Thousand Token Wood track
Tristan Leduc +1: Claude Opus 4.8 (1M context)- README/Space card: cities (Paris/London/Barcelona/NYC), offline no-cloud-API framing, track tag → thousand-token-wood, badge tags → off-the-grid/off-brand/ tiny-titan/field-notes/openbmb. - Start-field help now names the supported cities so judges find multi-city. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>2ab78dc -
Pre-baked offline cities (London, Barcelona, New York) + endpoint-stop fix
Tristan Leduc +1: Claude Opus 4.8 (1M context)Keeps the "Off the Grid" badge while going multi-city: each extra city is baked as a bounded walkable core (centre + radius) committed via Git LFS, so it routes fully offline — no live OSM at request time. - data/build_city.py + config.CITIES registry; data/cities/<slug>_{walk.graphml, pois.parquet} for london/barcelona/newyork (+ cities_manifest.json). - routing/area.py: resolve_area now picks Paris → a pre-baked city (both points in its core) → (online only) on-demand fetch. In offline mode, anywhere else is refused with an honest "WanderLust covers Paris, London, …" message. - routing/geocode.py: offline name index now spans Paris + every pre-baked city, with city-hint disambiguation ("…, London") so a landmark resolves to the right city; suggest()/local_geocode() are city-aware. - pipeline.py: drop candidate POIs within 80 m of the start/destination so an endpoint (e.g. the square you start from) is never offered as a "discovery stop" — it isn't a detour and read as …6881784 -
Mobile UI: bound the autocomplete dropdown + denser drawer + keyboard handling
Tristan Leduc +1: Claude Opus 4.8 (1M context)The "typing narrows the menu" issue: the start/destination autocomplete list had max-height:none, so a 9-item dropdown grew unbounded and buried the rest of the menu (Destination/Mode/sliders), with its tail clipped by the CTA. Cap it at min(46vh,300px) with internal scroll so it stays compact. Also for mobile readability: - Tighten drawer density (panel padding, control margins, chip gap) so more of the menu is visible at once — the brand + vibe header no longer clip at the top. - Add a visualViewport handler: when the on-screen keyboard opens, size the bottom drawer to the visible area above it and scroll the focused field into view (dvh alone gets crushed on Android / overlaid on iOS). Verified in the mobile preview (375px): dropdown now 300px + scrollable; full menu (vibe → Plan button) scrolls cleanly; no console errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>d34ffe8 -
Fix mode toggle layout: #dr-mode .wrap missing display:flex
Tristan Leduc +1: Claude Opus 4.8 (1M context)The walk/bike segmented control set its labels to flex:1 + justify-center, but the .wrap container was display:block, so the labels never expanded — each stayed ~content-width and clustered at the left of the tan box instead of splitting it in half. Add display:flex; align-items:center. Verified live: both labels now split evenly (332px each in a 680px box); click still toggles selection (handler was never broken). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>c4b5726 -
Add on-demand worldwide cities (any city via live OSM)
Tristan Leduc +1: Claude Opus 4.8 (1M context)Paris stays pre-baked (instant, offline). Any other city is now fetched from OpenStreetMap at request time — only the bounding box spanning the two endpoints plus a margin, so a cross-city route downloads a few MB, not the whole metropolis. - routing/area.py: new Area (graph + POIs + projection origin + timezone + CSR); resolve_area() returns the cached Paris area for in-Paris requests, else builds an on-demand bbox area (bounded LRU cache), with a max-endpoint-distance guard. - pois.py: projection origin is now per-area (index_table/to_metres take origin), not the Paris constant; corridor_pois accepts an area table+origin. - graph.py: build_csr(graph) extracted so the travel matrix uses the area's own network; geocode_point now resolves worldwide (Paris offline index for Paris- hinted queries, Nominatim otherwise) instead of rejecting non-Paris. - matrix.py: build_matrix accepts the area CSR. - pipeline.py: resolve + thread the area; open-now uses the area timezone. - confi…1a502dd -
Round-5 fix: relabel bakery_food_shop "food shop" (no false 'bakery' claim)
Tristan Leduc +1: Claude Fable 5Both round-5 reviewers converged on the SOLE remaining MAJOR: a wine shop ("Trois Fois Vin", OSM shop=wine → bakery_food_shop) was narrated "another bakery along the way" — a false, verifiable label. The category bundles bakery/patisserie/wine/cheese/deli, so render it "food shop" (always true). Sole change to pretty_category. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>2577e90 -
Round-4 fixes: drop overclaiming match-tag, dedup stops, hidden excludes famous
Tristan Leduc +1: Claude Fable 5Adversarial round 4 (NOT-CONVERGED) — root-caused to 3 issues: 1. The per-stop "a match for your vibe" tag overclaimed: any route that backfills a lower-ranked category (bakery on wine, church on jazz, statue on street-food/photography) falsely labelled those stops a match. Removed the tag entirely — each stop's reason text + the interpretation panel carry the honest framing; the model can't guarantee per-stop relevance. 2. No within-route dedup → the same place ("UP /SIDE / DOWN / TOWN") appeared twice in one route. Dedup the shortlist by osm_id AND name. 3. "hidden gems" still surfaced Notre Dame — the attraction-zeroing missed it (it's viewpoint). Discovery cues now drop famous, well-documented POIs by tag-richness (confidence >= FAMOUS_CONFIDENCE 0.85), category-independent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>c16ccf9 -
Round-3 fixes: wire interp weights, ref-name guard, tighten attraction gloss
Tristan Leduc +1: Claude Fable 5Adversarial round 3 (NOT-CONVERGED) found 3 MAJOR issues: 1. The discovery-cue affinity adjustments (zeroing "attraction" for "hidden gems") were COMPUTED then DISCARDED — the pipeline scored with effective_weights() while interp.weights was thrown away. Now the vibe path uses interp's own affinity (blended with profile when present), so "hidden gems" actually drops famous attractions. 2. OSM ref-code names ("PA_1570") surfaced as unfindable stops labelled "a match". Added taxonomy.is_real_name(); such POIs now self-demote (UNNAMED_SCORE_FACTOR) and render as "a <noun>". 3. "attraction" gloss ("famous landmark... worth seeing") embedded near "tour/spots/photo", landing Hôtel de Ville on a coffee tour. Tightened to "a major crowded tourist attraction or world-famous monument". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>720767c -
Round-2 follow-ups: discovery-cue handling + sparse-category honesty
Tristan Leduc +1: Claude Fable 5- "hidden gems / off the beaten path / like a local" now suppresses the famous-"attraction" category (its semantic opposite) and bumps adventurousness to 0.8 so the route favours under-documented places. - When the user's #1 requested category has zero stops on the corridor (e.g. "jazz and live music" with no venues between A and B), the interpretation panel says so instead of silently tagging churches "a match for your vibe". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>7ae16ab -
Round-2 route-fit: top-N category cap + weak-match honesty
Tristan Leduc +1: Claude Fable 5Adversarial round 2 (NOT-CONVERGED) found two systemic issues, both fixed: - AFFINITY_FLOOR let all 17 categories keep weight, so ranks 5-17 silently backfilled routes with off-vibe filler (same statues/churches bled into 10+ unrelated routes). Now cap to TOP_AFFINITY_CATEGORIES=6; the tail is zeroed (sparse routes end honestly short, not confabulated). Applied in embed + centrally in resolve_affinity (covers llm/keyword tiers too). - min-max forces a top category to 1.00 even for weak/out-of-vocabulary vibes, so "brutalist architecture" got churches confidently labelled "a match for your vibe". Added raw-cosine confidence (WEAK_MATCH_SIMILARITY =0.55; real vibes 0.66-0.85, brutalist 0.51, nonsense ~0.49); weak vibes now get honest framing ("no strong match — here's my closest guess") and drop the per-stop "a match for your vibe" tag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>a4c45c1 -
Route-fit fixes from adversarial review (span, glosses, attraction gate)
Tristan Leduc +1: Claude Fable 5- MIN_AFFINITY_SPAN 0.18 -> 0.10: 0.18 neutralised real evocative vibes ("romantic", "beautiful", "brutalist" all span ~0.14-0.15) into an identical generic grab-bag; gibberish spans 0.081, so 0.10 separates. - Gloss keyword-bleed: drop "coffee roaster" from bakery gloss (was tying cafe 1.00 / bakery 0.97 on "specialty coffee tour") and "quiet" from worship gloss (was pulling churches into "quiet to read"). - classify(): admit a bare tourism=attraction only if notable (wikidata/wikipedia/heritage) — drops commercial venues like escape rooms that polluted monuments/worship/romantic routes (conf can't filter them: an escape room has conf 1.0). Rebuilt parquet: 290 -> 58 attractions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>6c11e60 -
Fix Space card: trim short_description to <60 chars, set python_version
Tristan Leduc +1: Claude Fable 5Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>ae3e8f2 -
Merge pull request #1 from tristanleduc/v2
Unverified signatureV2bf423e9 -
Merge branch 'v2' of https://github.com/tristanleduc/wanderlust into v2
f2b21c0 -
fixed ui
2c5a5d1
-
Import narrate.llm at startup so ZeroGPU detects the @spaces.GPU function
Tristan Leduc +1: Claude Fable 5Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>bd037ff -
Add src/ path shim so the Space container finds the package
Tristan Leduc +1: Claude Fable 5Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>71d9edc -
Pin torch 2.11.0 for ZeroGPU compatibility
Tristan Leduc +1: Claude Fable 5Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>b31efd0 -
update readme
a82c73b -
v2 with model changed and using gradio server func
10cf611
-
Design system, live freshness, autocomplete, and clay-pin markers
Tristan Leduc +1: Claude Fable 5UI/UX (from the design handoff): - Clay-sticker theme, hero, framed Voyager map with warm grade, loading state ("Scouting your wander…"), route-draw + staggered marker pop-in - 14-piece clay-pin marker family (vendored SVGs) with color-by-meaning mapping for all 17 categories, start/dest pins, legend in the family's color language - Start/Destination autocomplete over the local 30k POI-name index - Force-light mode (design is light-only; Gradio dark vars made text unreadable), per-event js fixed to pass inputs through Freshness: - Open-now awareness from OSM opening_hours (9,461 POIs): conservative evaluator (abstains on exotic grammar, per-rule PH/SH handling), plan-time demotion of closed places, night realism for unknown-hours daytime categories, 🟢/🔴 itinerary badges - Optional Google Places live-verify of final stops (GOOGLE_MAPS_API_KEY; ToS-clean: per-request, never stored) - Embedder switched to fastembed/ONNX (no torch in the request path; warms in ~9s), bo…b34c92a -
Wanderlust: taste-aware Paris discovery routing
Tristan LeducBuild Small Hackathon submission - v1 complete All P0 requirements + P1 features: - OSM-based routing with detour budget control - POI extraction with confidence scoring (30k places, 17 categories) - Submodular orienteering solver with diversity optimization - Vibe interpretation via sentence embeddings (bge-small) - Grounded narration (0% hallucination gate) with optional Qwen3.5-9B - Persistent taste profile (browser-based) - Alternative routes (3 options) - Custom UI (clay/sticker design with animations) - Offline-first architecture (no runtime cloud APIs) - Fully tested (42 tests passing) Stack: OSM + networkx + scipy + Gradio 6 + HuggingFace Ready for HF Space deployment. See HACKATHON_DEPLOYMENT.md for push instructions.f00d669