Replacing Filters With a Conversation, Without Letting It Make Things Up
Jul 2026 · 8 min read
Most property search UIs are a wall of filters — price range, bedrooms, location radius, amenities checkboxes — and they share a quiet assumption: that the user already knows how to categorize what they want before they've started looking. A lot of real intent doesn't arrive pre-categorized. "Somewhere quiet, close enough to a metro that I don't need a car, and I can stretch the budget a bit for the right place" isn't a filter. It's a paragraph, and forcing it into five dropdowns loses information the user actually gave you.
The AI concierge I built for an early-stage property platform takes that paragraph directly and maps it onto the platform's real, structured search — the same search every other part of the product uses. The interesting design problem wasn't "how do we call an LLM." It was "how do we let free text drive a real search without letting the model invent things that aren't there."
Two failure modes, and they pull in opposite directions
Get this wrong in one direction and the system under-constrains: a vague phrase gets mapped to an overly narrow, oddly specific filter combination the model inferred too confidently, and a search that should return dozens of reasonable matches returns nothing. Get it wrong in the other direction and it over-constrains: the model latches onto an incidental detail in the user's phrasing as if it were a hard requirement. "I'd like something near a park, not essential though" becomes a mandatory park-proximity filter, and a perfectly good listing three blocks from a park gets silently excluded because the model treated a preference as a constraint.
The fix: soft preferences for ranking, hard filters only for explicit constraints
The concierge doesn't translate free text directly into a single hard filter query. It separates what the user said into two categories: explicit, unambiguous constraints — a stated budget cap, a named city, a specific number of bedrooms — become real filters that exclude non-matching listings. Everything else — proximity preferences, ambiance, soft trade-offs like "can stretch the budget for the right place" — becomes a ranking signal applied on top of the filtered result set, not a filter itself.
{
hardFilters: { city: "Bengaluru", maxBudget: 45000, bedrooms: 2 },
rankingSignals: [
{ signal: "near_metro", weight: 0.6 },
{ signal: "quiet_area", weight: 0.4 },
],
}A listing that doesn't sit near a metro still shows up — it just ranks lower than one that does. That distinction is the whole design: a user's soft preferences should shape which results come first, never whether a reasonable result is silently excluded from the list entirely.
Retrieval and ranking, not generation
The concierge's job stops at mapping intent onto the platform's existing structured search and re-ranking real results. It never generates a property description, never fabricates details about a listing, never answers a question about a specific property from the model's general knowledge instead of the platform's actual data. Every result the concierge shows is a real listing that exists in the database, found through the same search path every other part of the product uses — the model's job is understanding intent and shaping relevance, not producing content.
This matters more here than in most GenAI features, because the cost of a hallucinated answer isn't "an awkward chatbot response." It's someone making a decision about housing based on a detail that was never true. Any AI feature sitting on top of real inventory data should be scoped to retrieval and ranking, not open generation — the moment a feature like this starts inventing facts about real listings is the moment it stops being a convenience and starts being actively misleading.
Its own service, on purpose
The concierge runs as its own discrete service on AWS, separate from the core listings API — the same logical-boundary-before-physical-boundary reasoning behind the rest of the platform, applied to a case where the physical separation earns its keep immediately. Model behavior, pricing, and capabilities shift on a completely different cadence than a CRUD API for property listings does. Keeping the concierge as its own deployable meant swapping prompting strategy, tuning the constraint-extraction logic, or reacting to a model provider change without touching — or risking — the booking and listings path the rest of the product depends on.
The actual lesson
The valuable part of a GenAI feature in a real product usually isn't the model call itself — it's the layer around it that decides what the model is allowed to be confident about. Treating everything the model infers as equally authoritative is how you get a feature that's exciting in a demo and frustrating in production. Treating explicit statements as constraints and everything else as a preference to rank by, and keeping the model strictly in a retrieval-and-ranking role over real data rather than a generation role, is what makes a conversational interface a genuine improvement over a filter form instead of just a more expensive way to occasionally return zero results.