Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import os | |
| from openai import OpenAI | |
| # Initialize Groq LLM client | |
| client = OpenAI( | |
| api_key=os.getenv("GROQ_API_KEY"), | |
| base_url="https://api.groq.com/openai/v1", | |
| ) | |
| # Store search results | |
| product_cache = [] | |
| # Step 1: Search products | |
| def search_products(product_name): | |
| global product_cache | |
| url = f"https://world.openfoodfacts.org/cgi/search.pl?search_terms={product_name}&search_simple=1&action=process&json=1&page_size=10" | |
| response = requests.get(url) | |
| if response.status_code != 200: | |
| return [], gr.update(visible=False), gr.update(visible=False), gr.update(choices=[], visible=False) | |
| data = response.json() | |
| products = data.get("products", []) | |
| product_cache = [] | |
| dropdown_choices = [] | |
| display_rows = [] | |
| for i, p in enumerate(products): | |
| if not p.get("product_name"): | |
| continue | |
| product_cache.append(p) | |
| product_display = f"{p.get('product_name', 'N/A')} | {p.get('packaging', 'N/A')} | {p.get('categories', 'N/A')}" | |
| dropdown_choices.append(product_display) | |
| display_rows.append([ | |
| p.get("product_name", "N/A"), | |
| p.get("packaging", "N/A"), | |
| p.get("categories", "N/A"), | |
| p.get("code", "") | |
| ]) | |
| return display_rows, gr.update(visible=True), gr.update(visible=True), gr.update(choices=dropdown_choices, visible=True) | |
| # Step 2: Score product | |
| def score_product(p): | |
| packaging = (p.get("packaging") or "").lower() | |
| categories = (p.get("categories") or "").lower() | |
| ingredients = (p.get("ingredients_text") or "").lower() | |
| score = 50 # base score | |
| # Packaging impact | |
| if "plastic" in packaging: | |
| score -= 25 | |
| elif "glass" in packaging: | |
| score += 10 | |
| elif "paper" in packaging or "cardboard" in packaging: | |
| score += 5 | |
| elif "recyclable" in packaging: | |
| score += 8 | |
| elif "biodegradable" in packaging or "compostable" in packaging: | |
| score += 12 | |
| # Category-based adjustments | |
| if "organic" in categories: | |
| score += 10 | |
| if "local" in categories: | |
| score += 5 | |
| if "meat" in categories or "processed food" in categories: | |
| score -= 15 | |
| if "vegan" in categories: | |
| score += 10 | |
| if "snacks" in categories or "ready meals" in categories: | |
| score -= 10 | |
| # Ingredient clues | |
| if "palm oil" in ingredients: | |
| score -= 10 | |
| if "organic" in ingredients: | |
| score += 5 | |
| if "artificial flavor" in ingredients or "preservative" in ingredients: | |
| score -= 5 | |
| # Normalize score | |
| return max(0, min(score, 100)) | |
| # Step 3: Groq explanation | |
| def generate_explanation(p, score): | |
| prompt = f""" | |
| You are an environmental sustainability expert. | |
| Product: | |
| - Name: {p.get('product_name')} | |
| - Packaging: {p.get('packaging')} | |
| - Categories: {p.get('categories')} | |
| - Ingredients: {p.get('ingredients_text')} | |
| - Sustainability Score: {score}/100 | |
| Explain why this product received this score, and suggest 1–2 greener alternatives or improvements. | |
| """ | |
| try: | |
| res = client.chat.completions.create( | |
| model="llama3-8b-8192", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.7 | |
| ) | |
| return res.choices[0].message.content | |
| except Exception as e: | |
| return f"Groq explanation failed: {str(e)}" | |
| # Step 4: Analyze selected product | |
| def analyze_selected(product_label): | |
| global product_cache | |
| index = -1 | |
| for i, p in enumerate(product_cache): | |
| full_label = f"{p.get('product_name', 'N/A')} | {p.get('packaging', 'N/A')} | {p.get('categories', 'N/A')}" | |
| if full_label == product_label: | |
| index = i | |
| break | |
| if index == -1: | |
| return 0, {}, "Invalid selection", "" | |
| p = product_cache[index] | |
| score = score_product(p) | |
| breakdown = { | |
| "Product Name": p.get("product_name"), | |
| "Packaging": p.get("packaging"), | |
| "Categories": p.get("categories"), | |
| "Ingredients": p.get("ingredients_text"), | |
| "Product URL": f"https://world.openfoodfacts.org/product/{p.get('code')}" | |
| } | |
| alternatives = suggest_greener_alternatives(p) | |
| explanation = generate_explanation(p, score) | |
| return score, breakdown, "\n".join(alternatives), explanation | |
| # Step-5 Suggest Greener Product | |
| def suggest_greener_alternatives(p): | |
| alternatives = [] | |
| name = p.get("product_name", "this product") | |
| packaging = (p.get("packaging") or "").lower() | |
| categories = (p.get("categories") or "").lower() | |
| ingredients = (p.get("ingredients_text") or "").lower() | |
| if "plastic" in packaging: | |
| alternatives.append("Choose items with recyclable, glass, or biodegradable packaging.") | |
| if "meat" in categories: | |
| alternatives.append("Consider plant-based or vegan alternatives to reduce emissions.") | |
| if "palm oil" in ingredients: | |
| alternatives.append("Look for products without palm oil or with certified sustainable sources.") | |
| if "ready meal" in categories: | |
| alternatives.append("Try preparing similar meals at home using local ingredients.") | |
| if not alternatives: | |
| alternatives.append(f"{name} is relatively sustainable. You can further reduce impact by buying local or in bulk.") | |
| return alternatives | |
| # Gradio UI | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 🌱 Sustainability Score Analyzer") | |
| with gr.Row(): | |
| product_input = gr.Textbox(label="Search for a Product") | |
| search_btn = gr.Button("Search") | |
| product_table = gr.Dataframe(headers=["Product Name", "Packaging", "Categories", "Code"], | |
| interactive=False, visible=False, label="Matching Products") | |
| product_selector = gr.Dropdown(label="Select a Product from Search Results", choices=[], visible=False) | |
| analyze_btn = gr.Button("Analyze Selected Product", visible=False) | |
| score_output = gr.Number(label="Sustainability Score") | |
| breakdown_output = gr.JSON(label="Product Breakdown") | |
| alt_output = gr.Textbox(label="Greener Alternatives") | |
| explanation_output = gr.Textbox(label="AI Explanation", lines=8) | |
| search_btn.click(fn=search_products, | |
| inputs=[product_input], | |
| outputs=[product_table, product_selector, analyze_btn, product_selector]) | |
| analyze_btn.click(fn=analyze_selected, | |
| inputs=[product_selector], | |
| outputs=[score_output, breakdown_output, alt_output, explanation_output]) | |
| if __name__ == "__main__": | |
| demo.launch() | |