arvnoodle commited on
Commit
0236623
·
verified ·
1 Parent(s): f07f33d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -0
app.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import plotly.graph_objects as go
3
+ import pandas as pd
4
+ import numpy as np
5
+
6
+ def calculate_runpod_cost(
7
+ requests_per_hour,
8
+ execution_time_per_request,
9
+ active_cost_per_second,
10
+ flex_cost_per_second,
11
+ cold_start_penalty=30,
12
+ active_request_percentage=0.5
13
+ ):
14
+ # Calculate monthly requests
15
+ monthly_requests = requests_per_hour * 24 * 30
16
+
17
+ # Split requests between active and flex workers
18
+ active_requests = monthly_requests * active_request_percentage
19
+ flex_requests = monthly_requests * (1 - active_request_percentage)
20
+
21
+ # Calculate active worker cost
22
+ active_cost = active_requests * execution_time_per_request * active_cost_per_second
23
+
24
+ # Calculate flex worker cost (including cold start penalty)
25
+ flex_cost = flex_requests * (execution_time_per_request + cold_start_penalty) * flex_cost_per_second
26
+
27
+ # Total monthly cost
28
+ total_monthly_cost = active_cost + flex_cost
29
+
30
+ return {
31
+ "monthly_requests": monthly_requests,
32
+ "active_requests": active_requests,
33
+ "flex_requests": flex_requests,
34
+ "active_cost": active_cost,
35
+ "flex_cost": flex_cost,
36
+ "total_monthly_cost": total_monthly_cost
37
+ }
38
+
39
+ def generate_cost_projection(
40
+ min_requests,
41
+ max_requests,
42
+ execution_time,
43
+ active_cost,
44
+ flex_cost,
45
+ active_percentage,
46
+ cold_start
47
+ ):
48
+ # Generate data for different request volumes
49
+ request_volumes = np.linspace(min_requests, max_requests, 20)
50
+ results = []
51
+
52
+ for req_vol in request_volumes:
53
+ result = calculate_runpod_cost(
54
+ req_vol,
55
+ execution_time,
56
+ active_cost,
57
+ flex_cost,
58
+ cold_start,
59
+ active_percentage/100
60
+ )
61
+ results.append({
62
+ 'requests_per_hour': req_vol,
63
+ 'monthly_requests': result['monthly_requests'],
64
+ 'active_cost': result['active_cost'],
65
+ 'flex_cost': result['flex_cost'],
66
+ 'total_cost': result['total_monthly_cost']
67
+ })
68
+
69
+ df = pd.DataFrame(results)
70
+
71
+ # Create plotly figure
72
+ fig = go.Figure()
73
+ fig.add_trace(go.Scatter(
74
+ x=df['requests_per_hour'],
75
+ y=df['active_cost'],
76
+ name='Active Worker Cost',
77
+ line=dict(color='blue')
78
+ ))
79
+ fig.add_trace(go.Scatter(
80
+ x=df['requests_per_hour'],
81
+ y=df['flex_cost'],
82
+ name='Flex Worker Cost',
83
+ line=dict(color='orange')
84
+ ))
85
+ fig.add_trace(go.Scatter(
86
+ x=df['requests_per_hour'],
87
+ y=df['total_cost'],
88
+ name='Total Cost',
89
+ line=dict(color='green', width=3)
90
+ ))
91
+
92
+ fig.update_layout(
93
+ title='RunPod Serverless Monthly Cost Projection',
94
+ xaxis_title='Requests per Hour',
95
+ yaxis_title='Monthly Cost ($)',
96
+ hovermode='x unified'
97
+ )
98
+
99
+ return fig
100
+
101
+ def calculate_specific_cost(
102
+ requests,
103
+ execution_time,
104
+ active_cost,
105
+ flex_cost,
106
+ active_percentage,
107
+ cold_start
108
+ ):
109
+ result = calculate_runpod_cost(
110
+ requests,
111
+ execution_time,
112
+ active_cost,
113
+ flex_cost,
114
+ cold_start,
115
+ active_percentage/100
116
+ )
117
+
118
+ # Format the output HTML for the table
119
+ html = f"""
120
+ <table style="width:100%; border-collapse: collapse;">
121
+ <tr style="background-color: #f2f2f2;">
122
+ <th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Metric</th>
123
+ <th style="padding: 12px; text-align: right; border: 1px solid #ddd;">Value</th>
124
+ </tr>
125
+ <tr>
126
+ <td style="padding: 8px; border: 1px solid #ddd;">Monthly Requests</td>
127
+ <td style="padding: 8px; text-align: right; border: 1px solid #ddd;">{result['monthly_requests']:,.0f}</td>
128
+ </tr>
129
+ <tr>
130
+ <td style="padding: 8px; border: 1px solid #ddd;">Active Worker Cost</td>
131
+ <td style="padding: 8px; text-align: right; border: 1px solid #ddd;">${result['active_cost']:,.2f}</td>
132
+ </tr>
133
+ <tr>
134
+ <td style="padding: 8px; border: 1px solid #ddd;">Flex Worker Cost</td>
135
+ <td style="padding: 8px; text-align: right; border: 1px solid #ddd;">${result['flex_cost']:,.2f}</td>
136
+ </tr>
137
+ <tr style="font-weight: bold;">
138
+ <td style="padding: 8px; border: 1px solid #ddd;">Total Monthly Cost</td>
139
+ <td style="padding: 8px; text-align: right; border: 1px solid #ddd;">${result['total_monthly_cost']:,.2f}</td>
140
+ </tr>
141
+ </table>
142
+ """
143
+
144
+ return html
145
+
146
+ theme = gr.themes.Default(
147
+ primary_hue=gr.themes.colors.red,
148
+ secondary_hue=gr.themes.colors.red,
149
+ neutral_hue=gr.themes.colors.slate,
150
+ )
151
+
152
+ # Create Gradio interface
153
+ with gr.Blocks(title="RunPod Serverless Cost Estimator", theme=theme) as demo:
154
+ gr.Markdown("# RunPod Serverless Cost Estimator")
155
+ gr.Markdown("Estimate your monthly RunPod Serverless costs based on request volume and execution time")
156
+
157
+ with gr.Row():
158
+ with gr.Column(scale=1):
159
+ min_requests = gr.Slider(minimum=100, maximum=50000, value=1000, step=1000, label="Minimum Requests/Hour")
160
+ max_requests = gr.Slider(minimum=1000, maximum=100000, value=20000, step=1000, label="Maximum Requests/Hour")
161
+ execution_time = gr.Slider(minimum=1, maximum=120, value=30, step=1, label="Execution Time per Request (seconds)")
162
+ active_cost = gr.Number(value=0.00019, label="Active Worker Cost ($/second)", precision=5)
163
+ flex_cost = gr.Number(value=0.00031, label="Flex Worker Cost ($/second)", precision=5)
164
+ active_percentage = gr.Slider(minimum=0, maximum=100, value=50, step=1, label="% Requests on Active Workers")
165
+ cold_start = gr.Slider(minimum=0, maximum=60, value=30, step=1, label="Cold Start Penalty (seconds)")
166
+
167
+ plot_button = gr.Button("Generate Cost Projection")
168
+
169
+ with gr.Column(scale=2):
170
+ plot_output = gr.Plot(label="Cost Projection")
171
+
172
+ gr.Markdown("## Cost Breakdown for Specific Request Volume")
173
+
174
+ with gr.Row():
175
+ with gr.Column(scale=1):
176
+ specific_requests = gr.Number(value=10000, label="Requests per Hour", precision=0)
177
+ calc_button = gr.Button("Calculate Cost")
178
+
179
+ with gr.Column(scale=2):
180
+ cost_table = gr.HTML()
181
+
182
+ plot_button.click(
183
+ generate_cost_projection,
184
+ inputs=[min_requests, max_requests, execution_time, active_cost, flex_cost, active_percentage, cold_start],
185
+ outputs=plot_output
186
+ )
187
+
188
+ calc_button.click(
189
+ calculate_specific_cost,
190
+ inputs=[specific_requests, execution_time, active_cost, flex_cost, active_percentage, cold_start],
191
+ outputs=cost_table
192
+ )
193
+
194
+ # Launch the app
195
+ if __name__ == "__main__":
196
+ demo.launch()