import gradio as gr
from utils import SafeProgress, format_categories_html
from embeddings import create_product_embeddings
from similarity import compute_similarities
from chicory_api import call_chicory_parser
# Global variable for embeddings
embeddings = {}
def categorize_products(product_input, is_file=False, top_n=5, confidence_threshold=0.5, progress=None):
"""Categorize products from text input or file"""
progress_tracker = SafeProgress(progress)
progress_tracker(0, desc="Starting...")
# Parse input
if is_file:
from utils import parse_product_file
try:
product_names = parse_product_file(product_input.name)
except Exception as e:
return f"
Error: {str(e)}
"
else:
product_names = [line.strip() for line in product_input.split("\n") if line.strip()]
if not product_names:
return "No product names provided.
"
# Create embeddings
progress_tracker(0.2, desc="Generating product embeddings...")
products_embeddings = create_product_embeddings(product_names)
# Call Chicory Parser API
progress_tracker(0.5, desc="Calling Chicory Parser API...")
chicory_results = call_chicory_parser(product_names)
# Compute similarities
progress_tracker(0.7, desc="Computing similarities...")
all_similarities = compute_similarities(embeddings, products_embeddings)
# Format results
progress_tracker(0.9, desc="Formatting results...")
output_html = ""
for product, similarities in all_similarities.items():
filtered_similarities = [(ingredient, score) for ingredient, score in similarities if score >= confidence_threshold]
top_similarities = filtered_similarities[:top_n]
output_html += format_categories_html(product, top_similarities, chicory_result=chicory_results.get(product))
output_html += "
"
output_html += ""
if not all_similarities:
output_html = "No results found. Please check your input or try different products.
"
progress_tracker(1.0, desc="Done!")
return output_html
def create_demo():
"""Create the Gradio interface"""
with gr.Blocks(css="""
.results-container { min-height: 400px; }
.chicory-result { visibility: visible !important; display: block !important; }
.container { gap: 20px; }
""") as demo:
gr.Markdown("# Product Categorization Tool\nAnalyze products and find the most similar ingredients using AI embeddings.")
with gr.Tabs():
with gr.TabItem("Text Input"):
with gr.Row():
with gr.Column(scale=1):
# Input section
text_input = gr.Textbox(lines=10, placeholder="Enter product names, one per line", label="Product Names")
input_controls = gr.Row()
with input_controls:
top_n = gr.Slider(1, 10, 5, label="Top N Results")
confidence = gr.Slider(0.1, 0.9, 0.5, label="Confidence Threshold")
categorize_btn = gr.Button("Categorize")
with gr.Column(scale=1):
# Results section
text_output = gr.HTML(label="Categorization Results", elem_classes="results-container")
categorize_btn.click(
fn=categorize_products,
inputs=[text_input, gr.State(False), top_n, confidence],
outputs=text_output
)
with gr.TabItem("File Upload"):
with gr.Row():
with gr.Column(scale=1):
# Input section
file_input = gr.File(label="Upload JSON or text file with products", file_types=[".json", ".txt"])
file_controls = gr.Row()
with file_controls:
file_top_n = gr.Slider(1, 10, 5, label="Top N Results")
file_confidence = gr.Slider(0.1, 0.9, 0.5, label="Confidence Threshold")
process_btn = gr.Button("Process File")
with gr.Column(scale=1):
# Results section
file_output = gr.HTML(label="Categorization Results", elem_classes="results-container")
process_btn.click(
fn=categorize_products,
inputs=[file_input, gr.State(True), file_top_n, file_confidence],
outputs=file_output
)
gr.Markdown("Powered by Voyage AI embeddings • Built with Gradio")
return demo