from typing import List, Dict, Tuple, Any from utils import get_confidence_color, get_confidence_bg_color # Method colors (consistent across themes) METHOD_COLORS = { "base": "#f39c12", # Orange "voyage": "#3498db", # Blue "chicory": "#9b59b6", # Purple "openai": "#2ecc71", # Green "expanded": "#e74c3c", # Red "hybrid": "#1abc9c", # Turquoise "categories": "#1abc9c", # Same as hybrid "ingredients": "#f39c12" # Same as base } # Method display names METHOD_NAMES = { "base": "Base Embeddings", "voyage": "Voyage AI Reranker", "chicory": "Chicory Parser", "openai": "OpenAI Reranker", "expanded": "Expanded Description", "hybrid": "Hybrid Matching", "categories": "Category Matches", "ingredients": "Ingredient Matches" } def parse_result_item(item): """Helper function to parse result items into display text and score""" display_text = str(item) # Default score = 0.0 # Handle tuple formats if isinstance(item, tuple): if len(item) == 2: match, score = item display_text = str(match) elif len(item) == 3: id_val, text, score = item display_text = f"{id_val}: {text}" if text else str(id_val) # Handle dictionary formats elif isinstance(item, dict): if "name" in item and "score" in item: display_text = item["name"] score = item["score"] elif "category" in item and "confidence" in item: display_text = item["category"] score = item["confidence"] elif "ingredient" in item and "relevance_score" in item: display_text = item["ingredient"] score = item["relevance_score"] # Ensure score is a float try: score = float(score) except (ValueError, TypeError): score = 0.0 return display_text, score def filter_results_by_threshold(results, confidence_threshold=0.0): """Helper function to filter results by confidence threshold""" filtered_results = [] for item in results: _, score = parse_result_item(item) if score >= confidence_threshold: filtered_results.append(item) return filtered_results def format_confidence_badge(score): """Formats the confidence score as a styled span (badge)""" confidence_percent = int(score * 100) confidence_color = get_confidence_color(score) bg_color = get_confidence_bg_color(score) # Determine text color based on background lightness for better contrast # Simple heuristic: if bg_color is light (e.g., yellow, light green), use black text, otherwise use white/light text. # This is approximate. A proper solution would involve calculating luminance. light_bgs = ["#ffffcc", "#ccffcc", "#cceeff"] # Add more light hex codes if needed text_color = "#000000" if bg_color.lower() in light_bgs else "var(--text-color)" # Default to theme text color otherwise return ( f"" f"{confidence_percent}%" ) def format_result_list_html(results, confidence_threshold=0.0): """Formats a list of results (matches) into an HTML list.""" filtered_results = filter_results_by_threshold(results, confidence_threshold) if not filtered_results: return "
No matches found above confidence threshold.
" html = "{text}
" # Use theme text color f"No {match_type.lower()} matches found.
" html_elements = [] for result in results: product_name = result.get("product_name", "Unknown Product") matching_items = result.get("matching_items", []) item_scores = result.get("item_scores", []) explanation = result.get("explanation", "") if include_explanation else "" if len(item_scores) != len(matching_items): item_scores = [result.get("confidence", 0.0)] * len(matching_items) formatted_matches = [] for i, item in enumerate(matching_items): if ":" in str(item) and match_type == "categories": parts = str(item).split(":", 1) id_val = parts[0].strip() text = parts[1].strip() if len(parts) > 1 else "" formatted_matches.append((id_val, text, item_scores[i])) else: formatted_matches.append((str(item), item_scores[i])) content_html = "" if explanation: content_html += format_info_panel("Expanded Description", explanation) list_html = format_result_list_html(formatted_matches, confidence_threshold) content_html += list_html # Only add card if there's content to show (explanation or non-empty list html) if explanation or "No Chicory results available.
" # Add the main category/ingredient results match_title = METHOD_NAMES.get(match_type, match_type.capitalize()) color_hex = METHOD_COLORS.get(match_type, "var(--text-color)") # Fallback to theme text color content_html += f"