Spaces:
Runtime error
Runtime error
Update ui/conversation.py
Browse files- ui/conversation.py +80 -90
ui/conversation.py
CHANGED
|
@@ -1,95 +1,85 @@
|
|
| 1 |
-
|
| 2 |
-
Understanding agent for pharmaceutical data management.
|
| 3 |
-
This agent extracts user intent from natural language conversations.
|
| 4 |
-
"""
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
from anthropic.types import MessageParam
|
| 10 |
-
|
| 11 |
-
def understanding_agent(anthropic_client, state: Dict[str, Any]) -> Dict[str, Any]:
|
| 12 |
-
"""
|
| 13 |
-
Agent that understands user intent and requests clarification if needed.
|
| 14 |
-
|
| 15 |
-
Args:
|
| 16 |
-
anthropic_client: The Anthropic client for calling Claude API
|
| 17 |
-
state: Current state of the agent workflow
|
| 18 |
-
|
| 19 |
-
Returns:
|
| 20 |
-
Updated state
|
| 21 |
-
"""
|
| 22 |
-
# Ensure messages is properly initialized as a list
|
| 23 |
-
messages = state.get("messages", [])
|
| 24 |
-
if not isinstance(messages, list):
|
| 25 |
-
messages = []
|
| 26 |
-
|
| 27 |
-
# Format all messages to ensure they have role and content
|
| 28 |
-
formatted_messages = []
|
| 29 |
-
for msg in messages:
|
| 30 |
-
if isinstance(msg, dict) and "role" in msg and "content" in msg:
|
| 31 |
-
formatted_messages.append(msg)
|
| 32 |
-
|
| 33 |
-
# Add agent-specific instructions
|
| 34 |
-
system_message = """
|
| 35 |
-
You are an AI assistant specializing in understanding pharmaceutical data needs.
|
| 36 |
-
Your job is to understand what data pipeline the user needs to create.
|
| 37 |
-
Extract key information:
|
| 38 |
-
1. Business question/goal
|
| 39 |
-
2. Required data sources/tables
|
| 40 |
-
3. Needed transformations
|
| 41 |
-
4. Output format/visualization
|
| 42 |
-
5. Time frame/frequency
|
| 43 |
-
|
| 44 |
-
If information is missing, ask clarifying questions.
|
| 45 |
-
If you understand the request fully, summarize the user's intent and tag it as INTENT_COMPLETE.
|
| 46 |
-
"""
|
| 47 |
-
|
| 48 |
-
# Convert messages to the format expected by Anthropic API
|
| 49 |
-
anthropic_messages = []
|
| 50 |
-
for msg in formatted_messages:
|
| 51 |
-
anthropic_messages.append(MessageParam(
|
| 52 |
-
role=msg["role"],
|
| 53 |
-
content=msg["content"]
|
| 54 |
-
))
|
| 55 |
-
|
| 56 |
-
# Call Claude API
|
| 57 |
-
response = anthropic_client.messages.create(
|
| 58 |
-
model="claude-3-7-sonnet-20250219",
|
| 59 |
-
system=system_message,
|
| 60 |
-
messages=anthropic_messages,
|
| 61 |
-
max_tokens=2000
|
| 62 |
-
)
|
| 63 |
-
|
| 64 |
-
# Extract the response
|
| 65 |
-
agent_response = response.content[0].text
|
| 66 |
-
|
| 67 |
-
# Check if intent is complete
|
| 68 |
-
intent_complete = "INTENT_COMPLETE" in agent_response
|
| 69 |
|
| 70 |
-
#
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
# Parse the structured intent from the response
|
| 74 |
-
# This would be more sophisticated in production
|
| 75 |
-
user_intent = {
|
| 76 |
-
"understood": True,
|
| 77 |
-
"description": agent_response.replace("INTENT_COMPLETE", "").strip(),
|
| 78 |
-
"time": time.time()
|
| 79 |
-
}
|
| 80 |
-
new_state["user_intent"] = user_intent
|
| 81 |
-
new_state["current_agent"] = "planning_agent"
|
| 82 |
-
else:
|
| 83 |
-
# Need more information, stay with understanding agent
|
| 84 |
-
new_state["current_agent"] = "understanding_agent"
|
| 85 |
|
| 86 |
-
#
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
|
|
|
| 94 |
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
+
def render_conversation_tab(session_state, agent_graph, update_state_dict):
|
| 4 |
+
"""Render the conversation tab in the UI."""
|
| 5 |
+
st.subheader("Conversation with Data Management Agent")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
+
# Initialize messages in conversation if not already present
|
| 8 |
+
if "messages" not in session_state.conversation:
|
| 9 |
+
session_state.conversation["messages"] = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
+
# Display conversation history
|
| 12 |
+
for message in session_state.conversation["messages"]:
|
| 13 |
+
if isinstance(message, dict) and "role" in message and "content" in message:
|
| 14 |
+
if message["role"] == "user":
|
| 15 |
+
st.markdown(f"**You:** {message['content']}")
|
| 16 |
+
else:
|
| 17 |
+
st.markdown(f"**Agent:** {message['content']}")
|
| 18 |
|
| 19 |
+
# Input for new message
|
| 20 |
+
with st.form(key="user_input_form"):
|
| 21 |
+
user_input = st.text_area("What data pipeline do you need to create?",
|
| 22 |
+
placeholder="e.g., I need a sales performance dashboard showing regional performance by product for the last 2 years")
|
| 23 |
+
submit_button = st.form_submit_button("Submit")
|
| 24 |
|
| 25 |
+
if submit_button and user_input:
|
| 26 |
+
# Add user message to conversation
|
| 27 |
+
new_message = {"role": "user", "content": user_input}
|
| 28 |
+
session_state.conversation["messages"].append(new_message)
|
| 29 |
+
|
| 30 |
+
# Update agent state - ensure messages is a list
|
| 31 |
+
agent_state = session_state.agent_state.copy()
|
| 32 |
+
if "messages" not in agent_state or not isinstance(agent_state["messages"], list):
|
| 33 |
+
agent_state["messages"] = []
|
| 34 |
+
|
| 35 |
+
# Add new message to agent state
|
| 36 |
+
agent_state["messages"].append(new_message)
|
| 37 |
+
|
| 38 |
+
# Run the agent graph
|
| 39 |
+
with st.spinner("Agent is processing..."):
|
| 40 |
+
try:
|
| 41 |
+
# Update the state dictionary for tools
|
| 42 |
+
update_state_dict(agent_state)
|
| 43 |
+
|
| 44 |
+
# Execute the agent workflow
|
| 45 |
+
result = agent_graph.invoke(agent_state)
|
| 46 |
+
|
| 47 |
+
# Update session state with result
|
| 48 |
+
session_state.agent_state = result
|
| 49 |
+
|
| 50 |
+
# Update the state dictionary for tools again with the result
|
| 51 |
+
update_state_dict(result)
|
| 52 |
+
|
| 53 |
+
# Ensure messages is a list in the result
|
| 54 |
+
if not isinstance(result.get("messages", []), list):
|
| 55 |
+
result["messages"] = []
|
| 56 |
+
|
| 57 |
+
# Update conversation with agent responses
|
| 58 |
+
for message in result.get("messages", []):
|
| 59 |
+
if isinstance(message, dict) and "role" in message and "content" in message:
|
| 60 |
+
# Check if this message isn't already in the conversation
|
| 61 |
+
message_exists = False
|
| 62 |
+
for existing_msg in session_state.conversation["messages"]:
|
| 63 |
+
if (isinstance(existing_msg, dict) and
|
| 64 |
+
existing_msg.get("role") == message.get("role") and
|
| 65 |
+
existing_msg.get("content") == message.get("content")):
|
| 66 |
+
message_exists = True
|
| 67 |
+
break
|
| 68 |
+
|
| 69 |
+
if not message_exists:
|
| 70 |
+
session_state.conversation["messages"].append(message)
|
| 71 |
+
|
| 72 |
+
# Update other state properties
|
| 73 |
+
session_state.conversation["user_intent"] = result.get("user_intent", {})
|
| 74 |
+
session_state.conversation["pipeline_plan"] = result.get("pipeline_plan", {})
|
| 75 |
+
session_state.conversation["sql_queries"] = result.get("sql_queries", [])
|
| 76 |
+
session_state.conversation["execution_results"] = result.get("execution_results", {})
|
| 77 |
+
session_state.conversation["confidence_scores"] = result.get("confidence_scores", {})
|
| 78 |
+
session_state.conversation["status"] = result.get("status", "planning")
|
| 79 |
+
session_state.conversation["current_agent"] = result.get("current_agent", "understanding_agent")
|
| 80 |
+
|
| 81 |
+
# Force refresh
|
| 82 |
+
st.rerun()
|
| 83 |
+
|
| 84 |
+
except Exception as e:
|
| 85 |
+
st.error(f"Error executing agent workflow: {str(e)}")
|