import json import sys from pathlib import Path import streamlit as st from PIL import Image ROOT_DIR = Path(__file__).resolve().parent if str(ROOT_DIR) not in sys.path: sys.path.insert(0, str(ROOT_DIR)) from src.inference import ( load_predictor, render_metrics, render_prediction_card, render_top_predictions, ) from autocatalog.utils.config import load_config def main(): st.set_page_config( page_title="AutoCatalogAI V2", page_icon="🛍️", layout="wide", ) st.markdown( """ """, unsafe_allow_html=True, ) config = load_config( ROOT_DIR / "configs" / "config.yaml" ) repo_id = config.get("model", {}).get( "repo_id", "mohsin416/autocatalogai-clip-multitask-v2", ) inference_config = config.get("inference", {}) top_k = int(inference_config.get("top_k", 3)) device = inference_config.get("device") default_consistency = bool( inference_config.get( "apply_consistency_rules", True, ) ) st.markdown( '
AutoCatalogAI V2
', unsafe_allow_html=True, ) st.markdown( """
Fashion product attribute extraction and catalog metadata generation using CLIP, colour features, and hierarchical learning.
""", unsafe_allow_html=True, ) with st.sidebar: st.header("Settings") st.write("Model repository") st.code(repo_id) selected_top_k = st.slider( "Top-K predictions", min_value=1, max_value=5, value=top_k, ) consistency_enabled = st.toggle( "Apply consistency correction", value=default_consistency, ) st.divider() st.caption( "The model loads from Hugging Face Hub " "and performs inference only." ) with st.spinner("Loading AutoCatalogAI V2 model..."): predictor = load_predictor( repo_id=repo_id, device=device, ) metrics = predictor.get_model_metrics() corrected_metrics = metrics.get("corrected", metrics) render_metrics(corrected_metrics) st.divider() left_col, right_col = st.columns([0.9, 1.1]) image = None with left_col: st.subheader("Upload Product Image") uploaded_file = st.file_uploader( "Choose a product image", type=["jpg", "jpeg", "png", "webp"], label_visibility="collapsed", ) if uploaded_file is not None: image = Image.open(uploaded_file).convert("RGB") st.image( image, caption="Uploaded Image", width="stretch", ) with right_col: st.subheader("Prediction Result") if image is None: st.info( "Upload a fashion product image " "to generate catalog attributes." ) return if st.button( "Generate Catalog", type="primary", width="stretch", ): with st.spinner( "Predicting product attributes..." ): result = predictor.predict( image=image, top_k=selected_top_k, apply_consistency_rules=consistency_enabled, ) prediction = result["prediction"] catalog_output = result["catalog_output"] runtime = result["runtime"] st.markdown( f"""
Suggested Title

{catalog_output["suggested_title"]}

""", unsafe_allow_html=True, ) st.markdown("**Search Tags**") st.write( ", ".join( catalog_output["search_tags"] ) ) st.markdown("**Predicted Attributes**") for task, task_result in prediction.items(): render_prediction_card( task, task_result, ) if task_result.get("corrected"): st.caption( f"Corrected from: " f"{task_result['raw_label']}" ) render_top_predictions(prediction) st.markdown("**Runtime**") st.write( f"Device: `{runtime['device']}`" ) st.write( f"Inference time: " f"`{runtime['inference_time_ms']:.2f} ms`" ) json_output = json.dumps( catalog_output["json_export"], indent=2, ensure_ascii=False, ) st.download_button( label="Download JSON", data=json_output, file_name="autocatalogai_v2_prediction.json", mime="application/json", width="stretch", ) with st.expander("Raw JSON Output"): st.json( catalog_output["json_export"] ) if __name__ == "__main__": main()