File size: 5,710 Bytes
d7c8166 0225bda f02a5fd ae692d1 f02a5fd d7c8166 dd8438e 0e07292 dd8438e f02a5fd dd8438e 0e07292 dd8438e 0e07292 f02a5fd 0e07292 dd8438e f02a5fd dd8438e f02a5fd 0e07292 dd8438e 0e07292 dd8438e 0e07292 dd8438e 0e07292 dd8438e f02a5fd dd8438e 0e07292 dd8438e 0e07292 f02a5fd dd8438e 0e07292 dd8438e 0e07292 f02a5fd dd8438e 0e07292 dd8438e f02a5fd ae692d1 dd8438e 0e07292 dd8438e 0e07292 dd8438e 0e07292 d7c8166 dd8438e d7c8166 |
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 |
import gradio as gr
from predictor import predict
# π CUSTOM CSS
css_code = """
#footer-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1000;
background-color: var(--background-fill-primary);
padding: var(--spacing-md);
border-top: 1px solid var(--border-color-primary);
text-align: center;
}
.gradio-container {
padding-bottom: 70px !important;
}
"""
def update_inputs(mode: str):
if mode == "Multimodal":
return gr.Textbox(visible=True), gr.Image(visible=True)
elif mode == "Text Only":
return gr.Textbox(visible=True), gr.Image(visible=False)
elif mode == "Image Only":
return gr.Textbox(visible=False), gr.Image(visible=True)
else: # Default case
return gr.Textbox(visible=True), gr.Image(visible=True)
# π USER INTERFACE
with gr.Blocks(
title="Multimodal Product Classification",
theme=gr.themes.Ocean(),
css=css_code,
) as demo:
with gr.Tabs():
# π APP TAB
with gr.TabItem("App"):
gr.Markdown("""
<div style="text-align: center;">
<h1>ποΈ Multimodal Product Classification</h1>
</div>
<br><br>
""")
with gr.Row(equal_height=True):
# π CLASSIFICATION INPUTS COLUMN
with gr.Column():
with gr.Column():
gr.Markdown("## π Classification Inputs")
mode_radio = gr.Radio(
choices=["Multimodal", "Text Only", "Image Only"],
value="Multimodal",
label="Choose Classification Mode:",
)
text_input = gr.Textbox(
label="Product Description:",
placeholder="e.g., Apple iPhone 15 Pro Max 256GB",
)
image_input = gr.Image(
label="Product Image",
type="filepath",
visible=True,
height=350,
width="100%",
)
classify_button = gr.Button(
"β¨ Classify Product", variant="primary"
)
# π RESULTS COLUMN
with gr.Column():
with gr.Column():
gr.Markdown("## π Results")
gr.Markdown(
"""**π‘ How to use this app**
This app classifies a product based on its description and image.
- **Multimodal:** Uses both text and image for the most accurate prediction.
- **Text Only:** Uses only the product description.
- **Image Only:** Uses only the product image.
"""
)
gr.HTML("<hr>")
output_label = gr.Label(
label="Predict category", num_top_classes=5
)
# π ABOUT TAB
with gr.TabItem("About"):
gr.Markdown("""
## About This Project
- This project is an image classification app powered by a Convolutional Neural Network (CNN).
- Simply upload an image, and the app predicts its category from over 1,000 classes using a pre-trained ResNet50 model.
- Originally developed as a multi-service ML system (FastAPI + Redis + Streamlit), this version has been adapted into a single Streamlit app for lightweight, cost-effective deployment on Hugging Face Spaces.
## Model & Description
- Model: ResNet50 (pre-trained on the ImageNet dataset with 1,000+ categories).
- Pipeline: Images are resized, normalized, and passed to the model.
- Output: The app displays the Top prediction with confidence score.
ResNet50 is widely used in both research and production, making it an excellent showcase of deep learning capabilities and transferable ML skills.
""")
# π MODEL TAB
with gr.TabItem("Model"):
gr.Markdown("""
## Original Architecture
- FastAPI β REST API for image processing
- Redis β Message broker for service communication
- Streamlit β Interactive web UI
- TensorFlow β Deep learning inference engine
- Locust β Load testing & benchmarking
- Docker Compose β Service orchestration
## Simplified Version
- Streamlit only β UI and model combined in a single app
- TensorFlow (ResNet50) β Core prediction engine
- Docker β Containerized for Hugging Face Spaces deployment
This evolution demonstrates the ability to design a scalable microservices system and also adapt it into a lightweight single-service solution for cost-effective demos.
""")
# π FOOTER
# gr.HTML("<hr>")
with gr.Row(elem_id="footer-container"):
gr.HTML("""
<div>
<b>Connect with me:</b> πΌ <a href="https://www.linkedin.com/in/alex-turpo/" target="_blank">LinkedIn</a> β’
π± <a href="https://github.com/iBrokeTheCode" target="_blank">GitHub</a> β’
π€ <a href="https://huggingface.co/iBrokeTheCode" target="_blank">Hugging Face</a>
</div>
""")
# π EVENT LISTENERS
mode_radio.change(
fn=update_inputs,
inputs=mode_radio,
outputs=[text_input, image_input],
)
classify_button.click(
fn=predict, inputs=[mode_radio, text_input, image_input], outputs=output_label
)
demo.launch()
|