cstr commited on
Commit
d89b36d
·
verified ·
1 Parent(s): 4421b19

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +585 -221
app.py CHANGED
@@ -22,6 +22,16 @@ CONTEXT_SIZES = {
22
  "200K": 200000
23
  }
24
 
 
 
 
 
 
 
 
 
 
 
25
  class ModelRegistry:
26
  def __init__(self):
27
  self.hf_models = {
@@ -148,49 +158,61 @@ def build_prompts(snippets: List[str], prompt_instruction: str, custom_prompt: O
148
 
149
  return "\n\n".join(prompts)
150
 
151
- def send_to_model(prompt, model_selection, hf_model_choice, hf_custom_model, hf_api_key,
152
- groq_model_choice, groq_api_key, openai_api_key):
153
- """Send prompt to selected model"""
154
  try:
155
- if model_selection == "HuggingFace Inference":
156
- if not hf_api_key:
157
- return "HuggingFace API key required.", []
158
-
159
- model_id = hf_custom_model if hf_model_choice == "Custom Model" else model_registry.hf_models[hf_model_choice]
160
- summary = send_to_hf_inference(prompt, model_id, hf_api_key)
161
-
162
- elif model_selection == "Groq API":
163
- if not groq_api_key:
164
- return "Groq API key required.", []
165
-
166
- summary = send_to_groq(prompt, groq_model_choice, groq_api_key)
167
-
168
- elif model_selection == "OpenAI ChatGPT":
169
- if not openai_api_key:
170
- return "OpenAI API key required.", []
171
- # Implement OpenAI API call here
172
-
173
- # Save summary for download
174
- with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as summary_file:
175
- summary_file.write(summary)
176
-
177
- return summary, [summary_file.name]
178
-
179
  except Exception as e:
180
- logging.error(f"Error sending to model: {e}")
181
- return f"Error sending to model: {str(e)}", []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
 
183
  def send_to_hf_inference(prompt: str, model_name: str, api_key: str) -> str:
184
  """Send prompt to HuggingFace using Inference API"""
185
  try:
186
- client = InferenceClient(api_key=api_key)
187
- messages = [{"role": "user", "content": prompt}]
188
- completion = client.chat.completions.create(
189
  model=model_name,
190
- messages=messages,
191
- max_tokens=500
 
 
192
  )
193
- return completion.choices[0].message.content
194
  except Exception as e:
195
  logging.error(f"Error with HF inference: {e}")
196
  return f"Error with HF inference: {e}"
@@ -204,40 +226,77 @@ def send_to_groq(prompt: str, model_name: str, api_key: str) -> str:
204
  }
205
  data = {
206
  "model": model_name,
207
- "messages": [{"role": "user", "content": prompt}]
 
 
208
  }
209
  response = requests.post(
210
  "https://api.groq.com/openai/v1/chat/completions",
211
  headers=headers,
212
  json=data
213
  )
214
- return response.json()["choices"][0]["message"]["content"]
 
 
 
 
 
 
 
215
  except Exception as e:
216
  logging.error(f"Error with Groq API: {e}")
217
  return f"Error with Groq API: {e}"
218
 
219
- def copy_to_clipboard(text: str) -> str:
220
- """Copy text to clipboard using JavaScript"""
221
- return """
222
- navigator.clipboard.writeText(text)
223
- .then(() => gradioApp().querySelector('#progress_status').value = 'Copied to clipboard!')
224
- .catch(() => gradioApp().querySelector('#progress_status').value = 'Failed to copy');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  """
226
 
227
- def open_chatgpt() -> None:
 
 
 
 
228
  """Open ChatGPT in new browser tab"""
229
  return """window.open('https://chat.openai.com/', '_blank');"""
230
 
231
- def process_pdf(pdf, fmt, ctx_size, snippet_num, prompt):
232
- """Generate prompt from PDF without model processing"""
233
  try:
234
  if not pdf:
235
- return "Please upload a PDF file.", "", []
236
 
237
  # Extract text
238
  text = extract_text_from_pdf(pdf.name)
239
  if text.startswith("Error"):
240
- return text, "", []
241
 
242
  # Format content
243
  formatted_text = format_content(text, fmt)
@@ -245,164 +304,254 @@ def process_pdf(pdf, fmt, ctx_size, snippet_num, prompt):
245
  # Split into snippets
246
  snippets = split_into_snippets(formatted_text, ctx_size)
247
 
248
- # Build prompts
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  default_prompt = "Summarize the following text:"
250
- full_prompt = build_prompts(snippets, default_prompt, prompt, snippet_num)
251
 
252
- if isinstance(full_prompt, str) and full_prompt.startswith("Error"):
253
- return full_prompt, "", []
 
 
 
 
 
 
 
 
 
 
 
254
 
255
  # Save prompt for download
256
  with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as prompt_file:
257
- prompt_file.write(full_prompt)
258
-
259
- return "Prompt generated!", full_prompt, [prompt_file.name]
260
 
261
  except Exception as e:
262
- logging.error(f"Error processing PDF: {e}")
263
- return f"Error processing PDF: {str(e)}", "", []
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
  # Main Interface
266
  with gr.Blocks(theme=gr.themes.Default()) as demo:
267
- # Store context size value
268
- context_size_value = gr.State(value=32000)
 
269
 
270
  # Header
271
  gr.Markdown("# 📄 Smart PDF Summarizer")
272
  gr.Markdown("Upload a PDF document and get AI-powered summaries using various AI models.")
273
 
274
- # Main Content
275
- with gr.Row():
276
- # Left Column - Input Options
277
- with gr.Column(scale=1):
278
- pdf_input = gr.File(
279
- label="📁 Upload PDF",
280
- file_types=[".pdf"]
281
- )
282
-
283
- with gr.Row():
284
- format_type = gr.Radio(
285
- choices=["txt", "md", "html"],
286
- value="txt",
287
- label="📝 Output Format"
288
- )
289
-
290
- # First define the slider
291
- context_size = gr.Slider(
292
- minimum=1000,
293
- maximum=200000,
294
- step=1000,
295
- value=32000,
296
- label="📏 Custom Context Size"
297
- )
298
-
299
- # Then define the context size buttons
300
- gr.Markdown("### Context Size")
301
  with gr.Row():
302
- for size_name, size_value in CONTEXT_SIZES.items():
303
- gr.Button(
304
- size_name,
305
- size="sm", # Make buttons smaller
306
- scale=1 # Equal scaling
307
- ).click(
308
- lambda v=size_value: v,
309
- None,
310
- context_size
311
  )
312
-
313
- context_size = gr.Slider(
314
- minimum=1000,
315
- maximum=200000,
316
- step=1000,
317
- value=32000,
318
- label="📏 Custom Context Size"
319
- )
320
-
321
- snippet_number = gr.Number(
322
- label="🔢 Snippet Number",
323
- value=1,
324
- precision=0
325
- )
326
-
327
- custom_prompt = gr.Textbox(
328
- label="✍️ Custom Prompt",
329
- placeholder="Enter your custom prompt here...",
330
- lines=2
331
- )
332
-
333
- model_choice = gr.Radio(
334
- choices=["OpenAI ChatGPT", "HuggingFace Inference", "Groq API"],
335
- value="OpenAI ChatGPT",
336
- label="🤖 Model Selection"
337
- )
338
-
339
- with gr.Column(visible=False) as hf_options:
340
- hf_model = gr.Dropdown(
341
- choices=list(model_registry.hf_models.keys()),
342
- label="🔧 HuggingFace Model",
343
- value="Phi-3 Mini 128k"
344
- )
345
- hf_custom_model = gr.Textbox(
346
- label="Custom Model ID",
347
- placeholder="Enter custom model ID...",
348
- visible=False
349
- )
350
- hf_api_key = gr.Textbox(
351
- label="🔑 HuggingFace API Key",
352
- type="password"
353
- )
354
-
355
- with gr.Column(visible=False) as groq_options:
356
- groq_model = gr.Dropdown(
357
- choices=list(model_registry.groq_models.keys()),
358
- label="🔧 Groq Model",
359
- value=list(model_registry.groq_models.keys())[0]
360
- )
361
- groq_refresh_btn = gr.Button("🔄 Refresh Models")
362
- groq_api_key = gr.Textbox(
363
- label="🔑 Groq API Key",
364
- type="password"
365
- )
366
 
367
- # In the UI section, add OpenAI API key input:
368
- with gr.Column(visible=False) as openai_options:
369
- openai_api_key = gr.Textbox(
370
- label="🔑 OpenAI API Key",
371
- type="password"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  )
373
-
374
- # Right Column - Output
375
- with gr.Column(scale=1):
376
- process_button = gr.Button("🚀 Process PDF", variant="primary")
377
-
378
- progress_status = gr.Textbox(
379
- label="📊 Progress",
380
- interactive=False
381
- )
382
-
383
- generated_prompt = gr.Textbox(
384
- label="📋 Generated Prompt",
385
- lines=10
386
- )
387
-
388
  with gr.Row():
389
- copy_prompt_button = gr.Button("📋 Copy Prompt")
390
- open_chatgpt_button = gr.Button("🌐 Open ChatGPT")
391
-
392
- summary_output = gr.Textbox(
393
- label="📝 Summary",
394
- lines=15
395
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
 
397
- with gr.Row():
398
- copy_summary_button = gr.Button("📋 Copy Summary")
399
- download_files = gr.Files(
400
- label="📥 Download Files"
401
- )
402
 
403
  # Event Handlers
404
- def update_context_size(size):
405
- return gr.update(value=size)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
 
407
  def toggle_model_options(choice):
408
  return (
@@ -417,12 +566,211 @@ with gr.Blocks(theme=gr.themes.Default()) as demo:
417
 
418
  def toggle_custom_model(model_name):
419
  return gr.update(visible=model_name == "Custom Model")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
 
421
- # Connect event handlers
422
  model_choice.change(
423
- toggle_model_options,
424
  inputs=[model_choice],
425
- outputs=[hf_options, groq_options, openai_options]
 
 
 
 
 
426
  )
427
 
428
  hf_model.change(
@@ -431,30 +779,58 @@ with gr.Blocks(theme=gr.themes.Default()) as demo:
431
  outputs=[hf_custom_model]
432
  )
433
 
434
- groq_refresh_btn.click(
435
- refresh_groq_models_list,
436
- outputs=[groq_model]
 
437
  )
438
 
439
- process_button.click(
440
- process_pdf,
441
- inputs=[
442
- pdf_input,
443
- format_type,
444
- context_size,
445
- snippet_number,
446
- custom_prompt
447
- ],
448
- outputs=[
449
- progress_status,
450
- generated_prompt,
451
- download_files
452
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
  )
454
 
455
- # Add a new button for sending to model
456
- send_button = gr.Button("🚀 Send to Model", variant="primary")
457
- send_button.click(
458
  send_to_model,
459
  inputs=[
460
  generated_prompt,
@@ -472,21 +848,9 @@ with gr.Blocks(theme=gr.themes.Default()) as demo:
472
  ]
473
  )
474
 
475
- copy_prompt_button.click(
476
- copy_to_clipboard,
477
- inputs=[generated_prompt],
478
- outputs=[progress_status]
479
- )
480
-
481
- copy_summary_button.click(
482
- copy_to_clipboard,
483
- inputs=[summary_output],
484
- outputs=[progress_status]
485
- )
486
-
487
- open_chatgpt_button.click(
488
- open_chatgpt,
489
- outputs=[progress_status]
490
  )
491
 
492
  # Instructions
 
22
  "200K": 200000
23
  }
24
 
25
+ MODEL_CONTEXT_SIZES = {
26
+ "OpenAI ChatGPT": 4096,
27
+ "HuggingFace Inference": 4096,
28
+ "Groq API": {
29
+ "llama-3.1-70b-versatile": 32768,
30
+ "mixtral-8x7b-32768": 32768,
31
+ "llama-3.1-8b-instant": 8192
32
+ }
33
+ }
34
+
35
  class ModelRegistry:
36
  def __init__(self):
37
  self.hf_models = {
 
158
 
159
  return "\n\n".join(prompts)
160
 
161
+ def send_to_model(*args, **kwargs):
 
 
162
  try:
163
+ with gr.Progress() as progress:
164
+ progress(0, "Preparing to send to model...")
165
+ result = send_to_model_impl(*args, **kwargs)
166
+ progress(1, "Complete!")
167
+ return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  except Exception as e:
169
+ return f"Error: {str(e)}", None
170
+
171
+ def send_to_model_impl(prompt, model_selection, hf_model_choice, hf_custom_model, hf_api_key,
172
+ groq_model_choice, groq_api_key, openai_api_key):
173
+ """Implementation of send to model functionality"""
174
+ if model_selection == "HuggingFace Inference":
175
+ if not hf_api_key:
176
+ return "HuggingFace API key required.", []
177
+
178
+ model_id = hf_custom_model if hf_model_choice == "Custom Model" else model_registry.hf_models[hf_model_choice]
179
+ summary = send_to_hf_inference(prompt, model_id, hf_api_key)
180
+
181
+ elif model_selection == "Groq API":
182
+ if not groq_api_key:
183
+ return "Groq API key required.", []
184
+ summary = send_to_groq(prompt, groq_model_choice, groq_api_key)
185
+
186
+ elif model_selection == "OpenAI ChatGPT":
187
+ if not openai_api_key:
188
+ return "OpenAI API key required.", []
189
+ summary = send_to_openai(prompt, openai_api_key)
190
+
191
+ else:
192
+ return "Invalid model selection.", []
193
+
194
+ if summary.startswith("Error"):
195
+ return summary, []
196
+
197
+ # Save summary for download
198
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as f:
199
+ f.write(summary)
200
+
201
+ return summary, [f.name]
202
 
203
  def send_to_hf_inference(prompt: str, model_name: str, api_key: str) -> str:
204
  """Send prompt to HuggingFace using Inference API"""
205
  try:
206
+ client = InferenceClient(token=api_key)
207
+ response = client.text_generation(
208
+ prompt,
209
  model=model_name,
210
+ max_new_tokens=500,
211
+ temperature=0.7,
212
+ details=True, # Get full response details
213
+ stream=False # Don't stream output
214
  )
215
+ return response.generated_text # Return just the generated text
216
  except Exception as e:
217
  logging.error(f"Error with HF inference: {e}")
218
  return f"Error with HF inference: {e}"
 
226
  }
227
  data = {
228
  "model": model_name,
229
+ "messages": [{"role": "user", "content": prompt}],
230
+ "temperature": 0.7,
231
+ "max_tokens": 500
232
  }
233
  response = requests.post(
234
  "https://api.groq.com/openai/v1/chat/completions",
235
  headers=headers,
236
  json=data
237
  )
238
+ if response.status_code != 200:
239
+ return f"Error: Groq API returned status {response.status_code}"
240
+
241
+ response_json = response.json()
242
+ if "choices" not in response_json or not response_json["choices"]:
243
+ return "Error: No response from Groq API"
244
+
245
+ return response_json["choices"][0]["message"]["content"]
246
  except Exception as e:
247
  logging.error(f"Error with Groq API: {e}")
248
  return f"Error with Groq API: {e}"
249
 
250
+ def send_to_openai(prompt: str, api_key: str) -> str:
251
+ """Send prompt to OpenAI API"""
252
+ try:
253
+ import openai
254
+ openai.api_key = api_key
255
+
256
+ response = openai.ChatCompletion.create(
257
+ model="gpt-3.5-turbo",
258
+ messages=[{"role": "user", "content": prompt}],
259
+ temperature=0.7,
260
+ max_tokens=500
261
+ )
262
+
263
+ return response.choices[0].message.content
264
+ except Exception as e:
265
+ logging.error(f"Error with OpenAI API: {e}")
266
+ return f"Error with OpenAI API: {e}"
267
+
268
+ def copy_to_clipboard(element_id: str) -> str:
269
+ return f"""
270
+ () => {{
271
+ try {{
272
+ const text = document.querySelector('#{element_id} textarea').value;
273
+ navigator.clipboard.writeText(text);
274
+ return "Copied to clipboard!";
275
+ }} catch (e) {{
276
+ console.error(e);
277
+ return "Failed to copy to clipboard";
278
+ }}
279
+ }}
280
  """
281
 
282
+ def open_chatgpt_old() -> str:
283
+ webbrowser.open_new_tab('https://chat.openai.com')
284
+ return "Opening ChatGPT in new tab"
285
+
286
+ def open_chatgpt() -> str:
287
  """Open ChatGPT in new browser tab"""
288
  return """window.open('https://chat.openai.com/', '_blank');"""
289
 
290
+ def process_pdf(pdf, fmt, ctx_size):
291
+ """Process PDF and return text and snippets"""
292
  try:
293
  if not pdf:
294
+ return "Please upload a PDF file.", "", [], None
295
 
296
  # Extract text
297
  text = extract_text_from_pdf(pdf.name)
298
  if text.startswith("Error"):
299
+ return text, "", [], None
300
 
301
  # Format content
302
  formatted_text = format_content(text, fmt)
 
304
  # Split into snippets
305
  snippets = split_into_snippets(formatted_text, ctx_size)
306
 
307
+ # Save full text for download
308
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as text_file:
309
+ text_file.write(formatted_text)
310
+
311
+ snippet_choices = [f"Snippet {i+1} of {len(snippets)}" for i in range(len(snippets))]
312
+
313
+ return (
314
+ "PDF processed successfully!",
315
+ formatted_text,
316
+ snippets,
317
+ snippet_choices,
318
+ [text_file.name]
319
+ )
320
+
321
+ except Exception as e:
322
+ logging.error(f"Error processing PDF: {e}")
323
+ return f"Error processing PDF: {str(e)}", "", [], None
324
+
325
+ def generate_prompt(text, template, snippet_idx=None):
326
+ """Generate prompt from text or selected snippet"""
327
+ try:
328
+ if not text:
329
+ return "No text available.", "", None
330
+
331
  default_prompt = "Summarize the following text:"
332
+ prompt_template = template if template else default_prompt
333
 
334
+ if isinstance(text, list):
335
+ # If text is list of snippets
336
+ if snippet_idx is not None:
337
+ if 0 <= snippet_idx < len(text):
338
+ content = text[snippet_idx]
339
+ else:
340
+ return "Invalid snippet index.", "", None
341
+ else:
342
+ content = "\n\n".join(text)
343
+ else:
344
+ content = text
345
+
346
+ prompt = f"{prompt_template}\n---\n{content}\n---"
347
 
348
  # Save prompt for download
349
  with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as prompt_file:
350
+ prompt_file.write(prompt)
351
+
352
+ return "Prompt generated!", prompt, [prompt_file.name]
353
 
354
  except Exception as e:
355
+ logging.error(f"Error generating prompt: {e}")
356
+ return f"Error generating prompt: {str(e)}", "", None
357
+
358
+ def download_file(content: str, prefix: str = "file") -> List[str]:
359
+ """Create a downloadable file with content and better error handling"""
360
+ if not content:
361
+ return []
362
+ try:
363
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt', prefix=prefix) as f:
364
+ f.write(content)
365
+ return [f.name]
366
+ except Exception as e:
367
+ logging.error(f"Error creating download file: {e}")
368
+ return []
369
 
370
  # Main Interface
371
  with gr.Blocks(theme=gr.themes.Default()) as demo:
372
+ # State variables
373
+ pdf_content = gr.State("")
374
+ snippets = gr.State([])
375
 
376
  # Header
377
  gr.Markdown("# 📄 Smart PDF Summarizer")
378
  gr.Markdown("Upload a PDF document and get AI-powered summaries using various AI models.")
379
 
380
+ with gr.Tabs() as tabs:
381
+ # Tab 1: PDF Processing
382
+ with gr.Tab("1️⃣ PDF Processing"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  with gr.Row():
384
+ with gr.Column(scale=1):
385
+ pdf_input = gr.File(
386
+ label="📁 Upload PDF",
387
+ file_types=[".pdf"]
 
 
 
 
 
388
  )
389
+
390
+ format_type = gr.Radio(
391
+ choices=["txt", "md", "html"],
392
+ value="txt",
393
+ label="📝 Output Format"
394
+ )
395
+
396
+ context_size = gr.Slider(
397
+ minimum=1000,
398
+ maximum=200000,
399
+ step=1000,
400
+ value=4096,
401
+ label="Context Size"
402
+ )
403
+
404
+ with gr.Row():
405
+ for size_name, size_value in CONTEXT_SIZES.items():
406
+ gr.Button(
407
+ size_name,
408
+ size="sm",
409
+ scale=1
410
+ ).click(
411
+ lambda v=size_value: v, # Simplified
412
+ None,
413
+ context_size
414
+ )
415
+
416
+ process_button = gr.Button("🔍 Process PDF", variant="primary")
417
+
418
+ with gr.Column(scale=1):
419
+ progress_status = gr.Textbox(
420
+ label="Status",
421
+ interactive=False,
422
+ show_label=True,
423
+ visible=True # Ensure error messages are always visible
424
+ )
425
+ processed_text = gr.Textbox(
426
+ label="Processed Text",
427
+ lines=10,
428
+ max_lines=50,
429
+ show_copy_button=True
430
+ )
431
+ download_full_text = gr.Button("📥 Download Full Text")
 
 
 
 
 
 
 
 
 
 
 
432
 
433
+ # Tab 2: Snippet Selection
434
+ with gr.Tab("2️⃣ Snippet Selection"):
435
+ with gr.Row():
436
+ with gr.Column(scale=1):
437
+ snippet_selector = gr.Dropdown(
438
+ label="Select Snippet",
439
+ choices=[],
440
+ interactive=True
441
+ )
442
+
443
+ custom_prompt = gr.Textbox(
444
+ label="✍️ Custom Prompt Template",
445
+ placeholder="Enter your custom prompt here...",
446
+ lines=2
447
+ )
448
+
449
+ generate_prompt_btn = gr.Button("Generate Prompt", variant="primary")
450
+
451
+ with gr.Column(scale=1):
452
+ generated_prompt = gr.Textbox(
453
+ label="📋 Generated Prompt",
454
+ lines=10,
455
+ max_lines=50,
456
+ show_copy_button=True,
457
+ elem_id="generated_prompt" # Add this
458
  )
459
+
460
+ with gr.Row():
461
+ copy_prompt_button = gr.Button("📋 Copy Prompt")
462
+ download_prompt = gr.Button("📥 Download Prompt")
463
+ download_snippet = gr.Button("📥 Download Selected Snippet")
464
+
465
+ # Tab 3: Model Processing
466
+ with gr.Tab("3️⃣ Model Processing"):
 
 
 
 
 
 
 
467
  with gr.Row():
468
+ with gr.Column(scale=1):
469
+ model_choice = gr.Radio(
470
+ choices=["OpenAI ChatGPT", "HuggingFace Inference", "Groq API"],
471
+ value="OpenAI ChatGPT",
472
+ label="🤖 Model Selection"
473
+ )
474
+
475
+ with gr.Column(visible=False) as openai_options:
476
+ openai_api_key = gr.Textbox(
477
+ label="🔑 OpenAI API Key",
478
+ type="password"
479
+ )
480
+
481
+ with gr.Column(visible=False) as hf_options:
482
+ hf_model = gr.Dropdown(
483
+ choices=list(model_registry.hf_models.keys()),
484
+ label="🔧 HuggingFace Model",
485
+ value="Phi-3 Mini 128k"
486
+ )
487
+ hf_custom_model = gr.Textbox(
488
+ label="Custom Model ID",
489
+ visible=False
490
+ )
491
+ hf_api_key = gr.Textbox(
492
+ label="🔑 HuggingFace API Key",
493
+ type="password"
494
+ )
495
+
496
+ with gr.Column(visible=False) as groq_options:
497
+ groq_model = gr.Dropdown(
498
+ choices=list(model_registry.groq_models.keys()),
499
+ label="🔧 Groq Model"
500
+ )
501
+ groq_refresh_btn = gr.Button("🔄 Refresh Models")
502
+ groq_api_key = gr.Textbox(
503
+ label="🔑 Groq API Key",
504
+ type="password"
505
+ )
506
+
507
+ send_to_model_btn = gr.Button("🚀 Send to Model", variant="primary")
508
+ open_chatgpt_button = gr.Button("🌐 Open ChatGPT")
509
+
510
+ with gr.Column(scale=1):
511
+ summary_output = gr.Textbox(
512
+ label="📝 Summary",
513
+ lines=15,
514
+ max_lines=50,
515
+ show_copy_button=True,
516
+ elem_id="summary_output" # Add this
517
+ )
518
+
519
+ with gr.Row():
520
+ copy_summary_button = gr.Button("📋 Copy Summary")
521
+ download_summary = gr.Button("📥 Download Summary")
522
 
523
+ # Hidden components for file handling
524
+ download_files = gr.Files(label="📥 Downloads", visible=False)
 
 
 
525
 
526
  # Event Handlers
527
+ def update_context_size(size: int) -> None:
528
+ """Update context size slider with validation"""
529
+ if not isinstance(size, (int, float)):
530
+ size = 4096 # Default size
531
+ return gr.update(value=int(size))
532
+
533
+ def get_model_context_size(choice: str, groq_model: str = None) -> int:
534
+ """Get context size for model with better defaults"""
535
+ if choice == "Groq API" and groq_model:
536
+ return MODEL_CONTEXT_SIZES["Groq API"].get(groq_model, 4096)
537
+ elif choice == "OpenAI ChatGPT":
538
+ return 4096
539
+ elif choice == "HuggingFace Inference":
540
+ return 4096
541
+ return 32000 # Safe default
542
+
543
+ def update_snippet_choices(snippets_list: List[str]) -> List[str]:
544
+ """Create formatted snippet choices"""
545
+ return [f"Snippet {i+1} of {len(snippets_list)}" for i in range(len(snippets_list))]
546
+
547
+ def get_snippet_index(choice: str) -> int:
548
+ """Extract snippet index from choice string"""
549
+ if not choice:
550
+ return 0
551
+ try:
552
+ return int(choice.split()[1]) - 1
553
+ except:
554
+ return 0
555
 
556
  def toggle_model_options(choice):
557
  return (
 
566
 
567
  def toggle_custom_model(model_name):
568
  return gr.update(visible=model_name == "Custom Model")
569
+
570
+ def handle_model_change(choice):
571
+ """Handle model selection change"""
572
+ return (
573
+ gr.update(visible=choice == "HuggingFace Inference"),
574
+ gr.update(visible=choice == "Groq API"),
575
+ gr.update(visible=choice == "OpenAI ChatGPT"),
576
+ update_context_size(choice)
577
+ )
578
+
579
+ def handle_groq_model_change(model_name):
580
+ """Handle Groq model selection change"""
581
+ return update_context_size("Groq API", model_name)
582
+
583
+ def handle_model_selection(choice):
584
+ """Handle model selection and update UI"""
585
+ ctx_size = get_model_context_size(choice)
586
+ return {
587
+ hf_options: gr.update(visible=choice == "HuggingFace Inference"),
588
+ groq_options: gr.update(visible=choice == "Groq API"),
589
+ openai_options: gr.update(visible=choice == "OpenAI ChatGPT"),
590
+ context_size: gr.update(value=ctx_size)
591
+ }
592
+
593
+ # PDF Processing Handlers
594
+ def handle_pdf_process(pdf, fmt, ctx_size):
595
+ """Process PDF and update UI state"""
596
+ if not pdf:
597
+ return {
598
+ progress_status: "Please upload a PDF file.",
599
+ processed_text: "",
600
+ pdf_content: "",
601
+ snippets: [],
602
+ snippet_selector: gr.update(choices=[], value=None),
603
+ download_files: None
604
+ }
605
+
606
+ try:
607
+ # Extract and format text
608
+ text = extract_text_from_pdf(pdf.name)
609
+ if text.startswith("Error"):
610
+ return {
611
+ progress_status: text,
612
+ processed_text: "",
613
+ pdf_content: "",
614
+ snippets: [],
615
+ snippet_selector: gr.update(choices=[], value=None),
616
+ download_files: None
617
+ }
618
+
619
+ formatted_text = format_content(text, fmt)
620
+ snippets_list = split_into_snippets(formatted_text, ctx_size)
621
+
622
+ # Create downloadable full text
623
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as f:
624
+ f.write(formatted_text)
625
+ download_file = f.name
626
+
627
+ return {
628
+ progress_status: f"PDF processed successfully! Generated {len(snippets_list)} snippets.",
629
+ processed_text: formatted_text,
630
+ pdf_content: formatted_text,
631
+ snippets: snippets_list,
632
+ snippet_selector: gr.update(choices=update_snippet_choices(snippets_list), value="Snippet 1 of " + str(len(snippets_list))),
633
+ download_files: [download_file]
634
+ }
635
+
636
+ except Exception as e:
637
+ error_msg = f"Error processing PDF: {str(e)}"
638
+ logging.error(error_msg)
639
+ return {
640
+ progress_status: error_msg,
641
+ processed_text: "",
642
+ pdf_content: "",
643
+ snippets: [],
644
+ snippet_selector: gr.update(choices=[], value=None),
645
+ download_files: None
646
+ }
647
+
648
+ def handle_snippet_selection(choice, snippets_list):
649
+ """Handle snippet selection and update prompt"""
650
+ if not snippets_list:
651
+ return {
652
+ progress_status: "No snippets available.",
653
+ generated_prompt: "",
654
+ download_files: None
655
+ }
656
+
657
+ try:
658
+ idx = get_snippet_index(choice)
659
+ selected_snippet = snippets_list[idx]
660
+
661
+ # Create downloadable snippet
662
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as f:
663
+ f.write(selected_snippet)
664
+
665
+ return {
666
+ progress_status: f"Selected snippet {idx + 1}",
667
+ generated_prompt: selected_snippet,
668
+ download_files: [f.name]
669
+ }
670
+
671
+ except Exception as e:
672
+ error_msg = f"Error selecting snippet: {str(e)}"
673
+ logging.error(error_msg)
674
+ return {
675
+ progress_status: error_msg,
676
+ generated_prompt: "",
677
+ download_files: None
678
+ }
679
+
680
+ # Copy button handlers
681
+ def copy_text_js(element_id: str) -> str:
682
+ return f"""
683
+ () => {{
684
+ const text = document.querySelector('#{element_id} textarea').value;
685
+ navigator.clipboard.writeText(text);
686
+ return "Copied to clipboard!";
687
+ }}
688
+ """
689
+
690
+ def handle_prompt_generation(snippet_text, template, snippet_choice, snippets_list):
691
+ """Generate prompt from selected snippet"""
692
+ if not snippet_text or not snippets_list:
693
+ return {
694
+ progress_status: "No text available for prompt generation.",
695
+ generated_prompt: "",
696
+ download_files: None
697
+ }
698
+
699
+ try:
700
+ idx = get_snippet_index(snippet_choice)
701
+ prompt = generate_prompt(snippets_list[idx], template or "Summarize the following text:")
702
+
703
+ # Create downloadable prompt
704
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as f:
705
+ f.write(prompt)
706
+
707
+ return {
708
+ progress_status: "Prompt generated successfully!",
709
+ generated_prompt: prompt,
710
+ download_files: [f.name]
711
+ }
712
+
713
+ except Exception as e:
714
+ error_msg = f"Error generating prompt: {str(e)}"
715
+ logging.error(error_msg)
716
+ return {
717
+ progress_status: error_msg,
718
+ generated_prompt: "",
719
+ download_files: None
720
+ }
721
+
722
+ def handle_copy_action(text):
723
+ """Handle copy to clipboard action"""
724
+ return {
725
+ progress_status: gr.update(value="Text copied to clipboard!", visible=True)
726
+ }
727
+
728
+ # Connect all event handlers
729
+ # Core event handlers
730
+ process_button.click(
731
+ handle_pdf_process,
732
+ inputs=[pdf_input, format_type, context_size],
733
+ outputs=dict(
734
+ progress_status=progress_status,
735
+ processed_text=processed_text,
736
+ pdf_content=pdf_content,
737
+ snippets=snippets,
738
+ snippet_selector=snippet_selector,
739
+ download_files=download_files
740
+ )
741
+ )
742
+
743
+ generate_prompt_btn.click(
744
+ handle_prompt_generation,
745
+ inputs=[generated_prompt, custom_prompt, snippet_selector, snippets],
746
+ outputs={
747
+ progress_status: progress_status,
748
+ generated_prompt: generated_prompt,
749
+ download_files: download_files
750
+ }
751
+ )
752
+
753
+ # Snippet handling
754
+ snippet_selector.change(
755
+ handle_snippet_selection,
756
+ inputs=[snippet_selector, snippets],
757
+ outputs={
758
+ progress_status: progress_status,
759
+ generated_prompt: generated_prompt,
760
+ download_files: download_files
761
+ }
762
+ )
763
 
764
+ # Model selection
765
  model_choice.change(
766
+ handle_model_selection,
767
  inputs=[model_choice],
768
+ outputs={
769
+ hf_options: hf_options,
770
+ groq_options: groq_options,
771
+ openai_options: openai_options,
772
+ context_size: context_size
773
+ }
774
  )
775
 
776
  hf_model.change(
 
779
  outputs=[hf_custom_model]
780
  )
781
 
782
+ groq_model.change(
783
+ handle_groq_model_change,
784
+ inputs=[groq_model],
785
+ outputs=[context_size]
786
  )
787
 
788
+ # Context size buttons
789
+ """
790
+ for size_name, size_value in CONTEXT_SIZES.items():
791
+ gr.Button(size_name, size="sm").click(
792
+ update_context_size,
793
+ inputs=[],
794
+ outputs=context_size
795
+ ).success(
796
+ lambda s=size_value: int(s),
797
+ None,
798
+ context_size
799
+ ) """
800
+
801
+ # Download handlers
802
+ for btn, content in [
803
+ (download_full_text, pdf_content),
804
+ (download_snippet, generated_prompt),
805
+ (download_prompt, generated_prompt),
806
+ (download_summary, summary_output)
807
+ ]:
808
+ btn.click(
809
+ lambda x: [x] if x else None,
810
+ inputs=[content],
811
+ outputs=download_files
812
+ )
813
+
814
+ # Copy button handlers
815
+ for btn, elem_id in [
816
+ (copy_prompt_button, "generated_prompt"),
817
+ (copy_summary_button, "summary_output")
818
+ ]:
819
+ btn.click(
820
+ fn=None,
821
+ _js=copy_text_js(elem_id),
822
+ outputs=progress_status
823
+ )
824
+
825
+ # ChatGPT handler
826
+ open_chatgpt_button.click(
827
+ fn=None,
828
+ _js="() => { window.open('https://chat.openai.com/', '_blank'); return 'Opened ChatGPT in new tab'; }",
829
+ outputs=progress_status
830
  )
831
 
832
+ # Model processing
833
+ send_to_model_btn.click(
 
834
  send_to_model,
835
  inputs=[
836
  generated_prompt,
 
848
  ]
849
  )
850
 
851
+ groq_refresh_btn.click(
852
+ refresh_groq_models_list,
853
+ outputs=[groq_model]
 
 
 
 
 
 
 
 
 
 
 
 
854
  )
855
 
856
  # Instructions