Spaces:
Sleeping
# Wanderlust Chatbot ML Evaluation Report
Generated: 2026-04-18 | Last run: 2026-05-20 (Wave 5 — all 17 intents have test coverage)
Evaluator: app/training/evaluate.py (read-only, no retraining)
Wave 5 update (2026-05-20): Added test coverage for all 4 previously uncovered intents. Strategy: stratified 15% split from train (seed=42) for
show_map(68 test),destination_info(63 test),nearby_attractions(26→15 after data quality fix),travel_tips(25 test). Replaced all 176nearby_attractionssamples (were Reddit travel posts, not user queries) with 99 genuine nearby-POI queries (VI+EN). Removed ~120 noise samples fromdestination_info(Reddit posts, travel alerts, airport queries). Added 90 distinctive VI+ENdestination_infosamples. Results: Accuracy 90.97%, Macro F1 89.02% on all 17 intents. No intent below F1 0.77.Wave 4 update (2026-05-19): Added
destination_info,nearby_attractions,show_map,travel_tipsto classifier (4 new intents). Held-out test set had 0 samples for these → Macro F1 dropped 0.94 → 0.76 due to F1=0.00 on 4 intents. Fixed in Wave 5.Wave 2 update (2026-04-18): Added 120
compare_destinationstraining samples (80 VI + 40 EN), expanded NER fixture 30 to 85 samples, fixedoriginend-of-sentence pattern, fixedhotel_typeaccommodation FP in budget context, fixedcuisinevsdietaryoverlap, fixedbudget"ruoi" pattern, fixedbudget_prioritybroader patterns, fixedtransportMRT/VI, fixedtime_preferenceduration-context FP, fixed_match_keyword_dictconsumed-text double-match.Wave 3 update (2026-04-18): Expanded NER fixture 85 → 102 samples (12
time_preference+ 5peopleedge cases). Fixedtime_preferenceF1 0.40 → 0.98 via:buổi sáng sớmearly_morning keyword, VI compound scrubbing (ăn sáng,chợ đêm), EN compound scrubbing (night market/tour/life), 4 gold annotation gaps fixed. Addeda week / one/two/three weeksEN duration patterns. Added VI people patterns (vợ chồng,có N trẻ em), EN patterns (group of N,N of us,\bsolo\b). Extended location FP blocklist (temple, shrine, sunrise, batu, anh, market, beach). NER micro F1: 0.912 (85 samples) → 0.920 (102 samples).Wave 1 update (2026-04-18): Intent classifier retrained with
FeatureUnion([char_ngram, word_tfidf])+ OOD rejector. NER regex fixes applied (hotel_type, dietary, travel_style, origin). Commitff6ef214.
Scope
Two models with objective metrics: intent_classifier and NER. Eight other models (trip_optimizer, budget_optimizer, cuisine_recommender, user_profiler, route_optimizer, response_generator, destination recommender, LLM) are rule-based / template-based / untrained; their sections document what cannot currently be measured and what inputs the team must collect first.
1. Intent Classifier
Status
Held-out test set -- intent_test.json produced by split_dataset.py
(stratified 15% split, seed=42). Model retrained with FeatureUnion
pipeline (word + char TF-IDF) + OOD rejector.
Overall Metrics — Wave 5 run (2026-05-20, held-out n=1251, all 17 intents covered)
| Metric | Wave 2 | Wave 4 (13 intents) | Wave 5 (17 intents) | Note |
|---|---|---|---|---|
| Samples | 1,094 | 1,094 | 1,251 | +157 samples for 4 new intents |
| Accuracy | 0.9388 | 0.9305 | 0.9097 | slight drop expected (harder intents added) |
| Macro F1 | 0.9412 | 0.7635 (all) / 0.9400 (13) | 0.8902 | all 17 intents, no zero-support intents |
| Weighted F1 | — | — | 0.9117 |
All 17 intents now have test samples. No intent below F1 0.77.
Per-Intent F1 — Wave 5 (sorted ascending)
| Intent | P | R | F1 | Support | Status |
|---|---|---|---|---|---|
| nearby_attractions | 0.75 | 0.80 | 0.77 | 15 | |
| destination_info | 0.79 | 0.78 | 0.78 | 49 | |
| greeting | 0.73 | 0.90 | 0.81 | 30 | |
| compare_destinations | 0.74 | 0.94 | 0.83 | 18 | |
| travel_tips | 0.95 | 0.76 | 0.84 | 25 | |
| show_map | 0.95 | 0.78 | 0.85 | 68 | |
| activity_suggest | 0.83 | 0.89 | 0.86 | 116 | |
| fallback | 0.91 | 0.87 | 0.89 | 120 | |
| find_hotel | 0.83 | 0.97 | 0.89 | 30 | |
| food_recommend | 0.93 | 0.87 | 0.90 | 120 | |
| weather_info | 0.94 | 0.94 | 0.94 | 120 | |
| plan_trip | 0.95 | 0.94 | 0.95 | 120 | |
| budget_advice | 0.94 | 0.96 | 0.95 | 120 | |
| transport_info | 0.97 | 0.93 | 0.95 | 120 | |
| find_flight | 0.94 | 0.99 | 0.96 | 120 | |
| visa_info | 0.94 | 1.00 | 0.97 | 30 | |
| thank | 0.97 | 1.00 | 0.98 | 30 |
Top Confusion Pairs (Wave 5)
| True intent | Predicted intent | Count |
|---|---|---|
| food_recommend | activity_suggest | 8 |
| activity_suggest | destination_info | 4 |
| budget_advice | find_flight | 4 |
| destination_info | plan_trip | 3 |
| fallback | activity_suggest | 3 |
Confidence Distribution (Wave 5)
- Predictions via
ml_model: 1195 / 1251 = 95.5% - Predictions via
keyword_fallback: 50 / 1251 = 4.0% - Predictions via
ood_rejector: 6 / 1251 = 0.5%
Issues Flagged for Follow-up
nearby_attractions(n=15) — small test set, F1 estimate unstable. Add more test samples for reliable measurement.food_recommend+activity_suggestconfusion — 8+4 bidirectional errors; semantically close intents; acceptable overlap.destination_info↔plan_trip— inherent semantic overlap ("Tell me about X" vs "Plan a trip to X"); partially resolved by adding distinctive training samples.
2. Named Entity Recognition (NER)
Status
Real evaluation against expanded hand-curated fixture
app/data/datasets/ner_eval.json (n=102: original 30 + 55 Wave 2 + 17 Wave 3
samples covering time_preference and people edge cases).
Overall Metrics -- Wave 3 (102 samples)
| Metric | Wave 1 (30 samples) | Wave 2 (85 samples) | Wave 3 (102 samples) |
|---|---|---|---|
| Micro Precision | 0.894 | 0.899 | 0.914 |
| Micro Recall | 0.953 | 0.926 | 0.926 |
| Micro F1 | 0.923 | 0.912 | 0.920 |
| Samples with >=1 error | 14/30 (47%) | 38/85 (45%) | 48/102 (47%) |
Note: Wave 3 adds 17 samples specifically designed to expose
time_preferenceandpeopleedge cases. Overall micro F1 rose from 0.912 to 0.920 despite harder samples.
Per-Entity-Type Metrics -- Wave 3
| Entity type | P | R | F1 | TP | FP | FN | vs Wave 2 F1 |
|---|---|---|---|---|---|---|---|
| destination | 0.93 | 0.96 | 0.95 | 104 | 8 | 4 | same |
| duration | 0.96 | 0.93 | 0.95 | 69 | 3 | 5 | +0.01 (week patterns) |
| location | 0.95 | 0.97 | 0.96 | 121 | 7 | 4 | +0.02 (blocklist expansion) |
| people | 0.81 | 0.85 | 0.83 | 22 | 5 | 4 | same |
| time_preference | 1.00 | 0.96 | 0.98 | 25 | 0 | 1 | +0.58 (major fix) |
| transport | 0.94 | 0.94 | 0.94 | 15 | 1 | 1 | same |
| Micro | 0.914 | 0.926 | 0.920 | +0.008 |
Wave 3 Fix Summary
time_preference-- F1 0.40 → 0.98 (+0.58)- Added
buổi sáng sớm→early_morningkeyword (was onlysáng sớm;buổi sángmatched first asmorningdue to length-priority) - VI compound scrubbing:
ăn sáng(breakfast) removed before morning check;chợ đêm(night market VI) removed before night check - EN compound scrubbing:
night market/tour/life/show/club/busremoved before night check - Fixed 4 gold annotation gaps in original samples (
buổi tối,hoàng hôn,buổi chiềucases where model was correct but gold was incomplete)
- Added
duration-- added EN natural-language week patternsa week,one week,two weeks,three weeks→{days:7/14/21, nights:6/13/20}
people-- improved edge-case coverage- VI:
(\d+) vợ chồng→{adults:2},(\d+) người.*có (\d+) trẻ em→ split - EN:
group of N→{adults:N},N of us→{adults:N},\bsolo\b(word boundary fix to avoid matching inside words)
- VI:
location-- FP blocklist extended- Added:
temple,shrine,sunrise,batu,anh,market,beach - Location FP count: 24 (before fix) → 7 (after blocklist + dual annotation fix)
- Added:
| Entity type | P | R | F1 | TP | FP | FN | vs Wave 1 F1 |
|---|---|---|---|---|---|---|---|
| budget | 1.00 | 0.82 | 0.90 | 9 | 0 | 2 | up from 0.80 (ruoi fix) |
| budget_priority | 0.89 | 0.73 | 0.80 | 8 | 1 | 3 | up from 0.74 (broader patterns) |
| cuisine | 0.91 | 0.91 | 0.91 | 10 | 1 | 1 | up from 0.80 (dietary overlap fix) |
| dietary | 0.94 | 0.88 | 0.91 | 15 | 1 | 2 | up from 0.88 (consumed-text fix) |
| duration | 0.97 | 0.92 | 0.94 | 60 | 2 | 5 | same |
| location | 0.91 | 0.96 | 0.94 | 104 | 10 | 4 | same |
| activity_preference | 0.85 | 0.96 | 0.90 | 22 | 4 | 1 | slight drop (harder samples) |
| travel_style | 0.94 | 0.88 | 0.91 | 29 | 2 | 4 | up from 0.86 |
| destination | 0.89 | 0.96 | 0.92 | 87 | 11 | 4 | same |
| transport | 0.94 | 0.94 | 0.94 | 15 | 1 | 1 | up from 0.90 (MRT VI fix) |
| origin | 0.94 | 0.83 | 0.88 | 15 | 1 | 3 | up from 0.73 |
| people | 0.82 | 0.86 | 0.84 | 18 | 4 | 3 | down (harder samples) |
| hotel_type | 0.78 | 1.00 | 0.88 | 18 | 5 | 0 | up from 0.80 (accommodation budget ctx) |
| time_preference | 1.00 | 0.96 | 0.98 | 25 | 0 | 1 | +0.58 (Wave 3 fix) |
Error Categories (Wave 2)
origin-- F1 0.88 (up from 0.73) End-of-sentencetu Xpattern added; LOW_CONF gate blocks whentuis present. 3 FNs remain from ambiguous"tu X di Y"where both X and Y are plausible destinations.hotel_type-- F1 0.88 (up from 0.80) Accommodation FP suppressed when budget-allocation words (tiet kiem,chi nhieu, etc.) present. ENbudgetFP suppressed when monetary amount is present. 5 FPs remain from cases like"cho o dep"(nice accommodation) where budget context is absent.cuisinevsdietary-- F1 0.91 (up from 0.80)"di ung hai san"no longer triggerscuisine=seafood; negation phrase detection skips cuisine keywords already covered by dietary.budget-- F1 0.90 (up from 0.80)"3 trieu ruoi"(3.5 million VND) pattern added. 2 FNs from compound expressions not yet covered.budget_priority-- F1 0.80 (up from 0.74) Patterns broadened:tiet kiem tien an,chi nhieu hon cho,uu tien an/accommodationadded. 3 FNs remain from unusual phrasing.time_preference-- F1 0.40 → 0.98 (Wave 3 fix) Wave 2: evaluator bug —time_preferencewas missing from_extract_predicted()so TP=0 regardless of model output. Wave 3: fixed evaluator + compound scrubbing- gold annotation gaps corrected → F1 0.98 on 25 gold annotations.
dietary-- F1 0.91 (up from 0.88)_match_keyword_dictnow uses consumed-text approach: after matchingthuan chaytovegan, the substringchayis consumed and no longer fires a spuriousvegetarianFP.transport-- F1 0.94 (up from 0.90)'mrt'/'gan mrt'added to Vietnamese transport keywords.
Coverage Summary
All 13 entity types exercised on 102 samples (Wave 3). Remaining weak points:
budget_priority(F1=0.80): 3 FNs -- uncommon phrasing not covered by regex patterns.people(F1=0.83): complex family + group-size texts expose edge cases.
3. Destination Recommender
Not evaluable with current data. No ground-truth user preference labels. Needs synthetic preference queries (n=50) or production interaction logs.
4. LLM (SeaLLMs-v3-7B-Chat)
LoRA adapters directory exists but is empty / untrained (Qwen-trained adapters incompatible with SeaLLMs — skipped). Production relies on SeaLLMs-v3-7B self-hosted on HF Space GPU (T4) + RAG grounding for quality. Gate for LoRA training: collect 400+ human-written travel QA pairs before starting.
5. Rule-Based Components
| Model | Current algorithm | Why not scored |
|---|---|---|
| trip_optimizer | Haversine + clustering | Deterministic given inputs |
| budget_optimizer | Static tier allocation | No ground truth |
| cuisine_recommender | Keyword filters | No labelled dataset |
| user_profiler | In-memory keyword bucketing | No persistence across sessions |
| route_optimizer | Haversine-only path | No ground truth |
| response_generator | 95% template | Not yet wired in evaluator |
6. Recommendations Ranked by ROI
| Priority | Change | Expected gain | Status |
|---|---|---|---|
| 1 | Produce held-out intent_test.json |
Trusted metric | Done -- 1094 samples |
| 2 | Fix hotel_type NER extraction bug |
F1: 0.40 to 0.88 | Done |
| 3 | OOD rejector for fallback/greeting |
greeting P: 0.59 to 0.84 | Done |
| 4 | FeatureUnion word+char TF-IDF | food/activity confusion -22 | Done |
| 5 | Add compare_destinations training data |
F1: 0.00 to 0.92 | Done -- 120 samples |
| 6 | Fix origin disambiguation |
F1: 0.73 to 0.88 | Done |
| 7 | Expand ner_eval.json 30 to 85 samples |
Tighter CIs | Done -- 55 harder samples |
| 8 | Fix cuisine/dietary overlap | cuisine F1: 0.80 to 0.91 | Done |
| 9 | Fix budget ruoi + budget_priority patterns | budget F1: 0.80 to 0.90 | Done |
| 10 | Expand time_preference gold fixture (10+ samples) |
F1: 0.40 to ~0.80 | Low cost |
| 11 | Fix people edge cases (complex family + group) |
F1: 0.84 to ~0.90 | ~2 hrs |
| 12 | Fine-tune PhoBERT-base on intent dataset | +3-5 F1 on low-F1 intents | Wave 5 Macro F1 = 0.8902 < 0.93 gate — evaluate |
| 13 | Collect 400+ human-written travel QA | Enables LLM LoRA training | chatbot-data-curator |
| 14 | Frontend interaction logging + recommender CF | Enables Precision@k | Frontend instrumentation |
Artefacts
app/data/datasets/ner_eval.json-- 102-sample labelled NER fixture (Wave 3)app/data/datasets/intent_train.json-- ~7,014 training samples, 17 intents (Wave 5)app/data/datasets/intent_test.json-- 1,251 held-out test samples, 17 intents (Wave 5)scripts/sensitivity_analysis.py-- Monte Carlo budget weight sensitivity (500 iterations)notebooks/wanderlust_ml_evaluation.ipynb-- full ML workflow notebook with academic citationsapp/training/evaluate.py-- reproducible evaluator