avakanski commited on
Commit
7e2bf7c
·
verified ·
1 Parent(s): 8708015

Upload index.html

Browse files
Files changed (1) hide show
  1. static/index.html +383 -67
static/index.html CHANGED
@@ -1,120 +1,426 @@
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>US Army RAG System</title>
7
- <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600&display=swap" rel="stylesheet">
 
 
 
 
8
  <style>
9
- /* Previous styles remain... adding new ones for images */
10
- .results-section {
11
- margin-bottom: 2.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  .images-grid {
15
  display: grid;
 
16
  gap: 1.5rem;
17
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
18
- margin-top: 1.5rem;
19
  }
20
 
21
  .image-card {
22
- background: rgba(15, 23, 42, 0.5);
23
- border-radius: 1rem;
24
  overflow: hidden;
25
- border: 1px solid rgba(255, 255, 255, 0.1);
26
- transition: transform 0.2s;
 
 
27
  }
28
 
29
  .image-card:hover {
30
- transform: scale(1.02);
31
- z-index: 10;
 
 
 
 
 
 
 
32
  }
33
 
34
  .image-card img {
35
  width: 100%;
36
- height: 200px;
37
  object-fit: cover;
38
- display: block;
39
- }
40
-
41
- .image-card.full-view {
42
- position: fixed;
43
- top: 50%;
44
- left: 50%;
45
- transform: translate(-50%, -50%);
46
- width: 80vw;
47
- height: 80vh;
48
- z-index: 1000;
49
- background: black;
50
  }
51
-
52
- .image-card.full-view img {
53
- object-fit: contain;
54
- height: 100%;
55
  }
56
 
57
  .image-meta {
58
  padding: 1rem;
59
- font-size: 0.85rem;
60
- color: #cbd5e1;
61
  }
62
 
63
  .image-filename {
64
  font-weight: 600;
65
- color: #fff;
66
- margin-bottom: 0.25rem;
67
  white-space: nowrap;
68
  overflow: hidden;
69
  text-overflow: ellipsis;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
  </style>
72
  </head>
 
73
  <body>
74
  <div class="container">
75
  <header>
76
- <h1>Medical Research RAG</h1>
77
- <p class="subtitle">Multimodal AI (Text + Images) Analysis</p>
78
  </header>
79
 
80
- <div class="search-box">
81
  <div class="input-group">
82
- <input type="text" id="questionInput" placeholder="Ask a question (e.g., 'Show me images of...')" autocomplete="off">
 
83
  <button id="searchBtn" onclick="askQuestion()">
84
- Ask AI
 
 
 
 
85
  </button>
86
  </div>
87
  </div>
88
 
89
  <div id="loading">
90
  <div class="spinner"></div>
91
- <p>Analyzing medical papers & images...</p>
92
  </div>
93
 
94
  <div id="results">
95
  <!-- ANSWER SECTION -->
 
 
 
 
 
 
 
 
 
96
  <div class="answer-card">
97
- <div class="section-title">
98
- <svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>
99
- AI Consolidated Answer
100
- </div>
101
  <div id="answerText" class="answer-text"></div>
102
  </div>
103
 
104
  <!-- IMAGES SECTION -->
105
- <div id="imagesSection" class="results-section" style="display: none;">
106
- <div class="section-title">
107
- <svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
108
- Relevant Images
 
 
 
 
109
  </div>
110
  <div id="imagesGrid" class="images-grid"></div>
111
  </div>
112
 
113
  <!-- TEXT SOURCES SECTION -->
114
- <div id="textsSection" class="results-section" style="display: none;">
115
- <div class="section-title">
116
- <svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>
117
- Reference Texts
 
 
 
 
118
  </div>
119
  <div id="textsGrid" class="sources-grid"></div>
120
  </div>
@@ -127,15 +433,15 @@
127
  const loading = document.getElementById('loading');
128
  const results = document.getElementById('results');
129
  const answerText = document.getElementById('answerText');
130
-
131
  const imagesSection = document.getElementById('imagesSection');
132
  const imagesGrid = document.getElementById('imagesGrid');
133
-
134
  const textsSection = document.getElementById('textsSection');
135
  const textsGrid = document.getElementById('textsGrid');
136
 
137
  // Allow Enter key to submit
138
- input.addEventListener('keypress', function(e) {
139
  if (e.key === 'Enter') {
140
  askQuestion();
141
  }
@@ -147,10 +453,11 @@
147
 
148
  // UI State updates
149
  searchBtn.disabled = true;
 
150
  input.disabled = true;
151
  results.style.display = 'none';
152
  loading.style.display = 'block';
153
-
154
  // Reset sections
155
  imagesSection.style.display = 'none';
156
  textsSection.style.display = 'none';
@@ -167,24 +474,28 @@
167
  if (!response.ok) throw new Error('Failed to get response');
168
 
169
  const data = await response.json();
170
-
171
- // 1. Display Answer
172
- answerText.textContent = data.answer;
173
-
 
 
174
  // 2. Display Images
175
  if (data.images && data.images.length > 0) {
176
  imagesSection.style.display = 'block';
177
  data.images.forEach(img => {
178
  const div = document.createElement('div');
179
  div.className = 'image-card';
180
- // Add click to view full size could be implemented here
181
  div.innerHTML = `
182
  <a href="${img.path}" target="_blank">
183
  <img src="${img.path}" alt="${img.filename}" loading="lazy">
184
  </a>
185
  <div class="image-meta">
186
- <div class="image-filename">${img.filename}</div>
187
- <div>Page ${img.page || '?'} • Score: ${img.score?.toFixed(2)}</div>
 
 
 
188
  </div>
189
  `;
190
  imagesGrid.appendChild(div);
@@ -199,10 +510,10 @@
199
  div.className = 'source-card';
200
  div.innerHTML = `
201
  <div class="source-title">${txt.file || 'Document'}</div>
 
202
  <div class="source-meta">
203
- Page ${txt.page || 'N/A'} • Score: ${txt.score?.toFixed(2)}
204
  </div>
205
- <div class="source-excerpt">"...${txt.text}..."</div>
206
  `;
207
  textsGrid.appendChild(div);
208
  });
@@ -211,15 +522,20 @@
211
  results.style.display = 'block';
212
 
213
  } catch (error) {
214
- alert('Error querying system. Check console/logs.');
215
  console.error(error);
216
  } finally {
217
  loading.style.display = 'none';
218
  searchBtn.disabled = false;
 
 
 
 
219
  input.disabled = false;
220
  input.focus();
221
  }
222
  }
223
  </script>
224
  </body>
225
- </html>
 
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
+
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Multimodal RAG • AI Research Assistant</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap"
12
+ rel="stylesheet">
13
  <style>
14
+ :root {
15
+ --primary: #3b82f6;
16
+ --primary-glow: rgba(59, 130, 246, 0.5);
17
+ --bg-dark: #0f172a;
18
+ --bg-card: #1e293b;
19
+ --text-main: #f8fafc;
20
+ --text-muted: #94a3b8;
21
+ --border-color: #334155;
22
+ --accent-gradient: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
23
+ }
24
+
25
+ * {
26
+ box-sizing: border-box;
27
+ margin: 0;
28
+ padding: 0;
29
+ }
30
+
31
+ body {
32
+ font-family: 'Outfit', sans-serif;
33
+ background-color: var(--bg-dark);
34
+ color: var(--text-main);
35
+ min-height: 100vh;
36
+ line-height: 1.6;
37
+ background-image:
38
+ radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.1) 0%, transparent 20%),
39
+ radial-gradient(circle at 90% 80%, rgba(139, 92, 246, 0.1) 0%, transparent 20%);
40
+ }
41
+
42
+ .container {
43
+ max-width: 1200px;
44
+ margin: 0 auto;
45
+ padding: 2rem;
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: 2rem;
49
+ }
50
+
51
+ header {
52
+ text-align: center;
53
+ padding: 4rem 0 2rem;
54
+ animation: fadeInDown 0.8s ease-out;
55
+ }
56
+
57
+ h1 {
58
+ font-family: 'Space Grotesk', sans-serif;
59
+ font-size: 3.5rem;
60
+ font-weight: 700;
61
+ background: var(--accent-gradient);
62
+ -webkit-background-clip: text;
63
+ -webkit-text-fill-color: transparent;
64
+ margin-bottom: 0.5rem;
65
+ letter-spacing: -0.02em;
66
+ }
67
+
68
+ .subtitle {
69
+ color: var(--text-muted);
70
+ font-size: 1.25rem;
71
+ font-weight: 300;
72
+ }
73
+
74
+ /* Search Section */
75
+ .search-container {
76
+ max-width: 800px;
77
+ margin: 0 auto;
78
+ width: 100%;
79
+ position: relative;
80
+ z-index: 10;
81
+ }
82
+
83
+ .input-group {
84
+ position: relative;
85
+ display: flex;
86
+ gap: 1rem;
87
+ background: rgba(30, 41, 59, 0.7);
88
+ padding: 0.5rem;
89
+ border-radius: 1rem;
90
+ border: 1px solid var(--border-color);
91
+ backdrop-filter: blur(12px);
92
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
93
+ transition: all 0.3s ease;
94
+ }
95
+
96
+ .input-group:focus-within {
97
+ border-color: var(--primary);
98
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
99
+ transform: translateY(-2px);
100
+ }
101
+
102
+ input[type="text"] {
103
+ flex: 1;
104
+ background: transparent;
105
+ border: none;
106
+ padding: 1rem 1.5rem;
107
+ font-size: 1.1rem;
108
+ color: white;
109
+ font-family: 'Outfit', sans-serif;
110
+ width: 100%;
111
+ }
112
+
113
+ input[type="text"]:focus {
114
+ outline: none;
115
+ }
116
+
117
+ input[type="text"]::placeholder {
118
+ color: #64748b;
119
+ }
120
+
121
+ button#searchBtn {
122
+ background: var(--accent-gradient);
123
+ color: white;
124
+ border: none;
125
+ padding: 0 2rem;
126
+ border-radius: 0.75rem;
127
+ font-weight: 600;
128
+ font-size: 1rem;
129
+ cursor: pointer;
130
+ transition: opacity 0.2s;
131
+ display: flex;
132
+ align-items: center;
133
+ gap: 0.5rem;
134
+ }
135
+
136
+ button#searchBtn:hover {
137
+ opacity: 0.9;
138
+ }
139
+
140
+ button#searchBtn:disabled {
141
+ opacity: 0.5;
142
+ cursor: not-allowed;
143
+ }
144
+
145
+ /* Loading State */
146
+ #loading {
147
+ display: none;
148
+ text-align: center;
149
+ padding: 2rem;
150
+ }
151
+
152
+ .spinner {
153
+ width: 40px;
154
+ height: 40px;
155
+ border: 3px solid rgba(59, 130, 246, 0.3);
156
+ border-radius: 50%;
157
+ border-top-color: var(--primary);
158
+ animation: spin 1s linear infinite;
159
+ margin: 0 auto 1rem;
160
+ }
161
+
162
+ @keyframes spin {
163
+ to {
164
+ transform: rotate(360deg);
165
+ }
166
+ }
167
+
168
+ /* Results Area */
169
+ #results {
170
+ display: none;
171
+ /* Hidden by default */
172
+ max-width: 1000px;
173
+ margin: 0 auto;
174
+ width: 100%;
175
+ animation: fadeInUp 0.5s ease-out;
176
+ }
177
+
178
+ .section-title {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 0.75rem;
182
+ color: var(--text-muted);
183
+ font-size: 0.9rem;
184
+ text-transform: uppercase;
185
+ letter-spacing: 0.05em;
186
+ font-weight: 600;
187
+ margin-bottom: 1rem;
188
+ margin-top: 2rem;
189
+ border-bottom: 1px solid var(--border-color);
190
+ padding-bottom: 0.5rem;
191
  }
192
 
193
+ .answer-card {
194
+ background: var(--bg-card);
195
+ border: 1px solid var(--border-color);
196
+ padding: 2rem;
197
+ border-radius: 1rem;
198
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
199
+ position: relative;
200
+ overflow: hidden;
201
+ }
202
+
203
+ .answer-text {
204
+ font-size: 1.1rem;
205
+ color: #e2e8f0;
206
+ white-space: pre-wrap;
207
+ line-height: 1.8;
208
+ }
209
+
210
+ /* Image Grids */
211
  .images-grid {
212
  display: grid;
213
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
214
  gap: 1.5rem;
 
 
215
  }
216
 
217
  .image-card {
218
+ background: var(--bg-card);
219
+ border-radius: 0.75rem;
220
  overflow: hidden;
221
+ border: 1px solid var(--border-color);
222
+ transition: all 0.3s ease;
223
+ position: relative;
224
+ group: card;
225
  }
226
 
227
  .image-card:hover {
228
+ transform: translateY(-5px);
229
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
230
+ border-color: var(--primary);
231
+ }
232
+
233
+ .image-card a {
234
+ display: block;
235
+ overflow: hidden;
236
+ height: 180px;
237
  }
238
 
239
  .image-card img {
240
  width: 100%;
241
+ height: 100%;
242
  object-fit: cover;
243
+ transition: transform 0.5s ease;
 
 
 
 
 
 
 
 
 
 
 
244
  }
245
+
246
+ .image-card:hover img {
247
+ transform: scale(1.1);
 
248
  }
249
 
250
  .image-meta {
251
  padding: 1rem;
252
+ border-top: 1px solid var(--border-color);
 
253
  }
254
 
255
  .image-filename {
256
  font-weight: 600;
257
+ color: #f1f5f9;
258
+ font-size: 0.95rem;
259
  white-space: nowrap;
260
  overflow: hidden;
261
  text-overflow: ellipsis;
262
+ margin-bottom: 0.25rem;
263
+ }
264
+
265
+ .image-stats {
266
+ display: flex;
267
+ justify-content: space-between;
268
+ font-size: 0.8rem;
269
+ color: var(--text-muted);
270
+ }
271
+
272
+ /* Text Sources */
273
+ .sources-grid {
274
+ display: grid;
275
+ gap: 1rem;
276
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
277
+ }
278
+
279
+ .source-card {
280
+ background: rgba(30, 41, 59, 0.4);
281
+ border: 1px solid var(--border-color);
282
+ border-radius: 0.75rem;
283
+ padding: 1.25rem;
284
+ transition: background 0.2s;
285
+ }
286
+
287
+ .source-card:hover {
288
+ background: rgba(30, 41, 59, 0.8);
289
+ border-color: #475569;
290
+ }
291
+
292
+ .source-title {
293
+ font-weight: 600;
294
+ color: var(--primary);
295
+ margin-bottom: 0.5rem;
296
+ font-size: 0.95rem;
297
+ }
298
+
299
+ .source-excerpt {
300
+ font-style: italic;
301
+ color: #cbd5e1;
302
+ font-size: 0.9rem;
303
+ background: rgba(0, 0, 0, 0.2);
304
+ padding: 0.75rem;
305
+ border-radius: 0.5rem;
306
+ border-left: 3px solid var(--primary);
307
+ }
308
+
309
+ .source-meta {
310
+ margin-top: 0.75rem;
311
+ font-size: 0.8rem;
312
+ color: var(--text-muted);
313
+ text-align: right;
314
+ }
315
+
316
+ /* Animations */
317
+ @keyframes fadeInDown {
318
+ from {
319
+ opacity: 0;
320
+ transform: translateY(-20px);
321
+ }
322
+
323
+ to {
324
+ opacity: 1;
325
+ transform: translateY(0);
326
+ }
327
+ }
328
+
329
+ @keyframes fadeInUp {
330
+ from {
331
+ opacity: 0;
332
+ transform: translateY(20px);
333
+ }
334
+
335
+ to {
336
+ opacity: 1;
337
+ transform: translateY(0);
338
+ }
339
+ }
340
+
341
+ /* Scrollbar */
342
+ ::-webkit-scrollbar {
343
+ width: 8px;
344
+ }
345
+
346
+ ::-webkit-scrollbar-track {
347
+ background: var(--bg-dark);
348
+ }
349
+
350
+ ::-webkit-scrollbar-thumb {
351
+ background: var(--border-color);
352
+ border-radius: 4px;
353
+ }
354
+
355
+ ::-webkit-scrollbar-thumb:hover {
356
+ background: #475569;
357
  }
358
  </style>
359
  </head>
360
+
361
  <body>
362
  <div class="container">
363
  <header>
364
+ <h1>Multimodal RAG</h1>
365
+ <p class="subtitle">Advanced Medical Research Analysis System</p>
366
  </header>
367
 
368
+ <div class="search-container">
369
  <div class="input-group">
370
+ <input type="text" id="questionInput" placeholder="Ask a complex question about medical papers..."
371
+ autocomplete="off">
372
  <button id="searchBtn" onclick="askQuestion()">
373
+ <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
374
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
375
+ d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
376
+ </svg>
377
+ Analyze
378
  </button>
379
  </div>
380
  </div>
381
 
382
  <div id="loading">
383
  <div class="spinner"></div>
384
+ <p style="color: var(--text-muted); font-size: 0.9rem;">Processing multimodal embeddings...</p>
385
  </div>
386
 
387
  <div id="results">
388
  <!-- ANSWER SECTION -->
389
+ <div class="section-title">
390
+ <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
391
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
392
+ d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z">
393
+ </path>
394
+ </svg>
395
+ Consolidated Intelligence
396
+ </div>
397
+
398
  <div class="answer-card">
 
 
 
 
399
  <div id="answerText" class="answer-text"></div>
400
  </div>
401
 
402
  <!-- IMAGES SECTION -->
403
+ <div id="imagesSection" style="display: none;">
404
+ <div class="section-title" style="margin-top: 3rem;">
405
+ <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
406
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
407
+ 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">
408
+ </path>
409
+ </svg>
410
+ Relevant Visual Data
411
  </div>
412
  <div id="imagesGrid" class="images-grid"></div>
413
  </div>
414
 
415
  <!-- TEXT SOURCES SECTION -->
416
+ <div id="textsSection" style="display: none;">
417
+ <div class="section-title" style="margin-top: 3rem;">
418
+ <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
419
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
420
+ d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253">
421
+ </path>
422
+ </svg>
423
+ Source Documents
424
  </div>
425
  <div id="textsGrid" class="sources-grid"></div>
426
  </div>
 
433
  const loading = document.getElementById('loading');
434
  const results = document.getElementById('results');
435
  const answerText = document.getElementById('answerText');
436
+
437
  const imagesSection = document.getElementById('imagesSection');
438
  const imagesGrid = document.getElementById('imagesGrid');
439
+
440
  const textsSection = document.getElementById('textsSection');
441
  const textsGrid = document.getElementById('textsGrid');
442
 
443
  // Allow Enter key to submit
444
+ input.addEventListener('keypress', function (e) {
445
  if (e.key === 'Enter') {
446
  askQuestion();
447
  }
 
453
 
454
  // UI State updates
455
  searchBtn.disabled = true;
456
+ searchBtn.innerHTML = '<span style="font-size: 0.9em">Processing...</span>';
457
  input.disabled = true;
458
  results.style.display = 'none';
459
  loading.style.display = 'block';
460
+
461
  // Reset sections
462
  imagesSection.style.display = 'none';
463
  textsSection.style.display = 'none';
 
474
  if (!response.ok) throw new Error('Failed to get response');
475
 
476
  const data = await response.json();
477
+
478
+ // 1. Display Answer with simple markdown replacement for bold
479
+ // Very basic MD parser for bold text if any
480
+ let formattedAnswer = data.answer.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
481
+ answerText.innerHTML = formattedAnswer;
482
+
483
  // 2. Display Images
484
  if (data.images && data.images.length > 0) {
485
  imagesSection.style.display = 'block';
486
  data.images.forEach(img => {
487
  const div = document.createElement('div');
488
  div.className = 'image-card';
 
489
  div.innerHTML = `
490
  <a href="${img.path}" target="_blank">
491
  <img src="${img.path}" alt="${img.filename}" loading="lazy">
492
  </a>
493
  <div class="image-meta">
494
+ <div class="image-filename" title="${img.filename}">${img.filename}</div>
495
+ <div class="image-stats">
496
+ <span>Page ${img.page || '?'}</span>
497
+ <span>${(img.score * 100).toFixed(0)}% Match</span>
498
+ </div>
499
  </div>
500
  `;
501
  imagesGrid.appendChild(div);
 
510
  div.className = 'source-card';
511
  div.innerHTML = `
512
  <div class="source-title">${txt.file || 'Document'}</div>
513
+ <div class="source-excerpt">"${txt.text}..."</div>
514
  <div class="source-meta">
515
+ Page ${txt.page || 'N/A'} • Similarity: ${(txt.score * 100).toFixed(0)}%
516
  </div>
 
517
  `;
518
  textsGrid.appendChild(div);
519
  });
 
522
  results.style.display = 'block';
523
 
524
  } catch (error) {
525
+ alert('Error querying system. Please try again.');
526
  console.error(error);
527
  } finally {
528
  loading.style.display = 'none';
529
  searchBtn.disabled = false;
530
+ searchBtn.innerHTML = `
531
+ <svg width="20" height="20" 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>
532
+ Analyze
533
+ `;
534
  input.disabled = false;
535
  input.focus();
536
  }
537
  }
538
  </script>
539
  </body>
540
+
541
+ </html>