# ============================================================ # LEXOSYNTH - FRONTEND : GRADIO UI # File : frontend.py # # Provides a minimal Gradio interface that calls the Flask # backend at localhost:5000/analyze. # # Layout : # - Heading at top center # - Text input box (rounded) # - Dropdown "Choose Engine" on left # - "Analyze" button on right # - Output textbox with copy button below # ============================================================ import gradio as gr import requests # Flask backend URL FLASK_URL = "http://localhost:5000" # ============================================================ # SECTION 1 : ENGINE OPTIONS # ============================================================ ENGINES = [ "— Select from dropdown —", "Supersonic (Fast)", "Go Deep (Llama)", "Hybimix (Llama + Supersonic)", "Go Deep Max (Sarvam)", "Hybimix Max (Sarvam + Supersonic)" ] # Maps display name to backend engine key ENGINE_MAP = { "Supersonic (Fast)" : "supersonic", "Go Deep (Llama)" : "go_deep", "Hybimix (Llama + Supersonic)" : "hybimix", "Go Deep Max (Sarvam)" : "go_deep_max", "Hybimix Max (Sarvam + Supersonic)": "hybimix_max" } # ============================================================ # SECTION 2 : ANALYZE FUNCTION (CALLS FLASK API) # ============================================================ def analyze(text, engine_choice): """ Called when the user clicks Analyze. Sends text + engine to Flask /analyze and returns the formatted output string for display. Parameters: ----------- text : User input text (one or more sentences) engine_choice : Selected engine display name from dropdown Returns: ----------- str : Formatted result string shown in the output textbox """ # Input validation if not text or not text.strip(): return "⚠ Please enter some text before clicking Analyze." if not engine_choice or engine_choice == "— Select from dropdown —": return "⚠ Please select an engine from the dropdown." engine_key = ENGINE_MAP.get(engine_choice) if not engine_key: return "⚠ Invalid engine selection." # Show which engine is running engine_label = engine_choice # AI engines can be very slow on CPU — notify user is_ai = engine_key in ("go_deep", "hybimix", "go_deep_max", "hybimix_max") try: response = requests.post( f"{FLASK_URL}/analyze", json = {"text": text.strip(), "engine": engine_key}, timeout = 600 # 10 min timeout — AI inference on CPU is slow ) if response.status_code == 200: data = response.json() count = data.get("sentence_count", 0) output = data.get("formatted_output", "No output received.") # Add a summary header header = ( f"Engine : {engine_label}\n" f"Sentences processed : {count}\n" + "═" * 52 + "\n\n" ) return header + output else: error = response.json().get("error", "Unknown server error.") return f"❌ Server error : {error}" except requests.exceptions.ConnectionError: return ( "❌ Could not connect to the Flask backend.\n" " Please make sure test.py is running." ) except requests.exceptions.Timeout: return ( "❌ Request timed out.\n" " AI engines on CPU can take several minutes.\n" " Try again or use Supersonic (Fast) for quick results." ) except Exception as e: return f"❌ Unexpected error : {str(e)}" # ============================================================ # SECTION 3 : CUSTOM CSS # ============================================================ CUSTOM_CSS = """ /* Center the main heading */ .main-title { text-align : center; padding : 24px 0 8px 0; } /* Rounded text input */ .rounded-input textarea, .rounded-input input { border-radius : 12px !important; } /* Rounded output box */ .rounded-output textarea { border-radius : 12px !important; font-family : 'Courier New', monospace; font-size : 0.88rem; } /* Analyze button */ .analyze-btn button { min-height : 46px !important; border-radius : 10px !important; font-size : 1rem !important; font-weight : 600 !important; } /* Dropdown rounded */ .engine-dropdown .wrap { border-radius : 10px !important; } /* Subtle section spacing */ .section-gap { margin-top : 8px; } """ # ============================================================ # SECTION 4 : BUILD GRADIO UI # ============================================================ with gr.Blocks( title = "Tortured Phrase Detector and Corrector", theme = gr.themes.Soft( primary_hue = "slate", secondary_hue = "blue", neutral_hue = "gray" ), css = CUSTOM_CSS ) as demo: # ── Heading ── gr.HTML("""

Tortured Phrase Detector and Corrector

Detect and correct unnatural AIML paraphrases in scientific text

""") # ── Input text box ── with gr.Column(elem_classes=["section-gap"]): input_text = gr.Textbox( placeholder = "Paste your scientific text here. Each sentence will be analyzed individually...", label = "", lines = 6, max_lines = 20, elem_classes = ["rounded-input"], show_label = False ) # ── Dropdown (left) + Analyze button (right) ── with gr.Row(equal_height=True): engine_dropdown = gr.Dropdown( choices = ENGINES, value = "— Select from dropdown —", label = "Choose Engine", interactive = True, scale = 3, min_width = 240, elem_classes = ["engine-dropdown"] ) analyze_btn = gr.Button( value = "Analyze →", variant = "primary", scale = 1, elem_classes = ["analyze-btn"] ) # ── Output textbox with built-in copy button ── output_text = gr.Textbox( label = "Output", lines = 14, max_lines = 30, interactive = False, show_copy_button = True, # Built-in copy button show_label = True, placeholder = "Results will appear here after analysis...", elem_classes = ["rounded-output", "section-gap"] ) # ── Engine description (collapses by default) ── with gr.Accordion("Engine descriptions", open=False): gr.Markdown(""" | Engine | Speed | Description | |--------|-------|-------------| | **Supersonic (Fast)** | ⚡ Instant | CSV phrase lookup — no model loading needed | | **Go Deep (Llama)** | 🐢 Slow | LLaMA 1B fine-tuned adapter | | **Hybimix (Llama + Supersonic)** | 🐢 Slow | Both engines merged with confidence scoring | | **Go Deep Max (Sarvam)** | 🐢 Slow | Sarvam 2B fine-tuned adapter | | **Hybimix Max (Sarvam + Supersonic)** | 🐢 Slow | Both engines merged with confidence scoring | > ⚠ **Note :** AI engines (Go Deep / Hybimix) run on CPU and may take **several minutes** per request. > Use **Supersonic (Fast)** for instant results. """) # ── Wire Analyze button to function ── analyze_btn.click( fn = analyze, inputs = [input_text, engine_dropdown], outputs = output_text, show_progress = "minimal" ) # ── Also trigger on Enter key in text box ── input_text.submit( fn = analyze, inputs = [input_text, engine_dropdown], outputs = output_text, show_progress = "minimal" )