# 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."