PD03 commited on
Commit
0846ca3
Β·
verified Β·
1 Parent(s): bc02e50

Create agents/procurement_agent.py

Browse files
Files changed (1) hide show
  1. agents/procurement_agent.py +189 -0
agents/procurement_agent.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ from typing import Dict, List, Any
4
+ import streamlit as st
5
+
6
+ class ProcurementAgent:
7
+ def __init__(self):
8
+ self.insights = []
9
+
10
+ def analyze_spend_trends(self, df: pd.DataFrame) -> Dict[str, Any]:
11
+ """Analyze spending trends and patterns"""
12
+ try:
13
+ # Monthly spend analysis
14
+ df['PO_Date'] = pd.to_datetime(df['PO_Date'])
15
+ monthly_spend = df.groupby(df['PO_Date'].dt.to_period('M'))['Total_Value'].sum()
16
+
17
+ # Calculate trend
18
+ if len(monthly_spend) > 1:
19
+ trend = "increasing" if monthly_spend.iloc[-1] > monthly_spend.iloc[-2] else "decreasing"
20
+ else:
21
+ trend = "stable"
22
+
23
+ # Top categories
24
+ category_spend = df.groupby('Category')['Total_Value'].sum().sort_values(ascending=False)
25
+
26
+ insights = {
27
+ 'total_spend': df['Total_Value'].sum(),
28
+ 'monthly_trend': trend,
29
+ 'top_category': category_spend.index[0],
30
+ 'top_category_spend': category_spend.iloc[0],
31
+ 'avg_po_value': df['Total_Value'].mean(),
32
+ 'recommendations': self._generate_spend_recommendations(df)
33
+ }
34
+
35
+ return insights
36
+ except Exception as e:
37
+ st.error(f"Error in spend analysis: {str(e)}")
38
+ return {}
39
+
40
+ def analyze_supplier_performance(self, df: pd.DataFrame) -> Dict[str, Any]:
41
+ """Analyze supplier performance metrics"""
42
+ try:
43
+ supplier_metrics = df.groupby('Supplier').agg({
44
+ 'Total_Value': 'sum',
45
+ 'Delivery_Performance': 'mean',
46
+ 'PO_Number': 'count'
47
+ }).round(2)
48
+
49
+ # Best and worst performers
50
+ best_supplier = supplier_metrics.loc[supplier_metrics['Delivery_Performance'].idxmax()]
51
+ worst_supplier = supplier_metrics.loc[supplier_metrics['Delivery_Performance'].idxmin()]
52
+
53
+ insights = {
54
+ 'best_performer': {
55
+ 'name': best_supplier.name,
56
+ 'performance': best_supplier['Delivery_Performance']
57
+ },
58
+ 'worst_performer': {
59
+ 'name': worst_supplier.name,
60
+ 'performance': worst_supplier['Delivery_Performance']
61
+ },
62
+ 'recommendations': self._generate_supplier_recommendations(supplier_metrics)
63
+ }
64
+
65
+ return insights
66
+ except Exception as e:
67
+ st.error(f"Error in supplier analysis: {str(e)}")
68
+ return {}
69
+
70
+ def detect_anomalies(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
71
+ """Detect procurement anomalies"""
72
+ anomalies = []
73
+
74
+ try:
75
+ # High value orders
76
+ threshold = df['Total_Value'].quantile(0.95)
77
+ high_value_orders = df[df['Total_Value'] > threshold]
78
+
79
+ for _, order in high_value_orders.iterrows():
80
+ anomalies.append({
81
+ 'type': 'High Value Order',
82
+ 'po_number': order['PO_Number'],
83
+ 'value': order['Total_Value'],
84
+ 'supplier': order['Supplier'],
85
+ 'risk_level': 'Medium' if order['Total_Value'] < threshold * 1.5 else 'High'
86
+ })
87
+
88
+ # Overdue deliveries
89
+ df['PO_Date'] = pd.to_datetime(df['PO_Date'])
90
+ df['Delivery_Date'] = pd.to_datetime(df['Delivery_Date'])
91
+
92
+ overdue = df[
93
+ (df['Delivery_Date'] < pd.Timestamp.now()) &
94
+ (df['Status'] == 'Open')
95
+ ]
96
+
97
+ for _, order in overdue.iterrows():
98
+ days_overdue = (pd.Timestamp.now() - order['Delivery_Date']).days
99
+ anomalies.append({
100
+ 'type': 'Overdue Delivery',
101
+ 'po_number': order['PO_Number'],
102
+ 'days_overdue': days_overdue,
103
+ 'supplier': order['Supplier'],
104
+ 'risk_level': 'High' if days_overdue > 30 else 'Medium'
105
+ })
106
+
107
+ except Exception as e:
108
+ st.error(f"Error in anomaly detection: {str(e)}")
109
+
110
+ return anomalies[:10] # Return top 10 anomalies
111
+
112
+ def _generate_spend_recommendations(self, df: pd.DataFrame) -> List[str]:
113
+ """Generate AI-powered spending recommendations"""
114
+ recommendations = []
115
+
116
+ # Category concentration analysis
117
+ category_spend = df.groupby('Category')['Total_Value'].sum()
118
+ total_spend = category_spend.sum()
119
+
120
+ for category, spend in category_spend.items():
121
+ percentage = (spend / total_spend) * 100
122
+ if percentage > 30:
123
+ recommendations.append(f"🎯 Consider diversifying suppliers in {category} (represents {percentage:.1f}% of total spend)")
124
+
125
+ # Supplier dependency
126
+ supplier_spend = df.groupby('Supplier')['Total_Value'].sum()
127
+ for supplier, spend in supplier_spend.items():
128
+ percentage = (spend / total_spend) * 100
129
+ if percentage > 25:
130
+ recommendations.append(f"⚠️ High dependency on {supplier} ({percentage:.1f}% of spend) - consider risk mitigation")
131
+
132
+ # Price optimization
133
+ avg_unit_prices = df.groupby('Category')['Unit_Price'].mean()
134
+ recommendations.append("πŸ’‘ Implement category-specific negotiation strategies for cost optimization")
135
+
136
+ return recommendations[:5]
137
+
138
+ def _generate_supplier_recommendations(self, supplier_metrics: pd.DataFrame) -> List[str]:
139
+ """Generate supplier performance recommendations"""
140
+ recommendations = []
141
+
142
+ # Performance-based recommendations
143
+ poor_performers = supplier_metrics[supplier_metrics['Delivery_Performance'] < 90]
144
+ if not poor_performers.empty:
145
+ recommendations.append(f"πŸ“ˆ Develop improvement plans for {len(poor_performers)} underperforming suppliers")
146
+
147
+ # Volume-based recommendations
148
+ high_volume_suppliers = supplier_metrics[supplier_metrics['PO_Number'] > supplier_metrics['PO_Number'].quantile(0.8)]
149
+ recommendations.append(f"🀝 Consider strategic partnerships with top {len(high_volume_suppliers)} high-volume suppliers")
150
+
151
+ recommendations.append("πŸ” Implement regular supplier audits and performance reviews")
152
+ recommendations.append("πŸ“Š Set up automated alerts for delivery performance degradation")
153
+
154
+ return recommendations[:4]
155
+
156
+ def generate_insights(self, po_data: pd.DataFrame, supplier_data: pd.DataFrame) -> Dict[str, Any]:
157
+ """Generate comprehensive procurement insights"""
158
+ spend_insights = self.analyze_spend_trends(po_data)
159
+ supplier_insights = self.analyze_supplier_performance(po_data)
160
+ anomalies = self.detect_anomalies(po_data)
161
+
162
+ return {
163
+ 'spend_analysis': spend_insights,
164
+ 'supplier_analysis': supplier_insights,
165
+ 'anomalies': anomalies,
166
+ 'summary': self._generate_executive_summary(spend_insights, supplier_insights, anomalies)
167
+ }
168
+
169
+ def _generate_executive_summary(self, spend_insights: Dict, supplier_insights: Dict, anomalies: List) -> str:
170
+ """Generate executive summary"""
171
+ try:
172
+ total_spend = spend_insights.get('total_spend', 0)
173
+ trend = spend_insights.get('monthly_trend', 'stable')
174
+ best_supplier = supplier_insights.get('best_performer', {}).get('name', 'N/A')
175
+ anomaly_count = len(anomalies)
176
+
177
+ summary = f"""
178
+ πŸ“Š **Procurement Analytics Summary**
179
+
180
+ β€’ Total Spend: ${total_spend:,.2f}
181
+ β€’ Spending Trend: {trend.title()}
182
+ β€’ Best Performing Supplier: {best_supplier}
183
+ β€’ Critical Issues Detected: {anomaly_count}
184
+ β€’ Overall Health: {'Good' if anomaly_count < 5 else 'Needs Attention'}
185
+ """
186
+
187
+ return summary
188
+ except:
189
+ return "πŸ“Š **Procurement Analytics Summary**\n\nData processing in progress..."