Futuresony commited on
Commit
9666603
·
verified ·
1 Parent(s): 2ea0720

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -121
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, history: list = None) -> str:
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
- tool_results_string_builder = ["\n\nTool Results:\n"]
405
  for question, results in tool_results.items(): # Iterate through results per question
406
  if results:
407
- tool_results_string_builder.append(f"--- Results for: {question} ---\n") # Add question context
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
- tool_results_string_builder.append(f"Business Info {i+1}:\nService: {result.get('Service', 'N/A')}\nDescription: {result.get('Description', 'N/A')}\n\n")
413
  elif isinstance(result, dict) and 'url' in result: # Check if the result is from DuckDuckGo
414
- tool_results_string_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")
415
  else:
416
- tool_results_string_builder.append(f"{result}\n\n") # Handle other list items
417
  elif isinstance(results, dict):
418
  for key, value in results.items():
419
- tool_results_string_builder.append(f"{key}: {value}\n")
420
- tool_results_string_builder.append("\n")
421
  else:
422
- tool_results_string_builder.append(f"{results}\n\n") # Handle single string results (like date calculation)
423
- tool_results_string_builder.append("Based on the provided tool results and the conversation history, 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.")
424
- current_prompt_content += "".join(tool_results_string_builder)
425
- print("Added tool results and instruction to current prompt.")
426
  else:
427
- print("No tool results to add to current prompt.")
428
-
429
- messages.append({"role": "user", "content": current_prompt_content})
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=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, history: list):
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, while maintaining conversation history.
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
- print("\n--------------------------")
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, history=llm_history)
565
  print("\n--- Final Response from LLM ---")
566
  print(final_response)
567
  print("\n----------------------------")
568
 
569
- # Append to history and return
570
- return history + [{"role": "user", "content": query}, {"role": "assistant", "content": final_response}], final_response
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
- def bot(history):
614
- # history here is the updated list of lists from the user function
615
- user_message = history[-1][0]
616
- # Convert history to the list of dictionaries format before passing to chat
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
- msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
637
- bot, chatbot, chatbot
638
- )
639
- clear.click(lambda: [], None, chatbot, queue=False)
 
 
 
 
 
 
 
 
 
 
 
 
640
 
641
  try:
642
- demo.launch(debug=True, show_error=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.")