# --- Gradio UI (Aurora Glass theme) --- LOGO_URL = "https://raw.githubusercontent.com/Decoding-Data-Science/Omantel/main/Omantel_Logo%20(1).png" CUSTOM_CSS = """ :root{ --bg:#0a0f1c; --panel:#0f1629f2; --stroke:#1d2740; --muted:#96a3be; --brand:#2e90fa; --accent:#f59e0b; --ok:#10b981; --danger:#ef4444; } .gradio-container{ font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial !important; } body{ background: radial-gradient(1100px 500px at 10% -10%, #2e90fa22, transparent 70%), radial-gradient(1000px 500px at 110% 10%, #f59e0b18, transparent 60%), linear-gradient(180deg, var(--bg) 0%, #0a0f1c 100%); } .header{ position:relative; padding:18px 12px 8px; border-bottom:1px solid var(--stroke); display:grid; grid-template-columns: 140px 1fr 140px; align-items:center; gap:12px; } .header .logo img{height:50px;object-fit:contain; filter: drop-shadow(0 4px 14px rgba(0,0,0,.25));} .title{ text-align:center; color:#e5e7eb; } .title h1{ margin:0; font-weight:800; font-size:1.7rem; letter-spacing:.2px; } .title p{ margin:6px 0 0; color:var(--muted); font-size:.95rem; } .pill{ display:inline-flex; align-items:center; gap:8px; padding:6px 10px; border-radius:999px; font-size:12px; background:linear-gradient(180deg,#0d1425,#0a1222); border:1px solid var(--stroke); color:#cbd5e1; } .pill .dot{width:8px;height:8px;border-radius:999px;background:var(--ok); box-shadow:0 0 0 4px #10b98126;} .panel{ background:var(--panel); border:1px solid var(--stroke); border-radius:16px; padding:16px; backdrop-filter: blur(10px); box-shadow:0 12px 36px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.03); } .hero{ position:relative; border-radius:18px; padding:18px; margin-top:8px; border:1px solid #25314e; background: radial-gradient(800px 200px at 12% -12%, rgba(46, 144, 250, .24), transparent 70%), radial-gradient(700px 140px at 90% 0%, rgba(245, 158, 11, .14), transparent 60%), linear-gradient(180deg, #0d1428, #0c1224); } .hero h2{margin:0 0 6px;color:#e5e7eb;font-weight:700; font-size:1.1rem;} .hero p{margin:0;color:var(--muted);font-size:.95rem;} .label, label{color:#dbe3f0 !important; font-weight:600 !important;} .helper{font-size:12px;color:#9aa5b1;margin-top:6px;} .chips{display:flex; gap:8px; flex-wrap:wrap; margin-top:8px;} .chip{ cursor:pointer; user-select:none; padding:8px 12px; border-radius:12px; font-size:.9rem; background:#0b1222; border:1px solid #273043; color:#cbd5e1; } .chip:hover{border-color:#35507a} .actions{display:flex; gap:8px; flex-wrap:wrap;} button.primary{ background:linear-gradient(180deg,#3b82f6,#1e40af); color:white; border:1px solid #1e3a8a; } button.secondary{ background:#0b1222; color:#cbd5e1; border:1px solid #273043; } .footer{ text-align:center; font-size:12px; color:#94a3b8; padding:12px 0 0;} #answer_box{min-height:200px;} .small-note{font-size:12px;color:#9aa5b1;} kbd{ background:#0f172a; color:#e5e7eb; border:1px solid #334155; border-bottom-width:2px; padding:2px 6px; border-radius:6px; font-size:.8em; } """ with gr.Blocks(css=CUSTOM_CSS, title="Mulhim • Omantel Knowledge Assistant (Aurora)") as demo: # Header with gr.Row(elem_classes="header"): with gr.Column(scale=0, elem_classes="logo"): gr.HTML(f'''
Online • Mulhim

Omantel Logo ''') with gr.Column(scale=1, elem_classes="title"): gr.HTML("""

Mulhim — Omantel Knowledge Assistant

Answers are strictly grounded in your indexed PDF(s). If it’s not in the file, you’ll be told.

""") with gr.Column(scale=0): gr.HTML("") # spacer # Explainer / Hero gr.HTML("""

How it works

Ask about internal applications, steps, or focal points. Mulhim cites only what's inside your indexed document.

""") with gr.Row(): # Left: Ask + Answer with gr.Column(scale=7): with gr.Group(elem_classes="panel"): inp = gr.Textbox( label="Your question", placeholder="e.g., Procurement System — steps and owner contact?", lines=3, autofocus=True ) with gr.Row(elem_classes="actions"): ask_btn = gr.Button("Ask Mulhim", variant="primary", elem_classes="primary") clear_btn = gr.Button("Clear", variant="secondary", elem_classes="secondary") gr.Markdown('
Tip: Mention the process or department for best results. Press Enter to submit.
') # quick chips with gr.Row(elem_classes="chips"): chip1 = gr.Button("Focal point • Technology Strategy", elem_id=None, elem_classes="chip", variant="secondary") chip2 = gr.Button("Steps • New vendor contract", elem_classes="chip", variant="secondary") chip3 = gr.Button("Process • Customer complaints (CEX)", elem_classes="chip", variant="secondary") chip4 = gr.Button("Finance • Budget reallocation", elem_classes="chip", variant="secondary") with gr.Group(elem_classes="panel"): out = gr.Textbox( label="Answer", lines=14, elem_id="answer_box", show_copy_button=True ) gr.Markdown('
If the answer isn’t found in the PDF, you’ll see: “I couldn’t find that in the document.”
') # Right: Examples + Notes with gr.Column(scale=5): with gr.Group(elem_classes="panel"): gr.Markdown("**Quick examples**") examples = gr.Examples( examples=[ ["Who is the focal point for Technology Strategy and how can I reach them?"], ["I need to submit a new vendor contract. Which application and steps?"], ["For customer complaints (CEX), what's the process and owner contact?"], ["Finance: how to request a budget reallocation and who to email?"], ], inputs=inp, ) with gr.Group(elem_classes="panel"): gr.Markdown("**Notes**") gr.Markdown( "- Answers are sourced only from the indexed PDF/document.\n" "- If information isn’t found, Mulhim will say so.\n" "- For department-specific queries, the related contact is shown if present in the doc." ) gr.Markdown(f'') # Interactions ask_btn.click(fn=query_doc, inputs=inp, outputs=out) inp.submit(fn=query_doc, inputs=inp, outputs=out) clear_btn.click(lambda: ("", ""), inputs=None, outputs=[inp, out]) # Chip wiring (pre-fill the input, then auto-ask) chip1.click(lambda: "Who is the focal point for Technology Strategy and how can I reach them?", outputs=inp).then(query_doc, inp, out) chip2.click(lambda: "I need to submit a new vendor contract. Which application and steps?", outputs=inp).then(query_doc, inp, out) chip3.click(lambda: "For customer complaints (CEX), what's the process and owner contact?", outputs=inp).then(query_doc, inp, out) chip4.click(lambda: "Finance: how to request a budget reallocation and who to email?", outputs=inp).then(query_doc, inp, out) demo.launch()