File size: 7,981 Bytes
9ecbb13 b1f904b 6f5d954 c5d1c34 5a6a4b8 c5d1c34 9ecbb13 b1f904b c5d1c34 f26a80f b1f904b 5a6a4b8 b1f904b 6f5d954 5a6a4b8 b9401ae 6f5d954 b9401ae 84b9aa2 6f5d954 5a6a4b8 b9401ae 6f5d954 b9401ae b1f904b b9401ae b1f904b 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 b9401ae 5a6a4b8 6f5d954 5a6a4b8 6f5d954 5a6a4b8 6f5d954 5a6a4b8 6f5d954 b9401ae 6f5d954 b9401ae f26a80f 6f5d954 5a6a4b8 | 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 | import streamlit as st
from groq import Groq
import json
import os
import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objects as go
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Initialize Groq client
try:
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
except Exception as e:
st.error(f"Failed to initialize Groq client: {e}")
# App title
st.title("π AI Architect: Home Planner")
st.markdown("Get an easy-to-understand house plan with 2D/3D visualization!")
# --- USER INPUTS ---
st.header("π Step 1: Plot Details")
col1, col2 = st.columns(2)
with col1:
plot_length = st.number_input("Plot Length (ft)", min_value=20, max_value=500, value=50)
with col2:
plot_width = st.number_input("Plot Width (ft)", min_value=20, max_value=500, value=40)
st.header("πͺ Step 2: Room Requirements")
master_bed = st.number_input("Master Bedrooms (12x14 ft min)", min_value=0, max_value=5, value=1)
bedrooms = st.number_input("Standard Bedrooms (10x12 ft min)", min_value=0, max_value=10, value=2)
kitchens = st.number_input("Kitchens (8x10 ft min)", min_value=1, max_value=3, value=1)
study_rooms = st.number_input("Study Rooms (8x8 ft min)", min_value=0, max_value=3, value=0)
lounges = st.number_input("Lounges (12x16 ft min)", min_value=1, max_value=3, value=1)
st.header("π½ Step 3: Washrooms")
attached_washrooms = st.number_input("Attached Washrooms (6x8 ft min)", min_value=0, max_value=5, value=1)
common_washrooms = st.number_input("Common Washrooms (5x7 ft min)", min_value=0, max_value=3, value=1)
st.header("π³ Step 4: Extras")
parking = st.checkbox("Parking Space (12x20 ft min) π")
lawn = st.checkbox("Lawn/Garden π³")
# --- AI GENERATION ---
if st.button("Generate Professional Plan"):
prompt = f"""
Design a house plan for a {plot_length}x{plot_width} ft plot following architectural best practices.
Return response in STRICT JSON format with these EXACT keys:
{{
"floor_plan": {{
"rooms": [
{{
"name": "string",
"x": number,
"y": number,
"width": number,
"height": number
}}
],
"washrooms": [
{{
"name": "string",
"x": number,
"y": number,
"width": number,
"height": number
}}
]
}},
"visualization_tips": ["string"],
"material_suggestions": ["string"],
"warnings": ["string"]
}}
Requirements:
1. All dimensions must be numbers (not arrays)
2. Positions must be x,y coordinates as separate numbers
3. Room names should be clear (e.g., "Master Bedroom")
4. Include at least {master_bed} master bedroom(s) and {bedrooms} standard bedroom(s)
"""
try:
response = client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model="llama3-70b-8192",
response_format={"type": "json_object"},
temperature=0.3 # More deterministic output
)
# Parse and validate response
plan = json.loads(response.choices[0].message.content)
# Validate required fields
required_keys = ["floor_plan", "visualization_tips", "material_suggestions", "warnings"]
for key in required_keys:
if key not in plan:
raise ValueError(f"Missing required key: {key}")
if "rooms" not in plan["floor_plan"]:
raise ValueError("Missing rooms in floor plan")
st.success("β
Professionally Designed Plan Generated!")
# --- 2D Visualization ---
st.header("π 2D Floor Plan")
fig, ax = plt.subplots(figsize=(10, 8))
colors = plt.cm.tab20.colors
# Plot rooms
for i, room in enumerate(plan['floor_plan']['rooms']):
rect = plt.Rectangle(
(room['x'], room['y']),
room['width'],
room['height'],
linewidth=2,
edgecolor='black',
facecolor=colors[i % len(colors)])
ax.add_patch(rect)
# Add room label
center_x = room['x'] + room['width']/2
center_y = room['y'] + room['height']/2
ax.text(center_x, center_y,
f"{room.get('name', 'Room')}\n{room['width']}x{room['height']}ft",
ha='center', va='center', fontsize=8)
# Plot washrooms
for washroom in plan['floor_plan'].get('washrooms', []):
rect = plt.Rectangle(
(washroom['x'], washroom['y']),
washroom['width'],
washroom['height'],
linewidth=2,
edgecolor='black',
facecolor='lightblue',
hatch='/')
ax.add_patch(rect)
ax.text(washroom['x'] + washroom['width']/2,
washroom['y'] + washroom['height']/2,
"Bath",
ha='center', va='center', fontsize=8)
# Set plot limits and labels
ax.set_xlim(0, plot_length)
ax.set_ylim(0, plot_width)
ax.set_aspect('equal')
ax.set_xlabel('Length (ft)')
ax.set_ylabel('Width (ft)')
ax.set_title('2D Floor Plan')
st.pyplot(fig)
# --- 3D Visualization ---
st.header("β¨ 3D Visualization")
fig_3d = go.Figure()
# Add rooms as 3D boxes
for i, room in enumerate(plan['floor_plan']['rooms']):
fig_3d.add_trace(go.Mesh3d(
x=[room['x'], room['x'], room['x']+room['width'], room['x']+room['width'], room['x']],
y=[room['y'], room['y']+room['height'], room['y']+room['height'], room['y'], room['y']],
z=[0, 0, 0, 0, 0],
opacity=0.7,
color=f'rgb({colors[i][0]*255},{colors[i][1]*255},{colors[i][2]*255})',
name=room.get('name', 'Room'),
showlegend=True
))
fig_3d.add_trace(go.Mesh3d(
x=[room['x'], room['x'], room['x']+room['width'], room['x']+room['width'], room['x']],
y=[room['y'], room['y']+room['height'], room['y']+room['height'], room['y'], room['y']],
z=[10, 10, 10, 10, 10],
opacity=0.7,
color=f'rgb({colors[i][0]*255},{colors[i][1]*255},{colors[i][2]*255})',
showlegend=False
))
fig_3d.update_layout(
scene=dict(
xaxis=dict(title='Length (ft)'),
yaxis=dict(title='Width (ft)'),
zaxis=dict(title='Height (ft)'),
aspectmode='manual',
aspectratio=dict(x=1, y=plot_width/plot_length, z=0.2)
),
margin=dict(r=20, l=10, b=10, t=30),
legend=dict(x=1, y=1)
)
st.plotly_chart(fig_3d)
# --- Additional Information ---
st.header("π‘ Visualization Tips")
for tip in plan['visualization_tips']:
st.markdown(f"- {tip}")
st.header("ποΈ Material Suggestions")
for material in plan['material_suggestions']:
st.markdown(f"- {material}")
st.header("β οΈ Warnings")
for warning in plan['warnings']:
st.markdown(f"- β οΈ {warning}")
except json.JSONDecodeError:
st.error("Failed to parse the AI response. Please try again.")
except Exception as e:
st.error(f"Error: {str(e)}. Please adjust your inputs and try again.")
# Footer
st.markdown("---")
st.caption("β
Easy-to-understand visualizations | Powered by Groq API") |