Portfolio_ML / app.py
JanviMl's picture
Update app.py
357fcad verified
import gradio as gr
# Project data - expanded with examples to demonstrate the showcase functionality
projects = [
{
"name": "Toxic Comment Classifier",
"description": "An NLP model to detect toxic comments in real-time, built with transformers and deployed as an interactive app. Highlights my skills in natural language processing and UI integration.",
"impact": "Achieved 90%+ accuracy on a diverse dataset; fine-tuned for low latency to handle real-time inputs.",
"link": "https://huggingface.co/spaces/JanviMl/toxic-comment-classifier",
"built_with": "Transformers, Python, Gradio",
"category": "NLP"
},
{
"name": "ToxiScan",
"description": "application that classifies images as toxic or non-toxic using a pre-trained Vision Transformer (ViT) model from Hugging Face.",
"impact": "Leverages a pre-trained ViT model (`google/vit-base-patch16-224`) to predict if an image is toxic or non-toxic.Results are shown with the uploaded image, prediction label, confidence percentages, and a bar chart.",
"link": "https://huggingface.co/spaces/JanviMl/ToxiScan",
"built_with": "PyTorch, VIT, Python, StreamLit",
"category": "Computer Vision"
},
{
"name": "STLC-AI: Generative QA Automation for Insurance Billing Systems",
"description": "STLC-AI demonstrates an end-to-end automated testing lifecycle that transforms user stories into executable test scenarios using advanced language models.",
"impact": "This project specifically targets insurance billing and payment systems, providing a realistic simulation of AI-driven QA automation.",
"link": "https://huggingface.co/spaces/JanviMl/QA_VAM",
"built_with": "Python 3.10+ | Gradio Framework | Multi-LLM Integration (OpenAI, Anthropic) | Plotly Visualization | Cloud-Native Deployment",
"category": "Generative AI"
},
{
"name": "Enhanced FinSolve AI Assistant",
"description": "A production-ready RAG (Retrieval-Augmented Generation) system for FinSolve Technologies featuring advanced RBAC enforcement, interactive visualizations, and comprehensive security measures.",
"impact": "Advanced RAG System with Role-Based Access Control, Visualizations, and Enhanced Security",
"link": "https://huggingface.co/spaces/JanviMl/RAGFintech",
"built_with": "Tech Stack: Python, FastAPI, Streamlit, OpenAI GPT, ChromaDB,LangChain, SentenceTransformers, Plotly, JWT, RBAC, HuggingFace Spaces",
"category": " RAG "
},
{
"name": "MFPModelEvaluator",
"description": "A Streamlit app to compare MFP effectuation models (Direct Discount vs. Rebate) based on the blog Cracking the MFP Code.",
"impact": "Compare models on usability, speed, and cash flow",
"link": "https://huggingface.co/spaces/JanviMl/MFPModelEvaluator",
"built_with": " Streamlit, Pandas, Matplotlib",
"category": "Data Visualization"
},
{
"name": "AI Hallucination",
"description": "AI That Only Tells You What You Want to Hear.",
"impact": "A demo showing how AI can become an echo chamber when trained to agree with you.",
"link": "https://huggingface.co/spaces/JanviMl/Echo_Chamber_AI_chatbot",
"built_with": "GPT2, Python, Streamlit",
"category": "AI Ethics"
},
{
"name": "Task_Mate",
"description": "A chat-based task manager built with Python, Gradio and Fire",
"impact": "A demo showing how AI can become an echo chamber when trained to agree with you.",
"link": "https://huggingface.co/spaces/JanviMl/Taskmate",
"built_with": "Firebase, Python, Gradio",
"category": "Utilities"
}
]
# Custom CSS with animations and modern styling focused on projects
custom_css = """
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
background-color: #f9fafb;
}
.container {max-width: 1200px; margin: auto;}
.header {
text-align: center;
padding: 40px 30px;
background: linear-gradient(135deg, #1E3A8A 0%, #3B82F6 100%);
color: white;
border-radius: 12px;
margin-bottom: 30px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
animation: fadeIn 0.8s ease-in-out;
}
@keyframes fadeIn {
from {opacity: 0; transform: translateY(-20px);}
to {opacity: 1; transform: translateY(0);}
}
.category-nav {
display: flex;
justify-content: center;
gap: 12px;
margin-bottom: 30px;
padding: 0 15px;
flex-wrap: wrap;
animation: slideIn 0.6s ease-in-out;
}
@keyframes slideIn {
from {opacity: 0; transform: translateY(20px);}
to {opacity: 1; transform: translateY(0);}
}
.category-btn {
background-color: white;
color: #2563EB;
border: 2px solid #E0E7FF;
padding: 10px 20px;
border-radius: 30px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
font-size: 0.95rem;
}
.category-btn:hover, .category-btn-active {
background-color: #2563EB;
color: white;
border-color: #2563EB;
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);
}
.projects-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 25px;
padding: 0 15px;
}
.project-card {
border: none;
border-radius: 12px;
padding: 25px;
background-color: white;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
height: 100%;
display: flex;
flex-direction: column;
animation: cardPopIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
animation-fill-mode: both;
animation-delay: calc(var(--delay) * 0.1s);
}
.project-card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
}
@keyframes cardPopIn {
from {opacity: 0; transform: scale(0.9) translateY(20px);}
to {opacity: 1; transform: scale(1) translateY(0);}
}
.project-title {
font-size: 1.5rem;
color: #1E3A8A;
margin-bottom: 10px;
font-weight: 600;
line-height: 1.3;
}
.project-category {
display: inline-block;
background-color: #E0E7FF;
color: #1E3A8A;
font-size: 0.8rem;
padding: 5px 12px;
border-radius: 20px;
margin-bottom: 15px;
font-weight: 500;
}
.project-desc {
font-size: 1rem;
color: #4B5563;
margin-bottom: 15px;
line-height: 1.6;
}
.project-impact {
font-size: 0.95rem;
color: #0F766E;
font-weight: 500;
margin-bottom: 15px;
padding: 10px;
background-color: #ECFDF5;
border-radius: 8px;
line-height: 1.5;
}
.project-tech {
margin-top: auto;
padding-top: 15px;
}
.tech-tag {
display: inline-block;
background-color: #F3F4F6;
padding: 6px 12px;
border-radius: 6px;
font-size: 0.85rem;
color: #4B5563;
margin: 0 6px 6px 0;
}
.project-btn {
background-color: #2563EB;
color: white;
border: none;
padding: 12px 20px;
border-radius: 8px;
cursor: pointer;
margin-top: 20px;
font-weight: 500;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 10px;
width: 100%;
justify-content: center;
}
.project-btn:hover {
background-color: #1E40AF;
transform: translateY(-2px);
box-shadow: 0 6px 15px rgba(37, 99, 235, 0.3);
}
.project-btn svg {
width: 18px;
height: 18px;
}
.footer {
text-align: center;
padding: 30px 20px;
margin-top: 50px;
color: #6B7280;
font-size: 0.9rem;
animation: fadeIn 1s ease-in-out;
animation-delay: 0.5s;
animation-fill-mode: both;
}
.social-links {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 15px;
}
.social-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #F3F4F6;
color: #4B5563;
transition: all 0.3s ease;
}
.social-btn:hover {
background-color: #2563EB;
color: white;
transform: translateY(-3px);
}
"""
# Function to create category buttons
def generate_category_buttons():
# Get unique categories
categories = sorted(list(set(p["category"] for p in projects)))
categories.insert(0, "All Projects")
return [
gr.Button(
category,
elem_id=f"category-{category.lower().replace(' ', '-')}",
elem_classes=["category-btn"] + (["category-btn-active"] if category == "All Projects" else [])
)
for category in categories
]
# Function to create project cards with staggered animation
def create_project_cards(category="All Projects"):
filtered_projects = projects if category == "All Projects" else [p for p in projects if p["category"] == category]
html_content = "<div class='projects-container'>"
for i, project in enumerate(filtered_projects):
tech_tags = " ".join([f"<span class='tech-tag'>{tech.strip()}</span>" for tech in project["built_with"].split(",")])
html_content += f"""
<div class='project-card' style='--delay: {i}'>
<span class='project-category'>{project['category']}</span>
<h3 class='project-title'>{project['name']}</h3>
<p class='project-desc'>{project['description']}</p>
<div class='project-impact'>💡 Impact: {project['impact']}</div>
<div class='project-tech'>{tech_tags}</div>
<a href='{project['link']}' target='_blank' class='project-btn'>
Try It Live
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M5.22 14.78a.75.75 0 001.06 0l7.22-7.22v5.69a.75.75 0 001.5 0v-7.5a.75.75 0 00-.75-.75h-7.5a.75.75 0 000 1.5h5.69l-7.22 7.22a.75.75 0 000 1.06z" clip-rule="evenodd" />
</svg>
</a>
</div>
"""
html_content += "</div>"
return html_content
with gr.Blocks(css=custom_css, title="Janvi's ML Projects") as demo:
# Header
gr.Markdown("""
<div class='header'>
<h1>Janvi's Machine Learning Projects</h1>
<p>A showcase of interactive ML applications built with Python, TensorFlow, PyTorch, and more.</p>
</div>
""")
# Category navigation
with gr.Row(elem_classes="category-nav"):
category_buttons = generate_category_buttons()
# Projects display
projects_container = gr.HTML(create_project_cards(), elem_classes="container")
# Footer
gr.Markdown("""
<div class='footer'>
<p>Interested in collaborating on a project? Let's connect!</p>
<div class='social-links'>
<a href='https://github.com/yourusername' target='_blank' class='social-btn'>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
</a>
<a href='https://linkedin.com/in/yourprofile' target='_blank' class='social-btn'>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
<rect x="2" y="9" width="4" height="12"></rect>
<circle cx="4" cy="4" r="2"></circle>
</svg>
</a>
<a href='https://huggingface.co/yourusername' target='_blank' class='social-btn'>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M11.659 8.84a1.35 1.35 0 1 0 0-2.7 1.35 1.35 0 0 0 0 2.7Z"></path>
<path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm0-7.658a2.026 2.026 0 0 1-2.021-2.026c0-1.119.902-2.021 2.021-2.021s2.021.902 2.021 2.021A2.026 2.026 0 0 1 12 14.342Z"></path>
</svg>
</a>
</div>
</div>
""")
# Add interactivity to category buttons
for button in category_buttons:
button.click(
fn=lambda btn: create_project_cards(btn.strip()),
inputs=button,
outputs=projects_container
)
demo.launch()