Signal_Ghost / app.py
MalikShehram's picture
Update app.py
9deac83 verified
import os
import gradio as gr
import google.generativeai as genai
from PIL import Image
from dotenv import load_dotenv
# 1. Setup & Configuration
# ---------------------------------------------------------
load_dotenv()
# Fetch API Key from environment (HF Secrets or .env file)
API_KEY = os.getenv("GEMINI_API_KEY")
if not API_KEY:
# Fallback for local testing if env var is missing
print("⚠️ WARNING: GEMINI_API_KEY not found. Please set it in your environment.")
# Configure Gemini
genai.configure(api_key=API_KEY)
# Use Gemini 1.5 Flash for speed and multimodal capabilities
MODEL_NAME = "gemini-1.5-flash"
generation_config = {
"temperature": 0.4, # Lower temperature for more analytical/precise reasoning
"top_p": 0.95,
"top_k": 64,
"max_output_tokens": 8192,
}
model = genai.GenerativeModel(
model_name=MODEL_NAME,
generation_config=generation_config,
)
# 2. The "Signal Ghost" Logic (Bayesian Analysis)
# ---------------------------------------------------------
def signal_ghost_analysis(image, audio_path):
"""
Core function to process the multimodal inputs via Gemini.
"""
if not API_KEY:
return "❌ Error: API Key is missing. Please configure GEMINI_API_KEY in Settings."
if image is None or audio_path is None:
return "⚠️ Please upload both a PCB Image and an Audio Signal file to begin the diagnostic."
print("πŸ‘» Signal Ghost: Processing inputs...")
# Upload audio file to Gemini File API (required for audio processing)
# Note: In a production app, manage file deletion/lifecycle.
# For Hackathon demo, simple upload is fine.
try:
audio_file = genai.upload_file(path=audio_path)
except Exception as e:
return f"❌ Error processing audio: {str(e)}"
# The "Ghost" System Prompt
# We instruct the model to act as a Bayesian Diagnostic Engine.
prompt = """
You are 'Signal Ghost', an advanced AI diagnostic ecosystem for Electrical Engineering.
**YOUR MISSION:**
Perform a cross-domain analysis of the provided PCB IMAGE and the AUDIO SIGNAL (EMI noise/interference).
Use Bayesian reasoning: Update your confidence in a fault based on the combined evidence of visual defects and auditory signal signatures.
**INPUTS:**
1. Visual: A circuit board image (look for burnt components, bad traces, grounding issues).
2. Audio: A recording of electrical noise/interference (listen for 50/60Hz hum, high-pitch switching whine, arcing pops).
**OUTPUT FORMAT:**
You must generate a response with two distinct sections separated by a horizontal rule.
---
### πŸ—οΈ SECTION 1: ENGINEER TECHNICAL REPORT (The "Raw Data")
* **Tone:** Professional, precise, metric-driven (ISO/IEEE standard).
* **Bayesian Confidence:** "Fault Probability: X%" (Explain the priors: Visual + Audio).
* **Signal Analysis:** Estimate frequencies (e.g., "120Hz Ripple"), dB estimates, and wave shapes.
* **Visual Analysis:** Component coordinates (e.g., "Top left capacitor"), specific damage type.
* **Action Plan:** Bullet points of technical fixes (e.g., "Replace C4 with low-ESR variant", "Add ferrite bead").
---
### πŸŽ“ SECTION 2: STUDENT SUMMARY (The "Translation")
* **Tone:** Socratic, encouraging, simplified.
* **The Analogy:** Explain the technical fault using a real-world analogy (e.g., plumbing, traffic, music).
* **Why it happened:** Simple cause-and-effect.
* **Learning Moment:** One key concept to remember (e.g., "Why do capacitors explode?").
"""
# Generate Content
try:
response = model.generate_content([prompt, image, audio_file])
return response.text
except Exception as e:
return f"❌ Analysis Failed: {str(e)}"
# 3. User Interface (Gradio)
# ---------------------------------------------------------
# Custom CSS for that "Cyber/Ghost" Aesthetic
ghost_css = """
body { background-color: #0b0f19; color: #e0e0e0; }
gradio-app { background-color: #0b0f19 !important; }
.header-text { text-align: center; font-family: 'Courier New', monospace; color: #00f3ff; text-shadow: 0px 0px 10px #00f3ff; }
.sub-text { text-align: center; color: #8892b0; font-size: 1.1em; }
button.primary { background: linear-gradient(90deg, #00f3ff 0%, #0077ff 100%); border: none; color: #000; font-weight: bold; transition: all 0.3s ease; }
button.primary:hover { box-shadow: 0px 0px 15px #00f3ff; transform: scale(1.02); }
.panel { border: 1px solid #1f2937; background-color: #111827; border-radius: 8px; }
"""
with gr.Blocks(theme=gr.themes.Soft(), css=ghost_css, title="Signal Ghost") as app:
# --- Header ---
with gr.Row():
with gr.Column():
gr.Markdown("# πŸ‘» SIGNAL GHOST", elem_classes=["header-text"])
gr.Markdown("### Multimodal ECE Diagnostic Ecosystem", elem_classes=["sub-text"])
gr.Markdown("Upload a PCB Image and an Audio Recording of the circuit noise to detect EMI faults.", elem_classes=["sub-text"])
# --- Input Section ---
with gr.Row(equal_height=True):
with gr.Column(scale=1, min_width=300):
gr.Markdown("### πŸ‘οΈ Visual Input (PCB)")
img_input = gr.Image(type="pil", label="Upload Circuit Board Image", sources=["upload", "clipboard"])
with gr.Column(scale=1, min_width=300):
gr.Markdown("### πŸ‘‚ Auditory Input (Signal Noise)")
audio_input = gr.Audio(type="filepath", label="Upload Noise Signal (.wav, .mp3)", sources=["upload", "microphone"])
# --- Action Button ---
with gr.Row():
analyze_btn = gr.Button("πŸ” INITIATE DIAGNOSTIC SEQUENCE", variant="primary", size="lg")
# --- Output Section ---
with gr.Row():
with gr.Column():
gr.Markdown("### πŸ“Š Diagnostic Output")
output_text = gr.Markdown(value="Waiting for signal inputs...", label="Analysis Report")
# --- Footer ---
with gr.Row():
gr.Markdown("---")
gr.Markdown("*Powered by Gemini 1.5 Flash β€’ Bayesian Inference Engine v1.0*")
# --- Event Binding ---
analyze_btn.click(
fn=signal_ghost_analysis,
inputs=[img_input, audio_input],
outputs=output_text
)
# 4. Launch
# ---------------------------------------------------------
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860)