Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from openai import OpenAI | |
| import requests | |
| from PIL import Image | |
| import io | |
| import base64 | |
| import os | |
| import json | |
| from datetime import datetime | |
| # Initialize OpenAI client | |
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| def encode_image_to_base64(image): | |
| """Convert PIL image to base64 string for API calls""" | |
| buffer = io.BytesIO() | |
| image.save(buffer, format="PNG") | |
| img_str = base64.b64encode(buffer.getvalue()).decode() | |
| return img_str | |
| def search_current_landscaping_trends(): | |
| """Use web search to get current landscaping and outdoor design trends""" | |
| try: | |
| # In a real implementation, this would use the built-in web search capabilities | |
| # For now, we'll create a comprehensive knowledge base | |
| current_trends = """ | |
| Current 2025 landscaping and backyard design trends include: | |
| - Sustainable and native plant gardens | |
| - Outdoor living rooms with weather-resistant furniture | |
| - Multi-functional spaces for work and relaxation | |
| - Smart irrigation and lighting systems | |
| - Vertical gardens and living walls | |
| - Fire features as focal points | |
| - Natural swimming pools and water features | |
| - Outdoor kitchens with pizza ovens | |
| - Pergolas with retractable canopies | |
| - Drought-resistant xeriscaping | |
| - Edible landscaping with herb gardens | |
| - Wellness spaces for meditation and yoga | |
| """ | |
| return current_trends | |
| except Exception as e: | |
| return "Current outdoor design trends focus on sustainability, functionality, and wellness." | |
| def generate_design_prompt(user_preferences, current_trends): | |
| """Create a detailed prompt for the AI based on user preferences and current trends""" | |
| features_text = ", ".join(user_preferences['features']) if user_preferences['features'] else "basic landscaping" | |
| prompt = f""" | |
| Create a detailed, professional backyard oasis design description based on these specifications: | |
| DESIGN REQUIREMENTS: | |
| - Style: {user_preferences['style']} | |
| - Primary Use: {user_preferences['primary_use']} | |
| - Budget Range: {user_preferences['budget']} | |
| - Must-Have Features: {features_text} | |
| - Seating Arrangement: {user_preferences['seating']} | |
| - Plant Preferences: {user_preferences['plants']} | |
| - Privacy Level: {user_preferences['privacy']}/5 | |
| - Maintenance Level: {user_preferences['maintenance']}/5 | |
| - Lighting Style: {user_preferences['lighting']} | |
| - Climate Zone: {user_preferences['climate']} | |
| CURRENT TRENDS TO INCORPORATE: | |
| {current_trends} | |
| Please provide: | |
| 1. **Design Overview**: A compelling description of the overall backyard transformation | |
| 2. **Layout Plan**: Detailed spatial arrangement of all elements | |
| 3. **Plant Selection**: Specific plants suited to the climate and maintenance level | |
| 4. **Material Recommendations**: Specific materials for hardscaping, furniture, and structures | |
| 5. **Feature Integration**: How each requested feature will be incorporated | |
| 6. **Lighting Design**: Complete lighting strategy for ambiance and functionality | |
| 7. **Maintenance Schedule**: Seasonal care requirements | |
| 8. **Implementation Timeline**: Phased approach with estimated timeframes | |
| 9. **Cost Breakdown**: Detailed budget allocation by category | |
| 10. **Professional Tips**: Expert advice for maximizing the space and achieving goals | |
| Make this a comprehensive, actionable design plan that a homeowner could use to create their dream backyard. | |
| """ | |
| return prompt | |
| def generate_backyard_design(user_preferences, image_description=None): | |
| """Generate a comprehensive backyard design using OpenAI""" | |
| try: | |
| # Get current trends | |
| current_trends = search_current_landscaping_trends() | |
| # Create the design prompt | |
| design_prompt = generate_design_prompt(user_preferences, current_trends) | |
| # Add image context if provided | |
| if image_description: | |
| design_prompt = f""" | |
| CURRENT YARD ANALYSIS: {image_description} | |
| {design_prompt} | |
| Please incorporate the existing yard features and work with the current space limitations and opportunities. | |
| """ | |
| messages = [ | |
| { | |
| "role": "system", | |
| "content": """You are a world-class landscape architect and outdoor design expert trained by the best designers in the field. | |
| Your expertise includes sustainable design, modern outdoor living, plant selection, hardscaping, and creating functional beautiful spaces. | |
| Create highly detailed, actionable backyard designs that are: | |
| - Specific to the user's climate and preferences | |
| - Realistic within their stated budget | |
| - Incorporating current design trends and sustainable practices | |
| - Providing exact plant names, material specifications, and implementation steps | |
| - Including maintenance requirements and seasonal care | |
| - Offering creative solutions for common backyard challenges | |
| Always provide comprehensive, professional-quality designs that could be used by contractors and landscapers.""" | |
| }, | |
| { | |
| "role": "user", | |
| "content": design_prompt | |
| } | |
| ] | |
| response = client.chat.completions.create( | |
| model="gpt-4", | |
| messages=messages, | |
| max_tokens=3000, | |
| temperature=0.7 | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| st.error(f"Error generating design: {str(e)}") | |
| return None | |
| def analyze_yard_image(image): | |
| """Analyze the uploaded yard image using OpenAI Vision""" | |
| try: | |
| # Convert image to base64 | |
| img_base64 = encode_image_to_base64(image) | |
| response = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=[ | |
| { | |
| "role": "user", | |
| "content": [ | |
| { | |
| "type": "text", | |
| "text": """Analyze this backyard/yard image and provide a detailed description including: | |
| - Current layout and size estimation | |
| - Existing features (deck, patio, plants, structures) | |
| - Soil and grass condition | |
| - Sun/shade patterns visible | |
| - Potential challenges and opportunities | |
| - Existing trees and landscaping | |
| - Property boundaries and neighbor considerations | |
| - Overall style and condition | |
| Be specific and detailed to help with redesign planning.""" | |
| }, | |
| { | |
| "type": "image_url", | |
| "image_url": { | |
| "url": f"data:image/png;base64,{img_base64}" | |
| } | |
| } | |
| ] | |
| } | |
| ], | |
| max_tokens=1000 | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| st.warning(f"Could not analyze image: {str(e)}. Proceeding without image analysis.") | |
| return None | |
| def create_lead_capture_email(user_preferences, design_content): | |
| """Create email content for lead capture""" | |
| features_list = ", ".join(user_preferences['features']) if user_preferences['features'] else "Custom landscaping" | |
| email_subject = "My Dream Backyard Design - VIP Property List Request" | |
| email_body = f"""Hi there! | |
| I just created my dream backyard design using your Backyard Oasis Designer tool and would love to join your VIP list for homes with great outdoor potential! | |
| Here are my design preferences: | |
| π‘ DESIGN SPECIFICATIONS: | |
| β’ Style: {user_preferences['style']} | |
| β’ Primary Use: {user_preferences['primary_use']} | |
| β’ Budget: {user_preferences['budget']} | |
| β’ Must-Have Features: {features_list} | |
| β’ Seating: {user_preferences['seating']} | |
| β’ Plants: {user_preferences['plants']} | |
| β’ Privacy Level: {user_preferences['privacy']}/5 | |
| β’ Maintenance Level: {user_preferences['maintenance']}/5 | |
| β’ Lighting: {user_preferences['lighting']} | |
| β’ Climate: {user_preferences['climate']} | |
| GENERATED DESIGN SUMMARY: | |
| {design_content[:500]}... | |
| Please add me to your VIP list so I can be notified of homes that would work well for creating this type of outdoor space! | |
| Looking forward to hearing from you. | |
| Best regards, | |
| [Your Name] | |
| [Your Phone Number] | |
| [Your Email]""" | |
| return email_subject, email_body | |
| # Streamlit App Configuration | |
| st.set_page_config( | |
| page_title="Backyard Oasis Designer", | |
| page_icon="πΏ", | |
| layout="wide", | |
| initial_sidebar_state="collapsed" | |
| ) | |
| # Custom CSS for better styling | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| text-align: center; | |
| color: #2E7D32; | |
| font-size: 3rem; | |
| font-weight: bold; | |
| margin-bottom: 0.5rem; | |
| } | |
| .sub-header { | |
| text-align: center; | |
| color: #4CAF50; | |
| font-size: 1.2rem; | |
| margin-bottom: 2rem; | |
| } | |
| .section-header { | |
| color: #2E7D32; | |
| font-size: 1.5rem; | |
| font-weight: bold; | |
| margin-top: 2rem; | |
| margin-bottom: 1rem; | |
| } | |
| .feature-box { | |
| background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); | |
| padding: 1.5rem; | |
| border-radius: 10px; | |
| border-left: 5px solid #4CAF50; | |
| margin: 1rem 0; | |
| } | |
| .cta-box { | |
| background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%); | |
| padding: 2rem; | |
| border-radius: 15px; | |
| border: 2px solid #4CAF50; | |
| margin: 2rem 0; | |
| text-align: center; | |
| } | |
| .step-number { | |
| background: linear-gradient(135deg, #4CAF50, #2E7D32); | |
| color: white; | |
| width: 30px; | |
| height: 30px; | |
| border-radius: 50%; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: bold; | |
| margin-right: 10px; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Initialize session state | |
| if "design_result" not in st.session_state: | |
| st.session_state["design_result"] = None | |
| if "user_preferences" not in st.session_state: | |
| st.session_state["user_preferences"] = {} | |
| if "show_generating" not in st.session_state: | |
| st.session_state["show_generating"] = False | |
| # Main Header | |
| st.markdown('<h1 class="main-header">πΏ Backyard Oasis Designer</h1>', unsafe_allow_html=True) | |
| st.markdown('<p class="sub-header">Transform your yard into a stunning outdoor paradise with AI</p>', unsafe_allow_html=True) | |
| # Step 1: Image Upload | |
| st.markdown('<div class="section-header"><span class="step-number">1</span>Upload Your Current Yard Photo</div>', unsafe_allow_html=True) | |
| uploaded_file = st.file_uploader( | |
| "Upload a clear photo of your current backyard", | |
| type=['png', 'jpg', 'jpeg'], | |
| help="This helps us understand your current space and create a more personalized design" | |
| ) | |
| image_analysis = None | |
| if uploaded_file is not None: | |
| image = Image.open(uploaded_file) | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col2: | |
| st.image(image, caption="Your Current Yard", use_column_width=True) | |
| with st.spinner("Analyzing your yard..."): | |
| image_analysis = analyze_yard_image(image) | |
| if image_analysis: | |
| with st.expander("π Yard Analysis"): | |
| st.write(image_analysis) | |
| # Step 2: Design Preferences | |
| st.markdown('<div class="section-header"><span class="step-number">2</span>Design Your Perfect Oasis</div>', unsafe_allow_html=True) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| style = st.selectbox( | |
| "What's your preferred outdoor style?", | |
| ["", "Modern Minimalist", "Tropical Paradise", "Zen Garden", "Rustic Farmhouse", "Mediterranean", "Desert Contemporary"], | |
| help="This sets the overall aesthetic direction for your design" | |
| ) | |
| primary_use = st.selectbox( | |
| "What's the primary use for your backyard?", | |
| ["", "Entertaining & Parties", "Relaxation & Meditation", "Family Activities", "Gardening & Growing", "Outdoor Dining", "Sports & Recreation"] | |
| ) | |
| budget = st.selectbox( | |
| "What's your budget range?", | |
| ["", "Budget-Friendly ($500-2,000)", "Moderate ($2,000-10,000)", "Premium ($10,000-25,000)", "Luxury ($25,000+)"] | |
| ) | |
| seating = st.selectbox( | |
| "Preferred seating arrangement?", | |
| ["", "Lounge/Living Area", "Dining Table & Chairs", "Conversation Pit", "Built-in Benches", "Swings & Hammocks", "Mix of Different Seating"] | |
| ) | |
| plants = st.selectbox( | |
| "Plant preferences?", | |
| ["", "Low Maintenance", "Native Plants", "Tropical & Lush", "Drought Tolerant", "Seasonal Colors", "Herbs & Vegetables"] | |
| ) | |
| with col2: | |
| st.markdown("**Must-have features** (Select all that apply):") | |
| features = [] | |
| if st.checkbox("π Pool or Spa"): | |
| features.append("Pool or Spa") | |
| if st.checkbox("π³ Outdoor Kitchen"): | |
| features.append("Outdoor Kitchen") | |
| if st.checkbox("π₯ Fire Pit/Fireplace"): | |
| features.append("Fire Pit/Fireplace") | |
| if st.checkbox("π§ Water Feature"): | |
| features.append("Water Feature") | |
| if st.checkbox("ποΈ Pergola or Gazebo"): | |
| features.append("Pergola or Gazebo") | |
| if st.checkbox("π± Flower/Vegetable Gardens"): | |
| features.append("Flower/Vegetable Gardens") | |
| if st.checkbox("π Playground/Kids Area"): | |
| features.append("Playground/Kids Area") | |
| if st.checkbox("πΉ Outdoor Bar"): | |
| features.append("Outdoor Bar") | |
| privacy = st.slider("Privacy level desired:", 1, 5, 3, help="1 = Very Open, 5 = Very Private") | |
| maintenance = st.slider("Maintenance commitment:", 1, 5, 3, help="1 = Very Low, 5 = Very High") | |
| lighting = st.selectbox( | |
| "Lighting preferences?", | |
| ["", "String Lights", "Landscape Lighting", "Solar Lights", "Built-in LED System", "Fire-based Lighting", "Minimal Lighting"] | |
| ) | |
| climate = st.selectbox( | |
| "Your climate zone?", | |
| ["", "Tropical", "Subtropical", "Temperate", "Arid/Desert", "Continental", "Mediterranean"] | |
| ) | |
| # Form validation | |
| required_fields = [style, primary_use, budget, seating, plants, lighting, climate] | |
| all_filled = all(field != "" for field in required_fields) | |
| has_features = len(features) > 0 | |
| if st.button("π¨ Generate My Dream Backyard", type="primary", disabled=not (all_filled and has_features)): | |
| if not all_filled: | |
| st.error("Please fill in all the design preferences.") | |
| elif not has_features: | |
| st.error("Please select at least one must-have feature.") | |
| else: | |
| # Store user preferences | |
| st.session_state["user_preferences"] = { | |
| 'style': style, | |
| 'primary_use': primary_use, | |
| 'budget': budget, | |
| 'features': features, | |
| 'seating': seating, | |
| 'plants': plants, | |
| 'privacy': privacy, | |
| 'maintenance': maintenance, | |
| 'lighting': lighting, | |
| 'climate': climate | |
| } | |
| st.session_state["show_generating"] = True | |
| with st.spinner("Creating your personalized backyard oasis... This may take 30-60 seconds"): | |
| design_result = generate_backyard_design(st.session_state["user_preferences"], image_analysis) | |
| if design_result: | |
| st.session_state["design_result"] = design_result | |
| st.session_state["show_generating"] = False | |
| st.success("π Your dream backyard design is ready!") | |
| else: | |
| st.session_state["show_generating"] = False | |
| st.error("Sorry, we couldn't generate your design right now. Please try again.") | |
| # Display generating notice | |
| if st.session_state["show_generating"]: | |
| st.info("π¨ Generating your backyard design. This process may take a minute or two. Please wait...") | |
| # Display Results | |
| if st.session_state["design_result"]: | |
| st.markdown('<div class="section-header">π Your Dream Backyard Design</div>', unsafe_allow_html=True) | |
| # Display the design | |
| st.markdown(st.session_state["design_result"]) | |
| # Real Estate Lead Capture CTAs | |
| st.markdown('<div class="cta-box">', unsafe_allow_html=True) | |
| st.markdown("### π‘ Love This Design?") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("π§ Email me this design to join my VIP list for homes with great outdoor potential", key="email_cta"): | |
| email_subject, email_body = create_lead_capture_email(st.session_state["user_preferences"], st.session_state["design_result"]) | |
| # Create mailto link | |
| mailto_link = f"mailto:?subject={email_subject}&body={email_body}" | |
| st.markdown(f'<a href="{mailto_link}" target="_blank">Click here if email didn\'t open automatically</a>', unsafe_allow_html=True) | |
| # Also show a form for manual copy | |
| with st.expander("π Copy Email Content"): | |
| st.text_area("Subject:", value=email_subject, height=50) | |
| st.text_area("Email Body:", value=email_body, height=300) | |
| with col2: | |
| if st.button("π Share This Tool with Friends!", key="share_cta"): | |
| share_text = """πΏ Check out this amazing Backyard Oasis Designer! | |
| Upload a photo of your yard, answer 10 questions, and get an AI-generated design of your dream outdoor space. | |
| Perfect for anyone thinking about buying a home with outdoor potential! π‘β¨ | |
| Try it here: [Insert your website URL]""" | |
| st.text_area("Share this message:", value=share_text, height=150) | |
| st.info("Know someone who's ready to start house hunting? Send them this backyard designer to give them some great ideas!") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Generate another design option | |
| if st.button("π Generate Another Design Variation", key="regenerate"): | |
| with st.spinner("Creating another design variation..."): | |
| new_design = generate_backyard_design(st.session_state["user_preferences"], image_analysis) | |
| if new_design: | |
| st.session_state["design_result"] = new_design | |
| st.experimental_rerun() | |
| # Sidebar with additional info | |
| with st.sidebar: | |
| st.markdown("### About This Tool") | |
| st.write("This AI-powered designer creates custom backyard plans based on your preferences, budget, and climate.") | |
| st.markdown("### Need Help?") | |
| st.write("Having trouble? Make sure to:") | |
| st.write("β’ Upload a clear photo of your yard") | |
| st.write("β’ Fill in all preference fields") | |
| st.write("β’ Select at least one feature") | |
| st.markdown("### Real Estate Services") | |
| st.write("Looking for a home with great outdoor potential? Our VIP list gives you first access to properties perfect for your dream backyard!") |