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)
|