Easonwangzk's picture
Initial commit with Git LFS
ab26b91
raw
history blame
17.7 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Amazon Multimodal Assistant - Redesigned</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
--amazon-orange: #FF9900;
--amazon-orange-dark: #E68A00;
--amazon-blue: #146EB4;
--amazon-header: #131921;
--amazon-subnav: #232F3E;
--page-bg: #FAFAFA;
--panel-bg: #FFFFFF;
--panel-muted: #F9FAFB;
--border-subtle: #E5E7EB;
--text-main: #2D3748;
--text-muted: #4B5563;
--success: #10B981;
--warning: #F59E0B;
}
* { font-family: 'Inter', sans-serif; }
body { background-color: var(--page-bg); color: var(--text-main); }
.glass-effect {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.hover-lift { transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
.hover-lift:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.search-input:focus {
box-shadow: 0 0 0 3px rgba(255, 153, 0, 0.1);
border-color: var(--amazon-orange);
}
/* Styles for dynamically generated product cards in main.js */
.product-card { transition: all 0.2s ease; }
.product-card:hover {
transform: scale(1.02);
box-shadow: 0 8px 25px -5px rgba(0, 0, 0, 0.1);
}
.similarity-bar {
background: linear-gradient(90deg, var(--amazon-orange) 0%, var(--amazon-orange-dark) 100%);
height: 4px;
border-radius: 2px;
transition: width 0.8s ease;
}
.loading-skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.fade-in { animation: fadeIn 0.5s ease-in; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.status-indicator { animation: pulse 2s infinite; }
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
.micro-interaction { transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); }
.micro-interaction:active { transform: scale(0.98); }
.answer-card {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(249, 250, 251, 0.9) 100%);
border: 1px solid rgba(229, 231, 235, 0.5);
}
.evidence-highlight {
background: linear-gradient(135deg, rgba(255, 153, 0, 0.1) 0%, rgba(255, 153, 0, 0.05) 100%);
border: 1px solid rgba(255, 153, 0, 0.2);
}
.header-bg { background: linear-gradient(135deg, var(--amazon-header) 0%, var(--amazon-subnav) 100%); }
.search-button {
background: linear-gradient(135deg, var(--amazon-orange) 0%, var(--amazon-orange-dark) 100%);
transition: all 0.3s ease;
}
.search-button:hover {
background: linear-gradient(135deg, var(--amazon-orange-dark) 0%, var(--amazon-orange) 100%);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(255, 153, 0, 0.3);
}
.upload-area { border: 2px dashed #D1D5DB; transition: all 0.3s ease; }
.upload-area:hover {
border-color: var(--amazon-orange);
background-color: rgba(255, 153, 0, 0.05);
}
.upload-area.dragover {
border-color: var(--amazon-orange);
background-color: rgba(255, 153, 0, 0.1);
}
@media (max-width: 1024px) {
.three-column-layout { grid-template-columns: 1fr; gap: 1rem; }
.sidebar-panel { order: -1; }
}
</style>
</head>
<body class="min-h-screen flex flex-col">
<header class="header-bg text-white shadow-lg">
<div class="container mx-auto px-6 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<img src="amazon-logo.png" onerror="this.style.display='none'" alt="Amazon" class="h-8 w-auto">
<div>
<h1 class="text-2xl font-bold">Multimodal Assistant</h1>
<p class="text-sm text-gray-300">AI-powered product search with CLIP + GPT-4</p>
</div>
</div>
<div class="flex items-center space-x-4">
<div class="flex items-center space-x-2 glass-effect px-3 py-2 rounded-full">
<div class="w-2 h-2 bg-green-400 rounded-full status-indicator"></div>
<span class="text-xs">Index Ready</span>
</div>
<div class="flex items-center space-x-2 glass-effect px-3 py-2 rounded-full">
<span class="text-xs">9,509 Products</span>
</div>
</div>
</div>
</div>
</header>
<main class="container mx-auto px-6 py-8 flex-grow">
<div class="three-column-layout grid grid-cols-12 gap-6">
<div class="col-span-12 lg:col-span-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 hover-lift">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Search Query</h2>
<div class="mb-6">
<label for="search-text" class="block text-sm font-medium text-gray-700 mb-2">
Describe what you're looking for
</label>
<textarea
id="search-text"
placeholder="e.g., 'Wireless earbuds with noise cancellation under $150' or 'What is this product and how is it used?'"
class="search-input w-full p-4 border border-gray-300 rounded-lg resize-none focus:outline-none transition-all duration-200"
rows="3"
></textarea>
</div>
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-2">
Upload product image (optional)
</label>
<div id="upload-area" class="upload-area rounded-lg p-8 text-center cursor-pointer">
<div id="upload-content">
<svg class="mx-auto h-12 w-12 text-gray-400 mb-4" stroke="currentColor" fill="none" viewBox="0 0 48 48">
<path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<p class="text-sm text-gray-600 mb-2">
<span class="font-medium text-orange-600">Click to upload</span> or drag and drop
</p>
<p class="text-xs text-gray-500">PNG, JPG up to 10MB</p>
</div>
<div id="image-preview" class="hidden relative">
<img id="preview-img" class="mx-auto max-h-32 rounded-lg shadow-sm" alt="Preview">
<button id="remove-image" class="mt-2 text-sm text-red-600 hover:text-red-800">Remove image</button>
</div>
</div>
<input type="file" id="image-input" accept="image/*" class="hidden">
</div>
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-3">Search Mode</label>
<div class="space-y-2">
<label class="flex items-center cursor-pointer">
<input type="radio" name="search-mode" value="text_only" class="text-orange-600 focus:ring-orange-500">
<span class="ml-2 text-sm text-gray-700">Text Only</span>
</label>
<label class="flex items-center cursor-pointer">
<input type="radio" name="search-mode" value="image_only" class="text-orange-600 focus:ring-orange-500">
<span class="ml-2 text-sm text-gray-700">Image Only</span>
</label>
<label class="flex items-center cursor-pointer">
<input type="radio" name="search-mode" value="multimodal" checked class="text-orange-600 focus:ring-orange-500">
<span class="ml-2 text-sm text-gray-700">Multimodal (Text + Image)</span>
</label>
</div>
</div>
<button id="search-button" class="search-button w-full text-white font-semibold py-3 px-6 rounded-lg micro-interaction">
<span class="flex items-center justify-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<span id="btn-text">Search Products</span>
<div id="loading-state" class="hidden ml-2 w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
</span>
</button>
<div class="mt-6 pt-6 border-t border-gray-100">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-semibold text-gray-800">History</h3>
<button id="clear-history" class="text-xs text-red-600 hover:text-red-800">Clear</button>
</div>
<div id="history-container" class="space-y-2 max-h-48 overflow-y-auto pr-1">
<div class="text-xs text-gray-400 text-center py-2">No history yet</div>
</div>
</div>
</div>
</div>
<div class="col-span-12 lg:col-span-5">
<div id="query-card" class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6 hover-lift hidden fade-in">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-800">Current Query</h3>
<span id="retrieval-method" class="px-3 py-1 bg-orange-100 text-orange-800 text-xs font-medium rounded-full">
Multimodal Fusion
</span>
</div>
<div id="query-content" class="text-gray-700 text-sm leading-relaxed font-medium">
</div>
<div id="query-image" class="mt-4 hidden">
<img class="rounded-lg shadow-sm max-h-32 object-contain border border-gray-100" alt="Query image">
</div>
</div>
<div id="answer-card" class="answer-card rounded-xl p-6 mb-6 hover-lift hidden fade-in">
<div class="flex items-center mb-4">
<div class="w-8 h-8 bg-gradient-to-br from-orange-400 to-orange-600 rounded-full flex items-center justify-center mr-3 shadow-md">
<svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 20 20">
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<h3 class="text-lg font-semibold text-gray-800">AI Assistant Answer</h3>
</div>
<div id="answer-content" class="text-gray-700 leading-relaxed text-sm whitespace-pre-wrap">
</div>
<div class="mt-4 text-xs text-gray-500 flex items-center">
<span class="inline-block w-2 h-2 bg-green-500 rounded-full mr-2"></span>
Generated using CLIP retrieval + GPT-4 reasoning
</div>
</div>
<div id="evidence-card" class="evidence-highlight rounded-xl p-6 mb-6 hover-lift hidden fade-in">
<h4 class="text-md font-semibold text-gray-800 mb-3">πŸ” Grounding Evidence</h4>
<div class="flex items-start space-x-4">
<div class="flex-shrink-0 bg-white p-1 rounded-lg border border-gray-200">
<img id="evidence-image" class="w-20 h-20 object-contain rounded-md" src="https://via.placeholder.com/150?text=Wait..." onerror="this.src='https://via.placeholder.com/150?text=No+Img'" alt="Evidence product">
</div>
<div class="flex-1">
<h5 id="evidence-name" class="font-semibold text-gray-800 mb-1 text-sm line-clamp-2">Product Name</h5>
<p id="evidence-category" class="text-xs text-gray-600 mb-2">Category</p>
<div class="flex items-center space-x-2">
<span class="text-xs bg-orange-100 text-orange-800 px-2 py-1 rounded font-medium">Top Match</span>
<span id="evidence-similarity" class="text-xs text-green-700 font-bold">95.2% match</span>
</div>
</div>
</div>
<p class="text-xs text-gray-500 mt-4 italic">
The assistant's answer is primarily based on this product and similar items from the retrieved set.
</p>
</div>
</div>
<div class="col-span-12 lg:col-span-3">
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 hover-lift h-full flex flex-col">
<div class="flex items-center justify-between mb-4 border-b border-gray-100 pb-3">
<h3 class="text-lg font-semibold text-gray-800">Retrieved Products</h3>
<span id="results-count" class="text-xs font-medium bg-gray-100 text-gray-600 px-2 py-1 rounded-full">0 items</span>
</div>
<div id="results-container" class="space-y-3 flex-1 overflow-y-auto custom-scrollbar" style="max-height: 70vh;">
<div class="text-sm text-gray-400 text-center py-10">
Results from ChromaDB will appear here.
</div>
</div>
</div>
</div>
</div>
</main>
<footer class="bg-white border-t border-gray-200 mt-auto">
<div class="container mx-auto px-6 py-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 text-sm">
<div>
<h4 class="font-semibold text-gray-800 mb-2">System Information</h4>
<div class="space-y-1 text-gray-500">
<p>Products indexed: 9,509</p>
<p>Index status: <span class="text-green-600 font-medium">Ready</span></p>
</div>
</div>
<div>
<h4 class="font-semibold text-gray-800 mb-2">How it Works</h4>
<div class="space-y-1 text-gray-500">
<p>1. CLIP encodes your query</p>
<p>2. ChromaDB retrieves similar products</p>
</div>
</div>
<div>
<h4 class="font-semibold text-gray-800 mb-2">Tips</h4>
<div class="space-y-1 text-gray-500">
<p>β€’ Combine text + image for best results</p>
<p>β€’ Be specific in your descriptions</p>
</div>
</div>
</div>
<div class="border-t border-gray-100 mt-8 pt-6 text-center text-xs text-gray-400">
&copy; 2025 Amazon Multimodal RAG Demo. Powered by FastAPI + ChromaDB.
</div>
</div>
</footer>
<script src="main.js"></script>
</body>
</html>