PD03 commited on
Commit
1801261
·
verified ·
1 Parent(s): 9e6d6fb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +343 -0
app.py ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import pandas as pd
4
+ import tensorflow as tf
5
+ from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
6
+ from sklearn.model_selection import train_test_split
7
+ import plotly.graph_objects as go
8
+ import plotly.express as px
9
+ from datetime import datetime, timedelta
10
+ import random
11
+ import time
12
+
13
+ class SAPARPredictor:
14
+ def __init__(self):
15
+ self.model = None
16
+ self.training_history = None
17
+ self.is_trained = False
18
+
19
+ def generate_synthetic_data(self, n_samples=1000):
20
+ """Generate synthetic SAP AR data"""
21
+ np.random.seed(42) # For reproducibility
22
+
23
+ customers = ['CUST001', 'CUST002', 'CUST003', 'CUST004', 'CUST005', 'CUST006', 'CUST007', 'CUST008']
24
+
25
+ data = []
26
+ for i in range(n_samples):
27
+ invoice_amount = np.random.uniform(1000, 51000)
28
+ customer_code = np.random.choice(customers)
29
+ days_overdue = np.random.randint(0, 120)
30
+ previous_delays = np.random.randint(0, 5)
31
+ credit_score = np.random.uniform(0, 100)
32
+ industry_risk = np.random.uniform(0, 1)
33
+ seasonality = np.sin((i % 365) * 2 * np.pi / 365)
34
+
35
+ # Create correlation between features and payment probability
36
+ payment_prob = 0.7
37
+ payment_prob -= min(days_overdue / 100, 0.4)
38
+ payment_prob -= min(previous_delays / 10, 0.3)
39
+ payment_prob += (credit_score - 50) / 200
40
+ payment_prob -= industry_risk * 0.2
41
+ payment_prob += seasonality * 0.1
42
+ payment_prob = max(0.05, min(0.95, payment_prob))
43
+
44
+ paid_on_time = 1 if np.random.random() < payment_prob else 0
45
+
46
+ data.append({
47
+ 'invoice_amount': invoice_amount / 50000, # Normalize
48
+ 'days_overdue': days_overdue / 120, # Normalize
49
+ 'previous_delays': previous_delays / 5, # Normalize
50
+ 'credit_score': credit_score / 100, # Already normalized
51
+ 'industry_risk': industry_risk,
52
+ 'seasonality': (seasonality + 1) / 2, # Normalize to 0-1
53
+ 'paid_on_time': paid_on_time
54
+ })
55
+
56
+ return pd.DataFrame(data)
57
+
58
+ def train_model(self, progress=gr.Progress()):
59
+ """Train the ML model with progress tracking"""
60
+ progress(0, desc="Generating synthetic data...")
61
+
62
+ # Generate training data
63
+ df = self.generate_synthetic_data(1000)
64
+ time.sleep(1) # Simulate data generation time
65
+
66
+ progress(0.1, desc="Preparing features and labels...")
67
+
68
+ # Prepare features and labels
69
+ feature_columns = ['invoice_amount', 'days_overdue', 'previous_delays',
70
+ 'credit_score', 'industry_risk', 'seasonality']
71
+ X = df[feature_columns].values
72
+ y = df['paid_on_time'].values
73
+
74
+ # Split data
75
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
76
+
77
+ progress(0.2, desc="Building neural network...")
78
+
79
+ # Create model
80
+ self.model = tf.keras.Sequential([
81
+ tf.keras.layers.Dense(32, activation='relu', input_shape=(6,)),
82
+ tf.keras.layers.Dropout(0.2),
83
+ tf.keras.layers.Dense(16, activation='relu'),
84
+ tf.keras.layers.Dropout(0.2),
85
+ tf.keras.layers.Dense(1, activation='sigmoid')
86
+ ])
87
+
88
+ self.model.compile(
89
+ optimizer=tf.keras.optimizers.Adam(0.001),
90
+ loss='binary_crossentropy',
91
+ metrics=['accuracy']
92
+ )
93
+
94
+ progress(0.3, desc="Training model...")
95
+
96
+ # Train model
97
+ history = self.model.fit(
98
+ X_train, y_train,
99
+ epochs=50,
100
+ batch_size=32,
101
+ validation_split=0.2,
102
+ verbose=0
103
+ )
104
+
105
+ progress(0.8, desc="Evaluating model...")
106
+
107
+ # Make predictions on test set
108
+ y_pred_proba = self.model.predict(X_test)
109
+ y_pred = (y_pred_proba > 0.5).astype(int)
110
+
111
+ # Calculate metrics
112
+ accuracy = accuracy_score(y_test, y_pred)
113
+ precision = precision_score(y_test, y_pred)
114
+ recall = recall_score(y_test, y_pred)
115
+ f1 = f1_score(y_test, y_pred)
116
+
117
+ self.training_history = history.history
118
+ self.is_trained = True
119
+
120
+ progress(1.0, desc="Training completed!")
121
+
122
+ # Create training visualization
123
+ fig = go.Figure()
124
+
125
+ epochs = list(range(1, len(history.history['accuracy']) + 1))
126
+
127
+ fig.add_trace(go.Scatter(
128
+ x=epochs,
129
+ y=history.history['accuracy'],
130
+ mode='lines+markers',
131
+ name='Training Accuracy',
132
+ line=dict(color='#007bff', width=3),
133
+ marker=dict(size=6)
134
+ ))
135
+
136
+ fig.add_trace(go.Scatter(
137
+ x=epochs,
138
+ y=history.history['val_accuracy'],
139
+ mode='lines+markers',
140
+ name='Validation Accuracy',
141
+ line=dict(color='#28a745', width=3),
142
+ marker=dict(size=6)
143
+ ))
144
+
145
+ fig.update_layout(
146
+ title='Model Training Progress',
147
+ xaxis_title='Epoch',
148
+ yaxis_title='Accuracy',
149
+ template='plotly_white',
150
+ height=400,
151
+ hovermode='x unified'
152
+ )
153
+
154
+ # Create metrics summary
155
+ metrics_text = f"""
156
+ ## 🎯 Model Performance Metrics
157
+
158
+ - **Accuracy**: {accuracy:.1%}
159
+ - **Precision**: {precision:.1%}
160
+ - **Recall**: {recall:.1%}
161
+ - **F1 Score**: {f1:.1%}
162
+
163
+ ✅ Model trained successfully on 1,000 synthetic SAP AR records!
164
+ """
165
+
166
+ return fig, metrics_text, gr.update(interactive=True)
167
+
168
+ def generate_unpaid_invoices(self):
169
+ """Generate sample unpaid invoices for prediction"""
170
+ customers = ['SAP-CUST001', 'SAP-CUST002', 'SAP-CUST003', 'SAP-CUST004', 'SAP-CUST005']
171
+
172
+ invoices = []
173
+ for i in range(15):
174
+ invoice_id = f"INV-{datetime.now().strftime('%Y%m%d')}-{i:03d}"
175
+ customer = random.choice(customers)
176
+ amount = random.randint(5000, 50000)
177
+ days_overdue = random.randint(0, 90)
178
+ previous_delays = random.randint(0, 4)
179
+ credit_score = random.randint(40, 100)
180
+
181
+ invoices.append({
182
+ 'Invoice ID': invoice_id,
183
+ 'Customer': customer,
184
+ 'Amount ($)': amount,
185
+ 'Days Overdue': days_overdue,
186
+ 'Previous Delays': previous_delays,
187
+ 'Credit Score': credit_score,
188
+ 'Industry Risk': round(random.random(), 3),
189
+ 'Seasonality': round(random.random(), 3)
190
+ })
191
+
192
+ return pd.DataFrame(invoices)
193
+
194
+ def make_predictions(self):
195
+ """Make predictions on unpaid invoices"""
196
+ if not self.is_trained:
197
+ return None, "❌ Please train the model first!"
198
+
199
+ # Generate unpaid invoices
200
+ df = self.generate_unpaid_invoices()
201
+
202
+ # Prepare features for prediction
203
+ features = []
204
+ for _, row in df.iterrows():
205
+ features.append([
206
+ row['Amount ($)'] / 50000, # Normalize
207
+ row['Days Overdue'] / 120, # Normalize
208
+ row['Previous Delays'] / 5, # Normalize
209
+ row['Credit Score'] / 100, # Normalize
210
+ row['Industry Risk'],
211
+ row['Seasonality']
212
+ ])
213
+
214
+ # Make predictions
215
+ predictions = self.model.predict(np.array(features))
216
+
217
+ # Add predictions to dataframe
218
+ df['Payment Probability'] = [f"{p[0]:.1%}" for p in predictions]
219
+ df['Prediction'] = ['✅ Will Pay' if p[0] > 0.5 else '❌ Risk of Default' for p in predictions]
220
+ df['Risk Level'] = ['🟢 Low' if p[0] > 0.7 else '🟡 Medium' if p[0] > 0.4 else '🔴 High' for p in predictions]
221
+
222
+ # Format amount column
223
+ df['Amount ($)'] = df['Amount ($)'].apply(lambda x: f"${x:,}")
224
+
225
+ # Create probability distribution chart
226
+ prob_values = [p[0] for p in predictions]
227
+
228
+ fig = go.Figure(data=[
229
+ go.Histogram(
230
+ x=prob_values,
231
+ nbinsx=20,
232
+ marker_color='rgba(0, 123, 255, 0.7)',
233
+ marker_line_color='rgba(0, 123, 255, 1)',
234
+ marker_line_width=1
235
+ )
236
+ ])
237
+
238
+ fig.update_layout(
239
+ title='Distribution of Payment Probabilities',
240
+ xaxis_title='Payment Probability',
241
+ yaxis_title='Number of Invoices',
242
+ template='plotly_white',
243
+ height=300
244
+ )
245
+
246
+ success_msg = f"🔮 Generated predictions for {len(df)} unpaid invoices!"
247
+
248
+ return df, success_msg, fig
249
+
250
+ # Initialize the predictor
251
+ predictor = SAPARPredictor()
252
+
253
+ # Create Gradio interface
254
+ with gr.Blocks(
255
+ theme=gr.themes.Soft(
256
+ primary_hue="blue",
257
+ secondary_hue="green",
258
+ neutral_hue="slate"
259
+ ),
260
+ title="SAP AR ML Prediction Demo",
261
+ css="""
262
+ .gradio-container {
263
+ max-width: 1200px !important;
264
+ }
265
+ .main-header {
266
+ text-align: center;
267
+ margin-bottom: 2rem;
268
+ }
269
+ .metric-card {
270
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
271
+ padding: 1rem;
272
+ border-radius: 10px;
273
+ color: white;
274
+ text-align: center;
275
+ }
276
+ """
277
+ ) as demo:
278
+
279
+ gr.HTML("""
280
+ <div class="main-header">
281
+ <h1>🏢 SAP Account Receivable ML Prediction Demo</h1>
282
+ <p style="font-size: 1.1rem; color: #666;">
283
+ Machine Learning-powered invoice payment prediction system using TensorFlow
284
+ </p>
285
+ </div>
286
+ """)
287
+
288
+ with gr.Tabs() as tabs:
289
+
290
+ with gr.Tab("🎯 Model Training", id=0):
291
+ gr.Markdown("""
292
+ ### Train ML Model
293
+ Train a neural network on synthetic SAP AR data to predict invoice payment likelihood.
294
+ The model uses features like invoice amount, days overdue, customer credit score, and more.
295
+ """)
296
+
297
+ with gr.Row():
298
+ with gr.Column(scale=1):
299
+ train_btn = gr.Button(
300
+ "🚀 Train ML Model",
301
+ variant="primary",
302
+ size="lg"
303
+ )
304
+
305
+ with gr.Column(scale=2):
306
+ metrics_display = gr.Markdown("")
307
+
308
+ training_plot = gr.Plot(label="Training Progress")
309
+ predict_btn = gr.Button(
310
+ "🔮 Make Predictions",
311
+ variant="secondary",
312
+ interactive=False,
313
+ size="lg"
314
+ )
315
+
316
+ with gr.Tab("📊 Predictions", id=1):
317
+ gr.Markdown("""
318
+ ### Invoice Payment Predictions
319
+ View real-time predictions for unpaid invoices using the trained ML model.
320
+ """)
321
+
322
+ prediction_status = gr.Markdown("")
323
+ predictions_df = gr.Dataframe(
324
+ label="Invoice Predictions",
325
+ interactive=False,
326
+ wrap=True
327
+ )
328
+ probability_plot = gr.Plot(label="Probability Distribution")
329
+
330
+ # Event handlers
331
+ train_btn.click(
332
+ fn=predictor.train_model,
333
+ outputs=[training_plot, metrics_display, predict_btn]
334
+ )
335
+
336
+ predict_btn.click(
337
+ fn=predictor.make_predictions,
338
+ outputs=[predictions_df, prediction_status, probability_plot]
339
+ )
340
+
341
+ # Launch the app
342
+ if __name__ == "__main__":
343
+ demo.launch()