siddhartharya commited on
Commit
d8fbcd1
Β·
verified Β·
1 Parent(s): cdd7269

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -234
app.py CHANGED
@@ -2,6 +2,10 @@
2
 
3
  import gradio as gr
4
  from bs4 import BeautifulSoup
 
 
 
 
5
  import asyncio
6
  import aiohttp
7
  import re
@@ -9,9 +13,6 @@ import base64
9
  import logging
10
  import os
11
  import sys
12
- from sentence_transformers import SentenceTransformer
13
- import faiss
14
- import numpy as np
15
 
16
  # Import OpenAI library
17
  import openai
@@ -35,6 +36,7 @@ logger.addHandler(console_handler)
35
  logger.info("Initializing models and variables")
36
  embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
37
  faiss_index = None
 
38
  fetch_cache = {}
39
 
40
  # Define the categories
@@ -232,10 +234,10 @@ def vectorize_and_index(bookmarks):
232
  raise
233
 
234
  # Generate HTML display for bookmarks
235
- def display_bookmarks(bookmarks_list):
236
  logger.info("Generating HTML display for bookmarks")
237
  cards = ''
238
- for i, bookmark in enumerate(bookmarks_list):
239
  index = i + 1 # Start index at 1
240
  status = "❌ Dead Link" if bookmark.get('dead_link') else "βœ… Active"
241
  title = bookmark['title']
@@ -244,20 +246,22 @@ def display_bookmarks(bookmarks_list):
244
  summary = bookmark.get('summary', '')
245
  category = bookmark.get('category', 'Uncategorized')
246
 
247
- # Assign CSS classes based on bookmark status
248
  if bookmark.get('dead_link'):
249
- card_classes = "card dead-link"
 
250
  else:
251
- card_classes = "card active-link"
 
252
 
253
  card_html = f'''
254
- <div class="{card_classes}">
255
  <div class="card-content">
256
- <h3>{index}. {title} {status}</h3>
257
- <p><strong>Category:</strong> {category}</p>
258
- <p><strong>URL:</strong> <a href="{url}" target="_blank">{url}</a></p>
259
- <p><strong>ETag:</strong> {etag}</p>
260
- <p><strong>Summary:</strong> {summary}</p>
261
  </div>
262
  </div>
263
  '''
@@ -266,64 +270,34 @@ def display_bookmarks(bookmarks_list):
266
  return cards
267
 
268
  # Process the uploaded file
269
- def process_uploaded_file(file, state_bookmarks):
 
270
  logger.info("Processing uploaded file")
271
  if file is None:
272
  logger.warning("No file uploaded")
273
- return (
274
- "⚠️ Please upload a bookmarks HTML file.",
275
- "",
276
- [],
277
- "",
278
- state_bookmarks # Return the unchanged state
279
- )
280
-
281
  try:
282
  file_content = file.decode('utf-8')
283
  except UnicodeDecodeError as e:
284
  logger.error(f"Error decoding the file: {e}")
285
- return (
286
- "⚠️ Error decoding the file. Please ensure it's a valid HTML file.",
287
- "",
288
- [],
289
- "",
290
- state_bookmarks # Return the unchanged state
291
- )
292
 
293
  try:
294
  bookmarks = parse_bookmarks(file_content)
295
  except Exception as e:
296
  logger.error(f"Error parsing bookmarks: {e}")
297
- return (
298
- "⚠️ Error parsing the bookmarks HTML file.",
299
- "",
300
- [],
301
- "",
302
- state_bookmarks # Return the unchanged state
303
- )
304
 
305
  if not bookmarks:
306
  logger.warning("No bookmarks found in the uploaded file")
307
- return (
308
- "⚠️ No bookmarks found in the uploaded file.",
309
- "",
310
- [],
311
- "",
312
- state_bookmarks # Return the unchanged state
313
- )
314
 
315
  # Asynchronously fetch bookmark info
316
  try:
317
  asyncio.run(process_bookmarks_async(bookmarks))
318
  except Exception as e:
319
  logger.error(f"Error processing bookmarks asynchronously: {e}")
320
- return (
321
- "⚠️ Error processing bookmarks.",
322
- "",
323
- [],
324
- "",
325
- state_bookmarks # Return the unchanged state
326
- )
327
 
328
  # Generate summaries and assign categories
329
  for bookmark in bookmarks:
@@ -334,123 +308,67 @@ def process_uploaded_file(file, state_bookmarks):
334
  faiss_index, embeddings = vectorize_and_index(bookmarks)
335
  except Exception as e:
336
  logger.error(f"Error building FAISS index: {e}")
337
- return (
338
- "⚠️ Error building search index.",
339
- "",
340
- [],
341
- "",
342
- state_bookmarks # Return the unchanged state
343
- )
344
 
345
  message = f"βœ… Successfully processed {len(bookmarks)} bookmarks."
346
  logger.info(message)
347
- bookmark_html = display_bookmarks(bookmarks)
348
 
349
- # Prepare Manage Bookmarks tab outputs
350
  choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
351
- bookmarks_html_manage = display_bookmarks(bookmarks)
352
 
353
- # Update the shared state
354
- updated_state = bookmarks.copy()
355
 
356
- return (
357
- message,
358
- bookmark_html,
359
- choices,
360
- bookmarks_html_manage,
361
- updated_state # Return the updated state
362
- )
363
 
364
  # Delete selected bookmarks
365
- def delete_selected_bookmarks(selected_indices, state_bookmarks):
 
366
  if not selected_indices:
367
- return "⚠️ No bookmarks selected.", gr.update(choices=[]), ""
368
-
369
- bookmarks = state_bookmarks.copy()
370
- indices = []
371
- for s in selected_indices:
372
- try:
373
- idx = int(s.split('.')[0]) - 1
374
- if 0 <= idx < len(bookmarks):
375
- indices.append(idx)
376
- else:
377
- logger.warning(f"Index out of range: {idx + 1}")
378
- except ValueError:
379
- logger.error(f"Invalid selection format: {s}")
380
-
381
  indices = sorted(indices, reverse=True)
382
  for idx in indices:
383
- logger.info(f"Deleting bookmark at index {idx + 1}")
384
- bookmarks.pop(idx)
385
-
386
  if bookmarks:
387
  faiss_index, embeddings = vectorize_and_index(bookmarks)
388
  else:
389
  faiss_index = None
390
-
391
  message = "πŸ—‘οΈ Selected bookmarks deleted successfully."
392
  logger.info(message)
393
-
394
- # Regenerate HTML display
395
- bookmarks_html = display_bookmarks(bookmarks)
396
-
397
- # Update choices for selection
398
  choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
399
-
400
- # Update the shared state
401
- updated_state = bookmarks.copy()
402
-
403
- return message, gr.update(choices=choices), bookmarks_html
404
 
405
  # Edit category of selected bookmarks
406
- def edit_selected_bookmarks_category(selected_indices, new_category, state_bookmarks):
407
  if not selected_indices:
408
- return (
409
- "⚠️ No bookmarks selected.",
410
- gr.update(choices=[f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(state_bookmarks)]),
411
- display_bookmarks(state_bookmarks)
412
- )
413
-
414
  if not new_category:
415
- return (
416
- "⚠️ No new category selected.",
417
- gr.update(choices=[f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(state_bookmarks)]),
418
- display_bookmarks(state_bookmarks)
419
- )
420
-
421
- bookmarks = state_bookmarks.copy()
422
- indices = []
423
- for s in selected_indices:
424
- try:
425
- idx = int(s.split('.')[0]) - 1
426
- if 0 <= idx < len(bookmarks):
427
- indices.append(idx)
428
- else:
429
- logger.warning(f"Index out of range: {idx + 1}")
430
- except ValueError:
431
- logger.error(f"Invalid selection format: {s}")
432
-
433
  for idx in indices:
434
- bookmarks[idx]['category'] = new_category
435
- logger.info(f"Updated category for bookmark {idx + 1} to {new_category}")
436
-
437
  message = "✏️ Category updated for selected bookmarks."
438
  logger.info(message)
439
-
440
- # Regenerate HTML display
441
- bookmarks_html = display_bookmarks(bookmarks)
442
-
443
- # Update choices for selection
444
  choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
445
-
446
- # Update the shared state
447
- updated_state = bookmarks.copy()
448
-
449
- return message, gr.update(choices=choices), bookmarks_html
450
 
451
  # Export bookmarks to HTML
452
- def export_bookmarks(state_bookmarks):
453
- bookmarks = state_bookmarks
454
  if not bookmarks:
455
  logger.warning("No bookmarks to export")
456
  return "⚠️ No bookmarks to export."
@@ -477,12 +395,11 @@ def export_bookmarks(state_bookmarks):
477
  return "⚠️ Error exporting bookmarks."
478
 
479
  # Chatbot response using Groq Cloud API
480
- def chatbot_response(user_query, state_bookmarks):
481
  if not GROQ_API_KEY:
482
  logger.warning("GROQ_API_KEY not set.")
483
  return "⚠️ API key not set. Please set the GROQ_API_KEY environment variable in the Hugging Face Space settings."
484
 
485
- bookmarks = state_bookmarks
486
  if not bookmarks:
487
  logger.warning("No bookmarks available for chatbot")
488
  return "⚠️ No bookmarks available. Please upload and process your bookmarks first."
@@ -536,172 +453,156 @@ Please identify the most relevant bookmarks that match the user's query. Provide
536
  def build_app():
537
  try:
538
  logger.info("Building Gradio app")
539
- with gr.Blocks(theme=gr.themes.Default(), css="app.css") as demo:
540
- # Shared states
541
- state_bookmarks = gr.State([])
542
- chat_history = gr.State([])
543
-
 
 
 
 
544
  # General Overview
545
  gr.Markdown("""
546
- # πŸ“š SmartMarks - AI Browser Bookmarks Manager
547
-
548
- Welcome to **SmartMarks**, your intelligent assistant for managing browser bookmarks. SmartMarks leverages AI to help you organize, search, and interact with your bookmarks seamlessly. Whether you're looking to categorize your links, retrieve information quickly, or maintain an updated list, SmartMarks has you covered.
549
 
550
- ---
551
 
552
- ## πŸš€ **How to Use SmartMarks**
553
 
554
- SmartMarks is divided into three main sections:
555
 
556
- 1. **πŸ“‚ Upload and Process Bookmarks:** Import your existing bookmarks and let SmartMarks analyze and categorize them for you.
557
- 2. **πŸ’¬ Chat with Bookmarks:** Interact with your bookmarks using natural language queries to find relevant links effortlessly.
558
- 3. **πŸ› οΈ Manage Bookmarks:** View, edit, delete, and export your bookmarks with ease.
559
 
560
- Navigate through the tabs to explore each feature in detail.
561
- """)
 
562
 
563
- # Define Manage Bookmarks components outside the tab for global access
564
- bookmark_selector = gr.CheckboxGroup(label="βœ… Select Bookmarks", choices=[])
565
- bookmark_display_manage = gr.HTML(label="πŸ“„ Manage Bookmarks Display")
566
 
567
  # Upload and Process Bookmarks Tab
568
  with gr.Tab("Upload and Process Bookmarks"):
569
  gr.Markdown("""
570
- ## πŸ“‚ **Upload and Process Bookmarks**
571
 
572
- ### πŸ“ **Steps to Upload and Process:**
573
 
574
- 1. **πŸ”½ Upload Bookmarks File:**
575
- - Click on the **"πŸ“ Upload Bookmarks HTML File"** button.
576
- - Select your browser's exported bookmarks HTML file from your device.
577
 
578
- 2. **βš™οΈ Process Bookmarks:**
579
- - After uploading, click on the **"βš™οΈ Process Bookmarks"** button.
580
- - SmartMarks will parse your bookmarks, fetch additional information, generate summaries, and categorize each link based on predefined categories.
581
 
582
- 3. **πŸ“„ View Processed Bookmarks:**
583
- - Once processing is complete, your bookmarks will be displayed in an organized and visually appealing format below.
584
- """)
585
 
586
  upload = gr.File(label="πŸ“ Upload Bookmarks HTML File", type='binary')
587
  process_button = gr.Button("βš™οΈ Process Bookmarks")
588
  output_text = gr.Textbox(label="βœ… Output", interactive=False)
589
  bookmark_display = gr.HTML(label="πŸ“„ Bookmarks")
590
 
 
 
 
 
591
  process_button.click(
592
  process_uploaded_file,
593
- inputs=[upload, state_bookmarks],
594
- outputs=[output_text, bookmark_display, bookmark_selector, bookmark_display_manage, state_bookmarks]
595
  )
596
 
597
  # Chat with Bookmarks Tab
598
  with gr.Tab("Chat with Bookmarks"):
599
  gr.Markdown("""
600
- ## πŸ’¬ **Chat with Bookmarks**
601
 
602
- ### πŸ€– **How to Interact:**
603
 
604
- 1. **✍️ Enter Your Query:**
605
- - In the **"✍️ Ask about your bookmarks"** textbox, type your question or keyword related to your bookmarks. For example, "Do I have any bookmarks about GenerativeAI?"
606
 
607
- 2. **πŸ“¨ Submit Your Query:**
608
- - You can either press the **Enter** key or click the **"πŸ“¨ Send"** button to submit your query.
609
 
610
- 3. **πŸ“ˆ Receive AI-Driven Responses:**
611
- - SmartMarks will analyze your query and provide relevant bookmarks that match your request, making it easier to find specific links without manual searching.
 
612
 
613
- 4. **πŸ—‚οΈ View Chat History:**
614
- - All your queries and the corresponding AI responses are displayed in the chat history for your reference.
615
- """)
616
 
617
- with gr.Row():
618
- chat_history_display = gr.Chatbot(label="πŸ—¨οΈ Chat History")
619
- with gr.Column(scale=1):
620
- chat_input = gr.Textbox(
621
- label="✍️ Ask about your bookmarks",
622
- placeholder="e.g., Do I have any bookmarks about GenerativeAI?",
623
- lines=1,
624
- interactive=True
625
- )
626
- chat_button = gr.Button("πŸ“¨ Send")
627
-
628
- # When user presses Enter in chat_input
629
- chat_input.submit(
630
- chatbot_response,
631
- inputs=[chat_input, state_bookmarks],
632
- outputs=chat_history_display
633
- )
634
-
635
- # When user clicks Send button
636
  chat_button.click(
637
  chatbot_response,
638
- inputs=[chat_input, state_bookmarks],
639
- outputs=chat_history_display
640
  )
641
 
642
  # Manage Bookmarks Tab
643
  with gr.Tab("Manage Bookmarks"):
644
  gr.Markdown("""
645
- ## πŸ› οΈ **Manage Bookmarks**
646
 
647
- ### πŸ—‚οΈ **Features:**
648
 
649
- 1. **πŸ‘οΈ View Bookmarks:**
650
- - All your processed bookmarks are displayed here with their respective categories and summaries.
651
 
652
- 2. **βœ… Select Bookmarks:**
653
- - Use the checkboxes next to each bookmark to select one, multiple, or all bookmarks you wish to manage.
654
 
655
- 3. **πŸ—‘οΈ Delete Selected Bookmarks:**
656
- - After selecting the desired bookmarks, click the **"πŸ—‘οΈ Delete Selected Bookmarks"** button to remove them from your list.
657
 
658
- 4. **✏️ Edit Categories:**
659
- - Select the bookmarks you want to re-categorize.
660
- - Choose a new category from the dropdown menu labeled **"πŸ†• New Category"**.
661
- - Click the **"✏️ Edit Category of Selected Bookmarks"** button to update their categories.
662
 
663
- 5. **πŸ’Ύ Export Bookmarks:**
664
- - Click the **"πŸ’Ύ Export Bookmarks"** button to download your updated bookmarks as an HTML file.
665
- - This file can be uploaded back to your browser to reflect the changes made within SmartMarks.
666
- """)
667
 
668
  manage_output = gr.Textbox(label="πŸ”„ Manage Output", interactive=False)
 
 
 
669
  new_category_input = gr.Dropdown(label="πŸ†• New Category", choices=CATEGORIES, value="Uncategorized")
670
  with gr.Row():
671
  delete_button = gr.Button("πŸ—‘οΈ Delete Selected Bookmarks")
672
  edit_category_button = gr.Button("✏️ Edit Category of Selected Bookmarks")
673
  export_button = gr.Button("πŸ’Ύ Export Bookmarks")
674
  download_link = gr.HTML(label="πŸ“₯ Download Exported Bookmarks")
675
- refresh_button = gr.Button("πŸ”„ Refresh Bookmarks")
676
 
677
  # Define button actions
678
  delete_button.click(
679
  delete_selected_bookmarks,
680
- inputs=[bookmark_selector, state_bookmarks],
681
  outputs=[manage_output, bookmark_selector, bookmark_display_manage]
682
  )
683
 
684
  edit_category_button.click(
685
  edit_selected_bookmarks_category,
686
- inputs=[bookmark_selector, new_category_input, state_bookmarks],
687
  outputs=[manage_output, bookmark_selector, bookmark_display_manage]
688
  )
689
 
690
  export_button.click(
691
  export_bookmarks,
692
- inputs=[state_bookmarks],
693
  outputs=download_link
694
  )
695
 
696
- refresh_button.click(
697
- lambda bookmarks: (
698
- [
699
- f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)
700
- ],
701
- display_bookmarks(bookmarks)
702
- ),
703
- inputs=[state_bookmarks],
704
- outputs=[bookmark_selector, bookmark_display_manage]
705
  )
706
 
707
  logger.info("Launching Gradio app")
 
2
 
3
  import gradio as gr
4
  from bs4 import BeautifulSoup
5
+ import requests
6
+ from sentence_transformers import SentenceTransformer
7
+ import faiss
8
+ import numpy as np
9
  import asyncio
10
  import aiohttp
11
  import re
 
13
  import logging
14
  import os
15
  import sys
 
 
 
16
 
17
  # Import OpenAI library
18
  import openai
 
36
  logger.info("Initializing models and variables")
37
  embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
38
  faiss_index = None
39
+ bookmarks = []
40
  fetch_cache = {}
41
 
42
  # Define the categories
 
234
  raise
235
 
236
  # Generate HTML display for bookmarks
237
+ def display_bookmarks():
238
  logger.info("Generating HTML display for bookmarks")
239
  cards = ''
240
+ for i, bookmark in enumerate(bookmarks):
241
  index = i + 1 # Start index at 1
242
  status = "❌ Dead Link" if bookmark.get('dead_link') else "βœ… Active"
243
  title = bookmark['title']
 
246
  summary = bookmark.get('summary', '')
247
  category = bookmark.get('category', 'Uncategorized')
248
 
249
+ # Apply inline styles for dead links
250
  if bookmark.get('dead_link'):
251
+ card_style = "border: 2px solid #D32F2F;"
252
+ text_style = "color: #D32F2F;"
253
  else:
254
+ card_style = "border: 2px solid #4CAF50;"
255
+ text_style = "color: #000000;"
256
 
257
  card_html = f'''
258
+ <div class="card" style="{card_style}; padding: 10px; margin: 10px; border-radius: 5px;">
259
  <div class="card-content">
260
+ <h3 style="{text_style}">{index}. {title} {status}</h3>
261
+ <p style="{text_style}"><strong>Category:</strong> {category}</p>
262
+ <p style="{text_style}"><strong>URL:</strong> <a href="{url}" target="_blank" style="{text_style}">{url}</a></p>
263
+ <p style="{text_style}"><strong>ETag:</strong> {etag}</p>
264
+ <p style="{text_style}"><strong>Summary:</strong> {summary}</p>
265
  </div>
266
  </div>
267
  '''
 
270
  return cards
271
 
272
  # Process the uploaded file
273
+ def process_uploaded_file(file):
274
+ global bookmarks, faiss_index
275
  logger.info("Processing uploaded file")
276
  if file is None:
277
  logger.warning("No file uploaded")
278
+ return "Please upload a bookmarks HTML file.", '', gr.update(choices=[]), display_bookmarks()
 
 
 
 
 
 
 
279
  try:
280
  file_content = file.decode('utf-8')
281
  except UnicodeDecodeError as e:
282
  logger.error(f"Error decoding the file: {e}")
283
+ return "Error decoding the file. Please ensure it's a valid HTML file.", '', gr.update(choices=[]), display_bookmarks()
 
 
 
 
 
 
284
 
285
  try:
286
  bookmarks = parse_bookmarks(file_content)
287
  except Exception as e:
288
  logger.error(f"Error parsing bookmarks: {e}")
289
+ return "Error parsing the bookmarks HTML file.", '', gr.update(choices=[]), display_bookmarks()
 
 
 
 
 
 
290
 
291
  if not bookmarks:
292
  logger.warning("No bookmarks found in the uploaded file")
293
+ return "No bookmarks found in the uploaded file.", '', gr.update(choices=[]), display_bookmarks()
 
 
 
 
 
 
294
 
295
  # Asynchronously fetch bookmark info
296
  try:
297
  asyncio.run(process_bookmarks_async(bookmarks))
298
  except Exception as e:
299
  logger.error(f"Error processing bookmarks asynchronously: {e}")
300
+ return "Error processing bookmarks.", '', gr.update(choices=[]), display_bookmarks()
 
 
 
 
 
 
301
 
302
  # Generate summaries and assign categories
303
  for bookmark in bookmarks:
 
308
  faiss_index, embeddings = vectorize_and_index(bookmarks)
309
  except Exception as e:
310
  logger.error(f"Error building FAISS index: {e}")
311
+ return "Error building search index.", '', gr.update(choices=[]), display_bookmarks()
 
 
 
 
 
 
312
 
313
  message = f"βœ… Successfully processed {len(bookmarks)} bookmarks."
314
  logger.info(message)
315
+ bookmark_html = display_bookmarks()
316
 
317
+ # Update bookmark_selector choices
318
  choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
319
+ bookmark_selector_update = gr.update(choices=choices, value=[])
320
 
321
+ # Update bookmark_display_manage
322
+ bookmark_display_manage_update = display_bookmarks()
323
 
324
+ return message, bookmark_html, bookmark_selector_update, bookmark_display_manage_update
 
 
 
 
 
 
325
 
326
  # Delete selected bookmarks
327
+ def delete_selected_bookmarks(selected_indices):
328
+ global bookmarks, faiss_index
329
  if not selected_indices:
330
+ return "⚠️ No bookmarks selected.", gr.update(choices=[]), display_bookmarks()
331
+ indices = [int(s.split('.')[0])-1 for s in selected_indices]
 
 
 
 
 
 
 
 
 
 
 
 
332
  indices = sorted(indices, reverse=True)
333
  for idx in indices:
334
+ if 0 <= idx < len(bookmarks):
335
+ logger.info(f"Deleting bookmark at index {idx + 1}")
336
+ bookmarks.pop(idx)
337
  if bookmarks:
338
  faiss_index, embeddings = vectorize_and_index(bookmarks)
339
  else:
340
  faiss_index = None
 
341
  message = "πŸ—‘οΈ Selected bookmarks deleted successfully."
342
  logger.info(message)
343
+ # Update bookmark_selector choices
 
 
 
 
344
  choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
345
+ bookmark_selector_update = gr.update(choices=choices, value=[])
346
+ # Update bookmarks display
347
+ bookmarks_html = display_bookmarks()
348
+ return message, bookmark_selector_update, bookmarks_html
 
349
 
350
  # Edit category of selected bookmarks
351
+ def edit_selected_bookmarks_category(selected_indices, new_category):
352
  if not selected_indices:
353
+ return "⚠️ No bookmarks selected.", '', gr.update()
 
 
 
 
 
354
  if not new_category:
355
+ return "⚠️ No new category selected.", '', gr.update()
356
+ indices = [int(s.split('.')[0])-1 for s in selected_indices]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  for idx in indices:
358
+ if 0 <= idx < len(bookmarks):
359
+ bookmarks[idx]['category'] = new_category
360
+ logger.info(f"Updated category for bookmark {idx + 1} to {new_category}")
361
  message = "✏️ Category updated for selected bookmarks."
362
  logger.info(message)
363
+ # Update bookmark_selector choices
 
 
 
 
364
  choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
365
+ bookmark_selector_update = gr.update(choices=choices, value=[])
366
+ # Update bookmarks display
367
+ bookmarks_html = display_bookmarks()
368
+ return message, bookmark_selector_update, bookmarks_html
 
369
 
370
  # Export bookmarks to HTML
371
+ def export_bookmarks():
 
372
  if not bookmarks:
373
  logger.warning("No bookmarks to export")
374
  return "⚠️ No bookmarks to export."
 
395
  return "⚠️ Error exporting bookmarks."
396
 
397
  # Chatbot response using Groq Cloud API
398
+ def chatbot_response(user_query):
399
  if not GROQ_API_KEY:
400
  logger.warning("GROQ_API_KEY not set.")
401
  return "⚠️ API key not set. Please set the GROQ_API_KEY environment variable in the Hugging Face Space settings."
402
 
 
403
  if not bookmarks:
404
  logger.warning("No bookmarks available for chatbot")
405
  return "⚠️ No bookmarks available. Please upload and process your bookmarks first."
 
453
  def build_app():
454
  try:
455
  logger.info("Building Gradio app")
456
+ with gr.Blocks(css="""
457
+ .card {
458
+ box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
459
+ transition: 0.3s;
460
+ }
461
+ .card:hover {
462
+ box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
463
+ }
464
+ """) as demo:
465
  # General Overview
466
  gr.Markdown("""
467
+ # πŸ“š SmartMarks - AI Browser Bookmarks Manager
 
 
468
 
469
+ Welcome to **SmartMarks**, your intelligent assistant for managing browser bookmarks. SmartMarks leverages AI to help you organize, search, and interact with your bookmarks seamlessly. Whether you're looking to categorize your links, retrieve information quickly, or maintain an updated list, SmartMarks has you covered.
470
 
471
+ ---
472
 
473
+ ## πŸš€ **How to Use SmartMarks**
474
 
475
+ SmartMarks is divided into three main sections:
 
 
476
 
477
+ 1. **πŸ“‚ Upload and Process Bookmarks:** Import your existing bookmarks and let SmartMarks analyze and categorize them for you.
478
+ 2. **πŸ’¬ Chat with Bookmarks:** Interact with your bookmarks using natural language queries to find relevant links effortlessly.
479
+ 3. **πŸ› οΈ Manage Bookmarks:** View, edit, delete, and export your bookmarks with ease.
480
 
481
+ Navigate through the tabs to explore each feature in detail.
482
+ """)
 
483
 
484
  # Upload and Process Bookmarks Tab
485
  with gr.Tab("Upload and Process Bookmarks"):
486
  gr.Markdown("""
487
+ ## πŸ“‚ **Upload and Process Bookmarks**
488
 
489
+ ### πŸ“ **Steps to Upload and Process:**
490
 
491
+ 1. **πŸ”½ Upload Bookmarks File:**
492
+ - Click on the **"Upload Bookmarks HTML File"** button.
493
+ - Select your browser's exported bookmarks HTML file from your device.
494
 
495
+ 2. **βš™οΈ Process Bookmarks:**
496
+ - After uploading, click on the **"Process Bookmarks"** button.
497
+ - SmartMarks will parse your bookmarks, fetch additional information, generate summaries, and categorize each link based on predefined categories.
498
 
499
+ 3. **πŸ“„ View Processed Bookmarks:**
500
+ - Once processing is complete, your bookmarks will be displayed in an organized and visually appealing format below.
501
+ """)
502
 
503
  upload = gr.File(label="πŸ“ Upload Bookmarks HTML File", type='binary')
504
  process_button = gr.Button("βš™οΈ Process Bookmarks")
505
  output_text = gr.Textbox(label="βœ… Output", interactive=False)
506
  bookmark_display = gr.HTML(label="πŸ“„ Bookmarks")
507
 
508
+ # Initialize Manage Bookmarks components
509
+ bookmark_selector = gr.CheckboxGroup(label="βœ… Select Bookmarks", choices=[])
510
+ bookmark_display_manage = gr.HTML(label="πŸ“„ Manage Bookmarks Display")
511
+
512
  process_button.click(
513
  process_uploaded_file,
514
+ inputs=upload,
515
+ outputs=[output_text, bookmark_display, bookmark_selector, bookmark_display_manage]
516
  )
517
 
518
  # Chat with Bookmarks Tab
519
  with gr.Tab("Chat with Bookmarks"):
520
  gr.Markdown("""
521
+ ## πŸ’¬ **Chat with Bookmarks**
522
 
523
+ ### πŸ€– **How to Interact:**
524
 
525
+ 1. **✍️ Enter Your Query:**
526
+ - In the **"Ask about your bookmarks"** textbox, type your question or keyword related to your bookmarks. For example, "Do I have any bookmarks about GenerativeAI?"
527
 
528
+ 2. **πŸ“¨ Submit Your Query:**
529
+ - Click the **"Send"** button to submit your query.
530
 
531
+ 3. **πŸ“ˆ Receive AI-Driven Responses:**
532
+ - SmartMarks will analyze your query and provide relevant bookmarks that match your request, making it easier to find specific links without manual searching.
533
+ """)
534
 
535
+ user_input = gr.Textbox(label="✍️ Ask about your bookmarks", placeholder="e.g., Do I have any bookmarks about GenerativeAI?")
536
+ chat_output = gr.Textbox(label="πŸ’¬ Chatbot Response", interactive=False)
537
+ chat_button = gr.Button("πŸ“¨ Send")
538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  chat_button.click(
540
  chatbot_response,
541
+ inputs=user_input,
542
+ outputs=chat_output
543
  )
544
 
545
  # Manage Bookmarks Tab
546
  with gr.Tab("Manage Bookmarks"):
547
  gr.Markdown("""
548
+ ## πŸ› οΈ **Manage Bookmarks**
549
 
550
+ ### πŸ—‚οΈ **Features:**
551
 
552
+ 1. **πŸ‘οΈ View Bookmarks:**
553
+ - All your processed bookmarks are displayed here with their respective categories and summaries.
554
 
555
+ 2. **βœ… Select Bookmarks:**
556
+ - Use the checkboxes next to each bookmark to select one, multiple, or all bookmarks you wish to manage.
557
 
558
+ 3. **πŸ—‘οΈ Delete Selected Bookmarks:**
559
+ - After selecting the desired bookmarks, click the **"Delete Selected Bookmarks"** button to remove them from your list.
560
 
561
+ 4. **✏️ Edit Categories:**
562
+ - Select the bookmarks you want to re-categorize.
563
+ - Choose a new category from the dropdown menu labeled **"New Category"**.
564
+ - Click the **"Edit Category of Selected Bookmarks"** button to update their categories.
565
 
566
+ 5. **πŸ’Ύ Export Bookmarks:**
567
+ - Click the **"Export Bookmarks"** button to download your updated bookmarks as an HTML file.
568
+ - This file can be uploaded back to your browser to reflect the changes made within SmartMarks.
569
+ """)
570
 
571
  manage_output = gr.Textbox(label="πŸ”„ Manage Output", interactive=False)
572
+ bookmark_display_manage = gr.HTML(label="πŸ“„ Manage Bookmarks Display")
573
+ bookmark_selector = gr.CheckboxGroup(label="βœ… Select Bookmarks", choices=[])
574
+
575
  new_category_input = gr.Dropdown(label="πŸ†• New Category", choices=CATEGORIES, value="Uncategorized")
576
  with gr.Row():
577
  delete_button = gr.Button("πŸ—‘οΈ Delete Selected Bookmarks")
578
  edit_category_button = gr.Button("✏️ Edit Category of Selected Bookmarks")
579
  export_button = gr.Button("πŸ’Ύ Export Bookmarks")
580
  download_link = gr.HTML(label="πŸ“₯ Download Exported Bookmarks")
 
581
 
582
  # Define button actions
583
  delete_button.click(
584
  delete_selected_bookmarks,
585
+ inputs=bookmark_selector,
586
  outputs=[manage_output, bookmark_selector, bookmark_display_manage]
587
  )
588
 
589
  edit_category_button.click(
590
  edit_selected_bookmarks_category,
591
+ inputs=[bookmark_selector, new_category_input],
592
  outputs=[manage_output, bookmark_selector, bookmark_display_manage]
593
  )
594
 
595
  export_button.click(
596
  export_bookmarks,
597
+ inputs=None,
598
  outputs=download_link
599
  )
600
 
601
+ # Initialize display after processing bookmarks
602
+ process_button.click(
603
+ process_uploaded_file,
604
+ inputs=upload,
605
+ outputs=[output_text, bookmark_display, bookmark_selector, bookmark_display_manage]
 
 
 
 
606
  )
607
 
608
  logger.info("Launching Gradio app")