File size: 7,949 Bytes
f399b82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6e2d2c
 
f399b82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a1b219
 
f399b82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# --- 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()