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

Enhance property data handling and intent classification in AI chat

Browse files

- Updated the `chat_with_session_memory` function to include address data for AI use while ensuring it is not displayed in listings unless requested, improving user privacy and clarity.
- Modified the intent classification logic to recognize requests for addresses, allowing the system to respond appropriately to user inquiries about property locations.
- Adjusted the database schema in `supabase_setup.sql` to add an address field to the properties table and create an index for efficient querying, enhancing data organization and retrieval.
- These changes aim to improve user interaction by providing more comprehensive responses regarding property details while maintaining privacy and clarity in communication.

Files changed (2) hide show
  1. ai_chat.py +22 -9
  2. supabase_setup.sql +6 -1
ai_chat.py CHANGED
@@ -22,6 +22,8 @@ def chat_with_session_memory(state):
22
  props = state.get("properties", [])
23
  search_status = state.get("search_status_message", "")
24
 
 
 
25
  # Add system message with user context
26
  system_message = (
27
  f"Hello {user_info.get('name','there')}! You are a helpful and concise property agent. "
@@ -50,7 +52,7 @@ def chat_with_session_memory(state):
50
  if search_status:
51
  system_message += f"\n\n{search_status}"
52
 
53
- # Include property data if available (without image URLs)
54
  if props:
55
  system_message += "\n\nAvailable listings:\n"
56
  for p in props[:5]:
@@ -58,7 +60,7 @@ def chat_with_session_memory(state):
58
  f"- {p.get('title')} in {p.get('location')}, {p.get('city')}: "
59
  f"{p.get('size_sqm')} sqm, {p.get('price')} ({p.get('price_type')})\n"
60
  )
61
- # Include available data but NOT image URLs
62
  if p.get("listing_url"):
63
  system_message += f" URL: {p.get('listing_url')}\n"
64
  if p.get("features"):
@@ -67,9 +69,19 @@ def chat_with_session_memory(state):
67
  system_message += f" Floorplan: {p.get('floorplan_pdf')}\n"
68
  if p.get("video_url"):
69
  system_message += f" Video: {p.get('video_url')}\n"
70
- # Images are available but not shown - users must ask for them specifically
71
-
72
- system_message += "\n\nIMPORTANT: You may only reference listings passed in state['properties']. If the user requests more detail, respond with whatever is in that listing dict (URL, images, features, etc.). If information is not available, respond with 'For this listing, I don't have [specific detail] available right now'. When users ask for images, photos, or pictures, let them know that images are available and will be sent separately."
 
 
 
 
 
 
 
 
 
 
73
 
74
  # Build messages array with history
75
  messages = [{"role": "system", "content": system_message}]
@@ -269,11 +281,11 @@ async def extract_and_update_intent(state):
269
  missing = [f for f in intent_fields if state["intent"].get(f) is None]
270
  print(f"DEBUG - Missing intent fields: {missing}")
271
  if missing:
272
- # Check if user is asking for properties or images (using AI classification)
273
  classification = state.get("classification")
274
  print(f"DEBUG - Intent update classification check: '{classification}'")
275
- if classification in ["search_listings", "request_images"]:
276
- # User is asking for properties or images, don't interrupt with preference questions
277
  print(f"DEBUG - User asking for {classification}, skipping preference questions")
278
  return {"response": None}
279
 
@@ -301,6 +313,7 @@ async def classify_user_intent(state):
301
  Classify the user's message into exactly one of:
302
  - search_listings (user wants to see property listings)
303
  - request_images (user wants to see images/photos/pictures of a listing)
 
304
  - request_details (user wants other info like features, floorplan, video)
305
  - other (anything else)
306
  Return only the tag.
@@ -320,7 +333,7 @@ async def extract_and_search_properties(state):
320
  # Only search when the LLM tagged this as a listings request
321
  classification = state.get("classification")
322
  print(f"DEBUG - Property search classification check: '{classification}'")
323
- if classification not in ["search_listings", "request_images"]:
324
  print(f"DEBUG - Skipping property search, classification is '{classification}'")
325
  return {"response": None}
326
 
 
22
  props = state.get("properties", [])
23
  search_status = state.get("search_status_message", "")
24
 
25
+
26
+
27
  # Add system message with user context
28
  system_message = (
29
  f"Hello {user_info.get('name','there')}! You are a helpful and concise property agent. "
 
52
  if search_status:
53
  system_message += f"\n\n{search_status}"
54
 
55
+ # Include property data if available (without showing images or addresses in listings)
56
  if props:
57
  system_message += "\n\nAvailable listings:\n"
58
  for p in props[:5]:
 
60
  f"- {p.get('title')} in {p.get('location')}, {p.get('city')}: "
61
  f"{p.get('size_sqm')} sqm, {p.get('price')} ({p.get('price_type')})\n"
62
  )
63
+ # Include available data but NOT image URLs or addresses in public listings
64
  if p.get("listing_url"):
65
  system_message += f" URL: {p.get('listing_url')}\n"
66
  if p.get("features"):
 
69
  system_message += f" Floorplan: {p.get('floorplan_pdf')}\n"
70
  if p.get("video_url"):
71
  system_message += f" Video: {p.get('video_url')}\n"
72
+
73
+ # Include address data for AI use (but don't show in listings unless requested)
74
+ if p.get("address"):
75
+ system_message += f" Google Maps Address (for requests only): {p.get('address')}\n"
76
+
77
+ # Let AI know what additional info is available on request
78
+ available_extras = []
79
+ if p.get("images"): available_extras.append("images")
80
+ if p.get("address"): available_extras.append("address")
81
+ if available_extras:
82
+ system_message += f" Available on request: {', '.join(available_extras)}\n"
83
+
84
+ system_message += "\n\nIMPORTANT: You may only reference listings passed in state['properties']. When users ask for images, photos, or pictures, let them know that images are available and will be sent separately. When users ask for the address, location, or where a property is located, provide the Google Maps address from the property data. The addresses are Google Maps compatible for navigation. If information is not available, respond with 'For this listing, I don't have [specific detail] available right now'."
85
 
86
  # Build messages array with history
87
  messages = [{"role": "system", "content": system_message}]
 
281
  missing = [f for f in intent_fields if state["intent"].get(f) is None]
282
  print(f"DEBUG - Missing intent fields: {missing}")
283
  if missing:
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}
291
 
 
313
  Classify the user's message into exactly one of:
314
  - search_listings (user wants to see property listings)
315
  - request_images (user wants to see images/photos/pictures of a listing)
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.
 
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
 
supabase_setup.sql CHANGED
@@ -54,6 +54,7 @@ CREATE TABLE IF NOT EXISTS properties (
54
  description TEXT,
55
  location TEXT NOT NULL,
56
  city TEXT NOT NULL,
 
57
  size_sqm INTEGER,
58
  price INTEGER,
59
  price_type TEXT DEFAULT 'monthly',
@@ -86,6 +87,7 @@ CREATE INDEX IF NOT EXISTS idx_user_intents_updated_at ON user_intents(updated_a
86
  CREATE INDEX IF NOT EXISTS idx_properties_is_active ON properties(is_active);
87
  CREATE INDEX IF NOT EXISTS idx_properties_city ON properties(city);
88
  CREATE INDEX IF NOT EXISTS idx_properties_location ON properties(location);
 
89
  CREATE INDEX IF NOT EXISTS idx_properties_price ON properties(price);
90
  CREATE INDEX IF NOT EXISTS idx_properties_size_sqm ON properties(size_sqm);
91
  CREATE INDEX IF NOT EXISTS idx_properties_is_featured ON properties(is_featured);
@@ -166,12 +168,13 @@ CREATE TRIGGER update_properties_updated_at
166
  EXECUTE FUNCTION update_updated_at_column();
167
 
168
  -- Insert some sample properties for testing
169
- INSERT INTO properties (title, description, location, city, size_sqm, price, price_type, listing_url, images, features, is_active, is_featured) VALUES
170
  (
171
  '2-3 person office space in Edenvale',
172
  'Modern office space perfect for small teams',
173
  'Edenvale',
174
  'Johannesburg',
 
175
  40,
176
  15000,
177
  'monthly',
@@ -186,6 +189,7 @@ INSERT INTO properties (title, description, location, city, size_sqm, price, pri
186
  'Large warehouse space with loading dock',
187
  'Sandton',
188
  'Johannesburg',
 
189
  200,
190
  25000,
191
  'monthly',
@@ -200,6 +204,7 @@ INSERT INTO properties (title, description, location, city, size_sqm, price, pri
200
  'Cozy office space in the heart of Cape Town',
201
  'CBD',
202
  'Cape Town',
 
203
  25,
204
  12000,
205
  'monthly',
 
54
  description TEXT,
55
  location TEXT NOT NULL,
56
  city TEXT NOT NULL,
57
+ address TEXT,
58
  size_sqm INTEGER,
59
  price INTEGER,
60
  price_type TEXT DEFAULT 'monthly',
 
87
  CREATE INDEX IF NOT EXISTS idx_properties_is_active ON properties(is_active);
88
  CREATE INDEX IF NOT EXISTS idx_properties_city ON properties(city);
89
  CREATE INDEX IF NOT EXISTS idx_properties_location ON properties(location);
90
+ CREATE INDEX IF NOT EXISTS idx_properties_address ON properties(address);
91
  CREATE INDEX IF NOT EXISTS idx_properties_price ON properties(price);
92
  CREATE INDEX IF NOT EXISTS idx_properties_size_sqm ON properties(size_sqm);
93
  CREATE INDEX IF NOT EXISTS idx_properties_is_featured ON properties(is_featured);
 
168
  EXECUTE FUNCTION update_updated_at_column();
169
 
170
  -- Insert some sample properties for testing
171
+ INSERT INTO properties (title, description, location, city, address, size_sqm, price, price_type, listing_url, images, features, is_active, is_featured) VALUES
172
  (
173
  '2-3 person office space in Edenvale',
174
  'Modern office space perfect for small teams',
175
  'Edenvale',
176
  'Johannesburg',
177
+ 'Greenstone Shopping Centre, 1 Emerald Boulevard, Modderfontein, 1609, South Africa',
178
  40,
179
  15000,
180
  'monthly',
 
189
  'Large warehouse space with loading dock',
190
  'Sandton',
191
  'Johannesburg',
192
+ 'Sandton City Shopping Centre, 83 Rivonia Rd, Sandhurst, Sandton, 2196, South Africa',
193
  200,
194
  25000,
195
  'monthly',
 
204
  'Cozy office space in the heart of Cape Town',
205
  'CBD',
206
  'Cape Town',
207
+ 'V&A Waterfront, Dock Rd, Cape Town, 8001, South Africa',
208
  25,
209
  12000,
210
  'monthly',