CoolFace
Apppublic

danieljstuart/offshore-hazard-ai

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py107 linesDownload Raw Back to root
1import streamlit as st2import openai3import os4import base645from io import BytesIO6from PIL import Image7 8# Load OpenAI API key9OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")10openai.api_key = OPENAI_API_KEY11 12st.title("⚙️ AI Offshore Hazard Detection")13st.write("📝 **Upload a worksite image and (optionally) describe the job. The AI will detect hazards and recommend controls.**")14 15# User input16job_description = st.text_area("📋 **Job Description (optional):**")17uploaded_image = st.file_uploader("📷 **Upload an Image for Analysis:**", type=["jpg", "png", "jpeg"])18 19# Function to encode image to base6420def encode_image(image):21    image_bytes = image.read()22    return base64.b64encode(image_bytes).decode("utf-8")23 24# Function to determine task category25def infer_task_type(text):26    task = text.lower()27    if any(keyword in task for keyword in ["scaffold", "scaffolding"]):28        return "scaffold"29    elif any(keyword in task for keyword in ["valve", "flange", "relief valve"]):30        return "valve"31    elif any(keyword in task for keyword in ["tank", "vessel", "confined space"]):32        return "confined_space"33    else:34        return "general"35 36# Function to generate smart prompt chain37def generate_prompt(job_description, task_type):38    context = {39        "scaffold": "You're a safety advisor guiding a technician dismantling a scaffold offshore. Focus on structural, dropped object, access, and lifting hazards.",40        "valve": "You're a safety advisor guiding a technician replacing a valve in a pressurised system. Focus on pressure, gas, tool handling, access and dropped object risks.",41        "confined_space": "You're a safety advisor guiding a technician entering a confined space. Focus on ventilation, atmosphere, access and communication hazards.",42        "general": "You're a safety advisor guiding a technician offshore. Focus only on hazards visible in the image and described in the task."43    }[task_type]44 45    intro = f"""46    🚧 **Task Overview**47    {job_description if job_description else "No specific job description provided. Use the image as primary context."}48 49    📸 **Visual Scene Analysis**50    Carefully examine the uploaded image. Identify what kind of work area this is, any visible equipment, height, obstructions, trip hazards, pressure components, etc.51 52    ### 🔍 Step 1: Hazards Detected53    List only specific hazards that can be inferred from the image or the job description. Avoid generic advice. Skip anything that doesn’t clearly apply.54 55    ### 🛠 Step 2: Control Measures56    Provide task-specific, technician-focused controls for each hazard. Mention PPE, tooling, isolation, safe access, and other relevant controls.57 58    ### ✅ Step 3: Final Checklist59    Provide a short summary list of practical checks before starting work.60    """61 62    return f"{context}\n\n{intro}"63 64# Function to analyze hazards65def analyze_hazards(job_description, image):66    task_type = infer_task_type(job_description)67    prompt = generate_prompt(job_description, task_type)68 69    messages = [70        {"role": "system", "content": "You are an expert offshore safety advisor helping a technician complete their job safely. Use the uploaded photo and description to provide highly specific guidance — no generic policy language."},71        {"role": "user", "content": prompt}72    ]73 74    if image:75        encoded_image = encode_image(image)76        messages.append({77            "role": "user",78            "content": [79                {"type": "text", "text": "Use this image to detect specific real-world hazards, equipment, access issues, or risks. Don't give generic safety advice."},80                {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{encoded_image}"}}81            ]82        })83 84    try:85        with st.spinner("🔍 Analyzing photo and job info for hazards..."):86            response = openai.chat.completions.create(87                model="gpt-4o",88                messages=messages,89                max_tokens=900  # Reduced to reduce cost90            )91        return response.choices[0].message.content92    except Exception as e:93        return f"❌ Error: {str(e)}"94 95if st.button("🔍 Analyze Hazards"):96    if job_description or uploaded_image:97        hazard_report = analyze_hazards(job_description, uploaded_image)98        st.markdown("## 📊 **Hazard Analysis Report:**")99        st.markdown("---")100        st.markdown(hazard_report)101        st.markdown("---")102    else:103        st.warning("⚠️ Please enter a job description or upload an image before analyzing.")104 105if uploaded_image:106    st.image(uploaded_image, caption="📷 Uploaded Image", use_container_width=True)107