File size: 24,160 Bytes
2a38383
 
744ae62
2a38383
 
 
 
 
 
31e7cd4
2a38383
 
7f40688
6a5ed84
2a38383
 
31e7cd4
2a38383
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6a5ed84
2a38383
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7f40688
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b2007f3
 
 
 
2a38383
03e0f64
 
2a38383
d3403e1
 
 
 
 
 
 
 
 
2a38383
03e0f64
2a38383
03e0f64
d3403e1
 
 
03e0f64
2a38383
03e0f64
2a38383
03e0f64
 
 
 
d3403e1
 
03e0f64
b2007f3
03e0f64
 
 
d3403e1
 
03e0f64
d8efb74
 
 
 
b2007f3
 
 
 
 
 
 
 
d8efb74
 
 
 
 
 
 
 
 
03e0f64
2a38383
 
 
03e0f64
 
d8efb74
03e0f64
d3403e1
d8efb74
 
 
03e0f64
 
 
d3403e1
03e0f64
 
 
b2007f3
 
d3403e1
 
03e0f64
2a38383
 
 
03e0f64
 
2a38383
 
03e0f64
d3403e1
 
2a38383
 
 
d3403e1
 
 
b2007f3
 
 
03e0f64
 
 
 
 
 
2a38383
b2007f3
d3403e1
 
b2007f3
 
03e0f64
2a38383
d3403e1
03e0f64
 
2a38383
03e0f64
 
 
 
 
d3403e1
03e0f64
 
 
d8efb74
03e0f64
 
 
 
 
 
 
d8efb74
03e0f64
 
 
 
d3403e1
03e0f64
d3403e1
 
03e0f64
d8efb74
03e0f64
d3403e1
d8efb74
03e0f64
7f40688
03e0f64
 
 
 
 
 
 
 
d3403e1
7f40688
 
03e0f64
 
 
7f40688
 
03e0f64
 
 
7f40688
 
d3403e1
 
03e0f64
d3403e1
03e0f64
 
 
 
 
 
 
d3403e1
03e0f64
 
 
 
d3403e1
 
7f40688
03e0f64
 
 
 
 
 
 
 
 
d3403e1
7f40688
03e0f64
 
 
7f40688
03e0f64
 
d3403e1
 
7f40688
d3403e1
 
2a38383
 
 
 
 
 
b2007f3
2a38383
 
03e0f64
d3403e1
2a38383
d3403e1
2a38383
 
 
b2007f3
03e0f64
 
d8efb74
 
03e0f64
2a38383
b2007f3
2a38383
22e57d2
2a38383
03e0f64
 
 
 
 
 
 
 
 
 
 
 
 
 
2a38383
03e0f64
 
 
2a38383
 
 
 
7f40688
 
 
 
 
 
 
 
 
 
 
 
 
 
03e0f64
 
7f40688
2a38383
7f40688
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a38383
7f40688
 
03e0f64
7f40688
03e0f64
7f40688
03e0f64
7f40688
 
03e0f64
d3403e1
7f40688
 
2a38383
7f40688
 
 
 
03e0f64
 
7f40688
2a38383
7f40688
 
 
 
 
03e0f64
 
2a38383
7f40688
 
 
 
03e0f64
 
2a38383
 
 
d3403e1
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
"""
Angkit Sarma — Living CV (Gradio edition)

An interactive resume with a self-querying "Ask the CV" panel. The retrieval
engine is a real TF-IDF + cosine-similarity ranker over the resume's own
content (scikit-learn) — the same underlying idea as the semantic-search
optimization work described in the Experience section below, just visible
and playable instead of buried in a bullet point.
"""

import gradio as gr
import numpy as np
import pandas as pd
import spaces
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

CORPUS = [
    {"tag": "Experience · Flexday AI", "text": "Built and pitched INFERA, an AI-powered agentic solution that maps sales projects to real-world opportunities, winning 1st place at the Flexday AI Hackathon."},
    {"tag": "Experience · Flexday AI", "text": "Optimized a semantic search system using LLM and embedding based techniques, improving retrieval performance by 50 percent and enhancing user experience."},
    {"tag": "Experience · Flexday AI", "text": "Designed and implemented automated AI assisted workflows across departments, cutting process cycle time by 5 percent and freeing up 10 or more hours per month."},
    {"tag": "Experience · Flexday AI", "text": "Implemented OCR based data extraction pipelines across diverse image collections, improving data extraction accuracy and processing efficiency."},
    {"tag": "Experience · Flexday AI", "text": "Identified and remediated critical application security vulnerabilities, mitigating million dollar risk exposure and strengthening system security."},
    {"tag": "Experience · Flexday AI", "text": "Streamlined CI/CD build pipelines by reducing redundant steps, accelerating deployment times, using Git, GitHub, Jira and Azure DevOps."},
    {"tag": "Experience · Leokraft", "text": "Designed, trained and deployed end to end machine learning models into production, improving model accuracy by 8 percent while cutting infrastructure costs by 20 percent."},
    {"tag": "Experience · Leokraft", "text": "Engineered a key target variable feature that improved model accuracy by 5 percent."},
    {"tag": "Experience · Leokraft", "text": "Developed an end to end application for managing model scores and usage statistics, driving higher stakeholder engagement."},
    {"tag": "Experience · CodingZen", "text": "Taught over 100 students full stack web development with Node.js, from foundational HTML and CSS to advanced backend engineering, while supervising a team of teaching staff."},
    {"tag": "Project · INFERA", "text": "INFERA is an agentic AI system built with large language models that autonomously analyzes sales pipeline data and maps projects to real world business opportunities. Won first place at the Flexday AI Hackathon."},
    {"tag": "Project · Analytica", "text": "Analytica is a full stack data analytics platform built with React, Python, Azure and SQL, showing machine learning model performance and usage statistics."},
    {"tag": "Project · Predictive Allocation", "text": "Predictive Allocation re-engineered an end to end model training and deployment pipeline on Azure SQL and Azure Blob, hardened with Snyk and Wiz security scanning, and modernized legacy code."},
    {"tag": "Skills · AI/ML", "text": "Core AI and machine learning skills include large language models, generative AI, agentic AI and AI agents, prompt engineering, semantic search, classification, regression, decision trees, and SMOTE."},
    {"tag": "Skills · Cloud & MLOps", "text": "Cloud and MLOps skills include Microsoft Azure, Azure SQL, Azure Blob Storage, serverless architecture, virtual machines, and CI/CD pipelines."},
    {"tag": "Skills · Programming", "text": "Programming languages and runtimes include Python, JavaScript and Node.js."},
    {"tag": "Certifications", "text": "Certifications include Building with the Claude API, Generative AI professional certificate, AI Fluency Framework and Foundations, Machine Learning for Leaders, and Analyze Box Office Data with Seaborn and Python."},
    {"tag": "Education", "text": "M.Tech in Information Technology from Tezpur University, graduated with distinction at 8.69 CGPA, with a full time AICTE scholarship. B.Tech in Computer Science and Engineering from KIET, first division."},
]

_texts = [c["text"] for c in CORPUS]
_vectorizer = TfidfVectorizer(stop_words="english")
_doc_matrix = _vectorizer.fit_transform(_texts)


def retrieve(query: str, top_k: int = 3):
    if not query or not query.strip():
        return []
    q_vec = _vectorizer.transform([query])
    sims = cosine_similarity(q_vec, _doc_matrix)[0]
    ranked_idx = np.argsort(sims)[::-1]
    results = []
    for i in ranked_idx[:top_k]:
        if sims[i] <= 0:
            continue
        results.append({**CORPUS[i], "score": float(sims[i])})
    return results


@spaces.GPU
def ask_the_cv(query, history):
    history = history or []
    results = retrieve(query)

    if not results:
        answer = ("No strong match in the résumé index for that — try asking about "
                   "experience, projects, skills, or certifications.")
    else:
        top = results[0]
        answer = f"**{top['tag']}** — {top['text']}"
        if len(results) > 1:
            answer += "\n\n**Also relevant:**\n"
            for r in results[1:]:
                answer += f"\n- _{r['tag']}_ ({r['score']*100:.0f}% match): {r['text']}"

    history.append({"role": "user", "content": query})
    history.append({"role": "assistant", "content": answer})
    return history, ""


EXAMPLE_QUERIES = [
    "What is your experience with LLMs and generative AI?",
    "Tell me about INFERA",
    "What are your cloud and deployment skills?",
    "Have you done any teaching or mentoring?",
    "What certifications do you have?",
]

SKILLS_DF = pd.DataFrame([
    {"Category": "AI/ML & GenAI", "Skills": "LLMs, Generative AI, Agentic AI, Prompt Engineering, Semantic Search, Classification, Regression, Decision Trees, SMOTE, OCR/NLP"},
    {"Category": "Programming", "Skills": "Python, JavaScript, Node.js"},
    {"Category": "Cloud & MLOps", "Skills": "Microsoft Azure, Azure SQL, Azure Blob, Serverless, Virtual Machines, CI/CD"},
    {"Category": "Tools & Practices", "Skills": "Git, GitHub, Jira, Azure DevOps, Snyk, Wiz, Agile"},
])

IMPACT_DF = pd.DataFrame([
    {"Metric": "Hackathon placement", "Company": "Flexday AI (INFERA)", "Result": "🏆 1st"},
    {"Metric": "Semantic search retrieval improvement", "Company": "Flexday AI", "Result": "+50%"},
    {"Metric": "Infrastructure cost reduction", "Company": "Leokraft", "Result": "-20%"},
    {"Metric": "ML model accuracy improvement", "Company": "Leokraft", "Result": "+8%"},
    {"Metric": "Feature-engineering accuracy gain", "Company": "Leokraft", "Result": "+5%"},
    {"Metric": "Process cycle-time reduction", "Company": "Flexday AI", "Result": "-5%"},
    {"Metric": "Students taught (full-stack web dev)", "Company": "CodingZen", "Result": "100+"},
])

CERTS_DF = pd.DataFrame([
    {"Certification": "Building with the Claude API", "Focus": "LLM application development"},
    {"Certification": "Generative AI (Professional Certificate)", "Focus": "Generative AI fundamentals"},
    {"Certification": "AI Fluency: Framework & Foundations", "Focus": "Applied AI literacy"},
    {"Certification": "Machine Learning for Leaders", "Focus": "ML strategy"},
    {"Certification": "Analyze Box Office Data with Seaborn and Python", "Focus": "Data analysis & visualization"},
])

EDUCATION_DF = pd.DataFrame([
    {"Degree": "M.Tech, Information Technology", "Institution": "Tezpur University", "Years": "2019–2021", "Highlight": "Distinction, 8.69 CGPA, full AICTE scholarship"},
    {"Degree": "B.Tech, Computer Science & Engineering", "Institution": "KIET Group of Institutions", "Years": "2012–2016", "Highlight": "First Division"},
])

# ---------------------------------------------------------------------------
# Styling — "Aurora" theme: deep indigo base, violet -> coral gradient accent,
# mint accent for data. Hero content is centered.
# ---------------------------------------------------------------------------
CUSTOM_CSS = """
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600;700&display=swap');

:root {
    --blue: #2563eb;
    --blue-deep: #0ea5e9;
    --cyan: #06b6d4;
    --bg-0: #f7fafc;
    --card: #ffffff;
    --card-border: #e2e8f0;
    --text-heading: #0f172a;
    --text-dim: #475569;
    --text-faint: #94a3b8;
}

.gradio-container {
    background:
        radial-gradient(ellipse 900px 520px at 50% -8%, rgba(37,99,235,0.07) 0%, transparent 62%),
        radial-gradient(ellipse 700px 600px at 100% 20%, rgba(6,182,212,0.06) 0%, transparent 55%),
        radial-gradient(ellipse 1400px 900px at 50% 0%, #eef4ff 0%, var(--bg-0) 55%) !important;
    background-attachment: fixed !important;
    font-family: 'Inter', sans-serif !important;
    position: relative;
}
.gradio-container::before {
    content: "";
    position: fixed; inset: 0; pointer-events: none; z-index: 0;
    background-image:
        linear-gradient(rgba(15,23,42,0.03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(15,23,42,0.03) 1px, transparent 1px);
    background-size: 48px 48px;
    mask-image: radial-gradient(ellipse 1000px 600px at 50% 0%, black 0%, transparent 70%);
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg-0); }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: var(--blue); }

@keyframes revealUp {
    from { opacity: 0; transform: translateY(22px); }
    to   { opacity: 1; transform: translateY(0); }
}
#hero-wrap {
    text-align: center;
    max-width: 760px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
}
.status-badge, #hero-name, #hero-headline, #hero-bio, #hero-contact {
    opacity: 0;
    animation: revealUp 0.7s cubic-bezier(.16,1,.3,1) forwards;
}
.status-badge { animation-delay: 0.05s; }
#hero-name     { animation-delay: 0.15s; }
#hero-headline { animation-delay: 0.28s; }
#hero-bio      { animation-delay: 0.40s; }
#hero-contact  { animation-delay: 0.52s; }

#hero-name {
    font-family: 'Space Grotesk', sans-serif !important;
    font-weight: 700 !important;
    font-size: 60px !important;
    letter-spacing: -0.025em !important;
    line-height: 1.05 !important;
    margin-bottom: 6px !important;
    background: linear-gradient(135deg, #0f172a 0%, #1d4ed8 60%, #06b6d4 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}
#hero-headline {
    display: inline-block;
    color: #1d4ed8 !important;
    font-family: 'Space Grotesk', sans-serif !important;
    font-weight: 600 !important;
    font-size: 18px !important;
    margin-top: 10px !important;
    padding: 6px 18px !important;
    background: linear-gradient(90deg, rgba(37,99,235,0.08), rgba(6,182,212,0.08));
    border: 1px solid rgba(37,99,235,0.25);
    border-radius: 999px;
}
.status-badge {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: 'JetBrains Mono', monospace; font-size: 12px; letter-spacing: 0.12em;
    color: var(--text-dim); text-transform: uppercase; margin-bottom: 14px;
}
.dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--blue);
    box-shadow: 0 0 10px 2px rgba(37,99,235,0.55);
    display: inline-block; animation: pulse 2.2s infinite;
}
@keyframes pulse {
    0% { box-shadow: 0 0 0 0 rgba(37,99,235,.45), 0 0 10px 2px rgba(37,99,235,0.55); }
    70% { box-shadow: 0 0 0 9px rgba(37,99,235,0), 0 0 10px 2px rgba(37,99,235,0.55); }
    100% { box-shadow: 0 0 0 0 rgba(37,99,235,0), 0 0 10px 2px rgba(37,99,235,0.55); }
}
#hero-contact {
    display: flex !important; flex-wrap: wrap; justify-content: center; gap: 8px; align-items: center;
}
#hero-contact a {
    color: var(--text-dim); text-decoration: none;
    padding: 4px 12px; border-radius: 999px;
    border: 1px solid var(--card-border); background: var(--card);
    transition: all .18s ease;
}
#hero-contact a:hover {
    color: #ffffff !important;
    background: linear-gradient(90deg, var(--blue), var(--cyan));
    border-color: transparent;
}

.section-label {
    font-family: 'JetBrains Mono', monospace !important; color: var(--blue) !important;
    letter-spacing: 0.12em !important; text-transform: uppercase; font-size: 12.5px !important;
    font-weight: 600 !important;
}

.ask-card {
    background: var(--card) !important;
    border: 1px solid var(--card-border) !important;
    border-radius: 18px !important;
    box-shadow: 0 20px 50px -24px rgba(15,23,42,0.18), 0 4px 12px -6px rgba(15,23,42,0.06) !important;
    padding: 22px !important;
    position: relative;
    z-index: 1;
}
.ask-titlebar {
    display: flex; align-items: center; gap: 8px; margin-bottom: 14px;
    font-family: 'JetBrains Mono', monospace; font-size: 11.5px; color: var(--text-faint);
    letter-spacing: 0.08em;
}
.ask-titlebar .tl-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }

.gradio-container button {
    transition: transform .16s ease, border-color .16s ease, box-shadow .16s ease, background .16s ease !important;
}
.gradio-container button:hover { transform: translateY(-2px); }
button.primary, button[class*="primary"] {
    background: linear-gradient(135deg, var(--blue) 0%, var(--cyan) 100%) !important;
    border: none !important;
    box-shadow: 0 8px 20px -8px rgba(37,99,235,0.45) !important;
    color: #ffffff !important;
    font-weight: 700 !important;
}
button.primary:hover, button[class*="primary"]:hover {
    box-shadow: 0 12px 28px -8px rgba(6,182,212,0.5) !important;
}

.tabs > .tab-nav {
    border-bottom: none !important;
    background: var(--card);
    border: 1px solid var(--card-border);
    border-radius: 999px !important;
    padding: 5px !important;
    display: inline-flex !important;
    gap: 2px !important;
    margin-bottom: 18px;
    box-shadow: 0 2px 8px -4px rgba(15,23,42,0.08);
}
.tabs > .tab-nav button {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12.5px !important;
    color: var(--text-dim) !important;
    border: none !important;
    background: transparent !important;
    border-radius: 999px !important;
    padding: 9px 18px !important;
    margin: 0 !important;
}
.tabs > .tab-nav button.selected {
    background: linear-gradient(135deg, var(--blue) 0%, var(--cyan) 100%) !important;
    color: #ffffff !important;
    font-weight: 700 !important;
    box-shadow: 0 6px 16px -6px rgba(37,99,235,0.5);
}

.proj-card {
    background: var(--card) !important;
    border: 1px solid var(--card-border) !important;
    border-radius: 14px !important;
    padding: 18px !important;
    box-shadow: 0 2px 8px -4px rgba(15,23,42,0.06);
    transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease !important;
}
.proj-card:hover {
    transform: translateY(-4px);
    border-color: rgba(37,99,235,0.35) !important;
    box-shadow: 0 16px 36px -18px rgba(37,99,235,0.28) !important;
}

.gr-accordion, [class*="accordion"] {
    border-radius: 14px !important;
}

.cv-table {
    border-radius: 14px !important;
    overflow: hidden !important;
    border: 1px solid var(--card-border) !important;
    box-shadow: 0 12px 28px -20px rgba(15,23,42,0.2);
}
.cv-table table { font-size: 13.5px !important; }
.cv-table thead th {
    font-family: 'JetBrains Mono', monospace !important;
    text-transform: uppercase !important;
    font-size: 10.5px !important;
    letter-spacing: 0.08em !important;
    color: var(--blue) !important;
    background: rgba(37,99,235,0.06) !important;
}
.cv-table tbody tr:nth-child(even) { background: rgba(15,23,42,0.015) !important; }
.cv-table tbody tr:hover { background: rgba(37,99,235,0.05) !important; }
"""

with gr.Blocks(title="Angkit Sarma — Living CV") as demo:

    gr.HTML(
        """
        <div id="hero-wrap">
        <div class="status-badge"><span class="dot"></span> resume · live · self-querying</div>
        <div id="hero-name">Angkit Sarma</div>
        <div><span id="hero-headline">AI/ML Engineer — Agentic Systems &amp; LLM Applications</span></div>
        <p id="hero-bio" style="color:#475569; max-width:680px; margin-top:16px; line-height:1.6;">
        4+ years building and shipping ML and generative AI systems — from a 50%-faster semantic
        search pipeline to <b style="color:#0f172a">INFERA</b>, an agentic AI tool that won 1st place
        at the Flexday AI Hackathon. Ask the panel below anything about my experience — it's a live
        TF-IDF retrieval engine running over this résumé's own content.
        </p>
        <p id="hero-contact" style="font-family:'JetBrains Mono',monospace; font-size:12.5px; margin-top:16px;">
        <a href="tel:+919990797061">+91 9990797061</a>
        <a href="mailto:angkit93@gmail.com">angkit93@gmail.com</a>
        <a href="https://www.linkedin.com/in/angkit-s-81b7131b0/" target="_blank">LinkedIn</a>
        <a href="https://github.com/angkit-hash" target="_blank">GitHub</a>
        <a href="#" style="pointer-events:none;">Hyderabad, India</a>
        </p>
        </div>
        """
    )

    gr.HTML('<p class="section-label" style="margin-top:8px;">// ask the cv</p>')
    with gr.Group(elem_classes=["ask-card"]):
        gr.HTML(
            '<div class="ask-titlebar">'
            '<span class="tl-dot" style="background:#ff5f57;"></span>'
            '<span class="tl-dot" style="background:#febc2e;"></span>'
            '<span class="tl-dot" style="background:#28c840;"></span>'
            '&nbsp;&nbsp;ask_the_cv.py — live TF-IDF retrieval, runs in this Space'
            '</div>'
        )
        chatbot = gr.Chatbot(label=None, height=320, show_label=False)
        with gr.Row():
            query_box = gr.Textbox(placeholder="e.g. What's your experience with LLMs?", scale=5, show_label=False, container=False)
            ask_btn = gr.Button("Ask", variant="primary", scale=1)

        with gr.Row():
            for q in EXAMPLE_QUERIES:
                gr.Button(q, size="sm").click(fn=ask_the_cv, inputs=[gr.State(q), chatbot], outputs=[chatbot, query_box])

    ask_btn.click(fn=ask_the_cv, inputs=[query_box, chatbot], outputs=[chatbot, query_box])
    query_box.submit(fn=ask_the_cv, inputs=[query_box, chatbot], outputs=[chatbot, query_box])

    with gr.Tabs():
        with gr.Tab("Overview"):
            gr.Markdown(
                "Results-driven AI/ML Engineer with 4+ years designing, training, and deploying machine "
                "learning and generative AI systems that solve real business problems. Proven track record "
                "building agentic AI and LLM-powered applications, optimizing semantic search and NLP "
                "pipelines, and automating end-to-end ML workflows from data processing to production "
                "deployment. Combines strong ML engineering fundamentals with cloud deployment, MLOps, and "
                "application security expertise to ship secure, scalable, high-impact AI solutions."
            )
            gr.HTML('<p class="section-label" style="margin-top:22px;">// impact metrics</p>')
            gr.Dataframe(
                value=IMPACT_DF, interactive=False, wrap=True,
                column_widths=["55%", "25%", "20%"],
                row_count=(len(IMPACT_DF), "fixed"),
                elem_classes=["cv-table"],
            )

        with gr.Tab("Experience"):
            with gr.Accordion("Software Developer (AI/ML Focus) — Flexday AI, Hyderabad · Nov 2022 – Present", open=True):
                gr.Markdown(
                    "- Built and pitched **INFERA**, an AI-powered agentic solution that maps sales projects "
                    "to real-world opportunities — 1st place at the Flexday AI Hackathon\n"
                    "- Optimized a semantic search system using LLM/embedding-based techniques, improving "
                    "retrieval performance by **50%**\n"
                    "- Designed automated, AI-assisted workflows across departments, cutting process cycle "
                    "time by 5% and freeing 10+ hours/month\n"
                    "- Implemented OCR-based data extraction pipelines across diverse image collections\n"
                    "- Identified and remediated critical security vulnerabilities, mitigating million-dollar "
                    "risk exposure\n"
                    "- Streamlined CI/CD build pipelines using Git, GitHub, Jira, and Azure DevOps"
                )
            with gr.Accordion("Machine Learning Engineer — Leokraft Technologies, Bangalore · Dec 2021 – Dec 2022", open=False):
                gr.Markdown(
                    "- Designed, trained, and deployed end-to-end ML models into production, improving "
                    "accuracy by **8%** while cutting infrastructure costs by **20%**\n"
                    "- Engineered a key target-variable feature that improved model accuracy by 5%\n"
                    "- Built an end-to-end application for managing model scores and usage statistics"
                )
            with gr.Accordion("Senior Faculty — CodingZen, Delhi · Jul 2018 – Jul 2019", open=False):
                gr.Markdown(
                    "- Taught 100+ students full-stack web development with Node.js\n"
                    "- Supervised and mentored a team of teaching staff"
                )

        with gr.Tab("Projects"):
            with gr.Row():
                with gr.Column(elem_classes=["proj-card"]):
                    gr.Markdown("**INFERA** — Agentic AI Sales-Opportunity Mapper\n\n*LLMs · AI Agents · Python*\n\nAn AI agent that analyzes sales pipeline data and autonomously maps projects to real-world business opportunities.\n\n🏆 1st Place — Flexday AI Hackathon")
                with gr.Column(elem_classes=["proj-card"]):
                    gr.Markdown("**Analytica** — End-to-End ML Analytics Platform\n\n*React · Python · Azure · SQL*\n\nFull-stack analytics tool surfacing ML model performance metrics and usage statistics.")
                with gr.Column(elem_classes=["proj-card"]):
                    gr.Markdown("**Predictive Allocation** — ML Deployment Pipeline\n\n*Python · Azure SQL · Azure Blob · DevOps*\n\nRe-engineered end-to-end training/deployment pipeline; hardened security with Snyk and Wiz.")
            gr.HTML(
                '<p style="font-family:\'JetBrains Mono\',monospace; font-size:13px; margin-top:14px;">'
                '<a href="https://github.com/angkit-hash" target="_blank" style="color:#0ea5e9; text-decoration:none; border-bottom:1px solid #0ea5e9;">'
                '→ View source &amp; more projects on GitHub</a></p>'
            )

        with gr.Tab("Skills"):
            gr.Dataframe(
                value=SKILLS_DF, interactive=False, wrap=True,
                column_widths=["25%", "75%"],
                row_count=(len(SKILLS_DF), "fixed"),
                elem_classes=["cv-table"],
            )

        with gr.Tab("Certifications & Education"):
            gr.HTML('<p class="section-label">Certifications</p>')
            gr.Dataframe(
                value=CERTS_DF, interactive=False, wrap=True,
                column_widths=["55%", "45%"],
                row_count=(len(CERTS_DF), "fixed"),
                elem_classes=["cv-table"],
            )
            gr.HTML('<p class="section-label" style="margin-top:22px;">Education</p>')
            gr.Dataframe(
                value=EDUCATION_DF, interactive=False, wrap=True,
                column_widths=["30%", "28%", "14%", "28%"],
                row_count=(len(EDUCATION_DF), "fixed"),
                elem_classes=["cv-table"],
            )

if __name__ == "__main__":
    demo.launch(css=CUSTOM_CSS, theme=gr.themes.Base(primary_hue="blue", neutral_hue="slate"))