A newer version of the Gradio SDK is available: 6.13.0
QA Report β Hotel Search App
Plan-vs-Build Compliance Matrix
| # | Requirement | Plan | Build | Status |
|---|---|---|---|---|
| R1 | Free-form text input | gr.Textbox |
gr.Textbox, 5 lines, placeholder |
β Pass |
| R2 | Distinguish required vs preferred features | LLM parsing with keyword rules | PARSE_SYSTEM_PROMPT classifies by qualifier words |
β Pass |
| R3 | Extract dates, location, price, amenities | LLM β JSON schema | parse_request() β structured dict |
β Pass |
| R4 | Search for matching hotels | SerpAPI Google Search | search_hotels() via SerpAPI |
β Pass |
| R5 | Rank by required first, preferred as tie-breaker | +10 req, +3 pref, -5 missing | rank_results() implements exact scoring |
β Pass |
| R6 | Return name, description, price, score, direct link | Markdown cards | format_output() produces cards |
β Pass |
| R7 | Never show travel-agency links | Block list in utils.py | BLOCKED_DOMAINS set (40+ domains) |
β Pass |
| R8 | Clear message when no results | Warning with suggestions | format_output() handles empty list |
β Pass |
| R9 | Example queries in UI | Pre-filled examples | 5 examples in EXAMPLES list |
β Pass |
| R10 | Deploy on HF Spaces via Gradio | Gradio Blocks | gr.Blocks + HF README metadata |
β Pass |
Architecture Compliance
| Component | Plan | Build | Match |
|---|---|---|---|
app.py |
Gradio Blocks, Textbox, Markdown output, Examples | Implemented exactly | β |
search.py |
4-stage pipeline (parse β search β rank β format) | All 4 stages present | β |
utils.py |
Domain filtering, URL validation, price extraction | All implemented | β |
requirements.txt |
gradio, openai, serpapi | All listed with versions | β |
Issues Found and Resolved
Issue 1: Travel Agency Filter Gap (FIXED)
- Severity: Medium
- Description: Hotels from SerpAPI's
hotels_resultsblock were not filtered throughis_travel_agency(), only organic results were filtered. - Fix: Added
is_travel_agency(link)check to the hotels_results loop insearch_hotels().
Issue 2: Plan-Build Discrepancy on Default Feature Classification (FIXED)
- Severity: Low
- Description: Plan Section 7 said unqualified amenities default to "preferred," but the LLM prompt (correctly) treats them as "required." The assignment description supports the "required" default.
- Fix: Updated plan.md to match the build behavior.
Code Quality Assessment
| Aspect | Rating | Notes |
|---|---|---|
| Error handling | Good | API key checks, try/except blocks, graceful fallbacks |
| Input validation | Good | Empty input check, JSON parse fallback |
| Separation of concerns | Excellent | Clean split across app.py / search.py / utils.py |
| User experience | Good | Tips panel, example queries, interpretation display |
| Security | Good | API keys via env vars, not hardcoded |
| Code readability | Excellent | Clear docstrings, logical section dividers |
Edge Cases Considered
- β Empty input β friendly prompt message
- β Missing API keys β clear error with setup instructions
- β LLM returns invalid JSON β fallback to raw text as location
- β SerpAPI error β error message displayed
- β No matching hotels β suggestions for broadening search
- β Duplicate hotel names β deduplicated
Recommendations
- Future versions could add caching for repeated searches (mentioned in plan but not yet implemented).
- Consider adding a loading indicator/progress bar for long searches.
- The keyword-matching heuristic in
_feature_present()could be enhanced with semantic similarity.
QA Verdict: β PASS
The build faithfully implements the architecture plan. All 10 requirements are met. Two minor issues were found and fixed during QA review.