Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,3 +1,5 @@
|
|
|
|
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
from huggingface_hub import InferenceClient
|
@@ -89,8 +91,8 @@ def authenticate_google_sheets():
|
|
89 |
return True
|
90 |
except Exception as e:
|
91 |
print(f"Google Sheets authentication failed: {e}")
|
92 |
-
print(traceback.format_exc())
|
93 |
print("Please ensure your GOOGLE_BASE64_CREDENTIALS secret is correctly set and contains valid service account credentials.")
|
|
|
94 |
return False
|
95 |
# Google Sheets Data Loading and Embedding
|
96 |
data = [] # Global variable to store loaded data
|
@@ -372,16 +374,13 @@ def determine_tool_usage(query: str) -> str:
|
|
372 |
|
373 |
|
374 |
# Function to generate text using the LLM, incorporating tool results if available
|
375 |
-
def generate_text(prompt: str, tool_results: dict = None
|
376 |
"""
|
377 |
-
Generates text using the configured LLM, optionally incorporating tool results
|
378 |
-
and conversation history.
|
379 |
Args:
|
380 |
prompt: The initial prompt for the LLM.
|
381 |
tool_results: A dictionary containing results from executed tools.
|
382 |
Keys are tool names, values are their outputs.
|
383 |
-
history: A list of previous messages in the conversation.
|
384 |
-
Expected format: [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]
|
385 |
Returns:
|
386 |
The generated text from the LLM.
|
387 |
"""
|
@@ -390,46 +389,34 @@ def generate_text(prompt: str, tool_results: dict = None, history: list = None)
|
|
390 |
You are a friendly and helpful chatbot. Respond to greetings appropriately (e.g., "Hello!", "Hi there!", "Habari!"). If the user uses Swahili greetings or simple conversational phrases, respond in Swahili. Otherwise, respond in English unless the query is clearly in Swahili. Handle conversational flow and ask follow-up questions when appropriate.
|
391 |
If the user asks a question about other companies or general knowledge, answer their question. However, subtly remind them that your primary expertise and purpose are related to Absa-specific information.
|
392 |
"""
|
|
|
393 |
|
394 |
-
messages = [{"role": "system", "content": persona_instructions}]
|
395 |
-
|
396 |
-
# Add conversation history to the messages, alternating roles
|
397 |
-
if history:
|
398 |
-
print("Adding conversation history to messages.")
|
399 |
-
messages.extend(history) # history is already in the correct format
|
400 |
-
|
401 |
-
# Add the current user prompt
|
402 |
-
current_prompt_content = prompt
|
403 |
if tool_results and any(tool_results.values()):
|
404 |
-
|
405 |
for question, results in tool_results.items(): # Iterate through results per question
|
406 |
if results:
|
407 |
-
|
408 |
if isinstance(results, list):
|
409 |
for i, result in enumerate(results):
|
410 |
# Check if the result is from business info retrieval
|
411 |
if isinstance(result, dict) and 'Service' in result and 'Description' in result:
|
412 |
-
|
413 |
elif isinstance(result, dict) and 'url' in result: # Check if the result is from DuckDuckGo
|
414 |
-
|
415 |
else:
|
416 |
-
|
417 |
elif isinstance(results, dict):
|
418 |
for key, value in results.items():
|
419 |
-
|
420 |
-
|
421 |
else:
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
print("Added tool results and instruction to current prompt.")
|
426 |
else:
|
427 |
-
print("No tool results to add to
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
print(f"Sending messages to LLM:\n---\n{messages}\n---")
|
432 |
-
|
433 |
generation_config = {
|
434 |
"temperature": 0.7,
|
435 |
"max_new_tokens": 500,
|
@@ -439,7 +426,9 @@ If the user asks a question about other companies or general knowledge, answer t
|
|
439 |
}
|
440 |
try:
|
441 |
response = client.chat_completion(
|
442 |
-
messages=
|
|
|
|
|
443 |
max_tokens=generation_config.get("max_new_tokens", 512),
|
444 |
temperature=generation_config.get("temperature", 0.7),
|
445 |
top_p=generation_config.get("top_p", 0.95)
|
@@ -451,43 +440,13 @@ If the user asks a question about other companies or general knowledge, answer t
|
|
451 |
print(traceback.format_exc())
|
452 |
return "An error occurred while generating the final response."
|
453 |
# Main chat function with query breakdown and tool execution per question
|
454 |
-
def chat(query: str,
|
455 |
"""
|
456 |
Processes user queries by breaking down multi-part queries, determining and
|
457 |
executing appropriate tools for each question, and synthesizing results
|
458 |
-
using the LLM
|
459 |
-
Args:
|
460 |
-
query: The user's current query string.
|
461 |
-
history: The conversation history (list of dictionaries).
|
462 |
-
Expected format: [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]
|
463 |
-
Returns:
|
464 |
-
A tuple containing the updated conversation history and the model's response.
|
465 |
"""
|
466 |
print(f"Received query: {query}")
|
467 |
-
print(f"Current history: {history}")
|
468 |
-
|
469 |
-
# Convert history format for LLM (list of lists to list of dictionaries) - this is now handled by the Gradio interface
|
470 |
-
llm_history = history
|
471 |
-
|
472 |
-
|
473 |
-
# Check if the entire query is a simple Swahili greeting/conversational phrase
|
474 |
-
swahili_conversational_phrases = ['habari', 'mambo', 'shikamoo', 'karibu', 'asante', 'habari gani']
|
475 |
-
query_lower = query.lower().strip()
|
476 |
-
if query_lower in swahili_conversational_phrases:
|
477 |
-
print(f"Query is a simple Swahili conversational phrase: '{query}'. Directly calling date_calculation.")
|
478 |
-
# Directly use date_calculation which now handles these simple greetings
|
479 |
-
response = perform_date_calculation(query)
|
480 |
-
if response:
|
481 |
-
print(f"\n--- Direct Swahili Response ---")
|
482 |
-
print(response)
|
483 |
-
print("\n----------------------------")
|
484 |
-
# Append to history and return
|
485 |
-
return history + [{"role": "user", "content": query}, {"role": "assistant", "content": response}], response
|
486 |
-
else:
|
487 |
-
# Fallback if date_calculation didn't handle it
|
488 |
-
print("date_calculation did not handle the Swahili phrase. Proceeding with breakdown.")
|
489 |
-
# Continue to normal query processing if direct handling failed
|
490 |
-
|
491 |
|
492 |
# Step 1: Query Breakdown
|
493 |
print("\n--- Breaking down query ---")
|
@@ -552,22 +511,20 @@ Query: {query}
|
|
552 |
for question, result in tool_results.items():
|
553 |
print(f"\nQuestion: {question}")
|
554 |
print(f"Result: {result}")
|
555 |
-
print("\n--------------------------")
|
556 |
else:
|
557 |
print("No tool results were collected.")
|
558 |
-
|
559 |
-
|
560 |
|
561 |
# Step 5: Final Response Generation
|
562 |
print("\n--- Generating final response ---")
|
563 |
# The generate_text function already handles incorporating tool results if provided
|
564 |
-
final_response = generate_text(query, tool_results
|
565 |
print("\n--- Final Response from LLM ---")
|
566 |
print(final_response)
|
567 |
print("\n----------------------------")
|
568 |
|
569 |
-
#
|
570 |
-
return
|
571 |
|
572 |
|
573 |
# Keep the Gradio interface setup as is for now
|
@@ -588,60 +545,32 @@ if __name__ == "__main__":
|
|
588 |
"RAG will not be available. Please ensure the GOOGLE_BASE64_CREDENTIALS secret is set correctly.")
|
589 |
print("Launching Gradio Interface...")
|
590 |
import gradio as gr
|
591 |
-
with gr.Blocks(theme="soft") as demo:
|
592 |
-
gr.Markdown(
|
593 |
-
"""
|
594 |
-
# LLM with Tools (DuckDuckGo Search, Date Calculation, Business Info RAG)
|
595 |
-
Ask me anything! I can perform web searches, calculate dates, and retrieve business information.
|
596 |
-
"""
|
597 |
-
)
|
598 |
-
chatbot = gr.Chatbot(label="Chat History", show_label=True)
|
599 |
-
msg = gr.Textbox(label="Query", placeholder="Enter your query here....", lines=1)
|
600 |
-
clear = gr.Button("Clear")
|
601 |
-
|
602 |
-
def user(user_message, history):
|
603 |
-
# history comes in as a list of lists from Gradio
|
604 |
-
# Convert it to the list of dictionaries format for the chat function
|
605 |
-
llm_history_format = []
|
606 |
-
for human_message, ai_message in history:
|
607 |
-
if human_message is not None:
|
608 |
-
llm_history_format.append({"role": "user", "content": human_message})
|
609 |
-
if ai_message is not None:
|
610 |
-
llm_history_format.append({"role": "assistant", "content": ai_message})
|
611 |
-
return "", history + [[user_message, None]]
|
612 |
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
llm_history_format = []
|
618 |
-
for human_message, ai_message in history[:-1]: # Exclude the current user turn
|
619 |
-
if human_message is not None:
|
620 |
-
llm_history_format.append({"role": "user", "content": human_message})
|
621 |
-
if ai_message is not None:
|
622 |
-
llm_history_format.append({"role": "assistant", "content": ai_message})
|
623 |
-
|
624 |
-
# The chat function now returns history in the list of dictionaries format
|
625 |
-
updated_llm_history, response = chat(user_message, llm_history_format)
|
626 |
-
|
627 |
-
# Convert the updated history back to the list of lists format for Gradio
|
628 |
-
gradio_history_format = []
|
629 |
-
for i in range(0, len(updated_llm_history), 2):
|
630 |
-
user_msg = updated_llm_history[i]['content'] if i < len(updated_llm_history) else None
|
631 |
-
bot_msg = updated_llm_history[i+1]['content'] if i+1 < len(updated_llm_history) else None
|
632 |
-
gradio_history_format.append([user_msg, bot_msg])
|
633 |
-
|
634 |
-
return gradio_history_format
|
635 |
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
640 |
|
641 |
try:
|
642 |
-
demo.launch(debug=True
|
643 |
except Exception as e:
|
644 |
print(f"Error launching Gradio interface: {e}")
|
645 |
print(traceback.format_exc())
|
646 |
-
print("Please check the console output for more details on the error.")
|
647 |
-
# That is all we have
|
|
|
1 |
+
# app.py - Combined Script
|
2 |
+
# Combined Imports
|
3 |
import os
|
4 |
import gradio as gr
|
5 |
from huggingface_hub import InferenceClient
|
|
|
91 |
return True
|
92 |
except Exception as e:
|
93 |
print(f"Google Sheets authentication failed: {e}")
|
|
|
94 |
print("Please ensure your GOOGLE_BASE64_CREDENTIALS secret is correctly set and contains valid service account credentials.")
|
95 |
+
print(traceback.format_exc())
|
96 |
return False
|
97 |
# Google Sheets Data Loading and Embedding
|
98 |
data = [] # Global variable to store loaded data
|
|
|
374 |
|
375 |
|
376 |
# Function to generate text using the LLM, incorporating tool results if available
|
377 |
+
def generate_text(prompt: str, tool_results: dict = None) -> str:
|
378 |
"""
|
379 |
+
Generates text using the configured LLM, optionally incorporating tool results.
|
|
|
380 |
Args:
|
381 |
prompt: The initial prompt for the LLM.
|
382 |
tool_results: A dictionary containing results from executed tools.
|
383 |
Keys are tool names, values are their outputs.
|
|
|
|
|
384 |
Returns:
|
385 |
The generated text from the LLM.
|
386 |
"""
|
|
|
389 |
You are a friendly and helpful chatbot. Respond to greetings appropriately (e.g., "Hello!", "Hi there!", "Habari!"). If the user uses Swahili greetings or simple conversational phrases, respond in Swahili. Otherwise, respond in English unless the query is clearly in Swahili. Handle conversational flow and ask follow-up questions when appropriate.
|
390 |
If the user asks a question about other companies or general knowledge, answer their question. However, subtly remind them that your primary expertise and purpose are related to Absa-specific information.
|
391 |
"""
|
392 |
+
full_prompt_builder = [persona_instructions, prompt]
|
393 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
if tool_results and any(tool_results.values()):
|
395 |
+
full_prompt_builder.append("\n\nTool Results:\n")
|
396 |
for question, results in tool_results.items(): # Iterate through results per question
|
397 |
if results:
|
398 |
+
full_prompt_builder.append(f"--- Results for: {question} ---\n") # Add question context
|
399 |
if isinstance(results, list):
|
400 |
for i, result in enumerate(results):
|
401 |
# Check if the result is from business info retrieval
|
402 |
if isinstance(result, dict) and 'Service' in result and 'Description' in result:
|
403 |
+
full_prompt_builder.append(f"Business Info {i+1}:\nService: {result.get('Service', 'N/A')}\nDescription: {result.get('Description', 'N/A')}\n\n")
|
404 |
elif isinstance(result, dict) and 'url' in result: # Check if the result is from DuckDuckGo
|
405 |
+
full_prompt_builder.append(f"Search Result {i+1}:\nTitle: {result.get('title', 'N/A')}\nURL: {result.get('url', 'N/A')}\nSnippet: {result.get('body', 'N/A')}\n\n")
|
406 |
else:
|
407 |
+
full_prompt_builder.append(f"{result}\n\n") # Handle other list items
|
408 |
elif isinstance(results, dict):
|
409 |
for key, value in results.items():
|
410 |
+
full_prompt_builder.append(f"{key}: {value}\n")
|
411 |
+
full_prompt_builder.append("\n")
|
412 |
else:
|
413 |
+
full_prompt_builder.append(f"{results}\n\n") # Handle single string results (like date calculation)
|
414 |
+
full_prompt_builder.append("Based on the provided tool results, answer the user's original query. If a question was answered by a tool, use the tool's result directly in your response. Maintain the language of the original query if possible, especially for simple greetings or direct questions answered by tools.")
|
415 |
+
print("Added tool results and instruction to final prompt.")
|
|
|
416 |
else:
|
417 |
+
print("No tool results to add to final prompt.")
|
418 |
+
full_prompt = "".join(full_prompt_builder)
|
419 |
+
print(f"Sending prompt to LLM:\n---\n{full_prompt}\n---")
|
|
|
|
|
|
|
420 |
generation_config = {
|
421 |
"temperature": 0.7,
|
422 |
"max_new_tokens": 500,
|
|
|
426 |
}
|
427 |
try:
|
428 |
response = client.chat_completion(
|
429 |
+
messages=[
|
430 |
+
{"role": "user", "content": full_prompt}
|
431 |
+
],
|
432 |
max_tokens=generation_config.get("max_new_tokens", 512),
|
433 |
temperature=generation_config.get("temperature", 0.7),
|
434 |
top_p=generation_config.get("top_p", 0.95)
|
|
|
440 |
print(traceback.format_exc())
|
441 |
return "An error occurred while generating the final response."
|
442 |
# Main chat function with query breakdown and tool execution per question
|
443 |
+
def chat(query: str, chat_history: list[list[str]]):
|
444 |
"""
|
445 |
Processes user queries by breaking down multi-part queries, determining and
|
446 |
executing appropriate tools for each question, and synthesizing results
|
447 |
+
using the LLM. Prioritizes business information retrieval.
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
"""
|
449 |
print(f"Received query: {query}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
450 |
|
451 |
# Step 1: Query Breakdown
|
452 |
print("\n--- Breaking down query ---")
|
|
|
511 |
for question, result in tool_results.items():
|
512 |
print(f"\nQuestion: {question}")
|
513 |
print(f"Result: {result}")
|
|
|
514 |
else:
|
515 |
print("No tool results were collected.")
|
516 |
+
print("\n--------------------------")
|
|
|
517 |
|
518 |
# Step 5: Final Response Generation
|
519 |
print("\n--- Generating final response ---")
|
520 |
# The generate_text function already handles incorporating tool results if provided
|
521 |
+
final_response = generate_text(query, tool_results)
|
522 |
print("\n--- Final Response from LLM ---")
|
523 |
print(final_response)
|
524 |
print("\n----------------------------")
|
525 |
|
526 |
+
# Return only the latest AI response as a string for Gradio's ChatInterface
|
527 |
+
return final_response
|
528 |
|
529 |
|
530 |
# Keep the Gradio interface setup as is for now
|
|
|
545 |
"RAG will not be available. Please ensure the GOOGLE_BASE64_CREDENTIALS secret is set correctly.")
|
546 |
print("Launching Gradio Interface...")
|
547 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
548 |
|
549 |
+
DESCRIPTION = """
|
550 |
+
# LLM with Tools (DuckDuckGo Search, Date Calculation, Business Info RAG)
|
551 |
+
Ask me anything! I can perform web searches, calculate dates, and retrieve business information.
|
552 |
+
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
553 |
|
554 |
+
demo = gr.ChatInterface(
|
555 |
+
fn=chat,
|
556 |
+
stop_btn=None,
|
557 |
+
examples=[
|
558 |
+
["Hello there! How are you doing?"],
|
559 |
+
["What is the current time in East Africa?"],
|
560 |
+
["Tell me about the 'Project Management' service from Absa."],
|
561 |
+
["Search the web for the latest news on AI."],
|
562 |
+
["Habari!"],
|
563 |
+
["What is the date next Tuesday?"],
|
564 |
+
],
|
565 |
+
cache_examples=False,
|
566 |
+
type="messages",
|
567 |
+
description=DESCRIPTION,
|
568 |
+
fill_height=True,
|
569 |
+
)
|
570 |
|
571 |
try:
|
572 |
+
demo.launch(debug=True)
|
573 |
except Exception as e:
|
574 |
print(f"Error launching Gradio interface: {e}")
|
575 |
print(traceback.format_exc())
|
576 |
+
print("Please check the console output for more details on the error.")
|
|