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
voice_assistant.py
src/voice_assistant.py
Raw Download
Find: Go to:
"""
Voice Assistant Integration for Hands-Free Operation
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 voice assistant with speech recognition and natural language processing
"""

import os
import json
import asyncio
import threading
from typing import Dict, Any, Optional, Callable, List
from datetime import datetime
import time
try:
    import speech_recognition as sr
    import pyttsx3
except ImportError as e:
    print(f"Voice assistant dependencies not available: {e}")
    sr = None
    pyttsx3 = None

try:
    from queue import Queue
except ImportError:
    from collections import deque as Queue

class VoiceAssistant:
    def __init__(self, chatbot_instance, database_manager):
        """
        Initialize Voice Assistant
        
        Args:
            chatbot_instance: Main chatbot instance
            database_manager: Database manager instance
        """
        self.chatbot = chatbot_instance
        self.db_manager = database_manager
        
        # Check if voice dependencies are available
        if sr is None or pyttsx3 is None:
            print("Voice assistant features disabled - missing dependencies")
            self.voice_available = False
        else:
            self.voice_available = True
            try:
                # Speech recognition setup
                self.recognizer = sr.Recognizer()
                self.microphone = sr.Microphone()
                
                # Text-to-speech setup
                self.tts_engine = pyttsx3.init()
                self._configure_tts()
            except Exception as e:
                print(f"Error initializing voice features: {e}")
                self.voice_available = False
                self.recognizer = None
                self.microphone = None
                self.tts_engine = None
        
        # Voice commands and responses
        self.voice_commands = self._initialize_voice_commands()
        self.command_queue = Queue()
        
        # State management
        self.is_listening = False
        self.is_speaking = False
        self.current_user_id = 'voice_user'
        self.conversation_context = []
        
        # Audio settings
        self.wake_word = "hey real estate"
        self.confidence_threshold = 0.7
        self.silence_timeout = 2.0
        
        # Threading for continuous listening
        self.listening_thread = None
        self.processing_thread = None
        
    def _configure_tts(self):
        """Configure text-to-speech engine"""
        if not self.tts_engine:
            return
        
        try:
            voices = self.tts_engine.getProperty('voices')
            
            # Try to set a female voice (more natural for assistant)
            if voices:
                for voice in voices:
                    if 'female' in voice.name.lower():
                        self.tts_engine.setProperty('voice', voice.id)
                        break
            
            # Set speech rate and volume
            self.tts_engine.setProperty('rate', 180)  # Words per minute
            self.tts_engine.setProperty('volume', 0.9)
        except Exception as e:
            print(f"Error configuring TTS: {e}")
    
    def _initialize_voice_commands(self) -> Dict[str, Dict[str, Any]]:
        """Initialize voice command patterns"""
        return {
            'property_search': {
                'patterns': [
                    r'search for (.+)',
                    r'find me (.+)',
                    r'show me (.+)',
                    r'looking for (.+)',
                    r'i want (.+)'
                ],
                'action': 'search_properties',
                'response': 'Searching for properties that match your criteria...'
            },
            'property_details': {
                'patterns': [
                    r'tell me about property (\d+)',
                    r'show details of property (\d+)',
                    r'information about property (\d+)',
                    r'what about property (\d+)'
                ],
                'action': 'get_property_details',
                'response': 'Getting property details for you...'
            },
            'schedule_viewing': {
                'patterns': [
                    r'schedule a viewing',
                    r'book an appointment',
                    r'arrange a visit',
                    r'i want to see',
                    r'schedule visit'
                ],
                'action': 'schedule_appointment',
                'response': 'I can help you schedule a property viewing. Which property would you like to visit?'
            },
            'price_prediction': {
                'patterns': [
                    r'predict price',
                    r'price forecast',
                    r'how much will it be worth',
                    r'future price',
                    r'price prediction'
                ],
                'action': 'predict_price',
                'response': 'I can analyze price trends and make predictions. Which property are you interested in?'
            },
            'market_analysis': {
                'patterns': [
                    r'market analysis',
                    r'market trends',
                    r'how is the market',
                    r'market conditions',
                    r'real estate market'
                ],
                'action': 'market_analysis',
                'response': 'Analyzing current market conditions and trends...'
            },
            'virtual_tour': {
                'patterns': [
                    r'virtual tour',
                    r'360 view',
                    r'show me around',
                    r'take a tour',
                    r'virtual viewing'
                ],
                'action': 'start_virtual_tour',
                'response': 'Starting virtual tour. You can navigate through the property using voice commands.'
            },
            'recommendations': {
                'patterns': [
                    r'recommend',
                    r'suggest',
                    r'show me similar',
                    r'what do you recommend',
                    r'find similar'
                ],
                'action': 'get_recommendations',
                'response': 'Analyzing your preferences to find the best property recommendations...'
            },
            'help': {
                'patterns': [
                    r'help',
                    r'what can you do',
                    r'commands',
                    r'how to use',
                    r'instructions'
                ],
                'action': 'show_help',
                'response': 'I can help you search properties, schedule viewings, get price predictions, and more. Just say what you need!'
            },
            'stop': {
                'patterns': [
                    r'stop',
                    r'cancel',
                    r'never mind',
                    r'forget it',
                    r'dismiss'
                ],
                'action': 'stop_action',
                'response': 'Okay, I\'ve cancelled that action.'
            }
        }
    
    def start_listening(self):
        """Start continuous voice listening"""
        if not self.voice_available or not self.recognizer or not self.microphone:
            print("Voice assistant not available - missing dependencies")
            return
        
        if self.is_listening:
            return
        
        self.is_listening = True
        self.listening_thread = threading.Thread(target=self._continuous_listen, daemon=True)
        self.processing_thread = threading.Thread(target=self._process_commands, daemon=True)
        
        self.listening_thread.start()
        self.processing_thread.start()
        
        self.speak("Voice assistant activated. Say 'Hey Real Estate' to start.")
    
    def stop_listening(self):
        """Stop voice listening"""
        self.is_listening = False
        if self.listening_thread:
            self.listening_thread.join(timeout=1)
        if self.processing_thread:
            self.processing_thread.join(timeout=1)
    
    def _continuous_listen(self):
        """Continuous background listening"""
        if not self.voice_available or not self.recognizer or not self.microphone:
            return
        
        try:
            with self.microphone as source:
                self.recognizer.adjust_for_ambient_noise(source, duration=1)
        except Exception as e:
            print(f"Error adjusting for ambient noise: {e}")
            return
        
        while self.is_listening:
            try:
                # Listen for wake word or direct command
                with self.microphone as source:
                    audio = self.recognizer.listen(source, timeout=1, phrase_time_limit=5)
                
                # Try to recognize speech
                text = self._recognize_speech(audio)
                
                if text:
                    text = text.lower().strip()
                    
                    # Check for wake word
                    if self.wake_word in text:
                        self.speak("I'm listening. How can I help you?")
                        # Listen for actual command
                        command_audio = self._listen_for_command()
                        if command_audio:
                            command_text = self._recognize_speech(command_audio)
                            if command_text:
                                self.command_queue.put(command_text)
                    else:
                        # Direct command without wake word
                        self.command_queue.put(text)
                
            except sr.WaitTimeoutError:
                continue
            except Exception as e:
                print(f"Listening error: {e}")
                time.sleep(0.1)
    
    def _listen_for_command(self) -> Optional[Any]:
        """Listen for a specific command after wake word"""
        if not self.voice_available or not self.recognizer or not self.microphone:
            return None
            
        try:
            with self.microphone as source:
                return self.recognizer.listen(source, timeout=5, phrase_time_limit=10)
        except sr.WaitTimeoutError:
            return None
        except Exception as e:
            print(f"Error listening for command: {e}")
            return None
    
    def _recognize_speech(self, audio: Any) -> Optional[str]:
        """Recognize speech from audio data"""
        if not self.voice_available:
            return None
        try:
            # Try Google Speech Recognition first
            text = self.recognizer.recognize_google(audio, show_all=False)
            return text
        except sr.UnknownValueError:
            # Try Sphinx as fallback
            try:
                text = self.recognizer.recognize_sphinx(audio)
                return text
            except sr.UnknownValueError:
                return None
        except sr.RequestError as e:
            print(f"Speech recognition error: {e}")
            return None
    
    def _process_commands(self):
        """Process voice commands from queue"""
        while self.is_listening:
            try:
                if not self.command_queue.empty():
                    command = self.command_queue.get(timeout=0.1)
                    self._handle_voice_command(command)
                else:
                    time.sleep(0.1)
            except Exception as e:
                print(f"Command processing error: {e}")
    
    def _handle_voice_command(self, command: str):
        """Handle recognized voice command"""
        command = command.lower().strip()
        
        # Add to conversation context
        self.conversation_context.append({
            'type': 'user',
            'text': command,
            'timestamp': datetime.now().isoformat()
        })
        
        # Match command against patterns
        matched_command = self._match_command(command)
        
        if matched_command:
            action = matched_command['action']
            self.speak(matched_command['response'])
            
            # Execute the action
            self._execute_action(action, command, matched_command)
        else:
            # No specific command matched, pass to general chatbot
            self._handle_general_command(command)
    
    def _match_command(self, command: str) -> Optional[Dict[str, Any]]:
        """Match command against voice command patterns"""
        import re
        
        for command_name, command_data in self.voice_commands.items():
            for pattern in command_data['patterns']:
                match = re.search(pattern, command)
                if match:
                    return {
                        'name': command_name,
                        'action': command_data['action'],
                        'response': command_data['response'],
                        'match': match,
                        'pattern': pattern
                    }
        
        return None
    
    def _execute_action(self, action: str, command: str, matched_command: Dict[str, Any]):
        """Execute the matched voice command action"""
        try:
            if action == 'search_properties':
                self._handle_property_search(command, matched_command)
            elif action == 'get_property_details':
                self._handle_property_details(matched_command)
            elif action == 'schedule_appointment':
                self._handle_schedule_appointment()
            elif action == 'predict_price':
                self._handle_price_prediction()
            elif action == 'market_analysis':
                self._handle_market_analysis()
            elif action == 'start_virtual_tour':
                self._handle_virtual_tour()
            elif action == 'get_recommendations':
                self._handle_recommendations()
            elif action == 'show_help':
                self._handle_help()
            elif action == 'stop_action':
                self._handle_stop()
            
        except Exception as e:
            self.speak(f"Sorry, I encountered an error: {str(e)}")
    
    def _handle_property_search(self, command: str, matched_command: Dict[str, Any]):
        """Handle property search voice command"""
        if not self.chatbot or not hasattr(self.chatbot, 'property_search'):
            self.speak("I'm sorry, the property search feature is not available right now.")
            return
        
        # Extract search criteria from command
        criteria = self._extract_search_criteria(command)
        
        # Perform search
        properties = self.chatbot.property_search.search(criteria)
        
        if properties:
            response = f"I found {len(properties)} properties matching your criteria. "
            
            # Describe top 3 properties
            for i, prop in enumerate(properties[:3]):
                response += f"Property {i+1}: {prop.get('title', 'Property')} in {prop.get('location', 'Unknown')}, "
                response += f"priced at ₹{prop.get('price', 0):,}. "
            
            self.speak(response)
        else:
            self.speak("I couldn't find any properties matching your criteria. Would you like to try different search terms?")
    
    def _handle_property_details(self, matched_command: Dict[str, Any]):
        """Handle property details voice command"""
        if not self.chatbot or not hasattr(self.chatbot, 'property_search'):
            self.speak("I'm sorry, the property details feature is not available right now.")
            return
        
        match = matched_command['match']
        property_id = int(match.group(1))
        
        property_data = self.chatbot.property_search.get_property_by_id(property_id)
        
        if property_data:
            response = f"Property {property_id}: {property_data.get('title', 'Property')}. "
            response += f"Located in {property_data.get('location', 'Unknown')}. "
            response += f"It has {property_data.get('bedrooms', 0)} bedrooms and {property_data.get('bathrooms', 0)} bathrooms. "
            response += f"The area is {property_data.get('area_sqft', 0)} square feet. "
            response += f"Priced at ₹{property_data.get('price', 0):,}. "
            
            amenities = property_data.get('amenities', [])
            if amenities:
                response += f"Amenities include {', '.join(amenities[:3])}."
            
            self.speak(response)
        else:
            self.speak(f"Sorry, I couldn't find property {property_id}.")
    
    def _handle_schedule_appointment(self):
        """Handle appointment scheduling voice command"""
        self.speak("To schedule a viewing, I'll need some information. "
                   "First, what's the property ID you'd like to visit?")
        
        # This would start a conversational flow to collect appointment details
        # For now, provide guidance
        self.speak("You can also schedule appointments through the web interface for easier data entry.")
    
    def _handle_price_prediction(self):
        """Handle price prediction voice command"""
        self.speak("I can provide price predictions and market analysis. "
                   "Please specify which property you'd like me to analyze, or tell me a location for market trends.")
    
    def _handle_market_analysis(self):
        """Handle market analysis voice command"""
        self.speak("I can analyze market conditions for any location. "
                   "Which city or area would you like me to analyze?")
    
    def _handle_virtual_tour(self):
        """Handle virtual tour voice command"""
        self.speak("Virtual tours are available for select properties. "
                   "Please specify which property you'd like to tour virtually.")
    
    def _handle_recommendations(self):
        """Handle property recommendations"""
        if not self.chatbot or not hasattr(self.chatbot, 'property_search'):
            self.speak("I'm sorry, the recommendations feature is not available right now.")
            return
        
        # Get personalized recommendations
        recommendations = self.chatbot.property_search.get_property_recommendations({})
        
        if recommendations:
            response = f"Based on your preferences, I recommend {len(recommendations)} properties. "
            
            for i, prop in enumerate(recommendations[:3]):
                response += f"Recommendation {i+1}: {prop.get('title', 'Property')} in {prop.get('location', 'Unknown')}. "
            
            self.speak(response)
        else:
            self.speak("I need more information about your preferences to provide recommendations.")
    
    def _handle_help(self):
        """Handle help command"""
        help_text = """
        I can help you with several voice commands:
        
        Say "search for" followed by your criteria to find properties.
        Say "tell me about property" followed by the property number for details.
        Say "schedule a viewing" to book an appointment.
        Say "predict price" for price analysis.
        Say "market analysis" for market trends.
        Say "virtual tour" for 360-degree property tours.
        Say "recommend" for personalized suggestions.
        Say "help" to hear these options again.
        """
        
        self.speak(help_text)
    
    def _handle_stop(self):
        """Handle stop command"""
        self.speak("Current action cancelled.")
    
    def _handle_general_command(self, command: str):
        """Handle commands that don't match specific patterns"""
        if not self.chatbot:
            self.speak("I'm sorry, the chatbot is not available right now. Please try again later.")
            return
        
        # Pass to main chatbot
        try:
            response = self.chatbot.process_message(command, self.current_user_id)
            self.speak(response)
        except Exception as e:
            self.speak("I'm sorry, I didn't understand that. Could you please rephrase?")
    
    def _extract_search_criteria(self, command: str) -> Dict[str, Any]:
        """Extract search criteria from voice command"""
        criteria = {}
        
        # Extract location
        locations = ['mumbai', 'delhi', 'bangalore', 'pune', 'chennai', 'gurgaon', 'noida', 'hyderabad', 'kolkata']
        for location in locations:
            if location in command.lower():
                criteria['location'] = location
                break
        
        # Extract property type
        property_types = {
            'apartment': ['apartment', 'flat'],
            'house': ['house', 'home', 'villa', 'bungalow'],
            'condo': ['condo', 'condominium']
        }
        
        for prop_type, keywords in property_types.items():
            if any(keyword in command.lower() for keyword in keywords):
                criteria['property_type'] = prop_type
                break
        
        # Extract bedrooms
        import re
        bedroom_match = re.search(r'(\d+)\s*(?:bedroom|bed|bhk)', command.lower())
        if bedroom_match:
            criteria['bedrooms'] = int(bedroom_match.group(1))
        
        # Extract price range
        price_patterns = [
            (r'under\s*(?:₹|rs|rupees)?\s*([\d,]+)', 'price_max'),
            (r'below\s*(?:₹|rs|rupees)?\s*([\d,]+)', 'price_max'),
            (r'between\s*(?:₹|rs|rupees)?\s*([\d,]+)\s*and\s*(?:₹|rs|rupees)?\s*([\d,]+)', 'price_range'),
            (r'over\s*(?:₹|rs|rupees)?\s*([\d,]+)', 'price_min')
        ]
        
        for pattern, price_type in price_patterns:
            match = re.search(pattern, command.lower())
            if match:
                if price_type == 'price_range':
                    criteria['price_min'] = int(match.group(1).replace(',', ''))
                    criteria['price_max'] = int(match.group(2).replace(',', ''))
                else:
                    price_value = int(match.group(1).replace(',', ''))
                    if price_type == 'price_min':
                        criteria['price_min'] = price_value
                    else:
                        criteria['price_max'] = price_value
                break
        
        return criteria
    
    def speak(self, text: str):
        """Convert text to speech"""
        if not self.voice_available:
            print(f"Voice: {text}")  # Fallback to print if voice not available
            return
        
        if self.is_speaking:
            return  # Don't interrupt current speech
        
        def speak_thread():
            self.is_speaking = True
            try:
                if self.tts_engine:
                    self.tts_engine.say(text)
                    self.tts_engine.runAndWait()
            except Exception as e:
                print(f"Speech error: {e}")
            finally:
                self.is_speaking = False
        
        # Run speech in separate thread
        speech_thread = threading.Thread(target=speak_thread, daemon=True)
        speech_thread.start()
    
    def get_voice_commands_list(self) -> Dict[str, List[str]]:
        """Get list of available voice commands"""
        commands = {}
        for command_name, command_data in self.voice_commands.items():
            commands[command_name] = command_data['patterns']
        
        return commands
    
    def set_voice_settings(self, rate: int = None, volume: float = None, voice_index: int = None):
        """Update voice settings"""
        if not self.voice_available or not self.tts_engine:
            return
        
        if rate is not None:
            self.tts_engine.setProperty('rate', rate)
        
        if volume is not None:
            self.tts_engine.setProperty('volume', volume)
        
        if voice_index is not None:
            voices = self.tts_engine.getProperty('voices')
            if voices and 0 <= voice_index < len(voices):
                self.tts_engine.setProperty('voice', voices[voice_index].id)
    
    def get_conversation_history(self) -> List[Dict[str, Any]]:
        """Get voice conversation history"""
        return self.conversation_context.copy()
    
    def clear_conversation_history(self):
        """Clear conversation history"""
        self.conversation_context.clear()
        self.speak("Conversation history cleared.")


# Voice command processor for advanced features
class AdvancedVoiceProcessor:
    """Advanced voice processing with NLP and context awareness"""
    
    def __init__(self, voice_assistant):
        self.voice_assistant = voice_assistant
        self.context_memory = []
        self.user_preferences = {}
    
    def process_with_context(self, command: str) -> str:
        """Process command with context awareness"""
        # Analyze command intent with context
        enhanced_command = self._enhance_with_context(command)
        
        # Update context memory
        self.context_memory.append({
            'command': command,
            'enhanced': enhanced_command,
            'timestamp': datetime.now()
        })
        
        # Keep only last 10 commands in memory
        if len(self.context_memory) > 10:
            self.context_memory.pop(0)
        
        return enhanced_command
    
    def _enhance_with_context(self, command: str) -> str:
        """Enhance command based on conversation context"""
        # This would use more sophisticated NLP
        # For now, return original command
        return command
    
    def learn_user_preferences(self, command: str, response: str):
        """Learn user preferences from interactions"""
        # Extract preferences from successful interactions
        # This would analyze user commands and responses to build preference profiles
        # For now, store interaction for future analysis
        if not hasattr(self, 'user_preferences'):
            self.user_preferences = {}
        
        # Simple preference extraction - can be enhanced with NLP
        command_lower = command.lower()
        
        # Extract location preferences
        locations = ['mumbai', 'delhi', 'bangalore', 'pune', 'chennai', 'gurgaon', 'noida', 'hyderabad']
        for location in locations:
            if location in command_lower:
                if 'preferred_locations' not in self.user_preferences:
                    self.user_preferences['preferred_locations'] = []
                if location not in self.user_preferences['preferred_locations']:
                    self.user_preferences['preferred_locations'].append(location)
        
        # Extract property type preferences
        property_types = ['apartment', 'house', 'villa', 'condo', 'townhouse']
        for prop_type in property_types:
            if prop_type in command_lower:
                if 'preferred_types' not in self.user_preferences:
                    self.user_preferences['preferred_types'] = []
                if prop_type not in self.user_preferences['preferred_types']:
                    self.user_preferences['preferred_types'].append(prop_type)
687 lines•27.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