Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -36,7 +36,6 @@ logger.addHandler(console_handler)
|
|
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,10 +233,10 @@ def vectorize_and_index(bookmarks):
|
|
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(
|
241 |
index = i + 1 # Start index at 1
|
242 |
status = "โ Dead Link" if bookmark.get('dead_link') else "โ
Active"
|
243 |
title = bookmark['title']
|
@@ -253,7 +252,7 @@ def display_bookmarks():
|
|
253 |
card_classes = "card active-link"
|
254 |
|
255 |
card_html = f'''
|
256 |
-
<div class="{card_classes}"
|
257 |
<div class="card-content">
|
258 |
<h3>{index}. {title} {status}</h3>
|
259 |
<p><strong>Category:</strong> {category}</p>
|
@@ -268,34 +267,33 @@ def display_bookmarks():
|
|
268 |
return cards
|
269 |
|
270 |
# Process the uploaded file
|
271 |
-
def process_uploaded_file(file):
|
272 |
-
global bookmarks, faiss_index
|
273 |
logger.info("Processing uploaded file")
|
274 |
if file is None:
|
275 |
logger.warning("No file uploaded")
|
276 |
-
return "โ ๏ธ Please upload a bookmarks HTML file.",
|
277 |
try:
|
278 |
file_content = file.decode('utf-8')
|
279 |
except UnicodeDecodeError as e:
|
280 |
logger.error(f"Error decoding the file: {e}")
|
281 |
-
return "โ ๏ธ Error decoding the file. Please ensure it's a valid HTML file.",
|
282 |
|
283 |
try:
|
284 |
bookmarks = parse_bookmarks(file_content)
|
285 |
except Exception as e:
|
286 |
logger.error(f"Error parsing bookmarks: {e}")
|
287 |
-
return "โ ๏ธ Error parsing the bookmarks HTML file.",
|
288 |
|
289 |
if not bookmarks:
|
290 |
logger.warning("No bookmarks found in the uploaded file")
|
291 |
-
return "โ ๏ธ No bookmarks found in the uploaded file.",
|
292 |
|
293 |
# Asynchronously fetch bookmark info
|
294 |
try:
|
295 |
asyncio.run(process_bookmarks_async(bookmarks))
|
296 |
except Exception as e:
|
297 |
logger.error(f"Error processing bookmarks asynchronously: {e}")
|
298 |
-
return "โ ๏ธ Error processing bookmarks.",
|
299 |
|
300 |
# Generate summaries and assign categories
|
301 |
for bookmark in bookmarks:
|
@@ -306,26 +304,22 @@ def process_uploaded_file(file):
|
|
306 |
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
307 |
except Exception as e:
|
308 |
logger.error(f"Error building FAISS index: {e}")
|
309 |
-
return "โ ๏ธ Error building search index.",
|
310 |
|
311 |
message = f"โ
Successfully processed {len(bookmarks)} bookmarks."
|
312 |
logger.info(message)
|
313 |
-
bookmark_html = display_bookmarks()
|
314 |
|
315 |
-
# Update
|
316 |
-
|
317 |
-
bookmark_selector_update = gr.update(choices=choices, value=[])
|
318 |
-
|
319 |
-
# Update bookmark_display_manage
|
320 |
-
bookmark_display_manage_update = display_bookmarks()
|
321 |
|
322 |
-
return message, bookmark_html
|
323 |
|
324 |
# Delete selected bookmarks
|
325 |
-
def delete_selected_bookmarks(selected_indices):
|
326 |
-
global bookmarks, faiss_index
|
327 |
if not selected_indices:
|
328 |
-
return "โ ๏ธ No bookmarks selected.", gr.update(choices=[]),
|
|
|
329 |
indices = [int(s.split('.')[0])-1 for s in selected_indices]
|
330 |
indices = sorted(indices, reverse=True)
|
331 |
for idx in indices:
|
@@ -338,19 +332,21 @@ def delete_selected_bookmarks(selected_indices):
|
|
338 |
faiss_index = None
|
339 |
message = "๐๏ธ Selected bookmarks deleted successfully."
|
340 |
logger.info(message)
|
341 |
-
#
|
|
|
|
|
|
|
|
|
342 |
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
343 |
-
|
344 |
-
# Update bookmarks display
|
345 |
-
bookmarks_html = display_bookmarks()
|
346 |
-
return message, bookmark_selector_update, bookmarks_html
|
347 |
|
348 |
# Edit category of selected bookmarks
|
349 |
-
def edit_selected_bookmarks_category(selected_indices, new_category):
|
350 |
if not selected_indices:
|
351 |
-
return "โ ๏ธ No bookmarks selected.",
|
352 |
if not new_category:
|
353 |
-
return "โ ๏ธ No new category selected.",
|
|
|
354 |
indices = [int(s.split('.')[0])-1 for s in selected_indices]
|
355 |
for idx in indices:
|
356 |
if 0 <= idx < len(bookmarks):
|
@@ -358,15 +354,17 @@ def edit_selected_bookmarks_category(selected_indices, new_category):
|
|
358 |
logger.info(f"Updated category for bookmark {idx + 1} to {new_category}")
|
359 |
message = "โ๏ธ Category updated for selected bookmarks."
|
360 |
logger.info(message)
|
361 |
-
#
|
|
|
|
|
|
|
|
|
362 |
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
363 |
-
|
364 |
-
# Update bookmarks display
|
365 |
-
bookmarks_html = display_bookmarks()
|
366 |
-
return message, bookmark_selector_update, bookmarks_html
|
367 |
|
368 |
# Export bookmarks to HTML
|
369 |
-
def export_bookmarks():
|
|
|
370 |
if not bookmarks:
|
371 |
logger.warning("No bookmarks to export")
|
372 |
return "โ ๏ธ No bookmarks to export."
|
@@ -393,11 +391,12 @@ def export_bookmarks():
|
|
393 |
return "โ ๏ธ Error exporting bookmarks."
|
394 |
|
395 |
# Chatbot response using Groq Cloud API
|
396 |
-
def chatbot_response(user_query):
|
397 |
if not GROQ_API_KEY:
|
398 |
logger.warning("GROQ_API_KEY not set.")
|
399 |
return "โ ๏ธ API key not set. Please set the GROQ_API_KEY environment variable in the Hugging Face Space settings."
|
400 |
|
|
|
401 |
if not bookmarks:
|
402 |
logger.warning("No bookmarks available for chatbot")
|
403 |
return "โ ๏ธ No bookmarks available. Please upload and process your bookmarks first."
|
@@ -452,6 +451,9 @@ def build_app():
|
|
452 |
try:
|
453 |
logger.info("Building Gradio app")
|
454 |
with gr.Blocks(theme=gr.themes.Default(), css="app.css") as demo:
|
|
|
|
|
|
|
455 |
# General Overview
|
456 |
gr.Markdown("""
|
457 |
# ๐ SmartMarks - AI Browser Bookmarks Manager
|
@@ -495,14 +497,10 @@ def build_app():
|
|
495 |
output_text = gr.Textbox(label="โ
Output", interactive=False)
|
496 |
bookmark_display = gr.HTML(label="๐ Bookmarks")
|
497 |
|
498 |
-
# Initialize Manage Bookmarks components
|
499 |
-
bookmark_selector = gr.CheckboxGroup(label="โ
Select Bookmarks", choices=[])
|
500 |
-
bookmark_display_manage = gr.HTML(label="๐ Manage Bookmarks Display")
|
501 |
-
|
502 |
process_button.click(
|
503 |
process_uploaded_file,
|
504 |
-
inputs=upload,
|
505 |
-
outputs=[output_text, bookmark_display
|
506 |
)
|
507 |
|
508 |
# Chat with Bookmarks Tab
|
@@ -528,7 +526,7 @@ def build_app():
|
|
528 |
|
529 |
chat_button.click(
|
530 |
chatbot_response,
|
531 |
-
inputs=user_input,
|
532 |
outputs=chat_output
|
533 |
)
|
534 |
|
@@ -559,44 +557,53 @@ def build_app():
|
|
559 |
""")
|
560 |
|
561 |
manage_output = gr.Textbox(label="๐ Manage Output", interactive=False)
|
562 |
-
bookmark_display_manage = gr.HTML(label="๐ Manage Bookmarks Display")
|
563 |
bookmark_selector = gr.CheckboxGroup(label="โ
Select Bookmarks", choices=[])
|
564 |
-
|
565 |
new_category_input = gr.Dropdown(label="๐ New Category", choices=CATEGORIES, value="Uncategorized")
|
566 |
with gr.Row():
|
567 |
delete_button = gr.Button("๐๏ธ Delete Selected Bookmarks")
|
568 |
edit_category_button = gr.Button("โ๏ธ Edit Category of Selected Bookmarks")
|
569 |
export_button = gr.Button("๐พ Export Bookmarks")
|
570 |
download_link = gr.HTML(label="๐ฅ Download Exported Bookmarks")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
|
572 |
# Define button actions
|
573 |
delete_button.click(
|
574 |
delete_selected_bookmarks,
|
575 |
-
inputs=bookmark_selector,
|
576 |
outputs=[manage_output, bookmark_selector, bookmark_display_manage]
|
577 |
)
|
578 |
|
579 |
edit_category_button.click(
|
580 |
edit_selected_bookmarks_category,
|
581 |
-
inputs=[bookmark_selector, new_category_input],
|
582 |
outputs=[manage_output, bookmark_selector, bookmark_display_manage]
|
583 |
)
|
584 |
|
585 |
export_button.click(
|
586 |
export_bookmarks,
|
587 |
-
inputs=
|
588 |
outputs=download_link
|
589 |
)
|
590 |
|
591 |
-
|
592 |
-
|
593 |
-
process_uploaded_file,
|
594 |
-
inputs=upload,
|
595 |
-
outputs=[output_text, bookmark_display, bookmark_selector, bookmark_display_manage]
|
596 |
-
)
|
597 |
-
|
598 |
-
logger.info("Launching Gradio app")
|
599 |
-
demo.launch(debug=True)
|
600 |
except Exception as e:
|
601 |
logger.error(f"Error building the app: {e}")
|
602 |
print(f"Error building the app: {e}")
|
|
|
36 |
logger.info("Initializing models and variables")
|
37 |
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
|
38 |
faiss_index = None
|
|
|
39 |
fetch_cache = {}
|
40 |
|
41 |
# Define the categories
|
|
|
233 |
raise
|
234 |
|
235 |
# Generate HTML display for bookmarks
|
236 |
+
def display_bookmarks(bookmarks_list):
|
237 |
logger.info("Generating HTML display for bookmarks")
|
238 |
cards = ''
|
239 |
+
for i, bookmark in enumerate(bookmarks_list):
|
240 |
index = i + 1 # Start index at 1
|
241 |
status = "โ Dead Link" if bookmark.get('dead_link') else "โ
Active"
|
242 |
title = bookmark['title']
|
|
|
252 |
card_classes = "card active-link"
|
253 |
|
254 |
card_html = f'''
|
255 |
+
<div class="{card_classes}">
|
256 |
<div class="card-content">
|
257 |
<h3>{index}. {title} {status}</h3>
|
258 |
<p><strong>Category:</strong> {category}</p>
|
|
|
267 |
return cards
|
268 |
|
269 |
# Process the uploaded file
|
270 |
+
def process_uploaded_file(file, state_bookmarks):
|
|
|
271 |
logger.info("Processing uploaded file")
|
272 |
if file is None:
|
273 |
logger.warning("No file uploaded")
|
274 |
+
return "โ ๏ธ Please upload a bookmarks HTML file.", ""
|
275 |
try:
|
276 |
file_content = file.decode('utf-8')
|
277 |
except UnicodeDecodeError as e:
|
278 |
logger.error(f"Error decoding the file: {e}")
|
279 |
+
return "โ ๏ธ Error decoding the file. Please ensure it's a valid HTML file.", ""
|
280 |
|
281 |
try:
|
282 |
bookmarks = parse_bookmarks(file_content)
|
283 |
except Exception as e:
|
284 |
logger.error(f"Error parsing bookmarks: {e}")
|
285 |
+
return "โ ๏ธ Error parsing the bookmarks HTML file.", ""
|
286 |
|
287 |
if not bookmarks:
|
288 |
logger.warning("No bookmarks found in the uploaded file")
|
289 |
+
return "โ ๏ธ No bookmarks found in the uploaded file.", ""
|
290 |
|
291 |
# Asynchronously fetch bookmark info
|
292 |
try:
|
293 |
asyncio.run(process_bookmarks_async(bookmarks))
|
294 |
except Exception as e:
|
295 |
logger.error(f"Error processing bookmarks asynchronously: {e}")
|
296 |
+
return "โ ๏ธ Error processing bookmarks.", ""
|
297 |
|
298 |
# Generate summaries and assign categories
|
299 |
for bookmark in bookmarks:
|
|
|
304 |
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
305 |
except Exception as e:
|
306 |
logger.error(f"Error building FAISS index: {e}")
|
307 |
+
return "โ ๏ธ Error building search index.", ""
|
308 |
|
309 |
message = f"โ
Successfully processed {len(bookmarks)} bookmarks."
|
310 |
logger.info(message)
|
311 |
+
bookmark_html = display_bookmarks(bookmarks)
|
312 |
|
313 |
+
# Update the shared state
|
314 |
+
state_bookmarks.append(bookmarks)
|
|
|
|
|
|
|
|
|
315 |
|
316 |
+
return message, bookmark_html
|
317 |
|
318 |
# Delete selected bookmarks
|
319 |
+
def delete_selected_bookmarks(selected_indices, state_bookmarks):
|
|
|
320 |
if not selected_indices:
|
321 |
+
return "โ ๏ธ No bookmarks selected.", gr.update(choices=[]), ""
|
322 |
+
bookmarks = state_bookmarks[0]
|
323 |
indices = [int(s.split('.')[0])-1 for s in selected_indices]
|
324 |
indices = sorted(indices, reverse=True)
|
325 |
for idx in indices:
|
|
|
332 |
faiss_index = None
|
333 |
message = "๐๏ธ Selected bookmarks deleted successfully."
|
334 |
logger.info(message)
|
335 |
+
# Regenerate HTML display
|
336 |
+
bookmarks_html = display_bookmarks(bookmarks)
|
337 |
+
# Update the shared state
|
338 |
+
state_bookmarks[0] = bookmarks
|
339 |
+
# Update choices for selection
|
340 |
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
341 |
+
return message, gr.update(choices=choices), bookmarks_html
|
|
|
|
|
|
|
342 |
|
343 |
# Edit category of selected bookmarks
|
344 |
+
def edit_selected_bookmarks_category(selected_indices, new_category, state_bookmarks):
|
345 |
if not selected_indices:
|
346 |
+
return "โ ๏ธ No bookmarks selected.", "", ""
|
347 |
if not new_category:
|
348 |
+
return "โ ๏ธ No new category selected.", "", ""
|
349 |
+
bookmarks = state_bookmarks[0]
|
350 |
indices = [int(s.split('.')[0])-1 for s in selected_indices]
|
351 |
for idx in indices:
|
352 |
if 0 <= idx < len(bookmarks):
|
|
|
354 |
logger.info(f"Updated category for bookmark {idx + 1} to {new_category}")
|
355 |
message = "โ๏ธ Category updated for selected bookmarks."
|
356 |
logger.info(message)
|
357 |
+
# Regenerate HTML display
|
358 |
+
bookmarks_html = display_bookmarks(bookmarks)
|
359 |
+
# Update the shared state
|
360 |
+
state_bookmarks[0] = bookmarks
|
361 |
+
# Update choices for selection
|
362 |
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
363 |
+
return message, gr.update(choices=choices), bookmarks_html
|
|
|
|
|
|
|
364 |
|
365 |
# Export bookmarks to HTML
|
366 |
+
def export_bookmarks(state_bookmarks):
|
367 |
+
bookmarks = state_bookmarks[0]
|
368 |
if not bookmarks:
|
369 |
logger.warning("No bookmarks to export")
|
370 |
return "โ ๏ธ No bookmarks to export."
|
|
|
391 |
return "โ ๏ธ Error exporting bookmarks."
|
392 |
|
393 |
# Chatbot response using Groq Cloud API
|
394 |
+
def chatbot_response(user_query, state_bookmarks):
|
395 |
if not GROQ_API_KEY:
|
396 |
logger.warning("GROQ_API_KEY not set.")
|
397 |
return "โ ๏ธ API key not set. Please set the GROQ_API_KEY environment variable in the Hugging Face Space settings."
|
398 |
|
399 |
+
bookmarks = state_bookmarks[0]
|
400 |
if not bookmarks:
|
401 |
logger.warning("No bookmarks available for chatbot")
|
402 |
return "โ ๏ธ No bookmarks available. Please upload and process your bookmarks first."
|
|
|
451 |
try:
|
452 |
logger.info("Building Gradio app")
|
453 |
with gr.Blocks(theme=gr.themes.Default(), css="app.css") as demo:
|
454 |
+
# Shared state to store bookmarks
|
455 |
+
state_bookmarks = gr.State([])
|
456 |
+
|
457 |
# General Overview
|
458 |
gr.Markdown("""
|
459 |
# ๐ SmartMarks - AI Browser Bookmarks Manager
|
|
|
497 |
output_text = gr.Textbox(label="โ
Output", interactive=False)
|
498 |
bookmark_display = gr.HTML(label="๐ Bookmarks")
|
499 |
|
|
|
|
|
|
|
|
|
500 |
process_button.click(
|
501 |
process_uploaded_file,
|
502 |
+
inputs=[upload, state_bookmarks],
|
503 |
+
outputs=[output_text, bookmark_display]
|
504 |
)
|
505 |
|
506 |
# Chat with Bookmarks Tab
|
|
|
526 |
|
527 |
chat_button.click(
|
528 |
chatbot_response,
|
529 |
+
inputs=[user_input, state_bookmarks],
|
530 |
outputs=chat_output
|
531 |
)
|
532 |
|
|
|
557 |
""")
|
558 |
|
559 |
manage_output = gr.Textbox(label="๐ Manage Output", interactive=False)
|
|
|
560 |
bookmark_selector = gr.CheckboxGroup(label="โ
Select Bookmarks", choices=[])
|
|
|
561 |
new_category_input = gr.Dropdown(label="๐ New Category", choices=CATEGORIES, value="Uncategorized")
|
562 |
with gr.Row():
|
563 |
delete_button = gr.Button("๐๏ธ Delete Selected Bookmarks")
|
564 |
edit_category_button = gr.Button("โ๏ธ Edit Category of Selected Bookmarks")
|
565 |
export_button = gr.Button("๐พ Export Bookmarks")
|
566 |
download_link = gr.HTML(label="๐ฅ Download Exported Bookmarks")
|
567 |
+
bookmark_display_manage = gr.HTML(label="๐ Manage Bookmarks Display")
|
568 |
+
refresh_button = gr.Button("๐ Refresh Bookmarks")
|
569 |
+
|
570 |
+
# Function to refresh Manage Bookmarks Tab
|
571 |
+
def refresh_manage_tab(state_bookmarks):
|
572 |
+
bookmarks = state_bookmarks[0]
|
573 |
+
if bookmarks:
|
574 |
+
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
575 |
+
bookmarks_html = display_bookmarks(bookmarks)
|
576 |
+
return choices, bookmarks_html
|
577 |
+
else:
|
578 |
+
return [], ""
|
579 |
+
|
580 |
+
refresh_button.click(
|
581 |
+
refresh_manage_tab,
|
582 |
+
inputs=[state_bookmarks],
|
583 |
+
outputs=[bookmark_selector, bookmark_display_manage]
|
584 |
+
)
|
585 |
|
586 |
# Define button actions
|
587 |
delete_button.click(
|
588 |
delete_selected_bookmarks,
|
589 |
+
inputs=[bookmark_selector, state_bookmarks],
|
590 |
outputs=[manage_output, bookmark_selector, bookmark_display_manage]
|
591 |
)
|
592 |
|
593 |
edit_category_button.click(
|
594 |
edit_selected_bookmarks_category,
|
595 |
+
inputs=[bookmark_selector, new_category_input, state_bookmarks],
|
596 |
outputs=[manage_output, bookmark_selector, bookmark_display_manage]
|
597 |
)
|
598 |
|
599 |
export_button.click(
|
600 |
export_bookmarks,
|
601 |
+
inputs=[state_bookmarks],
|
602 |
outputs=download_link
|
603 |
)
|
604 |
|
605 |
+
logger.info("Launching Gradio app")
|
606 |
+
demo.launch(debug=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
607 |
except Exception as e:
|
608 |
logger.error(f"Error building the app: {e}")
|
609 |
print(f"Error building the app: {e}")
|