sales_analytics / diagnostics.py
cryogenic22's picture
Update diagnostics.py
4fbaac8 verified
"""
Simplified Planning Agent for Pharmaceutical Analytics
This version uses direct API calls instead of LangChain components
"""
import os
import json
import re
from typing import Dict, List, Any, Tuple
from pydantic import BaseModel, Field
# Define analysis plan schema
class AnalysisPlan(BaseModel):
"""Planning agent output with analysis plan details"""
problem_statement: str = Field(description="Refined problem statement based on the alert")
required_data_sources: List[Dict[str, str]] = Field(
description="List of data sources needed with table name and purpose")
analysis_approaches: List[Dict[str, str]] = Field(
description="List of analytical approaches to be used with type and purpose")
tasks: List[Dict[str, Any]] = Field(
description="Ordered list of tasks to execute with dependencies")
expected_insights: List[str] = Field(
description="List of expected insights that would answer the problem")
class PlanningAgent:
"""Agent responsible for planning the analysis workflow"""
def __init__(self):
"""Initialize the planning agent"""
api_key = os.getenv("ANTHROPIC_API_KEY")
if not api_key:
raise ValueError("ANTHROPIC_API_KEY not found in environment variables")
self.api_key = api_key
print("Planning Agent initialized successfully")
def create_analysis_plan(self, alert_description: str) -> Tuple[AnalysisPlan, Dict]:
"""Generate an analysis plan based on the alert description"""
print("Planning Agent: Creating analysis plan...")
# Create the system prompt and user message
system_prompt = """You are an expert pharmaceutical analytics planning agent.
Your task is to create a detailed analysis plan to investigate sales anomalies.
For pharmaceutical sales analysis:
- Consider product performance, competitor activities, prescriber behavior
- Include geographic, temporal, and demographic dimensions in your analysis
- Consider both internal factors (supply, marketing) and external factors (market events, seasonality)
Your output should be a complete JSON-formatted analysis plan following this structure:
{
"problem_statement": "Clear definition of the problem to solve",
"required_data_sources": [
{"table": "sales", "purpose": "Core sales metrics analysis"},
{"table": "regions", "purpose": "Geographic segmentation"}
],
"analysis_approaches": [
{"type": "time_series_decomposition", "purpose": "Separate trend from seasonality"},
{"type": "comparative_analysis", "purpose": "Compare performance across regions"}
],
"tasks": [
{
"id": 1,
"name": "Data acquisition",
"description": "Pull relevant data from sources",
"agent": "data_agent",
"dependencies": [],
"expected_output": "Cleaned datasets for analysis"
},
{
"id": 2,
"name": "Analysis execution",
"description": "Perform statistical analysis",
"agent": "analytics_agent",
"dependencies": [1],
"expected_output": "Analysis results"
}
],
"expected_insights": [
"Primary factors contributing to sales decline",
"Regional variations in performance"
]
}
Be thorough but focus on creating a practical analysis workflow.
"""
user_message = f"Create an analysis plan for the following alert: {alert_description}"
# Make direct API call to Claude
try:
import anthropic
client = anthropic.Anthropic(api_key=self.api_key)
# FIXED: Pass system as a parameter, not as a message
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=2000,
temperature=0.2,
system=system_prompt, # Pass as system parameter
messages=[
{"role": "user", "content": user_message}
]
)
# Extract response content
response_text = response.content[0].text
# Extract JSON from the response
plan_dict = self.extract_json_from_text(response_text)
# Convert to Pydantic model for validation
analysis_plan = AnalysisPlan.model_validate(plan_dict)
return analysis_plan, plan_dict
except Exception as e:
print(f"Error creating analysis plan: {e}")
raise
def extract_json_from_text(self, text: str) -> Dict:
"""Extract JSON from text that might contain additional content"""
try:
# First try to parse the entire text as JSON
return json.loads(text)
except json.JSONDecodeError:
# Try to find JSON block with regex
json_pattern = r'```json\s*([\s\S]*?)\s*```'
match = re.search(json_pattern, text)
if match:
try:
return json.loads(match.group(1))
except json.JSONDecodeError:
pass
# Try to find anything that looks like JSON
json_pattern = r'({[\s\S]*})'
match = re.search(json_pattern, text)
if match:
try:
return json.loads(match.group(1))
except json.JSONDecodeError:
pass
# If all extraction attempts fail
raise ValueError(f"Could not extract JSON from response: {text}")
# For testing
if __name__ == "__main__":
# Get API key from environment
agent = PlanningAgent()
alert = "Sales of DrugX down 15% in Northeast region over past 30 days compared to forecast."
plan, plan_dict = agent.create_analysis_plan(alert)
print(json.dumps(plan_dict, indent=2))