Spaces:
Sleeping
Sleeping
| 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) |