CarsonNg commited on
Commit
ad66f04
Β·
verified Β·
1 Parent(s): 0200ef3

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -87
app.py CHANGED
@@ -262,6 +262,16 @@ def upload_document(file_obj) -> Tuple[bool, Optional[str], Optional[int], str]:
262
  return _upload_text(text_content, filename)
263
 
264
 
 
 
 
 
 
 
 
 
 
 
265
  def load_selected_samples(selected_labels: list) -> Tuple[bool, Optional[str], Optional[int], str]:
266
  """Combine and upload one or more sample annual reports."""
267
  if not selected_labels:
@@ -322,10 +332,10 @@ def query_backend(message: str) -> Generator[str, None, None]:
322
  def update_index_display(filename: Optional[str], is_indexed: bool, char_count: Optional[int] = None) -> str:
323
  if is_indexed and filename:
324
  detail = f" ({char_count:,} characters)" if char_count else ""
325
- return f"πŸ“„ **Indexed Document:** {filename}{detail}"
326
  elif is_indexed:
327
- return "πŸ“„ **Indexed Document:** βœ… Document indexed"
328
- return "πŸ“„ **Indexed Document:** None"
329
 
330
 
331
  def load_index_state() -> Tuple[bool, Optional[str], Optional[int], str]:
@@ -422,117 +432,141 @@ def create_app() -> gr.Blocks:
422
  with gr.Column(elem_id="chat-page", visible=False) as chat_page:
423
  gr.Markdown(
424
  """
425
- <div style="text-align: center; margin-bottom: 1.5em;">
426
  <h1>πŸ“š RAG Chat Interface</h1>
427
- <p style="color: #666;">Load sample reports or upload your own, then ask questions.</p>
428
  </div>
429
  """
430
  )
431
 
432
- index_status = gr.Markdown("πŸ“„ **Indexed Document:** None")
433
-
434
- # ── Sample report section ─────────────────────────────────────
435
- gr.Markdown("### πŸ“‹ Sample Annual Reports")
436
- sample_selector = gr.CheckboxGroup(
437
- choices=list(SAMPLE_LABELS.keys()),
438
- value=[],
439
- label="Select one or more reports to index",
440
- interactive=True,
441
- )
442
 
443
- load_samples_btn = gr.Button("πŸš€ Load Selected Reports", variant="primary")
444
-
445
- sample_status = gr.Markdown("")
 
 
 
 
 
 
 
 
 
 
 
 
446
 
447
- with gr.Accordion("πŸ“– Preview Selected Documents", open=False):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  preview_box = gr.Textbox(
449
  value="",
450
  lines=18,
451
  max_lines=18,
452
  interactive=False,
453
  show_label=False,
454
- placeholder="Select reports above to preview their content here.",
455
  )
456
 
457
- sample_selector.change(
458
- fn=lambda labels: build_preview_text(labels)[0],
459
- inputs=[sample_selector],
460
- outputs=[preview_box],
461
- )
 
 
 
 
 
 
 
 
 
 
 
 
462
 
463
- def _after_load(success, filename, char_count, message):
464
- display = update_index_display(filename, success, char_count)
465
- return success, filename, char_count, message, display
 
 
466
 
467
  load_samples_btn.click(
468
- fn=load_selected_samples,
469
  inputs=[sample_selector],
470
- outputs=[document_indexed, indexed_filename, indexed_char_count, sample_status],
471
- ).then(
472
- fn=_after_load,
473
- inputs=[document_indexed, indexed_filename, indexed_char_count, sample_status],
474
- outputs=[document_indexed, indexed_filename, indexed_char_count, sample_status, index_status],
475
  )
476
 
477
- # ── Own file upload ────────────────────────────────────────────
478
- gr.Markdown("### πŸ“ Or Upload Your Own Document")
479
- with gr.Row():
480
- with gr.Column(scale=2):
481
- file_input = gr.File(
482
- label="Upload .txt file",
483
- file_types=[".txt"],
484
- file_count="single",
485
- )
486
- with gr.Column(scale=1):
487
- upload_btn = gr.Button("πŸ“€ Build Index", variant="primary", size="lg")
488
 
489
- upload_status = gr.Markdown("**Status:** Waiting for document...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
 
491
  upload_btn.click(
492
- fn=upload_document,
493
  inputs=[file_input],
494
- outputs=[document_indexed, indexed_filename, indexed_char_count, upload_status],
495
- ).then(
496
- fn=_after_load,
497
- inputs=[document_indexed, indexed_filename, indexed_char_count, upload_status],
498
- outputs=[document_indexed, indexed_filename, indexed_char_count, upload_status, index_status],
499
  )
500
 
501
- # ── Chat section ───────────────────────────────────────────────
502
- gr.Markdown("### πŸ’¬ Ask Questions")
503
-
504
- # Define respond BEFORE wiring any buttons that reference it
505
- def respond(message, history, is_indexed):
506
- history = history or []
507
- if not message or not message.strip():
508
- yield history, message
509
- return
510
- user_msg = {"role": "user", "content": message}
511
- if not is_indexed:
512
- yield history + [user_msg, {"role": "assistant", "content": "⚠️ Please load a sample report or upload a document first."}], ""
513
- return
514
- yield history + [user_msg, {"role": "assistant", "content": "πŸ€” Thinking..."}], ""
515
- final_answer = "πŸ€” Thinking..."
516
- for chunk in query_backend(message):
517
- final_answer = chunk
518
- yield history + [user_msg, {"role": "assistant", "content": final_answer}], ""
519
-
520
- gr.Markdown("<small style='color:#888'>Quick questions:</small>")
521
- with gr.Row():
522
- q_btns = [gr.Button(q, size="sm") for q in SAMPLE_QUESTIONS]
523
-
524
- chatbot = gr.Chatbot(height=420, show_label=False, value=[])
525
-
526
- with gr.Row():
527
- question_input = gr.Textbox(
528
- placeholder="Type your question and press Enter…",
529
- lines=1,
530
- scale=9,
531
- show_label=False,
532
- container=False,
533
- )
534
- send_btn = gr.Button("Send β–Ά", scale=1, variant="primary")
535
-
536
  # Quick-question buttons: fill the textbox, then auto-submit
537
  for btn, q in zip(q_btns, SAMPLE_QUESTIONS):
538
  btn.click(
 
262
  return _upload_text(text_content, filename)
263
 
264
 
265
+ def upload_pasted_text(text: str, filename: str = "pasted.txt") -> Tuple[bool, Optional[str], Optional[int], str]:
266
+ """Index user-pasted text directly."""
267
+ if not text or not text.strip():
268
+ return False, None, None, "⚠️ Please paste some text first."
269
+ filename = (filename or "pasted.txt").strip() or "pasted.txt"
270
+ if not filename.endswith(".txt"):
271
+ filename += ".txt"
272
+ return _upload_text(text, filename)
273
+
274
+
275
  def load_selected_samples(selected_labels: list) -> Tuple[bool, Optional[str], Optional[int], str]:
276
  """Combine and upload one or more sample annual reports."""
277
  if not selected_labels:
 
332
  def update_index_display(filename: Optional[str], is_indexed: bool, char_count: Optional[int] = None) -> str:
333
  if is_indexed and filename:
334
  detail = f" ({char_count:,} characters)" if char_count else ""
335
+ return f"πŸ“„ **Indexed** {filename}{detail}"
336
  elif is_indexed:
337
+ return "πŸ“„ **Indexed** (document ready)"
338
+ return "πŸ“„ *No document indexed yet*"
339
 
340
 
341
  def load_index_state() -> Tuple[bool, Optional[str], Optional[int], str]:
 
432
  with gr.Column(elem_id="chat-page", visible=False) as chat_page:
433
  gr.Markdown(
434
  """
435
+ <div style="text-align: center; margin-bottom: 1em;">
436
  <h1>πŸ“š RAG Chat Interface</h1>
 
437
  </div>
438
  """
439
  )
440
 
441
+ index_status = gr.Markdown("πŸ“„ *No document indexed yet*")
 
 
 
 
 
 
 
 
 
442
 
443
+ # Define respond up-front so any button below can reference it
444
+ def respond(message, history, is_indexed):
445
+ history = history or []
446
+ if not message or not message.strip():
447
+ yield history, message
448
+ return
449
+ user_msg = {"role": "user", "content": message}
450
+ if not is_indexed:
451
+ yield history + [user_msg, {"role": "assistant", "content": "⚠️ Please index a document first (see section 1)."}], ""
452
+ return
453
+ yield history + [user_msg, {"role": "assistant", "content": "πŸ€” Thinking..."}], ""
454
+ final_answer = "πŸ€” Thinking..."
455
+ for chunk in query_backend(message):
456
+ final_answer = chunk
457
+ yield history + [user_msg, {"role": "assistant", "content": final_answer}], ""
458
 
459
+ # Returns (indexed?, filename, char_count, display_md, preview_text)
460
+ def _after_index(success, filename, char_count, source_text):
461
+ display = update_index_display(filename, success, char_count)
462
+ preview = source_text if success else ""
463
+ return success, filename, char_count, display, preview
464
+
465
+ # ── Section 1: Select files to index ──────────────────────────
466
+ with gr.Accordion("πŸ“₯ 1. Select files to index", open=True):
467
+ with gr.Tabs():
468
+ # β€” Tab A: sample files β€”
469
+ with gr.Tab("πŸ“‹ Sample reports"):
470
+ sample_selector = gr.CheckboxGroup(
471
+ choices=list(SAMPLE_LABELS.keys()),
472
+ value=[],
473
+ label="Pick one or more sample annual reports",
474
+ interactive=True,
475
+ )
476
+ load_samples_btn = gr.Button("πŸš€ Index Selected Reports", variant="primary")
477
+
478
+ # β€” Tab B: paste text β€”
479
+ with gr.Tab("✏️ Paste text"):
480
+ paste_input = gr.Textbox(
481
+ label="Paste text here",
482
+ lines=10,
483
+ max_lines=20,
484
+ placeholder="Paste any text content you want to ask questions about…",
485
+ )
486
+ paste_filename = gr.Textbox(
487
+ label="Filename (optional)",
488
+ value="pasted.txt",
489
+ lines=1,
490
+ )
491
+ load_paste_btn = gr.Button("πŸš€ Index Pasted Text", variant="primary")
492
+
493
+ # β€” Tab C: upload file β€”
494
+ with gr.Tab("πŸ“ Upload file"):
495
+ file_input = gr.File(
496
+ label="Upload .txt file",
497
+ file_types=[".txt"],
498
+ file_count="single",
499
+ )
500
+ upload_btn = gr.Button("πŸš€ Index Uploaded File", variant="primary")
501
+
502
+ # ── Section 2: Preview indexed text ───────────────────────────
503
+ with gr.Accordion("πŸ“– 2. Preview indexed text", open=False):
504
  preview_box = gr.Textbox(
505
  value="",
506
  lines=18,
507
  max_lines=18,
508
  interactive=False,
509
  show_label=False,
510
+ placeholder="Index a document in section 1 to see its content here.",
511
  )
512
 
513
+ # ── Section 3: Chat ────────────────────────────────────────────
514
+ with gr.Accordion("πŸ’¬ 3. Ask questions", open=True):
515
+ gr.Markdown("<small style='color:#888'>Quick questions:</small>")
516
+ with gr.Row():
517
+ q_btns = [gr.Button(q, size="sm") for q in SAMPLE_QUESTIONS]
518
+
519
+ chatbot = gr.Chatbot(height=420, show_label=False, value=[])
520
+
521
+ with gr.Row():
522
+ question_input = gr.Textbox(
523
+ placeholder="Type your question and press Enter…",
524
+ lines=1,
525
+ scale=9,
526
+ show_label=False,
527
+ container=False,
528
+ )
529
+ send_btn = gr.Button("Send β–Ά", scale=1, variant="primary")
530
 
531
+ # ── Wiring for Section 1 actions ──────────────────────────────
532
+ def _samples_action(selected_labels):
533
+ success, filename, char_count, _msg = load_selected_samples(selected_labels)
534
+ source_text = build_preview_text(selected_labels)[0] if success else ""
535
+ return _after_index(success, filename, char_count, source_text)
536
 
537
  load_samples_btn.click(
538
+ fn=_samples_action,
539
  inputs=[sample_selector],
540
+ outputs=[document_indexed, indexed_filename, indexed_char_count, index_status, preview_box],
 
 
 
 
541
  )
542
 
543
+ def _paste_action(text, filename):
544
+ success, fn_used, char_count, _msg = upload_pasted_text(text, filename)
545
+ return _after_index(success, fn_used, char_count, text if success else "")
 
 
 
 
 
 
 
 
546
 
547
+ load_paste_btn.click(
548
+ fn=_paste_action,
549
+ inputs=[paste_input, paste_filename],
550
+ outputs=[document_indexed, indexed_filename, indexed_char_count, index_status, preview_box],
551
+ )
552
+
553
+ def _upload_action(file_obj):
554
+ success, fn_used, char_count, _msg = upload_document(file_obj)
555
+ source_text = ""
556
+ if success and file_obj is not None and os.path.exists(file_obj.name):
557
+ try:
558
+ with open(file_obj.name, "r", encoding="utf-8") as f:
559
+ source_text = f.read()
560
+ except Exception:
561
+ source_text = ""
562
+ return _after_index(success, fn_used, char_count, source_text)
563
 
564
  upload_btn.click(
565
+ fn=_upload_action,
566
  inputs=[file_input],
567
+ outputs=[document_indexed, indexed_filename, indexed_char_count, index_status, preview_box],
 
 
 
 
568
  )
569
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
570
  # Quick-question buttons: fill the textbox, then auto-submit
571
  for btn, q in zip(q_btns, SAMPLE_QUESTIONS):
572
  btn.click(