zenaight commited on
Commit ·
b77c962
1
Parent(s): 2f6ba3c
Refine property search logic and enhance fallback responses
Browse files- Updated the `extract_and_search_properties` function to improve the property search process by implementing a multi-pass filtering strategy, allowing for more flexible search results based on user preferences.
- Enhanced fallback responses to provide clearer communication when no properties match the user's criteria, including suggestions for broader searches and notifications for future availability.
- Improved logging to track the filtering process and the state of the search, aiding in debugging and user experience.
- ai_chat.py +68 -27
ai_chat.py
CHANGED
|
@@ -2,7 +2,7 @@ from langgraph.graph import StateGraph, END
|
|
| 2 |
from langchain_core.runnables import RunnableLambda
|
| 3 |
from typing import TypedDict
|
| 4 |
from config import llm, OPENAI_API_KEY
|
| 5 |
-
from database import get_session_messages, save_message, update_user_persona, update_user_intent, search_properties
|
| 6 |
|
| 7 |
def chat_with_session_memory(state):
|
| 8 |
"""Chat function with session-based memory"""
|
|
@@ -272,45 +272,86 @@ async def extract_and_search_properties(state):
|
|
| 272 |
intent = state.get("intent", {})
|
| 273 |
print(f"Intent data: {intent}")
|
| 274 |
|
| 275 |
-
# Check if we have the minimum required
|
| 276 |
location = intent.get("location_preference")
|
| 277 |
-
budget = intent.get("budget")
|
| 278 |
-
size = intent.get("size_preference_sqm")
|
| 279 |
|
| 280 |
-
print(f"Location: {location}
|
| 281 |
|
| 282 |
-
if not location
|
| 283 |
-
# Missing
|
| 284 |
-
print(f"Missing
|
| 285 |
return {"response": None}
|
| 286 |
|
| 287 |
# Prepare filters for property search
|
| 288 |
-
filters = {
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
"
|
| 293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
|
| 295 |
print(f"Searching with filters: {filters}")
|
| 296 |
|
| 297 |
# Search for properties
|
| 298 |
properties = await search_properties(filters)
|
| 299 |
-
print(f"Found {len(properties)} properties: {properties}")
|
| 300 |
state["properties"] = properties
|
| 301 |
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
)
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
|
| 315 |
# --- Build LangGraph ---
|
| 316 |
graph = StateGraph(ChatState)
|
|
|
|
| 2 |
from langchain_core.runnables import RunnableLambda
|
| 3 |
from typing import TypedDict
|
| 4 |
from config import llm, OPENAI_API_KEY
|
| 5 |
+
from database import get_session_messages, save_message, update_user_persona, update_user_intent, search_properties, end_session
|
| 6 |
|
| 7 |
def chat_with_session_memory(state):
|
| 8 |
"""Chat function with session-based memory"""
|
|
|
|
| 272 |
intent = state.get("intent", {})
|
| 273 |
print(f"Intent data: {intent}")
|
| 274 |
|
| 275 |
+
# Check if we have the minimum required field for property search
|
| 276 |
location = intent.get("location_preference")
|
|
|
|
|
|
|
| 277 |
|
| 278 |
+
print(f"Location: {location}")
|
| 279 |
|
| 280 |
+
if not location:
|
| 281 |
+
# Missing location, skip property search
|
| 282 |
+
print(f"Missing location - skipping property search")
|
| 283 |
return {"response": None}
|
| 284 |
|
| 285 |
# Prepare filters for property search
|
| 286 |
+
filters = {"location_preference": location}
|
| 287 |
+
|
| 288 |
+
# Add budget if set
|
| 289 |
+
if intent.get("budget") is not None:
|
| 290 |
+
filters["budget"] = intent["budget"]
|
| 291 |
+
|
| 292 |
+
# Add size if set
|
| 293 |
+
if intent.get("size_preference_sqm") is not None:
|
| 294 |
+
filters["size_preference_sqm"] = intent["size_preference_sqm"]
|
| 295 |
+
|
| 296 |
+
# Add must-have features if set
|
| 297 |
+
must_have = intent.get("must_have", [])
|
| 298 |
+
if must_have and len(must_have) > 0:
|
| 299 |
+
filters["must_have"] = must_have
|
| 300 |
|
| 301 |
print(f"Searching with filters: {filters}")
|
| 302 |
|
| 303 |
# Search for properties
|
| 304 |
properties = await search_properties(filters)
|
|
|
|
| 305 |
state["properties"] = properties
|
| 306 |
|
| 307 |
+
# Pass 1: strict filters
|
| 308 |
+
if properties:
|
| 309 |
+
return {"response": None}
|
| 310 |
+
|
| 311 |
+
# Pass 2: drop must-haves
|
| 312 |
+
if "must_have" in filters:
|
| 313 |
+
filters2 = {k: v for k, v in filters.items() if k != "must_have"}
|
| 314 |
+
props2 = await search_properties(filters2)
|
| 315 |
+
if props2:
|
| 316 |
+
state["properties"] = props2
|
| 317 |
+
state["response"] = (
|
| 318 |
+
"I don't have an exact match with those features, "
|
| 319 |
+
"but here are listings matching your location, budget and size."
|
| 320 |
+
)
|
| 321 |
+
return state
|
| 322 |
+
|
| 323 |
+
# Pass 3: drop size
|
| 324 |
+
if "size_preference_sqm" in filters2:
|
| 325 |
+
filters3 = {k: v for k, v in filters2.items() if k != "size_preference_sqm"}
|
| 326 |
+
props3 = await search_properties(filters3)
|
| 327 |
+
if props3:
|
| 328 |
+
state["properties"] = props3
|
| 329 |
+
state["response"] = (
|
| 330 |
+
"I don't have that exact size, "
|
| 331 |
+
"but here are listings matching your location and budget."
|
| 332 |
+
)
|
| 333 |
+
return state
|
| 334 |
+
|
| 335 |
+
# Pass 4: drop budget
|
| 336 |
+
if "budget" in filters3:
|
| 337 |
+
filters4 = {k: v for k, v in filters3.items() if k != "budget"}
|
| 338 |
+
props4 = await search_properties(filters4)
|
| 339 |
+
if props4:
|
| 340 |
+
state["properties"] = props4
|
| 341 |
+
state["response"] = (
|
| 342 |
+
f"I don't have listings within your budget in {filters4['location_preference']}, "
|
| 343 |
+
"but here are some options in that area."
|
| 344 |
+
)
|
| 345 |
+
return state
|
| 346 |
+
|
| 347 |
+
# Final fallback: no listings at all
|
| 348 |
+
state["response"] = (
|
| 349 |
+
f"I don't have any listings right now matching your criteria. "
|
| 350 |
+
"I'll notify you as soon as something becomes available. "
|
| 351 |
+
"Feel free to reach out any time!"
|
| 352 |
+
)
|
| 353 |
+
await end_session(state["session_id"])
|
| 354 |
+
return state
|
| 355 |
|
| 356 |
# --- Build LangGraph ---
|
| 357 |
graph = StateGraph(ChatState)
|