Spaces:
Sleeping
Sleeping
File size: 6,444 Bytes
b68d8c4 6a43816 b68d8c4 9deac83 b68d8c4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | 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) |