shukdevdatta123 commited on
Commit
037f856
·
verified ·
1 Parent(s): 2e98654

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +5 -3
  2. index.html +592 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Openai O4 Mini Multi Modal Chat App
3
- emoji:
4
  colorFrom: red
5
  colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: openai-o4-mini-multi-modal-chat-app
3
+ emoji: 🐳
4
  colorFrom: red
5
  colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,592 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>OpenAI O4 Analysis App</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
10
+ <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
11
+ <style>
12
+ body {
13
+ font-family: 'Inter', sans-serif;
14
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
15
+ min-height: 100vh;
16
+ }
17
+
18
+ .tab-button {
19
+ transition: all 0.3s ease;
20
+ }
21
+
22
+ .tab-button.active {
23
+ transform: translateY(-2px);
24
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
25
+ }
26
+
27
+ .result-box {
28
+ transition: all 0.3s ease;
29
+ min-height: 200px;
30
+ }
31
+
32
+ .loading-dots {
33
+ display: inline-block;
34
+ }
35
+
36
+ .loading-dots span {
37
+ display: inline-block;
38
+ width: 8px;
39
+ height: 8px;
40
+ border-radius: 50%;
41
+ background-color: #4f46e5;
42
+ margin: 0 2px;
43
+ animation: bounce 1.4s infinite ease-in-out both;
44
+ }
45
+
46
+ .loading-dots span:nth-child(1) {
47
+ animation-delay: -0.32s;
48
+ }
49
+
50
+ .loading-dots span:nth-child(2) {
51
+ animation-delay: -0.16s;
52
+ }
53
+
54
+ @keyframes bounce {
55
+ 0%, 80%, 100% {
56
+ transform: scale(0);
57
+ } 40% {
58
+ transform: scale(1);
59
+ }
60
+ }
61
+
62
+ .file-input-label {
63
+ transition: all 0.3s ease;
64
+ }
65
+
66
+ .file-input-label:hover {
67
+ transform: translateY(-2px);
68
+ box-shadow: 0 4px 6px -1px rgba(79, 70, 229, 0.3), 0 2px 4px -1px rgba(79, 70, 229, 0.06);
69
+ }
70
+
71
+ .glow {
72
+ animation: glow 2s infinite alternate;
73
+ }
74
+
75
+ @keyframes glow {
76
+ from {
77
+ box-shadow: 0 0 5px rgba(79, 70, 229, 0.5);
78
+ }
79
+ to {
80
+ box-shadow: 0 0 20px rgba(79, 70, 229, 0.8);
81
+ }
82
+ }
83
+ </style>
84
+ </head>
85
+ <body class="py-8 px-4 sm:px-6 lg:px-8">
86
+ <div class="max-w-4xl mx-auto">
87
+ <!-- Header -->
88
+ <div class="text-center mb-10 animate__animated animate__fadeIn">
89
+ <h1 class="text-4xl font-bold text-indigo-600 mb-2">OpenAI O4 Mini Analysis</h1>
90
+ <p class="text-lg text-gray-600">Analyze PDFs and Images with AI-powered insights</p>
91
+ </div>
92
+
93
+ <!-- API Key Input -->
94
+ <div class="bg-white rounded-xl shadow-lg p-6 mb-8 animate__animated animate__fadeInUp">
95
+ <label for="api-key" class="block text-sm font-medium text-gray-700 mb-1">OpenAI API Key</label>
96
+ <div class="relative">
97
+ <input
98
+ type="password"
99
+ id="api-key"
100
+ placeholder="Enter your OpenAI API key here..."
101
+ class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
102
+ >
103
+ <button
104
+ onclick="toggleApiKeyVisibility()"
105
+ class="absolute right-3 top-3 text-gray-500 hover:text-indigo-600 focus:outline-none"
106
+ >
107
+ 👁️
108
+ </button>
109
+ </div>
110
+ <p class="mt-2 text-sm text-gray-500">Your API key is only used for requests and is not stored.</p>
111
+ </div>
112
+
113
+ <!-- Tabs -->
114
+ <div class="flex space-x-2 mb-6 animate__animated animate__fadeIn">
115
+ <button
116
+ id="pdf-tab"
117
+ onclick="switchTab('pdf')"
118
+ class="tab-button active px-6 py-3 rounded-lg font-medium bg-indigo-600 text-white"
119
+ >
120
+ PDF Analysis
121
+ </button>
122
+ <button
123
+ id="image-tab"
124
+ onclick="switchTab('image')"
125
+ class="tab-button px-6 py-3 rounded-lg font-medium bg-gray-200 text-gray-700 hover:bg-gray-300"
126
+ >
127
+ Image Analysis
128
+ </button>
129
+ </div>
130
+
131
+ <!-- PDF Analysis Tab -->
132
+ <div id="pdf-content" class="animate__animated animate__fadeIn">
133
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden">
134
+ <div class="p-6">
135
+ <h2 class="text-2xl font-semibold text-gray-800 mb-4">Upload a PDF for Analysis</h2>
136
+
137
+ <div class="mb-6">
138
+ <label class="block text-sm font-medium text-gray-700 mb-2">Upload PDF</label>
139
+ <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">
140
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-gray-400 mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
141
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
142
+ </svg>
143
+ <span class="text-sm font-medium text-gray-600">Click to upload PDF</span>
144
+ <span class="text-xs text-gray-500 mt-1">.pdf files only</span>
145
+ <input id="pdf-upload" type="file" accept=".pdf" class="hidden">
146
+ </label>
147
+ <p id="pdf-filename" class="mt-2 text-sm text-gray-500 hidden">Selected file: <span class="font-medium"></span></p>
148
+ </div>
149
+
150
+ <div class="mb-6">
151
+ <label for="pdf-prompt" class="block text-sm font-medium text-gray-700 mb-2">Prompt</label>
152
+ <textarea
153
+ id="pdf-prompt"
154
+ rows="3"
155
+ class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
156
+ placeholder="Enter your question about the PDF..."
157
+ >What is this PDF about?</textarea>
158
+ </div>
159
+
160
+ <div class="mb-6">
161
+ <label class="block text-sm font-medium text-gray-700 mb-2">Reasoning Effort</label>
162
+ <div class="flex space-x-4">
163
+ <label class="inline-flex items-center">
164
+ <input type="radio" name="pdf-effort" value="low" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
165
+ <span class="ml-2 text-gray-700">Low</span>
166
+ </label>
167
+ <label class="inline-flex items-center">
168
+ <input type="radio" name="pdf-effort" value="medium" checked class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
169
+ <span class="ml-2 text-gray-700">Medium</span>
170
+ </label>
171
+ <label class="inline-flex items-center">
172
+ <input type="radio" name="pdf-effort" value="high" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
173
+ <span class="ml-2 text-gray-700">High</span>
174
+ </label>
175
+ </div>
176
+ </div>
177
+
178
+ <button
179
+ id="analyze-pdf-btn"
180
+ onclick="analyzePDF()"
181
+ class="w-full py-3 px-6 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition duration-200 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
182
+ >
183
+ Analyze PDF
184
+ </button>
185
+ </div>
186
+
187
+ <div id="pdf-result" class="result-box border-t border-gray-200 p-6 bg-gray-50 hidden">
188
+ <h3 class="text-lg font-medium text-gray-800 mb-3">Analysis Result</h3>
189
+ <div id="pdf-result-content" class="min-h-40 p-4 bg-white rounded-lg border border-gray-200"></div>
190
+ </div>
191
+ </div>
192
+ </div>
193
+
194
+ <!-- Image Analysis Tab -->
195
+ <div id="image-content" class="hidden animate__animated animate__fadeIn">
196
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden">
197
+ <div class="p-6">
198
+ <h2 class="text-2xl font-semibold text-gray-800 mb-4">Upload an Image for Analysis</h2>
199
+
200
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
201
+ <div>
202
+ <label class="block text-sm font-medium text-gray-700 mb-2">Upload Image</label>
203
+ <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">
204
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-gray-400 mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
205
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
206
+ </svg>
207
+ <span class="text-sm font-medium text-gray-600">Click to upload image</span>
208
+ <span class="text-xs text-gray-500 mt-1">.jpg, .png, etc.</span>
209
+ <input id="image-upload" type="file" accept="image/*" class="hidden">
210
+ </label>
211
+ <p id="image-filename" class="mt-2 text-sm text-gray-500 hidden">Selected file: <span class="font-medium"></span></p>
212
+
213
+ <div class="mt-4">
214
+ <label for="image-url" class="block text-sm font-medium text-gray-700 mb-2">Or enter image URL</label>
215
+ <input
216
+ type="text"
217
+ id="image-url"
218
+ placeholder="https://example.com/image.jpg"
219
+ class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
220
+ >
221
+ </div>
222
+ </div>
223
+
224
+ <div>
225
+ <div class="mb-6">
226
+ <label for="image-prompt" class="block text-sm font-medium text-gray-700 mb-2">Prompt</label>
227
+ <textarea
228
+ id="image-prompt"
229
+ rows="3"
230
+ class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition duration-200"
231
+ placeholder="Enter your question about the image..."
232
+ >What is this image about?</textarea>
233
+ </div>
234
+
235
+ <div class="mb-6">
236
+ <label class="block text-sm font-medium text-gray-700 mb-2">Reasoning Effort</label>
237
+ <div class="flex space-x-4">
238
+ <label class="inline-flex items-center">
239
+ <input type="radio" name="image-effort" value="low" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
240
+ <span class="ml-2 text-gray-700">Low</span>
241
+ </label>
242
+ <label class="inline-flex items-center">
243
+ <input type="radio" name="image-effort" value="medium" checked class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
244
+ <span class="ml-2 text-gray-700">Medium</span>
245
+ </label>
246
+ <label class="inline-flex items-center">
247
+ <input type="radio" name="image-effort" value="high" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
248
+ <span class="ml-2 text-gray-700">High</span>
249
+ </label>
250
+ </div>
251
+ </div>
252
+ </div>
253
+ </div>
254
+
255
+ <button
256
+ id="analyze-image-btn"
257
+ onclick="analyzeImage()"
258
+ class="w-full py-3 px-6 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition duration-200 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
259
+ >
260
+ Analyze Image
261
+ </button>
262
+ </div>
263
+
264
+ <div id="image-result" class="result-box border-t border-gray-200 p-6 bg-gray-50 hidden">
265
+ <h3 class="text-lg font-medium text-gray-800 mb-3">Analysis Result</h3>
266
+ <div id="image-result-content" class="min-h-40 p-4 bg-white rounded-lg border border-gray-200"></div>
267
+ </div>
268
+ </div>
269
+ </div>
270
+
271
+ <!-- Footer -->
272
+ <div class="mt-12 text-center text-gray-500 text-sm animate__animated animate__fadeIn">
273
+ <p>OpenAI O4 Mini Analysis Application</p>
274
+ </div>
275
+ </div>
276
+
277
+ <script>
278
+ // Toggle API key visibility
279
+ function toggleApiKeyVisibility() {
280
+ const apiKeyInput = document.getElementById('api-key');
281
+ if (apiKeyInput.type === 'password') {
282
+ apiKeyInput.type = 'text';
283
+ } else {
284
+ apiKeyInput.type = 'password';
285
+ }
286
+ }
287
+
288
+ // Switch between tabs
289
+ function switchTab(tab) {
290
+ const pdfTab = document.getElementById('pdf-tab');
291
+ const imageTab = document.getElementById('image-tab');
292
+ const pdfContent = document.getElementById('pdf-content');
293
+ const imageContent = document.getElementById('image-content');
294
+
295
+ if (tab === 'pdf') {
296
+ pdfTab.classList.remove('bg-gray-200', 'text-gray-700');
297
+ pdfTab.classList.add('bg-indigo-600', 'text-white');
298
+ imageTab.classList.remove('bg-indigo-600', 'text-white');
299
+ imageTab.classList.add('bg-gray-200', 'text-gray-700');
300
+
301
+ pdfContent.classList.remove('hidden');
302
+ imageContent.classList.add('hidden');
303
+
304
+ // Add animation
305
+ pdfContent.classList.remove('animate__fadeIn');
306
+ void pdfContent.offsetWidth; // Trigger reflow
307
+ pdfContent.classList.add('animate__fadeIn');
308
+ } else {
309
+ imageTab.classList.remove('bg-gray-200', 'text-gray-700');
310
+ imageTab.classList.add('bg-indigo-600', 'text-white');
311
+ pdfTab.classList.remove('bg-indigo-600', 'text-white');
312
+ pdfTab.classList.add('bg-gray-200', 'text-gray-700');
313
+
314
+ imageContent.classList.remove('hidden');
315
+ pdfContent.classList.add('hidden');
316
+
317
+ // Add animation
318
+ imageContent.classList.remove('animate__fadeIn');
319
+ void imageContent.offsetWidth; // Trigger reflow
320
+ imageContent.classList.add('animate__fadeIn');
321
+ }
322
+ }
323
+
324
+ // Handle file upload display
325
+ document.getElementById('pdf-upload').addEventListener('change', function(e) {
326
+ const filenameDisplay = document.getElementById('pdf-filename');
327
+ if (this.files.length > 0) {
328
+ filenameDisplay.classList.remove('hidden');
329
+ filenameDisplay.querySelector('span').textContent = this.files[0].name;
330
+ } else {
331
+ filenameDisplay.classList.add('hidden');
332
+ }
333
+ });
334
+
335
+ document.getElementById('image-upload').addEventListener('change', function(e) {
336
+ const filenameDisplay = document.getElementById('image-filename');
337
+ if (this.files.length > 0) {
338
+ filenameDisplay.classList.remove('hidden');
339
+ filenameDisplay.querySelector('span').textContent = this.files[0].name;
340
+ } else {
341
+ filenameDisplay.classList.add('hidden');
342
+ }
343
+ });
344
+
345
+ // Show loading state
346
+ function showLoading(element) {
347
+ element.innerHTML = '<div class="loading-dots"><span></span><span></span><span></span></div>';
348
+ }
349
+
350
+ // Analyze PDF function
351
+ async function analyzePDF() {
352
+ const apiKey = document.getElementById('api-key').value;
353
+ const pdfFile = document.getElementById('pdf-upload').files[0];
354
+ const prompt = document.getElementById('pdf-prompt').value;
355
+ const effortLevel = document.querySelector('input[name="pdf-effort"]:checked').value;
356
+ const resultContent = document.getElementById('pdf-result-content');
357
+ const resultBox = document.getElementById('pdf-result');
358
+
359
+ if (!apiKey) {
360
+ alert('Please provide an OpenAI API key.');
361
+ return;
362
+ }
363
+
364
+ if (!pdfFile) {
365
+ alert('Please upload a PDF file.');
366
+ return;
367
+ }
368
+
369
+ // Show loading state
370
+ resultBox.classList.remove('hidden');
371
+ showLoading(resultContent);
372
+
373
+ try {
374
+ // Read the PDF file and convert to base64
375
+ const pdfBase64 = await new Promise((resolve, reject) => {
376
+ const reader = new FileReader();
377
+ reader.onload = () => {
378
+ const arrayBuffer = reader.result;
379
+ const bytes = new Uint8Array(arrayBuffer);
380
+ let binary = '';
381
+ for (let i = 0; i < bytes.byteLength; i++) {
382
+ binary += String.fromCharCode(bytes[i]);
383
+ }
384
+ const base64 = btoa(binary);
385
+ resolve(base64);
386
+ };
387
+ reader.onerror = reject;
388
+ reader.readAsArrayBuffer(pdfFile);
389
+ });
390
+
391
+ // Create the request payload
392
+ const payload = {
393
+ model: "o4-mini",
394
+ input: [
395
+ {
396
+ role: "user",
397
+ content: [
398
+ {
399
+ type: "input_text",
400
+ text: prompt
401
+ },
402
+ {
403
+ type: "input_file",
404
+ filename: pdfFile.name,
405
+ file_data: `data:application/pdf;base64,${pdfBase64}`
406
+ }
407
+ ]
408
+ }
409
+ ],
410
+ text: {
411
+ format: {
412
+ type: "text"
413
+ }
414
+ },
415
+ reasoning: {
416
+ effort: effortLevel
417
+ },
418
+ tools: [],
419
+ store: true
420
+ };
421
+
422
+ // Make the API request
423
+ const response = await axios.post('https://api.openai.com/v1/responses', payload, {
424
+ headers: {
425
+ 'Authorization': `Bearer ${apiKey}`,
426
+ 'Content-Type': 'application/json'
427
+ }
428
+ });
429
+
430
+ // Process the response
431
+ const result = extractTextFromResponse(response.data);
432
+ resultContent.innerHTML = `<div class="text-gray-700 whitespace-pre-wrap">${result}</div>`;
433
+
434
+ } catch (error) {
435
+ console.error('Error:', error);
436
+ let errorMessage = 'An error occurred while analyzing the PDF.';
437
+ if (error.response) {
438
+ errorMessage = `Error: ${error.response.data.error?.message || error.response.statusText}`;
439
+ } else if (error.message) {
440
+ errorMessage = `Error: ${error.message}`;
441
+ }
442
+ resultContent.innerHTML = `<div class="text-red-600">${errorMessage}</div>`;
443
+ }
444
+ }
445
+
446
+ // Analyze Image function
447
+ async function analyzeImage() {
448
+ const apiKey = document.getElementById('api-key').value;
449
+ const imageFile = document.getElementById('image-upload').files[0];
450
+ const imageUrl = document.getElementById('image-url').value;
451
+ const prompt = document.getElementById('image-prompt').value;
452
+ const effortLevel = document.querySelector('input[name="image-effort"]:checked').value;
453
+ const resultContent = document.getElementById('image-result-content');
454
+ const resultBox = document.getElementById('image-result');
455
+
456
+ if (!apiKey) {
457
+ alert('Please provide an OpenAI API key.');
458
+ return;
459
+ }
460
+
461
+ if (!imageFile && !imageUrl) {
462
+ alert('Please upload an image or provide an image URL.');
463
+ return;
464
+ }
465
+
466
+ if (!prompt) {
467
+ alert('Please provide a prompt for the image analysis.');
468
+ return;
469
+ }
470
+
471
+ // Show loading state
472
+ resultBox.classList.remove('hidden');
473
+ showLoading(resultContent);
474
+
475
+ try {
476
+ const content = [
477
+ {
478
+ type: "input_text",
479
+ text: prompt
480
+ }
481
+ ];
482
+
483
+ if (imageFile) {
484
+ // Read the image file and convert to base64
485
+ const imageBase64 = await new Promise((resolve, reject) => {
486
+ const reader = new FileReader();
487
+ reader.onload = () => {
488
+ const base64 = reader.result.split(',')[1];
489
+ resolve(base64);
490
+ };
491
+ reader.onerror = reject;
492
+ reader.readAsDataURL(imageFile);
493
+ });
494
+
495
+ content.unshift({
496
+ type: "input_image",
497
+ image_url: `data:image/png;base64,${imageBase64}`
498
+ });
499
+ } else if (imageUrl) {
500
+ content.unshift({
501
+ type: "input_image",
502
+ image_url: imageUrl
503
+ });
504
+ }
505
+
506
+ // Create the request payload
507
+ const payload = {
508
+ model: "o4-mini",
509
+ input: [
510
+ {
511
+ role: "user",
512
+ content: content
513
+ }
514
+ ],
515
+ text: {
516
+ format: {
517
+ type: "text"
518
+ }
519
+ },
520
+ reasoning: {
521
+ effort: effortLevel
522
+ },
523
+ tools: [],
524
+ store: true
525
+ };
526
+
527
+ // Make the API request
528
+ const response = await axios.post('https://api.openai.com/v1/responses', payload, {
529
+ headers: {
530
+ 'Authorization': `Bearer ${apiKey}`,
531
+ 'Content-Type': 'application/json'
532
+ }
533
+ });
534
+
535
+ // Process the response
536
+ const result = extractTextFromResponse(response.data);
537
+ resultContent.innerHTML = `<div class="text-gray-700 whitespace-pre-wrap">${result}</div>`;
538
+
539
+ } catch (error) {
540
+ console.error('Error:', error);
541
+ let errorMessage = 'An error occurred while analyzing the image.';
542
+ if (error.response) {
543
+ errorMessage = `Error: ${error.response.data.error?.message || error.response.statusText}`;
544
+ } else if (error.message) {
545
+ errorMessage = `Error: ${error.message}`;
546
+ }
547
+ resultContent.innerHTML = `<div class="text-red-600">${errorMessage}</div>`;
548
+ }
549
+ }
550
+
551
+ // Extract text from response
552
+ function extractTextFromResponse(response) {
553
+ try {
554
+ // First check if response has an output attribute
555
+ if (response.output) {
556
+ const output = response.output;
557
+
558
+ // Look for message items in the output list
559
+ for (const item of output) {
560
+ if (item.role === 'assistant') {
561
+ for (const contentItem of item.content) {
562
+ if (contentItem.type === 'output_text') {
563
+ return contentItem.text;
564
+ }
565
+ }
566
+ }
567
+ }
568
+
569
+ // If we couldn't find it in the expected structure, return an error
570
+ return `Couldn't extract text from response: ${JSON.stringify(response)}`;
571
+ }
572
+
573
+ return `Unexpected response structure: ${JSON.stringify(response)}`;
574
+ } catch (error) {
575
+ return `Error processing response: ${error.message}`;
576
+ }
577
+ }
578
+
579
+ // Add glow effect to buttons on hover
580
+ document.querySelectorAll('button').forEach(button => {
581
+ if (button.id !== 'api-key-toggle') {
582
+ button.addEventListener('mouseenter', () => {
583
+ button.classList.add('glow');
584
+ });
585
+ button.addEventListener('mouseleave', () => {
586
+ button.classList.remove('glow');
587
+ });
588
+ }
589
+ });
590
+ </script>
591
+ <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>
592
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ import gradio as gr import base64 import os from openai import OpenAI import tempfile def extract_text_from_response(response): """Extract text from OpenAI API response based on the actual structure""" try: # First check if response has an output attribute if hasattr(response, 'output'): output = response.output # Look for message items in the output list for item in output: if hasattr(item, 'role') and item.role == 'assistant': for content_item in item.content: if hasattr(content_item, 'type') and content_item.type == 'output_text': return content_item.text # If we couldn't find it in the expected structure, return an error return f"Couldn't extract text from response: {str(response)}" except Exception as e: return f"Error processing response: {str(e)}" def analyze_pdf(api_key, pdf_file, prompt, effort_level): """Analyze a PDF file using OpenAI API""" if not api_key: return "Please provide an OpenAI API key." if pdf_file is None: return "Please upload a PDF file." # Initialize OpenAI client with the provided API key client = OpenAI(api_key=api_key) # Read the PDF file and encode it in base64 with open(pdf_file.name, "rb") as file: pdf_bytes = file.read() pdf_base64 = base64.b64encode(pdf_bytes).decode("utf-8") try: # Create the request response = client.responses.create( model="o4-mini", input=[ { "role": "user", "content": [ { "type": "input_text", "text": prompt }, { "type": "input_file", "filename": os.path.basename(pdf_file.name), "file_data": f"data:application/pdf;base64,{pdf_base64}" } ] } ], text={ "format": { "type": "text" } }, reasoning={ "effort": effort_level }, tools=[], store=True ) return extract_text_from_response(response) except Exception as e: return f"Error: {str(e)}" def analyze_image(api_key, image, image_url, prompt, effort_level): """Analyze an image using OpenAI API""" if not api_key: return "Please provide an OpenAI API key." if image is None and not image_url: return "Please upload an image or provide an image URL." if not prompt: return "Please provide a prompt for the image analysis." # Initialize OpenAI client with the provided API key client = OpenAI(api_key=api_key) content = [] # Add text prompt content.append({ "type": "input_text", "text": prompt }) # Add image - either from uploaded file or URL try: if image is not None: # Convert image to base64 with open(image, "rb") as img_file: img_bytes = img_file.read() img_base64 = base64.b64encode(img_bytes).decode("utf-8") content.insert(0, { "type": "input_image", "image_url": f"data:image/png;base64,{img_base64}" }) elif image_url: content.insert(0, { "type": "input_image", "image_url": image_url }) # Create the request response = client.responses.create( model="o4-mini", input=[ { "role": "user", "content": content } ], text={ "format": { "type": "text" } }, reasoning={ "effort": effort_level }, tools=[], store=True ) return extract_text_from_response(response) except Exception as e: return f"Error: {str(e)}" # Create Gradio interface with gr.Blocks(title="OpenAI O4 Analysis App") as app: gr.Markdown("# OpenAI O4 Mini Analysis Application") # API Key input (used across both tabs) api_key_input = gr.Textbox( label="OpenAI API Key", placeholder="Enter your OpenAI API key here...", type="password" ) with gr.Tab("PDF Analysis"): gr.Markdown("## Upload a PDF file for analysis") with gr.Row(): pdf_input = gr.File(label="Upload PDF", file_types=[".pdf"]) pdf_prompt = gr.Textbox( label="Prompt", placeholder="Enter your question about the PDF...", value="What is this PDF about?" ) pdf_effort = gr.Radio( ["low", "medium", "high"], label="Reasoning Effort", value="medium" ) pdf_button = gr.Button("Analyze PDF") pdf_output = gr.Textbox(label="Analysis Result", lines=10) pdf_button.click( analyze_pdf, inputs=[api_key_input, pdf_input, pdf_prompt, pdf_effort], outputs=pdf_output ) with gr.Tab("Image Analysis"): gr.Markdown("## Upload an image or provide an image URL for analysis") with gr.Row(): with gr.Column(): img_input = gr.Image(label="Upload Image", type="filepath") img_url = gr.Textbox( label="Or enter image URL", placeholder="https://example.com/image.jpg" ) img_prompt = gr.Textbox( label="Prompt", placeholder="Enter your question about the image...", value="What is this image about?" ) img_effort = gr.Radio( ["low", "medium", "high"], label="Reasoning Effort", value="medium" ) img_output = gr.Textbox(label="Analysis Result", lines=10) img_button = gr.Button("Analyze Image") img_button.click( analyze_image, inputs=[api_key_input, img_input, img_url, img_prompt, img_effort], outputs=img_output ) gr.Markdown(""" ### Note: - Your OpenAI API key is required to use this application - The API key is only used for requests and is not stored """) # Launch the app if __name__ == "__main__": app.launch() (please convert this code to a very very awesome looking website with amazing animations... make sure the website works exactly in the same way the above project code works)