File size: 15,993 Bytes
877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 6e3dbdb 877e000 1049797 6e3dbdb 1049797 6e3dbdb 1049797 6e3dbdb 1049797 6e3dbdb 1049797 6e3dbdb 1049797 6e3dbdb 1049797 877e000 6e3dbdb 1049797 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# models/property_summary.py
from .model_loader import load_model
from .logging_config import logger
import json
import re
def validate_and_format_data(data):
"""Validate and format property data"""
if not isinstance(data, dict):
logger.warning(f"Input to validate_and_format_data is not a dict: {type(data)}")
data = {}
# Format square feet
try:
sq_ft = float(data.get('sq_ft', 0) or 0)
if sq_ft < 100: # If square feet seems too small, it might be in wrong unit
sq_ft *= 100 # Convert to square feet if it was in square meters
data['sq_ft'] = int(sq_ft)
except Exception as e:
logger.warning(f"Invalid sq_ft value: {data.get('sq_ft')}, error: {e}")
data['sq_ft'] = 0
# Format market value
try:
market_value = float(data.get('market_value', 0) or 0)
if market_value > 1000000000: # If value seems too high
market_value = market_value / 100 # Adjust if there's a decimal point issue
data['market_value'] = int(market_value)
except Exception as e:
logger.warning(f"Invalid market_value: {data.get('market_value')}, error: {e}")
data['market_value'] = 0
# Format amenities
if data.get('amenities'):
if isinstance(data['amenities'], str):
amenities = [a.strip() for a in data['amenities'].split(',') if a.strip()]
data['amenities'] = amenities
elif isinstance(data['amenities'], list):
data['amenities'] = [a.strip() for a in data['amenities'] if isinstance(a, str) and a.strip()]
else:
data['amenities'] = []
else:
data['amenities'] = []
# Ensure all expected keys exist
for key in ['bedrooms', 'bathrooms', 'year_built', 'parking_spaces', 'property_type', 'status', 'city', 'state', 'property_description', 'possession_date', 'nearby_landmarks']:
if key not in data:
data[key] = ''
return data
def format_price(price):
"""Format price in Indian currency format"""
try:
price = float(price)
if price >= 10000000: # 1 Crore
return f"₹{price/10000000:.2f} Cr"
elif price >= 100000: # 1 Lakh
return f"₹{price/100000:.2f} L"
else:
return f"₹{price:,.2f}"
except Exception as e:
logger.warning(f"Invalid price for formatting: {price}, error: {e}")
return f"₹0"
def create_property_prompt(data):
"""Create a comprehensive prompt for the SLM to generate property summary"""
# Build location string
location_parts = []
if data.get('address'):
location_parts.append(data['address'])
if data.get('city'):
location_parts.append(data['city'])
if data.get('state'):
location_parts.append(data['state'])
location = ', '.join(location_parts) if location_parts else 'Prime location'
# Build amenities string
amenities = data.get('amenities', [])
amenities_str = ', '.join(amenities[:5]) if amenities else 'Modern amenities'
# Build landmarks string
landmarks = data.get('nearby_landmarks', '')
if isinstance(landmarks, str) and landmarks:
landmarks_list = [l.strip() for l in landmarks.split(',') if l.strip()]
landmarks_str = ', '.join(landmarks_list[:3])
else:
landmarks_str = 'Convenient location'
# Create the prompt
prompt = f"""Generate a compelling 512-word property summary for an Indian real estate listing. Write in a warm, professional tone that appeals to potential buyers.
Property Information:
- Type: {data.get('property_type', 'Property')}
- Status: {data.get('status', 'Available')}
- Location: {location}
- Size: {data.get('sq_ft', '0')} sq. ft.
- Price: {format_price(data.get('market_value', '0'))}
- Bedrooms: {data.get('bedrooms', '0')}
- Bathrooms: {data.get('bathrooms', '0')}
- Year Built: {data.get('year_built', 'N/A')}
- Parking: {data.get('parking_spaces', '0')} spaces
- Possession: {data.get('possession_date', 'Immediate')}
- Amenities: {amenities_str}
- Nearby: {landmarks_str}
Description: {data.get('property_description', 'Beautiful property with modern features')}
Instructions:
1. Start with an engaging introduction about the property
2. Highlight key features and benefits
3. Emphasize location advantages
4. Mention pricing and value proposition
5. Include amenities and nearby facilities
6. End with a compelling call-to-action
7. Keep the tone warm, professional, and trustworthy
8. Use Indian real estate terminology appropriately
9. Make it exactly 512 words
Property Summary:"""
return prompt
def generate_dynamic_summary_with_slm(data):
"""Generate property summary using AI summarization model"""
try:
# Validate and format data
data = validate_and_format_data(data)
# Create the property description text
property_text = create_property_description_text(data)
# Try to use summarization model
try:
summarizer = load_model("summarization")
# Check if we have a proper summarization model
if hasattr(summarizer, 'fallback_used') and not summarizer.fallback_used:
# Use the actual AI model for summarization
result = summarizer(property_text, max_length=150, min_length=50, do_sample=False)
if isinstance(result, list) and len(result) > 0:
summary = result[0].get('summary_text', '')
if summary and len(summary.strip()) > 20:
return summary.strip()
# If AI model fails or returns poor results, use enhanced fallback
return generate_enhanced_fallback_summary(data)
except Exception as model_error:
logger.warning(f"Summarization model failed: {str(model_error)}")
return generate_enhanced_fallback_summary(data)
except Exception as e:
logger.error(f"Error in dynamic summary generation: {str(e)}")
return generate_enhanced_fallback_summary(data)
def create_property_description_text(data):
"""Create a comprehensive property description text for summarization"""
try:
# Build location string
location_parts = []
if data.get('address'):
location_parts.append(data['address'])
if data.get('city'):
location_parts.append(data['city'])
if data.get('state'):
location_parts.append(data['state'])
location = ', '.join(location_parts) if location_parts else 'Prime location'
# Build amenities string
amenities = data.get('amenities', [])
amenities_str = ', '.join(amenities[:5]) if amenities else 'Modern amenities'
# Build landmarks string
landmarks = data.get('nearby_landmarks', '')
if isinstance(landmarks, str) and landmarks:
landmarks_list = [l.strip() for l in landmarks.split(',') if l.strip()]
landmarks_str = ', '.join(landmarks_list[:3])
else:
landmarks_str = 'Convenient location'
# Create comprehensive property description
description_parts = [
f"This is a {data.get('property_type', 'property')} located in {location}.",
f"The property is currently {data.get('status', 'available')} for sale.",
f"It features {data.get('bedrooms', '0')} bedrooms and {data.get('bathrooms', '0')} bathrooms.",
f"The total area is {data.get('sq_ft', '0')} square feet.",
f"The property is priced at {format_price(data.get('market_value', '0'))}.",
f"It includes amenities such as {amenities_str}.",
f"The property is near {landmarks_str}.",
f"It was built in {data.get('year_built', 'recent years')}.",
f"The property offers {data.get('parking_spaces', '0')} parking spaces.",
f"This is an excellent investment opportunity in a prime location with modern facilities and strategic connectivity."
]
return " ".join(description_parts)
except Exception as e:
logger.error(f"Error creating property description text: {str(e)}")
return f"This is a {data.get('property_type', 'property')} located in {data.get('city', 'prime location')} with excellent features and amenities."
def generate_enhanced_fallback_summary(data):
"""Enhanced fallback summary generation with better AI-like text"""
try:
data = validate_and_format_data(data)
# Create a comprehensive and dynamic summary
summary_parts = []
# Introduction with property type and status
property_type = data.get('property_type', 'Property')
status = data.get('status', 'Available')
summary_parts.append(f"Discover this exceptional {property_type.lower()} that's currently {status.lower()} for sale.")
# Location information
location_parts = []
if data.get('city'):
location_parts.append(data['city'])
if data.get('state'):
location_parts.append(data['state'])
if location_parts:
summary_parts.append(f"This prime property is strategically located in {', '.join(location_parts)}, offering excellent connectivity and accessibility.")
# Key features section
features = []
if data.get('sq_ft'):
features.append(f"{data['sq_ft']} sq. ft. of thoughtfully designed space")
if data.get('bedrooms'):
features.append(f"{data['bedrooms']} spacious bedroom{'s' if str(data['bedrooms']) != '1' else ''}")
if data.get('bathrooms'):
features.append(f"{data['bathrooms']} modern bathroom{'s' if str(data['bathrooms']) != '1' else ''}")
if data.get('parking_spaces'):
features.append(f"{data['parking_spaces']} covered parking space{'s' if str(data['parking_spaces']) != '1' else ''}")
if features:
summary_parts.append(f"The property features {', '.join(features)}.")
# Pricing information
if data.get('market_value'):
price_str = format_price(data['market_value'])
summary_parts.append(f"Priced at {price_str}, this property offers excellent value for money and represents a sound investment opportunity.")
# Amenities and facilities
amenities = data.get('amenities', [])
if amenities:
amenities_str = ', '.join(amenities[:3])
summary_parts.append(f"The property includes modern amenities such as {amenities_str}.")
# Location benefits
landmarks = data.get('nearby_landmarks', '')
if landmarks:
summary_parts.append(f"Conveniently located near {landmarks}, this property offers easy access to essential facilities and transportation.")
# Closing statement
summary_parts.append("Perfect for families and investors alike, this property combines modern amenities with strategic location. Don't miss this opportunity to own a piece of prime real estate. Contact us today for a detailed viewing and exclusive offers.")
return " ".join(summary_parts)
except Exception as e:
logger.error(f"Error in enhanced fallback summary: {str(e)}")
return create_basic_summary(data)
def generate_property_summary(data):
"""Main function to generate property summary using AI model"""
try:
# Validate input data
if not data or not isinstance(data, dict):
return "A beautiful property with excellent features and prime location. Contact us for detailed information and exclusive offers."
# Try to use AI model for summary generation
try:
# Use the new dynamic SLM-based approach
summary = generate_dynamic_summary_with_slm(data)
# Ensure summary is a proper string
if not summary or not isinstance(summary, str):
summary = generate_enhanced_fallback_summary(data)
if not summary or not summary.strip():
summary = generate_enhanced_fallback_summary(data)
# Final fallback - always return something meaningful
if not summary or not summary.strip():
summary = create_basic_summary(data)
# Ensure it's a string and clean it up
summary = str(summary).strip()
if summary == '[object Object]' or summary == 'null' or summary == 'undefined':
summary = generate_enhanced_fallback_summary(data)
# If still no valid summary, create a basic one
if not summary or len(summary) < 50:
summary = create_basic_summary(data)
return summary
except Exception as e:
logger.error(f"Error in AI summary generation: {str(e)}")
return create_basic_summary(data)
except Exception as e:
logger.error(f"Error generating property summary: {str(e)}")
return create_basic_summary(data)
def create_basic_summary(data):
"""Create a basic summary even for invalid data"""
try:
# Extract basic information
property_type = data.get('property_type', 'Property')
city = data.get('city', 'Prime Location')
state = data.get('state', '')
bedrooms = data.get('bedrooms', '')
bathrooms = data.get('bathrooms', '')
sq_ft = data.get('sq_ft', '')
market_value = data.get('market_value', '')
# Create location string
location_parts = []
if city:
location_parts.append(city)
if state:
location_parts.append(state)
location = ', '.join(location_parts) if location_parts else 'Prime Location'
# Create features string
features = []
if bedrooms:
features.append(f"{bedrooms} bedroom{'s' if str(bedrooms) != '1' else ''}")
if bathrooms:
features.append(f"{bathrooms} bathroom{'s' if str(bathrooms) != '1' else ''}")
if sq_ft:
features.append(f"{sq_ft} sq. ft.")
features_str = ', '.join(features) if features else 'excellent features'
# Create price string
price_str = ""
if market_value:
try:
price_val = float(str(market_value).replace(',', '').replace('₹', ''))
if price_val > 0:
price_str = f" at ₹{price_val:,.0f}"
except:
pass
# Create property name - use a generic name if the original is invalid
property_name = data.get('property_name', '')
if property_name in ['2', '0', '1', 'test', 'sample', 'dummy'] or len(str(property_name)) < 3:
property_name = f"Beautiful {property_type}"
# Build the summary
summary_parts = [
f"Discover this exceptional {property_type.lower()} located in {location}.",
f"This property features {features_str} and offers excellent value for money.",
f"Perfect for families and investors alike, this property combines modern amenities with strategic location.",
f"Don't miss this opportunity to own a piece of prime real estate{price_str}.",
"Contact us today for a detailed viewing and exclusive offers."
]
return " ".join(summary_parts)
except Exception as e:
logger.error(f"Error creating basic summary: {str(e)}")
return "A beautiful property with excellent features and prime location. Contact us for detailed information and exclusive offers."
|