SolarAI-Assistant / src /streamlit_app.py
123Divyansh's picture
Update src/streamlit_app.py
7e5229d verified
import streamlit as st
import base64
import requests
import json
import io
import re
from PIL import Image
st.set_page_config(page_title="Solar Rooftop Analyzer", layout="centered")
st.title("\U0001F31E Solar Rooftop Analysis")
st.markdown("Upload a rooftop image and provide your location and budget. The system will analyze the rooftop and estimate potential solar installation ROI.")
OPENROUTER_API_KEY = "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"
VISION_MODEL_NAME = "opengvlab/internvl3-14b:free"
def analyze_image_with_openrouter(image_file):
# Read and convert image to JPEG bytes
img = Image.open(image_file).convert("RGB")
buffer = io.BytesIO()
img.save(buffer, format="JPEG")
jpeg_bytes = buffer.getvalue()
# Base64 encode with content-type prefix
encoded_image = "data:image/jpeg;base64," + base64.b64encode(jpeg_bytes).decode("utf-8")
prompt = (
"Analyze the rooftop in this image. Output JSON with: "
"[Roof area (sqm), Sunlight availability (%), Shading (Yes/No), "
"Recommended solar panel type, Estimated capacity (kW)]."
)
headers = {
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": VISION_MODEL_NAME,
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": encoded_image}}
]
}
]
}
response = requests.post("https://openrouter.ai/api/v1/chat/completions", json=payload, headers=headers)
if response.status_code == 200:
return response.json()
return {"error": f"Failed to analyze image. Status code: {response.status_code}, Response: {response.text}"}
def extract_json_from_response(content):
try:
match = re.search(r"\{.*\}", content, re.DOTALL)
if match:
return json.loads(match.group(0))
except Exception as e:
st.warning(f"Failed to parse JSON: {e}")
return None
def estimate_roi(roof_area, capacity_kw, budget):
cost_per_kw = 65000 # INR/kW
estimated_cost = capacity_kw * cost_per_kw
incentives = estimated_cost * 0.30
net_cost = estimated_cost - incentives
annual_savings = capacity_kw * 1500 * 7
payback_years = round(net_cost / annual_savings, 2)
return {
"estimated_cost": estimated_cost,
"incentives": incentives,
"net_cost": net_cost,
"annual_savings": annual_savings,
"payback_years": payback_years,
"within_budget": budget >= net_cost
}
with st.form("solar_form"):
uploaded_file = st.file_uploader("Upload Rooftop Image", type=["jpg", "jpeg", "png"])
location = st.text_input("Location")
budget = st.number_input("Budget (INR)", min_value=10000.0, step=1000.0)
submitted = st.form_submit_button("Analyze")
if submitted:
if uploaded_file and location and budget:
st.image(uploaded_file, caption="Uploaded Rooftop Image", use_column_width=True)
with st.spinner("Analyzing rooftop image..."):
ai_response = analyze_image_with_openrouter(uploaded_file)
if "choices" in ai_response:
try:
content = ai_response["choices"][0]["message"]["content"]
content_json = extract_json_from_response(content)
if content_json:
st.success("Analysis complete!")
st.subheader("Rooftop Analysis")
st.json(content_json)
if "Roof area (sqm)" in content_json and "Estimated capacity (kW)" in content_json:
roi = estimate_roi(
roof_area=content_json["Roof area (sqm)"],
capacity_kw=content_json["Estimated capacity (kW)"],
budget=budget
)
st.subheader("ROI Estimation")
st.json(roi)
else:
st.error("Could not extract structured data from the AI response.")
st.text(content) # Fallback: show raw content
except Exception as e:
st.error(f"Error parsing analysis content: {e}")
st.json(ai_response)
else:
st.error("Failed to analyze the image. Please try again.")
else:
st.warning("Please upload an image and fill all fields.")