esilver commited on
Commit
c8d7df6
·
1 Parent(s): d457572

compare to chicory-ui

Browse files
Files changed (1) hide show
  1. ui.py +39 -233
ui.py CHANGED
@@ -2,274 +2,80 @@ import gradio as gr
2
  from utils import SafeProgress, format_categories_html
3
  from embeddings import create_product_embeddings
4
  from similarity import compute_similarities
5
- from chicory_api import call_chicory_parser # Import the Chicory API function
6
 
7
  # Global variable for embeddings
8
  embeddings = {}
9
 
10
- def categorize_products_from_text(product_text, top_n=5, confidence_threshold=0.5, progress=None):
11
- """Categorize products from text input (one product per line)"""
12
- # Create a safe progress tracker
13
  progress_tracker = SafeProgress(progress)
14
  progress_tracker(0, desc="Starting...")
15
-
16
- # Parse input text to get product names
17
- product_names = [line.strip() for line in product_text.split("\n") if line.strip()]
18
-
 
 
 
 
 
 
 
19
  if not product_names:
20
- return "No product names provided."
21
-
22
- # Create product embeddings
23
- progress_tracker(0.1, desc="Generating product embeddings...")
24
  products_embeddings = create_product_embeddings(product_names)
25
-
26
  # Call Chicory Parser API
27
  progress_tracker(0.5, desc="Calling Chicory Parser API...")
28
  chicory_results = call_chicory_parser(product_names)
29
-
30
  # Compute similarities
31
- progress_tracker(0.6, desc="Computing similarities...")
32
  all_similarities = compute_similarities(embeddings, products_embeddings)
33
-
34
  # Format results
35
  progress_tracker(0.9, desc="Formatting results...")
36
  output_html = "<div style='font-family: Arial, sans-serif;'>"
37
-
38
  for product, similarities in all_similarities.items():
39
- # Filter by confidence threshold and take top N
40
- filtered_similarities = [(ingredient, score) for ingredient, score in similarities
41
- if score >= confidence_threshold]
42
  top_similarities = filtered_similarities[:top_n]
43
-
44
  output_html += format_categories_html(product, top_similarities, chicory_result=chicory_results.get(product))
45
  output_html += "<hr style='margin: 15px 0; border: 0; border-top: 1px solid #eee;'>"
46
-
47
  output_html += "</div>"
48
-
49
  if not all_similarities:
50
  output_html = "<div style='color: #d32f2f; font-weight: bold; padding: 20px;'>No results found. Please check your input or try different products.</div>"
51
-
52
- progress_tracker(1.0, desc="Done!")
53
- return output_html
54
 
55
- def categorize_products_from_file(file, top_n=5, confidence_threshold=0.5, progress=None):
56
- """Categorize products from a JSON or text file"""
57
- from utils import parse_product_file
58
-
59
- # Create a safe progress tracker
60
- progress_tracker = SafeProgress(progress)
61
- progress_tracker(0.1, desc="Reading file...")
62
-
63
- try:
64
- product_names = parse_product_file(file.name)
65
- except Exception as e:
66
- return f"<div style='color: #d32f2f; font-weight: bold;'>Error: {str(e)}</div>"
67
-
68
- if not product_names:
69
- return "<div style='color: #d32f2f;'>No product names found in the file.</div>"
70
-
71
- # Create product embeddings
72
- progress_tracker(0.2, desc="Generating product embeddings...")
73
- products_embeddings = create_product_embeddings(product_names)
74
-
75
- # Call Chicory Parser API
76
- progress_tracker(0.5, desc="Calling Chicory Parser API...")
77
- chicory_results = call_chicory_parser(product_names)
78
-
79
- # Compute similarities
80
- progress_tracker(0.7, desc="Computing similarities...")
81
- all_similarities = compute_similarities(embeddings, products_embeddings)
82
-
83
- # Format results
84
- progress_tracker(0.9, desc="Formatting results...")
85
- output_html = f"<div style='font-family: Arial, sans-serif;'>"
86
- output_html += f"<div style='margin-bottom: 20px; padding: 10px; background-color: #e8f5e9; border-radius: 5px;'>"
87
- output_html += f"Found <b>{len(product_names)}</b> products in file. Showing results with confidence ≥ {confidence_threshold}."
88
- output_html += "</div>"
89
-
90
- for product, similarities in all_similarities.items():
91
- # Filter by confidence threshold and take top N
92
- filtered_similarities = [(ingredient, score) for ingredient, score in similarities
93
- if score >= confidence_threshold]
94
- top_similarities = filtered_similarities[:top_n]
95
-
96
- output_html += format_categories_html(product, top_similarities, chicory_result=chicory_results.get(product))
97
- output_html += "<hr style='margin: 15px 0; border: 0; border-top: 1px solid #eee;'>"
98
-
99
- output_html += "</div>"
100
-
101
  progress_tracker(1.0, desc="Done!")
102
  return output_html
103
 
104
  def create_demo():
105
  """Create the Gradio interface"""
106
- # Basic CSS theme
107
- css = """
108
- .container {
109
- max-width: 1200px;
110
- margin: auto;
111
- padding: 0;
112
- }
113
- footer {display: none !important;}
114
- .header {
115
- background-color: #0d47a1;
116
- padding: 15px 20px;
117
- border-radius: 10px;
118
- color: white;
119
- margin-bottom: 20px;
120
- display: flex;
121
- align-items: center;
122
- }
123
- .header svg {
124
- margin-right: 10px;
125
- height: 30px;
126
- width: 30px;
127
- }
128
- .header h1 {
129
- margin: 0;
130
- font-size: 24px;
131
- }
132
- .description {
133
- margin-bottom: 20px;
134
- padding: 15px;
135
- background-color: #f5f5f5;
136
- border-radius: 5px;
137
- }
138
- """
139
-
140
- # Custom theme
141
- theme = gr.themes.Soft(
142
- primary_hue="blue",
143
- secondary_hue="indigo",
144
- font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui"]
145
- ).set(
146
- button_primary_background_fill="*primary_500",
147
- button_primary_background_fill_hover="*primary_600",
148
- button_secondary_background_fill="*neutral_200",
149
- block_title_text_size="lg",
150
- block_label_text_size="md"
151
- )
152
 
153
- with gr.Blocks(css=css, theme=theme) as demo:
154
- # Header with icon
155
- gr.HTML("""
156
- <div class="header">
157
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white">
158
- <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"></path>
159
- </svg>
160
- <h1>Product Categorization Tool</h1>
161
- </div>
162
- <div class="description">
163
- This tool analyzes products and finds the most similar ingredients using AI embeddings.
164
- Just enter product names or upload a file to get started.
165
- </div>
166
- """)
167
-
168
  with gr.Tabs():
169
  with gr.TabItem("Text Input"):
170
- with gr.Row():
171
- with gr.Column(scale=2):
172
- example_products = [
173
- "Tomato Sauce\nApple Pie\nGreek Yogurt\nChocolate Chip Cookies",
174
- "Banana Bread\nOrange Juice\nGrilled Chicken\nCaesar Salad",
175
- "Vanilla Ice Cream\nPizza Dough\nStrawberry Jam\nGrilled Salmon"
176
- ]
177
-
178
- text_input = gr.Textbox(
179
- lines=10,
180
- placeholder="Enter product names, one per line",
181
- label="Product Names"
182
- )
183
-
184
- gr.Examples(
185
- examples=example_products,
186
- inputs=text_input,
187
- label="Example Product Sets"
188
- )
189
-
190
- with gr.Row():
191
- with gr.Column(scale=1):
192
- top_n = gr.Slider(
193
- minimum=1,
194
- maximum=10,
195
- value=5,
196
- step=1,
197
- label="Number of Top Categories"
198
- )
199
- with gr.Column(scale=1):
200
- confidence = gr.Slider(
201
- minimum=0.1,
202
- maximum=0.9,
203
- value=0.5,
204
- step=0.05,
205
- label="Confidence Threshold"
206
- )
207
-
208
- submit_button = gr.Button("Categorize Products", variant="primary")
209
-
210
- with gr.Column(scale=3):
211
- text_output = gr.HTML(label="Categorization Results",
212
- value="<div style='height: 450px; display: flex; justify-content: center; align-items: center; color: #666;'>Results will appear here</div>")
213
-
214
- submit_button.click(
215
- fn=categorize_products_from_text,
216
- inputs=[text_input, top_n, confidence],
217
  outputs=text_output
218
  )
219
-
220
  with gr.TabItem("File Upload"):
221
- with gr.Row():
222
- with gr.Column(scale=2):
223
- file_input = gr.File(
224
- label="Upload JSON or text file with products",
225
- file_types=[".json", ".txt"]
226
- )
227
-
228
- with gr.Accordion("Help", open=False):
229
- gr.Markdown("""
230
- - JSON files should contain either:
231
- - A list of objects with a 'name' field for each product
232
- - A simple array of product name strings
233
- - Text files should have one product name per line
234
- """)
235
-
236
- with gr.Row():
237
- with gr.Column(scale=1):
238
- file_top_n = gr.Slider(
239
- minimum=1,
240
- maximum=10,
241
- value=5,
242
- step=1,
243
- label="Number of Top Categories"
244
- )
245
- with gr.Column(scale=1):
246
- file_confidence = gr.Slider(
247
- minimum=0.1,
248
- maximum=0.9,
249
- value=0.5,
250
- step=0.05,
251
- label="Confidence Threshold"
252
- )
253
-
254
- file_button = gr.Button("Process File", variant="primary")
255
-
256
- with gr.Column(scale=3):
257
- file_output = gr.HTML(
258
- label="Categorization Results",
259
- value="<div style='height: 450px; display: flex; justify-content: center; align-items: center; color: #666;'>Upload a file to see results</div>"
260
- )
261
-
262
- file_button.click(
263
- fn=categorize_products_from_file,
264
- inputs=[file_input, file_top_n, file_confidence],
265
  outputs=file_output
266
  )
267
-
268
- # Footer
269
- gr.HTML("""
270
- <div style="margin-top: 20px; text-align: center; color: #666;">
271
- Powered by Voyage AI embeddings • Built with Gradio
272
- </div>
273
- """)
274
-
275
  return demo
 
2
  from utils import SafeProgress, format_categories_html
3
  from embeddings import create_product_embeddings
4
  from similarity import compute_similarities
5
+ from chicory_api import call_chicory_parser
6
 
7
  # Global variable for embeddings
8
  embeddings = {}
9
 
10
+ def categorize_products(product_input, is_file=False, top_n=5, confidence_threshold=0.5, progress=None):
11
+ """Categorize products from text input or file"""
 
12
  progress_tracker = SafeProgress(progress)
13
  progress_tracker(0, desc="Starting...")
14
+
15
+ # Parse input
16
+ if is_file:
17
+ from utils import parse_product_file
18
+ try:
19
+ product_names = parse_product_file(product_input.name)
20
+ except Exception as e:
21
+ return f"<div style='color: #d32f2f; font-weight: bold;'>Error: {str(e)}</div>"
22
+ else:
23
+ product_names = [line.strip() for line in product_input.split("\n") if line.strip()]
24
+
25
  if not product_names:
26
+ return "<div style='color: #d32f2f;'>No product names provided.</div>"
27
+
28
+ # Create embeddings
29
+ progress_tracker(0.2, desc="Generating product embeddings...")
30
  products_embeddings = create_product_embeddings(product_names)
31
+
32
  # Call Chicory Parser API
33
  progress_tracker(0.5, desc="Calling Chicory Parser API...")
34
  chicory_results = call_chicory_parser(product_names)
35
+
36
  # Compute similarities
37
+ progress_tracker(0.7, desc="Computing similarities...")
38
  all_similarities = compute_similarities(embeddings, products_embeddings)
39
+
40
  # Format results
41
  progress_tracker(0.9, desc="Formatting results...")
42
  output_html = "<div style='font-family: Arial, sans-serif;'>"
 
43
  for product, similarities in all_similarities.items():
44
+ filtered_similarities = [(ingredient, score) for ingredient, score in similarities if score >= confidence_threshold]
 
 
45
  top_similarities = filtered_similarities[:top_n]
 
46
  output_html += format_categories_html(product, top_similarities, chicory_result=chicory_results.get(product))
47
  output_html += "<hr style='margin: 15px 0; border: 0; border-top: 1px solid #eee;'>"
 
48
  output_html += "</div>"
49
+
50
  if not all_similarities:
51
  output_html = "<div style='color: #d32f2f; font-weight: bold; padding: 20px;'>No results found. Please check your input or try different products.</div>"
 
 
 
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  progress_tracker(1.0, desc="Done!")
54
  return output_html
55
 
56
  def create_demo():
57
  """Create the Gradio interface"""
58
+ with gr.Blocks() as demo:
59
+ gr.Markdown("# Product Categorization Tool\nAnalyze products and find the most similar ingredients using AI embeddings.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  with gr.Tabs():
62
  with gr.TabItem("Text Input"):
63
+ text_input = gr.Textbox(lines=10, placeholder="Enter product names, one per line", label="Product Names")
64
+ text_output = gr.HTML(label="Categorization Results")
65
+ gr.Button("Categorize").click(
66
+ fn=categorize_products,
67
+ inputs=[text_input, gr.State(False), gr.Slider(1, 10, 5), gr.Slider(0.1, 0.9, 0.5)],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  outputs=text_output
69
  )
70
+
71
  with gr.TabItem("File Upload"):
72
+ file_input = gr.File(label="Upload JSON or text file with products", file_types=[".json", ".txt"])
73
+ file_output = gr.HTML(label="Categorization Results")
74
+ gr.Button("Process File").click(
75
+ fn=categorize_products,
76
+ inputs=[file_input, gr.State(True), gr.Slider(1, 10, 5), gr.Slider(0.1, 0.9, 0.5)],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  outputs=file_output
78
  )
79
+
80
+ gr.Markdown("Powered by Voyage AI embeddings • Built with Gradio")
 
 
 
 
 
 
81
  return demo