Rekham1110's picture
Update app.py
ee60524 verified
raw
history blame
7.3 kB
import gradio as gr
from PIL import Image
import os
from dotenv import load_dotenv
from simple_salesforce import Salesforce
from datetime import datetime
from fastapi import FastAPI, HTTPException, Security, Depends
from fastapi.security import APIKeyHeader
import base64
import io
import random # For mock predictions
# Load environment variables
load_dotenv()
SF_USERNAME = os.getenv("SF_USERNAME")
SF_PASSWORD = os.getenv("SF_PASSWORD")
SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN")
SF_CONSUMER_KEY = os.getenv("SF_CONSUMER_KEY")
SF_CONSUMER_SECRET = os.getenv("SF_CONSUMER_SECRET")
API_KEY = os.getenv("API_KEY", "your-api-key-here")
# Validate Salesforce credentials
if not all([SF_USERNAME, SF_PASSWORD, SF_SECURITY_TOKEN, SF_CONSUMER_KEY, SF_CONSUMER_SECRET]):
raise ValueError("Missing Salesforce credentials. Set SF_USERNAME, SF_PASSWORD, SF_SECURITY_TOKEN, SF_CONSUMER_KEY, and SF_CONSUMER_SECRET in environment variables.")
# Initialize Salesforce connection
try:
sf = Salesforce(
username=SF_USERNAME,
password=SF_PASSWORD,
security_token=SF_SECURITY_TOKEN,
consumer_key=SF_CONSUMER_KEY,
consumer_secret=SF_CONSUMER_SECRET,
domain='login' # Use 'test' for sandbox
)
except Exception as e:
print(f"Salesforce connection failed: {str(e)}")
raise
# FastAPI app for API endpoint
app = FastAPI()
# API Key authentication
api_key_header = APIKeyHeader(name="X-API-Key")
async def verify_api_key(api_key: str = Security(api_key_header)):
if api_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid API Key")
return api_key
# Mock AI model for milestone detection (since we can't train a real model here)
def mock_ai_model(image):
# Preprocessing: Resize, normalize (simulated)
img = image.convert("RGB")
max_size = 1024
img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# Feature Extraction and Milestone Detection (simulated)
# In a real scenario, this would use a CNN model trained on construction images
milestones = [
"Foundation Completed",
"Structural Framework Started",
"Walls In Progress",
"Roofing Started",
"Interior Work Started",
"Project Completed"
]
# For this image, based on the concrete pillars and rebar, we assume "Structural Framework Started"
milestone = "Structural Framework Started"
completion_percent = 30 # Estimated based on the image
confidence_score = round(random.uniform(0.85, 0.95), 2) # Random confidence between 85-95%
return milestone, completion_percent, confidence_score
@app.post("/predict-milestone")
async def predict_milestone(payload: dict, api_key: str = Depends(verify_api_key)):
try:
# Validate payload
if "image" not in payload:
raise HTTPException(status_code=400, detail="Image field is required")
# Decode base64 image
image_data = payload["image"]
if image_data.startswith("data:image"):
image_data = image_data.split(",")[1] # Remove data URI prefix
img_bytes = base64.b64decode(image_data)
img = Image.open(io.BytesIO(img_bytes))
# Validate image size (max 20MB)
img_bytes_size = len(img_bytes) / (1024 * 1024)
if img_bytes_size > 20:
raise HTTPException(status_code=400, detail="Image size exceeds 20MB")
# Validate image type
if not img.format.lower() in ["jpeg", "png"]:
raise HTTPException(status_code=400, detail="Only JPG/PNG images are supported")
# Run mock AI model
milestone, percent_complete, confidence_score = mock_ai_model(img)
return {
"milestone": milestone,
"percent_complete": percent_complete,
"confidence_score": confidence_score
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}")
# Function for Gradio UI to process the image
def process_image(image, project_name):
try:
# Validate inputs
if image is None:
return "Error: Please upload an image to proceed.", "Pending", "", "", 0
if not project_name:
return "Error: Please enter a project name to proceed.", "Pending", "", "", 0
if not project_name.isalnum():
return "Error: Project name must be alphanumeric (letters and numbers only).", "Pending", "", "", 0
# Open and validate image
img = Image.open(image)
# Validate image size and type
image_size_mb = os.path.getsize(image) / (1024 * 1024)
if image_size_mb > 20:
return "Error: Image size exceeds 20MB.", "Failure", "", "", 0
if not image.lower().endswith(('.jpg', '.jpeg', '.png')):
return "Error: Only JPG/PNG images are supported.", "Failure", "", "", 0
# Run mock AI model
milestone, percent_complete, confidence_score = mock_ai_model(img)
# Update Salesforce record
record = {
"Name": project_name,
"Current_Milestone__c": milestone,
"Completion_Percentage__c": percent_complete,
"Last_Updated_On__c": datetime.now().isoformat(),
"Upload_Status__c": "Success",
"Comments__c": f"AI Prediction: {milestone} with {confidence_score*100}% confidence"
}
try:
query = f"SELECT Id FROM Construction_Project__c WHERE Name = '{project_name}'"
result = sf.query(query)
if result["totalSize"] > 0:
project_id = result["records"][0]["Id"]
sf.Construction_Project__c.update(project_id, record)
else:
sf.Construction_Project__c.create(record)
except Exception as e:
return f"Error: Failed to update Salesforce - {str(e)}", "Failure", "", "", 0
return (
f"Success: Milestone: {milestone}, Completion: {percent_complete}%",
"Success",
milestone,
f"Confidence Score: {confidence_score}",
percent_complete
)
except Exception as e:
return f"Error: {str(e)}", "Failure", "", "", 0
# Gradio interface for testing
with gr.Blocks(css=".gradio-container {background-color: #f0f4f8; font-family: Arial;} .title {color: #2c3e50; font-size: 24px; text-align: center;}") as demo:
gr.Markdown("<h1 class='title'>Construction Milestone Detector</h1>")
project_name = gr.Textbox(label="Project Name", placeholder="Enter project name (e.g., MyHouse)")
image_input = gr.Image(type="filepath", label="Upload Construction Site Photo (JPG/PNG, ≤ 20MB)")
submit_button = gr.Button("Process Image")
output_text = gr.Textbox(label="Result")
upload_status = gr.Textbox(label="Upload Status")
milestone = gr.Textbox(label="Detected Milestone")
confidence = gr.Textbox(label="Confidence Score")
progress = gr.Slider(0, 100, label="Completion Percentage", interactive=False, value=0)
submit_button.click(
fn=process_image,
inputs=[image_input, project_name],
outputs=[output_text, upload_status, milestone, confidence, progress]
)
# Launch the Gradio app
demo.launch()