Combining AI Search with Structured Filters
AI search and manual filters work together. AI-extracted filters fill gaps, but explicit params always take priority.
Merge Logic
AI extracts: { city: "Goa", adults: 6, petFriendly: true }
Explicit params: { channelId: "B2C", adults: 4 }
─────────────────────────────────────────────────
Merged: { channelId: "B2C", city: "Goa", adults: 4, petFriendly: true }
↑ explicit wins
Use Cases
User types a query, then adjusts filters
- User: "Villas in Goa for 6 people"
- Frontend calls
/ai-search/intent→ getscity: Goa, adults: 6, propertyType: Villa - Frontend auto-fills filter UI
- User changes adults to 4 and adds "pet-friendly"
- Frontend calls
/ai-searchwith:{
"query": "Villas in Goa for 6 people",
"rawParams": [
{ "filterName": "adults", "filterValues": ["4"] },
{ "filterName": "petFriendly", "filterValues": ["true"] }
]
} - Merged:
city=Goa(AI) +adults=4(explicit) +petFriendly=true(explicit) +propertyType=Villa(AI)
Search bar + filter chips together
The AI search bar and the filter chips are not mutually exclusive. The AI understands intent, the filters refine it.
What Happens Internally
1. ListingRagSearchService.search(query)
→ Vector similarity + LLM rerank → ListingSearchIntent
2. mergeIntentWithParams(intent, explicitParams)
→ AI listingIds become "listingId" rawParam (scopes to relevant listings)
→ AI checkInDate, city, etc. fill missing rawParams
→ Explicit params override on conflict
3. MultiListingSearchService.search(mergedRequest)
→ Standard listing search runs with merged filters
→ PricingContextService applies traffic context
→ Full pricing, offers, cancellation plans