openfree commited on
Commit
4ac1625
·
verified ·
1 Parent(s): 16c5e93

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +221 -215
app.py CHANGED
@@ -1,9 +1,14 @@
1
  import gradio as gr
 
2
  import os
3
  from typing import List, Dict, Any, Optional, Tuple
4
  import hashlib
5
  from datetime import datetime
6
  import numpy as np
 
 
 
 
7
 
8
  # PDF 처리 라이브러리
9
  try:
@@ -20,7 +25,7 @@ except ImportError:
20
  ST_AVAILABLE = False
21
  print("⚠️ Sentence Transformers not installed. Install with: pip install sentence-transformers")
22
 
23
- # Soft and bright custom CSS
24
  custom_css = """
25
  .gradio-container {
26
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
@@ -37,7 +42,6 @@ custom_css = """
37
  margin: 12px;
38
  }
39
 
40
- /* Status messages styling */
41
  .pdf-status {
42
  padding: 12px 16px;
43
  border-radius: 12px;
@@ -72,6 +76,14 @@ custom_css = """
72
  border-radius: 8px;
73
  font-size: 0.9rem;
74
  }
 
 
 
 
 
 
 
 
75
  """
76
 
77
  class SimpleTextSplitter:
@@ -237,44 +249,128 @@ class PDFRAGSystem:
237
  all_relevant_chunks.sort(key=lambda x: x.get('similarity', 0), reverse=True)
238
  return all_relevant_chunks[:top_k]
239
 
240
- def create_rag_prompt(self, query: str, doc_ids: List[str], top_k: int = 3) -> str:
241
- """RAG 프롬프트 생성"""
242
  relevant_chunks = self.search_relevant_chunks(query, doc_ids, top_k)
243
 
244
  if not relevant_chunks:
245
- return query
246
 
247
- # 프롬프트 구성
248
- prompt_parts = []
249
- prompt_parts.append("다음 문서 내용을 참고하여 답변해주세요:\n")
250
- prompt_parts.append("=" * 40)
251
 
252
  for i, chunk in enumerate(relevant_chunks, 1):
253
- prompt_parts.append(f"\n[참고 {i} - {chunk['doc_name']}]")
254
  content = chunk['content'][:300] if len(chunk['content']) > 300 else chunk['content']
255
- prompt_parts.append(content)
256
 
257
- prompt_parts.append("\n" + "=" * 40)
258
- prompt_parts.append(f"\n질문: {query}")
259
 
260
- return "\n".join(prompt_parts)
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
- # RAG 시스템 인스턴스 생성
263
  rag_system = PDFRAGSystem()
264
 
265
- # State variable to track current model and RAG settings
266
- current_model = gr.State("openai/gpt-oss-120b")
267
- rag_enabled_state = gr.State(False)
268
- selected_docs_state = gr.State([])
269
- top_k_state = gr.State(3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  def upload_pdf(file):
272
  """PDF 파일 업로드 처리"""
273
  if file is None:
274
  return (
275
  gr.update(value="<div class='pdf-status pdf-info'>📁 파일을 선택해주세요</div>"),
276
- gr.update(choices=[]),
277
- gr.update(value=False)
278
  )
279
 
280
  try:
@@ -302,257 +398,167 @@ def upload_pdf(file):
302
 
303
  return (
304
  status_html,
305
- gr.update(choices=doc_choices, value=doc_choices),
306
- gr.update(value=True)
307
  )
308
  else:
309
  return (
310
  f"<div class='pdf-status pdf-error'>❌ 오류: {result['error']}</div>",
311
- gr.update(),
312
- gr.update(value=False)
313
  )
314
 
315
  except Exception as e:
316
  return (
317
  f"<div class='pdf-status pdf-error'>❌ 오류: {str(e)}</div>",
318
- gr.update(),
319
- gr.update(value=False)
320
  )
321
 
322
  def clear_documents():
323
  """문서 초기화"""
 
324
  rag_system.documents = {}
325
  rag_system.document_chunks = {}
326
  rag_system.embeddings_store = {}
 
327
 
328
  return (
329
  gr.update(value="<div class='pdf-status pdf-info'>🗑️ 모든 문서가 삭제되었습니다</div>"),
330
- gr.update(choices=[], value=[]),
331
- gr.update(value=False)
332
  )
333
 
334
- def switch_model(model_choice):
335
- """Function to switch between models"""
336
- return gr.update(visible=False), gr.update(visible=True), model_choice
337
-
338
- def create_rag_wrapper(original_fn, model_name):
339
- """원본 모델 함수를 RAG로 감싸는 래퍼 생성"""
340
- def wrapped_fn(message, history=None):
341
- # RAG 설정 가져오기
342
- if rag_enabled_state.value and selected_docs_state.value:
343
- doc_ids = [doc.split(":")[0] for doc in selected_docs_state.value]
344
- enhanced_message = rag_system.create_rag_prompt(message, doc_ids, top_k_state.value)
345
-
346
- # RAG 적용 알림
347
- print(f"🔍 RAG 적용: {len(message)}자 → {len(enhanced_message)}자")
348
-
349
- # 원본 모델에 강화된 메시지 전달
350
- if history is not None:
351
- return original_fn(enhanced_message, history)
352
- else:
353
- return original_fn(enhanced_message)
354
- else:
355
- # RAG 미적용시 원본 메시지 그대로 전달
356
- if history is not None:
357
- return original_fn(message, history)
358
- else:
359
- return original_fn(message)
360
 
361
- return wrapped_fn
 
 
 
 
 
 
 
 
362
 
363
- # Main interface with soft theme
364
- with gr.Blocks(fill_height=True, theme=gr.themes.Soft(), css=custom_css) as demo:
 
 
365
 
366
  with gr.Row():
367
- # Sidebar
368
  with gr.Column(scale=1):
369
  with gr.Group(elem_classes="main-container"):
370
- gr.Markdown("# 🚀 Inference Provider + RAG")
371
- gr.Markdown(
372
- "OpenAI GPT-OSS models served by Cerebras API. "
373
- "Upload PDF documents for context-aware responses."
 
 
374
  )
375
 
376
- # Model selection
377
- model_dropdown = gr.Dropdown(
378
- choices=["openai/gpt-oss-120b", "openai/gpt-oss-20b"],
379
- value="openai/gpt-oss-120b",
380
- label="📊 Select Model",
381
- info="Choose between different model sizes"
382
  )
383
 
384
- # Login button
385
- login_button = gr.LoginButton("Sign in with Hugging Face", size="lg")
 
 
 
386
 
387
- # Reload button to apply model change
388
- reload_btn = gr.Button("🔄 Apply Model Change", variant="primary", size="lg")
389
 
390
- # RAG Settings
391
- with gr.Accordion("📚 PDF RAG Settings", open=True):
392
- pdf_upload = gr.File(
393
- label="Upload PDF",
394
- file_types=[".pdf"],
395
- type="filepath"
396
- )
397
-
398
- upload_status = gr.HTML(
399
- value="<div class='pdf-status pdf-info'>📤 Upload a PDF to enable document-based answers</div>"
400
- )
401
-
402
- document_list = gr.CheckboxGroup(
403
- choices=[],
404
- label="📄 Uploaded Documents",
405
- info="Select documents to use as context"
406
- )
407
-
408
- clear_btn = gr.Button("🗑️ Clear All Documents", size="sm", variant="secondary")
409
-
410
- enable_rag = gr.Checkbox(
411
- label="✨ Enable RAG",
412
- value=False,
413
- info="Use documents for context-aware responses"
414
- )
415
-
416
- top_k_chunks = gr.Slider(
417
- minimum=1,
418
- maximum=5,
419
- value=3,
420
- step=1,
421
- label="Context Chunks",
422
- info="Number of document chunks to use"
423
- )
424
 
425
- # Additional options
426
- with gr.Accordion("⚙️ Advanced Options", open=False):
427
- gr.Markdown("*These options will be available after model implementation*")
428
- temperature = gr.Slider(
429
- minimum=0,
430
- maximum=2,
431
- value=0.7,
432
- step=0.1,
433
- label="Temperature"
434
- )
435
- max_tokens = gr.Slider(
436
- minimum=1,
437
- maximum=4096,
438
- value=512,
439
- step=1,
440
- label="Max Tokens"
441
- )
442
-
443
- # Main chat area
444
- with gr.Column(scale=3):
445
- with gr.Group(elem_classes="main-container"):
446
- gr.Markdown("## 💬 Chat Interface")
447
 
448
- # RAG status
449
  rag_status = gr.HTML(
450
  value="<div class='pdf-status pdf-info'>🔍 RAG: <strong>Disabled</strong></div>"
451
  )
452
 
453
- # RAG context preview
454
  context_preview = gr.HTML(value="", visible=False)
455
-
456
- # Container for model interfaces
457
- with gr.Column(visible=True) as model_120b_container:
458
- gr.Markdown("### Model: openai/gpt-oss-120b")
459
-
460
- # Load the original model and wrap it with RAG
461
- original_interface_120b = gr.load(
462
- "models/openai/gpt-oss-120b",
463
- accept_token=login_button,
464
- provider="fireworks-ai"
465
- )
466
-
467
- # Note: The loaded interface will have its own chat components
468
- # We'll intercept the messages through our wrapper function
469
-
470
- with gr.Column(visible=False) as model_20b_container:
471
- gr.Markdown("### Model: openai/gpt-oss-20b")
472
-
473
- # Load the original model
474
- original_interface_20b = gr.load(
475
- "models/openai/gpt-oss-20b",
476
- accept_token=login_button,
477
- provider="fireworks-ai"
478
- )
479
-
480
- # Event Handlers
 
 
 
 
 
 
 
 
 
 
481
 
482
- # PDF upload
483
  pdf_upload.upload(
484
  fn=upload_pdf,
485
  inputs=[pdf_upload],
486
- outputs=[upload_status, document_list, enable_rag]
487
  )
488
 
489
- # Clear documents
490
  clear_btn.click(
491
  fn=clear_documents,
492
- outputs=[upload_status, document_list, enable_rag]
493
  )
494
 
495
- # Update RAG state when settings change
496
- def update_rag_state(enabled, docs, k):
497
- rag_enabled_state.value = enabled
498
- selected_docs_state.value = docs if docs else []
499
- top_k_state.value = k
500
-
501
- status = "✅ Enabled" if enabled and docs else "⭕ Disabled"
502
- status_html = f"<div class='pdf-status pdf-info'>🔍 RAG: <strong>{status}</strong></div>"
503
-
504
- # Show context preview if RAG is enabled
505
- if enabled and docs:
506
- preview = f"<div class='rag-context'>📚 Using {len(docs)} document(s) with {k} chunks per query</div>"
507
- return gr.update(value=status_html), gr.update(value=preview, visible=True)
508
- else:
509
- return gr.update(value=status_html), gr.update(value="", visible=False)
510
-
511
- # Connect RAG state updates
512
  enable_rag.change(
513
- fn=update_rag_state,
514
- inputs=[enable_rag, document_list, top_k_chunks],
515
  outputs=[rag_status, context_preview]
516
  )
517
 
518
  document_list.change(
519
- fn=update_rag_state,
520
- inputs=[enable_rag, document_list, top_k_chunks],
521
  outputs=[rag_status, context_preview]
522
  )
523
 
524
- top_k_chunks.change(
525
- fn=update_rag_state,
526
- inputs=[enable_rag, document_list, top_k_chunks],
527
  outputs=[rag_status, context_preview]
528
  )
529
-
530
- # Handle model switching
531
- reload_btn.click(
532
- fn=switch_model,
533
- inputs=[model_dropdown],
534
- outputs=[model_120b_container, model_20b_container, current_model]
535
- ).then(
536
- fn=lambda: gr.Info("Model switched successfully!"),
537
- inputs=[],
538
- outputs=[]
539
- )
540
-
541
- # Update visibility based on dropdown selection
542
- def update_visibility(model_choice):
543
- if model_choice == "openai/gpt-oss-120b":
544
- return gr.update(visible=True), gr.update(visible=False)
545
- else:
546
- return gr.update(visible=False), gr.update(visible=True)
547
-
548
- model_dropdown.change(
549
- fn=update_visibility,
550
- inputs=[model_dropdown],
551
- outputs=[model_120b_container, model_20b_container]
552
- )
553
-
554
- # Monkey-patch the loaded interfaces to add RAG support
555
- # This is done after the interface is loaded
556
- demo.load = lambda: print("📚 RAG System Ready!")
557
 
558
- demo.launch()
 
 
1
  import gradio as gr
2
+ import spaces
3
  import os
4
  from typing import List, Dict, Any, Optional, Tuple
5
  import hashlib
6
  from datetime import datetime
7
  import numpy as np
8
+ from transformers import pipeline, TextIteratorStreamer
9
+ import torch
10
+ from threading import Thread
11
+ import re
12
 
13
  # PDF 처리 라이브러리
14
  try:
 
25
  ST_AVAILABLE = False
26
  print("⚠️ Sentence Transformers not installed. Install with: pip install sentence-transformers")
27
 
28
+ # Custom CSS
29
  custom_css = """
30
  .gradio-container {
31
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
 
42
  margin: 12px;
43
  }
44
 
 
45
  .pdf-status {
46
  padding: 12px 16px;
47
  border-radius: 12px;
 
76
  border-radius: 8px;
77
  font-size: 0.9rem;
78
  }
79
+
80
+ .thinking-section {
81
+ background: rgba(0, 0, 0, 0.02);
82
+ border: 1px solid rgba(0, 0, 0, 0.1);
83
+ border-radius: 8px;
84
+ padding: 12px;
85
+ margin: 8px 0;
86
+ }
87
  """
88
 
89
  class SimpleTextSplitter:
 
249
  all_relevant_chunks.sort(key=lambda x: x.get('similarity', 0), reverse=True)
250
  return all_relevant_chunks[:top_k]
251
 
252
+ def create_rag_prompt(self, query: str, doc_ids: List[str], top_k: int = 3) -> tuple:
253
+ """RAG 프롬프트 생성 - 쿼리와 컨텍스트를 분리하여 반환"""
254
  relevant_chunks = self.search_relevant_chunks(query, doc_ids, top_k)
255
 
256
  if not relevant_chunks:
257
+ return query, ""
258
 
259
+ # 컨텍스트 구성
260
+ context_parts = []
261
+ context_parts.append("다음 문서 내용을 참고하여 답변해주세요:\n")
262
+ context_parts.append("=" * 40)
263
 
264
  for i, chunk in enumerate(relevant_chunks, 1):
265
+ context_parts.append(f"\n[참고 {i} - {chunk['doc_name']}]")
266
  content = chunk['content'][:300] if len(chunk['content']) > 300 else chunk['content']
267
+ context_parts.append(content)
268
 
269
+ context_parts.append("\n" + "=" * 40)
 
270
 
271
+ context = "\n".join(context_parts)
272
+ enhanced_query = f"{context}\n\n질문: {query}"
273
+
274
+ return enhanced_query, context
275
+
276
+ # Initialize model and RAG system
277
+ model_id = "openai/gpt-oss-20b"
278
+ pipe = pipeline(
279
+ "text-generation",
280
+ model=model_id,
281
+ torch_dtype="auto",
282
+ device_map="auto",
283
+ )
284
 
 
285
  rag_system = PDFRAGSystem()
286
 
287
+ # Global state for RAG
288
+ rag_enabled = False
289
+ selected_docs = []
290
+ top_k_chunks = 3
291
+ last_context = ""
292
+
293
+ def format_conversation_history(chat_history):
294
+ """Format conversation history for the model"""
295
+ messages = []
296
+ for item in chat_history:
297
+ role = item["role"]
298
+ content = item["content"]
299
+ if isinstance(content, list):
300
+ content = content[0]["text"] if content and "text" in content[0] else str(content)
301
+ messages.append({"role": role, "content": content})
302
+ return messages
303
+
304
+ @spaces.GPU()
305
+ def generate_response(input_data, chat_history, max_new_tokens, system_prompt, temperature, top_p, top_k, repetition_penalty):
306
+ """Generate response with optional RAG enhancement"""
307
+ global last_context
308
+
309
+ # Apply RAG if enabled
310
+ if rag_enabled and selected_docs:
311
+ doc_ids = [doc.split(":")[0] for doc in selected_docs]
312
+ enhanced_input, context = rag_system.create_rag_prompt(input_data, doc_ids, top_k_chunks)
313
+ last_context = context
314
+ actual_input = enhanced_input
315
+ else:
316
+ actual_input = input_data
317
+ last_context = ""
318
+
319
+ # Prepare messages
320
+ new_message = {"role": "user", "content": actual_input}
321
+ system_message = [{"role": "system", "content": system_prompt}] if system_prompt else []
322
+ processed_history = format_conversation_history(chat_history)
323
+ messages = system_message + processed_history + [new_message]
324
+
325
+ # Setup streaming
326
+ streamer = TextIteratorStreamer(pipe.tokenizer, skip_prompt=True, skip_special_tokens=True)
327
+ generation_kwargs = {
328
+ "max_new_tokens": max_new_tokens,
329
+ "do_sample": True,
330
+ "temperature": temperature,
331
+ "top_p": top_p,
332
+ "top_k": top_k,
333
+ "repetition_penalty": repetition_penalty,
334
+ "streamer": streamer
335
+ }
336
+
337
+ thread = Thread(target=pipe, args=(messages,), kwargs=generation_kwargs)
338
+ thread.start()
339
+
340
+ # Process streaming output
341
+ thinking = ""
342
+ final = ""
343
+ started_final = False
344
+
345
+ for chunk in streamer:
346
+ if not started_final:
347
+ if "assistantfinal" in chunk.lower():
348
+ split_parts = re.split(r'assistantfinal', chunk, maxsplit=1)
349
+ thinking += split_parts[0]
350
+ final += split_parts[1]
351
+ started_final = True
352
+ else:
353
+ thinking += chunk
354
+ else:
355
+ final += chunk
356
+
357
+ clean_thinking = re.sub(r'^analysis\s*', '', thinking).strip()
358
+ clean_final = final.strip()
359
+
360
+ # Add RAG context indicator if used
361
+ rag_indicator = ""
362
+ if rag_enabled and selected_docs and last_context:
363
+ rag_indicator = "<div class='rag-context'>📚 RAG Context Applied</div>\n\n"
364
+
365
+ formatted = f"{rag_indicator}<details open><summary>Click to view Thinking Process</summary>\n\n{clean_thinking}\n\n</details>\n\n{clean_final}"
366
+ yield formatted
367
 
368
  def upload_pdf(file):
369
  """PDF 파일 업로드 처리"""
370
  if file is None:
371
  return (
372
  gr.update(value="<div class='pdf-status pdf-info'>📁 파일을 선택해주세요</div>"),
373
+ gr.update(choices=[])
 
374
  )
375
 
376
  try:
 
398
 
399
  return (
400
  status_html,
401
+ gr.update(choices=doc_choices, value=doc_choices)
 
402
  )
403
  else:
404
  return (
405
  f"<div class='pdf-status pdf-error'>❌ 오류: {result['error']}</div>",
406
+ gr.update()
 
407
  )
408
 
409
  except Exception as e:
410
  return (
411
  f"<div class='pdf-status pdf-error'>❌ 오류: {str(e)}</div>",
412
+ gr.update()
 
413
  )
414
 
415
  def clear_documents():
416
  """문서 초기화"""
417
+ global selected_docs
418
  rag_system.documents = {}
419
  rag_system.document_chunks = {}
420
  rag_system.embeddings_store = {}
421
+ selected_docs = []
422
 
423
  return (
424
  gr.update(value="<div class='pdf-status pdf-info'>🗑️ 모든 문서가 삭제되었습니다</div>"),
425
+ gr.update(choices=[], value=[])
 
426
  )
427
 
428
+ def update_rag_settings(enable, docs, k):
429
+ """Update RAG settings"""
430
+ global rag_enabled, selected_docs, top_k_chunks
431
+ rag_enabled = enable
432
+ selected_docs = docs if docs else []
433
+ top_k_chunks = k
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
 
435
+ status = "✅ Enabled" if enable and docs else "⭕ Disabled"
436
+ status_html = f"<div class='pdf-status pdf-info'>🔍 RAG: <strong>{status}</strong></div>"
437
+
438
+ # Show context preview if RAG is enabled
439
+ if enable and docs:
440
+ preview = f"<div class='rag-context'>📚 Using {len(docs)} document(s) with {k} chunks per query</div>"
441
+ return gr.update(value=status_html), gr.update(value=preview, visible=True)
442
+ else:
443
+ return gr.update(value=status_html), gr.update(value="", visible=False)
444
 
445
+ # Build the interface
446
+ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css, fill_height=True) as demo:
447
+ gr.Markdown("# 🚀 GPT-OSS-20B with PDF RAG System")
448
+ gr.Markdown("Enhanced AI assistant with document-based context understanding")
449
 
450
  with gr.Row():
451
+ # Left sidebar for RAG controls
452
  with gr.Column(scale=1):
453
  with gr.Group(elem_classes="main-container"):
454
+ gr.Markdown("### 📚 Document RAG Settings")
455
+
456
+ pdf_upload = gr.File(
457
+ label="Upload PDF",
458
+ file_types=[".pdf"],
459
+ type="filepath"
460
  )
461
 
462
+ upload_status = gr.HTML(
463
+ value="<div class='pdf-status pdf-info'>📤 Upload a PDF to enable document-based answers</div>"
 
 
 
 
464
  )
465
 
466
+ document_list = gr.CheckboxGroup(
467
+ choices=[],
468
+ label="📄 Select Documents",
469
+ info="Choose documents to use as context"
470
+ )
471
 
472
+ clear_btn = gr.Button("🗑️ Clear All Documents", size="sm", variant="secondary")
 
473
 
474
+ enable_rag = gr.Checkbox(
475
+ label=" Enable RAG",
476
+ value=False,
477
+ info="Use documents for context-aware responses"
478
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
 
480
+ top_k_slider = gr.Slider(
481
+ minimum=1,
482
+ maximum=5,
483
+ value=3,
484
+ step=1,
485
+ label="Context Chunks",
486
+ info="Number of document chunks to use"
487
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
 
489
+ # RAG status display
490
  rag_status = gr.HTML(
491
  value="<div class='pdf-status pdf-info'>🔍 RAG: <strong>Disabled</strong></div>"
492
  )
493
 
 
494
  context_preview = gr.HTML(value="", visible=False)
495
+
496
+ # Right side for chat interface
497
+ with gr.Column(scale=3):
498
+ with gr.Group(elem_classes="main-container"):
499
+ # Create ChatInterface with custom function
500
+ chat_interface = gr.ChatInterface(
501
+ fn=generate_response,
502
+ additional_inputs=[
503
+ gr.Slider(label="Max new tokens", minimum=64, maximum=4096, step=1, value=2048),
504
+ gr.Textbox(
505
+ label="System Prompt",
506
+ value="You are a helpful assistant. Reasoning: medium",
507
+ lines=4,
508
+ placeholder="Change system prompt"
509
+ ),
510
+ gr.Slider(label="Temperature", minimum=0.1, maximum=2.0, step=0.1, value=0.7),
511
+ gr.Slider(label="Top-p", minimum=0.05, maximum=1.0, step=0.05, value=0.9),
512
+ gr.Slider(label="Top-k", minimum=1, maximum=100, step=1, value=50),
513
+ gr.Slider(label="Repetition Penalty", minimum=1.0, maximum=2.0, step=0.05, value=1.0)
514
+ ],
515
+ examples=[
516
+ [{"text": "Explain Newton laws clearly and concisely"}],
517
+ [{"text": "Write a Python function to calculate the Fibonacci sequence"}],
518
+ [{"text": "What are the benefits of open weight AI models"}],
519
+ ],
520
+ cache_examples=False,
521
+ type="messages",
522
+ description="""Chat with GPT-OSS-20B. Upload PDFs to enhance responses with document context.
523
+ Click to view thinking process (default is on).""",
524
+ textbox=gr.Textbox(
525
+ label="Query Input",
526
+ placeholder="Type your prompt (RAG will be applied if enabled)"
527
+ ),
528
+ stop_btn="Stop Generation",
529
+ multimodal=False
530
+ )
531
 
532
+ # Event handlers
533
  pdf_upload.upload(
534
  fn=upload_pdf,
535
  inputs=[pdf_upload],
536
+ outputs=[upload_status, document_list]
537
  )
538
 
 
539
  clear_btn.click(
540
  fn=clear_documents,
541
+ outputs=[upload_status, document_list]
542
  )
543
 
544
+ # Update RAG settings when changed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  enable_rag.change(
546
+ fn=update_rag_settings,
547
+ inputs=[enable_rag, document_list, top_k_slider],
548
  outputs=[rag_status, context_preview]
549
  )
550
 
551
  document_list.change(
552
+ fn=update_rag_settings,
553
+ inputs=[enable_rag, document_list, top_k_slider],
554
  outputs=[rag_status, context_preview]
555
  )
556
 
557
+ top_k_slider.change(
558
+ fn=update_rag_settings,
559
+ inputs=[enable_rag, document_list, top_k_slider],
560
  outputs=[rag_status, context_preview]
561
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
562
 
563
+ if __name__ == "__main__":
564
+ demo.launch(share=True)