nniehaus commited on
Commit
9dc9f53
Β·
verified Β·
1 Parent(s): 5066bf1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -28
app.py CHANGED
@@ -28,20 +28,20 @@ st.markdown(
28
  unsafe_allow_html=True
29
  )
30
 
31
- # --- Configuration ---
32
  API_URL = "https://api.openai.com/v1/chat/completions"
33
 
34
- # --- Cache utilities ---
35
  @st.cache_data
36
  def encode_image_to_b64(image: Image.Image) -> str:
37
  # Convert to RGB if needed
38
  if image.mode == 'RGBA':
39
- bg = Image.new('RGB', image.size, (255,255,255))
40
  bg.paste(image, mask=image.split()[3])
41
  image = bg
42
  elif image.mode not in ['RGB', 'L']:
43
  image = image.convert('RGB')
44
- # Resize to limit token usage
45
  max_size = (1024, 1024)
46
  if image.width > max_size[0] or image.height > max_size[1]:
47
  image.thumbnail(max_size, Image.LANCZOS)
@@ -49,23 +49,27 @@ def encode_image_to_b64(image: Image.Image) -> str:
49
  image.save(buf, format='JPEG', quality=85)
50
  return base64.b64encode(buf.getvalue()).decode('utf-8')
51
 
 
52
  def fix_formatting(text: str) -> str:
53
  text = re.sub(r'(\d+)([A-Za-z])', r'\1 \2', text)
54
  text = re.sub(r'([.,])([A-Za-z0-9])', r'\1 \2', text)
55
  text = re.sub(r':([A-Za-z0-9])', r': \1', text)
56
  return text
57
 
58
- # --- Analysis function via requests ---
59
  def analyze_home_photos(images, timeframe, details, api_key):
60
  if not api_key:
61
  return "Error: API key is required."
62
- headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
63
- # Build system prompt
 
 
 
64
  system_prompt = (
65
  f"You are a real estate advisor. Today's date is {datetime.now().strftime('%B %d, %Y')}. "
66
- "Analyze only visible areas in the images and give hyper-specific recommendations."
67
  )
68
- # Build user content with embedded images
69
  user_content = f"Sell within {timeframe}. {details}\n\n"
70
  for img in images:
71
  b64 = encode_image_to_b64(img)
@@ -81,29 +85,34 @@ def analyze_home_photos(images, timeframe, details, api_key):
81
  resp = requests.post(API_URL, headers=headers, json=payload, timeout=90)
82
  if resp.status_code == 200:
83
  data = resp.json()
84
- text = data['choices'][0]['message']['content']
85
- return fix_formatting(text)
86
  return f"API Error {resp.status_code}: {resp.text[:200]}"
87
 
88
  # --- Cost calculation ---
89
  def calculate_cost(usage):
90
  if not usage:
91
  return 0.0
92
- in_tok = usage.get('prompt_tokens',0)
93
- out_tok = usage.get('completion_tokens',0)
94
- cost = in_tok/1e6*3 + out_tok/1e6*10
95
- return cost
96
 
97
- # --- App layout ---
98
  st.title("Home Value Maximizer 🏑")
99
 
100
  # Sidebar inputs
101
  api_key = st.sidebar.text_input("OpenAI API Key", type="password")
102
- uploaded = st.sidebar.file_uploader("Upload home photos", accept_multiple_files=True, type=["jpg","png","jpeg"])
103
-
104
- timeframe = st.sidebar.selectbox("Selling timeframe", ["Within 1 month","1–3 months","3–6 months","6–12 months",">12 months"])
 
 
 
105
  budget = st.sidebar.slider("Max improvement budget ($)", 1000, 50000, 10000, 1000)
106
- focus = st.sidebar.multiselect("Focus areas", ["Curb appeal","Kitchen","Bathroom","Living Spaces","Outdoor","Storage"], default=["Kitchen","Bathroom"])
 
 
 
 
107
 
108
  if st.sidebar.button("πŸ” Analyze My Home"):
109
  if not api_key:
@@ -113,14 +122,23 @@ if st.sidebar.button("πŸ” Analyze My Home"):
113
  else:
114
  images = []
115
  for f in uploaded:
116
- try: images.append(Image.open(f))
117
- except: pass
 
 
118
  with st.spinner("Analyzing..."):
119
- result = analyze_home_photos(images, timeframe, f"Budget ${budget}. Focus: {', '.join(focus)}", api_key)
120
- st.markdown(f"<div style='background:#e3f2fd;padding:1rem;border-left:4px solid #1f77b4;'>{result}</div>", unsafe_allow_html=True)
121
- # Cost display
122
- # Note: HF Spaces does not return usage, so this may be blank
123
- usage = {} # placeholder
 
 
 
 
 
 
 
 
124
  cost = calculate_cost(usage)
125
  st.metric("πŸ’² Estimated cost", f"${cost:.2f}")
126
- ```
 
28
  unsafe_allow_html=True
29
  )
30
 
31
+ # --- API Configuration ---
32
  API_URL = "https://api.openai.com/v1/chat/completions"
33
 
34
+ # --- Caching helpers ---
35
  @st.cache_data
36
  def encode_image_to_b64(image: Image.Image) -> str:
37
  # Convert to RGB if needed
38
  if image.mode == 'RGBA':
39
+ bg = Image.new('RGB', image.size, (255, 255, 255))
40
  bg.paste(image, mask=image.split()[3])
41
  image = bg
42
  elif image.mode not in ['RGB', 'L']:
43
  image = image.convert('RGB')
44
+ # Resize large images
45
  max_size = (1024, 1024)
46
  if image.width > max_size[0] or image.height > max_size[1]:
47
  image.thumbnail(max_size, Image.LANCZOS)
 
49
  image.save(buf, format='JPEG', quality=85)
50
  return base64.b64encode(buf.getvalue()).decode('utf-8')
51
 
52
+
53
  def fix_formatting(text: str) -> str:
54
  text = re.sub(r'(\d+)([A-Za-z])', r'\1 \2', text)
55
  text = re.sub(r'([.,])([A-Za-z0-9])', r'\1 \2', text)
56
  text = re.sub(r':([A-Za-z0-9])', r': \1', text)
57
  return text
58
 
59
+ # --- Core analysis ---
60
  def analyze_home_photos(images, timeframe, details, api_key):
61
  if not api_key:
62
  return "Error: API key is required."
63
+ headers = {
64
+ "Authorization": f"Bearer {api_key}",
65
+ "Content-Type": "application/json"
66
+ }
67
+ # System prompt
68
  system_prompt = (
69
  f"You are a real estate advisor. Today's date is {datetime.now().strftime('%B %d, %Y')}. "
70
+ "Analyze only visible areas and give hyper-specific recommendations."
71
  )
72
+ # User content with embedded images
73
  user_content = f"Sell within {timeframe}. {details}\n\n"
74
  for img in images:
75
  b64 = encode_image_to_b64(img)
 
85
  resp = requests.post(API_URL, headers=headers, json=payload, timeout=90)
86
  if resp.status_code == 200:
87
  data = resp.json()
88
+ return fix_formatting(data['choices'][0]['message']['content'])
 
89
  return f"API Error {resp.status_code}: {resp.text[:200]}"
90
 
91
  # --- Cost calculation ---
92
  def calculate_cost(usage):
93
  if not usage:
94
  return 0.0
95
+ in_tok = usage.get('prompt_tokens', 0)
96
+ out_tok = usage.get('completion_tokens', 0)
97
+ return in_tok/1e6*3 + out_tok/1e6*10
 
98
 
99
+ # --- UI layout ---
100
  st.title("Home Value Maximizer 🏑")
101
 
102
  # Sidebar inputs
103
  api_key = st.sidebar.text_input("OpenAI API Key", type="password")
104
+ uploaded = st.sidebar.file_uploader(
105
+ "Upload home photos", accept_multiple_files=True, type=["jpg", "jpeg", "png"]
106
+ )
107
+ timeframe = st.sidebar.selectbox(
108
+ "Selling timeframe", ["Within 1 month", "1–3 months", "3–6 months", "6–12 months", ">12 months"]
109
+ )
110
  budget = st.sidebar.slider("Max improvement budget ($)", 1000, 50000, 10000, 1000)
111
+ focus = st.sidebar.multiselect(
112
+ "Focus areas",
113
+ ["Curb appeal", "Kitchen", "Bathroom", "Living Spaces", "Outdoor", "Storage"],
114
+ default=["Kitchen", "Bathroom"]
115
+ )
116
 
117
  if st.sidebar.button("πŸ” Analyze My Home"):
118
  if not api_key:
 
122
  else:
123
  images = []
124
  for f in uploaded:
125
+ try:
126
+ images.append(Image.open(f))
127
+ except:
128
+ pass
129
  with st.spinner("Analyzing..."):
130
+ result = analyze_home_photos(
131
+ images,
132
+ timeframe,
133
+ f"Budget ${budget}. Focus: {', '.join(focus)}",
134
+ api_key
135
+ )
136
+ # Render result with styled container
137
+ st.markdown(
138
+ f"<div style='background:#e3f2fd;padding:1rem;border-left:4px solid #1f77b4;'>{result}</div>",
139
+ unsafe_allow_html=True
140
+ )
141
+ # Display cost (usage info not returned in HF)
142
+ usage = {}
143
  cost = calculate_cost(usage)
144
  st.metric("πŸ’² Estimated cost", f"${cost:.2f}")