Spaces:
Build error
Build error
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -14,8 +14,6 @@ from langchain.chains.query_constructor.base import AttributeInfo # Base classe
|
|
| 14 |
from langchain.retrievers.self_query.base import SelfQueryRetriever # Base classes for self-querying retrievers
|
| 15 |
from langchain.retrievers.document_compressors import LLMChainExtractor, CrossEncoderReranker # Document compressors
|
| 16 |
from langchain.retrievers import ContextualCompressionRetriever # Contextual compression retrievers
|
| 17 |
-
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
|
| 18 |
-
from langchain_openai import ChatOpenAI
|
| 19 |
|
| 20 |
# LangChain community & experimental imports
|
| 21 |
from langchain_community.vectorstores import Chroma # Implementations of vector stores like Chroma
|
|
@@ -33,6 +31,8 @@ from langchain_core.prompts import ChatPromptTemplate
|
|
| 33 |
# LangChain OpenAI imports
|
| 34 |
from langchain_openai import AzureOpenAIEmbeddings, AzureChatOpenAI # OpenAI embeddings and models
|
| 35 |
from langchain.embeddings.openai import OpenAIEmbeddings # OpenAI embeddings for text vectors
|
|
|
|
|
|
|
| 36 |
|
| 37 |
# LlamaParse & LlamaIndex imports
|
| 38 |
from llama_parse import LlamaParse # Document parsing library
|
|
@@ -63,6 +63,17 @@ endpoint = os.environ['OPENAI_API_BASE']
|
|
| 63 |
llama_api_key = os.environ['GROQ_API_KEY']
|
| 64 |
MEM0_api_key = os.environ['MEM0_API_KEY']
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
# Initialize the OpenAI embedding function for Chroma
|
| 67 |
embedding_function = chromadb.utils.embedding_functions.OpenAIEmbeddingFunction(
|
| 68 |
api_base=endpoint, # Complete the code to define the API base endpoint
|
|
@@ -80,6 +91,7 @@ embedding_model = OpenAIEmbeddings(
|
|
| 80 |
)
|
| 81 |
|
| 82 |
|
|
|
|
| 83 |
# Initialize the Chat OpenAI model
|
| 84 |
llm = ChatOpenAI(
|
| 85 |
openai_api_base=endpoint,
|
|
@@ -87,6 +99,7 @@ llm = ChatOpenAI(
|
|
| 87 |
model="gpt-4o-mini",
|
| 88 |
streaming=False
|
| 89 |
)
|
|
|
|
| 90 |
# This initializes the Chat OpenAI model with the provided endpoint, API key, deployment name, and a temperature setting of 0 (to control response variability).
|
| 91 |
|
| 92 |
# set the LLM and embedding model in the LlamaIndex settings.
|
|
@@ -143,7 +156,7 @@ def expand_query(state):
|
|
| 143 |
# Initialize the Chroma vector store for retrieving documents
|
| 144 |
vector_store = Chroma(
|
| 145 |
collection_name="nutritional_hypotheticals",
|
| 146 |
-
persist_directory="
|
| 147 |
embedding_function=embedding_model
|
| 148 |
|
| 149 |
)
|
|
@@ -436,8 +449,6 @@ def max_iterations_reached(state: Dict) -> Dict:
|
|
| 436 |
state['response'] = response
|
| 437 |
return state
|
| 438 |
|
| 439 |
-
|
| 440 |
-
|
| 441 |
from langgraph.graph import END, StateGraph, START
|
| 442 |
|
| 443 |
def create_workflow() -> StateGraph:
|
|
@@ -556,250 +567,323 @@ def filter_input_with_llama_guard(user_input, model="llama-guard-3-8b"):
|
|
| 556 |
#============================= Adding Memory to the agent using mem0 ===============================#
|
| 557 |
|
| 558 |
class NutritionBot:
|
| 559 |
-
|
| 560 |
"""
|
| 561 |
-
Initialize the NutritionBot class
|
| 562 |
"""
|
|
|
|
|
|
|
| 563 |
|
| 564 |
-
|
| 565 |
-
# self.memory = MemoryClient(api_key=userdata.get("MEM0_API_KEY")) # Complete the code to define the memory client API key
|
| 566 |
-
|
| 567 |
-
self.memory = MemoryClient(api_key=MEM0_api_key) # Complete the code to define the memory client API key
|
| 568 |
-
|
| 569 |
-
# endpoint = os.environ['OPENAI_API_BASE']
|
| 570 |
-
# print("endpoint: ", endpoint)
|
| 571 |
-
|
| 572 |
-
# Initialize the OpenAI client using the provided credentials
|
| 573 |
-
self.client = ChatOpenAI(
|
| 574 |
-
model_name="gpt-4o-mini", # Specify the model to use (e.g., GPT-4 optimized version)
|
| 575 |
-
api_key=api_key, # API key for authentication
|
| 576 |
-
endpoint=endpoint,
|
| 577 |
-
temperature=0 # Controls randomness in responses; 0 ensures deterministic results
|
| 578 |
-
)
|
| 579 |
-
|
| 580 |
-
# Define tools available to the chatbot, such as web search
|
| 581 |
-
tools = [agentic_rag]
|
| 582 |
-
|
| 583 |
-
# Define the system prompt to set the behavior of the chatbot
|
| 584 |
-
system_prompt = """You are a caring and knowledgeable Medical Support Agent, specializing in nutrition disorder-related guidance. Your goal is to provide accurate, empathetic, and tailored nutritional recommendations while ensuring a seamless customer experience.
|
| 585 |
-
Guidelines for Interaction:
|
| 586 |
-
Maintain a polite, professional, and reassuring tone.
|
| 587 |
-
Show genuine empathy for customer concerns and health challenges.
|
| 588 |
-
Reference past interactions to provide personalized and consistent advice.
|
| 589 |
-
Engage with the customer by asking about their food preferences, dietary restrictions, and lifestyle before offering recommendations.
|
| 590 |
-
Ensure consistent and accurate information across conversations.
|
| 591 |
-
If any detail is unclear or missing, proactively ask for clarification.
|
| 592 |
-
Always use the agentic_rag tool to retrieve up-to-date and evidence-based nutrition insights.
|
| 593 |
-
Keep track of ongoing issues and follow-ups to ensure continuity in support.
|
| 594 |
-
Your primary goal is to help customers make informed nutrition decisions that align with their health conditions and personal preferences.
|
| 595 |
-
|
| 596 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 597 |
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
])
|
| 604 |
-
|
| 605 |
-
# Create an agent capable of interacting with tools and executing tasks
|
| 606 |
-
agent = create_tool_calling_agent(self.client, tools, prompt)
|
| 607 |
-
|
| 608 |
-
# Wrap the agent in an executor to manage tool interactions and execution flow
|
| 609 |
-
self.agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
| 610 |
-
|
| 611 |
|
| 612 |
-
|
| 613 |
"""
|
| 614 |
-
|
| 615 |
-
|
| 616 |
-
Args:
|
| 617 |
-
user_id (str): Unique identifier for the customer.
|
| 618 |
-
message (str): Customer's query or message.
|
| 619 |
-
response (str): Chatbot's response.
|
| 620 |
-
metadata (Dict, optional): Additional metadata for the interaction.
|
| 621 |
"""
|
| 622 |
-
|
| 623 |
-
|
| 624 |
-
|
| 625 |
-
# Add a timestamp to the metadata for tracking purposes
|
| 626 |
-
metadata["timestamp"] = datetime.now().isoformat()
|
| 627 |
-
|
| 628 |
-
# Format the conversation for storage
|
| 629 |
-
conversation = [
|
| 630 |
-
{"role": "user", "content": message},
|
| 631 |
-
{"role": "assistant", "content": response}
|
| 632 |
-
]
|
| 633 |
-
|
| 634 |
-
# Store the interaction in the memory client
|
| 635 |
-
self.memory.add(
|
| 636 |
-
conversation,
|
| 637 |
-
user_id=user_id,
|
| 638 |
-
output_format="v1.1",
|
| 639 |
-
metadata=metadata
|
| 640 |
)
|
| 641 |
|
| 642 |
-
|
| 643 |
-
def get_relevant_history(self, user_id: str, query: str) -> List[Dict]:
|
| 644 |
"""
|
| 645 |
-
|
| 646 |
-
|
| 647 |
-
Args:
|
| 648 |
-
user_id (str): Unique identifier for the customer.
|
| 649 |
-
query (str): The customer's current query.
|
| 650 |
-
|
| 651 |
-
Returns:
|
| 652 |
-
List[Dict]: A list of relevant past interactions.
|
| 653 |
"""
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
|
|
|
|
|
|
| 658 |
)
|
| 659 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 660 |
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
Args:
|
| 666 |
-
user_id (str): Unique identifier for the customer.
|
| 667 |
-
query (str): Customer's query.
|
| 668 |
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
print("handle_customer_query start, query: ", query)
|
| 673 |
|
| 674 |
-
|
| 675 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
context += f"Customer: {memory['memory']}\n" # Customer's past messages
|
| 681 |
-
context += f"Support: {memory['memory']}\n" # Chatbot's past responses
|
| 682 |
-
context += "---\n"
|
| 683 |
|
| 684 |
-
|
| 685 |
-
print("
|
|
|
|
| 686 |
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
{context}
|
| 691 |
|
| 692 |
-
|
|
|
|
|
|
|
| 693 |
|
| 694 |
-
|
| 695 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 696 |
|
| 697 |
-
|
| 698 |
-
|
| 699 |
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
| 705 |
-
|
| 706 |
-
|
| 707 |
-
|
|
|
|
|
|
|
| 708 |
|
| 709 |
-
|
| 710 |
-
|
| 711 |
|
| 712 |
|
| 713 |
#=====================User Interface using streamlit ===========================#
|
| 714 |
-
def nutrition_disorder_streamlit():
|
| 715 |
-
|
| 716 |
-
|
| 717 |
-
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
| 721 |
-
|
| 722 |
-
|
| 723 |
-
|
| 724 |
-
|
| 725 |
-
|
| 726 |
-
|
| 727 |
-
|
| 728 |
-
|
| 729 |
-
|
| 730 |
-
|
| 731 |
-
|
| 732 |
-
|
| 733 |
-
|
| 734 |
-
|
| 735 |
-
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
|
| 741 |
-
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
|
| 761 |
-
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
|
| 771 |
-
|
| 772 |
-
|
| 773 |
-
|
| 774 |
-
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
# Blank #7: Fill in with the method to handle queries (e.g., handle_customer_query)
|
| 793 |
-
st.write(response)
|
| 794 |
-
st.session_state.chat_history.append({"role": "assistant", "content": response})
|
| 795 |
-
except Exception as e:
|
| 796 |
-
error_msg = f"Sorry, I encountered an error while processing your query. Please try again. Error: {str(e)}"
|
| 797 |
-
st.write(error_msg)
|
| 798 |
-
st.session_state.chat_history.append({"role": "assistant", "content": error_msg})
|
| 799 |
-
# else:
|
| 800 |
-
# inappropriate_msg = "I apologize, but I cannot process that input as it may be inappropriate. Please try again."
|
| 801 |
-
# st.write(inappropriate_msg)
|
| 802 |
-
# st.session_state.chat_history.append({"role": "assistant", "content": inappropriate_msg})
|
| 803 |
-
|
| 804 |
-
if __name__ == "__main__":
|
| 805 |
-
nutrition_disorder_streamlit()
|
|
|
|
| 14 |
from langchain.retrievers.self_query.base import SelfQueryRetriever # Base classes for self-querying retrievers
|
| 15 |
from langchain.retrievers.document_compressors import LLMChainExtractor, CrossEncoderReranker # Document compressors
|
| 16 |
from langchain.retrievers import ContextualCompressionRetriever # Contextual compression retrievers
|
|
|
|
|
|
|
| 17 |
|
| 18 |
# LangChain community & experimental imports
|
| 19 |
from langchain_community.vectorstores import Chroma # Implementations of vector stores like Chroma
|
|
|
|
| 31 |
# LangChain OpenAI imports
|
| 32 |
from langchain_openai import AzureOpenAIEmbeddings, AzureChatOpenAI # OpenAI embeddings and models
|
| 33 |
from langchain.embeddings.openai import OpenAIEmbeddings # OpenAI embeddings for text vectors
|
| 34 |
+
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
|
| 35 |
+
from langchain_openai import ChatOpenAI
|
| 36 |
|
| 37 |
# LlamaParse & LlamaIndex imports
|
| 38 |
from llama_parse import LlamaParse # Document parsing library
|
|
|
|
| 63 |
llama_api_key = os.environ['GROQ_API_KEY']
|
| 64 |
MEM0_api_key = os.environ['MEM0_API_KEY']
|
| 65 |
|
| 66 |
+
# Storing API credentials in environment variables
|
| 67 |
+
os.environ['OPENAI_API_KEY'] = API_KEY
|
| 68 |
+
os.environ["OPENAI_BASE_URL"] = OPENAI_API_BASE
|
| 69 |
+
|
| 70 |
+
model_name = "gpt-4o-mini"
|
| 71 |
+
|
| 72 |
+
client = OpenAI(
|
| 73 |
+
api_key=os.environ.get("OPENAI_API_KEY"),
|
| 74 |
+
base_url=os.environ.get("OPENAI_API_BASE")
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
# Initialize the OpenAI embedding function for Chroma
|
| 78 |
embedding_function = chromadb.utils.embedding_functions.OpenAIEmbeddingFunction(
|
| 79 |
api_base=endpoint, # Complete the code to define the API base endpoint
|
|
|
|
| 91 |
)
|
| 92 |
|
| 93 |
|
| 94 |
+
|
| 95 |
# Initialize the Chat OpenAI model
|
| 96 |
llm = ChatOpenAI(
|
| 97 |
openai_api_base=endpoint,
|
|
|
|
| 99 |
model="gpt-4o-mini",
|
| 100 |
streaming=False
|
| 101 |
)
|
| 102 |
+
|
| 103 |
# This initializes the Chat OpenAI model with the provided endpoint, API key, deployment name, and a temperature setting of 0 (to control response variability).
|
| 104 |
|
| 105 |
# set the LLM and embedding model in the LlamaIndex settings.
|
|
|
|
| 156 |
# Initialize the Chroma vector store for retrieving documents
|
| 157 |
vector_store = Chroma(
|
| 158 |
collection_name="nutritional_hypotheticals",
|
| 159 |
+
persist_directory="/nutritional_db",
|
| 160 |
embedding_function=embedding_model
|
| 161 |
|
| 162 |
)
|
|
|
|
| 449 |
state['response'] = response
|
| 450 |
return state
|
| 451 |
|
|
|
|
|
|
|
| 452 |
from langgraph.graph import END, StateGraph, START
|
| 453 |
|
| 454 |
def create_workflow() -> StateGraph:
|
|
|
|
| 567 |
#============================= Adding Memory to the agent using mem0 ===============================#
|
| 568 |
|
| 569 |
class NutritionBot:
|
| 570 |
+
def __init__(self):
|
| 571 |
"""
|
| 572 |
+
Initialize the NutritionBot class with OpenAI client and conversation memory.
|
| 573 |
"""
|
| 574 |
+
self.client = client
|
| 575 |
+
self.conversation_history = {}
|
| 576 |
|
| 577 |
+
def store_customer_interaction(self, user_id: str, message: str, response: str):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 578 |
"""
|
| 579 |
+
Store customer interaction in a dictionary for future reference.
|
| 580 |
+
"""
|
| 581 |
+
if user_id not in self.conversation_history:
|
| 582 |
+
self.conversation_history[user_id] = []
|
| 583 |
|
| 584 |
+
self.conversation_history[user_id].append({
|
| 585 |
+
"timestamp": datetime.now().isoformat(),
|
| 586 |
+
"user": message,
|
| 587 |
+
"assistant": response
|
| 588 |
+
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 589 |
|
| 590 |
+
def get_relevant_history(self, user_id: str) -> str:
|
| 591 |
"""
|
| 592 |
+
Retrieve past interactions relevant to the user.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 593 |
"""
|
| 594 |
+
history = self.conversation_history.get(user_id, [])
|
| 595 |
+
return "\n".join(
|
| 596 |
+
[f"User: {entry['user']}\nAssistant: {entry['assistant']}" for entry in history[-5:]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 597 |
)
|
| 598 |
|
| 599 |
+
def handle_customer_query(self, user_id: str, query: str) -> str:
|
|
|
|
| 600 |
"""
|
| 601 |
+
Process a customer's query and provide a response using OpenAI's API.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
"""
|
| 603 |
+
history_context = self.get_relevant_history(user_id)
|
| 604 |
+
system_prompt = (
|
| 605 |
+
"You are a caring and knowledgeable Medical Support Agent, specializing in nutrition disorder-related guidance. "
|
| 606 |
+
"Your goal is to provide accurate, empathetic, and tailored nutritional recommendations while ensuring a seamless customer experience.\n\n"
|
| 607 |
+
"Always use available knowledge to guide customers about symptoms, causes, and treatments for nutrition disorders. "
|
| 608 |
+
"Ask clarifying questions where needed, and maintain a supportive tone."
|
| 609 |
)
|
| 610 |
|
| 611 |
+
messages = [
|
| 612 |
+
{"role": "system", "content": system_prompt},
|
| 613 |
+
{"role": "user", "content": f"Past interactions:\n{history_context}\n\nCustomer: {query}"}
|
| 614 |
+
]
|
| 615 |
|
| 616 |
+
response = self.client.chat.completions.create(
|
| 617 |
+
model="gpt-4o-mini",
|
| 618 |
+
messages=messages
|
| 619 |
+
)
|
|
|
|
|
|
|
|
|
|
| 620 |
|
| 621 |
+
reply = response.choices[0].message.content.strip()
|
| 622 |
+
self.store_customer_interaction(user_id, query, reply)
|
| 623 |
+
return reply
|
|
|
|
| 624 |
|
| 625 |
+
def nutrition_disorder_agent():
|
| 626 |
+
"""
|
| 627 |
+
A conversational agent for answering nutrition disorder-related questions.
|
| 628 |
+
"""
|
| 629 |
+
print("Welcome to the Nutrition Disorder Specialist Agent!")
|
| 630 |
+
print("You can ask me anything about nutrition disorders, such as symptoms, causes, treatments, and more.")
|
| 631 |
+
print("Type 'exit' to end the conversation.\n")
|
| 632 |
|
| 633 |
+
chatbot = NutritionBot()
|
| 634 |
+
print("Login by providing customer name:")
|
| 635 |
+
user_id = input().strip()
|
|
|
|
|
|
|
|
|
|
| 636 |
|
| 637 |
+
while True:
|
| 638 |
+
print("How can I help you?")
|
| 639 |
+
user_query = input("You: ").strip()
|
| 640 |
|
| 641 |
+
if user_query.lower() == "exit":
|
| 642 |
+
print("Agent: Goodbye! Feel free to return if you have more questions.")
|
| 643 |
+
break
|
|
|
|
| 644 |
|
| 645 |
+
# Input moderation (optional, if llama guard logic exists)
|
| 646 |
+
filtered_result = filter_input_with_llama_guard(user_query).replace("\n", " ")
|
| 647 |
+
print(filtered_result)
|
| 648 |
|
| 649 |
+
if filtered_result in ["safe", "unsafe S7", "unsafe S6"]:
|
| 650 |
+
try:
|
| 651 |
+
response = chatbot.handle_customer_query(user_id, user_query)
|
| 652 |
+
print(f"Agent: {response}\n")
|
| 653 |
+
except Exception as e:
|
| 654 |
+
print("Agent: Sorry, I encountered an error while processing your query. Please try again.")
|
| 655 |
+
print(f"Error: {e}\n")
|
| 656 |
+
else:
|
| 657 |
+
print("Agent: I apologize, but I cannot process that input as it may be inappropriate. Please try again.")
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
nutrition_disorder_agent()
|
| 661 |
+
|
| 662 |
+
# def __init__(self):
|
| 663 |
+
# """
|
| 664 |
+
# Initialize the NutritionBot class, setting up memory, the LLM client, tools, and the agent executor.
|
| 665 |
+
# """
|
| 666 |
+
|
| 667 |
+
# # Initialize a memory client to store and retrieve customer interactions
|
| 668 |
+
# # self.memory = MemoryClient(api_key=userdata.get("MEM0_API_KEY")) # Complete the code to define the memory client API key
|
| 669 |
+
|
| 670 |
+
# self.memory = MemoryClient(api_key=MEM0_api_key) # Complete the code to define the memory client API key
|
| 671 |
+
|
| 672 |
+
# # Initialize the OpenAI client using the provided credentials
|
| 673 |
+
# self.client = ChatOpenAI(
|
| 674 |
+
# model_name="gpt-4o-mini", # Specify the model to use (e.g., GPT-4 optimized version)
|
| 675 |
+
# api_key=api_key, # API key for authentication
|
| 676 |
+
# endpoint = endpoint,
|
| 677 |
+
# temperature=0 # Controls randomness in responses; 0 ensures deterministic results
|
| 678 |
+
# )
|
| 679 |
+
|
| 680 |
+
# # Define tools available to the chatbot, such as web search
|
| 681 |
+
# tools = [agentic_rag]
|
| 682 |
+
|
| 683 |
+
# # Define the system prompt to set the behavior of the chatbot
|
| 684 |
+
# system_prompt = """You are a caring and knowledgeable Medical Support Agent, specializing in nutrition disorder-related guidance. Your goal is to provide accurate, empathetic, and tailored nutritional recommendations while ensuring a seamless customer experience.
|
| 685 |
+
# Guidelines for Interaction:
|
| 686 |
+
# Maintain a polite, professional, and reassuring tone.
|
| 687 |
+
# Show genuine empathy for customer concerns and health challenges.
|
| 688 |
+
# Reference past interactions to provide personalized and consistent advice.
|
| 689 |
+
# Engage with the customer by asking about their food preferences, dietary restrictions, and lifestyle before offering recommendations.
|
| 690 |
+
# Ensure consistent and accurate information across conversations.
|
| 691 |
+
# If any detail is unclear or missing, proactively ask for clarification.
|
| 692 |
+
# Always use the agentic_rag tool to retrieve up-to-date and evidence-based nutrition insights.
|
| 693 |
+
# Keep track of ongoing issues and follow-ups to ensure continuity in support.
|
| 694 |
+
# Your primary goal is to help customers make informed nutrition decisions that align with their health conditions and personal preferences.
|
| 695 |
+
|
| 696 |
+
# """
|
| 697 |
+
|
| 698 |
+
# # Build the prompt template for the agent
|
| 699 |
+
# prompt = ChatPromptTemplate.from_messages([
|
| 700 |
+
# ("system", system_prompt), # System instructions
|
| 701 |
+
# ("human", "{input}"), # Placeholder for human input
|
| 702 |
+
# ("placeholder", "{agent_scratchpad}") # Placeholder for intermediate reasoning steps
|
| 703 |
+
# ])
|
| 704 |
+
|
| 705 |
+
# # Create an agent capable of interacting with tools and executing tasks
|
| 706 |
+
# agent = create_tool_calling_agent(self.client, tools, prompt)
|
| 707 |
+
|
| 708 |
+
# # Wrap the agent in an executor to manage tool interactions and execution flow
|
| 709 |
+
# self.agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
| 710 |
+
|
| 711 |
+
|
| 712 |
+
# def store_customer_interaction(self, user_id: str, message: str, response: str, metadata: Dict = None):
|
| 713 |
+
# """
|
| 714 |
+
# Store customer interaction in memory for future reference.
|
| 715 |
+
|
| 716 |
+
# Args:
|
| 717 |
+
# user_id (str): Unique identifier for the customer.
|
| 718 |
+
# message (str): Customer's query or message.
|
| 719 |
+
# response (str): Chatbot's response.
|
| 720 |
+
# metadata (Dict, optional): Additional metadata for the interaction.
|
| 721 |
+
# """
|
| 722 |
+
# if metadata is None:
|
| 723 |
+
# metadata = {}
|
| 724 |
+
|
| 725 |
+
# # Add a timestamp to the metadata for tracking purposes
|
| 726 |
+
# metadata["timestamp"] = datetime.now().isoformat()
|
| 727 |
+
|
| 728 |
+
# # Format the conversation for storage
|
| 729 |
+
# conversation = [
|
| 730 |
+
# {"role": "user", "content": message},
|
| 731 |
+
# {"role": "assistant", "content": response}
|
| 732 |
+
# ]
|
| 733 |
+
|
| 734 |
+
# # Store the interaction in the memory client
|
| 735 |
+
# self.memory.add(
|
| 736 |
+
# conversation,
|
| 737 |
+
# user_id=user_id,
|
| 738 |
+
# output_format="v1.1",
|
| 739 |
+
# metadata=metadata
|
| 740 |
+
# )
|
| 741 |
+
|
| 742 |
+
|
| 743 |
+
# def get_relevant_history(self, user_id: str, query: str) -> List[Dict]:
|
| 744 |
+
# """
|
| 745 |
+
# Retrieve past interactions relevant to the current query.
|
| 746 |
+
|
| 747 |
+
# Args:
|
| 748 |
+
# user_id (str): Unique identifier for the customer.
|
| 749 |
+
# query (str): The customer's current query.
|
| 750 |
+
|
| 751 |
+
# Returns:
|
| 752 |
+
# List[Dict]: A list of relevant past interactions.
|
| 753 |
+
# """
|
| 754 |
+
# return self.memory.search(
|
| 755 |
+
# query=query, # Search for interactions related to the query
|
| 756 |
+
# user_id=user_id, # Restrict search to the specific user
|
| 757 |
+
# limit=3 # Complete the code to define the limit for retrieved interactions
|
| 758 |
+
# )
|
| 759 |
+
|
| 760 |
+
|
| 761 |
+
# def handle_customer_query(self, user_id: str, query: str) -> str:
|
| 762 |
+
# """
|
| 763 |
+
# Process a customer's query and provide a response, taking into account past interactions.
|
| 764 |
+
|
| 765 |
+
# Args:
|
| 766 |
+
# user_id (str): Unique identifier for the customer.
|
| 767 |
+
# query (str): Customer's query.
|
| 768 |
+
|
| 769 |
+
# Returns:
|
| 770 |
+
# str: Chatbot's response.
|
| 771 |
+
# """
|
| 772 |
+
|
| 773 |
+
# # Retrieve relevant past interactions for context
|
| 774 |
+
# relevant_history = self.get_relevant_history(user_id, query)
|
| 775 |
+
|
| 776 |
+
# # Build a context string from the relevant history
|
| 777 |
+
# context = "Previous relevant interactions:\n"
|
| 778 |
+
# for memory in relevant_history:
|
| 779 |
+
# context += f"Customer: {memory['memory']}\n" # Customer's past messages
|
| 780 |
+
# context += f"Support: {memory['memory']}\n" # Chatbot's past responses
|
| 781 |
+
# context += "---\n"
|
| 782 |
+
|
| 783 |
+
# # Print context for debugging purposes
|
| 784 |
+
# print("Context: ", context)
|
| 785 |
+
|
| 786 |
+
# # Prepare a prompt combining past context and the current query
|
| 787 |
+
# prompt = f"""
|
| 788 |
+
# Context:
|
| 789 |
+
# {context}
|
| 790 |
+
|
| 791 |
+
# Current customer query: {query}
|
| 792 |
|
| 793 |
+
# Provide a helpful response that takes into account any relevant past interactions.
|
| 794 |
+
# """
|
| 795 |
|
| 796 |
+
# # Generate a response using the agent
|
| 797 |
+
# response = self.agent_executor.invoke({"input": prompt})
|
| 798 |
+
|
| 799 |
+
# # Store the current interaction for future reference
|
| 800 |
+
# self.store_customer_interaction(
|
| 801 |
+
# user_id=user_id,
|
| 802 |
+
# message=query,
|
| 803 |
+
# response=response["output"],
|
| 804 |
+
# metadata={"type": "support_query"}
|
| 805 |
+
# )
|
| 806 |
|
| 807 |
+
# # Return the chatbot's response
|
| 808 |
+
# return response['output']
|
| 809 |
|
| 810 |
|
| 811 |
#=====================User Interface using streamlit ===========================#
|
| 812 |
+
# def nutrition_disorder_streamlit():
|
| 813 |
+
# """
|
| 814 |
+
# A Streamlit-based UI for the Nutrition Disorder Specialist Agent.
|
| 815 |
+
# """
|
| 816 |
+
# st.title("Nutrition Disorder Specialist")
|
| 817 |
+
# st.write("Ask me anything about nutrition disorders, symptoms, causes, treatments, and more.")
|
| 818 |
+
# st.write("Type 'exit' to end the conversation.")
|
| 819 |
+
|
| 820 |
+
# # Initialize session state for chat history and user_id if they don't exist
|
| 821 |
+
# if 'chat_history' not in st.session_state:
|
| 822 |
+
# st.session_state.chat_history = []
|
| 823 |
+
# if 'user_id' not in st.session_state:
|
| 824 |
+
# st.session_state.user_id = None
|
| 825 |
+
|
| 826 |
+
# # Login form: Only if user is not logged in
|
| 827 |
+
# if st.session_state.user_id is None:
|
| 828 |
+
# with st.form("login_form", clear_on_submit=True):
|
| 829 |
+
# user_id = st.text_input("Please enter your name to begin:")
|
| 830 |
+
# submit_button = st.form_submit_button("Login")
|
| 831 |
+
# if submit_button and user_id:
|
| 832 |
+
# st.session_state.user_id = user_id
|
| 833 |
+
# st.session_state.chat_history.append({
|
| 834 |
+
# "role": "assistant",
|
| 835 |
+
# "content": f"Welcome, {user_id}! How can I help you with nutrition disorders today?"
|
| 836 |
+
# })
|
| 837 |
+
# st.session_state.login_submitted = True # Set flag to trigger rerun
|
| 838 |
+
# if st.session_state.get("login_submitted", False):
|
| 839 |
+
# st.session_state.pop("login_submitted")
|
| 840 |
+
# st.rerun()
|
| 841 |
+
# else:
|
| 842 |
+
# # Display chat history
|
| 843 |
+
# for message in st.session_state.chat_history:
|
| 844 |
+
# with st.chat_message(message["role"]):
|
| 845 |
+
# st.write(message["content"])
|
| 846 |
+
|
| 847 |
+
# # Chat input with custom placeholder text
|
| 848 |
+
# user_query = st.chat_input("Type your question here (or 'exit' to end") # Blank #1: Fill in the chat input prompt (e.g., "Type your question here (or 'exit' to end)...")
|
| 849 |
+
# if user_query:
|
| 850 |
+
# if user_query.lower() == "exit":
|
| 851 |
+
# st.session_state.chat_history.append({"role": "user", "content": "exit"})
|
| 852 |
+
# with st.chat_message("user"):
|
| 853 |
+
# st.write("exit")
|
| 854 |
+
# goodbye_msg = "Goodbye! Feel free to return if you have more questions about nutrition disorders."
|
| 855 |
+
# st.session_state.chat_history.append({"role": "assistant", "content": goodbye_msg})
|
| 856 |
+
# with st.chat_message("assistant"):
|
| 857 |
+
# st.write(goodbye_msg)
|
| 858 |
+
# st.session_state.user_id = None
|
| 859 |
+
# st.rerun()
|
| 860 |
+
# return
|
| 861 |
+
|
| 862 |
+
# st.session_state.chat_history.append({"role": "user", "content": user_query})
|
| 863 |
+
# with st.chat_message("user"):
|
| 864 |
+
# st.write(user_query)
|
| 865 |
+
|
| 866 |
+
# # Filter input using Llama Guard
|
| 867 |
+
# filtered_result = filter_input_with_llama_guard(user_query) # Blank #2: Fill in with the function name for filtering input (e.g., filter_input_with_llama_guard)
|
| 868 |
+
# filtered_result = filtered_result.replace("\n", " ") # Normalize the result
|
| 869 |
+
|
| 870 |
+
# # Check if input is safe based on allowed statuses
|
| 871 |
+
# if filtered_result in ["safe", "unsafe S7", "unsafe S6"]: # Blanks #3, #4, #5: Fill in with allowed safe statuses (e.g., "safe", "unsafe S7", "unsafe S6")
|
| 872 |
+
# try:
|
| 873 |
+
# if 'chatbot' not in st.session_state:
|
| 874 |
+
# st.session_state.chatbot = NutritionBot() # Blank #6: Fill in with the chatbot class initialization (e.g., NutritionBot)
|
| 875 |
+
# response = st.session_state.chatbot.handle_customer_query(st.session_state.user_id, user_query)
|
| 876 |
+
# # Blank #7: Fill in with the method to handle queries (e.g., handle_customer_query)
|
| 877 |
+
# st.write(response)
|
| 878 |
+
# st.session_state.chat_history.append({"role": "assistant", "content": response})
|
| 879 |
+
# except Exception as e:
|
| 880 |
+
# error_msg = f"Sorry, I encountered an error while processing your query. Please try again. Error: {str(e)}"
|
| 881 |
+
# st.write(error_msg)
|
| 882 |
+
# st.session_state.chat_history.append({"role": "assistant", "content": error_msg})
|
| 883 |
+
# else:
|
| 884 |
+
# inappropriate_msg = "I apologize, but I cannot process that input as it may be inappropriate. Please try again."
|
| 885 |
+
# st.write(inappropriate_msg)
|
| 886 |
+
# st.session_state.chat_history.append({"role": "assistant", "content": inappropriate_msg})
|
| 887 |
+
|
| 888 |
+
# if __name__ == "__main__":
|
| 889 |
+
# nutrition_disorder_streamlit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|