Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -28,9 +28,7 @@ llama_cloud_api_key = os.environ.get("LLAMA_CLOUD_API_KEY")
|
|
28 |
ACCOUNT_ID = os.environ.get("CLOUDFARE_ACCOUNT_ID")
|
29 |
API_TOKEN = os.environ.get("CLOUDFLARE_AUTH_TOKEN")
|
30 |
API_BASE_URL = "https://api.cloudflare.com/client/v4/accounts/a17f03e0f049ccae0c15cdcf3b9737ce/ai/run/"
|
31 |
-
|
32 |
-
# Add this to your existing imports and configurations
|
33 |
-
whisper_client = InferenceClient("openai/whisper-large-v3", token=huggingface_token)
|
34 |
|
35 |
print(f"ACCOUNT_ID: {ACCOUNT_ID}")
|
36 |
print(f"CLOUDFLARE_AUTH_TOKEN: {API_TOKEN[:5]}..." if API_TOKEN else "Not set")
|
@@ -280,46 +278,21 @@ def generate_chunked_response(prompt, model, max_tokens=10000, num_calls=3, temp
|
|
280 |
print(f"Final clean response: {final_response[:100]}...")
|
281 |
return final_response
|
282 |
|
283 |
-
def chatbot_interface(message, history, model, temperature, num_calls
|
|
|
|
|
|
|
|
|
|
|
284 |
try:
|
285 |
-
|
286 |
-
history =
|
287 |
-
|
288 |
-
# Prioritize text input
|
289 |
-
if message and isinstance(message, str) and message.strip():
|
290 |
-
input_text = message.strip()
|
291 |
-
elif audio is not None:
|
292 |
-
# Only use audio if text input is empty and audio is provided
|
293 |
-
transcribed_text = transcribe_audio(audio)
|
294 |
-
if transcribed_text:
|
295 |
-
input_text = transcribed_text
|
296 |
-
else:
|
297 |
-
return history # Return if both text and audio are empty
|
298 |
-
else:
|
299 |
-
return history # Return if both text and audio are empty
|
300 |
-
|
301 |
-
# Add user message to history
|
302 |
-
history.append((input_text, None))
|
303 |
-
|
304 |
-
# Get response from the model
|
305 |
-
response_generator = respond(input_text, history, model, temperature, num_calls, use_web_search, selected_docs)
|
306 |
-
|
307 |
-
full_response = ""
|
308 |
-
for partial_response in response_generator:
|
309 |
-
full_response += str(partial_response)
|
310 |
-
# Update the last message in history
|
311 |
-
history[-1] = (input_text, full_response)
|
312 |
-
yield history
|
313 |
-
|
314 |
-
# If no response was generated, yield an error message
|
315 |
-
if not full_response:
|
316 |
-
history[-1] = (input_text, "I'm sorry, I couldn't generate a response. Please try again.")
|
317 |
yield history
|
318 |
-
|
|
|
319 |
except Exception as e:
|
320 |
-
logging.error(f"
|
321 |
-
|
322 |
-
history.append((input_text if 'input_text' in locals() else "Error", error_message))
|
323 |
yield history
|
324 |
|
325 |
def retry_last_response(history, model, temperature, num_calls):
|
@@ -430,12 +403,13 @@ def respond(message, history, model, temperature, num_calls, use_web_search, sel
|
|
430 |
logging.info(f"Model Used: {model}")
|
431 |
logging.info(f"Selected Documents: {selected_docs}")
|
432 |
logging.info(f"Use Web Search: {use_web_search}")
|
433 |
-
|
434 |
if use_web_search:
|
435 |
original_query = message
|
436 |
rephrased_query = rephrase_query(message, conversation_manager)
|
437 |
logging.info(f"Original query: {original_query}")
|
438 |
logging.info(f"Rephrased query: {rephrased_query}")
|
|
|
439 |
final_summary = ""
|
440 |
for _ in range(num_calls):
|
441 |
search_results = get_web_search_results(rephrased_query)
|
@@ -445,7 +419,8 @@ def respond(message, history, model, temperature, num_calls, use_web_search, sel
|
|
445 |
final_summary += search_results[0]["error"] + "\n\n"
|
446 |
else:
|
447 |
summary = summarize_web_results(rephrased_query, search_results, conversation_manager)
|
448 |
-
final_summary +=
|
|
|
449 |
if final_summary:
|
450 |
conversation_manager.add_interaction(original_query, final_summary)
|
451 |
yield final_summary
|
@@ -476,21 +451,21 @@ def respond(message, history, model, temperature, num_calls, use_web_search, sel
|
|
476 |
if model.startswith("duckduckgo/"):
|
477 |
# Use DuckDuckGo chat with context
|
478 |
for partial_response in get_response_from_duckduckgo(message, model, context_str, num_calls, temperature):
|
479 |
-
yield
|
480 |
elif model == "@cf/meta/llama-3.1-8b-instruct":
|
481 |
# Use Cloudflare API
|
482 |
for partial_response in get_response_from_cloudflare(prompt="", context=context_str, query=message, num_calls=num_calls, temperature=temperature, search_type="pdf"):
|
483 |
-
yield
|
484 |
else:
|
485 |
# Use Hugging Face API
|
486 |
for partial_response in get_response_from_pdf(message, model, selected_docs, num_calls=num_calls, temperature=temperature):
|
487 |
-
yield
|
488 |
except Exception as e:
|
489 |
logging.error(f"Error with {model}: {str(e)}")
|
490 |
if "microsoft/Phi-3-mini-4k-instruct" in model:
|
491 |
logging.info("Falling back to Mistral model due to Phi-3 error")
|
492 |
fallback_model = "mistralai/Mistral-7B-Instruct-v0.3"
|
493 |
-
yield from
|
494 |
else:
|
495 |
yield f"An error occurred with the {model} model: {str(e)}. Please try again or select a different model."
|
496 |
|
@@ -632,28 +607,15 @@ Write a detailed and complete response that answers the following user question:
|
|
632 |
|
633 |
logging.info("Finished generating response")
|
634 |
|
635 |
-
def
|
636 |
if audio_file is None:
|
637 |
return ""
|
638 |
|
639 |
-
|
640 |
-
|
641 |
-
return ""
|
642 |
-
audio_file = audio_file[0] # Take the first element if it's a list
|
643 |
-
|
644 |
-
if not isinstance(audio_file, (str, bytes, os.PathLike)):
|
645 |
-
logging.error(f"Unexpected audio_file type: {type(audio_file)}")
|
646 |
-
return f"Error: Unexpected audio file type {type(audio_file)}"
|
647 |
|
648 |
-
|
649 |
-
|
650 |
-
data = f.read()
|
651 |
-
|
652 |
-
response = whisper_client.audio_to_text(data)
|
653 |
-
return response["text"]
|
654 |
-
except Exception as e:
|
655 |
-
logging.error(f"Error transcribing audio: {str(e)}")
|
656 |
-
return f"Error transcribing audio: {str(e)}"
|
657 |
|
658 |
def vote(data: gr.LikeData):
|
659 |
if data.liked:
|
@@ -704,42 +666,74 @@ use_web_search = gr.Checkbox(label="Use Web Search", value=False)
|
|
704 |
|
705 |
custom_placeholder = "Ask a question (Note: You can toggle between Web Search and PDF Chat in Additional Inputs below)"
|
706 |
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
additional_inputs_accordion=gr.Accordion(label="⚙️ Parameters", open=True, render=False),
|
712 |
-
additional_inputs=[
|
713 |
-
gr.Dropdown(choices=MODELS, label="Select Model", value=MODELS[3]),
|
714 |
-
gr.Slider(minimum=0.1, maximum=1.0, value=0.2, step=0.1, label="Temperature"),
|
715 |
-
gr.Slider(minimum=1, maximum=5, value=1, step=1, label="Number of API Calls"),
|
716 |
-
gr.Checkbox(label="Use Web Search", value=True),
|
717 |
-
gr.CheckboxGroup(label="Select documents to query"),
|
718 |
-
gr.Audio(sources="microphone", type="filepath", label="Or speak your question (optional)")
|
719 |
],
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
# ... (keep the existing theme configuration)
|
724 |
-
),
|
725 |
-
css=css,
|
726 |
-
examples=[
|
727 |
-
# ... (keep the existing examples)
|
728 |
-
],
|
729 |
-
cache_examples=False,
|
730 |
-
analytics_enabled=False,
|
731 |
-
textbox=gr.Textbox(placeholder="Type or speak your question", container=False, scale=7),
|
732 |
-
chatbot = gr.Chatbot(
|
733 |
-
show_copy_button=True,
|
734 |
-
likeable=True,
|
735 |
-
layout="bubble",
|
736 |
-
height=400,
|
737 |
-
value=initial_conversation()
|
738 |
-
)
|
739 |
)
|
740 |
|
741 |
-
#
|
742 |
-
with demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
743 |
gr.Markdown("## Upload and Manage PDF Documents")
|
744 |
with gr.Row():
|
745 |
file_input = gr.Files(label="Upload your PDF documents", file_types=[".pdf"])
|
@@ -754,35 +748,35 @@ with demo:
|
|
754 |
update_button.click(
|
755 |
update_vectors,
|
756 |
inputs=[file_input, parser_dropdown],
|
757 |
-
outputs=[update_output,
|
758 |
)
|
759 |
|
760 |
# Add the refresh button functionality
|
761 |
refresh_button.click(
|
762 |
refresh_documents,
|
763 |
inputs=[],
|
764 |
-
outputs=[
|
765 |
)
|
766 |
|
767 |
# Add the delete button functionality
|
768 |
delete_button.click(
|
769 |
delete_documents,
|
770 |
-
inputs=[
|
771 |
-
outputs=[update_output,
|
772 |
)
|
773 |
|
774 |
gr.Markdown(
|
775 |
"""
|
776 |
## How to use
|
777 |
-
1.
|
778 |
-
2.
|
779 |
-
3. Select the
|
780 |
-
4.
|
781 |
-
5.
|
782 |
-
6.
|
783 |
-
7.
|
|
|
784 |
"""
|
785 |
)
|
786 |
-
|
787 |
if __name__ == "__main__":
|
788 |
demo.launch(share=True)
|
|
|
28 |
ACCOUNT_ID = os.environ.get("CLOUDFARE_ACCOUNT_ID")
|
29 |
API_TOKEN = os.environ.get("CLOUDFLARE_AUTH_TOKEN")
|
30 |
API_BASE_URL = "https://api.cloudflare.com/client/v4/accounts/a17f03e0f049ccae0c15cdcf3b9737ce/ai/run/"
|
31 |
+
whisper_api = InferenceApi("openai/whisper-large-v2", token=huggingface_token)
|
|
|
|
|
32 |
|
33 |
print(f"ACCOUNT_ID: {ACCOUNT_ID}")
|
34 |
print(f"CLOUDFLARE_AUTH_TOKEN: {API_TOKEN[:5]}..." if API_TOKEN else "Not set")
|
|
|
278 |
print(f"Final clean response: {final_response[:100]}...")
|
279 |
return final_response
|
280 |
|
281 |
+
def chatbot_interface(message, history, model, temperature, num_calls):
|
282 |
+
if not message.strip():
|
283 |
+
return "", history
|
284 |
+
|
285 |
+
history = history + [(message, "")]
|
286 |
+
|
287 |
try:
|
288 |
+
for response in respond(message, history, model, temperature, num_calls):
|
289 |
+
history[-1] = (message, response)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
yield history
|
291 |
+
except gr.CancelledError:
|
292 |
+
yield history
|
293 |
except Exception as e:
|
294 |
+
logging.error(f"Unexpected error in chatbot_interface: {str(e)}")
|
295 |
+
history[-1] = (message, f"An unexpected error occurred: {str(e)}")
|
|
|
296 |
yield history
|
297 |
|
298 |
def retry_last_response(history, model, temperature, num_calls):
|
|
|
403 |
logging.info(f"Model Used: {model}")
|
404 |
logging.info(f"Selected Documents: {selected_docs}")
|
405 |
logging.info(f"Use Web Search: {use_web_search}")
|
406 |
+
|
407 |
if use_web_search:
|
408 |
original_query = message
|
409 |
rephrased_query = rephrase_query(message, conversation_manager)
|
410 |
logging.info(f"Original query: {original_query}")
|
411 |
logging.info(f"Rephrased query: {rephrased_query}")
|
412 |
+
|
413 |
final_summary = ""
|
414 |
for _ in range(num_calls):
|
415 |
search_results = get_web_search_results(rephrased_query)
|
|
|
419 |
final_summary += search_results[0]["error"] + "\n\n"
|
420 |
else:
|
421 |
summary = summarize_web_results(rephrased_query, search_results, conversation_manager)
|
422 |
+
final_summary += summary + "\n\n"
|
423 |
+
|
424 |
if final_summary:
|
425 |
conversation_manager.add_interaction(original_query, final_summary)
|
426 |
yield final_summary
|
|
|
451 |
if model.startswith("duckduckgo/"):
|
452 |
# Use DuckDuckGo chat with context
|
453 |
for partial_response in get_response_from_duckduckgo(message, model, context_str, num_calls, temperature):
|
454 |
+
yield partial_response
|
455 |
elif model == "@cf/meta/llama-3.1-8b-instruct":
|
456 |
# Use Cloudflare API
|
457 |
for partial_response in get_response_from_cloudflare(prompt="", context=context_str, query=message, num_calls=num_calls, temperature=temperature, search_type="pdf"):
|
458 |
+
yield partial_response
|
459 |
else:
|
460 |
# Use Hugging Face API
|
461 |
for partial_response in get_response_from_pdf(message, model, selected_docs, num_calls=num_calls, temperature=temperature):
|
462 |
+
yield partial_response
|
463 |
except Exception as e:
|
464 |
logging.error(f"Error with {model}: {str(e)}")
|
465 |
if "microsoft/Phi-3-mini-4k-instruct" in model:
|
466 |
logging.info("Falling back to Mistral model due to Phi-3 error")
|
467 |
fallback_model = "mistralai/Mistral-7B-Instruct-v0.3"
|
468 |
+
yield from respond(message, history, fallback_model, temperature, num_calls, selected_docs)
|
469 |
else:
|
470 |
yield f"An error occurred with the {model} model: {str(e)}. Please try again or select a different model."
|
471 |
|
|
|
607 |
|
608 |
logging.info("Finished generating response")
|
609 |
|
610 |
+
def transcribe(audio_file):
|
611 |
if audio_file is None:
|
612 |
return ""
|
613 |
|
614 |
+
with open(audio_file, "rb") as f:
|
615 |
+
audio_data = f.read()
|
|
|
|
|
|
|
|
|
|
|
|
|
616 |
|
617 |
+
response = whisper_api(audio_data)
|
618 |
+
return response["text"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
619 |
|
620 |
def vote(data: gr.LikeData):
|
621 |
if data.liked:
|
|
|
666 |
|
667 |
custom_placeholder = "Ask a question (Note: You can toggle between Web Search and PDF Chat in Additional Inputs below)"
|
668 |
|
669 |
+
asr_interface = gr.Interface(
|
670 |
+
fn=transcribe,
|
671 |
+
inputs=[
|
672 |
+
gr.Audio(sources="microphone", type="filepath", optional=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
673 |
],
|
674 |
+
outputs="text",
|
675 |
+
title="Speech to Text",
|
676 |
+
description="Speak your query, and it will be transcribed."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
677 |
)
|
678 |
|
679 |
+
# Update the Gradio interface
|
680 |
+
with gr.Blocks() as demo:
|
681 |
+
gr.Markdown("# AI-powered PDF Chat and Web Search Assistant with Speech Input")
|
682 |
+
|
683 |
+
with gr.Row():
|
684 |
+
with gr.Column(scale=1):
|
685 |
+
asr_interface.render()
|
686 |
+
|
687 |
+
with gr.Column(scale=2):
|
688 |
+
chatbot = gr.ChatInterface(
|
689 |
+
respond,
|
690 |
+
additional_inputs=[
|
691 |
+
gr.Dropdown(choices=MODELS, label="Select Model", value=MODELS[3]),
|
692 |
+
gr.Slider(minimum=0.1, maximum=1.0, value=0.2, step=0.1, label="Temperature"),
|
693 |
+
gr.Slider(minimum=1, maximum=5, value=1, step=1, label="Number of API Calls"),
|
694 |
+
gr.Checkbox(label="Use Web Search", value=True),
|
695 |
+
gr.CheckboxGroup(label="Select documents to query")
|
696 |
+
],
|
697 |
+
title="Chat with PDFs or Web Search",
|
698 |
+
description="Chat with your PDFs or use web search to answer questions.",
|
699 |
+
theme=gr.themes.Soft(
|
700 |
+
primary_hue="orange",
|
701 |
+
secondary_hue="amber",
|
702 |
+
neutral_hue="gray",
|
703 |
+
font=[gr.themes.GoogleFont("Exo"), "ui-sans-serif", "system-ui", "sans-serif"]
|
704 |
+
).set(
|
705 |
+
body_background_fill_dark="#0c0505",
|
706 |
+
block_background_fill_dark="#0c0505",
|
707 |
+
block_border_width="1px",
|
708 |
+
block_title_background_fill_dark="#1b0f0f",
|
709 |
+
input_background_fill_dark="#140b0b",
|
710 |
+
button_secondary_background_fill_dark="#140b0b",
|
711 |
+
border_color_accent_dark="#1b0f0f",
|
712 |
+
border_color_primary_dark="#1b0f0f",
|
713 |
+
background_fill_secondary_dark="#0c0505",
|
714 |
+
color_accent_soft_dark="transparent",
|
715 |
+
code_background_fill_dark="#140b0b"
|
716 |
+
),
|
717 |
+
css=css,
|
718 |
+
examples=[
|
719 |
+
["Tell me about the contents of the uploaded PDFs."],
|
720 |
+
["What are the main topics discussed in the documents?"],
|
721 |
+
["Can you summarize the key points from the PDFs?"],
|
722 |
+
["What's the latest news about artificial intelligence?"]
|
723 |
+
],
|
724 |
+
cache_examples=False,
|
725 |
+
analytics_enabled=False,
|
726 |
+
textbox=gr.Textbox(placeholder="Ask a question about the uploaded PDFs or any topic", container=False, scale=7),
|
727 |
+
chatbot=gr.Chatbot(
|
728 |
+
show_copy_button=True,
|
729 |
+
likeable=True,
|
730 |
+
layout="bubble",
|
731 |
+
height=400,
|
732 |
+
value=initial_conversation()
|
733 |
+
)
|
734 |
+
)
|
735 |
+
|
736 |
+
# Add file upload functionality
|
737 |
gr.Markdown("## Upload and Manage PDF Documents")
|
738 |
with gr.Row():
|
739 |
file_input = gr.Files(label="Upload your PDF documents", file_types=[".pdf"])
|
|
|
748 |
update_button.click(
|
749 |
update_vectors,
|
750 |
inputs=[file_input, parser_dropdown],
|
751 |
+
outputs=[update_output, chatbot.additional_inputs[-1]]
|
752 |
)
|
753 |
|
754 |
# Add the refresh button functionality
|
755 |
refresh_button.click(
|
756 |
refresh_documents,
|
757 |
inputs=[],
|
758 |
+
outputs=[chatbot.additional_inputs[-1]]
|
759 |
)
|
760 |
|
761 |
# Add the delete button functionality
|
762 |
delete_button.click(
|
763 |
delete_documents,
|
764 |
+
inputs=[chatbot.additional_inputs[-1]],
|
765 |
+
outputs=[update_output, chatbot.additional_inputs[-1]]
|
766 |
)
|
767 |
|
768 |
gr.Markdown(
|
769 |
"""
|
770 |
## How to use
|
771 |
+
1. Use the microphone to speak your query, or type it in the chat interface.
|
772 |
+
2. Upload PDF documents using the file input at the bottom.
|
773 |
+
3. Select the PDF parser (pypdf or llamaparse) and click "Upload Document" to update the vector store.
|
774 |
+
4. Select the documents you want to query using the checkboxes.
|
775 |
+
5. Ask questions in the chat interface.
|
776 |
+
6. Toggle "Use Web Search" to switch between PDF chat and web search.
|
777 |
+
7. Adjust Temperature and Number of API Calls to fine-tune the response generation.
|
778 |
+
8. Use the provided examples or ask your own questions.
|
779 |
"""
|
780 |
)
|
|
|
781 |
if __name__ == "__main__":
|
782 |
demo.launch(share=True)
|