awacke1 commited on
Commit
182d632
Β·
verified Β·
1 Parent(s): 5fe90b3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -120
app.py CHANGED
@@ -99,34 +99,25 @@ def markdown_to_story(markdown_text: str, font_name: str, emoji_font: str):
99
  style_h1 = ParagraphStyle('h1', fontName=bold_font, spaceBefore=12, fontSize=24, textColor=colors.HexColor("#1E3A8A"))
100
  style_h2 = ParagraphStyle('h2', fontName=bold_font, spaceBefore=10, fontSize=18, textColor=colors.HexColor("#374151"))
101
  style_h3 = ParagraphStyle('h3', fontName=bold_font, spaceBefore=8, fontSize=14, textColor=colors.HexColor("#4B5563"))
102
- style_code = ParagraphStyle('Code', fontName='Courier', backColor=colors.whitesmoke, textColor=colors.darkred, borderWidth=1, borderColor=colors.lightgrey, padding=8)
103
-
104
  story, first_heading = [], True
105
  for line in markdown_text.split('\n'):
106
  stripped_line = line.strip()
107
  if not stripped_line:
108
  story.append(Spacer(1, 0.1 * inch)); continue
109
 
110
- # Determine the structural element and its style
111
  content, style, extra_args = stripped_line, style_normal, {}
112
  if stripped_line.startswith("# "):
113
  if not first_heading: story.append(PageBreak())
114
  content, style, first_heading = stripped_line.lstrip('# '), style_h1, False
115
- elif stripped_line.startswith("## "):
116
- content, style = stripped_line.lstrip('## '), style_h2
117
- elif stripped_line.startswith("### "):
118
- content, style = stripped_line.lstrip('### '), style_h3
119
- elif stripped_line.startswith(("- ", "* ")):
120
- content, extra_args = stripped_line[2:], {'bulletText': 'β€’'}
121
 
122
- # Now, format the content string correctly for ReportLab
123
- # Apply bold/italic first
124
  formatted_content = re.sub(r'_(.*?)_', r'<i>\1</i>', re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', content))
125
- # Then, apply the emoji font tags. This order is crucial.
126
  final_content = apply_emoji_font(formatted_content, emoji_font)
127
 
128
  story.append(Paragraph(final_content, style, **extra_args))
129
-
130
  return story
131
 
132
 
@@ -193,13 +184,22 @@ def build_file_explorer_html(generated_files, pdf_files_for_gallery):
193
 
194
  file_explorer_html = ""
195
  file_icons = {".pdf": "πŸ“„", ".docx": "πŸ“", ".xlsx": "πŸ“Š"}
 
 
 
 
 
 
196
  for file_path in generated_files:
197
  icon = file_icons.get(file_path.suffix, 'πŸ“Ž')
198
  file_explorer_html += f"""
199
- <a href="/file={file_path}" class="file-link" download="{file_path.name}">
200
- <span class="file-icon">{icon}</span>
201
- <span class="file-name">{file_path.name}</span>
202
- </a>
 
 
 
203
  """
204
 
205
  gallery_items = []
@@ -208,103 +208,79 @@ def build_file_explorer_html(generated_files, pdf_files_for_gallery):
208
  if preview_path:
209
  with open(preview_path, "rb") as f:
210
  img_base64 = base64.b64encode(f.read()).decode("utf-8")
211
- gallery_items.append({
212
- "preview_src": f"data:image/png;base64,{img_base64}",
213
- "filename": pdf_path.name
214
- })
215
 
216
  gallery_html = ""
217
  if gallery_items:
218
- thumbs_html = ""
219
- for item in gallery_items:
220
- thumbs_html += f'<img src="{item["preview_src"]}" class="thumbnail" onclick="selectThumbnail(this, \'{item["preview_src"]}\', \'{item["filename"]}\')">'
221
-
222
  gallery_html = f"""
223
  <div class="gallery-container">
224
- <div class="main-view">
225
- <img id="main-image" src="{gallery_items[0]['preview_src']}" class="main-image">
226
- <p id="main-filename">{gallery_items[0]['filename']}</p>
227
- </div>
228
  <div class="thumbnail-strip">{thumbs_html}</div>
229
  </div>
 
230
  """
231
 
232
  html = f"""
233
  <style>
234
  .tabs {{ display: flex; border-bottom: 2px solid #ccc; }}
235
- .tab-button {{ padding: 10px 15px; cursor: pointer; background: #f1f1f1; border: none; border-bottom: 2px solid transparent; outline: none; }}
236
- .tab-button.active {{ background: #fff; border-top: 2px solid #007bff; border-left: 2px solid #ccc; border-right: 2px solid #ccc; border-bottom: 2px solid #fff; }}
237
  .tab-content {{ display: none; padding: 15px; border: 1px solid #ccc; border-top: none; }}
238
  .tab-content.active {{ display: block; }}
239
- .file-explorer {{ display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }}
240
- .file-link {{ display: flex; align-items: center; padding: 10px; background: #f9f9f9; border-radius: 5px; text-decoration: none; color: #333; }}
241
- .file-link:hover {{ background: #e9e9e9; }}
242
- .file-icon {{ font-size: 2.5em; margin-right: 10px; }}
 
 
 
243
  .gallery-container {{ display: flex; height: 500px; }}
244
- .main-view {{ flex: 3; padding: 10px; display: flex; flex-direction: column; align-items: center; justify-content: center; }}
245
- .main-image {{ max-width: 100%; max-height: 90%; }}
246
- .thumbnail-strip {{ flex: 1; overflow-y: auto; padding: 5px; }}
247
- .thumbnail {{ width: 100%; margin-bottom: 5px; cursor: pointer; border: 2px solid transparent; }}
248
- .thumbnail.active {{ border-color: #007bff; }}
249
  </style>
250
  <div class="tabs">
251
- <button class="tab-button active" onclick="openTab(event, 'explorer')">πŸ—‚οΈ File Explorer</button>
252
- {'<button class="tab-button" onclick="openTab(event, \'gallery\')">πŸ–ΌοΈ PDF Gallery</button>' if gallery_items else ''}
253
- </div>
254
- <div id="explorer" class="tab-content active">
255
- <div class="file-explorer">{file_explorer_html}</div>
256
- </div>
257
- <div id="gallery" class="tab-content">
258
- {gallery_html}
259
  </div>
 
 
260
  <script>
261
  function openTab(evt, tabName) {{
262
- var i, tabcontent, tablinks;
263
- tabcontent = document.getElementsByClassName("tab-content");
264
- for (i = 0; i < tabcontent.length; i++) {{ tabcontent[i].style.display = "none"; }}
265
- tablinks = document.getElementsByClassName("tab-button");
266
- for (i = 0; i < tablinks.length; i++) {{ tablinks[i].className = tablinks[i].className.replace(" active", ""); }}
267
- document.getElementById(tabName).style.display = "block";
268
- evt.currentTarget.className += " active";
269
  }}
270
-
271
- const mainImage = document.getElementById('main-image');
272
- const mainFilename = document.getElementById('main-filename');
273
- const thumbnails = document.querySelectorAll('.thumbnail');
274
  if (thumbnails.length > 0) thumbnails[0].classList.add('active');
275
-
276
- function selectThumbnail(selectedThumb, imgSrc, filename) {{
277
- mainImage.src = imgSrc; mainFilename.textContent = filename;
278
- thumbnails.forEach(t => t.classList.remove('active'));
279
- selectedThumb.classList.add('active');
280
  }};
281
  </script>
282
  """
283
  return html
284
 
285
- def generate_outputs_api(omni_files, omni_prompt, output_formats, layouts, fonts, num_columns, page_w_mult, page_h_mult, progress=gr.Progress(track_tqdm=True)):
286
- """πŸš€ The main entry point that orchestrates the entire multi-modal generation process."""
287
- if not omni_prompt and not omni_files: raise gr.Error("Please provide a prompt or upload at least one file.")
288
  if not output_formats: raise gr.Error("Please select at least one output format.")
289
 
290
  shutil.rmtree(OUTPUT_DIR, ignore_errors=True); shutil.rmtree(PREVIEW_DIR, ignore_errors=True)
291
  OUTPUT_DIR.mkdir(); PREVIEW_DIR.mkdir()
292
 
293
  md_content = ""
294
- if omni_files:
295
- temp_paths = []
296
- for f in omni_files:
297
- temp_path = UPLOAD_DIR / Path(f.name).name
298
- shutil.copyfile(f.name, temp_path)
299
- temp_paths.append(temp_path)
300
-
301
- file_path = temp_paths[0]
302
- file_ext = file_path.suffix.lower()
303
-
304
- if file_ext == '.md': md_content = "\n\n".join([p.read_text(encoding='utf-8') for p in temp_paths if p.suffix.lower() == '.md'])
305
- elif file_ext == '.pdf': md_content = process_pdf_input(file_path, omni_prompt or "Extract text", progress)
306
- elif file_ext in ['.png', '.jpg', '.jpeg']: md_content = process_image_input(file_path, omni_prompt or "Describe image")
307
- elif file_ext in ['.wav', '.mp3']: md_content = process_audio_input(file_path, omni_prompt or "Summarize transcription")
308
  elif omni_prompt:
309
  md_content = process_text_input(omni_prompt)
310
 
@@ -319,8 +295,7 @@ def generate_outputs_api(omni_files, omni_prompt, output_formats, layouts, fonts
319
  pagesize = LAYOUTS[layout_name]["size"]
320
  final_pagesize = (pagesize[0] * page_w_mult, pagesize[1] * page_h_mult)
321
  pdf_buffer = create_pdf(md_content, font_name, EMOJI_FONT_NAME, final_pagesize, num_columns)
322
- filename = f"Document_{time_str}.pdf"
323
- output_path = OUTPUT_DIR / filename
324
  with open(output_path, "wb") as f: f.write(pdf_buffer.getvalue())
325
  generated_files.append(output_path); pdf_files_for_gallery.append(output_path)
326
  elif format_choice == "DOCX":
@@ -336,39 +311,17 @@ def generate_outputs_api(omni_files, omni_prompt, output_formats, layouts, fonts
336
 
337
  # --- 🎨 Gradio UI Definition ---
338
  AVAILABLE_FONTS, EMOJI_FONT_NAME = register_local_fonts()
339
- SAMPLE_MARKDOWN = """# Deities Guide: Mythology and Moral Lessons
340
-
341
- 1. πŸ“œ **Introduction**
342
- - **Purpose**: Explore deities, spirits, saints, and beings with their epic stories and morals!
343
- - **Usage**: A guide for learning and storytelling across traditions. ️
344
- - **Themes**: Justice βš–οΈ, faith πŸ™, hubris πŸ›οΈ, redemption ✨, cosmic order 🌌.
345
-
346
- # βš”οΈ Arthurian Legends
347
- - **Merlin, Morgan le Fay, Arthur**: Mentor πŸ§™, rival πŸ§™β€β™€οΈ, son πŸ‘‘.
348
- - **Relation**: Family tests loyalty 🀝.
349
- - **Lesson**: Honor πŸŽ–οΈ vs. betrayal πŸ—‘οΈ.
350
- """
351
 
352
  with gr.Blocks(theme=gr.themes.Soft(), title="Omni-Model Document Generator") as demo:
353
  gr.Markdown("# 🧠 Omni-Model Document Generator")
354
- gr.Markdown("Provide a prompt, or upload a file (MD, PDF, Image, Audio). A virtual AI will process it, and you can generate documents from the result.")
355
 
356
  with gr.Row():
357
  with gr.Column(scale=1):
358
- with gr.Tabs():
359
- with gr.TabItem("πŸ’¬ Text"):
360
- text_prompt = gr.Textbox(label="Prompt", lines=5, placeholder="Ask a question or provide instructions...")
361
- with gr.TabItem("πŸ–ΌοΈ Image"):
362
- image_prompt = gr.Textbox(label="Image Prompt", lines=2, placeholder="e.g., Describe this picture")
363
- image_file = gr.File(label="Upload Image", file_types=["image"])
364
- with gr.TabItem("🎀 Audio"):
365
- audio_prompt = gr.Textbox(label="Audio Prompt", lines=2, placeholder="e.g., Summarize this audio")
366
- audio_file = gr.File(label="Upload Audio", file_types=[".wav", ".mp3"])
367
- with gr.TabItem("πŸ“„ Document"):
368
- doc_prompt = gr.Textbox(label="Document Prompt", lines=2, placeholder="e.g., Extract text from this PDF")
369
- doc_file = gr.File(label="Upload MD or PDF", file_types=[".md", ".pdf"])
370
 
371
- gr.Markdown("### πŸ“„ Output Settings")
372
  output_formats = gr.CheckboxGroup(choices=["PDF", "DOCX", "XLSX"], label="Select Output Formats", value=["PDF"])
373
 
374
  with gr.Accordion("PDF Customization", open=False):
@@ -386,17 +339,8 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Omni-Model Document Generator") as
386
  gr.Markdown("### πŸ—‚οΈ Generated Files")
387
  file_explorer_output = gr.HTML(label="File Explorer & Gallery")
388
 
389
- def master_process(p1, p2, p3, p4, f1, f2, f3, f4, *args):
390
- # Determine active tab and route to the API
391
- if f1: return generate_outputs_api([f1], p1 or "Describe this text", *args)
392
- if f2: return generate_outputs_api([f2], p2 or "Describe this image", *args)
393
- if f3: return generate_outputs_api([f3], p3 or "Summarize this audio", *args)
394
- if f4: return generate_outputs_api([f4], p4 or "Process this document", *args)
395
- if p1: return generate_outputs_api(None, p1, *args)
396
- raise gr.Error("Please provide an input in one of the tabs.")
397
-
398
- generate_btn.click(fn=master_process,
399
- inputs=[text_prompt, image_prompt, audio_prompt, doc_prompt, text_prompt, image_file, audio_file, doc_file, output_formats, selected_layouts, selected_fonts, num_columns_slider, page_w_mult_slider, page_h_mult_slider],
400
  outputs=[ai_response_output, file_explorer_output])
401
 
402
  if __name__ == "__main__":
 
99
  style_h1 = ParagraphStyle('h1', fontName=bold_font, spaceBefore=12, fontSize=24, textColor=colors.HexColor("#1E3A8A"))
100
  style_h2 = ParagraphStyle('h2', fontName=bold_font, spaceBefore=10, fontSize=18, textColor=colors.HexColor("#374151"))
101
  style_h3 = ParagraphStyle('h3', fontName=bold_font, spaceBefore=8, fontSize=14, textColor=colors.HexColor("#4B5563"))
102
+
 
103
  story, first_heading = [], True
104
  for line in markdown_text.split('\n'):
105
  stripped_line = line.strip()
106
  if not stripped_line:
107
  story.append(Spacer(1, 0.1 * inch)); continue
108
 
 
109
  content, style, extra_args = stripped_line, style_normal, {}
110
  if stripped_line.startswith("# "):
111
  if not first_heading: story.append(PageBreak())
112
  content, style, first_heading = stripped_line.lstrip('# '), style_h1, False
113
+ elif stripped_line.startswith("## "): content, style = stripped_line.lstrip('## '), style_h2
114
+ elif stripped_line.startswith("### "): content, style = stripped_line.lstrip('### '), style_h3
115
+ elif stripped_line.startswith(("- ", "* ")): content, extra_args = stripped_line[2:], {'bulletText': 'β€’'}
 
 
 
116
 
 
 
117
  formatted_content = re.sub(r'_(.*?)_', r'<i>\1</i>', re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', content))
 
118
  final_content = apply_emoji_font(formatted_content, emoji_font)
119
 
120
  story.append(Paragraph(final_content, style, **extra_args))
 
121
  return story
122
 
123
 
 
184
 
185
  file_explorer_html = ""
186
  file_icons = {".pdf": "πŸ“„", ".docx": "πŸ“", ".xlsx": "πŸ“Š"}
187
+ action_buttons = """
188
+ <div class="actions">
189
+ <button class="action-btn" onclick="event.preventDefault(); alert('QuizMe: Feature coming soon!')">🧠 QuizMe</button>
190
+ <button class="action-btn" onclick="event.preventDefault(); alert('Revise: Feature coming soon!')">✍️ Revise</button>
191
+ </div>
192
+ """
193
  for file_path in generated_files:
194
  icon = file_icons.get(file_path.suffix, 'πŸ“Ž')
195
  file_explorer_html += f"""
196
+ <div class="file-item">
197
+ <a href="/file={file_path}" class="file-link" download="{file_path.name}">
198
+ <span class="file-icon">{icon}</span>
199
+ <span class="file-name">{file_path.name}</span>
200
+ </a>
201
+ {action_buttons if file_path.suffix == '.pdf' else ''}
202
+ </div>
203
  """
204
 
205
  gallery_items = []
 
208
  if preview_path:
209
  with open(preview_path, "rb") as f:
210
  img_base64 = base64.b64encode(f.read()).decode("utf-8")
211
+ gallery_items.append({"preview_src": f"data:image/png;base64,{img_base64}", "filename": pdf_path.name})
 
 
 
212
 
213
  gallery_html = ""
214
  if gallery_items:
215
+ thumbs_html = "".join([f'<img src="{item["preview_src"]}" class="thumbnail" onclick="selectThumbnail(this, \'{item["preview_src"]}\', \'{item["filename"]}\')">' for item in gallery_items])
 
 
 
216
  gallery_html = f"""
217
  <div class="gallery-container">
218
+ <div class="main-view"><img id="main-image" src="{gallery_items[0]['preview_src']}" class="main-image"></div>
 
 
 
219
  <div class="thumbnail-strip">{thumbs_html}</div>
220
  </div>
221
+ <p id="main-filename">{gallery_items[0]['filename']}</p>
222
  """
223
 
224
  html = f"""
225
  <style>
226
  .tabs {{ display: flex; border-bottom: 2px solid #ccc; }}
227
+ .tab-button {{ padding: 10px 15px; cursor: pointer; background: #f1f1f1; border: none; font-size: 1.2em; }}
228
+ .tab-button.active {{ background: #fff; border-top: 2px solid #6366f1; border-left: 1px solid #ccc; border-right: 1px solid #ccc; position: relative; top: 1px;}}
229
  .tab-content {{ display: none; padding: 15px; border: 1px solid #ccc; border-top: none; }}
230
  .tab-content.active {{ display: block; }}
231
+ .file-explorer {{ display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px; }}
232
+ .file-item {{ background: #f9f9f9; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }}
233
+ .file-link {{ display: flex; align-items: center; padding: 15px; text-decoration: none; color: #333; }}
234
+ .file-icon {{ font-size: 3em; margin-right: 15px; }}
235
+ .file-name {{ font-weight: bold; word-break: break-all; }}
236
+ .actions {{ display: flex; justify-content: space-around; padding: 5px 10px; border-top: 1px solid #eee; }}
237
+ .action-btn {{ background: none; border: none; cursor: pointer; font-size: 1.1em; }}
238
  .gallery-container {{ display: flex; height: 500px; }}
239
+ .main-view {{ flex: 4; }} .main-image {{ width: 100%; height: 100%; object-fit: contain; }}
240
+ .thumbnail-strip {{ flex: 1; overflow-y: auto; }} .thumbnail {{ width: 100%; margin-bottom: 5px; cursor: pointer; border: 3px solid transparent; }}
241
+ .thumbnail.active {{ border-color: #6366f1; }}
242
+ #main-filename {{ text-align: center; font-weight: bold; margin-top: 10px; }}
 
243
  </style>
244
  <div class="tabs">
245
+ <button class="tab-button active" onclick="openTab(event, 'explorer')">πŸ—‚οΈ FileExplorer</button>
246
+ {'<button class="tab-button" onclick="openTab(event, \'gallery\')">πŸ–ΌοΈ GlimpsePDFs</button>' if gallery_items else ''}
 
 
 
 
 
 
247
  </div>
248
+ <div id="explorer" class="tab-content active"><div class="file-explorer">{file_explorer_html}</div></div>
249
+ <div id="gallery" class="tab-content">{gallery_html}</div>
250
  <script>
251
  function openTab(evt, tabName) {{
252
+ let i, tabcontent = document.getElementsByClassName("tab-content"), tablinks = document.getElementsByClassName("tab-button");
253
+ for (i = 0; i < tabcontent.length; i++) tabcontent[i].style.display = "none";
254
+ for (i = 0; i < tablinks.length; i++) tablinks[i].className = tablinks[i].className.replace(" active", "");
255
+ document.getElementById(tabName).style.display = "block"; evt.currentTarget.className += " active";
 
 
 
256
  }}
257
+ const mainImage = document.getElementById('main-image'), mainFilename = document.getElementById('main-filename'), thumbnails = document.querySelectorAll('.thumbnail');
 
 
 
258
  if (thumbnails.length > 0) thumbnails[0].classList.add('active');
259
+ function selectThumbnail(thumb, src, name) {{
260
+ mainImage.src = src; mainFilename.textContent = name;
261
+ thumbnails.forEach(t => t.classList.remove('active')); thumb.classList.add('active');
 
 
262
  }};
263
  </script>
264
  """
265
  return html
266
 
267
+ def generate_outputs_api(omni_file, omni_prompt, output_formats, layouts, fonts, num_columns, page_w_mult, page_h_mult, progress=gr.Progress(track_tqdm=True)):
268
+ if not omni_prompt and not omni_file: raise gr.Error("Please provide a prompt or upload at least one file.")
 
269
  if not output_formats: raise gr.Error("Please select at least one output format.")
270
 
271
  shutil.rmtree(OUTPUT_DIR, ignore_errors=True); shutil.rmtree(PREVIEW_DIR, ignore_errors=True)
272
  OUTPUT_DIR.mkdir(); PREVIEW_DIR.mkdir()
273
 
274
  md_content = ""
275
+ if omni_file:
276
+ temp_path = UPLOAD_DIR / Path(omni_file.name).name
277
+ shutil.copyfile(omni_file.name, temp_path)
278
+ file_ext = temp_path.suffix.lower()
279
+
280
+ if file_ext == '.md': md_content = temp_path.read_text(encoding='utf-8')
281
+ elif file_ext == '.pdf': md_content = process_pdf_input(temp_path, omni_prompt or "Extract text", progress)
282
+ elif file_ext in ['.png', '.jpg', '.jpeg']: md_content = process_image_input(temp_path, omni_prompt or "Describe image")
283
+ elif file_ext in ['.wav', '.mp3']: md_content = process_audio_input(temp_path, omni_prompt or "Summarize transcription")
 
 
 
 
 
284
  elif omni_prompt:
285
  md_content = process_text_input(omni_prompt)
286
 
 
295
  pagesize = LAYOUTS[layout_name]["size"]
296
  final_pagesize = (pagesize[0] * page_w_mult, pagesize[1] * page_h_mult)
297
  pdf_buffer = create_pdf(md_content, font_name, EMOJI_FONT_NAME, final_pagesize, num_columns)
298
+ filename = f"Document_{time_str}.pdf"; output_path = OUTPUT_DIR / filename
 
299
  with open(output_path, "wb") as f: f.write(pdf_buffer.getvalue())
300
  generated_files.append(output_path); pdf_files_for_gallery.append(output_path)
301
  elif format_choice == "DOCX":
 
311
 
312
  # --- 🎨 Gradio UI Definition ---
313
  AVAILABLE_FONTS, EMOJI_FONT_NAME = register_local_fonts()
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
  with gr.Blocks(theme=gr.themes.Soft(), title="Omni-Model Document Generator") as demo:
316
  gr.Markdown("# 🧠 Omni-Model Document Generator")
317
+ gr.Markdown("Provide a prompt or upload a file (MD, PDF, Image, Audio). A virtual AI will process it, and you can generate documents from the result.")
318
 
319
  with gr.Row():
320
  with gr.Column(scale=1):
321
+ gr.Markdown("### βš™οΈ Input & Settings")
322
+ omni_prompt = gr.Textbox(label="Prompt", lines=3, placeholder="Ask a question or provide instructions...")
323
+ omni_file = gr.File(label="Upload File (Optional)", file_types=["image", ".wav", ".mp3", ".md", ".pdf"])
 
 
 
 
 
 
 
 
 
324
 
 
325
  output_formats = gr.CheckboxGroup(choices=["PDF", "DOCX", "XLSX"], label="Select Output Formats", value=["PDF"])
326
 
327
  with gr.Accordion("PDF Customization", open=False):
 
339
  gr.Markdown("### πŸ—‚οΈ Generated Files")
340
  file_explorer_output = gr.HTML(label="File Explorer & Gallery")
341
 
342
+ generate_btn.click(fn=generate_outputs_api,
343
+ inputs=[omni_file, omni_prompt, output_formats, selected_layouts, selected_fonts, num_columns_slider, page_w_mult_slider, page_h_mult_slider],
 
 
 
 
 
 
 
 
 
344
  outputs=[ai_response_output, file_explorer_output])
345
 
346
  if __name__ == "__main__":