AymanAlmaawali's picture
Update app.py
f399b82 verified
raw
history blame
7.95 kB
# --- 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()