help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
real-estate-bot
/
src
RSK World
real-estate-bot
Real Estate Bot - Python + Flask + OpenAI + SQLite + Property Search + AI Chatbot + Viewing Scheduler
src
  • __pycache__
  • __init__.py476 B
  • ai_recommendation_engine.py20.6 KB
  • app.py7.8 KB
  • blockchain_integration.py1.5 KB
  • chatbot.py15.5 KB
  • database.py18.4 KB
  • image_enhancer.py7.9 KB
  • multilang_support.py8.8 KB
  • neighborhood_analyzer.py6.1 KB
  • price_prediction_engine.py25.1 KB
  • property_search.py15.6 KB
  • virtual_tour_manager.py21.8 KB
  • voice_assistant.py27.6 KB
.gitignoreai_recommendation_engine.py
.gitignore
Raw Download
Find: Go to:
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# Project specific
real_estate_bot.db
*.db
*.sqlite
*.sqlite3

# Logs
logs/
*.log

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Temporary files
tmp/
temp/
*.tmp
*.temp

# Node modules (if using npm for frontend dependencies)
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Frontend build artifacts
static/dist/
static/build/

# Backup files
*.bak
*.backup
*.old

# Configuration files with sensitive data
config.json
secrets.json
credentials.json

# Upload directories
uploads/
media/
186 lines•2.5 KB
text
src/ai_recommendation_engine.py
Raw Download
Find: Go to:
"""
AI-Powered Property Recommendation Engine
Author: RSK World (https://rskworld.in)
Founded by: Molla Samser
Designer & Tester: Rima Khatun
Contact: info@rskworld.com, +91 93305 39277
Year: 2026
Description: Advanced AI recommendation system for personalized property suggestions
"""

import numpy as np
import pandas as pd
from typing import List, Dict, Any, Tuple
from datetime import datetime, timedelta
import json
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import StandardScaler
import pickle
import os

class AIRecommendationEngine:
    def __init__(self, database_manager):
        """
        Initialize AI Recommendation Engine
        
        Args:
            database_manager: Database manager instance
        """
        self.db_manager = database_manager
        self.user_profiles = {}
        self.property_features = {}
        self.tfidf_vectorizer = TfidfVectorizer(stop_words='english', max_features=1000)
        self.scaler = StandardScaler()
        self.model_path = 'data/recommendation_models'
        os.makedirs(self.model_path, exist_ok=True)
        
        # Load or train models
        self._load_or_train_models()
    
    def _load_or_train_models(self):
        """Load existing models or train new ones"""
        try:
            self._load_models()
        except:
            self._train_models()
            self._save_models()
    
    def _train_models(self):
        """Train recommendation models"""
        # Get all properties for feature extraction
        properties = self.db_manager.search_properties({})
        
        if not properties:
            return
        
        # Extract features for content-based filtering
        self._extract_property_features(properties)
        
        # Create TF-IDF matrix for property descriptions
        descriptions = [prop.get('description', '') + ' ' + 
                        prop.get('location', '') + ' ' + 
                        prop.get('property_type', '') 
                        for prop in properties]
        
        if descriptions:
            self.tfidf_matrix = self.tfidf_vectorizer.fit_transform(descriptions)
    
    def _extract_property_features(self, properties: List[Dict[str, Any]]):
        """Extract numerical features from properties"""
        features = []
        
        for prop in properties:
            feature_vector = [
                prop.get('price', 0) / 1000000,  # Price in millions
                prop.get('bedrooms', 0),
                prop.get('bathrooms', 0),
                prop.get('area_sqft', 0) / 1000,  # Area in thousands
                prop.get('year_built', 2020) - 2000,  # Age since 2000
                len(prop.get('amenities', [])),  # Number of amenities
                self._get_property_type_score(prop.get('property_type', '')),
                self._get_location_score(prop.get('location', ''))
            ]
            features.append(feature_vector)
            self.property_features[prop['id']] = feature_vector
        
        if features:
            self.feature_matrix = np.array(features)
            self.feature_matrix = self.scaler.fit_transform(self.feature_matrix)
    
    def _get_property_type_score(self, property_type: str) -> float:
        """Get numerical score for property type"""
        type_scores = {
            'apartment': 1.0,
            'house': 2.0,
            'villa': 3.0,
            'penthouse': 4.0,
            'condo': 1.5,
            'townhouse': 2.5
        }
        return type_scores.get(property_type.lower(), 1.0)
    
    def _get_location_score(self, location: str) -> float:
        """Get location desirability score"""
        premium_locations = [
            'mumbai', 'delhi', 'bangalore', 'pune', 'chennai',
            'gurgaon', 'noida', 'hyderabad', 'kolkata'
        ]
        
        location_lower = location.lower()
        for premium_loc in premium_locations:
            if premium_loc in location_lower:
                return 2.0
        return 1.0
    
    def get_personalized_recommendations(self, user_id: str, limit: int = 10) -> List[Dict[str, Any]]:
        """
        Get personalized property recommendations for a user
        
        Args:
            user_id: User identifier
            limit: Maximum number of recommendations
            
        Returns:
            List of recommended properties with scores
        """
        # Get user profile
        user_profile = self._get_user_profile(user_id)
        
        # Get user interaction history
        interaction_history = self._get_user_interactions(user_id)
        
        # Generate recommendations using multiple strategies
        content_based = self._content_based_recommendations(user_profile, limit)
        collaborative = self._collaborative_filtering_recommendations(user_id, limit)
        hybrid = self._hybrid_recommendations(content_based, collaborative, limit)
        
        return hybrid
    
    def _get_user_profile(self, user_id: str) -> Dict[str, Any]:
        """Get or create user profile"""
        if user_id not in self.user_profiles:
            # Create new user profile
            self.user_profiles[user_id] = {
                'preferences': {
                    'price_range': [0, 10000000],
                    'preferred_types': [],
                    'preferred_locations': [],
                    'bedrooms': 2,
                    'amenities': []
                },
                'behavior': {
                    'view_count': 0,
                    'inquiry_count': 0,
                    'appointment_count': 0,
                    'avg_session_duration': 0
                },
                'created_at': datetime.now()
            }
        
        return self.user_profiles[user_id]
    
    def _get_user_interactions(self, user_id: str) -> List[Dict[str, Any]]:
        """Get user interaction history"""
        # Get user's appointments, inquiries, and chat history
        appointments = self.db_manager.get_user_appointments(user_id)
        
        interactions = []
        for apt in appointments:
            interactions.append({
                'property_id': apt['property_id'],
                'interaction_type': 'appointment',
                'timestamp': apt.get('created_at', datetime.now()),
                'weight': 3.0  # High weight for appointments
            })
        
        return interactions
    
    def _content_based_recommendations(self, user_profile: Dict[str, Any], limit: int) -> List[Dict[str, Any]]:
        """Generate content-based recommendations"""
        preferences = user_profile['preferences']
        
        # Get all properties
        all_properties = self.db_manager.search_properties({})
        
        recommendations = []
        
        for prop in all_properties:
            score = self._calculate_content_score(prop, preferences)
            
            if score > 0:
                recommendations.append({
                    'property': prop,
                    'score': score,
                    'reason': self._get_content_reason(prop, preferences)
                })
        
        # Sort by score and return top recommendations
        recommendations.sort(key=lambda x: x['score'], reverse=True)
        return recommendations[:limit]
    
    def _calculate_content_score(self, property: Dict[str, Any], preferences: Dict[str, Any]) -> float:
        """Calculate content-based similarity score"""
        score = 0.0
        
        # Price range matching
        price = property.get('price', 0)
        price_min, price_max = preferences.get('price_range', [0, 10000000])
        if price_min <= price <= price_max:
            score += 0.3
        
        # Property type preference
        preferred_types = preferences.get('preferred_types', [])
        if property.get('property_type') in preferred_types:
            score += 0.25
        
        # Location preference
        preferred_locations = preferences.get('preferred_locations', [])
        property_location = property.get('location', '').lower()
        for loc in preferred_locations:
            if loc.lower() in property_location:
                score += 0.2
                break
        
        # Bedroom preference
        preferred_bedrooms = preferences.get('bedrooms', 2)
        if property.get('bedrooms') == preferred_bedrooms:
            score += 0.15
        
        # Amenities matching
        preferred_amenities = set(preferences.get('amenities', []))
        property_amenities = set(property.get('amenities', []))
        if preferred_amenities:
            amenity_score = len(preferred_amenities & property_amenities) / len(preferred_amenities)
            score += amenity_score * 0.1
        
        return score
    
    def _get_content_reason(self, property: Dict[str, Any], preferences: Dict[str, Any]) -> str:
        """Generate explanation for recommendation"""
        reasons = []
        
        price = property.get('price', 0)
        price_min, price_max = preferences.get('price_range', [0, 10000000])
        if price_min <= price <= price_max:
            reasons.append("fits your budget")
        
        preferred_types = preferences.get('preferred_types', [])
        if property.get('property_type') in preferred_types:
            reasons.append(f"{property.get('property_type')} type")
        
        preferred_bedrooms = preferences.get('bedrooms', 2)
        if property.get('bedrooms') == preferred_bedrooms:
            reasons.append(f"{preferred_bedrooms} bedrooms")
        
        if reasons:
            return "Recommended because it " + ", ".join(reasons)
        return "Matches your search criteria"
    
    def _collaborative_filtering_recommendations(self, user_id: str, limit: int) -> List[Dict[str, Any]]:
        """Generate collaborative filtering recommendations"""
        # Find similar users based on interaction patterns
        similar_users = self._find_similar_users(user_id)
        
        # Get properties liked by similar users
        recommendations = {}
        
        for similar_user_id, similarity_score in similar_users:
            user_interactions = self._get_user_interactions(similar_user_id)
            
            for interaction in user_interactions:
                property_id = interaction['property_id']
                weight = interaction['weight'] * similarity_score
                
                if property_id not in recommendations:
                    recommendations[property_id] = {
                        'property_id': property_id,
                        'score': 0,
                        'similar_users': []
                    }
                
                recommendations[property_id]['score'] += weight
                recommendations[property_id]['similar_users'].append(similar_user_id)
        
        # Convert to property objects and sort
        result = []
        for prop_id, rec_data in recommendations.items():
            property = self.db_manager.get_property_by_id(prop_id)
            if property:
                result.append({
                    'property': property,
                    'score': rec_data['score'],
                    'reason': f"Liked by {len(rec_data['similar_users'])} similar users"
                })
        
        result.sort(key=lambda x: x['score'], reverse=True)
        return result[:limit]
    
    def _find_similar_users(self, user_id: str, top_k: int = 10) -> List[Tuple[str, float]]:
        """Find users with similar preferences"""
        current_profile = self._get_user_profile(user_id)
        similarities = []
        
        for other_user_id, other_profile in self.user_profiles.items():
            if other_user_id == user_id:
                continue
            
            similarity = self._calculate_user_similarity(current_profile, other_profile)
            if similarity > 0:
                similarities.append((other_user_id, similarity))
        
        similarities.sort(key=lambda x: x[1], reverse=True)
        return similarities[:top_k]
    
    def _calculate_user_similarity(self, profile1: Dict[str, Any], profile2: Dict[str, Any]) -> float:
        """Calculate similarity between two user profiles"""
        similarity = 0.0
        
        # Compare price preferences
        price1_min, price1_max = profile1['preferences']['price_range']
        price2_min, price2_max = profile2['preferences']['price_range']
        
        price_overlap = min(price1_max, price2_max) - max(price1_min, price2_min)
        price_range1 = price1_max - price1_min
        price_range2 = price2_max - price2_min
        
        if price_range1 > 0 and price_range2 > 0:
            price_similarity = price_overlap / min(price_range1, price_range2)
            similarity += price_similarity * 0.3
        
        # Compare property types
        types1 = set(profile1['preferences']['preferred_types'])
        types2 = set(profile2['preferences']['preferred_types'])
        
        if types1 and types2:
            type_similarity = len(types1 & types2) / len(types1 | types2)
            similarity += type_similarity * 0.3
        
        # Compare bedroom preferences
        beds1 = profile1['preferences']['bedrooms']
        beds2 = profile2['preferences']['bedrooms']
        
        if beds1 == beds2:
            similarity += 0.2
        
        # Compare behavior patterns
        behavior1 = profile1['behavior']
        behavior2 = profile2['behavior']
        
        behavior_similarity = 0
        total_interactions = 0
        
        for key in ['view_count', 'inquiry_count', 'appointment_count']:
            val1 = behavior1.get(key, 0)
            val2 = behavior2.get(key, 0)
            
            if val1 > 0 and val2 > 0:
                behavior_similarity += min(val1, val2) / max(val1, val2)
                total_interactions += 1
        
        if total_interactions > 0:
            similarity += (behavior_similarity / total_interactions) * 0.2
        
        return similarity
    
    def _hybrid_recommendations(self, content_based: List[Dict], collaborative: List[Dict], limit: int) -> List[Dict[str, Any]]:
        """Combine content-based and collaborative recommendations"""
        # Weight the two approaches
        content_weight = 0.6
        collaborative_weight = 0.4
        
        # Combine recommendations
        combined = {}
        
        # Add content-based recommendations
        for rec in content_based:
            prop_id = rec['property']['id']
            combined[prop_id] = {
                'property': rec['property'],
                'score': rec['score'] * content_weight,
                'reason': rec['reason'],
                'approach': 'content-based'
            }
        
        # Add collaborative recommendations
        for rec in collaborative:
            prop_id = rec['property']['id']
            if prop_id in combined:
                # Combine scores
                combined[prop_id]['score'] += rec['score'] * collaborative_weight
                combined[prop_id]['reason'] += f" and {rec['reason']}"
                combined[prop_id]['approach'] = 'hybrid'
            else:
                combined[prop_id] = {
                    'property': rec['property'],
                    'score': rec['score'] * collaborative_weight,
                    'reason': rec['reason'],
                    'approach': 'collaborative'
                }
        
        # Sort by combined score
        result = list(combined.values())
        result.sort(key=lambda x: x['score'], reverse=True)
        
        return result[:limit]
    
    def update_user_preferences(self, user_id: str, interaction_data: Dict[str, Any]):
        """Update user preferences based on interactions"""
        profile = self._get_user_profile(user_id)
        
        # Update behavior metrics
        behavior = profile['behavior']
        interaction_type = interaction_data.get('type', 'view')
        
        if interaction_type == 'view':
            behavior['view_count'] += 1
        elif interaction_type == 'inquiry':
            behavior['inquiry_count'] += 1
        elif interaction_type == 'appointment':
            behavior['appointment_count'] += 1
        
        # Update preferences based on interaction
        property_data = interaction_data.get('property', {})
        
        # Update price range preference
        price = property_data.get('price', 0)
        current_min, current_max = profile['preferences']['price_range']
        
        if price > 0:
            # Gradually adjust price range based on viewed properties
            new_min = min(current_min, price * 0.8)
            new_max = max(current_max, price * 1.2)
            profile['preferences']['price_range'] = [new_min, new_max]
        
        # Update property type preference
        prop_type = property_data.get('property_type')
        if prop_type and prop_type not in profile['preferences']['preferred_types']:
            profile['preferences']['preferred_types'].append(prop_type)
        
        # Update location preference
        location = property_data.get('location', '')
        if location and location not in profile['preferences']['preferred_locations']:
            profile['preferences']['preferred_locations'].append(location)
        
        # Save updated profile
        self.user_profiles[user_id] = profile
    
    def get_trending_properties(self, limit: int = 10) -> List[Dict[str, Any]]:
        """Get trending properties based on recent interactions"""
        # This would typically analyze recent user interactions
        # For now, return properties with high engagement potential
        
        all_properties = self.db_manager.search_properties({})
        
        # Score properties based on various factors
        scored_properties = []
        
        for prop in all_properties:
            score = 0
            
            # Newer properties get higher scores
            if prop.get('year_built', 2020) >= 2022:
                score += 0.3
            
            # Properties with more amenities
            score += len(prop.get('amenities', [])) * 0.05
            
            # Premium locations
            if self._get_location_score(prop.get('location', '')) > 1.5:
                score += 0.2
            
            # Reasonable pricing (not too high, not too low)
            price_per_sqft = prop.get('price', 0) / max(prop.get('area_sqft', 1), 1)
            if 5000 <= price_per_sqft <= 15000:  # Reasonable range
                score += 0.2
            
            scored_properties.append({
                'property': prop,
                'score': score,
                'trend_reason': self._get_trend_reason(prop, score)
            })
        
        scored_properties.sort(key=lambda x: x['score'], reverse=True)
        return scored_properties[:limit]
    
    def _get_trend_reason(self, property: Dict[str, Any], score: float) -> str:
        """Get reason why property is trending"""
        reasons = []
        
        if property.get('year_built', 2020) >= 2022:
            reasons.append("newly built")
        
        if len(property.get('amenities', [])) > 5:
            reasons.append("well-equipped")
        
        if self._get_location_score(property.get('location', '')) > 1.5:
            reasons.append("prime location")
        
        if reasons:
            return f"Trending: {', '.join(reasons)}"
        return "Popular choice"
    
    def _save_models(self):
        """Save trained models"""
        models_data = {
            'user_profiles': self.user_profiles,
            'property_features': self.property_features,
            'tfidf_vectorizer': self.tfidf_vectorizer
        }
        
        with open(os.path.join(self.model_path, 'recommendation_models.pkl'), 'wb') as f:
            pickle.dump(models_data, f)
    
    def _load_models(self):
        """Load pre-trained models"""
        with open(os.path.join(self.model_path, 'recommendation_models.pkl'), 'rb') as f:
            models_data = pickle.load(f)
        
        self.user_profiles = models_data.get('user_profiles', {})
        self.property_features = models_data.get('property_features', {})
        self.tfidf_vectorizer = models_data.get('tfidf_vectorizer', self.tfidf_vectorizer)
522 lines•20.6 KB
python

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer