from fastapi import FastAPI, HTTPException, Depends
from langchain.agents import Agent, Tool
from langchain.llms import OpenAI
from langchain.memory import ConversationBufferMemory
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
import redis
import logging
from typing import List, Dict, Any, Optional
from datetime import datetime
import json
# Enterprise Customer Service Agent System
class EnterpriseCustomerServiceAgent:
"""Enterprise-grade customer service agent with full business integration"""
def __init__(self, config: Dict[str, Any]):
self.config = config
self.setup_database()
self.setup_cache()
self.setup_logging()
self.setup_integrations()
self.setup_agents()
def setup_database(self):
"""Setup enterprise database connections"""
self.engine = create_engine(self.config['database_url'])
self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self.engine)
# Customer interaction tracking
Base = declarative_base()
class CustomerInteraction(Base):
__tablename__ = "customer_interactions"
id = Column(Integer, primary_key=True, index=True)
customer_id = Column(String, index=True)
session_id = Column(String, index=True)
agent_type = Column(String)
query = Column(Text)
response = Column(Text)
satisfaction_score = Column(Integer)
resolution_status = Column(String)
created_at = Column(DateTime, default=datetime.utcnow)
self.CustomerInteraction = CustomerInteraction
Base.metadata.create_all(bind=self.engine)
def setup_cache(self):
"""Setup Redis cache for session management"""
self.redis_client = redis.Redis(
host=self.config['redis_host'],
port=self.config['redis_port'],
decode_responses=True
)
def setup_logging(self):
"""Setup enterprise logging"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('customer_service_agent.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def setup_integrations(self):
"""Setup enterprise system integrations"""
# CRM Integration
self.crm_tools = [
Tool(
name="get_customer_profile",
description="Retrieve customer profile and history from CRM",
func=self.get_customer_profile
),
Tool(
name="update_customer_record",
description="Update customer information in CRM system",
func=self.update_customer_record
),
Tool(
name="create_support_ticket",
description="Create support ticket in ticketing system",
func=self.create_support_ticket
)
]
# Knowledge Base Integration
self.kb_tools = [
Tool(
name="search_knowledge_base",
description="Search company knowledge base for solutions",
func=self.search_knowledge_base
),
Tool(
name="get_product_info",
description="Retrieve detailed product information",
func=self.get_product_info
),
Tool(
name="check_service_status",
description="Check current service status and outages",
func=self.check_service_status
)
]
# Business Process Integration
self.process_tools = [
Tool(
name="initiate_refund_process",
description="Start refund process for eligible customers",
func=self.initiate_refund_process
),
Tool(
name="schedule_callback",
description="Schedule callback with human agent",
func=self.schedule_callback
),
Tool(
name="escalate_to_supervisor",
description="Escalate complex issues to supervisor",
func=self.escalate_to_supervisor
)
]
def setup_agents(self):
"""Setup specialized customer service agents"""
llm = OpenAI(api_key=self.config['openai_api_key'], temperature=0.1)
# Tier 1 Support Agent
self.tier1_agent = Agent(
llm=llm,
tools=self.crm_tools + self.kb_tools,
memory=ConversationBufferMemory(),
system_message="""You are a Tier 1 customer service agent. Handle common inquiries,
provide product information, and resolve basic issues. Always be helpful, professional,
and empathetic. Escalate complex issues to appropriate specialists."""
)
# Technical Support Agent
self.tech_agent = Agent(
llm=llm,
tools=self.kb_tools + self.process_tools,
memory=ConversationBufferMemory(),
system_message="""You are a technical support specialist. Provide detailed technical
assistance, troubleshooting guidance, and solution recommendations. Use the knowledge
base effectively and create tickets for unresolved issues."""
)
# Billing Support Agent
self.billing_agent = Agent(
llm=llm,
tools=self.crm_tools + self.process_tools,
memory=ConversationBufferMemory(),
system_message="""You are a billing support specialist. Handle billing inquiries,
payment issues, refund requests, and account management. Ensure compliance with
company policies and financial regulations."""
)
def get_customer_profile(self, customer_id: str) -> str:
"""Retrieve customer profile from CRM"""
try:
# Simulate CRM API call
profile = {
"customer_id": customer_id,
"name": "John Doe",
"tier": "Premium",
"account_status": "Active",
"last_interaction": "2024-01-15",
"total_value": "$15,000",
"support_history": [
{"date": "2024-01-10", "issue": "Login problem", "status": "Resolved"},
{"date": "2024-01-05", "issue": "Billing inquiry", "status": "Resolved"}
]
}
self.logger.info(f"Retrieved customer profile for {customer_id}")
return json.dumps(profile)
except Exception as e:
self.logger.error(f"Error retrieving customer profile: {e}")
return "Unable to retrieve customer profile"
def search_knowledge_base(self, query: str) -> str:
"""Search knowledge base for solutions"""
try:
# Simulate knowledge base search
results = [
{
"title": "How to reset password",
"content": "To reset your password, go to login page and click 'Forgot Password'",
"relevance": 0.95
},
{
"title": "Billing cycle information",
"content": "Billing cycles run from the 1st to the last day of each month",
"relevance": 0.87
}
]
self.logger.info(f"Knowledge base search for: {query}")
return json.dumps(results)
except Exception as e:
self.logger.error(f"Error searching knowledge base: {e}")
return "Unable to search knowledge base"
def create_support_ticket(self, issue_description: str, customer_id: str, priority: str = "Medium") -> str:
"""Create support ticket in ticketing system"""
try:
ticket_id = f"TKT-{datetime.now().strftime('%Y%m%d%H%M%S')}"
ticket = {
"ticket_id": ticket_id,
"customer_id": customer_id,
"description": issue_description,
"priority": priority,
"status": "Open",
"created_at": datetime.now().isoformat()
}
self.logger.info(f"Created support ticket {ticket_id} for customer {customer_id}")
return f"Support ticket {ticket_id} created successfully"
except Exception as e:
self.logger.error(f"Error creating support ticket: {e}")
return "Unable to create support ticket"
def handle_customer_inquiry(self, customer_id: str, query: str, session_id: str) -> Dict[str, Any]:
"""Handle customer inquiry with appropriate agent"""
try:
# Determine appropriate agent based on query classification
agent_type = self.classify_inquiry(query)
# Select appropriate agent
if agent_type == "technical":
agent = self.tech_agent
elif agent_type == "billing":
agent = self.billing_agent
else:
agent = self.tier1_agent
# Get customer context
customer_profile = self.get_customer_profile(customer_id)
# Prepare context-aware prompt
context_prompt = f"""
Customer Profile: {customer_profile}
Customer Query: {query}
Please provide a helpful, professional response addressing the customer's needs.
"""
# Generate response
response = agent.run(context_prompt)
# Store interaction in database
self.store_interaction(customer_id, session_id, agent_type, query, response)
# Cache session data
self.update_session_cache(session_id, {
"customer_id": customer_id,
"last_agent": agent_type,
"last_query": query,
"timestamp": datetime.now().isoformat()
})
return {
"response": response,
"agent_type": agent_type,
"session_id": session_id,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
self.logger.error(f"Error handling customer inquiry: {e}")
return {
"response": "I apologize, but I'm experiencing technical difficulties. Please try again or contact our support team directly.",
"agent_type": "error",
"session_id": session_id,
"error": str(e)
}
def classify_inquiry(self, query: str) -> str:
"""Classify customer inquiry to route to appropriate agent"""
query_lower = query.lower()
# Technical keywords
technical_keywords = ['error', 'bug', 'not working', 'technical', 'login', 'password', 'setup']
# Billing keywords
billing_keywords = ['bill', 'payment', 'charge', 'refund', 'invoice', 'subscription', 'pricing']
if any(keyword in query_lower for keyword in technical_keywords):
return "technical"
elif any(keyword in query_lower for keyword in billing_keywords):
return "billing"
else:
return "general"
def store_interaction(self, customer_id: str, session_id: str, agent_type: str, query: str, response: str):
"""Store customer interaction in database"""
db = self.SessionLocal()
try:
interaction = self.CustomerInteraction(
customer_id=customer_id,
session_id=session_id,
agent_type=agent_type,
query=query,
response=response,
resolution_status="In Progress"
)
db.add(interaction)
db.commit()
except Exception as e:
self.logger.error(f"Error storing interaction: {e}")
db.rollback()
finally:
db.close()
def update_session_cache(self, session_id: str, data: Dict[str, Any]):
"""Update session data in Redis cache"""
try:
self.redis_client.setex(
f"session:{session_id}",
3600, # 1 hour expiry
json.dumps(data)
)
except Exception as e:
self.logger.error(f"Error updating session cache: {e}")
def get_analytics_dashboard(self) -> Dict[str, Any]:
"""Generate analytics dashboard for management"""
db = self.SessionLocal()
try:
# Query interaction statistics
total_interactions = db.query(self.CustomerInteraction).count()
# Agent performance metrics
agent_stats = db.query(
self.CustomerInteraction.agent_type,
db.func.count(self.CustomerInteraction.id).label('count'),
db.func.avg(self.CustomerInteraction.satisfaction_score).label('avg_satisfaction')
).group_by(self.CustomerInteraction.agent_type).all()
return {
"total_interactions": total_interactions,
"agent_performance": [
{
"agent_type": stat.agent_type,
"interaction_count": stat.count,
"avg_satisfaction": round(stat.avg_satisfaction or 0, 2)
}
for stat in agent_stats
],
"generated_at": datetime.now().isoformat()
}
except Exception as e:
self.logger.error(f"Error generating analytics: {e}")
return {"error": "Unable to generate analytics"}
finally:
db.close()
# FastAPI Application
app = FastAPI(title="Enterprise Customer Service Agent API")
# Initialize agent system
config = {
"database_url": "postgresql://user:password@localhost/customer_service",
"redis_host": "localhost",
"redis_port": 6379,
"openai_api_key": "your-openai-api-key"
}
cs_agent = EnterpriseCustomerServiceAgent(config)
@app.post("/api/customer-inquiry")
async def handle_inquiry(customer_id: str, query: str, session_id: str):
"""Handle customer inquiry endpoint"""
result = cs_agent.handle_customer_inquiry(customer_id, query, session_id)
return result
@app.get("/api/analytics")
async def get_analytics():
"""Get analytics dashboard"""
return cs_agent.get_analytics_dashboard()
@app.get("/api/health")
async def health_check():
"""Health check endpoint"""
return {"status": "healthy", "timestamp": datetime.now().isoformat()}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)