Spaces:
Runtime error
Runtime error
| # --- 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''' | |
| <div class="pill"><span class="dot"></span> Online • Mulhim</div> | |
| <br><img src="{LOGO_URL}" alt="Omantel Logo"> | |
| ''') | |
| with gr.Column(scale=1, elem_classes="title"): | |
| gr.HTML(""" | |
| <h1>Mulhim — Omantel Knowledge Assistant</h1> | |
| <p>Answers are <b>strictly</b> grounded in your indexed PDF(s). If it’s not in the file, you’ll be told.</p> | |
| """) | |
| with gr.Column(scale=0): | |
| gr.HTML("") # spacer | |
| # Explainer / Hero | |
| gr.HTML(""" | |
| <div class="hero panel"> | |
| <h2>How it works</h2> | |
| <p>Ask about internal applications, steps, or focal points. Mulhim cites only what's inside your indexed document.</p> | |
| </div> | |
| """) | |
| 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('<div class="helper">Tip: Mention the process or department for best results. Press <kbd>Enter</kbd> to submit.</div>') | |
| # 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('<div class="small-note">If the answer isn’t found in the PDF, you’ll see: <i>“I couldn’t find that in the document.”</i></div>') | |
| # 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'<div class="footer">Pinecone index: <b>{index_name}</b> • Namespace: <b>{PINECONE_NAMESPACE}</b> • LlamaIndex + Pinecone</div>') | |
| # 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() | |