cryogenic22 commited on
Commit
4fbaac8
·
verified ·
1 Parent(s): 4c2ee17

Update diagnostics.py

Browse files
Files changed (1) hide show
  1. diagnostics.py +135 -224
diagnostics.py CHANGED
@@ -1,243 +1,154 @@
1
  """
2
- Updated diagnostics module for the Pharmaceutical Analytics application.
3
- Uses the simplified Planning Agent implementation.
4
  """
5
 
6
- import streamlit as st
7
  import os
8
  import json
9
- import traceback
10
- import time
11
- from datetime import datetime
12
- from typing import Dict, Any, Tuple
13
 
14
- def test_claude_connectivity() -> Tuple[bool, str]:
15
- """
16
- Test basic connectivity to Claude API
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- Returns:
19
- Tuple of (success_flag, response_or_error)
20
- """
21
- try:
22
- # Check API key
23
  api_key = os.getenv("ANTHROPIC_API_KEY")
24
  if not api_key:
25
- return False, "No ANTHROPIC_API_KEY found in environment variables"
26
-
27
- # Import anthropic
28
- try:
29
- import anthropic
30
- except ImportError:
31
- return False, "Failed to import anthropic library. Make sure it's installed (pip install anthropic)"
32
-
33
- # Create client and send request
34
- client = anthropic.Anthropic(api_key=api_key)
35
-
36
- response = client.messages.create(
37
- model="claude-3-haiku-20240307",
38
- max_tokens=300,
39
- messages=[
40
- {"role": "user", "content": "Briefly tell me about Egyptian history in 2-3 sentences."}
41
- ]
42
- )
43
 
44
- if response and response.content:
45
- return True, response.content[0].text
46
- else:
47
- return False, "Received empty response from Anthropic API"
 
 
48
 
49
- except Exception as e:
50
- error_msg = f"Error testing Claude API: {str(e)}\n\n{traceback.format_exc()}"
51
- return False, error_msg
52
 
53
- def test_simplified_agent() -> Tuple[bool, Dict[str, Any]]:
54
- """
55
- Test the simplified Planning Agent functionality
56
-
57
- Returns:
58
- Tuple of (success_flag, results_dict)
59
- """
60
- results = {
61
- "steps": [],
62
- "errors": [],
63
- "plan": None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
-
66
- try:
67
- # Test Planning Agent import
68
- results["steps"].append({"step": "import", "status": "started"})
69
- try:
70
- from simplified_planning_agent import PlanningAgent
71
- results["steps"].append({"step": "import", "status": "success"})
72
- except Exception as import_error:
73
- error_msg = f"Error importing simplified PlanningAgent: {str(import_error)}\n\n{traceback.format_exc()}"
74
- results["errors"].append({"phase": "import", "error": error_msg})
75
- return False, results
76
 
77
- # Test agent initialization
78
- results["steps"].append({"step": "initialization", "status": "started"})
79
- try:
80
- planning_agent = PlanningAgent()
81
- results["steps"].append({"step": "initialization", "status": "success"})
82
- except Exception as init_error:
83
- error_msg = f"Error initializing PlanningAgent: {str(init_error)}\n\n{traceback.format_exc()}"
84
- results["errors"].append({"phase": "initialization", "error": error_msg})
85
- return False, results
86
 
87
- # Test plan creation
88
- results["steps"].append({"step": "plan_creation", "status": "started"})
89
  try:
90
- test_alert = "Sales of DrugX down 15% in Northeast region over past 30 days."
91
- analysis_plan, plan_dict = planning_agent.create_analysis_plan(test_alert)
92
 
93
- results["steps"].append({"step": "plan_creation", "status": "success"})
94
- results["plan"] = plan_dict
95
- return True, results
96
- except Exception as plan_error:
97
- error_msg = f"Error creating analysis plan: {str(plan_error)}\n\n{traceback.format_exc()}"
98
- results["errors"].append({"phase": "plan_creation", "error": error_msg})
99
- return False, results
 
 
 
100
 
101
- except Exception as e:
102
- error_msg = f"Unexpected error in agent functionality test: {str(e)}\n\n{traceback.format_exc()}"
103
- results["errors"].append({"phase": "unknown", "error": error_msg})
104
- return False, results
105
-
106
- def render_diagnostics_tab():
107
- """
108
- Render the diagnostics tab in the Streamlit app
109
- """
110
- st.header("🔧 System Diagnostics")
111
-
112
- # Environment information
113
- st.subheader("Environment Information")
114
-
115
- # Check API key
116
- api_key = os.getenv("ANTHROPIC_API_KEY")
117
- api_status = "✅ Set" if api_key else "❌ Not Set"
118
-
119
- environment_data = {
120
- "API Key": api_status,
121
- "Python Version": os.sys.version,
122
- "Timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
123
- }
124
-
125
- # Try to get library versions
126
- try:
127
- import anthropic
128
- environment_data["Anthropic Library"] = anthropic.__version__
129
- except (ImportError, AttributeError):
130
- environment_data["Anthropic Library"] = "Not found"
131
-
132
- try:
133
- import langgraph
134
- environment_data["LangGraph Library"] = langgraph.__version__
135
- except (ImportError, AttributeError):
136
- environment_data["LangGraph Library"] = "Not found"
137
-
138
- # Display environment table
139
- for key, value in environment_data.items():
140
- cols = st.columns([1, 3])
141
- with cols[0]:
142
- st.markdown(f"**{key}:**")
143
- with cols[1]:
144
- st.markdown(f"{value}")
145
-
146
- # Claude connectivity test
147
- st.subheader("Claude LLM Test")
148
- if st.button("Test Claude Connectivity"):
149
- with st.spinner("Testing connection to Claude..."):
150
- success, response = test_claude_connectivity()
151
-
152
- if success:
153
- st.success("✅ Claude API is working properly!")
154
- st.markdown("**Response:**")
155
- st.info(response)
156
- else:
157
- st.error("❌ Claude API test failed")
158
- st.expander("Error Details", expanded=True).error(response)
159
-
160
- # Simplified Agent functionality test
161
- st.subheader("Simplified Planning Agent Test")
162
- if st.button("Test Simplified Planning Agent"):
163
- with st.spinner("Testing Simplified Planning Agent..."):
164
- success, results = test_simplified_agent()
165
-
166
- if success:
167
- st.success("✅ Simplified Planning Agent is working properly!")
168
- st.json(results["plan"])
169
- else:
170
- st.error("�� Simplified Planning Agent test failed")
171
- for error in results["errors"]:
172
- st.expander(f"Error in {error['phase']} phase", expanded=True).error(error["error"])
173
-
174
- # Original Agent functionality test
175
- st.subheader("Original Planning Agent Test (Likely to Fail)")
176
- if st.button("Test Original Planning Agent"):
177
- with st.spinner("Testing Original Planning Agent..."):
178
- try:
179
- from agents.planning_agent import PlanningAgent
180
- planning_agent = PlanningAgent()
181
- test_alert = "Sales of DrugX down 15% in Northeast region over past 30 days."
182
- analysis_plan, plan_dict = planning_agent.create_analysis_plan(test_alert)
183
-
184
- st.success("✅ Original Planning Agent is working!")
185
- st.json(plan_dict)
186
- except Exception as e:
187
- st.error("❌ Original Planning Agent test failed")
188
- st.expander("Error Details", expanded=True).error(f"{str(e)}\n\n{traceback.format_exc()}")
189
-
190
- # Database Connectivity
191
- st.subheader("Database Connectivity")
192
- if st.button("Test Database Connection"):
193
- with st.spinner("Testing database connection..."):
194
- try:
195
- import sqlite3
196
- conn = sqlite3.connect("data/pharma_db.sqlite")
197
-
198
- # Test query
199
- cursor = conn.cursor()
200
- cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
201
- tables = cursor.fetchall()
202
-
203
- # Close connection
204
- conn.close()
205
-
206
- st.success(f"✅ Successfully connected to database")
207
- st.write(f"Found {len(tables)} tables:")
208
- st.json([table[0] for table in tables])
209
-
210
- except Exception as e:
211
- st.error(f"❌ Database connection failed: {str(e)}")
212
- st.expander("Error Details", expanded=True).error(traceback.format_exc())
213
-
214
- # Add guidance
215
- st.markdown("---")
216
- st.markdown("""
217
- ### Using the Simplified Agent
218
-
219
- The original Planning Agent implementation has issues with the LangChain prompt templates.
220
- We've created a simplified version that uses direct API calls to Claude.
221
-
222
- To use the simplified agent:
223
-
224
- 1. Copy the `simplified_planning_agent.py` file to your project
225
- 2. Update your workflow to import from `simplified_planning_agent` instead of `agents.planning_agent`
226
-
227
- ### Troubleshooting Tips
228
-
229
- 1. If Claude test fails:
230
- - Check your API key in environment variables
231
- - Verify internet connectivity
232
- - Confirm your API key has sufficient credits
233
-
234
- 2. If Agent test fails:
235
- - Check import errors (are all libraries installed?)
236
- - Verify agent implementation
237
- - Check for syntax errors in agent code
238
 
239
- 3. If Database test fails:
240
- - Verify database file exists
241
- - Check file permissions
242
- - Run setup_environment() function again
243
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ Simplified Planning Agent for Pharmaceutical Analytics
3
+ This version uses direct API calls instead of LangChain components
4
  """
5
 
 
6
  import os
7
  import json
8
+ import re
9
+ from typing import Dict, List, Any, Tuple
10
+ from pydantic import BaseModel, Field
 
11
 
12
+ # Define analysis plan schema
13
+ class AnalysisPlan(BaseModel):
14
+ """Planning agent output with analysis plan details"""
15
+ problem_statement: str = Field(description="Refined problem statement based on the alert")
16
+ required_data_sources: List[Dict[str, str]] = Field(
17
+ description="List of data sources needed with table name and purpose")
18
+ analysis_approaches: List[Dict[str, str]] = Field(
19
+ description="List of analytical approaches to be used with type and purpose")
20
+ tasks: List[Dict[str, Any]] = Field(
21
+ description="Ordered list of tasks to execute with dependencies")
22
+ expected_insights: List[str] = Field(
23
+ description="List of expected insights that would answer the problem")
24
+
25
+ class PlanningAgent:
26
+ """Agent responsible for planning the analysis workflow"""
27
 
28
+ def __init__(self):
29
+ """Initialize the planning agent"""
 
 
 
30
  api_key = os.getenv("ANTHROPIC_API_KEY")
31
  if not api_key:
32
+ raise ValueError("ANTHROPIC_API_KEY not found in environment variables")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ self.api_key = api_key
35
+ print("Planning Agent initialized successfully")
36
+
37
+ def create_analysis_plan(self, alert_description: str) -> Tuple[AnalysisPlan, Dict]:
38
+ """Generate an analysis plan based on the alert description"""
39
+ print("Planning Agent: Creating analysis plan...")
40
 
41
+ # Create the system prompt and user message
42
+ system_prompt = """You are an expert pharmaceutical analytics planning agent.
43
+ Your task is to create a detailed analysis plan to investigate sales anomalies.
44
 
45
+ For pharmaceutical sales analysis:
46
+ - Consider product performance, competitor activities, prescriber behavior
47
+ - Include geographic, temporal, and demographic dimensions in your analysis
48
+ - Consider both internal factors (supply, marketing) and external factors (market events, seasonality)
49
+
50
+ Your output should be a complete JSON-formatted analysis plan following this structure:
51
+ {
52
+ "problem_statement": "Clear definition of the problem to solve",
53
+ "required_data_sources": [
54
+ {"table": "sales", "purpose": "Core sales metrics analysis"},
55
+ {"table": "regions", "purpose": "Geographic segmentation"}
56
+ ],
57
+ "analysis_approaches": [
58
+ {"type": "time_series_decomposition", "purpose": "Separate trend from seasonality"},
59
+ {"type": "comparative_analysis", "purpose": "Compare performance across regions"}
60
+ ],
61
+ "tasks": [
62
+ {
63
+ "id": 1,
64
+ "name": "Data acquisition",
65
+ "description": "Pull relevant data from sources",
66
+ "agent": "data_agent",
67
+ "dependencies": [],
68
+ "expected_output": "Cleaned datasets for analysis"
69
+ },
70
+ {
71
+ "id": 2,
72
+ "name": "Analysis execution",
73
+ "description": "Perform statistical analysis",
74
+ "agent": "analytics_agent",
75
+ "dependencies": [1],
76
+ "expected_output": "Analysis results"
77
  }
78
+ ],
79
+ "expected_insights": [
80
+ "Primary factors contributing to sales decline",
81
+ "Regional variations in performance"
82
+ ]
83
+ }
84
+
85
+ Be thorough but focus on creating a practical analysis workflow.
86
+ """
 
 
87
 
88
+ user_message = f"Create an analysis plan for the following alert: {alert_description}"
 
 
 
 
 
 
 
 
89
 
90
+ # Make direct API call to Claude
 
91
  try:
92
+ import anthropic
93
+ client = anthropic.Anthropic(api_key=self.api_key)
94
 
95
+ # FIXED: Pass system as a parameter, not as a message
96
+ response = client.messages.create(
97
+ model="claude-3-haiku-20240307",
98
+ max_tokens=2000,
99
+ temperature=0.2,
100
+ system=system_prompt, # Pass as system parameter
101
+ messages=[
102
+ {"role": "user", "content": user_message}
103
+ ]
104
+ )
105
 
106
+ # Extract response content
107
+ response_text = response.content[0].text
108
+
109
+ # Extract JSON from the response
110
+ plan_dict = self.extract_json_from_text(response_text)
111
+
112
+ # Convert to Pydantic model for validation
113
+ analysis_plan = AnalysisPlan.model_validate(plan_dict)
114
+
115
+ return analysis_plan, plan_dict
116
+
117
+ except Exception as e:
118
+ print(f"Error creating analysis plan: {e}")
119
+ raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
+ def extract_json_from_text(self, text: str) -> Dict:
122
+ """Extract JSON from text that might contain additional content"""
123
+ try:
124
+ # First try to parse the entire text as JSON
125
+ return json.loads(text)
126
+ except json.JSONDecodeError:
127
+ # Try to find JSON block with regex
128
+ json_pattern = r'```json\s*([\s\S]*?)\s*```'
129
+ match = re.search(json_pattern, text)
130
+ if match:
131
+ try:
132
+ return json.loads(match.group(1))
133
+ except json.JSONDecodeError:
134
+ pass
135
+
136
+ # Try to find anything that looks like JSON
137
+ json_pattern = r'({[\s\S]*})'
138
+ match = re.search(json_pattern, text)
139
+ if match:
140
+ try:
141
+ return json.loads(match.group(1))
142
+ except json.JSONDecodeError:
143
+ pass
144
+
145
+ # If all extraction attempts fail
146
+ raise ValueError(f"Could not extract JSON from response: {text}")
147
+
148
+ # For testing
149
+ if __name__ == "__main__":
150
+ # Get API key from environment
151
+ agent = PlanningAgent()
152
+ alert = "Sales of DrugX down 15% in Northeast region over past 30 days compared to forecast."
153
+ plan, plan_dict = agent.create_analysis_plan(alert)
154
+ print(json.dumps(plan_dict, indent=2))