import streamlit as st import requests import pandas as pd import plotly.express as px import plotly.graph_objects as go from datetime import datetime, timedelta import json from typing import List, Dict, Any from PIL import Image import io import numpy as np import asyncio import threading import uvicorn from fastapi import FastAPI, UploadFile, File, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse import random # Configure Streamlit page st.set_page_config( page_title="Visual ShopLens", page_icon="🔍", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for better UI st.markdown(""" """, unsafe_allow_html=True) # FastAPI Backend (Embedded) app = FastAPI(title="Visual ShopLens API", description="Embedded API for HF Spaces") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Dummy data for demo @app.get("/health") async def health(): return {"status": "healthy", "timestamp": datetime.now().isoformat()} @app.post("/v1/match/image") async def match_image(file: UploadFile = File(...)): # Simulate processing delay await asyncio.sleep(1) # Return dummy search results results = [ { "product_id": "prod_1", "title": "Smartphone Pro Max 256GB", "brand": "TechBrand", "score": 0.89, "category": "Electronics", "image_url": "https://via.placeholder.com/200x200/4285f4/ffffff?text=Phone", "listings": [ { "id": "amz_1", "store": "amazon", "url": "https://amazon.in/dp/example", "price": 25999.0, "currency": "INR", "in_stock": True, "seller": "Amazon", "seller_rating": 4.2, "last_updated": datetime.now().isoformat() }, { "id": "fkrt_1", "store": "flipkart", "url": "https://flipkart.com/product/example", "price": 24499.0, "currency": "INR", "in_stock": True, "seller": "Flipkart", "seller_rating": 4.0, "last_updated": datetime.now().isoformat() } ], "deal_score": 78 }, { "product_id": "prod_2", "title": "Wireless Headphones Premium", "brand": "AudioCorp", "score": 0.76, "category": "Electronics", "image_url": "https://via.placeholder.com/200x200/34a853/ffffff?text=Headphones", "listings": [ { "id": "amz_2", "store": "amazon", "url": "https://amazon.in/dp/example2", "price": 8999.0, "currency": "INR", "in_stock": True, "seller": "Amazon", "seller_rating": 4.3, "last_updated": datetime.now().isoformat() } ], "deal_score": 85 } ] return results @app.get("/v1/product/{product_id}/forecast") async def get_forecast(product_id: str, days: int = 30): base_price = 25000 predictions = [] for i in range(1, days + 1): date = datetime.now() + timedelta(days=i) price = base_price + (i * 10) + (50 * ((i % 7) - 3)) predictions.append({ "date": date.isoformat(), "predicted_price": price, "confidence_lower": price - 500, "confidence_upper": price + 500 }) return { "product_id": product_id, "current_price": base_price, "currency": "INR", "forecast_days": days, "predictions": predictions, "deal_score": 78, "price_trend": "stable", "best_time_to_buy": None, "price_vs_90_day_avg": -5.2, "volatility": 0.08, "confidence": 0.85 } # Start FastAPI in background thread def start_api(): uvicorn.run(app, host="0.0.0.0", port=8000, log_level="error") # Start API server if 'api_started' not in st.session_state: st.session_state.api_started = True api_thread = threading.Thread(target=start_api, daemon=True) api_thread.start() # Helper functions def display_deal_score(score: int) -> str: if score >= 80: return f'{score}/100 (Excellent Deal!)' elif score >= 60: return f'{score}/100 (Good Deal)' else: return f'{score}/100 (Fair Price)' def display_price_trend(trend: str) -> str: if trend == "rising": return "📈 Rising" elif trend == "falling": return "📉 Falling" else: return "➡️ Stable" # Main Streamlit App def main(): # Header with animation st.markdown('

🔍 Visual ShopLens

', unsafe_allow_html=True) # Hero section col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.markdown("""

🚀 AI-Powered Product Discovery & Price Intelligence

Upload any product image and discover similar items across multiple stores with intelligent price forecasting

""", unsafe_allow_html=True) # Demo notification st.info("🎮 **Demo Mode**: This is a demonstration with simulated data. In production, it would connect to real e-commerce APIs.") # Main tabs tab1, tab2, tab3 = st.tabs(["🔍 Visual Search", "📈 Price Intelligence", "🎯 Features"]) with tab1: st.subheader("📷 Upload Product Image") col1, col2 = st.columns([2, 1]) with col1: uploaded_file = st.file_uploader( "Choose an image...", type=['png', 'jpg', 'jpeg', 'webp'], help="Upload a clear image of any product" ) query_text = st.text_input( "Additional keywords (optional)", placeholder="e.g., smartphone 128GB black, wireless headphones", help="Add keywords to improve search accuracy" ) col_btn1, col_btn2 = st.columns(2) with col_btn1: search_button = st.button("🔍 Find Similar Products", type="primary") with col_btn2: demo_button = st.button("🎲 Try Demo Search", type="secondary") with col2: if uploaded_file is not None: image = Image.open(uploaded_file) st.image(image, caption="Uploaded Image", width=300) else: st.markdown("""

📤 Upload an Image

Drag & drop or click to browse

""", unsafe_allow_html=True) # Search results if search_button and uploaded_file or demo_button: with st.spinner("🤖 Analyzing image and finding similar products..."): # Simulate API call import time time.sleep(2) # Mock results results = [ { "product_id": "prod_1", "title": "Smartphone Pro Max 256GB", "brand": "TechBrand", "score": 0.89, "category": "Electronics", "image_url": "https://via.placeholder.com/200x200/4285f4/ffffff?text=Phone", "listings": [ {"store": "amazon", "price": 25999, "in_stock": True, "seller_rating": 4.2, "url": "#"}, {"store": "flipkart", "price": 24499, "in_stock": True, "seller_rating": 4.0, "url": "#"} ], "deal_score": 78 }, { "product_id": "prod_2", "title": "Premium Wireless Headphones", "brand": "AudioCorp", "score": 0.76, "category": "Electronics", "image_url": "https://via.placeholder.com/200x200/34a853/ffffff?text=Headphones", "listings": [ {"store": "amazon", "price": 8999, "in_stock": True, "seller_rating": 4.3, "url": "#"} ], "deal_score": 85 } ] st.success(f"✅ Found {len(results)} similar products!") for i, result in enumerate(results): with st.expander(f"🏷️ {result['title']} (Match: {result['score']:.0%})", expanded=i<2): col1, col2, col3 = st.columns([1, 2, 1]) with col1: st.image(result['image_url'], width=150) with col2: st.write(f"**Brand:** {result['brand']}") st.write(f"**Category:** {result['category']}") st.markdown(f"**Deal Score:** {display_deal_score(result['deal_score'])}", unsafe_allow_html=True) with col3: if st.button(f"📊 View Forecast", key=f"forecast_{i}"): st.session_state.selected_product = result['product_id'] # Price comparison if result['listings']: st.subheader("💰 Price Comparison") listings_df = pd.DataFrame([ { "Store": listing['store'].title(), "Price": f"₹{listing['price']:,}", "Status": "✅ In Stock" if listing['in_stock'] else "❌ Out of Stock", "Rating": f"⭐ {listing['seller_rating']}" } for listing in result['listings'] ]) st.dataframe(listings_df, use_container_width=True) # Best deal highlight available = [l for l in result['listings'] if l['in_stock']] if available: best = min(available, key=lambda x: x['price']) st.success(f"💡 **Best Deal:** ₹{best['price']:,} at {best['store'].title()}") with tab2: st.subheader("📈 Price Intelligence & Forecasting") if 'selected_product' in st.session_state: st.success("📊 Analyzing price trends for selected product...") # Forecast controls col1, col2 = st.columns(2) with col1: forecast_days = st.selectbox("Forecast Period", [7, 14, 30], index=2) with col2: st.metric("Confidence Level", "85%", delta="High") # Generate mock forecast data base_price = 25000 dates = [(datetime.now() + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(1, forecast_days + 1)] prices = [base_price + (i * 10) + random.randint(-200, 200) for i in range(forecast_days)] # Key metrics col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Current Price", "₹25,000", delta="-5.2% vs 90d avg") with col2: st.metric("Deal Score", "78/100", delta="Good Deal") with col3: st.metric("Price Trend", "Stable", delta="No change") with col4: st.metric("Volatility", "Low", delta="8% std dev") # Price forecast chart fig = go.Figure() fig.add_trace(go.Scatter( x=dates, y=prices, mode='lines+markers', name='Predicted Price', line=dict(color='#667eea', width=3), marker=dict(size=6) )) # Add confidence band upper_bound = [p + 500 for p in prices] lower_bound = [p - 500 for p in prices] fig.add_trace(go.Scatter( x=dates + dates[::-1], y=upper_bound + lower_bound[::-1], fill='toself', fillcolor='rgba(102, 126, 234, 0.2)', line=dict(color='rgba(255,255,255,0)'), name='Confidence Band' )) fig.add_hline(y=base_price, line_dash="dash", line_color="red", annotation_text=f"Current: ₹{base_price:,}") fig.update_layout( title=f"📈 Price Forecast - Next {forecast_days} Days", xaxis_title="Date", yaxis_title="Price (₹)", template="plotly_white", height=500, showlegend=True ) st.plotly_chart(fig, use_container_width=True) # Insights st.subheader("🧠 AI Insights") col1, col2 = st.columns(2) with col1: st.info("💡 **Best Time to Buy:** Current price is fair. Consider waiting 1-2 weeks for potential drops.") st.success("📊 **Price Analysis:** 22% below peak price, good buying opportunity.") with col2: st.warning("⚠️ **Market Trend:** Slight upward pressure expected due to seasonal demand.") st.info("🔔 **Recommendation:** Set price alert for ₹23,000 for excellent deal.") else: st.info("👆 Search for a product first to view price intelligence") # Show sample forecast st.subheader("📊 Sample Price Forecast") sample_dates = [(datetime.now() + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(30)] sample_prices = [25000 + (i * 15) + random.randint(-300, 300) for i in range(30)] sample_fig = px.line( x=sample_dates[::3], y=sample_prices[::3], title="Sample Product Price Trend", labels={'x': 'Date', 'y': 'Price (₹)'} ) sample_fig.update_layout(template="plotly_white", height=400) st.plotly_chart(sample_fig, use_container_width=True) with tab3: st.subheader("🎯 Visual ShopLens Features") # Feature showcase features = [ { "icon": "🔍", "title": "Visual Product Search", "description": "Upload any product image and find visually similar items using advanced AI", "tech": "CLIP + SBERT embeddings" }, { "icon": "💰", "title": "Multi-Store Price Comparison", "description": "Real-time price comparison across Amazon, Flipkart, Snapdeal and more", "tech": "Async web scraping" }, { "icon": "📈", "title": "AI Price Forecasting", "description": "7-30 day price predictions with confidence intervals", "tech": "Prophet + LightGBM" }, { "icon": "🎯", "title": "Smart Deal Scoring", "description": "AI-powered deal analysis with 0-100 scoring system", "tech": "Statistical modeling" }, { "icon": "🔔", "title": "Price Drop Alerts", "description": "Get notified when prices drop below your target", "tech": "Email notifications" }, { "icon": "⚡", "title": "Lightning Fast Search", "description": "<250ms response time with vector similarity search", "tech": "FAISS indexing" } ] for i in range(0, len(features), 2): col1, col2 = st.columns(2) for j, col in enumerate([col1, col2]): if i + j < len(features): feature = features[i + j] with col: st.markdown(f"""

{feature['icon']} {feature['title']}

{feature['description']}

Tech: {feature['tech']}
""", unsafe_allow_html=True) # Technical specs st.subheader("🛠️ Technical Architecture") col1, col2 = st.columns(2) with col1: st.markdown(""" **🧠 Machine Learning:** - CLIP for image embeddings - SBERT for text processing - EasyOCR for text extraction - Prophet for forecasting **🔍 Search Engine:** - FAISS vector similarity - Real-time indexing - Fusion scoring algorithm """) with col2: st.markdown(""" **⚡ Performance:** - <250ms P95 search latency - 1M+ product index support - 100+ searches/minute throughput **🌐 Web Stack:** - FastAPI backend - Streamlit frontend - Async scraping pipeline """) # Footer st.markdown("---") col1, col2, col3 = st.columns(3) with col1: st.markdown("**🔍 Visual ShopLens**") st.markdown("*AI-powered shopping intelligence*") with col2: st.markdown("**🚀 Built with:**") st.markdown("• FastAPI + Streamlit") st.markdown("• OpenAI CLIP + Hugging Face") with col3: st.markdown("**⭐ Open Source**") st.markdown("[GitHub Repository](#)") if __name__ == "__main__": main()