delightfulrachel commited on
Commit
f834afc
·
verified ·
1 Parent(s): c1df871

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -35
app.py CHANGED
@@ -4,16 +4,44 @@ import numpy as np
4
  import plotly.express as px
5
  import plotly.graph_objects as go
6
 
7
- # Pricing data
8
- # Only matching T4-based instances for fair comparison:
9
  aws_instances = {
10
- "g4dn.xlarge": {"vcpus": 4, "memory": 16, "gpu": "1x NVIDIA T4", "hourly_rate": 0.526, "gpu_memory": "16GB"},
11
- "g4dn.2xlarge": {"vcpus": 8, "memory": 32, "gpu": "1x NVIDIA T4", "hourly_rate": 0.752, "gpu_memory": "16GB"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
 
14
  gcp_instances = {
15
- "n1-standard-4-t4": {"vcpus": 4, "memory": 15, "gpu": "1x NVIDIA T4", "hourly_rate": 0.49, "gpu_memory": "16GB"},
16
- "n1-standard-8-t4": {"vcpus": 8, "memory": 30, "gpu": "1x NVIDIA T4", "hourly_rate": 0.69, "gpu_memory": "16GB"},
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
  api_pricing = {
@@ -69,8 +97,8 @@ def calculate_gcp_cost(instance, hours, storage, reserved=False, spot=False, yea
69
 
70
  def calculate_api_cost(provider, model, in_tokens, out_tokens, calls):
71
  m = api_pricing[provider][model]
72
- input_cost = in_tokens * m['input_per_1M']
73
- output_cost = out_tokens * m['output_per_1M']
74
  call_cost = calls * 0.0001 if provider == 'TogetherAI' else 0
75
  return {'total_cost': input_cost + output_cost + call_cost, 'details': m}
76
 
@@ -91,45 +119,53 @@ def filter_compatible(instances, min_mem):
91
 
92
  def generate_cost_comparison(
93
  compute_hours, tokens_per_month, input_ratio, api_calls,
94
- model_size, storage_gb, reserved_instances, spot_instances, multi_year_commitment
 
95
  ):
96
  years = int(multi_year_commitment)
97
- in_tokens = tokens_per_month * (input_ratio/100)
98
- out_tokens = tokens_per_month - in_tokens
99
  min_mem = model_sizes[model_size]['memory_required']
100
 
 
101
  aws_comp = filter_compatible(aws_instances, min_mem)
102
  gcp_comp = filter_compatible(gcp_instances, min_mem)
 
 
 
 
103
 
104
  results = []
105
 
106
  # AWS table
107
  aws_html = '<h3>AWS Instances</h3>'
108
- aws_html += '<table width="100%"><tr><th>Instance</th><th>vCPUs</th><th>Memory</th><th>GPU</th><th>Monthly Cost ($)</th></tr>'
109
  if aws_comp:
110
  for inst in aws_comp:
111
  res = calculate_aws_cost(inst, compute_hours, storage_gb, reserved_instances, spot_instances, years)
112
- aws_html += f'<tr><td>{inst}</td><td>{res["details"]["vcpus"]}</td><td>{res["details"]["memory"]}GB</td><td>{res["details"]["gpu"]}</td><td>${res["total_cost"]:.2f}</td></tr>'
113
  # best AWS
114
  best_aws = min(aws_comp, key=lambda x: calculate_aws_cost(x, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost'])
115
  best_aws_cost = calculate_aws_cost(best_aws, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost']
116
- results.append({'provider': f'AWS ({best_aws})', 'cost': best_aws_cost, 'type': 'Cloud'})
 
117
  else:
118
- aws_html += '<tr><td colspan="5">No compatible instances</td></tr>'
119
  aws_html += '</table>'
120
 
121
  # GCP table
122
  gcp_html = '<h3>GCP Instances</h3>'
123
- gcp_html += '<table width="100%"><tr><th>Instance</th><th>vCPUs</th><th>Memory</th><th>GPU</th><th>Monthly Cost ($)</th></tr>'
124
  if gcp_comp:
125
  for inst in gcp_comp:
126
  res = calculate_gcp_cost(inst, compute_hours, storage_gb, reserved_instances, spot_instances, years)
127
- gcp_html += f'<tr><td>{inst}</td><td>{res["details"]["vcpus"]}</td><td>{res["details"]["memory"]}GB</td><td>{res["details"]["gpu" ]}</td><td>${res["total_cost"]:.2f}</td></tr>'
128
  best_gcp = min(gcp_comp, key=lambda x: calculate_gcp_cost(x, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost'])
129
  best_gcp_cost = calculate_gcp_cost(best_gcp, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost']
130
- results.append({'provider': f'GCP ({best_gcp})', 'cost': best_gcp_cost, 'type': 'Cloud'})
 
131
  else:
132
- gcp_html += '<tr><td colspan="5">No compatible instances</td></tr>'
133
  gcp_html += '</table>'
134
 
135
  # API table
@@ -140,28 +176,71 @@ def generate_cost_comparison(
140
  for mdl in api_pricing[prov]:
141
  res = calculate_api_cost(prov, mdl, in_tokens, out_tokens, api_calls)
142
  details = api_pricing[prov][mdl]
143
- api_html += f'<tr><td>{prov}</td><td>{mdl}</td><td>${in_tokens * details["input_per_1M"]:.2f}</td><td>${out_tokens * details["output_per_1M"]:.2f}</td><td>${res["total_cost"]:.2f}</td><td>{details["token_context"]:,}</td></tr>'
144
  api_costs[(prov, mdl)] = res['total_cost']
145
  api_html += '</table>'
146
- best_api = min(api_costs, key=api_costs.get)
147
- results.append({'provider': f'{best_api[0]} ({best_api[1]})', 'cost': api_costs[best_api], 'type': 'API'})
 
 
148
 
149
- # Recommendation and Breakeven omitted for brevity
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  # Chart with annotations
152
  df = pd.DataFrame(results)
153
- colors = {r['provider']: c for r,c in zip(results, ['#FF9900','#4285F4','#D62828'])}
154
 
155
  # Create figure using plotly graph objects for more control
156
  fig = go.Figure()
157
 
158
  # Add bars
159
  for i, row in df.iterrows():
 
160
  fig.add_trace(go.Bar(
161
  x=[row['provider']],
162
  y=[row['cost']],
163
  name=row['provider'],
164
- marker_color=colors[row['provider']]
165
  ))
166
 
167
  # Add annotations on top of each bar
@@ -186,6 +265,7 @@ def generate_cost_comparison(
186
 
187
  html = f"""
188
  <div style='padding:20px;font-family:Arial;'>
 
189
  {aws_html}
190
  {gcp_html}
191
  {api_html}
@@ -204,6 +284,7 @@ with gr.Blocks(title="Cloud Cost Estimator", theme=gr.themes.Soft(primary_hue="i
204
  api_calls = gr.Slider(label="API Calls per Month", minimum=100, maximum=100000, value=5000, step=100)
205
  model_size = gr.Dropdown(label="Model Size", choices=list(model_sizes.keys()), value="Medium (13B parameters)")
206
  storage_gb = gr.Slider(label="Storage (GB)", minimum=10, maximum=1000, value=100)
 
207
  reserved_instances = gr.Checkbox(label="Reserved Instances", value=False)
208
  spot_instances = gr.Checkbox(label="Spot Instances", value=False)
209
  multi_year_commitment = gr.Radio(label="Commitment Period (years)", choices=["1","3"], value="1")
@@ -213,21 +294,14 @@ with gr.Blocks(title="Cloud Cost Estimator", theme=gr.themes.Soft(primary_hue="i
213
 
214
  # Create inputs list for the function
215
  inputs = [compute_hours, tokens_per_month, input_ratio, api_calls,
216
- model_size, storage_gb, reserved_instances, spot_instances, multi_year_commitment]
217
  outputs = [out_html, out_plot]
218
 
219
  # Initial calculation on load
220
  demo.load(generate_cost_comparison, inputs, outputs)
221
 
222
  # Update on each input change
223
- compute_hours.change(generate_cost_comparison, inputs, outputs)
224
- tokens_per_month.change(generate_cost_comparison, inputs, outputs)
225
- input_ratio.change(generate_cost_comparison, inputs, outputs)
226
- api_calls.change(generate_cost_comparison, inputs, outputs)
227
- model_size.change(generate_cost_comparison, inputs, outputs)
228
- storage_gb.change(generate_cost_comparison, inputs, outputs)
229
- reserved_instances.change(generate_cost_comparison, inputs, outputs)
230
- spot_instances.change(generate_cost_comparison, inputs, outputs)
231
- multi_year_commitment.change(generate_cost_comparison, inputs, outputs)
232
 
233
  demo.launch()
 
4
  import plotly.express as px
5
  import plotly.graph_objects as go
6
 
7
+ # Updated pricing data - restructured for better comparison
 
8
  aws_instances = {
9
+ # T4 GPU Instances (entry level)
10
+ "g4dn.xlarge": {"vcpus": 4, "memory": 16, "gpu": "1x NVIDIA T4", "hourly_rate": 0.526, "gpu_memory": "16GB", "tier": "Entry"},
11
+ "g4dn.2xlarge": {"vcpus": 8, "memory": 32, "gpu": "1x NVIDIA T4", "hourly_rate": 0.752, "gpu_memory": "16GB", "tier": "Entry"},
12
+
13
+ # A10G GPU Instances (mid-tier)
14
+ "g5.xlarge": {"vcpus": 4, "memory": 16, "gpu": "1x NVIDIA A10G", "hourly_rate": 0.65, "gpu_memory": "24GB", "tier": "Mid"},
15
+ "g5.2xlarge": {"vcpus": 8, "memory": 32, "gpu": "1x NVIDIA A10G", "hourly_rate": 1.006, "gpu_memory": "24GB", "tier": "Mid"},
16
+
17
+ # V100 GPU Instances (high-tier)
18
+ "p3.2xlarge": {"vcpus": 8, "memory": 61, "gpu": "1x NVIDIA V100", "hourly_rate": 3.06, "gpu_memory": "16GB", "tier": "High"},
19
+
20
+ # A100 GPU Instances (premium)
21
+ "p4d.24xlarge": {"vcpus": 96, "memory": 1152, "gpu": "8x NVIDIA A100", "hourly_rate": 32.77, "gpu_memory": "8x40GB", "tier": "Premium"},
22
+
23
+ # Added comparable instances to match GCP
24
+ "p4d.xlarge": {"vcpus": 12, "memory": 85, "gpu": "1x NVIDIA A100", "hourly_rate": 4.10, "gpu_memory": "40GB", "tier": "Premium"},
25
+ "p4d.2xlarge": {"vcpus": 24, "memory": 170, "gpu": "2x NVIDIA A100", "hourly_rate": 8.20, "gpu_memory": "2x40GB", "tier": "Premium"},
26
+ "p4d.4xlarge": {"vcpus": 48, "memory": 340, "gpu": "4x NVIDIA A100", "hourly_rate": 16.40, "gpu_memory": "4x40GB", "tier": "Premium"},
27
  }
28
 
29
  gcp_instances = {
30
+ # T4 GPU Instances (entry level)
31
+ "n1-standard-4-t4": {"vcpus": 4, "memory": 15, "gpu": "1x NVIDIA T4", "hourly_rate": 0.49, "gpu_memory": "16GB", "tier": "Entry"},
32
+ "n1-standard-8-t4": {"vcpus": 8, "memory": 30, "gpu": "1x NVIDIA T4", "hourly_rate": 0.69, "gpu_memory": "16GB", "tier": "Entry"},
33
+
34
+ # L4 GPU Instances (mid-tier)
35
+ "g2-standard-4": {"vcpus": 4, "memory": 16, "gpu": "1x NVIDIA L4", "hourly_rate": 0.59, "gpu_memory": "24GB", "tier": "Mid"},
36
+ "g2-standard-8": {"vcpus": 8, "memory": 32, "gpu": "1x NVIDIA L4", "hourly_rate": 0.89, "gpu_memory": "24GB", "tier": "Mid"},
37
+
38
+ # Added comparable V100 instance
39
+ "n1-standard-8-v100": {"vcpus": 8, "memory": 60, "gpu": "1x NVIDIA V100", "hourly_rate": 2.95, "gpu_memory": "16GB", "tier": "High"},
40
+
41
+ # A100 GPU Instances (premium)
42
+ "a2-highgpu-1g": {"vcpus": 12, "memory": 85, "gpu": "1x NVIDIA A100", "hourly_rate": 1.46, "gpu_memory": "40GB", "tier": "Premium"},
43
+ "a2-highgpu-2g": {"vcpus": 24, "memory": 170, "gpu": "2x NVIDIA A100", "hourly_rate": 2.93, "gpu_memory": "2x40GB", "tier": "Premium"},
44
+ "a2-highgpu-4g": {"vcpus": 48, "memory": 340, "gpu": "4x NVIDIA A100", "hourly_rate": 5.86, "gpu_memory": "4x40GB", "tier": "Premium"},
45
  }
46
 
47
  api_pricing = {
 
97
 
98
  def calculate_api_cost(provider, model, in_tokens, out_tokens, calls):
99
  m = api_pricing[provider][model]
100
+ input_cost = in_tokens * m['input_per_1M'] / 1000000
101
+ output_cost = out_tokens * m['output_per_1M'] / 1000000
102
  call_cost = calls * 0.0001 if provider == 'TogetherAI' else 0
103
  return {'total_cost': input_cost + output_cost + call_cost, 'details': m}
104
 
 
119
 
120
  def generate_cost_comparison(
121
  compute_hours, tokens_per_month, input_ratio, api_calls,
122
+ model_size, storage_gb, reserved_instances, spot_instances, multi_year_commitment,
123
+ comparison_tier
124
  ):
125
  years = int(multi_year_commitment)
126
+ in_tokens = tokens_per_month * 1000000 * (input_ratio/100)
127
+ out_tokens = tokens_per_month * 1000000 - in_tokens
128
  min_mem = model_sizes[model_size]['memory_required']
129
 
130
+ # Filter by both memory requirements and tier if a tier is selected
131
  aws_comp = filter_compatible(aws_instances, min_mem)
132
  gcp_comp = filter_compatible(gcp_instances, min_mem)
133
+
134
+ if comparison_tier != "All":
135
+ aws_comp = {k: v for k, v in aws_comp.items() if v.get('tier', '') == comparison_tier}
136
+ gcp_comp = {k: v for k, v in gcp_comp.items() if v.get('tier', '') == comparison_tier}
137
 
138
  results = []
139
 
140
  # AWS table
141
  aws_html = '<h3>AWS Instances</h3>'
142
+ aws_html += '<table width="100%"><tr><th>Instance</th><th>vCPUs</th><th>Memory</th><th>GPU</th><th>Tier</th><th>Monthly Cost ($)</th></tr>'
143
  if aws_comp:
144
  for inst in aws_comp:
145
  res = calculate_aws_cost(inst, compute_hours, storage_gb, reserved_instances, spot_instances, years)
146
+ aws_html += f'<tr><td>{inst}</td><td>{res["details"]["vcpus"]}</td><td>{res["details"]["memory"]}GB</td><td>{res["details"]["gpu"]}</td><td>{res["details"].get("tier", "")}</td><td>${res["total_cost"]:.2f}</td></tr>'
147
  # best AWS
148
  best_aws = min(aws_comp, key=lambda x: calculate_aws_cost(x, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost'])
149
  best_aws_cost = calculate_aws_cost(best_aws, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost']
150
+ best_aws_tier = aws_instances[best_aws].get('tier', '')
151
+ results.append({'provider': f'AWS ({best_aws})', 'cost': best_aws_cost, 'type': 'Cloud', 'tier': best_aws_tier})
152
  else:
153
+ aws_html += '<tr><td colspan="6">No compatible instances</td></tr>'
154
  aws_html += '</table>'
155
 
156
  # GCP table
157
  gcp_html = '<h3>GCP Instances</h3>'
158
+ gcp_html += '<table width="100%"><tr><th>Instance</th><th>vCPUs</th><th>Memory</th><th>GPU</th><th>Tier</th><th>Monthly Cost ($)</th></tr>'
159
  if gcp_comp:
160
  for inst in gcp_comp:
161
  res = calculate_gcp_cost(inst, compute_hours, storage_gb, reserved_instances, spot_instances, years)
162
+ gcp_html += f'<tr><td>{inst}</td><td>{res["details"]["vcpus"]}</td><td>{res["details"]["memory"]}GB</td><td>{res["details"]["gpu"]}</td><td>{res["details"].get("tier", "")}</td><td>${res["total_cost"]:.2f}</td></tr>'
163
  best_gcp = min(gcp_comp, key=lambda x: calculate_gcp_cost(x, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost'])
164
  best_gcp_cost = calculate_gcp_cost(best_gcp, compute_hours, storage_gb, reserved_instances, spot_instances, years)['total_cost']
165
+ best_gcp_tier = gcp_instances[best_gcp].get('tier', '')
166
+ results.append({'provider': f'GCP ({best_gcp})', 'cost': best_gcp_cost, 'type': 'Cloud', 'tier': best_gcp_tier})
167
  else:
168
+ gcp_html += '<tr><td colspan="6">No compatible instances</td></tr>'
169
  gcp_html += '</table>'
170
 
171
  # API table
 
176
  for mdl in api_pricing[prov]:
177
  res = calculate_api_cost(prov, mdl, in_tokens, out_tokens, api_calls)
178
  details = api_pricing[prov][mdl]
179
+ api_html += f'<tr><td>{prov}</td><td>{mdl}</td><td>${in_tokens * details["input_per_1M"] / 1000000:.2f}</td><td>${out_tokens * details["output_per_1M"] / 1000000:.2f}</td><td>${res["total_cost"]:.2f}</td><td>{details["token_context"]:,}</td></tr>'
180
  api_costs[(prov, mdl)] = res['total_cost']
181
  api_html += '</table>'
182
+
183
+ if api_costs:
184
+ best_api = min(api_costs, key=api_costs.get)
185
+ results.append({'provider': f'{best_api[0]} ({best_api[1]})', 'cost': api_costs[best_api], 'type': 'API', 'tier': 'API'})
186
 
187
+ # Direct comparison tables for similar instances
188
+ direct_comparison_html = ""
189
+ if comparison_tier != "All" and comparison_tier != "API":
190
+ direct_comparison_html = f'<h3>Direct {comparison_tier} Tier Comparison</h3>'
191
+ direct_comparison_html += '<table width="100%"><tr><th>Provider</th><th>Instance</th><th>vCPUs</th><th>Memory</th><th>GPU</th><th>Monthly Cost ($)</th></tr>'
192
+
193
+ aws_filtered = {k: v for k, v in aws_instances.items() if v.get('tier', '') == comparison_tier}
194
+ gcp_filtered = {k: v for k, v in gcp_instances.items() if v.get('tier', '') == comparison_tier}
195
+
196
+ # Group by vCPU for comparison
197
+ vcpu_groups = {}
198
+ for inst, data in aws_filtered.items():
199
+ vcpu = data['vcpus']
200
+ if vcpu not in vcpu_groups:
201
+ vcpu_groups[vcpu] = {'aws': [], 'gcp': []}
202
+ vcpu_groups[vcpu]['aws'].append(inst)
203
+
204
+ for inst, data in gcp_filtered.items():
205
+ vcpu = data['vcpus']
206
+ if vcpu not in vcpu_groups:
207
+ vcpu_groups[vcpu] = {'aws': [], 'gcp': []}
208
+ vcpu_groups[vcpu]['gcp'].append(inst)
209
+
210
+ # Display direct comparisons
211
+ for vcpu in sorted(vcpu_groups.keys()):
212
+ group = vcpu_groups[vcpu]
213
+ for aws_inst in group['aws']:
214
+ aws_cost = calculate_aws_cost(aws_inst, compute_hours, storage_gb, reserved_instances, spot_instances, years)
215
+ aws_data = aws_cost['details']
216
+ direct_comparison_html += f'<tr><td>AWS</td><td>{aws_inst}</td><td>{aws_data["vcpus"]}</td><td>{aws_data["memory"]}GB</td><td>{aws_data["gpu"]}</td><td>${aws_cost["total_cost"]:.2f}</td></tr>'
217
+
218
+ for gcp_inst in group['gcp']:
219
+ gcp_cost = calculate_gcp_cost(gcp_inst, compute_hours, storage_gb, reserved_instances, spot_instances, years)
220
+ gcp_data = gcp_cost['details']
221
+ direct_comparison_html += f'<tr><td>GCP</td><td>{gcp_inst}</td><td>{gcp_data["vcpus"]}</td><td>{gcp_data["memory"]}GB</td><td>{gcp_data["gpu"]}</td><td>${gcp_cost["total_cost"]:.2f}</td></tr>'
222
+
223
+ # Add separator between different vCPU groups
224
+ if vcpu != sorted(vcpu_groups.keys())[-1]:
225
+ direct_comparison_html += '<tr><td colspan="6" style="border-bottom: 1px solid #ccc; height: 10px;"></td></tr>'
226
+
227
+ direct_comparison_html += '</table>'
228
 
229
  # Chart with annotations
230
  df = pd.DataFrame(results)
231
+ colors = {'Entry': '#66BB6A', 'Mid': '#42A5F5', 'High': '#FFA726', 'Premium': '#EF5350', 'API': '#AB47BC'}
232
 
233
  # Create figure using plotly graph objects for more control
234
  fig = go.Figure()
235
 
236
  # Add bars
237
  for i, row in df.iterrows():
238
+ tier_color = colors.get(row.get('tier', 'API'), '#9E9E9E')
239
  fig.add_trace(go.Bar(
240
  x=[row['provider']],
241
  y=[row['cost']],
242
  name=row['provider'],
243
+ marker_color=tier_color
244
  ))
245
 
246
  # Add annotations on top of each bar
 
265
 
266
  html = f"""
267
  <div style='padding:20px;font-family:Arial;'>
268
+ {direct_comparison_html}
269
  {aws_html}
270
  {gcp_html}
271
  {api_html}
 
284
  api_calls = gr.Slider(label="API Calls per Month", minimum=100, maximum=100000, value=5000, step=100)
285
  model_size = gr.Dropdown(label="Model Size", choices=list(model_sizes.keys()), value="Medium (13B parameters)")
286
  storage_gb = gr.Slider(label="Storage (GB)", minimum=10, maximum=1000, value=100)
287
+ comparison_tier = gr.Radio(label="Comparison Tier", choices=["All", "Entry", "Mid", "High", "Premium", "API"], value="All")
288
  reserved_instances = gr.Checkbox(label="Reserved Instances", value=False)
289
  spot_instances = gr.Checkbox(label="Spot Instances", value=False)
290
  multi_year_commitment = gr.Radio(label="Commitment Period (years)", choices=["1","3"], value="1")
 
294
 
295
  # Create inputs list for the function
296
  inputs = [compute_hours, tokens_per_month, input_ratio, api_calls,
297
+ model_size, storage_gb, reserved_instances, spot_instances, multi_year_commitment, comparison_tier]
298
  outputs = [out_html, out_plot]
299
 
300
  # Initial calculation on load
301
  demo.load(generate_cost_comparison, inputs, outputs)
302
 
303
  # Update on each input change
304
+ for input_component in inputs:
305
+ input_component.change(generate_cost_comparison, inputs, outputs)
 
 
 
 
 
 
 
306
 
307
  demo.launch()