File size: 15,879 Bytes
e0e93c4
50f19fa
044dd38
ecaa1ea
bec7fe8
ecaa1ea
 
ea19e17
ecaa1ea
044dd38
80b9501
 
044dd38
ea19e17
564f119
f4c03fc
ea19e17
e0e93c4
044dd38
 
 
 
 
 
 
 
f4c03fc
044dd38
564f119
f4c03fc
044dd38
7432d34
564f119
f4c03fc
 
 
564f119
f4c03fc
 
 
 
044dd38
7432d34
564f119
f4c03fc
564f119
f4c03fc
 
 
 
 
 
044dd38
f4c03fc
564f119
f4c03fc
564f119
f4c03fc
 
 
 
564f119
 
 
 
 
 
 
 
 
 
 
 
947c3f0
564f119
 
 
 
 
 
 
 
 
 
ea19e17
80b9501
 
 
 
 
 
 
 
 
94ce651
044dd38
 
 
ecaa1ea
bec7fe8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ecaa1ea
 
 
 
bec7fe8
 
 
ecaa1ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4c03fc
 
ecaa1ea
 
 
649c4c8
 
 
 
ecaa1ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80b9501
50f19fa
ea19e17
 
 
044dd38
 
80b9501
 
044dd38
ecaa1ea
f4c03fc
80b9501
f4c03fc
 
80b9501
ecaa1ea
044dd38
 
 
73d3fc4
2d9906b
80b9501
50f19fa
ecaa1ea
 
80b9501
b3b6d77
2d9906b
80b9501
50f19fa
ecaa1ea
 
80b9501
73d3fc4
80b9501
 
ea19e17
80b9501
f4c03fc
ea19e17
 
f4c03fc
 
ea19e17
 
 
564f119
044dd38
ecaa1ea
ea19e17
 
 
564f119
044dd38
ecaa1ea
ea19e17
044dd38
 
 
564f119
 
 
 
044dd38
ea19e17
564f119
50f19fa
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import gradio as gr
import models
import pandas as pd
from gradio.themes.base import Base
from gradio.themes.utils.colors import Color
from gradio.themes.utils import colors, fonts, sizes
from typing import Iterable
    
text = "<h1 style='text-align: center; color: #f0ba2d; font-size: 40px;'>TCO Comparison Calculator"
text0 = "<h1 style='text-align: center; color: midnightblue; font-size: 30px;'>Describe your use case"
text1 = "<h1 style='text-align: center; color: midnightblue; font-size: 25px;'>First option"
text2 = "<h1 style='text-align: center; color: midnightblue; font-size: 25px;'>Second option"
text3 = "<h1 style='text-align: center; color: midnightblue; font-size: 30px;'>Compute and compare TCOs"
description=f"""
<p>In this demo application, we help you compare different AI model services, such as Open source or SaaS solutions, based on the Total Cost of Ownership for their deployment. Please note that we focus on getting the service up and running, but not the maintenance that follows.</p>
<p>First, you'll have to select your use case. Then, select the two model service options you'd like to compare. Depending on the options you chose, you could be able to customize some parameters of the set-up. Eventually, we will provide you with the cost of deployment for the selected model services, as a function of the number of requests. You can compare both solutions to evaluate which one best suits your needs.</p>
"""

def on_use_case_change(use_case):
    if use_case == "Summarize":
        return gr.update(value=500), gr.update(value=200)
    elif use_case == "Question-Answering":
        return gr.update(value=300), gr.update(value=300)
    else:
        return gr.update(value=50), gr.update(value=10)
    
def compare(tco1, tco2, labor_cost1, labor_cost2, dropdown, dropdown2):
    r = tco1 / tco2
    comparison_result3 = ""
    
    if r < 1:
        comparison_result = f"The cost/request of the second {dropdown2} service is {1/r:.5f} times more expensive than the one of the first {dropdown} service."
        if labor_cost1 > labor_cost2:
            comparison_result2 = f"However, it will cost a lot more to deploy the set-up for the {dropdown} service because the labor cost per month is of ${labor_cost1}, compared to a labor cost per month of ${labor_cost2} for the {dropdown2} solution."
            meeting_point = (labor_cost2 - labor_cost1) / (tco1 - tco2)
            comparison_result3 = f"The number of requests you need to achieve in a month to have the labor cost of the {dropdown} service be absorbed and both solution TCOs be equal would be of {meeting_point:.0f}."
        elif labor_cost1 < labor_cost2:
            comparison_result2 = f"Additionally, it will cost a lot more to deploy the set-up for the {dropdown2} service because the labor cost per month is of ${labor_cost2}, compared to a labor cost per month of ${labor_cost1} for the {dropdown} solution."
        else: 
            comparison_result2 = f"Additionally, both services have the same labor cost per month."
    
    elif r > 1:
        comparison_result = f"The cost/request of the second {dropdown2} service is {r:.5f} times cheaper than the one of the first {dropdown} service."
        if labor_cost1 > labor_cost2:
            comparison_result2 = f"Additionally, it will cost a lot more to deploy the set-up for the {dropdown} service because the labor cost per month is of ${labor_cost1}, compared to a labor cost per month of ${labor_cost2} for the {dropdown2} solution."
        elif labor_cost1 < labor_cost2:
            comparison_result2 = f"However, it will cost a lot more to deploy the set-up for the {dropdown2} service because the labor cost per month is of ${labor_cost2}, compared to a labor cost per month of ${labor_cost1} for the {dropdown} solution."
            meeting_point = (labor_cost2 - labor_cost1) / (tco1 - tco2)
            comparison_result3 = f"The number of requests you need to achieve in a month to have the labor cost of the {dropdown2} service be absorbed and both solution TCOs be equal would be of {meeting_point:.0f}."
        else: 
            comparison_result2 = f"Additionally, both services have the same labor cost per month."
    
    else:
        comparison_result = f"Both solutions have the same cost/request." 
        if labor_cost1 > labor_cost2:
            comparison_result2 = f"However, it will cost a lot more to deploy the set-up for the {dropdown} service because the labor cost per month is of ${labor_cost1}, compared to a labor cost per month of ${labor_cost2} for the {dropdown2} solution."
        elif labor_cost1 < 1:
            comparison_result2 = f"However, it will cost a lot more to deploy the set-up for the {dropdown2} service because the labor cost per month is of ${labor_cost2}, compared to a labor cost per month of ${labor_cost1} for the {dropdown} solution."
        else: 
            comparison_result2 = f"Additionally, both services have the same labor cost per month."
    
    #return comparison_result + "\n" + "\n" + comparison_result2 + "\n" + "\n" + comparison_result3
    return gr.update(value=comparison_result), comparison_result3

def create_table(tco1, tco2, labor_cost1, labor_cost2, dropdown, dropdown2):
    list_values = []
    labor_cost1 = round(labor_cost1, 1)
    labor_cost2 = round(labor_cost2, 1)
    first_sol = [tco1, labor_cost1]
    second_sol = [tco2, labor_cost2]
    list_values.append(first_sol)
    list_values.append(second_sol)

    data = pd.DataFrame(list_values, index=["1)" + " " + dropdown, "2)" + " " + dropdown2], columns=["Cost/request ($) ", "Labor Cost ($/month)"])
    
    formatted_data = data.copy()
    formatted_data["Cost/request ($) "] = formatted_data["Cost/request ($) "].apply('{:.5f}'.format)
    formatted_data["Labor Cost ($/month)"] = formatted_data["Labor Cost ($/month)"].apply('{:.1f}'.format)

    styled_data = formatted_data.style\
        .set_properties(**{'background-color': '#050f19', 'color': '#ffffff', 'border-color': '#ffffff', 'border-width': '1px', 'border-style': 'solid'})\
        .to_html()
        
    return gr.update(value=styled_data)

def update_plot(tco1, tco2, dropdown, dropdown2, labour_cost1, labour_cost2):
    
    request_ranges = [100, 200, 300, 400, 500, 1000, 10000]
    costs_tco1 = [(tco1 * req + labour_cost1) for req in request_ranges]
    costs_tco2 = [(tco2 * req + labour_cost2) for req in request_ranges]

    data = pd.DataFrame({
        "Number of requests": request_ranges * 2,
        "Cost ($)": costs_tco1 + costs_tco2,
        "AI model service": ["1)" + " " + dropdown] * len(request_ranges) + ["2)" + " " + dropdown2] * len(request_ranges)
        }
    )
    return gr.LinePlot.update(data, x="Number of requests", y="Cost ($)",color="AI model service",color_legend_position="bottom", title="Total Cost of Model Serving for one month", height=300, width=500, tooltip=["Number of requests", "Cost ($)", "AI model service"])

light_grey = Color(
    name="light_grey",
    c50="#e0e0e0",
    c100="#e0e0e0",
    c200="#e0e0e0",
    c300="#e0e0e0",
    c400="#e0e0e0",
    c500="#e0e0e0",
    c600="#e0e0e0",
    c700="#e0e0e0",
    c800="#e0e0e0",
    c900="#e0e0e0",
    c950="#e0e0e0",
)

class Style(Base):
    def __init__(
        self,
        *,
        primary_hue: colors.Color | str = light_grey,
        secondary_hue: colors.Color | str = light_grey,
        neutral_hue: colors.Color | str = light_grey,
        spacing_size: sizes.Size | str = sizes.spacing_md,
        radius_size: sizes.Size | str = sizes.radius_md,
        text_size: sizes.Size | str = sizes.text_md,
        font: fonts.Font
        | str
        | Iterable[fonts.Font | str] = (fonts.GoogleFont("Sora")),
        font_mono: fonts.Font
        | str
        | Iterable[fonts.Font | str] = (fonts.GoogleFont("Sora")),
    ):
        super().__init__(
            primary_hue=primary_hue,
            secondary_hue=secondary_hue,
            neutral_hue=neutral_hue,
            spacing_size=spacing_size,
            radius_size=radius_size,
            text_size=text_size,
            font=font,
            font_mono=font_mono,
        )
        super().set(
            background_fill_primary="#050f19", #The color of the background of blocks
            background_fill_secondary="#050f19",
            block_background_fill="#050f19", #The color of the background of blocks
            block_background_fill_dark="#050f19",
            
            border_color_primary="#050f19", #The border of a block such as dropdown 
            border_color_primary_dark="#050f19",
            
            link_text_color="#f0ba2d", #The color for links
            link_text_color_dark="#f0ba2d",
            
            block_info_text_color="ffffff",
            block_info_text_color_dark="ffffff",
            
            block_border_color="#050f19", #The border color around an item (e.g. Accordion)
            block_border_color_dark="#050f19",
            block_shadow="*shadow_drop_lg",
            #form_gap_width="*spacing_md", #The border gap between form elements, (e.g. consecutive textboxes)
            
            input_background_fill="#081527", #The background of an input field
            input_background_fill_dark="#081527", 
            input_border_color="#050f19",
            input_border_color_dark="#050f19",
            input_border_width="2px", 
            
            block_label_background_fill="#f0ba2d",
            block_label_background_fill_dark="#f0ba2d",
            block_label_border_color=None,
            block_label_border_color_dark=None,
            block_label_text_color="#050f19",
            block_label_text_color_dark="#050f19",
            
            button_primary_background_fill="#ffffff",
            button_primary_border_color="#ffffff",
            button_primary_text_color="#050f19",
            button_shadow="*shadow_drop_lg",
            
            block_title_background_fill="#f0ba2d", #The background of the title of a form element (e.g. textbox).
            block_title_background_fill_dark="#f0ba2d", 
            block_title_radius="*radius_sm",#The corner radius of the title of a form element (e.g. textbox).
            block_title_text_color="#050f19", #The text color of the title of a form element (e.g. textbox).
            block_title_text_color_dark="#050f19",
            block_title_text_size="*text_lg",
            block_title_border_width="2px", #The border around the title of a form element (e.g. textbox)
            block_title_border_width_dark="2px",
            block_title_border_color="#f0ba2d",
            block_title_border_color_dark="#f0ba2d",
            
            body_background_fill="#050f19",
            body_background_fill_dark="#050f19",
            body_text_color="#ffffff", #The default text color.
            body_text_color_dark="#ffffff",
            body_text_color_subdued="#ffffff",
            body_text_color_subdued_dark="#ffffff",
            
            slider_color="*secondary_300",
            slider_color_dark="*secondary_600",
        )

style = Style()

with gr.Blocks(theme=style) as demo:
    Models: list[models.BaseTCOModel] = [models.OpenAIModel, models.CohereModel, models.OpenSourceLlama2Model]
    model_names = [Model().get_name() for Model in Models]
    gr.Markdown(value=text)
    gr.Markdown(value=description)
    
    with gr.Row():
        with gr.Column():
            # with gr.Row():
            #     gr.Markdown(value=text0)
            with gr.Row():
                use_case = gr.Dropdown(["Summarize", "Question-Answering", "Classification"], value="Question-Answering", label=" Describe your use case ")
            with gr.Accordion("Click here if you want to customize the number of input and output tokens per request", open=False):    
                with gr.Row():
                    input_tokens = gr.Slider(minimum=1, maximum=1000, value=300, step=1, label=" Input tokens per request", info="We suggest a value that we believe best suit your use case choice but feel free to adjust", interactive=True)
                    output_tokens = gr.Slider(minimum=1, maximum=1000, value=300, step=1, label=" Output tokens per request", info="We suggest a value that we believe best suit your use case choice but feel free to adjust", interactive=True)
                with gr.Row(visible=False):    
                    num_users = gr.Number(value="1000", interactive = True, label=" Number of users for your service ")
    
    use_case.change(on_use_case_change, inputs=use_case, outputs=[input_tokens, output_tokens])
    
    with gr.Row():
        with gr.Column():
            #gr.Markdown(value=text1)
            page1 = models.ModelPage(Models)
            dropdown = gr.Dropdown(model_names, interactive=True, label=" First AI service option ")
            with gr.Accordion("Click here for more information on the computation parameters for your first AI service option", open=False):    
                page1.render()

        with gr.Column():
            #gr.Markdown(value=text2)
            page2 = models.ModelPage(Models)
            dropdown2 = gr.Dropdown(model_names, interactive=True, label=" Second AI service option ")
            with gr.Accordion("Click here for more information on the computation parameters for your second AI service option", open=False):        
                page2.render()
            
    dropdown.change(page1.make_model_visible, inputs=[dropdown, use_case], outputs=page1.get_all_components())
    dropdown2.change(page2.make_model_visible, inputs=[dropdown2, use_case], outputs=page2.get_all_components())
    
    #gr.Markdown(value=text3)
    compute_tco_btn = gr.Button("Compute & Compare", size="lg", variant="primary", scale=1) 
    tco1 = gr.State()
    tco2 = gr.State()
    labor_cost1 = gr.State()
    labor_cost2 = gr.State()
    
    with gr.Row():  
        with gr.Column():
            tco_output = gr.Text("Cost/request 1: ", label=" Cost/request for the first option ", info="This is only the infrastructure cost per request for deployment, the labor cost still has to be added for the AI model service deployment TCO.")
            latency_info = gr.Markdown()
            with gr.Accordion("Click here to see the formula", open=False):
                tco_formula = gr.Markdown()
    
        with gr.Column():
            tco_output2 = gr.Text("Cost/request 2: ", label=" Cost/request for the second option ", info="This is only the infrastructure cost per request for deployment, the labor cost still has to be added for the AI model service deployment TCO.")
            latency_info2 = gr.Markdown()
            with gr.Accordion("Click here to see the formula", open=False):
                tco_formula2 = gr.Markdown()
                
    with gr.Row(): 
        with gr.Column(scale=1): 
            info = gr.Text("Click on Compute & Compare to get the results", label=" Comparison of cost/request and TCOs")
            table = gr.Markdown()
            ratio = gr.Markdown()
        with gr.Column(scale=2):
            plot = gr.LinePlot()
    
    compute_tco_btn.click(page1.compute_cost_per_token, inputs=page1.get_all_components_for_cost_computing() + [dropdown, input_tokens, output_tokens], outputs=[tco_output, tco1, tco_formula, latency_info, labor_cost1]).then(page2.compute_cost_per_token, inputs=page2.get_all_components_for_cost_computing() + [dropdown2, input_tokens, output_tokens], outputs=[tco_output2, tco2, tco_formula2, latency_info2, labor_cost2]).then(create_table, inputs=[tco1, tco2, labor_cost1, labor_cost2, dropdown, dropdown2], outputs=table).then(compare, inputs=[tco1, tco2, labor_cost1, labor_cost2, dropdown, dropdown2], outputs=[info, ratio]).then(update_plot, inputs=[tco1, tco2, dropdown, dropdown2, labor_cost1, labor_cost2], outputs=plot)

demo.launch(debug=True)