samuelrince commited on
Commit
c6c2a93
·
2 Parent(s): c33c8ad 200986c

Merge remote-tracking branch 'origin/main'

Browse files
app.py CHANGED
@@ -6,7 +6,6 @@ from src.content import (
6
  CITATION_LABEL,
7
  CITATION_TEXT,
8
  LICENCE_TEXT,
9
- INTRO_TEXT,
10
  METHODOLOGY_TEXT,
11
  SUPPORT_TEXT,
12
  )
@@ -15,15 +14,13 @@ from src.expert import expert_mode
15
  from src.calculator import calculator_mode
16
  from src.token_estimator import token_estimator
17
 
18
- st.set_page_config(layout="wide", page_title="ECOLOGITS", page_icon="💬")
19
 
20
  with open("src/style.css") as css:
21
  st.markdown(f"<style>{css.read()}</style>", unsafe_allow_html=True)
22
 
23
  st.html(HERO_TEXT)
24
 
25
- st.success(INTRO_TEXT, icon="🌱")
26
-
27
  tab_calculator, tab_expert, tab_token, tab_method, tab_about, tab_support = st.tabs(
28
  [
29
  "🧮 Calculator",
 
6
  CITATION_LABEL,
7
  CITATION_TEXT,
8
  LICENCE_TEXT,
 
9
  METHODOLOGY_TEXT,
10
  SUPPORT_TEXT,
11
  )
 
14
  from src.calculator import calculator_mode
15
  from src.token_estimator import token_estimator
16
 
17
+ st.set_page_config(layout="wide", page_title="EcoLogits Calculator", page_icon="🧮")
18
 
19
  with open("src/style.css") as css:
20
  st.markdown(f"<style>{css.read()}</style>", unsafe_allow_html=True)
21
 
22
  st.html(HERO_TEXT)
23
 
 
 
24
  tab_calculator, tab_expert, tab_token, tab_method, tab_about, tab_support = st.tabs(
25
  [
26
  "🧮 Calculator",
assets/logo.png ADDED
data/electricity_mix.csv DELETED
@@ -1,4 +0,0 @@
1
- name,unit,source,WOR,EEE,ZWE,ZMB,ZAF,YEM,VNM,VEN,UZB,URY,USA,UKR,TZA,TWN,TTO,TUR,TUN,TKM,TJK,THA,TGO,SYR,SLV,SEN,SVK,SVN,SGP,SWE,SDN,SAU,RUS,SCG,ROU,QAT,PRY,PRT,POL,PAK,PHL,PER,PAN,OMN,NZL,NPL,NOR,NLD,NIC,NGA,NAM,MOZ,MYS,MEX,MLT,MNG,MMR,MKD,MDA,MAR,LBY,LVA,LUX,LTU,LKA,LBN,KAZ,KWT,KOR,PRK,KHM,KGZ,KEN,JPN,JOR,JAM,ITA,ISL,IRN,IRQ,IND,ISR,IRL,IDN,HUN,HTI,HRV,HND,HKG,GTM,GRC,GIB,GHA,GEO,GBR,GAB,FRA,FIN,ETH,ESP,ERI,EGY,EST,ECU,DZA,DOM,DNK,DEU,CZE,CYP,CUB,CRI,COL,CHN,CMR,CHL,CIV,CHE,COG,COD,CAN,BLR,BWA,BRA,BOL,BRN,BEN,BHR,BGR,BEL,BGD,BIH,AZE,AUS,AUT,ARG,AGO,ANT,ARM,ALB,ARE
2
- adpe,kg éq. Sb,ADEME Base IMPACTS ®,0.0000000737708,0.0000000642317,0.000000109502,0.000000162193,0.0000000862445,0.0000000163908,0.0000000945573,0.000000112811,0.000000103681,0.000000104586,0.0000000985548,0.0000000647907,0.000000132261,0.0000000578088,0.000000064552,0.0000000749765,0.0000000177021,0.000000131822,0.000000152621,0.0000000569593,0.000000134255,0.0000000268396,0.0000000472135,0.0000000470662,0.0000000606109,0.0000000992283,0.0000000198459,0.0000000777062,0.0000000955701,0.0000000134206,0.0000000960312,0.000000132772,0.0000000981761,0.00000001324,0.000000149181,0.0000000341863,0.000000101946,0.0000000842952,0.0000000595304,0.0000000952688,0.0000000790553,0.0000000374073,0.0000000720474,0.000000238273,0.000000127486,0.0000000329318,0.0000000414983,0.0000000621,0.000000128285,0.000000148382,0.000000044938,0.0000000578358,0.000000049475,0.000000176361,0.000000152699,0.000000119873,0.000000110674,0.0000000641089,0.0000000206592,0.000000153757,0.000000105692,0.0000000294596,0.0000000986932,0.0000000182134,0.000000135386,0.0000000141168,0.0000000518017,0.000000117457,0.0000000319202,0.000000181827,0.0000000958533,0.0000000596578,0.0000000147031,0.0000000196047,0.00000005439,0.0000000781905,0.0000000220304,0.0000000404306,0.000000100099,0.0000000610194,0.0000000219257,0.0000000610451,0.0000000644587,0.0000000937057,0.000000153989,0.0000000649373,0.0000000816213,0.0000000803251,0.0000000691645,0.0000000286211,0.000000156003,0.000000137999,0.0000000370973,0.000000113843,0.0000000485798,0.0000000805114,0.000000174161,0.0000000518326,0.0000000512406,0.000000033925,0.0000000990171,0.000000127168,0.0000000216438,0.0000000429285,0.0000000157411,0.0000000878733,0.0000000817565,0.0000000448771,0.0000000299542,0.0000000863908,0.000000122031,0.0000000851552,0.000000146313,0.000000105851,0.0000000949004,0.000000100467,0.000000265575,0.000000174647,0.0000000993179,0.0000000840478,0.0000000866014,0.00000010962,0.0000000969793,0.0000000185641,0.0000000239702,0.0000000135014,0.0000000823611,0.0000000337201,0.0000000394158,0.000000148007,0.000000092567,0.0000000790846,0.000000141124,0.0000000768612,0.000000124074,0.0000000449103,0.0000000854245,0.000000229556,0.0000000141548
3
- pe,MJ,ADPf / (1-%renewable_energy),9.988,12.873,16.122,1.798,11.732,16.250,11.238,15.163,17.367,107.570,11.358,12.936,9.305,11.439,14.289,16.150,12.902,23.300,19.165,10.414,21.978,16.989,13.012,14.516,11.680,12.146,10.477,11.026,29.629,14.058,13.200,14.242,15.585,11.916,0.020,14.153,13.178,16.175,11.120,8.211,16.364,22.306,24.731,0.396,4.952,8.511,24.696,11.279,468.150,0.206,12.268,11.775,19.374,15.114,14.132,19.120,18.429,11.702,19.116,8.249,10.128,21.043,12.116,12.341,13.260,12.753,10.199,32.793,34.655,15.380,68.996,10.718,13.677,14.799,12.656,0.013,15.022,20.372,20.363,10.023,10.706,11.603,11.784,20.167,18.548,15.762,,14.340,14.487,,10.097,10.425,13.579,28.341,11.289,11.275,36.133,12.090,13.289,10.195,16.334,20.908,16.376,12.412,16.824,16.260,12.517,13.118,17.317,45.996,7.312,14.119,10.807,11.348,14.783,11.782,34.147,0.097,11.987,13.194,19.642,9.031,11.587,15.689,14.337,14.036,14.375,10.776,12.935,21.705,12.831,16.908,11.036,10.049,16.972,,13.380,0.201,19.032
4
- gwp,kg éq. CO2,ADEME Base IMPACTS ®,0.590478,0.509427,0.842811,0.0141304,1.17562,1.06777,0.555572,0.497373,0.81178,0.296953,0.67978,0.646745,0.475635,0.845351,0.933059,0.706988,0.80722,1.38296,0.0426743,0.646174,0.545455,1.08778,0.473128,1.1195,0.309341,0.498523,0.655825,0.0464664,1.12472,0.913677,0.66131,1.07808,0.664245,0.722125,0.241601,0.571172,1.15075,0.748727,0.761317,0.284364,0.53403,1.41292,0.293397,0.0841323,0.023754,0.544803,0.941626,0.693123,0.357253,0.00880732,0.832206,0.739214,1.31149,1.47192,0.48193,1.24074,1.04213,0.933694,1.35361,0.234273,0.490016,0.154229,0.709185,0.883627,1.128,0.885084,0.599585,0.797361,1.41054,0.156039,0.589603,0.540891,0.781372,1.07345,0.621329,0.0194609,0.930385,1.48728,1.58299,0.901842,0.648118,0.875394,0.541558,1.3858,0.535759,0.692837,0.95888,0.645801,1.13127,0.977477,0.540126,0.132046,0.602137,0.732511,0.0813225,0.322068,0.251299,0.467803,1.13153,0.587775,1.51492,0.627714,1.02318,0.909252,0.633534,0.657374,0.799077,0.978041,1.28325,0.224471,0.214014,1.05738,0.456622,0.574415,0.928583,0.0448568,0.904053,0.0613102,0.238191,0.795697,2.12572,0.278647,0.585131,0.997577,1.19128,0.804567,0.827087,0.256537,0.795168,1.56025,0.726126,1.12326,0.245573,0.476811,0.412014,1.13161,0.252002,0.0207635,1.09088
 
 
 
 
 
pyproject.toml CHANGED
@@ -5,9 +5,17 @@ description = "Add your description here"
5
  readme = "README.md"
6
  requires-python = ">=3.11"
7
  dependencies = [
8
- "ecologits>=0.7.3,<0.8.0",
9
  "pint>=0.24.4",
10
  "plotly>=6.2.0",
11
  "streamlit>=1.47.1",
12
  "tiktoken>=0.9.0",
13
  ]
 
 
 
 
 
 
 
 
 
5
  readme = "README.md"
6
  requires-python = ">=3.11"
7
  dependencies = [
8
+ "ecologits>=0.9.0,<0.10.0",
9
  "pint>=0.24.4",
10
  "plotly>=6.2.0",
11
  "streamlit>=1.47.1",
12
  "tiktoken>=0.9.0",
13
  ]
14
+
15
+ [tool.uv.sources]
16
+ ecologits = { git = "https://github.com/genai-impact/ecologits" }
17
+
18
+ [dependency-groups]
19
+ dev = [
20
+ "watchdog>=6.0.0",
21
+ ]
src/__init__.py CHANGED
@@ -4,6 +4,6 @@ from .expert import expert_mode
4
  from .token_estimator import token_estimator
5
  from .utils import *
6
  from .calculator import calculator_mode
7
- from .impacts import get_impacts, display_impacts
8
  from .models import load_models
9
  from .electricity_mix import *
 
4
  from .token_estimator import token_estimator
5
  from .utils import *
6
  from .calculator import calculator_mode
7
+ from .impacts import display_impacts
8
  from .models import load_models
9
  from .electricity_mix import *
src/calculator.py CHANGED
@@ -1,99 +1,111 @@
1
- import streamlit as st
2
-
3
- from ecologits.tracers.utils import llm_impacts
4
- from src.impacts import get_impacts, display_impacts, display_equivalent_ghg, display_equivalent_energy
5
- from src.utils import format_impacts
6
- from src.content import WARNING_CLOSED_SOURCE, WARNING_MULTI_MODAL, WARNING_BOTH, HOW_TO_TEXT
7
- from src.models import load_models
8
-
9
- from src.constants import PROMPTS
10
-
11
-
12
- def calculator_mode():
13
-
14
- st.expander("How to use this calculator?", expanded = False).markdown(HOW_TO_TEXT)
15
-
16
- with st.container(border=True):
17
- df = load_models(filter_main=True)
18
-
19
- col1, col2, col3 = st.columns(3)
20
-
21
- with col1:
22
- providers_clean = [x for x in df["provider_clean"].unique()]
23
- provider = st.selectbox(
24
- label="Provider",
25
- options=providers_clean,
26
- index=providers_clean.index("OpenAI"),
27
- )
28
-
29
- with col2:
30
- model = st.selectbox(
31
- label="Model",
32
- options=[
33
- x
34
- for x in df["name_clean"].unique()
35
- if x in df[df["provider_clean"] == provider]["name_clean"].unique()
36
- ],
37
- )
38
-
39
- with col3:
40
- output_tokens = st.selectbox("Example prompt", [x[0] for x in PROMPTS])
41
-
42
- # WARNING DISPLAY
43
- provider_raw = df[
44
- (df["provider_clean"] == provider) & (df["name_clean"] == model)
45
- ]["provider"].values[0]
46
- model_raw = df[
47
- (df["provider_clean"] == provider) & (df["name_clean"] == model)
48
- ]["name"].values[0]
49
-
50
- df_filtered = df[
51
- (df["provider_clean"] == provider) & (df["name_clean"] == model)
52
- ]
53
-
54
- if (
55
- df_filtered["warning_arch"].values[0]
56
- and not df_filtered["warning_multi_modal"].values[0]
57
- ):
58
- st.warning(WARNING_CLOSED_SOURCE, icon="⚠️")
59
- if (
60
- df_filtered["warning_multi_modal"].values[0]
61
- and not df_filtered["warning_arch"].values[0]
62
- ):
63
- st.warning(WARNING_MULTI_MODAL, icon="⚠️")
64
- if (
65
- df_filtered["warning_arch"].values[0]
66
- and df_filtered["warning_multi_modal"].values[0]
67
- ):
68
- st.warning(WARNING_BOTH, icon="⚠️")
69
-
70
- try:
71
- impacts = llm_impacts(
72
- provider=provider_raw,
73
- model_name=model_raw,
74
- output_token_count=[x[1] for x in PROMPTS if x[0] == output_tokens][0],
75
- request_latency=100000,
76
- )
77
-
78
- impacts, _, _ = format_impacts(impacts)
79
-
80
- with st.container(border=True):
81
-
82
- st.markdown('<h3 align = "center">Environmental impacts</h3>', unsafe_allow_html=True)
83
- #st.markdown('<p align = "center">To understand how the environmental impacts are computed go to the 📖 Methodology tab.</p>', unsafe_allow_html=True)
84
- display_impacts(impacts)
85
-
86
- with st.container(border=False):
87
- st.markdown('<h3 align = "center">Equivalences</h3>', unsafe_allow_html=True)
88
- st.markdown('<p align = "center">Making this request to the LLM is equivalent to the following actions :</p>', unsafe_allow_html=True)
89
- page = st.radio(' ', ['Energy' , 'GHG'], horizontal=True)
90
-
91
- with st.container(border=True):
92
- if page == 'Energy' :
93
- display_equivalent_energy(impacts)
94
- else :
95
- display_equivalent_ghg(impacts)
96
-
97
-
98
- except Exception as e:
99
- st.error('Could not find the model in the repository. Please try another model.')
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import streamlit as st
3
+
4
+ from ecologits.tracers.utils import llm_impacts
5
+ from src.impacts import display_impacts, display_equivalent_ghg, display_equivalent_energy
6
+ from src.latency_estimator import latency_estimator
7
+ from src.utils import format_impacts
8
+ from src.content import WARNING_CLOSED_SOURCE, WARNING_MULTI_MODAL, WARNING_BOTH, HOW_TO_TEXT
9
+ from src.models import load_models
10
+
11
+ from src.constants import PROMPTS
12
+
13
+
14
+ def calculator_mode():
15
+
16
+ st.expander("How to use this calculator?", expanded = False).markdown(HOW_TO_TEXT)
17
+
18
+ with st.container(border=True):
19
+ df = load_models(filter_main=True)
20
+
21
+ col1, col2, col3 = st.columns(3)
22
+
23
+ with col1:
24
+ providers_clean = [x for x in df["provider_clean"].unique()]
25
+ provider = st.selectbox(
26
+ label="Provider",
27
+ options=providers_clean,
28
+ index=providers_clean.index("OpenAI"),
29
+ )
30
+
31
+ with col2:
32
+ models_clean = [
33
+ x
34
+ for x in df["name_clean"].unique()
35
+ if x in df[df["provider_clean"] == provider]["name_clean"].unique()
36
+ ]
37
+ model = st.selectbox(
38
+ label="Model",
39
+ options=models_clean,
40
+ )
41
+
42
+ with col3:
43
+ output_tokens = st.selectbox(
44
+ label="Example prompt",
45
+ options=[x[0] for x in PROMPTS],
46
+ index=2
47
+ )
48
+
49
+ # WARNING DISPLAY
50
+ provider_raw = df[
51
+ (df["provider_clean"] == provider) & (df["name_clean"] == model)
52
+ ]["provider"].values[0]
53
+ model_raw = df[
54
+ (df["provider_clean"] == provider) & (df["name_clean"] == model)
55
+ ]["name"].values[0]
56
+
57
+ df_filtered = df[
58
+ (df["provider_clean"] == provider) & (df["name_clean"] == model)
59
+ ]
60
+
61
+ if (
62
+ df_filtered["warning_arch"].values[0]
63
+ and not df_filtered["warning_multi_modal"].values[0]
64
+ ):
65
+ st.warning(WARNING_CLOSED_SOURCE, icon="⚠️")
66
+ if (
67
+ df_filtered["warning_multi_modal"].values[0]
68
+ and not df_filtered["warning_arch"].values[0]
69
+ ):
70
+ st.warning(WARNING_MULTI_MODAL, icon="⚠️")
71
+ if (
72
+ df_filtered["warning_arch"].values[0]
73
+ and df_filtered["warning_multi_modal"].values[0]
74
+ ):
75
+ st.warning(WARNING_BOTH, icon="⚠️")
76
+
77
+ try:
78
+ output_tokens_count = [x[1] for x in PROMPTS if x[0] == output_tokens][0]
79
+ estimated_latency = latency_estimator.estimate(provider=provider_raw,
80
+ model_name=model_raw,
81
+ output_tokens=output_tokens_count)
82
+ impacts = llm_impacts(
83
+ provider=provider_raw,
84
+ model_name=model_raw,
85
+ output_token_count=output_tokens_count,
86
+ request_latency=estimated_latency
87
+ )
88
+
89
+ impacts, _, _ = format_impacts(impacts)
90
+
91
+ with st.container(border=True):
92
+
93
+ st.markdown('<h3 align = "center">Environmental impacts</h3>', unsafe_allow_html=True)
94
+ #st.markdown('<p align = "center">To understand how the environmental impacts are computed go to the 📖 Methodology tab.</p>', unsafe_allow_html=True)
95
+ display_impacts(impacts)
96
+
97
+ with st.container(border=False):
98
+ st.markdown('<h3 align = "center">Equivalences</h3>', unsafe_allow_html=True)
99
+ st.markdown('<p align = "center">Making this request to the LLM is equivalent to the following actions :</p>', unsafe_allow_html=True)
100
+ page = st.radio(' ', ['Energy' , 'GHG'], horizontal=True)
101
+
102
+ with st.container(border=True):
103
+ if page == 'Energy' :
104
+ display_equivalent_energy(impacts)
105
+ else :
106
+ display_equivalent_ghg(impacts)
107
+
108
+
109
+ except Exception as e:
110
+ st.error('Could not find the model in the repository. Please try another model.')
111
+ raise e
src/constants.py CHANGED
@@ -11,7 +11,6 @@ PROMPTS = [(s + f" ({v} output tokens)", v) for (s, v) in PROMPTS]
11
  MODEL_REPOSITORY_URL = "https://raw.githubusercontent.com/genai-impact/ecologits/refs/heads/main/ecologits/data/models.json"
12
 
13
  main_models_openai = [
14
- "chatgpt-4o-latest",
15
  "gpt-3.5-turbo",
16
  "gpt-4",
17
  "gpt-4-turbo",
@@ -19,93 +18,65 @@ main_models_openai = [
19
  "gpt-4o-mini",
20
  "o1",
21
  "o1-mini",
22
- ]
23
-
24
- main_models_meta = [
25
- "meta-llama/Meta-Llama-3.1-8B",
26
- "meta-llama/Meta-Llama-3.1-70B",
27
- "meta-llama/Meta-Llama-3.1-405B",
28
- "meta-llama/Meta-Llama-3-8B",
29
- "meta-llama/Meta-Llama-3-70B",
30
- "meta-llama/Meta-Llama-3-70B",
31
- "meta-llama/Llama-2-7b",
32
- "meta-llama/Llama-2-13b",
33
- "meta-llama/Llama-2-70b",
34
- "meta-llama/CodeLlama-7b-hf",
35
- "meta-llama/CodeLlama-13b-hf",
36
- "meta-llama/CodeLlama-34b-hf",
37
- "meta-llama/CodeLlama-70b-hf",
38
- ]
39
-
40
- main_models_msft = [
41
- "microsoft/phi-1",
42
- "microsoft/phi-1_5",
43
- "microsoft/Phi-3-mini-128k-instruct",
44
- "microsoft/Phi-3-small-128k-instruct",
45
- "microsoft/Phi-3-medium-128k-instruct",
46
  ]
47
 
48
  main_models_anthropic = [
49
- "claude-2.0",
50
- "claude-2.1",
51
  "claude-3-5-haiku-latest",
52
  "claude-3-5-sonnet-latest",
53
  "claude-3-7-sonnet-latest",
54
- "claude-3-haiku-20240307",
55
- "claude-3-opus-latest",
56
- "claude-3-sonnet-20240229",
 
 
57
  ]
58
 
59
  main_models_cohere = [
60
- "c4ai-aya-expanse-8b",
61
- "c4ai-aya-expanse-32b",
62
- "command",
63
- "command-light",
64
  "command-r",
65
- "command-r-plus",
 
 
66
  ]
67
 
68
  main_models_google = [
69
- "google/gemma-2-2b",
70
- "google/gemma-2-9b",
71
- "google/gemma-2-27b",
72
- "google/codegemma-2b",
73
- "google/codegemma-7b",
74
- "gemini-1.0-pro",
75
- "gemini-1.5-pro",
76
- "gemini-1.5-flash",
77
  "gemini-2.0-flash",
78
- ]
79
-
80
- main_models_databricks = [
81
- "databricks/dolly-v1-6b",
82
- "databricks/dolly-v2-12b",
83
- "databricks/dolly-v2-7b",
84
- "databricks/dolly-v2-3b",
85
- "databricks/dbrx-base",
86
  ]
87
 
88
  main_models_mistral = [
89
- "mistralai/Mistral-7B-v0.3",
90
- "mistralai/Mixtral-8x7B-v0.1",
91
- "mistralai/Mixtral-8x22B-v0.1",
92
- "mistralai/Codestral-22B-v0.1",
93
- "mistralai/Mathstral-7B-v0.1",
94
  "ministral-3b-latest",
95
  "ministral-8b-latest",
96
- "mistral-tiny",
97
- "mistral-small",
98
- "mistral-medium",
99
  "mistral-large-latest",
 
 
 
 
 
 
 
100
  ]
101
 
102
  MAIN_MODELS = (
103
- main_models_meta
104
- + main_models_openai
105
  + main_models_anthropic
106
  + main_models_cohere
107
- + main_models_msft
108
  + main_models_mistral
109
- + main_models_databricks
110
  + main_models_google
111
  )
 
11
  MODEL_REPOSITORY_URL = "https://raw.githubusercontent.com/genai-impact/ecologits/refs/heads/main/ecologits/data/models.json"
12
 
13
  main_models_openai = [
 
14
  "gpt-3.5-turbo",
15
  "gpt-4",
16
  "gpt-4-turbo",
 
18
  "gpt-4o-mini",
19
  "o1",
20
  "o1-mini",
21
+ "o3-mini",
22
+ "gpt-4.1-nano",
23
+ "gpt-4.1-mini",
24
+ "gpt-4.1",
25
+ "o4-mini",
26
+ "gpt-5-nano",
27
+ "gpt-5-mini",
28
+ "gpt-5",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  ]
30
 
31
  main_models_anthropic = [
 
 
32
  "claude-3-5-haiku-latest",
33
  "claude-3-5-sonnet-latest",
34
  "claude-3-7-sonnet-latest",
35
+ "claude-opus-4-0",
36
+ "claude-opus-4-1",
37
+ "claude-sonnet-4-0",
38
+ "claude-sonnet-4-5",
39
+ "claude-haiku-4-5"
40
  ]
41
 
42
  main_models_cohere = [
43
+ "command-a-03-2025",
 
 
 
44
  "command-r",
45
+ "command-r-08-2024",
46
+ "command-r-plus-08-2024",
47
+ "command-r7b-12-2024"
48
  ]
49
 
50
  main_models_google = [
51
+ "gemini-2.0-flash-lite",
 
 
 
 
 
 
 
52
  "gemini-2.0-flash",
53
+ "gemini-2.5-flash-lite",
54
+ "gemini-2.5-flash",
55
+ "gemini-2.5-pro"
 
 
 
 
 
56
  ]
57
 
58
  main_models_mistral = [
59
+ "codestral-latest",
60
+ "devstral-medium-latest",
61
+ "devstral-small-latest",
62
+ "magistral-medium-latest",
63
+ "magistral-small-latest",
64
  "ministral-3b-latest",
65
  "ministral-8b-latest",
 
 
 
66
  "mistral-large-latest",
67
+ "mistral-medium-latest",
68
+ "mistral-small-latest",
69
+ "mistral-tiny-latest",
70
+ "open-mistral-7b",
71
+ "open-mistral-nemo",
72
+ "open-mixtral-8x22b",
73
+ "open-mixtral-8x7b"
74
  ]
75
 
76
  MAIN_MODELS = (
77
+ main_models_openai
 
78
  + main_models_anthropic
79
  + main_models_cohere
 
80
  + main_models_mistral
 
81
  + main_models_google
82
  )
src/content.py CHANGED
@@ -1,26 +1,20 @@
1
  HERO_TEXT = """
2
- <div align="center">
3
  <a href="https://ecologits.ai/">
4
- <img style="max-height: 200px" alt="EcoLogits" src="https://raw.githubusercontent.com/genai-impact/ecologits/main/docs/assets/logo_calculator.png">
5
  </a>
6
  </div>
7
  <div align="center">
8
  <p style="max-width: 850px; text-align: left">
9
- <b>EcoLogits</b> is a python library that tracks the <b>energy consumption</b> and <b>environmental
10
- footprint</b> of using <b>generative AI</b> models through APIs.
11
- <br>
12
- This Calculator allows a broader access to <b>EcoLogits</b> estimates through a visual application.</i>
13
-
14
  </p>
15
 
16
  </div>
17
  <br>
18
  """
19
 
20
- INTRO_TEXT = """
21
- EcoLogits Calculator is developed and maintained by [GenAI Impact](https://genai-impact.org/) non-profit. To learn more about EcoLogits documentation visit [ecologits.ai](https://ecologits.ai).
22
- """
23
-
24
  HOW_TO_TEXT = """
25
  Chose a provider, a model and an example of usage (prompts).
26
 
@@ -74,7 +68,7 @@ When you're writing or interacting with an LLM, being aware of token count can h
74
  """
75
 
76
  ABOUT_TEXT = r"""
77
- ## 🎯 Our goal
78
 
79
  **The main goal of the EcoLogits Calculator is to raise awareness on the environmental impacts of LLM inference.**
80
 
@@ -83,7 +77,7 @@ The rapid evolution of generative AI is reshaping numerous industries and aspect
83
  At **[GenAI Impact](https://genai-impact.org/) we are dedicated to understanding and mitigating the environmental impacts of generative AI** through rigorous research, innovative tools, and community engagement. Especially, in early 2024 we have launched an new open-source tool called [EcoLogits](https://github.com/genai-impact/ecologits) that tracks the energy consumption and environmental footprint of using generative AI models through APIs.
84
 
85
 
86
- ## 🙋 FAQ
87
 
88
  **How we assess the impacts of closed-source models?**
89
 
@@ -115,88 +109,84 @@ To see the full list of **generative AI providers** currently supported by EcoLo
115
  EcoLogits is focused on estimating the environmental impacts of generative AI (only LLMs for now) used **through API providers (such as OpenAI, Anthropic, Cloud APIs...)** whereas CodeCarbon is more general tool to measure energy consumption and estimate GHG emissions measurement. If you deploy LLMs locally we encourage you to use CodeCarbon to get real numbers of your energy consumption.
116
 
117
 
118
- ## 🤗 Contributing
119
 
120
  We are eager to get feedback from the community, don't hesitate to engage the discussion with us on this [GitHub thread](https://github.com/genai-impact/ecologits/discussions/45) or message us on [LinkedIn](https://www.linkedin.com/company/genai-impact/).
121
 
122
  We also welcome any open-source contributions on 🌱 **[EcoLogits](https://github.com/genai-impact/ecologits)** or on 🧮 **EcoLogits Calculator**.
123
 
124
 
125
- ## ⚖️ License
126
 
127
  <p xmlns:cc="http://creativecommons.org/ns#" >
128
  This work is licensed under
129
  <a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">
130
  CC BY-SA 4.0
131
  </a>
132
- <br>
133
- <br>
134
- <img style="display:inline-block;height:5px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" height="30" width="30" alt="">
135
- <img style="display:inline-block;height:5px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" height="30" width="30" alt="">
136
- <img style="display:inline-block;height:5px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1" height="30" width="30" alt="">
137
  </p>
138
 
139
- ## 🙌 Acknowledgement
140
 
141
  We thank [Data For Good](https://dataforgood.fr/) and [Boavizta](https://boavizta.org/en) for supporting the development of this project. Their contributions of tools, best practices, and expertise in environmental impact assessment have been invaluable.
142
 
143
- We also extend our gratitude to the open-source contributions of 🤗 [Hugging Face](huggingface.com) on the LLM-Perf Leaderboard.
144
 
145
-
146
- ## 🤝 Contact
147
 
148
  For general question on the project, please use the [GitHub thread](https://github.com/genai-impact/ecologits/discussions/45).
149
  Otherwise use our contact form on [genai-impact.org/contact](https://genai-impact.org/contact/).
150
  """
151
 
152
  SUPPORT_TEXT = r"""
153
- ## How to support
154
 
155
  At GenAI Impact, our projects are powered by the passion and dedication of our team.
156
- Since its first release in June 2024, this calculator has been **developped and maintained entirely on a volunteer basis by our members**.
157
- We aim to keep this tool available as a free and open-source ressource for the common good. We need your support to reach this goal, this is how you can help.
 
 
158
 
159
- ### If you have 1 second
160
- 3 easy ways to help this project :
161
  - Give a ❤️ like to this space
162
- - Give a ⭐ to the EcoLogits repo on [GitHub](https://github.com/genai-impact/ecologits)
163
  - Follow us on [LinkedIn](https://fr.linkedin.com/company/genai-impact)
164
 
165
- ### If you have 5 minutes
 
166
  Share your feedback, ask questions, help other members of the community !
167
 
168
- Engage the discussion with us :
169
  - Start a new discussion on this space or on this
170
  [GitHub thread](https://github.com/genai-impact/ecologits/discussions/45)
171
  - Use the contact form on [GenAI Impact website](https://genai-impact.org/contact/)
172
  - message us on [LinkedIn](https://www.linkedin.com/company/genai-impact/).
173
 
174
- ### If you have more to give
 
 
175
 
176
- ##### As an individual
177
  We welcome any open source contribution ! You can :
178
  - Contribute on **[EcoLogits](https://github.com/genai-impact/ecologits)** or on
179
  **EcoLogits Calculator**.
180
  - Become a an active member of [GenAI Impact ](https://genai-impact.org/contact/) non profit. Get involved in our broader mission !
181
 
182
 
183
- ##### As an organization
 
184
  If EcoLogits Calculator brings value to your organization, customers or communities you can help finance this project.
185
  - Become a **sponsor**
186
  - Become a **benefactor member** if you are a public sector or non-profit organization or a university.
187
 
188
- Contact us on [GenAI Impact ](https://genai-impact.org/contact/)
189
-
190
  """
191
 
192
  METHODOLOGY_TEXT = r"""
193
- ## 📖 Methodology
194
 
195
  We have developed a methodology to **estimate the energy consumption and environmental impacts for an LLM inference** based on request parameters and hypotheses on the data center location, the hardware used, the model architecture and more.
196
 
197
  In this section we will only cover the principles of the methodology related to the 🧮 **EcoLogits Calculator**. If you wish to learn more on the environmental impacts modeling of an LLM request checkout the 🌱 [EcoLogits documentation page](https://ecologits.ai/methodology/).
198
 
199
- ### Modeling impacts of an LLM request
200
 
201
  The environmental impacts of an LLM inference are split into the **usage impacts** $I_{request}^u$ to account for electricity consumption and the **embodied impacts** $I_{request}^e$ that relates to resource extraction, hardware manufacturing and transportation. In general terms it can be expressed as follow:
202
 
@@ -216,8 +206,10 @@ Additionally, to ⚡️ **direct energy consumption** the environmental impacts
216
  * 🌍 **Global Warming Potential** (GWP): Potential impact on global warming in kgCO2eq (commonly known as GHG/carbon emissions).
217
  * 🪨 **Abiotic Depletion Potential for Elements** (ADPe): Impact on the depletion of non-living resources such as minerals or metals in kgSbeq.
218
  * ⛽️ **Primary Energy** (PE): Total energy consumed from primary sources in MJ.
 
 
 
219
 
220
- ### Principles, Data and Hypotheses
221
  We use a **bottom-up methodology** to model impacts, meaning that we will estimate the impacts of low-level physical components to then estimate the impacts at software level (in that case an LLM inference). We also rely on **Life Cycle Approach (LCA) proxies and approach** to model both usage and embodied phases with multi-criteria impacts. If you are interested in this approach we recommend you to read the following [Boavizta](https://boavizta.org/) resources.
222
 
223
  * [Digital & environment: How to evaluate server manufacturing footprint, beyond greenhouse gas emissions?](https://boavizta.org/en/blog/empreinte-de-la-fabrication-d-un-serveur)
@@ -225,26 +217,27 @@ We use a **bottom-up methodology** to model impacts, meaning that we will estima
225
  * [Boavizta API documentation](https://doc.api.boavizta.org/)
226
 
227
  We leverage **open data to estimate the environmental impacts**, here is an exhaustive list of our data providers.
228
- * [LLM-Perf Leaderboard](https://huggingface.co/spaces/optimum/llm-perf-leaderboard) to estimate GPU energy consumption and latency based on the model architecture and number of output tokens.
 
229
  * [Boavizta API](https://github.com/Boavizta/boaviztapi) to estimate server embodied impacts and base energy consumption.
230
- * [ADEME Base Empreinte®](https://base-empreinte.ademe.fr/) for electricity mix impacts per country.
231
 
232
  Finally here are the **main hypotheses** we have made to compute the impacts.
233
 
234
  * ⚠️ **We *"guesstimate"* the model architecture of proprietary LLMs when not disclosed by the provider.**
235
- * Production setup: quantized models running on data center grade servers and GPUs such as A100.
236
- * Electricity mix does not depend on time (help us enhance EcoLogits and work on this [issue](https://github.com/genai-impact/ecologits/issues/42))
237
  * Ignore the following impacts: unused cloud resources, data center building, network and end-user devices... (for now)
238
 
239
- ## Equivalents
240
 
241
  We have integrated impact equivalents to help people better understand the impacts and have reference points for standard use cases and everyday activities.
242
 
243
- ### Request impacts
244
 
245
  These equivalents are computed based on the request impacts only.
246
 
247
- #### 🚶‍♂️‍➡️ Walking or 🏃‍♂️‍➡️ running distance
248
 
249
  We compare the ⚡️ direct energy consumption with the energy consumption of someone 🚶‍♂️‍➡️ walking or 🏃‍♂️‍➡️ running. From [runningtools.com](https://www.runningtools.com/energyusage.htm) we consider the following energy values per physical activity (for someone weighing 70kg):
250
 
@@ -253,18 +246,19 @@ We compare the ⚡️ direct energy consumption with the energy consumption of s
253
 
254
  We divide the request energy consumption by these values to compute the distance traveled.
255
 
256
- #### 🔋 Electric Vehicle distance
 
257
  We compare the ⚡️ direct energy consumption with the energy consumer by a EV car. From [selectra.info](https://selectra.info/energie/actualites/insolite/consommation-vehicules-electriques-france-2040) or [tesla.com](https://www.tesla.com/fr_fr/support/power-consumption) we consider an average value of energy consumed per kilometer of: $ 0.17\ kWh/km $.
258
 
259
  We divide the request energy consumption by this value to compute the distance driven by an EV.
260
 
261
- #### ⏯️ Streaming time
262
 
263
  We compare the 🌍 GHG emissions of the request and of streaming a video. From [impactco2.fr](https://impactco2.fr/outils/comparateur?value=1&comparisons=streamingvideo), we consider that $ 1\ kgCO2eq $ is equivalent to $ 15.6\ h $ of streaming.
264
 
265
  We multiply that value by the GHG emissions of the request to get an equivalent in hours of video streaming.
266
 
267
- ### Scaled impacts
268
 
269
  These equivalents are computed based on the request impacts scaled to a worldwide adoption use case. We imply that the same request is done 1% of the planet everyday for 1 year, and then compute impact equivalents.
270
 
@@ -272,25 +266,25 @@ $$
272
  I_{scaled} = I_{request} * [1 \% \ \text{of}\ 8B\ \text{people on earth}] * 365\ \text{days}
273
  $$
274
 
275
- #### Number of 💨 wind turbines or ☢️ nuclear plants
276
 
277
  We compare the ⚡️ direct energy consumption (scaled) by the energy production of wind turbines and nuclear power plants. From [ecologie.gouv.fr](https://www.ecologie.gouv.fr/eolien-terrestre) we consider that a $ 2\ MW $ wind turbine produces $ 4.2\ GWh $ a year. And from [edf.fr](https://www.edf.fr/groupe-edf/espaces-dedies/jeunes-enseignants/pour-les-jeunes/lenergie-de-a-a-z/produire-de-lelectricite/le-nucleaire-en-chiffres) we learn that a $ 900\ MW $ nuclear power plant produces $ 6\ TWh $ a year.
278
 
279
  We divide the scaled energy consumption by these values to get the number of wind turbines or nuclear power plants needed.
280
 
281
- #### Multiplier of 🇮🇪 Ireland electricity consumption
282
 
283
  We compare the ⚡️ direct energy consumption (scaled) by the electricity consumption of Ireland per year. From [wikipedia.org](https://en.wikipedia.org/wiki/List_of_countries_by_electricity_consumption) we consider the Ireland electricity consumption to be $ 33\ TWh $ a year for a population of 5M.
284
 
285
  We divide the scaled energy consumption by this value to get the equivalent number of "Ireland countries".
286
 
287
- #### Number of ✈️ Paris ↔ New York City flights
288
 
289
  We compare the 🌍 GHG emissions (scaled) of the request and of a return flight Paris ↔ New York City. From [impactco2.fr](https://impactco2.fr/outils/comparateur?value=1&comparisons=&equivalent=avion-pny) we consider that a return flight Paris → New York City → Paris for one passenger emits $ 1,770\ kgCO2eq $ and we consider an overall average load of 100 passengers per flight.
290
 
291
  We divide the scaled GHG emissions by this value to get the equivalent number of return flights.
292
 
293
- #### If you are motivated to help us test and enhance this methodology [contact us](https://genai-impact.org/contact/)! 💪
294
  """
295
 
296
  CITATION_LABEL = "BibTeX citation for EcoLogits Calculator and the EcoLogits library:"
 
1
  HERO_TEXT = """
2
+ <div align="center" class="hero">
3
  <a href="https://ecologits.ai/">
4
+ <img style="max-height: 200px" alt="EcoLogits" src="https://raw.githubusercontent.com/genai-impact/ecologits-calculator/main/assets/logo.png">
5
  </a>
6
  </div>
7
  <div align="center">
8
  <p style="max-width: 850px; text-align: left">
9
+ <b><a href="https://ecologits.ai/" target="_blank">EcoLogits</a></b> is an <b>open source</b> tool for estimating the <b>energy consumption</b> and <b>environmental footprint</b> when using <b>generative AI models</b>. It is developed by the <b><a href="https://genai-impact.org/">GenAI Impact</a></b> non-profit.
10
+ <br><br>
11
+ This page is the official calculator made for everyone to explore the impact evaluation methodology and raise awareness on sustainable AI.
 
 
12
  </p>
13
 
14
  </div>
15
  <br>
16
  """
17
 
 
 
 
 
18
  HOW_TO_TEXT = """
19
  Chose a provider, a model and an example of usage (prompts).
20
 
 
68
  """
69
 
70
  ABOUT_TEXT = r"""
71
+ ### 🎯 Our goal
72
 
73
  **The main goal of the EcoLogits Calculator is to raise awareness on the environmental impacts of LLM inference.**
74
 
 
77
  At **[GenAI Impact](https://genai-impact.org/) we are dedicated to understanding and mitigating the environmental impacts of generative AI** through rigorous research, innovative tools, and community engagement. Especially, in early 2024 we have launched an new open-source tool called [EcoLogits](https://github.com/genai-impact/ecologits) that tracks the energy consumption and environmental footprint of using generative AI models through APIs.
78
 
79
 
80
+ ### 🙋 FAQ
81
 
82
  **How we assess the impacts of closed-source models?**
83
 
 
109
  EcoLogits is focused on estimating the environmental impacts of generative AI (only LLMs for now) used **through API providers (such as OpenAI, Anthropic, Cloud APIs...)** whereas CodeCarbon is more general tool to measure energy consumption and estimate GHG emissions measurement. If you deploy LLMs locally we encourage you to use CodeCarbon to get real numbers of your energy consumption.
110
 
111
 
112
+ ### 🤗 Contributing
113
 
114
  We are eager to get feedback from the community, don't hesitate to engage the discussion with us on this [GitHub thread](https://github.com/genai-impact/ecologits/discussions/45) or message us on [LinkedIn](https://www.linkedin.com/company/genai-impact/).
115
 
116
  We also welcome any open-source contributions on 🌱 **[EcoLogits](https://github.com/genai-impact/ecologits)** or on 🧮 **EcoLogits Calculator**.
117
 
118
 
119
+ ### ⚖️ License
120
 
121
  <p xmlns:cc="http://creativecommons.org/ns#" >
122
  This work is licensed under
123
  <a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">
124
  CC BY-SA 4.0
125
  </a>
 
 
 
 
 
126
  </p>
127
 
128
+ ### 🙌 Acknowledgement
129
 
130
  We thank [Data For Good](https://dataforgood.fr/) and [Boavizta](https://boavizta.org/en) for supporting the development of this project. Their contributions of tools, best practices, and expertise in environmental impact assessment have been invaluable.
131
 
 
132
 
133
+ ### 🤝 Contact
 
134
 
135
  For general question on the project, please use the [GitHub thread](https://github.com/genai-impact/ecologits/discussions/45).
136
  Otherwise use our contact form on [genai-impact.org/contact](https://genai-impact.org/contact/).
137
  """
138
 
139
  SUPPORT_TEXT = r"""
140
+ ### How to support us
141
 
142
  At GenAI Impact, our projects are powered by the passion and dedication of our team.
143
+ Since its first release in June 2024, this calculator has been **developed and maintained entirely on a volunteer basis by our members**.
144
+ We aim to keep this tool available as a free and open-source resource for the common good. We need your support to reach this goal, this is how you can help.
145
+
146
+ #### If you have 1 second
147
 
148
+ 3 easy ways to help this project:
 
149
  - Give a ❤️ like to this space
150
+ - Give a ⭐ to the EcoLogits repository on [GitHub](https://github.com/genai-impact/ecologits)
151
  - Follow us on [LinkedIn](https://fr.linkedin.com/company/genai-impact)
152
 
153
+ #### If you have 5 minutes
154
+
155
  Share your feedback, ask questions, help other members of the community !
156
 
157
+ Engage the discussion with us:
158
  - Start a new discussion on this space or on this
159
  [GitHub thread](https://github.com/genai-impact/ecologits/discussions/45)
160
  - Use the contact form on [GenAI Impact website](https://genai-impact.org/contact/)
161
  - message us on [LinkedIn](https://www.linkedin.com/company/genai-impact/).
162
 
163
+ #### If you have more to give
164
+
165
+ ###### As an individual
166
 
 
167
  We welcome any open source contribution ! You can :
168
  - Contribute on **[EcoLogits](https://github.com/genai-impact/ecologits)** or on
169
  **EcoLogits Calculator**.
170
  - Become a an active member of [GenAI Impact ](https://genai-impact.org/contact/) non profit. Get involved in our broader mission !
171
 
172
 
173
+ ###### As an organization
174
+
175
  If EcoLogits Calculator brings value to your organization, customers or communities you can help finance this project.
176
  - Become a **sponsor**
177
  - Become a **benefactor member** if you are a public sector or non-profit organization or a university.
178
 
179
+ Contact us on [GenAI Impact](https://genai-impact.org/contact/)
 
180
  """
181
 
182
  METHODOLOGY_TEXT = r"""
183
+ ### 📖 Methodology
184
 
185
  We have developed a methodology to **estimate the energy consumption and environmental impacts for an LLM inference** based on request parameters and hypotheses on the data center location, the hardware used, the model architecture and more.
186
 
187
  In this section we will only cover the principles of the methodology related to the 🧮 **EcoLogits Calculator**. If you wish to learn more on the environmental impacts modeling of an LLM request checkout the 🌱 [EcoLogits documentation page](https://ecologits.ai/methodology/).
188
 
189
+ #### Modeling impacts of an LLM request
190
 
191
  The environmental impacts of an LLM inference are split into the **usage impacts** $I_{request}^u$ to account for electricity consumption and the **embodied impacts** $I_{request}^e$ that relates to resource extraction, hardware manufacturing and transportation. In general terms it can be expressed as follow:
192
 
 
206
  * 🌍 **Global Warming Potential** (GWP): Potential impact on global warming in kgCO2eq (commonly known as GHG/carbon emissions).
207
  * 🪨 **Abiotic Depletion Potential for Elements** (ADPe): Impact on the depletion of non-living resources such as minerals or metals in kgSbeq.
208
  * ⛽️ **Primary Energy** (PE): Total energy consumed from primary sources in MJ.
209
+ * ⛽️ **Water Consumption Footprint** (WCF): Water consumed by data centers and electricity generation power plants.
210
+
211
+ #### Principles, Data and Hypotheses
212
 
 
213
  We use a **bottom-up methodology** to model impacts, meaning that we will estimate the impacts of low-level physical components to then estimate the impacts at software level (in that case an LLM inference). We also rely on **Life Cycle Approach (LCA) proxies and approach** to model both usage and embodied phases with multi-criteria impacts. If you are interested in this approach we recommend you to read the following [Boavizta](https://boavizta.org/) resources.
214
 
215
  * [Digital & environment: How to evaluate server manufacturing footprint, beyond greenhouse gas emissions?](https://boavizta.org/en/blog/empreinte-de-la-fabrication-d-un-serveur)
 
217
  * [Boavizta API documentation](https://doc.api.boavizta.org/)
218
 
219
  We leverage **open data to estimate the environmental impacts**, here is an exhaustive list of our data providers.
220
+
221
+ * [ML.ENERGY Leaderboard](https://ml.energy/leaderboard/) to estimate GPU energy consumption and latency based on the model architecture and number of output tokens.
222
  * [Boavizta API](https://github.com/Boavizta/boaviztapi) to estimate server embodied impacts and base energy consumption.
223
+ * [Our World in Data](https://ourworldindata.org/), [ADEME Base Empreinte®](https://base-empreinte.ademe.fr/) and [World Resource Institute](https://www.wri.org/) for electricity mix impacts per country.
224
 
225
  Finally here are the **main hypotheses** we have made to compute the impacts.
226
 
227
  * ⚠️ **We *"guesstimate"* the model architecture of proprietary LLMs when not disclosed by the provider.**
228
+ * Production setup: quantized models running on data center grade servers and GPUs such as H100.
229
+ * Electricity mixes are yearly averages.
230
  * Ignore the following impacts: unused cloud resources, data center building, network and end-user devices... (for now)
231
 
232
+ ### Equivalents
233
 
234
  We have integrated impact equivalents to help people better understand the impacts and have reference points for standard use cases and everyday activities.
235
 
236
+ #### Request impacts
237
 
238
  These equivalents are computed based on the request impacts only.
239
 
240
+ ##### 🚶‍♂️‍➡️ Walking or 🏃‍♂️‍➡️ running distance
241
 
242
  We compare the ⚡️ direct energy consumption with the energy consumption of someone 🚶‍♂️‍➡️ walking or 🏃‍♂️‍➡️ running. From [runningtools.com](https://www.runningtools.com/energyusage.htm) we consider the following energy values per physical activity (for someone weighing 70kg):
243
 
 
246
 
247
  We divide the request energy consumption by these values to compute the distance traveled.
248
 
249
+ ##### 🔋 Electric Vehicle distance
250
+
251
  We compare the ⚡️ direct energy consumption with the energy consumer by a EV car. From [selectra.info](https://selectra.info/energie/actualites/insolite/consommation-vehicules-electriques-france-2040) or [tesla.com](https://www.tesla.com/fr_fr/support/power-consumption) we consider an average value of energy consumed per kilometer of: $ 0.17\ kWh/km $.
252
 
253
  We divide the request energy consumption by this value to compute the distance driven by an EV.
254
 
255
+ ##### ⏯️ Streaming time
256
 
257
  We compare the 🌍 GHG emissions of the request and of streaming a video. From [impactco2.fr](https://impactco2.fr/outils/comparateur?value=1&comparisons=streamingvideo), we consider that $ 1\ kgCO2eq $ is equivalent to $ 15.6\ h $ of streaming.
258
 
259
  We multiply that value by the GHG emissions of the request to get an equivalent in hours of video streaming.
260
 
261
+ #### Scaled impacts
262
 
263
  These equivalents are computed based on the request impacts scaled to a worldwide adoption use case. We imply that the same request is done 1% of the planet everyday for 1 year, and then compute impact equivalents.
264
 
 
266
  I_{scaled} = I_{request} * [1 \% \ \text{of}\ 8B\ \text{people on earth}] * 365\ \text{days}
267
  $$
268
 
269
+ ##### Number of 💨 wind turbines or ☢️ nuclear plants
270
 
271
  We compare the ⚡️ direct energy consumption (scaled) by the energy production of wind turbines and nuclear power plants. From [ecologie.gouv.fr](https://www.ecologie.gouv.fr/eolien-terrestre) we consider that a $ 2\ MW $ wind turbine produces $ 4.2\ GWh $ a year. And from [edf.fr](https://www.edf.fr/groupe-edf/espaces-dedies/jeunes-enseignants/pour-les-jeunes/lenergie-de-a-a-z/produire-de-lelectricite/le-nucleaire-en-chiffres) we learn that a $ 900\ MW $ nuclear power plant produces $ 6\ TWh $ a year.
272
 
273
  We divide the scaled energy consumption by these values to get the number of wind turbines or nuclear power plants needed.
274
 
275
+ ##### Multiplier of 🇮🇪 Ireland electricity consumption
276
 
277
  We compare the ⚡️ direct energy consumption (scaled) by the electricity consumption of Ireland per year. From [wikipedia.org](https://en.wikipedia.org/wiki/List_of_countries_by_electricity_consumption) we consider the Ireland electricity consumption to be $ 33\ TWh $ a year for a population of 5M.
278
 
279
  We divide the scaled energy consumption by this value to get the equivalent number of "Ireland countries".
280
 
281
+ ##### Number of ✈️ Paris ↔ New York City flights
282
 
283
  We compare the 🌍 GHG emissions (scaled) of the request and of a return flight Paris ↔ New York City. From [impactco2.fr](https://impactco2.fr/outils/comparateur?value=1&comparisons=&equivalent=avion-pny) we consider that a return flight Paris → New York City → Paris for one passenger emits $ 1,770\ kgCO2eq $ and we consider an overall average load of 100 passengers per flight.
284
 
285
  We divide the scaled GHG emissions by this value to get the equivalent number of return flights.
286
 
287
+ ##### If you are motivated to help us test and enhance this methodology [contact us](https://genai-impact.org/contact/)! 💪
288
  """
289
 
290
  CITATION_LABEL = "BibTeX citation for EcoLogits Calculator and the EcoLogits library:"
src/data/electricity_mix.csv DELETED
@@ -1,4 +0,0 @@
1
- name,unit,source,WOR,EEE,ZWE,ZMB,ZAF,YEM,VNM,VEN,UZB,URY,USA,UKR,TZA,TWN,TTO,TUR,TUN,TKM,TJK,THA,TGO,SYR,SLV,SEN,SVK,SVN,SGP,SWE,SDN,SAU,RUS,SCG,ROU,QAT,PRY,PRT,POL,PAK,PHL,PER,PAN,OMN,NZL,NPL,NOR,NLD,NIC,NGA,NAM,MOZ,MYS,MEX,MLT,MNG,MMR,MKD,MDA,MAR,LBY,LVA,LUX,LTU,LKA,LBN,KAZ,KWT,KOR,PRK,KHM,KGZ,KEN,JPN,JOR,JAM,ITA,ISL,IRN,IRQ,IND,ISR,IRL,IDN,HUN,HTI,HRV,HND,HKG,GTM,GRC,GIB,GHA,GEO,GBR,GAB,FRA,FIN,ETH,ESP,ERI,EGY,EST,ECU,DZA,DOM,DNK,DEU,CZE,CYP,CUB,CRI,COL,CHN,CMR,CHL,CIV,CHE,COG,COD,CAN,BLR,BWA,BRA,BOL,BRN,BEN,BHR,BGR,BEL,BGD,BIH,AZE,AUS,AUT,ARG,AGO,ANT,ARM,ALB,ARE
2
- adpe,kg éq. Sb,ADEME Base IMPACTS ®,0.0000000737708,0.0000000642317,0.000000109502,0.000000162193,0.0000000862445,0.0000000163908,0.0000000945573,0.000000112811,0.000000103681,0.000000104586,0.0000000985548,0.0000000647907,0.000000132261,0.0000000578088,0.000000064552,0.0000000749765,0.0000000177021,0.000000131822,0.000000152621,0.0000000569593,0.000000134255,0.0000000268396,0.0000000472135,0.0000000470662,0.0000000606109,0.0000000992283,0.0000000198459,0.0000000777062,0.0000000955701,0.0000000134206,0.0000000960312,0.000000132772,0.0000000981761,0.00000001324,0.000000149181,0.0000000341863,0.000000101946,0.0000000842952,0.0000000595304,0.0000000952688,0.0000000790553,0.0000000374073,0.0000000720474,0.000000238273,0.000000127486,0.0000000329318,0.0000000414983,0.0000000621,0.000000128285,0.000000148382,0.000000044938,0.0000000578358,0.000000049475,0.000000176361,0.000000152699,0.000000119873,0.000000110674,0.0000000641089,0.0000000206592,0.000000153757,0.000000105692,0.0000000294596,0.0000000986932,0.0000000182134,0.000000135386,0.0000000141168,0.0000000518017,0.000000117457,0.0000000319202,0.000000181827,0.0000000958533,0.0000000596578,0.0000000147031,0.0000000196047,0.00000005439,0.0000000781905,0.0000000220304,0.0000000404306,0.000000100099,0.0000000610194,0.0000000219257,0.0000000610451,0.0000000644587,0.0000000937057,0.000000153989,0.0000000649373,0.0000000816213,0.0000000803251,0.0000000691645,0.0000000286211,0.000000156003,0.000000137999,0.0000000370973,0.000000113843,0.0000000485798,0.0000000805114,0.000000174161,0.0000000518326,0.0000000512406,0.000000033925,0.0000000990171,0.000000127168,0.0000000216438,0.0000000429285,0.0000000157411,0.0000000878733,0.0000000817565,0.0000000448771,0.0000000299542,0.0000000863908,0.000000122031,0.0000000851552,0.000000146313,0.000000105851,0.0000000949004,0.000000100467,0.000000265575,0.000000174647,0.0000000993179,0.0000000840478,0.0000000866014,0.00000010962,0.0000000969793,0.0000000185641,0.0000000239702,0.0000000135014,0.0000000823611,0.0000000337201,0.0000000394158,0.000000148007,0.000000092567,0.0000000790846,0.000000141124,0.0000000768612,0.000000124074,0.0000000449103,0.0000000854245,0.000000229556,0.0000000141548
3
- pe,MJ,ADPf / (1-%renewable_energy),9.988,12.873,16.122,1.798,11.732,16.250,11.238,15.163,17.367,107.570,11.358,12.936,9.305,11.439,14.289,16.150,12.902,23.300,19.165,10.414,21.978,16.989,13.012,14.516,11.680,12.146,10.477,11.026,29.629,14.058,13.200,14.242,15.585,11.916,0.020,14.153,13.178,16.175,11.120,8.211,16.364,22.306,24.731,0.396,4.952,8.511,24.696,11.279,468.150,0.206,12.268,11.775,19.374,15.114,14.132,19.120,18.429,11.702,19.116,8.249,10.128,21.043,12.116,12.341,13.260,12.753,10.199,32.793,34.655,15.380,68.996,10.718,13.677,14.799,12.656,0.013,15.022,20.372,20.363,10.023,10.706,11.603,11.784,20.167,18.548,15.762,,14.340,14.487,,10.097,10.425,13.579,28.341,11.289,11.275,36.133,12.090,13.289,10.195,16.334,20.908,16.376,12.412,16.824,16.260,12.517,13.118,17.317,45.996,7.312,14.119,10.807,11.348,14.783,11.782,34.147,0.097,11.987,13.194,19.642,9.031,11.587,15.689,14.337,14.036,14.375,10.776,12.935,21.705,12.831,16.908,11.036,10.049,16.972,,13.380,0.201,19.032
4
- gwp,kg éq. CO2,ADEME Base IMPACTS ®,0.590478,0.509427,0.842811,0.0141304,1.17562,1.06777,0.555572,0.497373,0.81178,0.296953,0.67978,0.646745,0.475635,0.845351,0.933059,0.706988,0.80722,1.38296,0.0426743,0.646174,0.545455,1.08778,0.473128,1.1195,0.309341,0.498523,0.655825,0.0464664,1.12472,0.913677,0.66131,1.07808,0.664245,0.722125,0.241601,0.571172,1.15075,0.748727,0.761317,0.284364,0.53403,1.41292,0.293397,0.0841323,0.023754,0.544803,0.941626,0.693123,0.357253,0.00880732,0.832206,0.739214,1.31149,1.47192,0.48193,1.24074,1.04213,0.933694,1.35361,0.234273,0.490016,0.154229,0.709185,0.883627,1.128,0.885084,0.599585,0.797361,1.41054,0.156039,0.589603,0.540891,0.781372,1.07345,0.621329,0.0194609,0.930385,1.48728,1.58299,0.901842,0.648118,0.875394,0.541558,1.3858,0.535759,0.692837,0.95888,0.645801,1.13127,0.977477,0.540126,0.132046,0.602137,0.732511,0.0813225,0.322068,0.251299,0.467803,1.13153,0.587775,1.51492,0.627714,1.02318,0.909252,0.633534,0.657374,0.799077,0.978041,1.28325,0.224471,0.214014,1.05738,0.456622,0.574415,0.928583,0.0448568,0.904053,0.0613102,0.238191,0.795697,2.12572,0.278647,0.585131,0.997577,1.19128,0.804567,0.827087,0.256537,0.795168,1.56025,0.726126,1.12326,0.245573,0.476811,0.412014,1.13161,0.252002,0.0207635,1.09088
 
 
 
 
 
src/data/throughputs.json ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "models": [
3
+ {
4
+ "provider": "openai",
5
+ "name": "gpt-3.5-turbo",
6
+ "throughput": 144.6
7
+ },
8
+ {
9
+ "provider": "openai",
10
+ "name": "gpt-4",
11
+ "throughput": 33.0
12
+ },
13
+ {
14
+ "provider": "openai",
15
+ "name": "gpt-4-turbo",
16
+ "throughput": 46.5
17
+ },
18
+ {
19
+ "provider": "openai",
20
+ "name": "gpt-4o",
21
+ "throughput": 68.4
22
+ },
23
+ {
24
+ "provider": "openai",
25
+ "name": "gpt-4o-mini",
26
+ "throughput": 59.5
27
+ },
28
+ {
29
+ "provider": "openai",
30
+ "name": "o1",
31
+ "throughput": 442.9
32
+ },
33
+ {
34
+ "provider": "openai",
35
+ "name": "o1-mini",
36
+ "throughput": 173.2
37
+ },
38
+ {
39
+ "provider": "openai",
40
+ "name": "o3-mini",
41
+ "throughput": 597.4
42
+ },
43
+ {
44
+ "provider": "openai",
45
+ "name": "gpt-4.1-nano",
46
+ "throughput": 91.9
47
+ },
48
+ {
49
+ "provider": "openai",
50
+ "name": "gpt-4.1-mini",
51
+ "throughput": 68.7
52
+ },
53
+ {
54
+ "provider": "openai",
55
+ "name": "gpt-4.1",
56
+ "throughput": 61.0
57
+ },
58
+ {
59
+ "provider": "openai",
60
+ "name": "o4-mini",
61
+ "throughput": 64.7
62
+ },
63
+ {
64
+ "provider": "openai",
65
+ "name": "gpt-5-nano",
66
+ "throughput": 82.4
67
+ },
68
+ {
69
+ "provider": "openai",
70
+ "name": "gpt-5-mini",
71
+ "throughput": 47.1
72
+ },
73
+ {
74
+ "provider": "openai",
75
+ "name": "gpt-5",
76
+ "throughput": 41.3
77
+ },
78
+ {
79
+ "provider": "anthropic",
80
+ "name": "claude-3-5-haiku-latest",
81
+ "throughput": 59.6
82
+ },
83
+ {
84
+ "provider": "anthropic",
85
+ "name": "claude-3-5-sonnet-latest",
86
+ "throughput": 52.7
87
+ },
88
+ {
89
+ "provider": "anthropic",
90
+ "name": "claude-3-7-sonnet-latest",
91
+ "throughput": 51.9
92
+ },
93
+ {
94
+ "provider": "anthropic",
95
+ "name": "claude-opus-4-0",
96
+ "throughput": 37.0
97
+ },
98
+ {
99
+ "provider": "anthropic",
100
+ "name": "claude-opus-4-1",
101
+ "throughput": 38.1
102
+ },
103
+ {
104
+ "provider": "anthropic",
105
+ "name": "claude-sonnet-4-0",
106
+ "throughput": 60.2
107
+ },
108
+ {
109
+ "provider": "anthropic",
110
+ "name": "claude-sonnet-4-5",
111
+ "throughput": 61.4
112
+ },
113
+ {
114
+ "provider": "anthropic",
115
+ "name": "claude-haiku-4-5",
116
+ "throughput": 119.8
117
+ },
118
+ {
119
+ "provider": "mistralai",
120
+ "name": "codestral-latest",
121
+ "throughput": 272.8
122
+ },
123
+ {
124
+ "provider": "mistralai",
125
+ "name": "devstral-medium-latest",
126
+ "throughput": 106.7
127
+ },
128
+ {
129
+ "provider": "mistralai",
130
+ "name": "devstral-small-latest",
131
+ "throughput": 187.8
132
+ },
133
+ {
134
+ "provider": "mistralai",
135
+ "name": "magistral-medium-latest",
136
+ "throughput": 106.7
137
+ },
138
+ {
139
+ "provider": "mistralai",
140
+ "name": "magistral-small-latest",
141
+ "throughput": 187.8
142
+ },
143
+ {
144
+ "provider": "mistralai",
145
+ "name": "ministral-3b-latest",
146
+ "throughput": 309.6
147
+ },
148
+ {
149
+ "provider": "mistralai",
150
+ "name": "ministral-8b-latest",
151
+ "throughput": 213.7
152
+ },
153
+ {
154
+ "provider": "mistralai",
155
+ "name": "mistral-large-latest",
156
+ "throughput": 48.6
157
+ },
158
+ {
159
+ "provider": "mistralai",
160
+ "name": "mistral-medium-latest",
161
+ "throughput": 54.6
162
+ },
163
+ {
164
+ "provider": "mistralai",
165
+ "name": "mistral-small-latest",
166
+ "throughput": 158.0
167
+ },
168
+ {
169
+ "provider": "mistralai",
170
+ "name": "mistral-tiny-latest",
171
+ "throughput": 92.8
172
+ },
173
+ {
174
+ "provider": "mistralai",
175
+ "name": "open-mistral-7b",
176
+ "throughput": 121.5
177
+ },
178
+ {
179
+ "provider": "mistralai",
180
+ "name": "open-mistral-nemo",
181
+ "throughput": 153.2
182
+ },
183
+ {
184
+ "provider": "mistralai",
185
+ "name": "open-mixtral-8x22b",
186
+ "throughput": 85.7
187
+ },
188
+ {
189
+ "provider": "mistralai",
190
+ "name": "open-mixtral-8x7b",
191
+ "throughput": 80
192
+ },
193
+ {
194
+ "provider": "google_genai",
195
+ "name": "gemini-2.0-flash-lite",
196
+ "throughput": 74.1
197
+ },
198
+ {
199
+ "provider": "google_genai",
200
+ "name": "gemini-2.0-flash",
201
+ "throughput": 151.4
202
+ },
203
+ {
204
+ "provider": "google_genai",
205
+ "name": "gemini-2.5-flash-lite",
206
+ "throughput": 74.1
207
+ },
208
+ {
209
+ "provider": "google_genai",
210
+ "name": "gemini-2.5-flash",
211
+ "throughput": 93.2
212
+ },
213
+ {
214
+ "provider": "google_genai",
215
+ "name": "gemini-2.5-pro",
216
+ "throughput": 86.6
217
+ },
218
+ {
219
+ "provider": "cohere",
220
+ "name": "command-a-03-2025",
221
+ "throughput": 77.4
222
+ },
223
+ {
224
+ "provider": "cohere",
225
+ "name": "command-r",
226
+ "throughput": 125.1
227
+ },
228
+ {
229
+ "provider": "cohere",
230
+ "name": "command-r-08-2024",
231
+ "throughput": 67.2
232
+ },
233
+ {
234
+ "provider": "cohere",
235
+ "name": "command-r-plus-08-2024",
236
+ "throughput": 26.9
237
+ },
238
+ {
239
+ "provider": "cohere",
240
+ "name": "command-r7b-12-2024",
241
+ "throughput": 125.1
242
+ }
243
+ ]
244
+ }
src/electricity_mix.py CHANGED
@@ -1,174 +1,74 @@
1
- from csv import DictReader
2
- import pandas as pd
3
 
4
- PATH = "src/data/electricity_mix.csv"
5
 
 
6
  COUNTRY_CODES = [
7
  ("🌎 World", "WOR"),
8
- ("🇪🇺 Europe", "EEE"),
9
- ("🇿🇼 Zimbabwe", "ZWE"),
10
- ("🇿🇲 Zambia", "ZMB"),
11
- ("🇿🇦 South Africa", "ZAF"),
12
- ("🇾🇪 Yemen", "YEM"),
13
- ("🇻🇳 Vietnam", "VNM"),
14
- ("🇻🇪 Venezuela", "VEN"),
15
- ("🇺🇿 Uzbekistan", "UZB"),
16
- ("🇺🇾 Uruguay", "URY"),
17
- ("🇺🇸 United States", "USA"),
18
- ("🇺🇦 Ukraine", "UKR"),
19
- ("🇹🇿 Tanzania", "TZA"),
20
- ("🇹🇼 Taiwan", "TWN"),
21
- ("🇹🇹 Trinidad and Tobago", "TTO"),
22
- ("🇹🇷 Turkey", "TUR"),
23
- ("🇹🇳 Tunisia", "TUN"),
24
- ("🇹🇲 Turkmenistan", "TKM"),
25
- ("🇹🇯 Tajikistan", "TJK"),
26
- ("🇹🇭 Thailand", "THA"),
27
- ("🇹🇬 Togo", "TGO"),
28
- ("🇸🇾 Syrian Arab Republic", "SYR"),
29
- ("🇸🇻 El Salvador", "SLV"),
30
- ("🇸🇳 Senegal", "SEN"),
31
- ("🇸🇰 Slovak Republic", "SVK"),
32
- ("🇸🇮 Slovenia", "SVN"),
33
- ("🇸🇬 Singapore", "SGP"),
34
- ("🇸🇪 Sweden", "SWE"),
35
- ("🇸🇩 Sudan", "SDN"),
36
- ("🇸🇦 Saudi Arabia", "SAU"),
37
- ("🇷🇺 Russian Federation", "RUS"),
38
- ("🇷🇸 Serbia and Montenegro", "SCG"),
39
- ("🇷🇴 Romania", "ROU"),
40
- ("🇶🇦 Qatar", "QAT"),
41
- ("🇵🇾 Paraguay", "PRY"),
42
- ("🇵🇹 Portugal", "PRT"),
43
- ("🇵🇱 Poland", "POL"),
44
- ("🇵🇰 Pakistan", "PAK"),
45
- ("🇵🇭 Philippines", "PHL"),
46
- ("🇵🇪 Peru", "PER"),
47
- ("🇵🇦 Panama", "PAN"),
48
- ("🇴🇲 Oman", "OMN"),
49
- ("🇳🇿 New Zealand", "NZL"),
50
- ("🇳🇵 Nepal", "NPL"),
51
- ("🇳🇴 Norway", "NOR"),
52
- ("🇳🇱 Netherlands", "NLD"),
53
- ("🇳🇮 Nicaragua", "NIC"),
54
- ("🇳🇬 Nigeria", "NGA"),
55
- ("🇳🇦 Namibia", "NAM"),
56
- ("🇲🇿 Mozambique", "MOZ"),
57
- ("🇲🇾 Malaysia", "MYS"),
58
- ("🇲🇽 Mexico", "MEX"),
59
- ("🇲🇹 Malta", "MLT"),
60
- ("🇲🇳 Mongolia", "MNG"),
61
- ("🇲🇲 Myanmar", "MMR"),
62
- ("🇲🇰 North Macedonia", "MKD"),
63
- ("🇲🇩 Moldova", "MDA"),
64
- ("🇲🇦 Morocco", "MAR"),
65
- ("🇱🇾 Libya", "LBY"),
66
- ("🇱🇻 Latvia", "LVA"),
67
- ("🇱🇺 Luxembourg", "LUX"),
68
- ("🇱🇹 Lithuania", "LTU"),
69
- ("🇱🇰 Sri Lanka", "LKA"),
70
- ("🇱🇧 Lebanon", "LBN"),
71
- ("🇰🇿 Kazakhstan", "KAZ"),
72
- ("🇰🇼 Kuwait", "KWT"),
73
- ("🇰🇷 South Korea", "KOR"),
74
- ("🇰🇵 North Korea", "PRK"),
75
- ("🇰🇭 Cambodia", "KHM"),
76
- ("🇰🇬 Kyrgyz Republic", "KGZ"),
77
- ("🇰🇪 Kenya", "KEN"),
78
- ("🇯🇵 Japan", "JPN"),
79
- ("🇯🇴 Jordan", "JOR"),
80
- ("🇯🇲 Jamaica", "JAM"),
81
- ("🇮🇹 Italy", "ITA"),
82
- ("🇮🇸 Iceland", "ISL"),
83
- ("🇮🇷 Iran", "IRN"),
84
- ("🇮🇶 Iraq", "IRQ"),
85
- ("🇮🇳 India", "IND"),
86
- ("🇮🇱 Israel", "ISR"),
87
- ("🇮🇪 Ireland", "IRL"),
88
- ("🇮🇩 Indonesia", "IDN"),
89
- ("🇭🇺 Hungary", "HUN"),
90
- ("🇭🇹 Haiti", "HTI"),
91
- ("🇭🇷 Croatia", "HRV"),
92
- ("🇭🇳 Honduras", "HND"),
93
- ("🇭🇰 Hong Kong", "HKG"),
94
- ("🇬🇹 Guatemala", "GTM"),
95
- ("🇬🇷 Greece", "GRC"),
96
- ("🇬🇮 Gibraltar", "GIB"),
97
- ("🇬🇭 Ghana", "GHA"),
98
- ("🇬🇪 Georgia", "GEO"),
99
- ("🇬🇧 United Kingdom", "GBR"),
100
- ("🇬🇦 Gabon", "GAB"),
101
- ("🇫🇷 France", "FRA"),
102
- ("🇫🇮 Finland", "FIN"),
103
- ("🇪🇹 Ethiopia", "ETH"),
104
- ("🇪🇸 Spain", "ESP"),
105
- ("🇪🇷 Eritrea", "ERI"),
106
- ("🇪🇬 Egypt", "EGY"),
107
- ("🇪🇪 Estonia", "EST"),
108
- ("🇪🇨 Ecuador", "ECU"),
109
- ("🇩🇿 Algeria", "DZA"),
110
- ("🇩🇴 Dominican Republic", "DOM"),
111
- ("🇩🇰 Denmark", "DNK"),
112
- ("🇩🇪 Germany", "DEU"),
113
- ("🇨🇿 Czech Republic", "CZE"),
114
- ("🇨🇾 Cyprus", "CYP"),
115
- ("🇨🇺 Cuba", "CUB"),
116
- ("🇨🇷 Costa Rica", "CRI"),
117
- ("🇨🇴 Colombia", "COL"),
118
- ("🇨🇳 China", "CHN"),
119
- ("🇨🇲 Cameroon", "CMR"),
120
- ("🇨🇱 Chile", "CHL"),
121
- ("🇨🇮 Cote d'Ivoire", "CIV"),
122
- ("🇨🇭 Switzerland", "CHE"),
123
- ("🇨🇬 Congo", "COG"),
124
- ("🇨🇩 Democratic Republic of the Congo", "COD"),
125
- ("🇨🇦 Canada", "CAN"),
126
- ("🇧🇾 Belarus", "BLR"),
127
- ("🇧🇼 Botswana", "BWA"),
128
- ("🇧🇷 Brazil", "BRA"),
129
- ("🇧🇴 Bolivia", "BOL"),
130
- ("🇧🇳 Brunei", "BRN"),
131
- ("🇧🇯 Benin", "BEN"),
132
- ("🇧🇭 Bahrain", "BHR"),
133
- ("🇧🇬 Bulgaria", "BGR"),
134
- ("🇧🇪 Belgium", "BEL"),
135
- ("🇧🇩 Bangladesh", "BGD"),
136
- ("🇧🇦 Bosnia and Herzegovina", "BIH"),
137
- ("🇦🇿 Azerbaijan", "AZE"),
138
  ("🇦🇺 Australia", "AUS"),
139
  ("🇦🇹 Austria", "AUT"),
140
  ("🇦🇷 Argentina", "ARG"),
141
- ("🇦🇴 Angola", "AGO"),
142
- ("���� Netherlands Antilles", "ANT"),
143
- ("🇦🇲 Armenia", "ARM"),
144
- ("🇦🇱 Albania", "ALB"),
145
- ("🇦🇪 United Arab Emirates", "ARE"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  ]
147
 
 
 
 
 
 
 
148
 
149
- def find_electricity_mix(code: str):
150
- # TODO: Maybe more optimal to construct database at the beginning of the app
151
- # in the same fashion as find_model
152
- res = []
153
- with open(PATH) as fd:
154
- csv = DictReader(fd)
155
- for row in csv:
156
- res += [float(row[code])]
157
- return res
158
-
159
-
160
- def dataframe_electricity_mix(countries: list):
161
- df = pd.read_csv("src/data/electricity_mix.csv")
162
- df["name_unit"] = df["name"] + " (" + df["unit"] + ")"
163
- df = df[["name_unit"] + [x[1] for x in COUNTRY_CODES if x[0] in countries]]
164
 
165
- df_melted = df.melt(
166
- id_vars=["name_unit"],
167
- value_vars=[x[1] for x in COUNTRY_CODES if x[0] in countries],
168
- var_name="country",
169
- value_name="value",
170
- )
171
 
172
- df = df_melted.pivot(columns="name_unit", index="country", values="value")
173
 
174
- return df
 
 
1
+ from __future__ import annotations
 
2
 
 
3
 
4
+ PATH = "src/data/electricity_mix.csv"
5
  COUNTRY_CODES = [
6
  ("🌎 World", "WOR"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  ("🇦🇺 Australia", "AUS"),
8
  ("🇦🇹 Austria", "AUT"),
9
  ("🇦🇷 Argentina", "ARG"),
10
+ ("🇧🇪 Belgium", "BEL"),
11
+ ("🇧🇬 Bulgaria", "BGR"),
12
+ ("🇧🇷 Brazil", "BRA"),
13
+ ("🇨🇦 Canada", "CAN"),
14
+ ("🇨🇭 Switzerland", "CHE"),
15
+ ("🇨🇱 Chile", "CHL"),
16
+ ("🇨🇳 China", "CHN"),
17
+ ("🇨🇾 Cyprus", "CYP"),
18
+ ("🇨🇿 Czech Republic", "CZE"),
19
+ ("🇩🇪 Germany", "DEU"),
20
+ ("🇩🇰 Denmark", "DNK"),
21
+ ("🇪🇸 Spain", "ESP"),
22
+ ("🇪🇪 Estonia", "EST"),
23
+ ("🇫🇮 Finland", "FIN"),
24
+ ("🇫🇷 France", "FRA"),
25
+ ("🇬🇧 United Kingdom", "GBR"),
26
+ ("🇬🇷 Greece", "GRC"),
27
+ ("🇭🇺 Hungary", "HUN"),
28
+ ("🇮🇩 Indonesia", "IDN"),
29
+ ("🇮🇳 India", "IND"),
30
+ ("🇮🇪 Ireland", "IRL"),
31
+ ("🇮🇸 Iceland", "ISL"),
32
+ ("🇮🇹 Italy", "ITA"),
33
+ ("🇯🇵 Japan", "JPN"),
34
+ ("🇰🇷 South Korea", "KOR"),
35
+ ("🇱🇹 Lithuania", "LTU"),
36
+ ("🇱🇺 Luxembourg", "LUX"),
37
+ ("🇱🇻 Latvia", "LVA"),
38
+ ("🇲🇽 Mexico", "MEX"),
39
+ ("🇲🇹 Malta", "MLT"),
40
+ ("🇲🇾 Malaysia", "MYS"),
41
+ ("🇳🇱 Netherlands", "NLD"),
42
+ ("🇳🇴 Norway", "NOR"),
43
+ ("🇳🇿 New Zealand", "NZL"),
44
+ ("🇵🇱 Poland", "POL"),
45
+ ("🇵🇹 Portugal", "PRT"),
46
+ ("🇷🇴 Romania", "ROU"),
47
+ ("🇷🇺 Russian Federation", "RUS"),
48
+ ("🇸🇰 Slovak Republic", "SVK"),
49
+ ("🇸🇮 Slovenia", "SVN"),
50
+ ("🇸🇪 Sweden", "SWE"),
51
+ ("🇺🇦 Ukraine", "UKR"),
52
+ ("🇹🇭 Thailand", "THA"),
53
+ ("🇹🇷 Turkey", "TUR"),
54
+ ("🇹🇼 Taiwan", "TWN"),
55
+ ("🇺🇸 United States", "USA")
56
  ]
57
 
58
+ CRITERIA = {
59
+ "gwp": "GHG Emission (kg CO2 eq)",
60
+ "adpe": "Abiotic Resources (kg Sb eq)",
61
+ "pe": "Primary Energy (MJ)",
62
+ "wue": "Water Usage Effectiveness (L/kWh)"
63
+ }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
+ def format_country_name(code: str) -> str | None:
67
+ for country_name, country_code in COUNTRY_CODES:
68
+ if country_code == code:
69
+ return country_name
70
+ return None
 
71
 
 
72
 
73
+ def format_electricity_mix_criterion(criterion: str) -> str | None:
74
+ return CRITERIA.get(criterion)
src/expert.py CHANGED
@@ -1,58 +1,52 @@
 
1
  import streamlit as st
 
2
  from ecologits.impacts.llm import compute_llm_impacts
3
 
4
- from src.utils import format_impacts, average_range_impacts
 
5
  from src.impacts import display_impacts
6
- from src.electricity_mix import (
7
- COUNTRY_CODES,
8
- find_electricity_mix,
9
- dataframe_electricity_mix,
10
- )
11
  from src.models import load_models
12
  from src.constants import PROMPTS
 
13
 
14
  import plotly.express as px
15
 
16
 
17
- def reset_model():
18
- model = "CUSTOM"
19
-
20
-
21
  def expert_mode():
22
  st.markdown("### 🤓 Expert mode")
23
 
24
  with st.container(border=True):
 
 
25
  ########## Model info ##########
26
 
27
- col1, col2, col3 = st.columns(3)
28
 
29
  df = load_models(filter_main=True)
30
 
31
- with col1:
 
32
  provider_exp = st.selectbox(
33
  label="Provider",
34
- options=[x for x in df["provider_clean"].unique()],
35
- index=7,
36
  key=1,
37
  )
38
 
39
- with col2:
 
 
 
 
 
40
  model_exp = st.selectbox(
41
  label="Model",
42
- options=[
43
- x
44
- for x in df["name_clean"].unique()
45
- if x
46
- in df[df["provider_clean"] == provider_exp]["name_clean"].unique()
47
- ],
48
  key=2,
49
  )
50
 
51
- with col3:
52
- output_tokens_exp = st.selectbox(
53
- label="Example prompt", options=[x[0] for x in PROMPTS], key=3
54
- )
55
-
56
  df_filtered = df[
57
  (df["provider_clean"] == provider_exp) & (df["name_clean"] == model_exp)
58
  ]
@@ -79,67 +73,111 @@ def expert_mode():
79
  / 2
80
  )
81
 
 
 
 
 
82
  ########## Model parameters ##########
83
 
84
- col11, col22, col33 = st.columns(3)
85
 
86
- with col11:
87
- active_params = st.number_input(
88
- "Active parameters (B)", 0, None, active_params
89
- )
 
90
 
91
- with col22:
92
- total_params = st.number_input(
93
- "Total parameters (B)", 0, None, total_params
 
 
 
 
 
 
 
 
 
94
  )
95
 
96
- with col33:
97
  output_tokens = st.number_input(
98
  label="Output completion tokens",
99
  min_value=0,
100
  value=[x[1] for x in PROMPTS if x[0] == output_tokens_exp][0],
101
  )
102
 
103
- ########## Electricity mix ##########
104
 
105
- location = st.selectbox("Location", [x[0] for x in COUNTRY_CODES])
106
-
107
- col4, col5, col6 = st.columns(3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
- with col4:
110
- mix_gwp = st.number_input(
111
- "Electricity mix - GHG emissions [kgCO2eq / kWh]",
112
- find_electricity_mix(
113
- [x[1] for x in COUNTRY_CODES if x[0] == location][0]
114
- )[2],
115
  format="%0.6f",
116
  )
117
- # disp_ranges = st.toggle('Display impact ranges', False)
118
- with col5:
119
- mix_adpe = st.number_input(
120
- "Electricity mix - Abiotic resources [kgSbeq / kWh]",
121
- find_electricity_mix(
122
- [x[1] for x in COUNTRY_CODES if x[0] == location][0]
123
- )[0],
124
  format="%0.13f",
125
  )
126
- with col6:
127
- mix_pe = st.number_input(
128
- "Electricity mix - Primary energy [MJ / kWh]",
129
- find_electricity_mix(
130
- [x[1] for x in COUNTRY_CODES if x[0] == location][0]
131
- )[1],
 
 
 
 
132
  format="%0.3f",
133
  )
134
 
 
 
 
 
 
 
 
135
  impacts = compute_llm_impacts(
136
  model_active_parameter_count=active_params,
137
  model_total_parameter_count=total_params,
138
  output_token_count=output_tokens,
139
- request_latency=100000,
140
- if_electricity_mix_gwp=mix_gwp,
141
- if_electricity_mix_adpe=mix_adpe,
142
- if_electricity_mix_pe=mix_pe,
 
 
 
143
  )
144
 
145
  impacts, usage, embodied = format_impacts(impacts)
@@ -166,8 +204,8 @@ def expert_mode():
166
  with col_ghg_comparison:
167
  fig_gwp = px.pie(
168
  values=[
169
- average_range_impacts(usage.gwp.value),
170
- average_range_impacts(embodied.gwp.value),
171
  ],
172
  names=["usage", "embodied"],
173
  title="GHG emissions",
@@ -181,8 +219,8 @@ def expert_mode():
181
  with col_adpe_comparison:
182
  fig_adpe = px.pie(
183
  values=[
184
- average_range_impacts(usage.adpe.value),
185
- average_range_impacts(embodied.adpe.value),
186
  ],
187
  names=["usage", "embodied"],
188
  title="Abiotic depletion",
@@ -196,8 +234,8 @@ def expert_mode():
196
  with col_pe_comparison:
197
  fig_pe = px.pie(
198
  values=[
199
- average_range_impacts(usage.pe.value),
200
- average_range_impacts(embodied.pe.value),
201
  ],
202
  names=["usage", "embodied"],
203
  title="Primary energy",
@@ -216,24 +254,25 @@ def expert_mode():
216
 
217
  countries_to_compare = st.multiselect(
218
  label="Countries to compare",
219
- options=[x[0] for x in COUNTRY_CODES],
220
- default=["🇫🇷 France", "🇺🇸 United States", "🇨🇳 China"],
 
221
  )
222
 
223
  try:
224
- df_comp = dataframe_electricity_mix(countries_to_compare)
225
-
226
  impact_type = st.selectbox(
227
  label="Select an impact type to compare",
228
- options=[x for x in df_comp.columns if x != "country"],
229
- index=1,
 
230
  )
231
 
232
- df_comp.sort_values(by=impact_type, inplace=True)
 
233
 
234
  fig_2 = px.bar(
235
  df_comp,
236
- x=df_comp.index,
237
  y=impact_type,
238
  text=impact_type,
239
  color=impact_type,
 
1
+ import pandas as pd
2
  import streamlit as st
3
+ from ecologits.electricity_mix_repository import electricity_mixes
4
  from ecologits.impacts.llm import compute_llm_impacts
5
 
6
+ from src.latency_estimator import latency_estimator
7
+ from src.utils import format_impacts
8
  from src.impacts import display_impacts
9
+ from src.electricity_mix import COUNTRY_CODES, format_electricity_mix_criterion, format_country_name
 
 
 
 
10
  from src.models import load_models
11
  from src.constants import PROMPTS
12
+ from src.constants import PROMPTS
13
 
14
  import plotly.express as px
15
 
16
 
 
 
 
 
17
  def expert_mode():
18
  st.markdown("### 🤓 Expert mode")
19
 
20
  with st.container(border=True):
21
+ st.markdown("###### Configure the model")
22
+
23
  ########## Model info ##########
24
 
25
+ provider_col, model_col = st.columns(2)
26
 
27
  df = load_models(filter_main=True)
28
 
29
+ with provider_col:
30
+ providers_clean = [x for x in df["provider_clean"].unique()]
31
  provider_exp = st.selectbox(
32
  label="Provider",
33
+ options=providers_clean,
34
+ index=providers_clean.index("OpenAI"),
35
  key=1,
36
  )
37
 
38
+ with model_col:
39
+ models_clean = [
40
+ x
41
+ for x in df["name_clean"].unique()
42
+ if x in df[df["provider_clean"] == provider_exp]["name_clean"].unique()
43
+ ]
44
  model_exp = st.selectbox(
45
  label="Model",
46
+ options=models_clean,
 
 
 
 
 
47
  key=2,
48
  )
49
 
 
 
 
 
 
50
  df_filtered = df[
51
  (df["provider_clean"] == provider_exp) & (df["name_clean"] == model_exp)
52
  ]
 
73
  / 2
74
  )
75
 
76
+ provider_raw = df_filtered["provider"].values[0]
77
+ model_name_raw = df_filtered["name"].values[0]
78
+ tps_raw = latency_estimator.get_throughput(provider_raw, model_name_raw)
79
+
80
  ########## Model parameters ##########
81
 
82
+ active_params_col, total_params_col, throughput_col = st.columns(3)
83
 
84
+ with active_params_col:
85
+ active_params = st.number_input("Active parameters (B)", 0, None, active_params)
86
+
87
+ with total_params_col:
88
+ total_params = st.number_input("Total parameters (B)", 0, None, total_params)
89
 
90
+ with throughput_col:
91
+ throughput = st.number_input("Average TPS", 1.0, None, tps_raw)
92
+
93
+
94
+ with st.container(border=True):
95
+ st.markdown("###### Configure the prompt")
96
+
97
+ prompt_col, token_col = st.columns(2)
98
+
99
+ with prompt_col:
100
+ output_tokens_exp = st.selectbox(
101
+ label="Example prompt", options=[x[0] for x in PROMPTS], key=3
102
  )
103
 
104
+ with token_col:
105
  output_tokens = st.number_input(
106
  label="Output completion tokens",
107
  min_value=0,
108
  value=[x[1] for x in PROMPTS if x[0] == output_tokens_exp][0],
109
  )
110
 
 
111
 
112
+ with st.container(border=True):
113
+ st.markdown("###### Configure the data center")
114
+
115
+ dc_pue_col, dc_wue_col, dc_location_col = st.columns(3)
116
+ with dc_pue_col:
117
+ datacenter_pue = st.number_input(
118
+ label="Data center PUE",
119
+ value=1.2,
120
+ min_value=1.0
121
+ )
122
+ with dc_wue_col:
123
+ datacenter_wue = st.number_input(
124
+ label="Data center WUE [L / kWh]",
125
+ value=0.6,
126
+ min_value=0.
127
+ )
128
+ with dc_location_col:
129
+ dc_location = st.selectbox(
130
+ label="Data center location",
131
+ options=[c[1] for c in COUNTRY_CODES],
132
+ format_func=format_country_name,
133
+ index=0
134
+ )
135
 
136
+ em_gwp_col, em_adpe_col, em_pe_col, em_wue_col = st.columns(4)
137
+ electricity_mix = electricity_mixes.find_electricity_mix(dc_location)
138
+ with em_gwp_col:
139
+ em_gwp = st.number_input(
140
+ label="GHG emissions [kgCO2eq / kWh]",
141
+ value=electricity_mix.gwp,
142
  format="%0.6f",
143
  )
144
+ with em_adpe_col:
145
+ em_adpe = st.number_input(
146
+ label="Abiotic resources [kgSbeq / kWh]",
147
+ value=electricity_mix.adpe,
 
 
 
148
  format="%0.13f",
149
  )
150
+ with em_pe_col:
151
+ em_pe = st.number_input(
152
+ label="Primary energy [MJ / kWh]",
153
+ value=electricity_mix.pe,
154
+ format="%0.3f",
155
+ )
156
+ with em_wue_col:
157
+ em_wue = st.number_input(
158
+ label="Water consumption [L / kWh]",
159
+ value=electricity_mix.wue,
160
  format="%0.3f",
161
  )
162
 
163
+ estimated_latency = latency_estimator.estimate(
164
+ provider=provider_raw,
165
+ model_name=model_name_raw,
166
+ output_tokens=output_tokens,
167
+ throughput=throughput
168
+ )
169
+
170
  impacts = compute_llm_impacts(
171
  model_active_parameter_count=active_params,
172
  model_total_parameter_count=total_params,
173
  output_token_count=output_tokens,
174
+ request_latency=estimated_latency,
175
+ if_electricity_mix_gwp=em_gwp,
176
+ if_electricity_mix_adpe=em_adpe,
177
+ if_electricity_mix_pe=em_pe,
178
+ if_electricity_mix_wue=em_wue,
179
+ datacenter_pue=datacenter_pue,
180
+ datacenter_wue=datacenter_wue
181
  )
182
 
183
  impacts, usage, embodied = format_impacts(impacts)
 
204
  with col_ghg_comparison:
205
  fig_gwp = px.pie(
206
  values=[
207
+ usage.gwp.value if isinstance(usage.gwp.value, float) else usage.gwp.value.mean,
208
+ embodied.gwp.value if isinstance(embodied.gwp.value, float) else embodied.gwp.value.mean,
209
  ],
210
  names=["usage", "embodied"],
211
  title="GHG emissions",
 
219
  with col_adpe_comparison:
220
  fig_adpe = px.pie(
221
  values=[
222
+ usage.adpe.value if isinstance(usage.adpe.value, float) else usage.adpe.value.mean,
223
+ embodied.adpe.value if isinstance(embodied.adpe.value, float) else embodied.adpe.value.mean,
224
  ],
225
  names=["usage", "embodied"],
226
  title="Abiotic depletion",
 
234
  with col_pe_comparison:
235
  fig_pe = px.pie(
236
  values=[
237
+ usage.pe.value if isinstance(usage.pe.value, float) else usage.pe.value.mean,
238
+ embodied.pe.value if isinstance(embodied.pe.value, float) else embodied.pe.value.mean,
239
  ],
240
  names=["usage", "embodied"],
241
  title="Primary energy",
 
254
 
255
  countries_to_compare = st.multiselect(
256
  label="Countries to compare",
257
+ options=[c[1] for c in COUNTRY_CODES],
258
+ format_func=format_country_name,
259
+ default=["FRA", "USA", "CHN"],
260
  )
261
 
262
  try:
 
 
263
  impact_type = st.selectbox(
264
  label="Select an impact type to compare",
265
+ options=["gwp", "adpe", "pe", "wue"],
266
+ format_func=format_electricity_mix_criterion,
267
+ index=0,
268
  )
269
 
270
+ df_comp = pd.DataFrame([em for em in electricity_mixes.list_electricity_mixes() if em.zone in countries_to_compare])
271
+ df_comp = df_comp.sort_values(by=impact_type, ascending=True)
272
 
273
  fig_2 = px.bar(
274
  df_comp,
275
+ x=df_comp.zone.apply(format_country_name),
276
  y=impact_type,
277
  text=impact_type,
278
  color=impact_type,
src/impacts.py CHANGED
@@ -10,56 +10,58 @@ from src.utils import (
10
  EnergyProduction,
11
  )
12
 
13
- ############################################################################################################
14
-
15
-
16
- def get_impacts(model, active_params, total_params, mix_ghg, mix_adpe, mix_pe):
17
- return 1
18
-
19
-
20
- ############################################################################################################
21
-
22
 
23
  def display_impacts(impacts):
24
  st.divider()
25
 
26
- col1, col_energy, col_ghg, col2 = st.columns([1,2,2,1])
27
 
28
  with col_energy:
29
-
30
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>⚡️</p><p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Energy</p>""", unsafe_allow_html = True)
31
  st.markdown(f'<p align="center">Electricity consumption</p>', unsafe_allow_html = True)
32
- range_plot(impacts.energy.magnitude,impacts.energy_min.magnitude, impacts.energy_max.magnitude, impacts.energy.units)
33
-
34
-
35
- with col_ghg:
36
 
 
37
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>🌍️</p><p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>GHG Emissions</p>""", unsafe_allow_html = True)
38
- st.markdown(f'<p align="center">Effect on global warming</p>', unsafe_allow_html = True)
39
- range_plot(impacts.gwp.magnitude,impacts.gwp_min.magnitude, impacts.gwp_max.magnitude, impacts.gwp.units)
 
 
 
40
 
41
  st.markdown(f'<br>', unsafe_allow_html = True)
42
 
43
- col_adpe, col_pe, col_water = st.columns(3)
44
 
45
  with col_adpe:
46
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>🪨</p>""", unsafe_allow_html = True)
47
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Abiotic Resources</p>""", unsafe_allow_html = True)
48
  st.markdown('<p align="center"> Use of metals and minerals</p>', unsafe_allow_html = True)
49
- range_plot(impacts.adpe.magnitude,impacts.adpe_min.magnitude, impacts.adpe_max.magnitude, impacts.adpe.units)
50
-
 
 
51
 
52
  with col_pe:
53
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>⛽️</p>""", unsafe_allow_html = True)
54
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Primary Energy</p>""", unsafe_allow_html = True)
55
  st.markdown(f'<p align="center">Use of natural energy resources</p>', unsafe_allow_html = True)
56
- range_plot(impacts.pe.magnitude,impacts.pe_min.magnitude, impacts.pe_max.magnitude, impacts.pe.units)
 
 
 
57
 
58
- with col_water:
59
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>🚰</p>""", unsafe_allow_html = True)
60
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Water</p>""", unsafe_allow_html = True)
61
- st.markdown(f'<p align="center">Evaluates the use of water</p>', unsafe_allow_html = True)
62
- st.markdown(f"""<p style='font-size:35px;text-align: center'> Upcoming... </p>""", unsafe_allow_html = True)
 
 
 
63
 
64
 
65
 
 
10
  EnergyProduction,
11
  )
12
 
 
 
 
 
 
 
 
 
 
13
 
14
  def display_impacts(impacts):
15
  st.divider()
16
 
17
+ col1, col_energy, col_gwp, col2 = st.columns([1,2,2,1])
18
 
19
  with col_energy:
 
20
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>⚡️</p><p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Energy</p>""", unsafe_allow_html = True)
21
  st.markdown(f'<p align="center">Electricity consumption</p>', unsafe_allow_html = True)
22
+ if impacts.ranges:
23
+ range_plot(impacts.energy.magnitude,impacts.energy_min.magnitude, impacts.energy_max.magnitude, impacts.energy.units)
24
+ else:
25
+ st.latex(f'\Large {impacts.energy.magnitude:.3g} \ \large {impacts.energy.units}')
26
 
27
+ with col_gwp:
28
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>🌍️</p><p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>GHG Emissions</p>""", unsafe_allow_html = True)
29
+ st.markdown(f'<p align="center">Effect on global warming</p>', unsafe_allow_html = True)
30
+ if impacts.ranges:
31
+ range_plot(impacts.gwp.magnitude,impacts.gwp_min.magnitude, impacts.gwp_max.magnitude, impacts.gwp.units)
32
+ else:
33
+ st.latex(f'\Large {impacts.gwp.magnitude:.3g} \ \large {impacts.gwp.units}')
34
 
35
  st.markdown(f'<br>', unsafe_allow_html = True)
36
 
37
+ col_adpe, col_pe, col_wcf = st.columns(3)
38
 
39
  with col_adpe:
40
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>🪨</p>""", unsafe_allow_html = True)
41
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Abiotic Resources</p>""", unsafe_allow_html = True)
42
  st.markdown('<p align="center"> Use of metals and minerals</p>', unsafe_allow_html = True)
43
+ if impacts.ranges:
44
+ range_plot(impacts.adpe.magnitude, impacts.adpe_min.magnitude, impacts.adpe_max.magnitude, impacts.adpe.units)
45
+ else:
46
+ st.latex(f'\Large {impacts.adpe.magnitude:.3g} \ \large {impacts.adpe.units}')
47
 
48
  with col_pe:
49
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>⛽️</p>""", unsafe_allow_html = True)
50
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Primary Energy</p>""", unsafe_allow_html = True)
51
  st.markdown(f'<p align="center">Use of natural energy resources</p>', unsafe_allow_html = True)
52
+ if impacts.ranges:
53
+ range_plot(impacts.pe.magnitude, impacts.pe_min.magnitude, impacts.pe_max.magnitude, impacts.pe.units)
54
+ else:
55
+ st.latex(f'\Large {impacts.pe.magnitude:.3g} \ \large {impacts.pe.units}')
56
 
57
+ with col_wcf:
58
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'>🚰</p>""", unsafe_allow_html = True)
59
  st.markdown(f"""<p style='font-size:30px;text-align: center;margin-bottom :2px'><strong>Water</p>""", unsafe_allow_html = True)
60
+ st.markdown(f'<p align="center">Water consumption</p>', unsafe_allow_html = True)
61
+ if impacts.ranges:
62
+ range_plot(impacts.wcf.magnitude, impacts.wcf_min.magnitude, impacts.wcf_max.magnitude, impacts.wcf.units)
63
+ else:
64
+ st.latex(f'\Large {impacts.wcf.magnitude:.3g} \ \large {impacts.wcf.units}')
65
 
66
 
67
 
src/latency_estimator.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+ _BASE_PATH = Path(__file__).parent / "data" / "throughputs.json"
7
+
8
+
9
+ class LatencyEstimator:
10
+ __DEFAULT_TPS = 80.0
11
+
12
+ def __init__(self, file_path: str | Path) -> None:
13
+ with open(file_path, "r") as fd:
14
+ data = json.load(fd)
15
+
16
+ self.__throughputs = {}
17
+ for el in data["models"]:
18
+ self.__throughputs[(el["provider"], el["name"])] = el["throughput"]
19
+
20
+ def get_throughput(self, provider: str, model_name: str) -> float:
21
+ return float(self.__throughputs.get((provider, model_name), self.__DEFAULT_TPS))
22
+
23
+ def estimate(self,
24
+ provider: str,
25
+ model_name: str,
26
+ output_tokens: int,
27
+ throughput: float | None = None) -> float:
28
+ if throughput is None:
29
+ throughput = self.__throughputs.get((provider, model_name), self.__DEFAULT_TPS)
30
+ return float(output_tokens / throughput)
31
+
32
+
33
+ latency_estimator = LatencyEstimator(file_path=_BASE_PATH)
src/models.py CHANGED
@@ -1,8 +1,13 @@
1
- import requests
2
  import json
 
 
3
  import pandas as pd
4
- from src.constants import MODEL_REPOSITORY_URL, MAIN_MODELS
5
  import streamlit as st
 
 
 
 
 
6
 
7
 
8
  def clean_models_data(df, with_filter=True):
@@ -70,10 +75,68 @@ def clean_models_data(df, with_filter=True):
70
  ]
71
 
72
 
 
 
 
 
 
 
 
 
 
73
  @st.cache_data
74
- def load_models(filter_main=True):
75
- resp = requests.get(MODEL_REPOSITORY_URL)
76
- data = json.loads(resp.text)
77
- df = pd.DataFrame(data["models"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
- return clean_models_data(df, filter_main)
 
 
 
 
 
 
1
  import json
2
+
3
+ import requests
4
  import pandas as pd
 
5
  import streamlit as st
6
+ from ecologits.model_repository import models as model_repository, ArchitectureTypes
7
+ from ecologits.status_messages import ModelArchNotReleasedWarning, ModelArchMultimodalWarning
8
+ from ecologits.utils.range_value import RangeValue
9
+
10
+ from src.constants import MODEL_REPOSITORY_URL, MAIN_MODELS
11
 
12
 
13
  def clean_models_data(df, with_filter=True):
 
75
  ]
76
 
77
 
78
+ PROVIDERS_FORMAT = {
79
+ "anthropic": "Anthropic",
80
+ "cohere": "Cohere",
81
+ "google_genai": "Google",
82
+ "mistralai": "Mistral AI",
83
+ "openai": "OpenAI",
84
+ }
85
+
86
+
87
  @st.cache_data
88
+ def load_models(filter_main=True) -> pd.DataFrame:
89
+ data = []
90
+ for m in model_repository.list_models():
91
+ if filter_main and m.name not in MAIN_MODELS:
92
+ continue # Ignore "not main" models when filter is enabled
93
+
94
+ if m.architecture.type == ArchitectureTypes.DENSE:
95
+ if isinstance(m.architecture.parameters, RangeValue):
96
+ total_parameters = dict(m.architecture.parameters)
97
+ else:
98
+ total_parameters = m.architecture.parameters
99
+ active_parameters = total_parameters
100
+
101
+ elif m.architecture.type == ArchitectureTypes.MOE:
102
+ if isinstance(m.architecture.parameters.total, RangeValue):
103
+ total_parameters = dict(m.architecture.parameters.total)
104
+ else:
105
+ total_parameters = m.architecture.parameters.total
106
+
107
+ if isinstance(m.architecture.parameters.active, RangeValue):
108
+ active_parameters = dict(m.architecture.parameters.active)
109
+ else:
110
+ active_parameters = m.architecture.parameters.active
111
+
112
+ else:
113
+ continue # Ignore model
114
+
115
+ warning_arch = False
116
+ warning_multi_modal = False
117
+ for w in m.warnings:
118
+ if isinstance(w, ModelArchNotReleasedWarning):
119
+ warning_arch = True
120
+ if isinstance(w, ModelArchMultimodalWarning):
121
+ warning_multi_modal = True
122
+
123
+ data.append({
124
+ "provider": m.provider.value,
125
+ "provider_clean": PROVIDERS_FORMAT.get(m.provider.value, m.provider.value),
126
+ "name": m.name,
127
+ "name_clean": clean_model_name(m.name),
128
+ "architecture_type": m.architecture.type.value,
129
+ "total_parameters": total_parameters,
130
+ "active_parameters": active_parameters,
131
+ "warning_arch": warning_arch,
132
+ "warning_multi_modal": warning_multi_modal,
133
+ })
134
+
135
+ return pd.DataFrame(data)
136
+
137
 
138
+ def clean_model_name(model_name: str) -> str:
139
+ model_name = model_name.replace("latest", "")
140
+ model_name = model_name.replace("-", " ")
141
+ model_name = model_name.replace("_", " ")
142
+ return model_name
src/style.css CHANGED
@@ -4,7 +4,7 @@ html, body, [class*="css"] {
4
  font-family: 'Montserrat', sans-serif;
5
  font-size: 18px;
6
  font-weight: 500;
7
- color: #091747;
8
  }
9
 
10
  [data-testid="metric-container"] {
 
4
  font-family: 'Montserrat', sans-serif;
5
  font-size: 18px;
6
  font-weight: 500;
7
+ color: #062522;
8
  }
9
 
10
  [data-testid="metric-container"] {
src/utils.py CHANGED
@@ -1,12 +1,10 @@
1
  from dataclasses import dataclass
2
  from enum import Enum
3
 
4
- from ecologits.impacts.modeling import Impacts, Energy, GWP, ADPe, PE
5
 
6
- # from ecologits.tracers.utils import llm_impacts
7
  from pint import UnitRegistry, Quantity
8
  import streamlit as st
9
- import plotly.express as px
10
  import plotly.graph_objects as go
11
 
12
  #####################################################################################
@@ -15,16 +13,23 @@ import plotly.graph_objects as go
15
 
16
  u = UnitRegistry()
17
  u.define("Wh = watt_hour")
 
18
  u.define("kWh = kilowatt_hour")
19
  u.define("MWh = megawatt_hour")
20
  u.define("GWh = gigawatt_hour")
21
  u.define("TWh = terawatt_hour")
22
  u.define("gCO2eq = gram")
 
23
  u.define("kgCO2eq = kilogram")
24
  u.define("tCO2eq = metricton")
25
  u.define("kgSbeq = kilogram")
 
 
 
26
  u.define("kJ = kilojoule")
27
  u.define("MJ = megajoule")
 
 
28
  u.define("m = meter")
29
  u.define("km = kilometer")
30
  u.define("s = second")
@@ -36,17 +41,22 @@ q = u.Quantity
36
  @dataclass
37
  class QImpacts:
38
  energy: Quantity
39
- energy_min : Quantity
40
- energy_max : Quantity
41
  gwp: Quantity
42
- gwp_min : Quantity
43
- gwp_max : Quantity
44
  adpe: Quantity
45
- adpe_min : Quantity
46
- adpe_max : Quantity
47
  pe: Quantity
48
- pe_min : Quantity
49
- pe_max : Quantity
 
 
 
 
 
 
 
 
 
 
 
50
 
51
 
52
  class PhysicalActivity(str, Enum):
@@ -108,119 +118,84 @@ AIRPLANE_PARIS_NYC_GWP_EQ = q("177000 kgCO2eq")
108
  #####################################################################################
109
 
110
 
111
- def format_energy(energy: Energy) -> Quantity:
112
-
113
- val_min = q(energy.value.min, energy.unit)
114
- val_max = q(energy.value.max, energy.unit)
115
- val_mean = (val_min + val_max)/2
116
-
117
- if val_max < q("1 kWh"):
118
- val_min = val_min.to("Wh")
119
- val_max = val_max.to("Wh")
120
- val_mean = val_mean.to("Wh")
121
-
122
- return val_mean, val_min, val_max
123
 
124
 
125
- def format_gwp(gwp: GWP) -> Quantity:
126
-
127
- val_min = q(gwp.value.min, gwp.unit)
128
- val_max =q(gwp.value.max, gwp.unit)
129
- val_mean = (val_min + val_max)/2
130
-
131
- if val_max < q("1 kgCO2eq"):
132
- val_min = val_min.to("gCO2eq")
133
- val_max = val_max.to("gCO2eq")
134
- val_mean = val_mean.to("gCO2eq")
135
-
136
- return val_mean, val_min, val_max
137
-
138
-
139
- def format_adpe(adpe: ADPe) -> Quantity:
140
-
141
- val_min = q(adpe.value.min, adpe.unit)
142
- val_max = q(adpe.value.max, adpe.unit)
143
- val_mean = (val_min + val_max)/2
144
- return val_mean, val_min, val_max
145
-
146
-
147
- def format_pe(pe: PE) -> Quantity:
148
-
149
- val_min = q(pe.value.min, pe.unit)
150
- val_max = q(pe.value.max, pe.unit)
151
- val_mean = (val_min + val_max)/2
152
-
153
- if val_max < q("1 MJ"):
154
- val_min = val_min.to("kJ")
155
- val_max = val_max.to("kJ")
156
- val_mean = val_mean.to("kJ")
157
-
158
- return val_mean, val_min, val_max
159
-
160
-
161
- def format_impacts(impacts: Impacts) -> QImpacts:
162
- energy, energy_min, energy_max = format_energy(impacts.energy)
163
- gwp, gwp_min, gwp_max = format_gwp(impacts.gwp)
164
- adpe, adpe_min, adpe_max = format_adpe(impacts.adpe)
165
- pe, pe_min, pe_max = format_pe(impacts.pe)
166
- return QImpacts(
167
- energy= energy,
168
- energy_min=energy_min,
169
- energy_max=energy_max,
170
- gwp = gwp,
171
- gwp_min = gwp_min,
172
- gwp_max = gwp_max,
173
- adpe = adpe,
174
- adpe_min = adpe_min,
175
- adpe_max = adpe_max,
176
- pe = pe,
177
- pe_min = pe_min,
178
- pe_max = pe_max
179
- ), impacts.usage, impacts.embodied
180
-
181
-
182
- def split_impacts_u_e(impacts: Impacts) -> QImpacts:
183
- return impacts.usage, impacts.embodied
184
-
185
-
186
- def average_range_impacts(x):
187
- if isinstance(x, float):
188
- return x
189
- else:
190
- return (x.max + x.min) / 2
191
-
192
-
193
- def format_impacts_expert(impacts: Impacts, display_range: bool) -> QImpacts:
194
- if display_range:
195
- return (
196
- QImpacts(
197
- energy=format_energy(impacts.energy),
198
- gwp=format_gwp(impacts.gwp),
199
- adpe=format_adpe(impacts.adpe),
200
- pe=format_pe(impacts.pe),
201
- ),
202
- impacts.usage,
203
- impacts.embodied,
204
- )
205
 
206
  else:
207
- energy = {
208
- "value": (impacts.energy.value.max + impacts.energy.value.min) / 2,
209
- "unit": impacts.energy.unit,
210
- }
211
- gwp = (impacts.gwp.value.max + impacts.gwp.value.min) / 2
212
- adpe = (impacts.adpe.value.max + impacts.adpe.value.min) / 2
213
- pe = (impacts.pe.value.max + impacts.pe.value.min) / 2
214
- return (
215
- QImpacts(
216
- energy=format_energy(energy),
217
- gwp=format_gwp(gwp),
218
- adpe=format_adpe(adpe),
219
- pe=format_pe(pe),
220
- ),
221
- impacts.usage,
222
- impacts.embodied,
223
- )
 
 
 
 
 
 
 
224
 
225
 
226
  #####################################################################################
@@ -280,7 +255,7 @@ def format_energy_eq_electricity_consumption_ireland(energy: Quantity) -> Quanti
280
  def format_gwp_eq_airplane_paris_nyc(gwp: Quantity) -> Quantity:
281
  gwp_eq = gwp * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR
282
  gwp_eq = gwp_eq.to("kgCO2eq")
283
- return gwp_eq / AIRPLANE_PARIS_NYC_GWP_EQ####################################################################################### MODELS PARAMETER####################################################################################
284
 
285
  #####################################################################################
286
  ### VISUALIZATIONS
@@ -339,4 +314,4 @@ def range_plot (mean_val, min_val, max_val, unit):
339
  )
340
 
341
  # Show the plot in Streamlit
342
- st.plotly_chart(fig, use_container_width=True)
 
1
  from dataclasses import dataclass
2
  from enum import Enum
3
 
4
+ from ecologits.impacts.modeling import Impacts, Energy, GWP, ADPe, PE, WCF, Usage, Embodied
5
 
 
6
  from pint import UnitRegistry, Quantity
7
  import streamlit as st
 
8
  import plotly.graph_objects as go
9
 
10
  #####################################################################################
 
13
 
14
  u = UnitRegistry()
15
  u.define("Wh = watt_hour")
16
+ u.define("mWh = milliwatt_hour")
17
  u.define("kWh = kilowatt_hour")
18
  u.define("MWh = megawatt_hour")
19
  u.define("GWh = gigawatt_hour")
20
  u.define("TWh = terawatt_hour")
21
  u.define("gCO2eq = gram")
22
+ u.define("mgCO2eq = milligram")
23
  u.define("kgCO2eq = kilogram")
24
  u.define("tCO2eq = metricton")
25
  u.define("kgSbeq = kilogram")
26
+ u.define("gSbeq = gram")
27
+ u.define("mgSbeq = milligram")
28
+ u.define("µgSbeq = microgram")
29
  u.define("kJ = kilojoule")
30
  u.define("MJ = megajoule")
31
+ u.define("L = liter")
32
+ u.define("mL = milliliter")
33
  u.define("m = meter")
34
  u.define("km = kilometer")
35
  u.define("s = second")
 
41
  @dataclass
42
  class QImpacts:
43
  energy: Quantity
 
 
44
  gwp: Quantity
 
 
45
  adpe: Quantity
 
 
46
  pe: Quantity
47
+ wcf: Quantity
48
+ ranges: bool = False
49
+ energy_min: Quantity | None = None
50
+ energy_max: Quantity | None = None
51
+ gwp_min: Quantity | None = None
52
+ gwp_max: Quantity | None = None
53
+ adpe_min: Quantity | None = None
54
+ adpe_max: Quantity | None = None
55
+ pe_min: Quantity | None = None
56
+ pe_max: Quantity | None = None
57
+ wcf_min: Quantity | None = None
58
+ wcf_max: Quantity | None = None
59
+
60
 
61
 
62
  class PhysicalActivity(str, Enum):
 
118
  #####################################################################################
119
 
120
 
121
+ def format_energy(energy_value: float, energy_unit = Energy(value=0.).unit) -> Quantity:
122
+ val = q(energy_value, energy_unit)
123
+ if val < q("1 kWh"):
124
+ val = val.to("Wh")
125
+ if val < q("1 Wh"):
126
+ val = val.to("mWh")
127
+ return val
 
 
 
 
 
128
 
129
 
130
+ def format_gwp(gwp_value: float, gwp_unit = GWP(value=0.).unit) -> Quantity:
131
+ val = q(gwp_value, gwp_unit)
132
+ if val < q("1 kgCO2eq"):
133
+ val = val.to("gCO2eq")
134
+ if val < q("1 gCO2eq"):
135
+ val = val.to("mgCO2eq")
136
+ return val
137
+
138
+
139
+ def format_adpe(adpe_value: float, adpe_unit = ADPe(value=0.).unit) -> Quantity:
140
+ val = q(adpe_value, adpe_unit)
141
+ if val < q("1 kgSbeq"):
142
+ val = val.to("gSbeq")
143
+ if val < q("1 gSbeq"):
144
+ val = val.to("mgSbeq")
145
+ if val < q("1 mgSbeq"):
146
+ val = val.to("µgSbeq")
147
+ return val
148
+
149
+
150
+ def format_pe(pe_value: float, pe_unit = PE(value=0.).unit) -> Quantity:
151
+ val = q(pe_value, pe_unit)
152
+ if val < q("1 MJ"):
153
+ val = val.to("kJ")
154
+ return val
155
+
156
+
157
+ def format_wcf(wcf_value: float, wcf_unit = WCF(value=0.).unit) -> Quantity:
158
+ val = q(wcf_value, wcf_unit)
159
+ if val < q("1 L"):
160
+ val = val.to("mL")
161
+ return val
162
+
163
+
164
+ def format_impacts(impacts: Impacts) -> tuple[QImpacts, Usage, Embodied]:
165
+ if isinstance(impacts.energy.value, float):
166
+ return QImpacts(
167
+ energy=format_energy(impacts.energy.value),
168
+ gwp=format_gwp(impacts.gwp.value),
169
+ adpe=format_adpe(impacts.adpe.value),
170
+ pe=format_pe(impacts.pe.value),
171
+ wcf=format_wcf(impacts.wcf.value)
172
+ ), impacts.usage, impacts.embodied
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
  else:
175
+ energy = format_energy(impacts.energy.value.mean)
176
+ gwp = format_gwp(impacts.gwp.value.mean)
177
+ adpe = format_adpe(impacts.adpe.value.mean)
178
+ pe = format_pe(impacts.pe.value.mean)
179
+ wcf = format_wcf(impacts.wcf.value.mean)
180
+
181
+ return QImpacts(
182
+ energy=energy,
183
+ energy_min=format_energy(impacts.energy.value.min).to(energy.units),
184
+ energy_max=format_energy(impacts.energy.value.max).to(energy.units),
185
+ gwp=gwp,
186
+ gwp_min=format_gwp(impacts.gwp.value.min).to(gwp.units),
187
+ gwp_max=format_gwp(impacts.gwp.value.max).to(gwp.units),
188
+ adpe=adpe,
189
+ adpe_min=format_adpe(impacts.adpe.value.min).to(adpe.units),
190
+ adpe_max=format_adpe(impacts.adpe.value.max).to(adpe.units),
191
+ pe=pe,
192
+ pe_min=format_pe(impacts.pe.value.min).to(pe.units),
193
+ pe_max=format_pe(impacts.pe.value.max).to(pe.units),
194
+ wcf=wcf,
195
+ wcf_min=format_wcf(impacts.wcf.value.min).to(wcf.units),
196
+ wcf_max=format_wcf(impacts.wcf.value.max).to(wcf.units),
197
+ ranges=True
198
+ ), impacts.usage, impacts.embodied
199
 
200
 
201
  #####################################################################################
 
255
  def format_gwp_eq_airplane_paris_nyc(gwp: Quantity) -> Quantity:
256
  gwp_eq = gwp * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR
257
  gwp_eq = gwp_eq.to("kgCO2eq")
258
+ return gwp_eq / AIRPLANE_PARIS_NYC_GWP_EQ
259
 
260
  #####################################################################################
261
  ### VISUALIZATIONS
 
314
  )
315
 
316
  # Show the plot in Streamlit
317
+ st.plotly_chart(fig, use_container_width=True)
uv.lock CHANGED
@@ -1,5 +1,5 @@
1
  version = 1
2
- revision = 2
3
  requires-python = ">=3.11"
4
  resolution-markers = [
5
  "python_full_version >= '3.12'",
@@ -31,20 +31,6 @@ wheels = [
31
  { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
32
  ]
33
 
34
- [[package]]
35
- name = "anyio"
36
- version = "4.9.0"
37
- source = { registry = "https://pypi.org/simple" }
38
- dependencies = [
39
- { name = "idna" },
40
- { name = "sniffio" },
41
- { name = "typing-extensions", marker = "python_full_version < '3.13'" },
42
- ]
43
- sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" }
44
- wheels = [
45
- { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" },
46
- ]
47
-
48
  [[package]]
49
  name = "attrs"
50
  version = "25.3.0"
@@ -152,20 +138,13 @@ wheels = [
152
 
153
  [[package]]
154
  name = "ecologits"
155
- version = "0.7.3"
156
- source = { registry = "https://pypi.org/simple" }
157
  dependencies = [
158
- { name = "httpx" },
159
  { name = "packaging" },
160
  { name = "pydantic" },
161
- { name = "requests" },
162
- { name = "tqdm" },
163
  { name = "wrapt" },
164
  ]
165
- sdist = { url = "https://files.pythonhosted.org/packages/a4/99/6c7855fecbf28f90a7add8db581b7da700709765d128842303c28133b0a1/ecologits-0.7.3.tar.gz", hash = "sha256:ec6294eb0d0e271effe5f913dd65150da040e438738d960098e783cb1894e277", size = 33335, upload-time = "2025-07-15T17:52:26.27Z" }
166
- wheels = [
167
- { url = "https://files.pythonhosted.org/packages/f5/b1/2459cc5385ff3cb7467cf10b7ec94b54685920563b7030280c665d190d40/ecologits-0.7.3-py3-none-any.whl", hash = "sha256:91c1b91800333dbfd710a4411278d6f71c9c8f0efa3942144f8eb7cb65f19e14", size = 42390, upload-time = "2025-07-15T17:52:24.954Z" },
168
- ]
169
 
170
  [[package]]
171
  name = "ecologits-calculator"
@@ -179,15 +158,23 @@ dependencies = [
179
  { name = "tiktoken" },
180
  ]
181
 
 
 
 
 
 
182
  [package.metadata]
183
  requires-dist = [
184
- { name = "ecologits", specifier = ">=0.7.3,<0.8.0" },
185
  { name = "pint", specifier = ">=0.24.4" },
186
  { name = "plotly", specifier = ">=6.2.0" },
187
  { name = "streamlit", specifier = ">=1.47.1" },
188
  { name = "tiktoken", specifier = ">=0.9.0" },
189
  ]
190
 
 
 
 
191
  [[package]]
192
  name = "flexcache"
193
  version = "0.3"
@@ -236,43 +223,6 @@ wheels = [
236
  { url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" },
237
  ]
238
 
239
- [[package]]
240
- name = "h11"
241
- version = "0.16.0"
242
- source = { registry = "https://pypi.org/simple" }
243
- sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
244
- wheels = [
245
- { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
246
- ]
247
-
248
- [[package]]
249
- name = "httpcore"
250
- version = "1.0.9"
251
- source = { registry = "https://pypi.org/simple" }
252
- dependencies = [
253
- { name = "certifi" },
254
- { name = "h11" },
255
- ]
256
- sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
257
- wheels = [
258
- { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
259
- ]
260
-
261
- [[package]]
262
- name = "httpx"
263
- version = "0.28.1"
264
- source = { registry = "https://pypi.org/simple" }
265
- dependencies = [
266
- { name = "anyio" },
267
- { name = "certifi" },
268
- { name = "httpcore" },
269
- { name = "idna" },
270
- ]
271
- sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
272
- wheels = [
273
- { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
274
- ]
275
-
276
  [[package]]
277
  name = "idna"
278
  version = "3.10"
@@ -682,7 +632,7 @@ wheels = [
682
 
683
  [[package]]
684
  name = "pydantic"
685
- version = "2.11.7"
686
  source = { registry = "https://pypi.org/simple" }
687
  dependencies = [
688
  { name = "annotated-types" },
@@ -690,74 +640,98 @@ dependencies = [
690
  { name = "typing-extensions" },
691
  { name = "typing-inspection" },
692
  ]
693
- sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" }
694
  wheels = [
695
- { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" },
696
  ]
697
 
698
  [[package]]
699
  name = "pydantic-core"
700
- version = "2.33.2"
701
  source = { registry = "https://pypi.org/simple" }
702
  dependencies = [
703
  { name = "typing-extensions" },
704
  ]
705
- sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
706
  wheels = [
707
- { url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
708
- { url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
709
- { url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
710
- { url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
711
- { url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
712
- { url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
713
- { url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
714
- { url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
715
- { url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
716
- { url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
717
- { url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
718
- { url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
719
- { url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
720
- { url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
721
- { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
722
- { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
723
- { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
724
- { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
725
- { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
726
- { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
727
- { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
728
- { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
729
- { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
730
- { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
731
- { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
732
- { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
733
- { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
734
- { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
735
- { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
736
- { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
737
- { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
738
- { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
739
- { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
740
- { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
741
- { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
742
- { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
743
- { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
744
- { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
745
- { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
746
- { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
747
- { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
748
- { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
749
- { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
750
- { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
751
- { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
752
- { url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
753
- { url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
754
- { url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
755
- { url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
756
- { url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
757
- { url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
758
- { url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
759
- { url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
760
- { url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
761
  ]
762
 
763
  [[package]]
@@ -1006,15 +980,6 @@ wheels = [
1006
  { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" },
1007
  ]
1008
 
1009
- [[package]]
1010
- name = "sniffio"
1011
- version = "1.3.1"
1012
- source = { registry = "https://pypi.org/simple" }
1013
- sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
1014
- wheels = [
1015
- { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
1016
- ]
1017
-
1018
  [[package]]
1019
  name = "streamlit"
1020
  version = "1.47.1"
@@ -1111,18 +1076,6 @@ wheels = [
1111
  { url = "https://files.pythonhosted.org/packages/55/a7/535c44c7bea4578e48281d83c615219f3ab19e6abc67625ef637c73987be/tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", size = 443596, upload-time = "2025-05-22T18:15:37.433Z" },
1112
  ]
1113
 
1114
- [[package]]
1115
- name = "tqdm"
1116
- version = "4.67.1"
1117
- source = { registry = "https://pypi.org/simple" }
1118
- dependencies = [
1119
- { name = "colorama", marker = "sys_platform == 'win32'" },
1120
- ]
1121
- sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" }
1122
- wheels = [
1123
- { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" },
1124
- ]
1125
-
1126
  [[package]]
1127
  name = "typing-extensions"
1128
  version = "4.14.1"
@@ -1134,14 +1087,14 @@ wheels = [
1134
 
1135
  [[package]]
1136
  name = "typing-inspection"
1137
- version = "0.4.1"
1138
  source = { registry = "https://pypi.org/simple" }
1139
  dependencies = [
1140
  { name = "typing-extensions" },
1141
  ]
1142
- sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
1143
  wheels = [
1144
- { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
1145
  ]
1146
 
1147
  [[package]]
@@ -1168,6 +1121,15 @@ version = "6.0.0"
1168
  source = { registry = "https://pypi.org/simple" }
1169
  sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" }
1170
  wheels = [
 
 
 
 
 
 
 
 
 
1171
  { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" },
1172
  { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" },
1173
  { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" },
@@ -1182,53 +1144,59 @@ wheels = [
1182
 
1183
  [[package]]
1184
  name = "wrapt"
1185
- version = "1.17.2"
1186
  source = { registry = "https://pypi.org/simple" }
1187
- sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531, upload-time = "2025-01-14T10:35:45.465Z" }
1188
  wheels = [
1189
- { url = "https://files.pythonhosted.org/packages/cd/f7/a2aab2cbc7a665efab072344a8949a71081eed1d2f451f7f7d2b966594a2/wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58", size = 53308, upload-time = "2025-01-14T10:33:33.992Z" },
1190
- { url = "https://files.pythonhosted.org/packages/50/ff/149aba8365fdacef52b31a258c4dc1c57c79759c335eff0b3316a2664a64/wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", size = 38488, upload-time = "2025-01-14T10:33:35.264Z" },
1191
- { url = "https://files.pythonhosted.org/packages/65/46/5a917ce85b5c3b490d35c02bf71aedaa9f2f63f2d15d9949cc4ba56e8ba9/wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", size = 38776, upload-time = "2025-01-14T10:33:38.28Z" },
1192
- { url = "https://files.pythonhosted.org/packages/ca/74/336c918d2915a4943501c77566db41d1bd6e9f4dbc317f356b9a244dfe83/wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", size = 83776, upload-time = "2025-01-14T10:33:40.678Z" },
1193
- { url = "https://files.pythonhosted.org/packages/09/99/c0c844a5ccde0fe5761d4305485297f91d67cf2a1a824c5f282e661ec7ff/wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", size = 75420, upload-time = "2025-01-14T10:33:41.868Z" },
1194
- { url = "https://files.pythonhosted.org/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", size = 83199, upload-time = "2025-01-14T10:33:43.598Z" },
1195
- { url = "https://files.pythonhosted.org/packages/9d/4b/71996e62d543b0a0bd95dda485219856def3347e3e9380cc0d6cf10cfb2f/wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", size = 82307, upload-time = "2025-01-14T10:33:48.499Z" },
1196
- { url = "https://files.pythonhosted.org/packages/39/35/0282c0d8789c0dc9bcc738911776c762a701f95cfe113fb8f0b40e45c2b9/wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", size = 75025, upload-time = "2025-01-14T10:33:51.191Z" },
1197
- { url = "https://files.pythonhosted.org/packages/4f/6d/90c9fd2c3c6fee181feecb620d95105370198b6b98a0770cba090441a828/wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", size = 81879, upload-time = "2025-01-14T10:33:52.328Z" },
1198
- { url = "https://files.pythonhosted.org/packages/8f/fa/9fb6e594f2ce03ef03eddbdb5f4f90acb1452221a5351116c7c4708ac865/wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", size = 36419, upload-time = "2025-01-14T10:33:53.551Z" },
1199
- { url = "https://files.pythonhosted.org/packages/47/f8/fb1773491a253cbc123c5d5dc15c86041f746ed30416535f2a8df1f4a392/wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", size = 38773, upload-time = "2025-01-14T10:33:56.323Z" },
1200
- { url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799, upload-time = "2025-01-14T10:33:57.4Z" },
1201
- { url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821, upload-time = "2025-01-14T10:33:59.334Z" },
1202
- { url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919, upload-time = "2025-01-14T10:34:04.093Z" },
1203
- { url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721, upload-time = "2025-01-14T10:34:07.163Z" },
1204
- { url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899, upload-time = "2025-01-14T10:34:09.82Z" },
1205
- { url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222, upload-time = "2025-01-14T10:34:11.258Z" },
1206
- { url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707, upload-time = "2025-01-14T10:34:12.49Z" },
1207
- { url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685, upload-time = "2025-01-14T10:34:15.043Z" },
1208
- { url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567, upload-time = "2025-01-14T10:34:16.563Z" },
1209
- { url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672, upload-time = "2025-01-14T10:34:17.727Z" },
1210
- { url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865, upload-time = "2025-01-14T10:34:19.577Z" },
1211
- { url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800, upload-time = "2025-01-14T10:34:21.571Z" },
1212
- { url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824, upload-time = "2025-01-14T10:34:22.999Z" },
1213
- { url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920, upload-time = "2025-01-14T10:34:25.386Z" },
1214
- { url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690, upload-time = "2025-01-14T10:34:28.058Z" },
1215
- { url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861, upload-time = "2025-01-14T10:34:29.167Z" },
1216
- { url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174, upload-time = "2025-01-14T10:34:31.702Z" },
1217
- { url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721, upload-time = "2025-01-14T10:34:32.91Z" },
1218
- { url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763, upload-time = "2025-01-14T10:34:34.903Z" },
1219
- { url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585, upload-time = "2025-01-14T10:34:36.13Z" },
1220
- { url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676, upload-time = "2025-01-14T10:34:37.962Z" },
1221
- { url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871, upload-time = "2025-01-14T10:34:39.13Z" },
1222
- { url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312, upload-time = "2025-01-14T10:34:40.604Z" },
1223
- { url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062, upload-time = "2025-01-14T10:34:45.011Z" },
1224
- { url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155, upload-time = "2025-01-14T10:34:47.25Z" },
1225
- { url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471, upload-time = "2025-01-14T10:34:50.934Z" },
1226
- { url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208, upload-time = "2025-01-14T10:34:52.297Z" },
1227
- { url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339, upload-time = "2025-01-14T10:34:53.489Z" },
1228
- { url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232, upload-time = "2025-01-14T10:34:55.327Z" },
1229
- { url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476, upload-time = "2025-01-14T10:34:58.055Z" },
1230
- { url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377, upload-time = "2025-01-14T10:34:59.3Z" },
1231
- { url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986, upload-time = "2025-01-14T10:35:00.498Z" },
1232
- { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750, upload-time = "2025-01-14T10:35:03.378Z" },
1233
- { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594, upload-time = "2025-01-14T10:35:44.018Z" },
 
 
 
 
 
 
1234
  ]
 
1
  version = 1
2
+ revision = 3
3
  requires-python = ">=3.11"
4
  resolution-markers = [
5
  "python_full_version >= '3.12'",
 
31
  { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
32
  ]
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  [[package]]
35
  name = "attrs"
36
  version = "25.3.0"
 
138
 
139
  [[package]]
140
  name = "ecologits"
141
+ version = "0.8.2"
142
+ source = { git = "https://github.com/genai-impact/ecologits#81f70cf8b3e81490da226d0fa5bdaf8512e6446d" }
143
  dependencies = [
 
144
  { name = "packaging" },
145
  { name = "pydantic" },
 
 
146
  { name = "wrapt" },
147
  ]
 
 
 
 
148
 
149
  [[package]]
150
  name = "ecologits-calculator"
 
158
  { name = "tiktoken" },
159
  ]
160
 
161
+ [package.dev-dependencies]
162
+ dev = [
163
+ { name = "watchdog" },
164
+ ]
165
+
166
  [package.metadata]
167
  requires-dist = [
168
+ { name = "ecologits", git = "https://github.com/genai-impact/ecologits" },
169
  { name = "pint", specifier = ">=0.24.4" },
170
  { name = "plotly", specifier = ">=6.2.0" },
171
  { name = "streamlit", specifier = ">=1.47.1" },
172
  { name = "tiktoken", specifier = ">=0.9.0" },
173
  ]
174
 
175
+ [package.metadata.requires-dev]
176
+ dev = [{ name = "watchdog", specifier = ">=6.0.0" }]
177
+
178
  [[package]]
179
  name = "flexcache"
180
  version = "0.3"
 
223
  { url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" },
224
  ]
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  [[package]]
227
  name = "idna"
228
  version = "3.10"
 
632
 
633
  [[package]]
634
  name = "pydantic"
635
+ version = "2.12.0"
636
  source = { registry = "https://pypi.org/simple" }
637
  dependencies = [
638
  { name = "annotated-types" },
 
640
  { name = "typing-extensions" },
641
  { name = "typing-inspection" },
642
  ]
643
+ sdist = { url = "https://files.pythonhosted.org/packages/c3/da/b8a7ee04378a53f6fefefc0c5e05570a3ebfdfa0523a878bcd3b475683ee/pydantic-2.12.0.tar.gz", hash = "sha256:c1a077e6270dbfb37bfd8b498b3981e2bb18f68103720e51fa6c306a5a9af563", size = 814760, upload-time = "2025-10-07T15:58:03.467Z" }
644
  wheels = [
645
+ { url = "https://files.pythonhosted.org/packages/f4/9d/d5c855424e2e5b6b626fbc6ec514d8e655a600377ce283008b115abb7445/pydantic-2.12.0-py3-none-any.whl", hash = "sha256:f6a1da352d42790537e95e83a8bdfb91c7efbae63ffd0b86fa823899e807116f", size = 459730, upload-time = "2025-10-07T15:58:01.576Z" },
646
  ]
647
 
648
  [[package]]
649
  name = "pydantic-core"
650
+ version = "2.41.1"
651
  source = { registry = "https://pypi.org/simple" }
652
  dependencies = [
653
  { name = "typing-extensions" },
654
  ]
655
+ sdist = { url = "https://files.pythonhosted.org/packages/7d/14/12b4a0d2b0b10d8e1d9a24ad94e7bbb43335eaf29c0c4e57860e8a30734a/pydantic_core-2.41.1.tar.gz", hash = "sha256:1ad375859a6d8c356b7704ec0f547a58e82ee80bb41baa811ad710e124bc8f2f", size = 454870, upload-time = "2025-10-07T10:50:45.974Z" }
656
  wheels = [
657
+ { url = "https://files.pythonhosted.org/packages/f6/a9/ec440f02e57beabdfd804725ef1e38ac1ba00c49854d298447562e119513/pydantic_core-2.41.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4f276a6134fe1fc1daa692642a3eaa2b7b858599c49a7610816388f5e37566a1", size = 2111456, upload-time = "2025-10-06T21:10:09.824Z" },
658
+ { url = "https://files.pythonhosted.org/packages/f0/f9/6bc15bacfd8dcfc073a1820a564516d9c12a435a9a332d4cbbfd48828ddd/pydantic_core-2.41.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07588570a805296ece009c59d9a679dc08fab72fb337365afb4f3a14cfbfc176", size = 1915012, upload-time = "2025-10-06T21:10:11.599Z" },
659
+ { url = "https://files.pythonhosted.org/packages/38/8a/d9edcdcdfe80bade17bed424284427c08bea892aaec11438fa52eaeaf79c/pydantic_core-2.41.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28527e4b53400cd60ffbd9812ccb2b5135d042129716d71afd7e45bf42b855c0", size = 1973762, upload-time = "2025-10-06T21:10:13.154Z" },
660
+ { url = "https://files.pythonhosted.org/packages/d5/b3/ff225c6d49fba4279de04677c1c876fc3dc6562fd0c53e9bfd66f58c51a8/pydantic_core-2.41.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46a1c935c9228bad738c8a41de06478770927baedf581d172494ab36a6b96575", size = 2065386, upload-time = "2025-10-06T21:10:14.436Z" },
661
+ { url = "https://files.pythonhosted.org/packages/47/ba/183e8c0be4321314af3fd1ae6bfc7eafdd7a49bdea5da81c56044a207316/pydantic_core-2.41.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:447ddf56e2b7d28d200d3e9eafa936fe40485744b5a824b67039937580b3cb20", size = 2252317, upload-time = "2025-10-06T21:10:15.719Z" },
662
+ { url = "https://files.pythonhosted.org/packages/57/c5/aab61e94fd02f45c65f1f8c9ec38bb3b33fbf001a1837c74870e97462572/pydantic_core-2.41.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63892ead40c1160ac860b5debcc95c95c5a0035e543a8b5a4eac70dd22e995f4", size = 2373405, upload-time = "2025-10-06T21:10:17.017Z" },
663
+ { url = "https://files.pythonhosted.org/packages/e5/4f/3aaa3bd1ea420a15acc42d7d3ccb3b0bbc5444ae2f9dbc1959f8173e16b8/pydantic_core-2.41.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4a9543ca355e6df8fbe9c83e9faab707701e9103ae857ecb40f1c0cf8b0e94d", size = 2073794, upload-time = "2025-10-06T21:10:18.383Z" },
664
+ { url = "https://files.pythonhosted.org/packages/58/bd/e3975cdebe03ec080ef881648de316c73f2a6be95c14fc4efb2f7bdd0d41/pydantic_core-2.41.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2611bdb694116c31e551ed82e20e39a90bea9b7ad9e54aaf2d045ad621aa7a1", size = 2194430, upload-time = "2025-10-06T21:10:19.638Z" },
665
+ { url = "https://files.pythonhosted.org/packages/2b/b8/6b7e7217f147d3b3105b57fb1caec3c4f667581affdfaab6d1d277e1f749/pydantic_core-2.41.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fecc130893a9b5f7bfe230be1bb8c61fe66a19db8ab704f808cb25a82aad0bc9", size = 2154611, upload-time = "2025-10-06T21:10:21.28Z" },
666
+ { url = "https://files.pythonhosted.org/packages/fe/7b/239c2fe76bd8b7eef9ae2140d737368a3c6fea4fd27f8f6b4cde6baa3ce9/pydantic_core-2.41.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:1e2df5f8344c99b6ea5219f00fdc8950b8e6f2c422fbc1cc122ec8641fac85a1", size = 2329809, upload-time = "2025-10-06T21:10:22.678Z" },
667
+ { url = "https://files.pythonhosted.org/packages/bd/2e/77a821a67ff0786f2f14856d6bd1348992f695ee90136a145d7a445c1ff6/pydantic_core-2.41.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:35291331e9d8ed94c257bab6be1cb3a380b5eee570a2784bffc055e18040a2ea", size = 2327907, upload-time = "2025-10-06T21:10:24.447Z" },
668
+ { url = "https://files.pythonhosted.org/packages/fd/9a/b54512bb9df7f64c586b369328c30481229b70ca6a5fcbb90b715e15facf/pydantic_core-2.41.1-cp311-cp311-win32.whl", hash = "sha256:2876a095292668d753f1a868c4a57c4ac9f6acbd8edda8debe4218d5848cf42f", size = 1989964, upload-time = "2025-10-06T21:10:25.676Z" },
669
+ { url = "https://files.pythonhosted.org/packages/9d/72/63c9a4f1a5c950e65dd522d7dd67f167681f9d4f6ece3b80085a0329f08f/pydantic_core-2.41.1-cp311-cp311-win_amd64.whl", hash = "sha256:b92d6c628e9a338846a28dfe3fcdc1a3279388624597898b105e078cdfc59298", size = 2025158, upload-time = "2025-10-06T21:10:27.522Z" },
670
+ { url = "https://files.pythonhosted.org/packages/d8/16/4e2706184209f61b50c231529257c12eb6bd9eb36e99ea1272e4815d2200/pydantic_core-2.41.1-cp311-cp311-win_arm64.whl", hash = "sha256:7d82ae99409eb69d507a89835488fb657faa03ff9968a9379567b0d2e2e56bc5", size = 1972297, upload-time = "2025-10-06T21:10:28.814Z" },
671
+ { url = "https://files.pythonhosted.org/packages/ee/bc/5f520319ee1c9e25010412fac4154a72e0a40d0a19eb00281b1f200c0947/pydantic_core-2.41.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:db2f82c0ccbce8f021ad304ce35cbe02aa2f95f215cac388eed542b03b4d5eb4", size = 2099300, upload-time = "2025-10-06T21:10:30.463Z" },
672
+ { url = "https://files.pythonhosted.org/packages/31/14/010cd64c5c3814fb6064786837ec12604be0dd46df3327cf8474e38abbbd/pydantic_core-2.41.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47694a31c710ced9205d5f1e7e8af3ca57cbb8a503d98cb9e33e27c97a501601", size = 1910179, upload-time = "2025-10-06T21:10:31.782Z" },
673
+ { url = "https://files.pythonhosted.org/packages/8e/2e/23fc2a8a93efad52df302fdade0a60f471ecc0c7aac889801ac24b4c07d6/pydantic_core-2.41.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e9decce94daf47baf9e9d392f5f2557e783085f7c5e522011545d9d6858e00", size = 1957225, upload-time = "2025-10-06T21:10:33.11Z" },
674
+ { url = "https://files.pythonhosted.org/packages/b9/b6/6db08b2725b2432b9390844852e11d320281e5cea8a859c52c68001975fa/pydantic_core-2.41.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab0adafdf2b89c8b84f847780a119437a0931eca469f7b44d356f2b426dd9741", size = 2053315, upload-time = "2025-10-06T21:10:34.87Z" },
675
+ { url = "https://files.pythonhosted.org/packages/61/d9/4de44600f2d4514b44f3f3aeeda2e14931214b6b5bf52479339e801ce748/pydantic_core-2.41.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5da98cc81873f39fd56882e1569c4677940fbc12bce6213fad1ead784192d7c8", size = 2224298, upload-time = "2025-10-06T21:10:36.233Z" },
676
+ { url = "https://files.pythonhosted.org/packages/7a/ae/dbe51187a7f35fc21b283c5250571a94e36373eb557c1cba9f29a9806dcf/pydantic_core-2.41.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:209910e88afb01fd0fd403947b809ba8dba0e08a095e1f703294fda0a8fdca51", size = 2351797, upload-time = "2025-10-06T21:10:37.601Z" },
677
+ { url = "https://files.pythonhosted.org/packages/b5/a7/975585147457c2e9fb951c7c8dab56deeb6aa313f3aa72c2fc0df3f74a49/pydantic_core-2.41.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365109d1165d78d98e33c5bfd815a9b5d7d070f578caefaabcc5771825b4ecb5", size = 2074921, upload-time = "2025-10-06T21:10:38.927Z" },
678
+ { url = "https://files.pythonhosted.org/packages/62/37/ea94d1d0c01dec1b7d236c7cec9103baab0021f42500975de3d42522104b/pydantic_core-2.41.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:706abf21e60a2857acdb09502bc853ee5bce732955e7b723b10311114f033115", size = 2187767, upload-time = "2025-10-06T21:10:40.651Z" },
679
+ { url = "https://files.pythonhosted.org/packages/d3/fe/694cf9fdd3a777a618c3afd210dba7b414cb8a72b1bd29b199c2e5765fee/pydantic_core-2.41.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bf0bd5417acf7f6a7ec3b53f2109f587be176cb35f9cf016da87e6017437a72d", size = 2136062, upload-time = "2025-10-06T21:10:42.09Z" },
680
+ { url = "https://files.pythonhosted.org/packages/0f/ae/174aeabd89916fbd2988cc37b81a59e1186e952afd2a7ed92018c22f31ca/pydantic_core-2.41.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:2e71b1c6ceb9c78424ae9f63a07292fb769fb890a4e7efca5554c47f33a60ea5", size = 2317819, upload-time = "2025-10-06T21:10:43.974Z" },
681
+ { url = "https://files.pythonhosted.org/packages/65/e8/e9aecafaebf53fc456314f72886068725d6fba66f11b013532dc21259343/pydantic_core-2.41.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:80745b9770b4a38c25015b517451c817799bfb9d6499b0d13d8227ec941cb513", size = 2312267, upload-time = "2025-10-06T21:10:45.34Z" },
682
+ { url = "https://files.pythonhosted.org/packages/35/2f/1c2e71d2a052f9bb2f2df5a6a05464a0eb800f9e8d9dd800202fe31219e1/pydantic_core-2.41.1-cp312-cp312-win32.whl", hash = "sha256:83b64d70520e7890453f1aa21d66fda44e7b35f1cfea95adf7b4289a51e2b479", size = 1990927, upload-time = "2025-10-06T21:10:46.738Z" },
683
+ { url = "https://files.pythonhosted.org/packages/b1/78/562998301ff2588b9c6dcc5cb21f52fa919d6e1decc75a35055feb973594/pydantic_core-2.41.1-cp312-cp312-win_amd64.whl", hash = "sha256:377defd66ee2003748ee93c52bcef2d14fde48fe28a0b156f88c3dbf9bc49a50", size = 2034703, upload-time = "2025-10-06T21:10:48.524Z" },
684
+ { url = "https://files.pythonhosted.org/packages/b2/53/d95699ce5a5cdb44bb470bd818b848b9beadf51459fd4ea06667e8ede862/pydantic_core-2.41.1-cp312-cp312-win_arm64.whl", hash = "sha256:c95caff279d49c1d6cdfe2996e6c2ad712571d3b9caaa209a404426c326c4bde", size = 1972719, upload-time = "2025-10-06T21:10:50.256Z" },
685
+ { url = "https://files.pythonhosted.org/packages/27/8a/6d54198536a90a37807d31a156642aae7a8e1263ed9fe6fc6245defe9332/pydantic_core-2.41.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70e790fce5f05204ef4403159857bfcd587779da78627b0babb3654f75361ebf", size = 2105825, upload-time = "2025-10-06T21:10:51.719Z" },
686
+ { url = "https://files.pythonhosted.org/packages/4f/2e/4784fd7b22ac9c8439db25bf98ffed6853d01e7e560a346e8af821776ccc/pydantic_core-2.41.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9cebf1ca35f10930612d60bd0f78adfacee824c30a880e3534ba02c207cceceb", size = 1910126, upload-time = "2025-10-06T21:10:53.145Z" },
687
+ { url = "https://files.pythonhosted.org/packages/f3/92/31eb0748059ba5bd0aa708fb4bab9fcb211461ddcf9e90702a6542f22d0d/pydantic_core-2.41.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:170406a37a5bc82c22c3274616bf6f17cc7df9c4a0a0a50449e559cb755db669", size = 1961472, upload-time = "2025-10-06T21:10:55.754Z" },
688
+ { url = "https://files.pythonhosted.org/packages/ab/91/946527792275b5c4c7dde4cfa3e81241bf6900e9fee74fb1ba43e0c0f1ab/pydantic_core-2.41.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12d4257fc9187a0ccd41b8b327d6a4e57281ab75e11dda66a9148ef2e1fb712f", size = 2063230, upload-time = "2025-10-06T21:10:57.179Z" },
689
+ { url = "https://files.pythonhosted.org/packages/31/5d/a35c5d7b414e5c0749f1d9f0d159ee2ef4bab313f499692896b918014ee3/pydantic_core-2.41.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a75a33b4db105dd1c8d57839e17ee12db8d5ad18209e792fa325dbb4baeb00f4", size = 2229469, upload-time = "2025-10-06T21:10:59.409Z" },
690
+ { url = "https://files.pythonhosted.org/packages/21/4d/8713737c689afa57ecfefe38db78259d4484c97aa494979e6a9d19662584/pydantic_core-2.41.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08a589f850803a74e0fcb16a72081cafb0d72a3cdda500106942b07e76b7bf62", size = 2347986, upload-time = "2025-10-06T21:11:00.847Z" },
691
+ { url = "https://files.pythonhosted.org/packages/f6/ec/929f9a3a5ed5cda767081494bacd32f783e707a690ce6eeb5e0730ec4986/pydantic_core-2.41.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a97939d6ea44763c456bd8a617ceada2c9b96bb5b8ab3dfa0d0827df7619014", size = 2072216, upload-time = "2025-10-06T21:11:02.43Z" },
692
+ { url = "https://files.pythonhosted.org/packages/26/55/a33f459d4f9cc8786d9db42795dbecc84fa724b290d7d71ddc3d7155d46a/pydantic_core-2.41.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2ae423c65c556f09569524b80ffd11babff61f33055ef9773d7c9fabc11ed8d", size = 2193047, upload-time = "2025-10-06T21:11:03.787Z" },
693
+ { url = "https://files.pythonhosted.org/packages/77/af/d5c6959f8b089f2185760a2779079e3c2c411bfc70ea6111f58367851629/pydantic_core-2.41.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:4dc703015fbf8764d6a8001c327a87f1823b7328d40b47ce6000c65918ad2b4f", size = 2140613, upload-time = "2025-10-06T21:11:05.607Z" },
694
+ { url = "https://files.pythonhosted.org/packages/58/e5/2c19bd2a14bffe7fabcf00efbfbd3ac430aaec5271b504a938ff019ac7be/pydantic_core-2.41.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:968e4ffdfd35698a5fe659e5e44c508b53664870a8e61c8f9d24d3d145d30257", size = 2327641, upload-time = "2025-10-06T21:11:07.143Z" },
695
+ { url = "https://files.pythonhosted.org/packages/93/ef/e0870ccda798c54e6b100aff3c4d49df5458fd64217e860cb9c3b0a403f4/pydantic_core-2.41.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:fff2b76c8e172d34771cd4d4f0ade08072385310f214f823b5a6ad4006890d32", size = 2318229, upload-time = "2025-10-06T21:11:08.73Z" },
696
+ { url = "https://files.pythonhosted.org/packages/b1/4b/c3b991d95f5deb24d0bd52e47bcf716098fa1afe0ce2d4bd3125b38566ba/pydantic_core-2.41.1-cp313-cp313-win32.whl", hash = "sha256:a38a5263185407ceb599f2f035faf4589d57e73c7146d64f10577f6449e8171d", size = 1997911, upload-time = "2025-10-06T21:11:10.329Z" },
697
+ { url = "https://files.pythonhosted.org/packages/a7/ce/5c316fd62e01f8d6be1b7ee6b54273214e871772997dc2c95e204997a055/pydantic_core-2.41.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42ae7fd6760782c975897e1fdc810f483b021b32245b0105d40f6e7a3803e4b", size = 2034301, upload-time = "2025-10-06T21:11:12.113Z" },
698
+ { url = "https://files.pythonhosted.org/packages/29/41/902640cfd6a6523194123e2c3373c60f19006447f2fb06f76de4e8466c5b/pydantic_core-2.41.1-cp313-cp313-win_arm64.whl", hash = "sha256:ad4111acc63b7384e205c27a2f15e23ac0ee21a9d77ad6f2e9cb516ec90965fb", size = 1977238, upload-time = "2025-10-06T21:11:14.1Z" },
699
+ { url = "https://files.pythonhosted.org/packages/04/04/28b040e88c1b89d851278478842f0bdf39c7a05da9e850333c6c8cbe7dfa/pydantic_core-2.41.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:440d0df7415b50084a4ba9d870480c16c5f67c0d1d4d5119e3f70925533a0edc", size = 1875626, upload-time = "2025-10-06T21:11:15.69Z" },
700
+ { url = "https://files.pythonhosted.org/packages/d6/58/b41dd3087505220bb58bc81be8c3e8cbc037f5710cd3c838f44f90bdd704/pydantic_core-2.41.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71eaa38d342099405dae6484216dcf1e8e4b0bebd9b44a4e08c9b43db6a2ab67", size = 2045708, upload-time = "2025-10-06T21:11:17.258Z" },
701
+ { url = "https://files.pythonhosted.org/packages/d7/b8/760f23754e40bf6c65b94a69b22c394c24058a0ef7e2aa471d2e39219c1a/pydantic_core-2.41.1-cp313-cp313t-win_amd64.whl", hash = "sha256:555ecf7e50f1161d3f693bc49f23c82cf6cdeafc71fa37a06120772a09a38795", size = 1997171, upload-time = "2025-10-06T21:11:18.822Z" },
702
+ { url = "https://files.pythonhosted.org/packages/41/12/cec246429ddfa2778d2d6301eca5362194dc8749ecb19e621f2f65b5090f/pydantic_core-2.41.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:05226894a26f6f27e1deb735d7308f74ef5fa3a6de3e0135bb66cdcaee88f64b", size = 2107836, upload-time = "2025-10-06T21:11:20.432Z" },
703
+ { url = "https://files.pythonhosted.org/packages/20/39/baba47f8d8b87081302498e610aefc37142ce6a1cc98b2ab6b931a162562/pydantic_core-2.41.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:85ff7911c6c3e2fd8d3779c50925f6406d770ea58ea6dde9c230d35b52b16b4a", size = 1904449, upload-time = "2025-10-06T21:11:22.185Z" },
704
+ { url = "https://files.pythonhosted.org/packages/50/32/9a3d87cae2c75a5178334b10358d631bd094b916a00a5993382222dbfd92/pydantic_core-2.41.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47f1f642a205687d59b52dc1a9a607f45e588f5a2e9eeae05edd80c7a8c47674", size = 1961750, upload-time = "2025-10-06T21:11:24.348Z" },
705
+ { url = "https://files.pythonhosted.org/packages/27/42/a96c9d793a04cf2a9773bff98003bb154087b94f5530a2ce6063ecfec583/pydantic_core-2.41.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df11c24e138876ace5ec6043e5cae925e34cf38af1a1b3d63589e8f7b5f5cdc4", size = 2063305, upload-time = "2025-10-06T21:11:26.556Z" },
706
+ { url = "https://files.pythonhosted.org/packages/3e/8d/028c4b7d157a005b1f52c086e2d4b0067886b213c86220c1153398dbdf8f/pydantic_core-2.41.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f0bf7f5c8f7bf345c527e8a0d72d6b26eda99c1227b0c34e7e59e181260de31", size = 2228959, upload-time = "2025-10-06T21:11:28.426Z" },
707
+ { url = "https://files.pythonhosted.org/packages/08/f7/ee64cda8fcc9ca3f4716e6357144f9ee71166775df582a1b6b738bf6da57/pydantic_core-2.41.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82b887a711d341c2c47352375d73b029418f55b20bd7815446d175a70effa706", size = 2345421, upload-time = "2025-10-06T21:11:30.226Z" },
708
+ { url = "https://files.pythonhosted.org/packages/13/c0/e8ec05f0f5ee7a3656973ad9cd3bc73204af99f6512c1a4562f6fb4b3f7d/pydantic_core-2.41.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5f1d5d6bbba484bdf220c72d8ecd0be460f4bd4c5e534a541bb2cd57589fb8b", size = 2065288, upload-time = "2025-10-06T21:11:32.019Z" },
709
+ { url = "https://files.pythonhosted.org/packages/0a/25/d77a73ff24e2e4fcea64472f5e39b0402d836da9b08b5361a734d0153023/pydantic_core-2.41.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bf1917385ebe0f968dc5c6ab1375886d56992b93ddfe6bf52bff575d03662be", size = 2189759, upload-time = "2025-10-06T21:11:33.753Z" },
710
+ { url = "https://files.pythonhosted.org/packages/66/45/4a4ebaaae12a740552278d06fe71418c0f2869537a369a89c0e6723b341d/pydantic_core-2.41.1-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:4f94f3ab188f44b9a73f7295663f3ecb8f2e2dd03a69c8f2ead50d37785ecb04", size = 2140747, upload-time = "2025-10-06T21:11:35.781Z" },
711
+ { url = "https://files.pythonhosted.org/packages/da/6d/b727ce1022f143194a36593243ff244ed5a1eb3c9122296bf7e716aa37ba/pydantic_core-2.41.1-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:3925446673641d37c30bd84a9d597e49f72eacee8b43322c8999fa17d5ae5bc4", size = 2327416, upload-time = "2025-10-06T21:11:37.75Z" },
712
+ { url = "https://files.pythonhosted.org/packages/6f/8c/02df9d8506c427787059f87c6c7253435c6895e12472a652d9616ee0fc95/pydantic_core-2.41.1-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:49bd51cc27adb980c7b97357ae036ce9b3c4d0bb406e84fbe16fb2d368b602a8", size = 2318138, upload-time = "2025-10-06T21:11:39.463Z" },
713
+ { url = "https://files.pythonhosted.org/packages/98/67/0cf429a7d6802536941f430e6e3243f6d4b68f41eeea4b242372f1901794/pydantic_core-2.41.1-cp314-cp314-win32.whl", hash = "sha256:a31ca0cd0e4d12ea0df0077df2d487fc3eb9d7f96bbb13c3c5b88dcc21d05159", size = 1998429, upload-time = "2025-10-06T21:11:41.989Z" },
714
+ { url = "https://files.pythonhosted.org/packages/38/60/742fef93de5d085022d2302a6317a2b34dbfe15258e9396a535c8a100ae7/pydantic_core-2.41.1-cp314-cp314-win_amd64.whl", hash = "sha256:1b5c4374a152e10a22175d7790e644fbd8ff58418890e07e2073ff9d4414efae", size = 2028870, upload-time = "2025-10-06T21:11:43.66Z" },
715
+ { url = "https://files.pythonhosted.org/packages/31/38/cdd8ccb8555ef7720bd7715899bd6cfbe3c29198332710e1b61b8f5dd8b8/pydantic_core-2.41.1-cp314-cp314-win_arm64.whl", hash = "sha256:4fee76d757639b493eb600fba668f1e17475af34c17dd61db7a47e824d464ca9", size = 1974275, upload-time = "2025-10-06T21:11:45.476Z" },
716
+ { url = "https://files.pythonhosted.org/packages/e7/7e/8ac10ccb047dc0221aa2530ec3c7c05ab4656d4d4bd984ee85da7f3d5525/pydantic_core-2.41.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f9b9c968cfe5cd576fdd7361f47f27adeb120517e637d1b189eea1c3ece573f4", size = 1875124, upload-time = "2025-10-06T21:11:47.591Z" },
717
+ { url = "https://files.pythonhosted.org/packages/c3/e4/7d9791efeb9c7d97e7268f8d20e0da24d03438a7fa7163ab58f1073ba968/pydantic_core-2.41.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1ebc7ab67b856384aba09ed74e3e977dded40e693de18a4f197c67d0d4e6d8e", size = 2043075, upload-time = "2025-10-06T21:11:49.542Z" },
718
+ { url = "https://files.pythonhosted.org/packages/2d/c3/3f6e6b2342ac11ac8cd5cb56e24c7b14afa27c010e82a765ffa5f771884a/pydantic_core-2.41.1-cp314-cp314t-win_amd64.whl", hash = "sha256:8ae0dc57b62a762985bc7fbf636be3412394acc0ddb4ade07fe104230f1b9762", size = 1995341, upload-time = "2025-10-06T21:11:51.497Z" },
719
+ { url = "https://files.pythonhosted.org/packages/16/89/d0afad37ba25f5801735af1472e650b86baad9fe807a42076508e4824a2a/pydantic_core-2.41.1-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:68f2251559b8efa99041bb63571ec7cdd2d715ba74cc82b3bc9eff824ebc8bf0", size = 2124001, upload-time = "2025-10-07T10:49:54.369Z" },
720
+ { url = "https://files.pythonhosted.org/packages/8e/c4/08609134b34520568ddebb084d9ed0a2a3f5f52b45739e6e22cb3a7112eb/pydantic_core-2.41.1-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:c7bc140c596097cb53b30546ca257dbe3f19282283190b1b5142928e5d5d3a20", size = 1941841, upload-time = "2025-10-07T10:49:56.248Z" },
721
+ { url = "https://files.pythonhosted.org/packages/2a/43/94a4877094e5fe19a3f37e7e817772263e2c573c94f1e3fa2b1eee56ef3b/pydantic_core-2.41.1-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2896510fce8f4725ec518f8b9d7f015a00db249d2fd40788f442af303480063d", size = 1961129, upload-time = "2025-10-07T10:49:58.298Z" },
722
+ { url = "https://files.pythonhosted.org/packages/a2/30/23a224d7e25260eb5f69783a63667453037e07eb91ff0e62dabaadd47128/pydantic_core-2.41.1-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ced20e62cfa0f496ba68fa5d6c7ee71114ea67e2a5da3114d6450d7f4683572a", size = 2148770, upload-time = "2025-10-07T10:49:59.959Z" },
723
+ { url = "https://files.pythonhosted.org/packages/2b/3e/a51c5f5d37b9288ba30683d6e96f10fa8f1defad1623ff09f1020973b577/pydantic_core-2.41.1-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:b04fa9ed049461a7398138c604b00550bc89e3e1151d84b81ad6dc93e39c4c06", size = 2115344, upload-time = "2025-10-07T10:50:02.466Z" },
724
+ { url = "https://files.pythonhosted.org/packages/5a/bd/389504c9e0600ef4502cd5238396b527afe6ef8981a6a15cd1814fc7b434/pydantic_core-2.41.1-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b3b7d9cfbfdc43c80a16638c6dc2768e3956e73031fca64e8e1a3ae744d1faeb", size = 1927994, upload-time = "2025-10-07T10:50:04.379Z" },
725
+ { url = "https://files.pythonhosted.org/packages/ff/9c/5111c6b128861cb792a4c082677e90dac4f2e090bb2e2fe06aa5b2d39027/pydantic_core-2.41.1-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eec83fc6abef04c7f9bec616e2d76ee9a6a4ae2a359b10c21d0f680e24a247ca", size = 1959394, upload-time = "2025-10-07T10:50:06.335Z" },
726
+ { url = "https://files.pythonhosted.org/packages/14/3f/cfec8b9a0c48ce5d64409ec5e1903cb0b7363da38f14b41de2fcb3712700/pydantic_core-2.41.1-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6771a2d9f83c4038dfad5970a3eef215940682b2175e32bcc817bdc639019b28", size = 2147365, upload-time = "2025-10-07T10:50:07.978Z" },
727
+ { url = "https://files.pythonhosted.org/packages/e6/6c/fa3e45c2b054a1e627a89a364917f12cbe3abc3e91b9004edaae16e7b3c5/pydantic_core-2.41.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:af2385d3f98243fb733862f806c5bb9122e5fba05b373e3af40e3c82d711cef1", size = 2112094, upload-time = "2025-10-07T10:50:25.513Z" },
728
+ { url = "https://files.pythonhosted.org/packages/e5/17/7eebc38b4658cc8e6902d0befc26388e4c2a5f2e179c561eeb43e1922c7b/pydantic_core-2.41.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6550617a0c2115be56f90c31a5370261d8ce9dbf051c3ed53b51172dd34da696", size = 1935300, upload-time = "2025-10-07T10:50:27.715Z" },
729
+ { url = "https://files.pythonhosted.org/packages/2b/00/9fe640194a1717a464ab861d43595c268830f98cb1e2705aa134b3544b70/pydantic_core-2.41.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc17b6ecf4983d298686014c92ebc955a9f9baf9f57dad4065e7906e7bee6222", size = 1970417, upload-time = "2025-10-07T10:50:29.573Z" },
730
+ { url = "https://files.pythonhosted.org/packages/b2/ad/f4cdfaf483b78ee65362363e73b6b40c48e067078d7b146e8816d5945ad6/pydantic_core-2.41.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:42ae9352cf211f08b04ea110563d6b1e415878eea5b4c70f6bdb17dca3b932d2", size = 2190745, upload-time = "2025-10-07T10:50:31.48Z" },
731
+ { url = "https://files.pythonhosted.org/packages/cb/c1/18f416d40a10f44e9387497ba449f40fdb1478c61ba05c4b6bdb82300362/pydantic_core-2.41.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e82947de92068b0a21681a13dd2102387197092fbe7defcfb8453e0913866506", size = 2150888, upload-time = "2025-10-07T10:50:33.477Z" },
732
+ { url = "https://files.pythonhosted.org/packages/42/30/134c8a921630d8a88d6f905a562495a6421e959a23c19b0f49b660801d67/pydantic_core-2.41.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e244c37d5471c9acdcd282890c6c4c83747b77238bfa19429b8473586c907656", size = 2324489, upload-time = "2025-10-07T10:50:36.48Z" },
733
+ { url = "https://files.pythonhosted.org/packages/9c/48/a9263aeaebdec81e941198525b43edb3b44f27cfa4cb8005b8d3eb8dec72/pydantic_core-2.41.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1e798b4b304a995110d41ec93653e57975620ccb2842ba9420037985e7d7284e", size = 2322763, upload-time = "2025-10-07T10:50:38.751Z" },
734
+ { url = "https://files.pythonhosted.org/packages/1d/62/755d2bd2593f701c5839fc084e9c2c5e2418f460383ad04e3b5d0befc3ca/pydantic_core-2.41.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f1fc716c0eb1663c59699b024428ad5ec2bcc6b928527b8fe28de6cb89f47efb", size = 2144046, upload-time = "2025-10-07T10:50:40.686Z" },
735
  ]
736
 
737
  [[package]]
 
980
  { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" },
981
  ]
982
 
 
 
 
 
 
 
 
 
 
983
  [[package]]
984
  name = "streamlit"
985
  version = "1.47.1"
 
1076
  { url = "https://files.pythonhosted.org/packages/55/a7/535c44c7bea4578e48281d83c615219f3ab19e6abc67625ef637c73987be/tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", size = 443596, upload-time = "2025-05-22T18:15:37.433Z" },
1077
  ]
1078
 
 
 
 
 
 
 
 
 
 
 
 
 
1079
  [[package]]
1080
  name = "typing-extensions"
1081
  version = "4.14.1"
 
1087
 
1088
  [[package]]
1089
  name = "typing-inspection"
1090
+ version = "0.4.2"
1091
  source = { registry = "https://pypi.org/simple" }
1092
  dependencies = [
1093
  { name = "typing-extensions" },
1094
  ]
1095
+ sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
1096
  wheels = [
1097
+ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
1098
  ]
1099
 
1100
  [[package]]
 
1121
  source = { registry = "https://pypi.org/simple" }
1122
  sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" }
1123
  wheels = [
1124
+ { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" },
1125
+ { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" },
1126
+ { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" },
1127
+ { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" },
1128
+ { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" },
1129
+ { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" },
1130
+ { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" },
1131
+ { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" },
1132
+ { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" },
1133
  { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" },
1134
  { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" },
1135
  { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" },
 
1144
 
1145
  [[package]]
1146
  name = "wrapt"
1147
+ version = "1.17.3"
1148
  source = { registry = "https://pypi.org/simple" }
1149
+ sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" }
1150
  wheels = [
1151
+ { url = "https://files.pythonhosted.org/packages/52/db/00e2a219213856074a213503fdac0511203dceefff26e1daa15250cc01a0/wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7", size = 53482, upload-time = "2025-08-12T05:51:45.79Z" },
1152
+ { url = "https://files.pythonhosted.org/packages/5e/30/ca3c4a5eba478408572096fe9ce36e6e915994dd26a4e9e98b4f729c06d9/wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85", size = 38674, upload-time = "2025-08-12T05:51:34.629Z" },
1153
+ { url = "https://files.pythonhosted.org/packages/31/25/3e8cc2c46b5329c5957cec959cb76a10718e1a513309c31399a4dad07eb3/wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f", size = 38959, upload-time = "2025-08-12T05:51:56.074Z" },
1154
+ { url = "https://files.pythonhosted.org/packages/5d/8f/a32a99fc03e4b37e31b57cb9cefc65050ea08147a8ce12f288616b05ef54/wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311", size = 82376, upload-time = "2025-08-12T05:52:32.134Z" },
1155
+ { url = "https://files.pythonhosted.org/packages/31/57/4930cb8d9d70d59c27ee1332a318c20291749b4fba31f113c2f8ac49a72e/wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1", size = 83604, upload-time = "2025-08-12T05:52:11.663Z" },
1156
+ { url = "https://files.pythonhosted.org/packages/a8/f3/1afd48de81d63dd66e01b263a6fbb86e1b5053b419b9b33d13e1f6d0f7d0/wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5", size = 82782, upload-time = "2025-08-12T05:52:12.626Z" },
1157
+ { url = "https://files.pythonhosted.org/packages/1e/d7/4ad5327612173b144998232f98a85bb24b60c352afb73bc48e3e0d2bdc4e/wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2", size = 82076, upload-time = "2025-08-12T05:52:33.168Z" },
1158
+ { url = "https://files.pythonhosted.org/packages/bb/59/e0adfc831674a65694f18ea6dc821f9fcb9ec82c2ce7e3d73a88ba2e8718/wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89", size = 36457, upload-time = "2025-08-12T05:53:03.936Z" },
1159
+ { url = "https://files.pythonhosted.org/packages/83/88/16b7231ba49861b6f75fc309b11012ede4d6b0a9c90969d9e0db8d991aeb/wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77", size = 38745, upload-time = "2025-08-12T05:53:02.885Z" },
1160
+ { url = "https://files.pythonhosted.org/packages/9a/1e/c4d4f3398ec073012c51d1c8d87f715f56765444e1a4b11e5180577b7e6e/wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a", size = 36806, upload-time = "2025-08-12T05:52:53.368Z" },
1161
+ { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" },
1162
+ { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" },
1163
+ { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" },
1164
+ { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" },
1165
+ { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" },
1166
+ { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" },
1167
+ { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" },
1168
+ { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" },
1169
+ { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" },
1170
+ { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" },
1171
+ { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" },
1172
+ { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" },
1173
+ { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" },
1174
+ { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" },
1175
+ { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" },
1176
+ { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" },
1177
+ { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" },
1178
+ { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" },
1179
+ { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" },
1180
+ { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" },
1181
+ { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" },
1182
+ { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" },
1183
+ { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" },
1184
+ { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" },
1185
+ { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" },
1186
+ { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" },
1187
+ { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" },
1188
+ { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" },
1189
+ { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" },
1190
+ { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" },
1191
+ { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" },
1192
+ { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" },
1193
+ { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" },
1194
+ { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" },
1195
+ { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" },
1196
+ { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" },
1197
+ { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" },
1198
+ { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" },
1199
+ { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" },
1200
+ { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" },
1201
+ { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" },
1202
  ]