import os import sys import gradio as gr from utils import load_embeddings from embeddings import create_product_embeddings from similarity import compute_similarities from ui import categorize_products_from_text, categorize_products_from_file # Path to the embeddings file EMBEDDINGS_PATH = "ingredient_embeddings_voyageai.pkl" # Check if embeddings file exists if not os.path.exists(EMBEDDINGS_PATH): print(f"Error: Embeddings file {EMBEDDINGS_PATH} not found!") print(f"Please ensure the file exists at {os.path.abspath(EMBEDDINGS_PATH)}") sys.exit(1) # Load embeddings globally try: embeddings_data = load_embeddings(EMBEDDINGS_PATH) # Make embeddings available to the UI functions import ui ui.embeddings = embeddings_data except Exception as e: print(f"Error loading embeddings: {e}") sys.exit(1) # Basic CSS theme css = """ .container { max-width: 1200px; margin: auto; padding: 0; } footer {display: none !important;} .header { background-color: #0d47a1; padding: 15px 20px; border-radius: 10px; color: white; margin-bottom: 20px; display: flex; align-items: center; } .header svg { margin-right: 10px; height: 30px; width: 30px; } .header h1 { margin: 0; font-size: 24px; } .description { margin-bottom: 20px; padding: 15px; background-color: #f5f5f5; border-radius: 5px; } """ # Custom theme theme = gr.themes.Soft( primary_hue="blue", secondary_hue="indigo", font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui"] ).set( button_primary_background_fill="*primary_500", button_primary_background_fill_hover="*primary_600", button_secondary_background_fill="*neutral_200", block_title_text_size="lg", block_label_text_size="md" ) # Create the Gradio interface directly in this file for Spaces with gr.Blocks(css=css, theme=theme) as app: # Header with icon gr.HTML("""

Product Categorization Tool

This tool analyzes products and finds the most similar ingredients using AI embeddings. Just enter product names or upload a file to get started.
""") with gr.Tabs(): with gr.TabItem("Text Input"): with gr.Row(): with gr.Column(scale=2): example_products = [ "Tomato Sauce\nApple Pie\nGreek Yogurt\nChocolate Chip Cookies", "Banana Bread\nOrange Juice\nGrilled Chicken\nCaesar Salad", "Vanilla Ice Cream\nPizza Dough\nStrawberry Jam\nGrilled Salmon" ] text_input = gr.Textbox( lines=10, placeholder="Enter product names, one per line", label="Product Names" ) gr.Examples( examples=example_products, inputs=text_input, label="Example Product Sets" ) with gr.Row(): with gr.Column(scale=1): top_n = gr.Slider( minimum=1, maximum=10, value=5, step=1, label="Number of Top Categories" ) with gr.Column(scale=1): confidence = gr.Slider( minimum=0.1, maximum=0.9, value=0.5, step=0.05, label="Confidence Threshold" ) compare_chicory = gr.Checkbox( label="Compare with Chicory Parser V3", value=False, info="When enabled, results will include comparisons with Chicory Parser V3 API" ) submit_button = gr.Button("Categorize Products", variant="primary") with gr.Column(scale=3): text_output = gr.HTML(label="Categorization Results", value="
Results will appear here
") submit_button.click( fn=categorize_products_from_text, inputs=[text_input, top_n, confidence], outputs=text_output ) with gr.TabItem("File Upload"): with gr.Row(): with gr.Column(scale=2): file_input = gr.File( label="Upload JSON or text file with products", file_types=[".json", ".txt"] ) with gr.Accordion("Help", open=False): gr.Markdown(""" - JSON files should contain either: - A list of objects with a 'name' field for each product - A simple array of product name strings - Text files should have one product name per line """) with gr.Row(): with gr.Column(scale=1): file_top_n = gr.Slider( minimum=1, maximum=10, value=5, step=1, label="Number of Top Categories" ) with gr.Column(scale=1): file_confidence = gr.Slider( minimum=0.1, maximum=0.9, value=0.5, step=0.05, label="Confidence Threshold" ) file_button = gr.Button("Process File", variant="primary") with gr.Column(scale=3): file_output = gr.HTML( label="Categorization Results", value="
Upload a file to see results
" ) file_button.click( fn=categorize_products_from_file, inputs=[file_input, file_top_n, file_confidence], outputs=file_output ) # Footer gr.HTML("""
Powered by Voyage AI embeddings • Built with Gradio
""") # For Hugging Face Spaces compatibility - do not remove if __name__ == "__main__": app.launch()