zenaight commited on
Commit
9900964
·
1 Parent(s): df9de2d

Refine intent classification and image request handling in AI chat

Browse files

- Enhanced the `extract_and_update_intent` function to streamline the classification of user requests, allowing for more efficient handling of inquiries related to property listings, images, and addresses.
- Updated the `handle_image_request` function to improve property selection based on user identifiers, ensuring that the AI can accurately respond to image requests with relevant property images.
- Adjusted the `receive_message` function to correctly identify image requests, enhancing the system's responsiveness to user inquiries about images and photos.
- These changes aim to improve user interaction by providing clearer and more accurate responses to property and image requests, ultimately enhancing the overall user experience.

Files changed (2) hide show
  1. ai_chat.py +80 -24
  2. main.py +1 -1
ai_chat.py CHANGED
@@ -284,7 +284,15 @@ async def extract_and_update_intent(state):
284
  # Check if user is asking for properties, images, or address (using AI classification)
285
  classification = state.get("classification")
286
  print(f"DEBUG - Intent update classification check: '{classification}'")
287
- if classification in ["search_listings", "request_images", "request_address"]:
 
 
 
 
 
 
 
 
288
  # User is asking for properties, images, or address - don't interrupt with preference questions
289
  print(f"DEBUG - User asking for {classification}, skipping preference questions")
290
  return {"response": None}
@@ -316,7 +324,11 @@ Classify the user's message into exactly one of:
316
  - request_address (user wants the address/location of a listing)
317
  - request_details (user wants other info like features, floorplan, video)
318
  - other (anything else)
319
- Return only the tag.
 
 
 
 
320
  Message: {user_message}
321
  """
322
  resp = await llm.ainvoke([{"role":"user","content":prompt}])
@@ -333,7 +345,15 @@ async def extract_and_search_properties(state):
333
  # Only search when the LLM tagged this as a listings request
334
  classification = state.get("classification")
335
  print(f"DEBUG - Property search classification check: '{classification}'")
336
- if classification not in ["search_listings", "request_images", "request_address"]:
 
 
 
 
 
 
 
 
337
  print(f"DEBUG - Skipping property search, classification is '{classification}'")
338
  return {"response": None}
339
 
@@ -450,36 +470,72 @@ async def handle_image_request(state):
450
  """
451
  user_message = state["user_message"].lower()
452
  props = state.get("properties", [])
 
453
 
454
- # Check if user is asking for images (more specific triggers)
455
- image_triggers = [
456
- "show me the images", "send me the images", "show me photos", "send me photos",
457
- "show me pictures", "send me pictures", "i want to see", "can i see",
458
- "image", "images", "photo", "photos", "picture", "pictures"
459
- ]
460
-
461
- # Check if any image trigger is in the message
462
- is_image_request = any(trigger in user_message for trigger in image_triggers)
463
 
464
- # Also check if user is asking about a specific property's images
465
- if not is_image_request and props:
466
- property_title = props[0].get("title", "").lower()
467
- if property_title and any(word in user_message for word in property_title.split()):
468
- is_image_request = any(trigger in user_message for trigger in ["image", "photo", "picture"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
 
470
- if not is_image_request or not props:
471
- return None
 
472
 
473
- # Get the first property (assuming user is asking about the most recent listing)
474
- property_data = props[0]
475
- images = property_data.get("images", [])
476
 
477
  if not images:
478
- return ["Sorry, I don't have any images available for this listing."]
 
479
 
480
  # Prepare image messages
481
  image_messages = []
482
- property_title = property_data.get("title", "This property")
483
 
484
  # Add a text message first to introduce the images
485
  image_messages.append(f"Here are the images for {property_title}:")
 
284
  # Check if user is asking for properties, images, or address (using AI classification)
285
  classification = state.get("classification")
286
  print(f"DEBUG - Intent update classification check: '{classification}'")
287
+
288
+ # Check if this is a request that should skip preference questions
289
+ skip_preferences = (
290
+ classification == "search_listings" or
291
+ classification.startswith("request_images") or
292
+ classification == "request_address"
293
+ )
294
+
295
+ if skip_preferences:
296
  # User is asking for properties, images, or address - don't interrupt with preference questions
297
  print(f"DEBUG - User asking for {classification}, skipping preference questions")
298
  return {"response": None}
 
324
  - request_address (user wants the address/location of a listing)
325
  - request_details (user wants other info like features, floorplan, video)
326
  - other (anything else)
327
+
328
+ If the user is asking for images and mentions a specific property (like "option 1", "the office", "warehouse", etc.),
329
+ extract the property identifier and return: request_images:IDENTIFIER
330
+
331
+ Return only the tag (and identifier if applicable).
332
  Message: {user_message}
333
  """
334
  resp = await llm.ainvoke([{"role":"user","content":prompt}])
 
345
  # Only search when the LLM tagged this as a listings request
346
  classification = state.get("classification")
347
  print(f"DEBUG - Property search classification check: '{classification}'")
348
+
349
+ # Check if classification matches our search categories
350
+ is_search_request = (
351
+ classification == "search_listings" or
352
+ classification.startswith("request_images") or
353
+ classification == "request_address"
354
+ )
355
+
356
+ if not is_search_request:
357
  print(f"DEBUG - Skipping property search, classification is '{classification}'")
358
  return {"response": None}
359
 
 
470
  """
471
  user_message = state["user_message"].lower()
472
  props = state.get("properties", [])
473
+ classification = state.get("classification", "")
474
 
475
+ # Check if this is an image request
476
+ if not classification.startswith("request_images") or not props:
477
+ return None
 
 
 
 
 
 
478
 
479
+ # Extract property identifier from classification if present
480
+ property_identifier = None
481
+ if ":" in classification:
482
+ property_identifier = classification.split(":", 1)[1].lower()
483
+
484
+ # Smart property selection based on AI classification
485
+ selected_property = None
486
+
487
+ if property_identifier:
488
+ # Method 1: Handle option numbers
489
+ if "option" in property_identifier:
490
+ # Extract numeric option
491
+ import re
492
+ numbers = re.findall(r'\d+', property_identifier)
493
+ if numbers:
494
+ option_num = int(numbers[0])
495
+ if 1 <= option_num <= len(props):
496
+ selected_property = props[option_num - 1]
497
+
498
+ # Method 2: Handle text-based identifiers
499
+ if not selected_property:
500
+ best_match_score = 0
501
+ for prop in props:
502
+ title = prop.get("title", "").lower()
503
+ location = prop.get("location", "").lower()
504
+ city = prop.get("city", "").lower()
505
+
506
+ # Check if identifier matches property keywords
507
+ score = 0
508
+ identifier_words = property_identifier.split()
509
+
510
+ for word in identifier_words:
511
+ if word in title:
512
+ score += 3 # Title matches are most important
513
+ if word in location:
514
+ score += 2
515
+ if word in city:
516
+ score += 1
517
+ # Check for property type keywords
518
+ if word in ["office", "warehouse", "space"] and word in title:
519
+ score += 2
520
+
521
+ if score > best_match_score:
522
+ best_match_score = score
523
+ selected_property = prop
524
 
525
+ # Fallback: use first property if no specific identifier
526
+ if not selected_property:
527
+ selected_property = props[0]
528
 
529
+ # Get images from selected property
530
+ images = selected_property.get("images", [])
 
531
 
532
  if not images:
533
+ property_title = selected_property.get("title", "this listing")
534
+ return [f"Sorry, I don't have any images available for {property_title}."]
535
 
536
  # Prepare image messages
537
  image_messages = []
538
+ property_title = selected_property.get("title", "This property")
539
 
540
  # Add a text message first to introduce the images
541
  image_messages.append(f"Here are the images for {property_title}:")
main.py CHANGED
@@ -76,7 +76,7 @@ async def receive_message(req: Request):
76
  classification = ai_result.get("classification", "")
77
  image_messages = None
78
 
79
- if classification == "request_images" or "image" in user_message.lower() or "photo" in user_message.lower():
80
  image_messages = await handle_image_request(state)
81
 
82
  if image_messages:
 
76
  classification = ai_result.get("classification", "")
77
  image_messages = None
78
 
79
+ if classification.startswith("request_images") or "image" in user_message.lower() or "photo" in user_message.lower():
80
  image_messages = await handle_image_request(state)
81
 
82
  if image_messages: