shukdevdatta123's picture
Update index.html
c86a3da verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenAI O4 Analysis App</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<style>
:root {
--primary: #6366f1;
--primary-dark: #4f46e5;
--primary-light: #818cf8;
}
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
min-height: 100vh;
}
.gradient-bg {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
}
.tab-button {
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.tab-button::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
background: white;
transform: scaleX(0);
transform-origin: right;
transition: transform 0.3s ease;
}
.tab-button.active::after {
transform: scaleX(1);
transform-origin: left;
}
.result-box {
transition: all 0.3s ease;
min-height: 200px;
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
}
.loading-dots {
display: inline-block;
}
.loading-dots span {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: var(--primary);
margin: 0 2px;
animation: bounce 1.4s infinite ease-in-out both;
}
.loading-dots span:nth-child(1) {
animation-delay: -0.32s;
}
.loading-dots span:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes bounce {
0%, 80%, 100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
.file-input-label {
transition: all 0.3s ease;
position: relative;
}
.file-input-label:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.3), 0 2px 4px -1px rgba(99, 102, 241, 0.06);
}
.glow {
animation: glow 2s infinite alternate;
}
@keyframes glow {
from {
box-shadow: 0 0 5px rgba(99, 102, 241, 0.5);
}
to {
box-shadow: 0 0 20px rgba(99, 102, 241, 0.8);
}
}
.card {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.btn-primary {
background: var(--primary);
transition: all 0.3s ease;
}
.btn-primary:hover {
background: var(--primary-dark);
transform: translateY(-2px);
}
.btn-secondary {
background: #f1f5f9;
transition: all 0.3s ease;
}
.btn-secondary:hover {
background: #e2e8f0;
transform: translateY(-2px);
}
.input-field {
transition: all 0.3s ease;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05);
}
.input-field:focus {
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3);
}
.preview-container {
position: relative;
border-radius: 0.5rem;
overflow: hidden;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.remove-btn {
position: absolute;
top: 0.5rem;
right: 0.5rem;
background: rgba(0, 0, 0, 0.6);
color: white;
border-radius: 50%;
width: 2rem;
height: 2rem;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.remove-btn:hover {
background: rgba(239, 68, 68, 0.8);
transform: scale(1.1);
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
.floating {
animation: floating 6s ease-in-out infinite;
}
@keyframes floating {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-10px);
}
100% {
transform: translateY(0px);
}
}
.wave {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
overflow: hidden;
line-height: 0;
}
.wave svg {
position: relative;
display: block;
width: calc(100% + 1.3px);
height: 150px;
}
.wave .shape-fill {
fill: #FFFFFF;
}
.feature-icon {
width: 60px;
height: 60px;
border-radius: 50%;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(99, 102, 241, 0.2) 100%);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1rem;
}
</style>
</head>
<body class="antialiased">
<!-- Wave Background -->
<div class="fixed top-0 left-0 w-full h-full -z-10 opacity-10">
<div class="absolute top-0 left-0 w-full h-full bg-gradient-to-br from-indigo-100 to-purple-100"></div>
</div>
<!-- Main Container -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<!-- Header -->
<div class="text-center mb-16 animate__animated animate__fadeIn">
<div class="inline-flex items-center justify-center mb-4 px-6 py-2 rounded-full bg-indigo-50 text-indigo-600">
<i class="fas fa-bolt mr-2"></i>
<span class="font-medium">AI-Powered Analysis</span>
</div>
<h1 class="text-5xl font-bold text-gray-900 mb-4">OpenAI O4 Mini <span class="text-indigo-600">Analysis</span></h1>
<p class="text-xl text-gray-600 max-w-2xl mx-auto">Unlock insights from your documents and images with cutting-edge AI technology</p>
</div>
<!-- Features Section -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 mb-16">
<div class="bg-white rounded-xl card p-6 text-center">
<div class="feature-icon mx-auto">
<i class="fas fa-file-pdf text-indigo-600 text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">PDF Analysis</h3>
<p class="text-gray-600">Extract key information and insights from your PDF documents with AI-powered analysis.</p>
</div>
<div class="bg-white rounded-xl card p-6 text-center">
<div class="feature-icon mx-auto">
<i class="fas fa-image text-indigo-600 text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">Image Analysis</h3>
<p class="text-gray-600">Understand visual content with advanced image recognition and description capabilities.</p>
</div>
<div class="bg-white rounded-xl card p-6 text-center">
<div class="feature-icon mx-auto">
<i class="fas fa-brain text-indigo-600 text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">Smart Insights</h3>
<p class="text-gray-600">Get comprehensive answers to your questions with adjustable reasoning levels.</p>
</div>
</div>
<!-- API Key Input -->
<div class="bg-white rounded-xl card p-8 mb-12 animate__animated animate__fadeInUp relative overflow-hidden">
<div class="absolute -top-10 -right-10 w-32 h-32 rounded-full bg-indigo-100 opacity-50"></div>
<div class="absolute -bottom-10 -left-10 w-32 h-32 rounded-full bg-purple-100 opacity-50"></div>
<div class="relative z-10">
<label for="api-key" class="block text-sm font-medium text-gray-700 mb-2 flex items-center">
<i class="fas fa-key mr-2 text-indigo-600"></i>
OpenAI API Key
</label>
<div class="relative">
<input
type="password"
id="api-key"
placeholder="Enter your OpenAI API key here..."
class="w-full px-4 py-3 rounded-lg border border-gray-300 input-field focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
>
<button
onclick="toggleApiKeyVisibility()"
class="absolute right-3 top-3 text-gray-500 hover:text-indigo-600 focus:outline-none"
>
<i class="far fa-eye"></i>
</button>
</div>
<p class="mt-2 text-sm text-gray-500">
<i class="fas fa-info-circle mr-1 text-indigo-500"></i>
Your API key is only used for requests and is not stored.
</p>
</div>
</div>
<!-- Tabs Navigation -->
<div class="flex space-x-2 mb-8 animate__animated animate__fadeIn">
<button
id="pdf-tab"
onclick="switchTab('pdf')"
class="tab-button active px-8 py-4 rounded-t-lg font-medium bg-white text-indigo-600 border-b-2 border-indigo-600"
>
<i class="fas fa-file-pdf mr-2"></i>
PDF Analysis
</button>
<button
id="image-tab"
onclick="switchTab('image')"
class="tab-button px-8 py-4 rounded-t-lg font-medium bg-white text-gray-600 hover:text-indigo-600 border-b-2 border-transparent hover:border-gray-300"
>
<i class="fas fa-image mr-2"></i>
Image Analysis
</button>
</div>
<!-- PDF Analysis Tab -->
<div id="pdf-content" class="animate__animated animate__fadeIn">
<div class="bg-white rounded-b-xl rounded-tr-xl card overflow-hidden">
<div class="p-8">
<h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center">
<i class="fas fa-file-pdf mr-3 text-indigo-600"></i>
PDF Document Analysis
</h2>
<div class="mb-8">
<label class="block text-sm font-medium text-gray-700 mb-3">Upload PDF</label>
<div id="pdf-upload-container">
<label for="pdf-upload" class="file-input-label cursor-pointer flex flex-col items-center justify-center px-6 py-12 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50 hover:bg-gray-100 transition duration-200">
<i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
<span class="text-sm font-medium text-gray-600">Drag & drop your PDF here or click to browse</span>
<span class="text-xs text-gray-500 mt-1">Supports .pdf files up to 10MB</span>
<input id="pdf-upload" type="file" accept=".pdf" class="hidden">
</label>
</div>
<div id="pdf-preview-container" class="hidden mt-4">
<div class="preview-container p-4 bg-gray-50 rounded-lg">
<div class="flex items-center">
<i class="fas fa-file-pdf text-3xl text-red-500 mr-3"></i>
<div>
<p id="pdf-filename" class="font-medium text-gray-800"></p>
<p id="pdf-filesize" class="text-sm text-gray-500"></p>
</div>
<button id="remove-pdf" class="ml-auto remove-btn">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</div>
</div>
<div class="mb-8">
<label for="pdf-prompt" class="block text-sm font-medium text-gray-700 mb-3">Analysis Prompt</label>
<textarea
id="pdf-prompt"
rows="4"
class="w-full px-4 py-3 rounded-lg border border-gray-300 input-field focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
placeholder="What would you like to know about this PDF? (e.g., 'Summarize this document', 'What are the key points?', 'Extract the main ideas')"
>What is this PDF about?</textarea>
</div>
<div class="mb-8">
<label class="block text-sm font-medium text-gray-700 mb-3">Reasoning Effort Level</label>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<label class="inline-flex items-center bg-gray-50 hover:bg-gray-100 rounded-lg p-4 cursor-pointer transition duration-200">
<input type="radio" name="pdf-effort" value="low" class="h-5 w-5 text-indigo-600 focus:ring-indigo-500">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Quick Scan</span>
<span class="block text-xs text-gray-500">Basic analysis, faster results</span>
</div>
</label>
<label class="inline-flex items-center bg-gray-50 hover:bg-gray-100 rounded-lg p-4 cursor-pointer transition duration-200">
<input type="radio" name="pdf-effort" value="medium" checked class="h-5 w-5 text-indigo-600 focus:ring-indigo-500">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Standard</span>
<span class="block text-xs text-gray-500">Balanced speed and depth</span>
</div>
</label>
<label class="inline-flex items-center bg-gray-50 hover:bg-gray-100 rounded-lg p-4 cursor-pointer transition duration-200">
<input type="radio" name="pdf-effort" value="high" class="h-5 w-5 text-indigo-600 focus:ring-indigo-500">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Deep Dive</span>
<span class="block text-xs text-gray-500">Comprehensive, detailed analysis</span>
</div>
</label>
</div>
</div>
<button
id="analyze-pdf-btn"
onclick="analyzePDF()"
class="w-full py-4 px-6 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition duration-200 transform hover:scale-[1.02] focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 flex items-center justify-center"
>
<i class="fas fa-magic mr-2"></i>
Analyze PDF
</button>
</div>
<div id="pdf-result" class="result-box border-t border-gray-200 p-8 hidden">
<div class="flex items-center justify-between mb-6">
<h3 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-chart-line mr-2 text-indigo-600"></i>
Analysis Results
</h3>
<button id="copy-pdf-result" class="text-sm text-indigo-600 hover:text-indigo-800 flex items-center">
<i class="far fa-copy mr-1"></i> Copy
</button>
</div>
<div id="pdf-result-content" class="min-h-40 p-6 bg-white rounded-lg border border-gray-200 shadow-sm"></div>
</div>
</div>
</div>
<!-- Image Analysis Tab -->
<div id="image-content" class="hidden animate__animated animate__fadeIn">
<div class="bg-white rounded-b-xl rounded-tr-xl card overflow-hidden">
<div class="p-8">
<h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center">
<i class="fas fa-image mr-3 text-indigo-600"></i>
Image Analysis
</h2>
<div class="mb-8">
<label class="block text-sm font-medium text-gray-700 mb-3">Image Source</label>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<div class="flex items-center space-x-4 mb-4">
<div class="flex-1 border-b-2 border-indigo-600 pb-2">
<h4 class="font-medium text-indigo-600 flex items-center">
<i class="fas fa-upload mr-2"></i>
Upload Image
</h4>
</div>
<div class="flex-1 text-center text-gray-400 pb-2">
<h4 class="font-medium">or</h4>
</div>
<div class="flex-1 border-b-2 border-gray-200 pb-2">
<h4 class="font-medium text-gray-600 hover:text-indigo-600 cursor-pointer flex items-center justify-end" onclick="switchImageSource('url')">
<i class="fas fa-link mr-2"></i>
Use URL
</h4>
</div>
</div>
<div id="image-upload-container">
<label for="image-upload" class="file-input-label cursor-pointer flex flex-col items-center justify-center px-6 py-12 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50 hover:bg-gray-100 transition duration-200">
<i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
<span class="text-sm font-medium text-gray-600">Drag & drop your image here or click to browse</span>
<span class="text-xs text-gray-500 mt-1">Supports JPG, PNG, GIF up to 5MB</span>
<input id="image-upload" type="file" accept="image/*" class="hidden">
</label>
</div>
<div id="image-preview-container" class="hidden mt-4">
<div class="preview-container">
<img id="image-preview" src="" alt="Preview" class="w-full h-auto rounded-lg">
<button id="remove-image" class="remove-btn">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</div>
<div id="image-url-container" class="hidden">
<div class="flex items-center space-x-4 mb-4">
<div class="flex-1 border-b-2 border-gray-200 pb-2">
<h4 class="font-medium text-gray-600 hover:text-indigo-600 cursor-pointer flex items-center" onclick="switchImageSource('upload')">
<i class="fas fa-upload mr-2"></i>
Upload Image
</h4>
</div>
<div class="flex-1 text-center text-gray-400 pb-2">
<h4 class="font-medium">or</h4>
</div>
<div class="flex-1 border-b-2 border-indigo-600 pb-2">
<h4 class="font-medium text-indigo-600 flex items-center justify-end">
<i class="fas fa-link mr-2"></i>
Use URL
</h4>
</div>
</div>
<div class="mb-4">
<label for="image-url" class="block text-sm font-medium text-gray-700 mb-2">Image URL</label>
<input
type="text"
id="image-url"
placeholder="https://example.com/image.jpg"
class="w-full px-4 py-3 rounded-lg border border-gray-300 input-field focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
>
</div>
<div id="url-preview-container" class="hidden mt-4">
<div class="preview-container">
<img id="url-preview" src="" alt="Preview" class="w-full h-auto rounded-lg">
<button id="remove-url" class="remove-btn">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="mb-8">
<label for="image-prompt" class="block text-sm font-medium text-gray-700 mb-3">Analysis Prompt</label>
<textarea
id="image-prompt"
rows="4"
class="w-full px-4 py-3 rounded-lg border border-gray-300 input-field focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
placeholder="What would you like to know about this image? (e.g., 'Describe this image', 'What objects are visible?', 'What is the main subject?')"
>What is this image about?</textarea>
</div>
<div class="mb-8">
<label class="block text-sm font-medium text-gray-700 mb-3">Reasoning Effort Level</label>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<label class="inline-flex items-center bg-gray-50 hover:bg-gray-100 rounded-lg p-4 cursor-pointer transition duration-200">
<input type="radio" name="image-effort" value="low" class="h-5 w-5 text-indigo-600 focus:ring-indigo-500">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Quick Scan</span>
<span class="block text-xs text-gray-500">Basic analysis, faster results</span>
</div>
</label>
<label class="inline-flex items-center bg-gray-50 hover:bg-gray-100 rounded-lg p-4 cursor-pointer transition duration-200">
<input type="radio" name="image-effort" value="medium" checked class="h-5 w-5 text-indigo-600 focus:ring-indigo-500">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Standard</span>
<span class="block text-xs text-gray-500">Balanced speed and depth</span>
</div>
</label>
<label class="inline-flex items-center bg-gray-50 hover:bg-gray-100 rounded-lg p-4 cursor-pointer transition duration-200">
<input type="radio" name="image-effort" value="high" class="h-5 w-5 text-indigo-600 focus:ring-indigo-500">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Deep Dive</span>
<span class="block text-xs text-gray-500">Comprehensive, detailed analysis</span>
</div>
</label>
</div>
</div>
<button
id="analyze-image-btn"
onclick="analyzeImage()"
class="w-full py-4 px-6 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition duration-200 transform hover:scale-[1.02] focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 flex items-center justify-center"
>
<i class="fas fa-magic mr-2"></i>
Analyze Image
</button>
</div>
<div id="image-result" class="result-box border-t border-gray-200 p-8 hidden">
<div class="flex items-center justify-between mb-6">
<h3 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-chart-line mr-2 text-indigo-600"></i>
Analysis Results
</h3>
<button id="copy-image-result" class="text-sm text-indigo-600 hover:text-indigo-800 flex items-center">
<i class="far fa-copy mr-1"></i> Copy
</button>
</div>
<div id="image-result-content" class="min-h-40 p-6 bg-white rounded-lg border border-gray-200 shadow-sm"></div>
</div>
</div>
</div>
<!-- How It Works Section -->
<div class="mt-20 bg-white rounded-xl card p-8 relative overflow-hidden">
<div class="absolute -top-20 -right-20 w-64 h-64 rounded-full bg-indigo-100 opacity-30"></div>
<div class="absolute -bottom-20 -left-20 w-64 h-64 rounded-full bg-purple-100 opacity-30"></div>
<div class="relative z-10">
<h2 class="text-3xl font-bold text-center text-gray-900 mb-12">
<span class="text-indigo-600">How It Works</span>
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="flex flex-col items-center text-center">
<div class="w-16 h-16 rounded-full bg-indigo-100 text-indigo-600 flex items-center justify-center mb-4 text-2xl">
1
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">Upload Your File</h3>
<p class="text-gray-600">Select a PDF document or image you want to analyze by uploading from your device or providing a URL.</p>
</div>
<div class="flex flex-col items-center text-center">
<div class="w-16 h-16 rounded-full bg-indigo-100 text-indigo-600 flex items-center justify-center mb-4 text-2xl">
2
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">Set Your Preferences</h3>
<p class="text-gray-600">Enter your analysis prompt and choose the reasoning effort level that suits your needs.</p>
</div>
<div class="flex flex-col items-center text-center">
<div class="w-16 h-16 rounded-full bg-indigo-100 text-indigo-600 flex items-center justify-center mb-4 text-2xl">
3
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">Get AI Insights</h3>
<p class="text-gray-600">Receive comprehensive analysis and answers to your questions powered by OpenAI's advanced models.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer class="bg-gray-900 text-white py-12 mt-20 relative">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<h3 class="text-xl font-semibold mb-4">OpenAI O4 Mini Analysis</h3>
<p class="text-gray-400">Unlock the power of AI to analyze your documents and images with ease.</p>
</div>
<div>
<h3 class="text-xl font-semibold mb-4">Quick Links</h3>
<ul class="space-y-2">
<li><a href="#" class="text-gray-400 hover:text-white transition duration-200">Home</a></li>
<li><a href="#" class="text-gray-400 hover:text-white transition duration-200">PDF Analysis</a></li>
<li><a href="#" class="text-gray-400 hover:text-white transition duration-200">Image Analysis</a></li>
</ul>
</div>
<div>
<h3 class="text-xl font-semibold mb-4">Connect</h3>
<div class="flex space-x-4">
<a href="https://www.facebook.com/shukdevdattatroy" class="text-gray-400 hover:text-white transition duration-200 text-xl"><i class="fab fa-facebook-f"></i></a>
<a href="https://github.com/shukdevtroy" class="text-gray-400 hover:text-white transition duration-200 text-xl"><i class="fab fa-github"></i></a>
<a href="https://www.linkedin.com/in/shukdev-datta-729767144/" class="text-gray-400 hover:text-white transition duration-200 text-xl"><i class="fab fa-linkedin"></i></a>
<a href="https://huggingface.co./shukdevdatta123" class="text-gray-400 hover:text-white transition duration-200 text-xl"><i class="fa-solid fa-link"></i></a>
</div>
</div>
</div>
<div class="border-t border-gray-800 mt-8 pt-8 text-center text-gray-400">
<p>&copy; 2023 OpenAI O4 Mini Analysis. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// Toggle API key visibility
function toggleApiKeyVisibility() {
const apiKeyInput = document.getElementById('api-key');
const toggleBtn = apiKeyInput.nextElementSibling;
if (apiKeyInput.type === 'password') {
apiKeyInput.type = 'text';
toggleBtn.innerHTML = '<i class="far fa-eye-slash"></i>';
} else {
apiKeyInput.type = 'password';
toggleBtn.innerHTML = '<i class="far fa-eye"></i>';
}
}
// Switch between tabs
function switchTab(tab) {
const pdfTab = document.getElementById('pdf-tab');
const imageTab = document.getElementById('image-tab');
const pdfContent = document.getElementById('pdf-content');
const imageContent = document.getElementById('image-content');
if (tab === 'pdf') {
pdfTab.classList.remove('bg-white', 'text-gray-600', 'border-transparent', 'hover:border-gray-300');
pdfTab.classList.add('bg-white', 'text-indigo-600', 'border-b-2', 'border-indigo-600');
imageTab.classList.remove('bg-white', 'text-indigo-600', 'border-b-2', 'border-indigo-600');
imageTab.classList.add('bg-white', 'text-gray-600', 'border-transparent', 'hover:border-gray-300');
pdfContent.classList.remove('hidden');
imageContent.classList.add('hidden');
// Add animation
pdfContent.classList.remove('animate__fadeIn');
void pdfContent.offsetWidth; // Trigger reflow
pdfContent.classList.add('animate__fadeIn');
} else {
imageTab.classList.remove('bg-white', 'text-gray-600', 'border-transparent', 'hover:border-gray-300');
imageTab.classList.add('bg-white', 'text-indigo-600', 'border-b-2', 'border-indigo-600');
pdfTab.classList.remove('bg-white', 'text-indigo-600', 'border-b-2', 'border-indigo-600');
pdfTab.classList.add('bg-white', 'text-gray-600', 'border-transparent', 'hover:border-gray-300');
imageContent.classList.remove('hidden');
pdfContent.classList.add('hidden');
// Add animation
imageContent.classList.remove('animate__fadeIn');
void imageContent.offsetWidth; // Trigger reflow
imageContent.classList.add('animate__fadeIn');
}
}
// Switch between image upload and URL
function switchImageSource(source) {
const uploadContainer = document.getElementById('image-upload-container');
const urlContainer = document.getElementById('image-url-container');
const uploadPreview = document.getElementById('image-preview-container');
const urlPreview = document.getElementById('url-preview-container');
if (source === 'upload') {
uploadContainer.classList.remove('hidden');
urlContainer.classList.add('hidden');
urlPreview.classList.add('hidden');
document.getElementById('image-url').value = '';
} else {
uploadContainer.classList.add('hidden');
urlContainer.classList.remove('hidden');
uploadPreview.classList.add('hidden');
document.getElementById('image-upload').value = '';
}
}
// Handle file upload display for PDF
document.getElementById('pdf-upload').addEventListener('change', function(e) {
const uploadContainer = document.getElementById('pdf-upload-container');
const previewContainer = document.getElementById('pdf-preview-container');
const filenameDisplay = document.getElementById('pdf-filename');
const filesizeDisplay = document.getElementById('pdf-filesize');
if (this.files.length > 0) {
const file = this.files[0];
filenameDisplay.textContent = file.name;
filesizeDisplay.textContent = formatFileSize(file.size);
uploadContainer.classList.add('hidden');
previewContainer.classList.remove('hidden');
} else {
uploadContainer.classList.remove('hidden');
previewContainer.classList.add('hidden');
}
});
// Handle file upload display for Image
document.getElementById('image-upload').addEventListener('change', function(e) {
const uploadContainer = document.getElementById('image-upload-container');
const previewContainer = document.getElementById('image-preview-container');
const previewImage = document.getElementById('image-preview');
if (this.files.length > 0) {
const file = this.files[0];
const reader = new FileReader();
reader.onload = function(event) {
previewImage.src = event.target.result;
uploadContainer.classList.add('hidden');
previewContainer.classList.remove('hidden');
}
reader.readAsDataURL(file);
} else {
uploadContainer.classList.remove('hidden');
previewContainer.classList.add('hidden');
}
});
// Handle image URL preview
document.getElementById('image-url').addEventListener('change', function(e) {
const url = this.value.trim();
const previewContainer = document.getElementById('url-preview-container');
const previewImage = document.getElementById('url-preview');
if (url) {
previewImage.src = url;
previewContainer.classList.remove('hidden');
// Check if image loads successfully
previewImage.onload = function() {
previewContainer.classList.remove('hidden');
}
previewImage.onerror = function() {
previewContainer.classList.add('hidden');
alert('Could not load image from the provided URL. Please check the URL and try again.');
}
} else {
previewContainer.classList.add('hidden');
}
});
// Remove PDF file
document.getElementById('remove-pdf').addEventListener('click', function() {
document.getElementById('pdf-upload').value = '';
document.getElementById('pdf-upload-container').classList.remove('hidden');
document.getElementById('pdf-preview-container').classList.add('hidden');
});
// Remove uploaded image
document.getElementById('remove-image').addEventListener('click', function() {
document.getElementById('image-upload').value = '';
document.getElementById('image-upload-container').classList.remove('hidden');
document.getElementById('image-preview-container').classList.add('hidden');
});
// Remove URL image
document.getElementById('remove-url').addEventListener('click', function() {
document.getElementById('image-url').value = '';
document.getElementById('url-preview-container').classList.add('hidden');
});
// Format file size
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// Show loading state
function showLoading(element) {
element.innerHTML = `
<div class="flex flex-col items-center justify-center py-8">
<div class="loading-dots mb-4">
<span></span>
<span></span>
<span></span>
</div>
<p class="text-gray-500">Analyzing content, please wait...</p>
</div>
`;
}
// Copy result to clipboard
document.getElementById('copy-pdf-result')?.addEventListener('click', function() {
const resultContent = document.getElementById('pdf-result-content').textContent;
navigator.clipboard.writeText(resultContent).then(() => {
const originalText = this.innerHTML;
this.innerHTML = '<i class="fas fa-check mr-1"></i> Copied!';
setTimeout(() => {
this.innerHTML = originalText;
}, 2000);
});
});
document.getElementById('copy-image-result')?.addEventListener('click', function() {
const resultContent = document.getElementById('image-result-content').textContent;
navigator.clipboard.writeText(resultContent).then(() => {
const originalText = this.innerHTML;
this.innerHTML = '<i class="fas fa-check mr-1"></i> Copied!';
setTimeout(() => {
this.innerHTML = originalText;
}, 2000);
});
});
// Analyze PDF function
async function analyzePDF() {
const apiKey = document.getElementById('api-key').value;
const pdfFile = document.getElementById('pdf-upload').files[0];
const prompt = document.getElementById('pdf-prompt').value;
const effortLevel = document.querySelector('input[name="pdf-effort"]:checked').value;
const resultContent = document.getElementById('pdf-result-content');
const resultBox = document.getElementById('pdf-result');
if (!apiKey) {
showAlert('Please provide an OpenAI API key.', 'error');
return;
}
if (!pdfFile) {
showAlert('Please upload a PDF file.', 'error');
return;
}
// Show loading state
resultBox.classList.remove('hidden');
showLoading(resultContent);
try {
// Read the PDF file and convert to base64
const pdfBase64 = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const arrayBuffer = reader.result;
const bytes = new Uint8Array(arrayBuffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
const base64 = btoa(binary);
resolve(base64);
};
reader.onerror = reject;
reader.readAsArrayBuffer(pdfFile);
});
// Create the request payload
const payload = {
model: "o4-mini",
input: [
{
role: "user",
content: [
{
type: "input_text",
text: prompt
},
{
type: "input_file",
filename: pdfFile.name,
file_data: `data:application/pdf;base64,${pdfBase64}`
}
]
}
],
text: {
format: {
type: "text"
}
},
reasoning: {
effort: effortLevel
},
tools: [],
store: true
};
// Make the API request
const response = await axios.post('https://api.openai.com/v1/responses', payload, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
// Process the response
const result = extractTextFromResponse(response.data);
resultContent.innerHTML = `<div class="text-gray-700 whitespace-pre-wrap">${result}</div>`;
} catch (error) {
console.error('Error:', error);
let errorMessage = 'An error occurred while analyzing the PDF.';
if (error.response) {
errorMessage = `Error: ${error.response.data.error?.message || error.response.statusText}`;
} else if (error.message) {
errorMessage = `Error: ${error.message}`;
}
resultContent.innerHTML = `<div class="text-red-600">${errorMessage}</div>`;
}
}
// Analyze Image function
async function analyzeImage() {
const apiKey = document.getElementById('api-key').value;
const imageFile = document.getElementById('image-upload').files[0];
const imageUrl = document.getElementById('image-url').value;
const prompt = document.getElementById('image-prompt').value;
const effortLevel = document.querySelector('input[name="image-effort"]:checked').value;
const resultContent = document.getElementById('image-result-content');
const resultBox = document.getElementById('image-result');
if (!apiKey) {
showAlert('Please provide an OpenAI API key.', 'error');
return;
}
if (!imageFile && !imageUrl) {
showAlert('Please upload an image or provide an image URL.', 'error');
return;
}
if (!prompt) {
showAlert('Please provide a prompt for the image analysis.', 'error');
return;
}
// Show loading state
resultBox.classList.remove('hidden');
showLoading(resultContent);
try {
const content = [
{
type: "input_text",
text: prompt
}
];
if (imageFile) {
// Read the image file and convert to base64
const imageBase64 = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const base64 = reader.result.split(',')[1];
resolve(base64);
};
reader.onerror = reject;
reader.readAsDataURL(imageFile);
});
content.unshift({
type: "input_image",
image_url: `data:image/png;base64,${imageBase64}`
});
} else if (imageUrl) {
content.unshift({
type: "input_image",
image_url: imageUrl
});
}
// Create the request payload
const payload = {
model: "o4-mini",
input: [
{
role: "user",
content: content
}
],
text: {
format: {
type: "text"
}
},
reasoning: {
effort: effortLevel
},
tools: [],
store: true
};
// Make the API request
const response = await axios.post('https://api.openai.com/v1/responses', payload, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
// Process the response
const result = extractTextFromResponse(response.data);
resultContent.innerHTML = `<div class="text-gray-700 whitespace-pre-wrap">${result}</div>`;
} catch (error) {
console.error('Error:', error);
let errorMessage = 'An error occurred while analyzing the image.';
if (error.response) {
errorMessage = `Error: ${error.response.data.error?.message || error.response.statusText}`;
} else if (error.message) {
errorMessage = `Error: ${error.message}`;
}
resultContent.innerHTML = `<div class="text-red-600">${errorMessage}</div>`;
}
}
// Extract text from response
function extractTextFromResponse(response) {
try {
// First check if response has an output attribute
if (response.output) {
const output = response.output;
// Look for message items in the output list
for (const item of output) {
if (item.role === 'assistant') {
for (const contentItem of item.content) {
if (contentItem.type === 'output_text') {
return contentItem.text;
}
}
}
}
// If we couldn't find it in the expected structure, return an error
return `Couldn't extract text from response: ${JSON.stringify(response)}`;
}
return `Unexpected response structure: ${JSON.stringify(response)}`;
} catch (error) {
return `Error processing response: ${error.message}`;
}
}
// Show alert message
function showAlert(message, type = 'info') {
const alertDiv = document.createElement('div');
alertDiv.className = `fixed top-4 right-4 z-50 px-6 py-4 rounded-lg shadow-lg flex items-center ${
type === 'error' ? 'bg-red-100 text-red-800' :
type === 'success' ? 'bg-green-100 text-green-800' :
'bg-blue-100 text-blue-800'
}`;
const icon = type === 'error' ? 'exclamation-circle' :
type === 'success' ? 'check-circle' : 'info-circle';
alertDiv.innerHTML = `
<i class="fas fa-${icon} mr-3"></i>
<span>${message}</span>
<button class="ml-4 text-xl" onclick="this.parentElement.remove()">
<i class="fas fa-times"></i>
</button>
`;
document.body.appendChild(alertDiv);
setTimeout(() => {
alertDiv.remove();
}, 5000);
}
// Add glow effect to buttons on hover
document.querySelectorAll('button').forEach(button => {
if (!button.id.includes('remove') && button.id !== 'api-key-toggle') {
button.addEventListener('mouseenter', () => {
button.classList.add('glow');
});
button.addEventListener('mouseleave', () => {
button.classList.remove('glow');
});
}
});
// Add pulse animation to feature cards on hover
document.querySelectorAll('.card').forEach(card => {
card.addEventListener('mouseenter', () => {
card.classList.add('glow');
});
card.addEventListener('mouseleave', () => {
card.classList.remove('pulse');
});
});
</script>
<!-- <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=shukdevdatta123/openai-o4-mini-multi-modal-chat-app" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p> -->
</body>
</html>