Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -276,29 +276,29 @@ def process_uploaded_file(file):
|
|
276 |
logger.info("Processing uploaded file")
|
277 |
if file is None:
|
278 |
logger.warning("No file uploaded")
|
279 |
-
return "Please upload a bookmarks HTML file.", ''
|
280 |
try:
|
281 |
file_content = file.decode('utf-8')
|
282 |
except UnicodeDecodeError as e:
|
283 |
logger.error(f"Error decoding the file: {e}")
|
284 |
-
return "Error decoding the file. Please ensure it's a valid HTML file.", ''
|
285 |
|
286 |
try:
|
287 |
bookmarks = parse_bookmarks(file_content)
|
288 |
except Exception as e:
|
289 |
logger.error(f"Error parsing bookmarks: {e}")
|
290 |
-
return "Error parsing the bookmarks HTML file.", ''
|
291 |
|
292 |
if not bookmarks:
|
293 |
logger.warning("No bookmarks found in the uploaded file")
|
294 |
-
return "No bookmarks found in the uploaded file.", ''
|
295 |
|
296 |
# Asynchronously fetch bookmark info
|
297 |
try:
|
298 |
asyncio.run(process_bookmarks_async(bookmarks))
|
299 |
except Exception as e:
|
300 |
logger.error(f"Error processing bookmarks asynchronously: {e}")
|
301 |
-
return "Error processing bookmarks.", ''
|
302 |
|
303 |
# Generate summaries and assign categories
|
304 |
for bookmark in bookmarks:
|
@@ -309,12 +309,90 @@ def process_uploaded_file(file):
|
|
309 |
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
310 |
except Exception as e:
|
311 |
logger.error(f"Error building FAISS index: {e}")
|
312 |
-
return "Error building search index.", ''
|
313 |
|
314 |
message = f"Successfully processed {len(bookmarks)} bookmarks."
|
315 |
logger.info(message)
|
316 |
bookmark_html = display_bookmarks()
|
317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
|
319 |
# Chatbot response using Groq Cloud API
|
320 |
def chatbot_response(user_query):
|
@@ -371,82 +449,6 @@ Please identify the most relevant bookmarks that match the user's query. Provide
|
|
371 |
print(error_message) # Ensure error appears in Hugging Face Spaces logs
|
372 |
return error_message
|
373 |
|
374 |
-
# Edit a bookmark
|
375 |
-
def edit_bookmark(bookmark_idx, new_title, new_url, new_category):
|
376 |
-
global faiss_index
|
377 |
-
try:
|
378 |
-
bookmark_idx = int(bookmark_idx) - 1 # Adjust index to match list (starting at 0)
|
379 |
-
if bookmark_idx < 0 or bookmark_idx >= len(bookmarks):
|
380 |
-
logger.warning(f"Invalid bookmark index for editing: {bookmark_idx + 1}")
|
381 |
-
return "Invalid bookmark index.", display_bookmarks()
|
382 |
-
logger.info(f"Editing bookmark at index {bookmark_idx + 1}")
|
383 |
-
bookmarks[bookmark_idx]['title'] = new_title
|
384 |
-
bookmarks[bookmark_idx]['url'] = new_url
|
385 |
-
bookmarks[bookmark_idx]['category'] = new_category
|
386 |
-
# Re-fetch bookmark info
|
387 |
-
asyncio.run(process_bookmarks_async([bookmarks[bookmark_idx]]))
|
388 |
-
generate_summary(bookmarks[bookmark_idx])
|
389 |
-
# Rebuild the FAISS index
|
390 |
-
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
391 |
-
message = "Bookmark updated successfully."
|
392 |
-
logger.info(message)
|
393 |
-
updated_html = display_bookmarks()
|
394 |
-
return message, updated_html
|
395 |
-
except Exception as e:
|
396 |
-
logger.error(f"Error editing bookmark: {e}")
|
397 |
-
return f"Error: {str(e)}", display_bookmarks()
|
398 |
-
|
399 |
-
# Delete selected bookmarks
|
400 |
-
def delete_bookmarks(indices_str):
|
401 |
-
global faiss_index
|
402 |
-
try:
|
403 |
-
indices = [int(idx.strip()) - 1 for idx in indices_str.split(',') if idx.strip().isdigit()]
|
404 |
-
indices = sorted(indices, reverse=True)
|
405 |
-
logger.info(f"Deleting bookmarks at indices: {indices}")
|
406 |
-
for idx in indices:
|
407 |
-
if 0 <= idx < len(bookmarks):
|
408 |
-
logger.info(f"Deleting bookmark at index {idx + 1}")
|
409 |
-
bookmarks.pop(idx)
|
410 |
-
# Rebuild the FAISS index
|
411 |
-
if bookmarks:
|
412 |
-
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
413 |
-
else:
|
414 |
-
faiss_index = None
|
415 |
-
message = "Selected bookmarks deleted successfully."
|
416 |
-
logger.info(message)
|
417 |
-
updated_html = display_bookmarks()
|
418 |
-
return message, updated_html
|
419 |
-
except Exception as e:
|
420 |
-
logger.error(f"Error deleting bookmarks: {e}")
|
421 |
-
return f"Error: {str(e)}", display_bookmarks()
|
422 |
-
|
423 |
-
# Export bookmarks to HTML
|
424 |
-
def export_bookmarks():
|
425 |
-
if not bookmarks:
|
426 |
-
logger.warning("No bookmarks to export")
|
427 |
-
return None
|
428 |
-
try:
|
429 |
-
logger.info("Exporting bookmarks to HTML")
|
430 |
-
# Create an HTML content similar to the imported bookmarks file
|
431 |
-
soup = BeautifulSoup("<!DOCTYPE NETSCAPE-Bookmark-file-1><Title>Bookmarks</Title><H1>Bookmarks</H1>", 'html.parser')
|
432 |
-
dl = soup.new_tag('DL')
|
433 |
-
for bookmark in bookmarks:
|
434 |
-
dt = soup.new_tag('DT')
|
435 |
-
a = soup.new_tag('A', href=bookmark['url'])
|
436 |
-
a.string = bookmark['title']
|
437 |
-
dt.append(a)
|
438 |
-
dl.append(dt)
|
439 |
-
soup.append(dl)
|
440 |
-
html_content = str(soup)
|
441 |
-
# Encode the HTML content to base64 for download
|
442 |
-
b64 = base64.b64encode(html_content.encode()).decode()
|
443 |
-
href = f'data:text/html;base64,{b64}'
|
444 |
-
logger.info("Bookmarks exported successfully")
|
445 |
-
return href
|
446 |
-
except Exception as e:
|
447 |
-
logger.error(f"Error exporting bookmarks: {e}")
|
448 |
-
return None
|
449 |
-
|
450 |
# Build the Gradio app
|
451 |
def build_app():
|
452 |
try:
|
@@ -464,9 +466,9 @@ def build_app():
|
|
464 |
return process_uploaded_file(file)
|
465 |
|
466 |
process_button.click(
|
467 |
-
|
468 |
inputs=upload,
|
469 |
-
outputs=[output_text, bookmark_display]
|
470 |
)
|
471 |
|
472 |
with gr.Tab("Chat with Bookmarks"):
|
@@ -481,59 +483,46 @@ def build_app():
|
|
481 |
)
|
482 |
|
483 |
with gr.Tab("Manage Bookmarks"):
|
484 |
-
manage_output = gr.Textbox(label="Manage Output")
|
485 |
bookmark_display_manage = gr.HTML(label="Bookmarks")
|
486 |
-
|
487 |
-
|
488 |
-
indices_input = gr.Textbox(label="Bookmark Indices to Delete (comma-separated)")
|
489 |
-
delete_button = gr.Button("Delete Selected Bookmarks")
|
490 |
-
export_button = gr.Button("Export Bookmarks")
|
491 |
-
download_link = gr.HTML(label="Download Exported Bookmarks")
|
492 |
|
|
|
493 |
with gr.Row():
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
edit_button = gr.Button("Edit Bookmark")
|
500 |
-
|
501 |
-
def update_manage_display():
|
502 |
-
return display_bookmarks()
|
503 |
-
|
504 |
-
refresh_button.click(
|
505 |
-
update_manage_display,
|
506 |
-
inputs=None,
|
507 |
-
outputs=bookmark_display_manage
|
508 |
-
)
|
509 |
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
outputs=[manage_output, bookmark_display_manage]
|
514 |
-
)
|
515 |
|
|
|
516 |
delete_button.click(
|
517 |
-
|
518 |
-
inputs=
|
519 |
-
outputs=[manage_output, bookmark_display_manage]
|
520 |
)
|
521 |
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
return "No bookmarks to export."
|
528 |
|
529 |
export_button.click(
|
530 |
-
|
531 |
inputs=None,
|
532 |
outputs=download_link
|
533 |
)
|
534 |
|
535 |
-
#
|
536 |
-
|
|
|
|
|
|
|
|
|
537 |
|
538 |
logger.info("Launching Gradio app")
|
539 |
demo.launch(debug=True)
|
|
|
276 |
logger.info("Processing uploaded file")
|
277 |
if file is None:
|
278 |
logger.warning("No file uploaded")
|
279 |
+
return "Please upload a bookmarks HTML file.", '', gr.update(), ''
|
280 |
try:
|
281 |
file_content = file.decode('utf-8')
|
282 |
except UnicodeDecodeError as e:
|
283 |
logger.error(f"Error decoding the file: {e}")
|
284 |
+
return "Error decoding the file. Please ensure it's a valid HTML file.", '', gr.update(), ''
|
285 |
|
286 |
try:
|
287 |
bookmarks = parse_bookmarks(file_content)
|
288 |
except Exception as e:
|
289 |
logger.error(f"Error parsing bookmarks: {e}")
|
290 |
+
return "Error parsing the bookmarks HTML file.", '', gr.update(), ''
|
291 |
|
292 |
if not bookmarks:
|
293 |
logger.warning("No bookmarks found in the uploaded file")
|
294 |
+
return "No bookmarks found in the uploaded file.", '', gr.update(), ''
|
295 |
|
296 |
# Asynchronously fetch bookmark info
|
297 |
try:
|
298 |
asyncio.run(process_bookmarks_async(bookmarks))
|
299 |
except Exception as e:
|
300 |
logger.error(f"Error processing bookmarks asynchronously: {e}")
|
301 |
+
return "Error processing bookmarks.", '', gr.update(), ''
|
302 |
|
303 |
# Generate summaries and assign categories
|
304 |
for bookmark in bookmarks:
|
|
|
309 |
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
310 |
except Exception as e:
|
311 |
logger.error(f"Error building FAISS index: {e}")
|
312 |
+
return "Error building search index.", '', gr.update(), ''
|
313 |
|
314 |
message = f"Successfully processed {len(bookmarks)} bookmarks."
|
315 |
logger.info(message)
|
316 |
bookmark_html = display_bookmarks()
|
317 |
+
|
318 |
+
# Update bookmark_selector choices
|
319 |
+
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
320 |
+
bookmark_selector_update = gr.update(choices=choices, value=[])
|
321 |
+
|
322 |
+
# Update bookmark_display_manage
|
323 |
+
bookmark_display_manage_update = display_bookmarks()
|
324 |
+
|
325 |
+
return message, bookmark_html, bookmark_selector_update, bookmark_display_manage_update
|
326 |
+
|
327 |
+
# Delete selected bookmarks
|
328 |
+
def delete_selected_bookmarks(selected_indices):
|
329 |
+
global bookmarks, faiss_index
|
330 |
+
if not selected_indices:
|
331 |
+
return "No bookmarks selected.", gr.update(), ''
|
332 |
+
indices = [int(s.split('.')[0])-1 for s in selected_indices]
|
333 |
+
indices = sorted(indices, reverse=True)
|
334 |
+
for idx in indices:
|
335 |
+
if 0 <= idx < len(bookmarks):
|
336 |
+
logger.info(f"Deleting bookmark at index {idx + 1}")
|
337 |
+
bookmarks.pop(idx)
|
338 |
+
if bookmarks:
|
339 |
+
faiss_index, embeddings = vectorize_and_index(bookmarks)
|
340 |
+
else:
|
341 |
+
faiss_index = None
|
342 |
+
message = "Selected bookmarks deleted successfully."
|
343 |
+
logger.info(message)
|
344 |
+
# Update bookmark_selector choices
|
345 |
+
choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
346 |
+
bookmark_selector_update = gr.update(choices=choices, value=[])
|
347 |
+
# Update bookmarks display
|
348 |
+
bookmarks_html = display_bookmarks()
|
349 |
+
return message, bookmark_selector_update, bookmarks_html
|
350 |
+
|
351 |
+
# Edit category of selected bookmarks
|
352 |
+
def edit_selected_bookmarks_category(selected_indices, new_category):
|
353 |
+
if not selected_indices:
|
354 |
+
return "No bookmarks selected.", '', gr.update()
|
355 |
+
if not new_category:
|
356 |
+
return "No new category selected.", '', gr.update()
|
357 |
+
indices = [int(s.split('.')[0])-1 for s in selected_indices]
|
358 |
+
for idx in indices:
|
359 |
+
if 0 <= idx < len(bookmarks):
|
360 |
+
bookmarks[idx]['category'] = 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."
|
375 |
+
try:
|
376 |
+
logger.info("Exporting bookmarks to HTML")
|
377 |
+
# Create an HTML content similar to the imported bookmarks file
|
378 |
+
soup = BeautifulSoup("<!DOCTYPE NETSCAPE-Bookmark-file-1><Title>Bookmarks</Title><H1>Bookmarks</H1>", 'html.parser')
|
379 |
+
dl = soup.new_tag('DL')
|
380 |
+
for bookmark in bookmarks:
|
381 |
+
dt = soup.new_tag('DT')
|
382 |
+
a = soup.new_tag('A', href=bookmark['url'])
|
383 |
+
a.string = bookmark['title']
|
384 |
+
dt.append(a)
|
385 |
+
dl.append(dt)
|
386 |
+
soup.append(dl)
|
387 |
+
html_content = str(soup)
|
388 |
+
# Encode the HTML content to base64 for download
|
389 |
+
b64 = base64.b64encode(html_content.encode()).decode()
|
390 |
+
href = f'data:text/html;base64,{b64}'
|
391 |
+
logger.info("Bookmarks exported successfully")
|
392 |
+
return f'<a href="{href}" download="bookmarks.html">Download Exported Bookmarks</a>'
|
393 |
+
except Exception as e:
|
394 |
+
logger.error(f"Error exporting bookmarks: {e}")
|
395 |
+
return "Error exporting bookmarks."
|
396 |
|
397 |
# Chatbot response using Groq Cloud API
|
398 |
def chatbot_response(user_query):
|
|
|
449 |
print(error_message) # Ensure error appears in Hugging Face Spaces logs
|
450 |
return error_message
|
451 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
452 |
# Build the Gradio app
|
453 |
def build_app():
|
454 |
try:
|
|
|
466 |
return process_uploaded_file(file)
|
467 |
|
468 |
process_button.click(
|
469 |
+
process_uploaded_file,
|
470 |
inputs=upload,
|
471 |
+
outputs=[output_text, bookmark_display, gr.State(), gr.State()]
|
472 |
)
|
473 |
|
474 |
with gr.Tab("Chat with Bookmarks"):
|
|
|
483 |
)
|
484 |
|
485 |
with gr.Tab("Manage Bookmarks"):
|
486 |
+
manage_output = gr.Textbox(label="Manage Output", interactive=False)
|
487 |
bookmark_display_manage = gr.HTML(label="Bookmarks")
|
488 |
+
bookmark_selector = gr.CheckboxGroup(label="Select Bookmarks", choices=[])
|
|
|
|
|
|
|
|
|
|
|
489 |
|
490 |
+
new_category_input = gr.Dropdown(label="New Category", choices=CATEGORIES)
|
491 |
with gr.Row():
|
492 |
+
delete_button = gr.Button("Delete Selected Bookmarks")
|
493 |
+
edit_category_button = gr.Button("Edit Category of Selected Bookmarks")
|
494 |
+
export_button = gr.Button("Export Bookmarks")
|
495 |
+
download_link = gr.HTML(label="Download Exported Bookmarks")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
|
497 |
+
# Update the bookmark display and selector when the app loads
|
498 |
+
bookmark_display_manage.value = display_bookmarks()
|
499 |
+
bookmark_selector.choices = [f"{i+1}. {bookmark['title']} (Category: {bookmark['category']})" for i, bookmark in enumerate(bookmarks)]
|
|
|
|
|
500 |
|
501 |
+
# Define button actions
|
502 |
delete_button.click(
|
503 |
+
delete_selected_bookmarks,
|
504 |
+
inputs=bookmark_selector,
|
505 |
+
outputs=[manage_output, bookmark_selector, bookmark_display_manage]
|
506 |
)
|
507 |
|
508 |
+
edit_category_button.click(
|
509 |
+
edit_selected_bookmarks_category,
|
510 |
+
inputs=[bookmark_selector, new_category_input],
|
511 |
+
outputs=[manage_output, bookmark_selector, bookmark_display_manage]
|
512 |
+
)
|
|
|
513 |
|
514 |
export_button.click(
|
515 |
+
export_bookmarks,
|
516 |
inputs=None,
|
517 |
outputs=download_link
|
518 |
)
|
519 |
|
520 |
+
# Update the bookmark display and selector after processing bookmarks
|
521 |
+
process_button.click(
|
522 |
+
process_uploaded_file,
|
523 |
+
inputs=upload,
|
524 |
+
outputs=[output_text, bookmark_display, bookmark_selector, bookmark_display_manage]
|
525 |
+
)
|
526 |
|
527 |
logger.info("Launching Gradio app")
|
528 |
demo.launch(debug=True)
|