Spaces:
Build error
Build error
Upload planning_agent.py
Browse files- agent/planning_agent.py +223 -0
agent/planning_agent.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_openai import ChatOpenAI
|
| 2 |
+
from langchain.agents import initialize_agent, AgentType
|
| 3 |
+
from langchain.tools import Tool
|
| 4 |
+
from langchain.memory import ConversationBufferMemory, SimpleMemory
|
| 5 |
+
import agent.router_agent as router_agent
|
| 6 |
+
import agent.product_review_agent as product_review_agent
|
| 7 |
+
import agent.generic_agent as generic_agent
|
| 8 |
+
import agent.composer_agent as composer_agent
|
| 9 |
+
import agent.order_tracking_agent as order_tracking_agent #new agent
|
| 10 |
+
import logging
|
| 11 |
+
|
| 12 |
+
# Set httpx (HTTP request) logging to WARNING or ERROR level
|
| 13 |
+
# This will hide the HTTP request logs while keeping agent thoughts visible
|
| 14 |
+
logging.getLogger("httpx").setLevel(logging.WARNING) # added on 23-Nob
|
| 15 |
+
|
| 16 |
+
# Configure logging
|
| 17 |
+
logging.basicConfig(level=logging.INFO)
|
| 18 |
+
logger = logging.getLogger(__name__)
|
| 19 |
+
|
| 20 |
+
# Global variables
|
| 21 |
+
llm = None
|
| 22 |
+
chat_memory = None
|
| 23 |
+
query_memory = None
|
| 24 |
+
agent = None
|
| 25 |
+
order_tracking_agent_instance = None # Global variable
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def initialize_planning_agent(llm_instance, chat_memory_instance, query_memory_instance):
|
| 29 |
+
global llm, chat_memory, query_memory, agent, order_tracking_agent_instance
|
| 30 |
+
|
| 31 |
+
llm = llm_instance
|
| 32 |
+
chat_memory = chat_memory_instance
|
| 33 |
+
query_memory = query_memory_instance
|
| 34 |
+
|
| 35 |
+
# Initialize agents
|
| 36 |
+
router_agent.initialize_router_agent(llm, chat_memory)
|
| 37 |
+
product_review_agent.initialize_product_review_agent(llm, chat_memory)
|
| 38 |
+
generic_agent.initialize_generic_agent(llm, chat_memory)
|
| 39 |
+
order_tracking_agent_instance = order_tracking_agent.OrderTrackingAgent() # Initialize Order Tracking Agent
|
| 40 |
+
|
| 41 |
+
# composer_agent.initialize_composer_agent(llm, memory)
|
| 42 |
+
|
| 43 |
+
tools = [
|
| 44 |
+
Tool(
|
| 45 |
+
name="route_query",
|
| 46 |
+
func=route_query,
|
| 47 |
+
description="Determine query type. Returns either 'product_review' or 'generic'"
|
| 48 |
+
),
|
| 49 |
+
Tool(
|
| 50 |
+
name="get_product_info",
|
| 51 |
+
func=get_product_info,
|
| 52 |
+
description="Use this to get product-related data such as features, prices, availability, or reviews"
|
| 53 |
+
),
|
| 54 |
+
Tool(
|
| 55 |
+
name="handle_generic_query",
|
| 56 |
+
func=handle_generic_query,
|
| 57 |
+
description="Use this to get response to user queries which are generic and where the retrieval of product details are not required"
|
| 58 |
+
),
|
| 59 |
+
Tool(
|
| 60 |
+
name="compose_response",
|
| 61 |
+
func=compose_response,
|
| 62 |
+
description="Use this to only format the response. After this step, return the formatted response to main.py"
|
| 63 |
+
),
|
| 64 |
+
|
| 65 |
+
Tool(
|
| 66 |
+
name="handle_order_tracking_query",
|
| 67 |
+
func=handle_order_tracking_query,
|
| 68 |
+
description="Use this to handle order tracking, refunds, or replacement queries based on the order number or tracking number."
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
]
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
system_prompt = """You are an efficient AI planning agent. Follow these rules strictly:
|
| 75 |
+
|
| 76 |
+
CRITICAL INSTRUCTION:
|
| 77 |
+
For simple queries listed below, skip the route_query and directly go to handle_generic_query.
|
| 78 |
+
|
| 79 |
+
SIMPLE QUERIES (NEVER use tools):
|
| 80 |
+
1. Greetings: "hi", "hello", "hey", "good morning", "good evening", "good afternoon"
|
| 81 |
+
2. Farewells: "bye", "goodbye", "see you", "take care"
|
| 82 |
+
3. Thank you messages: "thanks", "thank you", "thanks a lot", "appreciate it"
|
| 83 |
+
4. Simple confirmations: "okay", "yes", "no", "sure", "alright"
|
| 84 |
+
5. Basic courtesy: "how are you?", "how are you doing?", "what's up?", "what are you doing?"
|
| 85 |
+
6. Simple acknowledgments: "got it", "understood", "I see"
|
| 86 |
+
|
| 87 |
+
FOR ALL OTHER QUERIES:
|
| 88 |
+
1. Use route_query to determine if query is product_review or generic
|
| 89 |
+
2. If route_query returns 'generic', use handle_generic_query and STOP
|
| 90 |
+
3. If route_query returns 'product_review', use get_product_info and STOP
|
| 91 |
+
|
| 92 |
+
EXAMPLES:
|
| 93 |
+
|
| 94 |
+
User: "Hi"
|
| 95 |
+
Thought: This is a Simple greeting, I will use handle_generic_query to get appropriate response
|
| 96 |
+
Action: handle_generic_query
|
| 97 |
+
Observation: "Hi! How can I help you today?"
|
| 98 |
+
Thought: I have got the final answer. I will use compose_responses to format the response.
|
| 99 |
+
Action: compose_responses
|
| 100 |
+
Final Answer: "Hi! How can I help you today?"
|
| 101 |
+
|
| 102 |
+
User: "I got my package delivered yesterday. It was delivered very late. I want to file a complaint."
|
| 103 |
+
Thought: This is a generic query that does not require product details. I will use handle_generic_query to get appropriate response.
|
| 104 |
+
Action: handle_generic_query
|
| 105 |
+
Action Input: User query: I got my package delivered yesterday. It was delivered very late. I want to file a complaint.
|
| 106 |
+
Observation: {'intermediate_steps': [], 'output': "I'm sorry to hear about the delay in your package delivery. I understand your frustration and I'm here to assist you with filing a complaint. To better assist you, could you please provide me with the tracking number of your package? Once I have that information, I will look into the matter and ensure that your feedback is addressed appropriately.", 'action': 'Final Answer', 'action_input': "I'm sorry to hear about the delay in your package delivery. I understand your frustration and I'm here to assist you with filing a complaint. To better assist you, could you please provide me with the tracking number of your package? Once I have that information, I will look into the matter and ensure that your feedback is addressed appropriately."}
|
| 107 |
+
Thought:I have got the final answer. I will use compose_responses to format the response.
|
| 108 |
+
Action: compose_responses
|
| 109 |
+
Final Answer: I'm sorry to hear about the delay in your package delivery. I understand your frustration and I'm here to assist you with filing a complaint. To better assist you, could you please provide me with the tracking number of your package? Once I have that information, I will look into the matter and ensure that your feedback is addressed appropriately.
|
| 110 |
+
|
| 111 |
+
Remember: For simple queries listed above, respond immediately with Final Answer WITHOUT using tools.
|
| 112 |
+
"""
|
| 113 |
+
|
| 114 |
+
agent = initialize_agent(
|
| 115 |
+
tools,
|
| 116 |
+
llm,
|
| 117 |
+
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
|
| 118 |
+
verbose=True,
|
| 119 |
+
memory=chat_memory,
|
| 120 |
+
system_message=system_prompt,
|
| 121 |
+
early_stopping_method="generate",
|
| 122 |
+
max_iterations=2
|
| 123 |
+
)
|
| 124 |
+
logger.info("Planning agent initialized successfully")
|
| 125 |
+
|
| 126 |
+
def summarize_chat_history():
|
| 127 |
+
"""Summarize the chat history to retain context without overwhelming memory."""
|
| 128 |
+
try:
|
| 129 |
+
if chat_memory:
|
| 130 |
+
# Retrieve the chat history as a list of messages
|
| 131 |
+
chat_history = chat_memory.buffer # Assuming this is a list of messages
|
| 132 |
+
|
| 133 |
+
logger.info(f"Chat history type: {type(chat_history)}")
|
| 134 |
+
|
| 135 |
+
if chat_history:
|
| 136 |
+
# Extract text from AIMessage objects
|
| 137 |
+
text_messages = [msg.content for msg in chat_history if hasattr(msg, 'content')]
|
| 138 |
+
|
| 139 |
+
logger.info(f"Extracted messages: {text_messages}")
|
| 140 |
+
|
| 141 |
+
# Get the last 5 messages for the summary
|
| 142 |
+
summary = "\n".join(text_messages[-5:]) # Adjust as needed
|
| 143 |
+
logger.info(f"Generated summary: {summary}")
|
| 144 |
+
|
| 145 |
+
# Clear the old history
|
| 146 |
+
chat_memory.clear() # Clear the old history
|
| 147 |
+
|
| 148 |
+
# If the memory allows appending, do that
|
| 149 |
+
chat_memory.buffer.append(summary) # Append the summary
|
| 150 |
+
# Or if there's a method to set the buffer, do that:
|
| 151 |
+
# chat_memory.set_memory([summary]) # If such a method exists
|
| 152 |
+
except Exception as e:
|
| 153 |
+
logger.error(f"Error summarizing chat history: {str(e)}")
|
| 154 |
+
|
| 155 |
+
def route_query(query):
|
| 156 |
+
# Summarize chat history before routing
|
| 157 |
+
summarize_chat_history()
|
| 158 |
+
# Get original query from memory if needed
|
| 159 |
+
original_query = query_memory.memories.get('original_query', query)
|
| 160 |
+
return router_agent.classify_query(original_query)
|
| 161 |
+
|
| 162 |
+
def get_product_info(query):
|
| 163 |
+
# Summarize chat history before retrieving product info
|
| 164 |
+
summarize_chat_history()
|
| 165 |
+
# Get original query from memory if needed
|
| 166 |
+
original_query = query_memory.memories.get('original_query', query)
|
| 167 |
+
response = product_review_agent.process(original_query)
|
| 168 |
+
|
| 169 |
+
return {
|
| 170 |
+
"intermediate_steps": [],
|
| 171 |
+
"output": response,
|
| 172 |
+
"action": "Final Answer",
|
| 173 |
+
"action_input": response
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
def handle_generic_query(query):
|
| 177 |
+
# Summarize chat history before handling generic queries
|
| 178 |
+
summarize_chat_history()
|
| 179 |
+
# Get original query from memory if needed
|
| 180 |
+
original_query = query_memory.memories.get('original_query', query)
|
| 181 |
+
response = generic_agent.process(original_query)
|
| 182 |
+
return {
|
| 183 |
+
"intermediate_steps": [],
|
| 184 |
+
"output": response,
|
| 185 |
+
"action": "Final Answer",
|
| 186 |
+
"action_input": response
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
def handle_order_tracking_query(query):
|
| 190 |
+
# Summarize chat history before handling order tracking queries
|
| 191 |
+
summarize_chat_history()
|
| 192 |
+
# Get the original query or context from memory
|
| 193 |
+
original_query = query_memory.memories.get('original_query', query)
|
| 194 |
+
response = order_tracking_agent_instance.process_query(original_query)
|
| 195 |
+
return {
|
| 196 |
+
"intermediate_steps": [],
|
| 197 |
+
"output": response,
|
| 198 |
+
"action": "Final Answer",
|
| 199 |
+
"action_input": response
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
def compose_response(response):
|
| 203 |
+
return composer_agent.compose_response(response)
|
| 204 |
+
|
| 205 |
+
def execute(query):
|
| 206 |
+
try:
|
| 207 |
+
# Store original query
|
| 208 |
+
query_memory.memories['original_query'] = query
|
| 209 |
+
return agent.run(
|
| 210 |
+
f"Process this user query: {query}"
|
| 211 |
+
)
|
| 212 |
+
except Exception as e:
|
| 213 |
+
logger.error(f"Error in planning agent: {str(e)}")
|
| 214 |
+
return f"Error in planning agent: {str(e)}"
|
| 215 |
+
|
| 216 |
+
def clear_context():
|
| 217 |
+
if chat_memory:
|
| 218 |
+
chat_memory.clear()
|
| 219 |
+
if query_memory:
|
| 220 |
+
query_memory.memories.clear()
|
| 221 |
+
product_review_agent.clear_context()
|
| 222 |
+
generic_agent.clear_context()
|
| 223 |
+
|