ecologits-chat / app_original.py
yipfram's picture
Upload 14 files
b00f1d1 verified
import os
from dotenv import load_dotenv
from ecologits import EcoLogits
from mistralai import Mistral
import gradio as gr
# Load environment variables from .env file
load_dotenv()
# Initialize EcoLogits
EcoLogits.init(providers=["mistralai"])
client = Mistral(api_key=os.getenv("MISTRAL_API_KEY"))
# Initialize cumulative impacts storage
class CumulativeImpacts:
def __init__(self):
self.reset()
def reset(self):
self.energy_min = 0.0
self.energy_max = 0.0
self.energy_unit = "kWh"
self.gwp_min = 0.0
self.gwp_max = 0.0
self.gwp_unit = "kgCO2eq"
self.adpe_min = 0.0
self.adpe_max = 0.0
self.adpe_unit = "kgSbeq"
self.pe_min = 0.0
self.pe_max = 0.0
self.pe_unit = "kWh"
self.usage_energy_min = 0.0
self.usage_energy_max = 0.0
self.usage_gwp_min = 0.0
self.usage_gwp_max = 0.0
self.embodied_gwp = 0.0
self.embodied_gwp_unit = "kgCO2eq"
self.embodied_adpe = 0.0
self.embodied_adpe_unit = "kgSbeq"
self.embodied_pe = 0.0
self.embodied_pe_unit = "kWh"
self.generation_count = 0
# Store previous values for delta calculation
self.prev_energy_min = 0.0
self.prev_energy_max = 0.0
self.prev_gwp_min = 0.0
self.prev_gwp_max = 0.0
self.prev_adpe_min = 0.0
self.prev_adpe_max = 0.0
self.prev_pe_min = 0.0
self.prev_pe_max = 0.0
self.prev_usage_energy_min = 0.0
self.prev_usage_energy_max = 0.0
self.prev_usage_gwp_min = 0.0
self.prev_usage_gwp_max = 0.0
self.prev_embodied_gwp = 0.0
self.prev_embodied_adpe = 0.0
self.prev_embodied_pe = 0.0
def get_generation_delta(self):
"""Get the delta between current and previous totals (impact of last generation)"""
return {
'energy_min': self.energy_min - self.prev_energy_min,
'energy_max': self.energy_max - self.prev_energy_max,
'energy_unit': self.energy_unit,
'gwp_min': self.gwp_min - self.prev_gwp_min,
'gwp_max': self.gwp_max - self.prev_gwp_max,
'gwp_unit': self.gwp_unit,
'adpe_min': self.adpe_min - self.prev_adpe_min,
'adpe_max': self.adpe_max - self.prev_adpe_max,
'adpe_unit': self.adpe_unit,
'pe_min': self.pe_min - self.prev_pe_min,
'pe_max': self.pe_max - self.prev_pe_max,
'pe_unit': self.pe_unit,
'usage_energy_min': self.usage_energy_min - self.prev_usage_energy_min,
'usage_energy_max': self.usage_energy_max - self.prev_usage_energy_max,
'usage_gwp_min': self.usage_gwp_min - self.prev_usage_gwp_min,
'usage_gwp_max': self.usage_gwp_max - self.prev_usage_gwp_max,
'embodied_gwp': float(self.embodied_gwp) - float(self.prev_embodied_gwp),
'embodied_gwp_unit': self.embodied_gwp_unit,
'embodied_adpe': float(self.embodied_adpe) - float(self.prev_embodied_adpe),
'embodied_adpe_unit': self.embodied_adpe_unit,
'embodied_pe': float(self.embodied_pe) - float(self.prev_embodied_pe),
'embodied_pe_unit': self.embodied_pe_unit
}
def add_impacts(self, impacts):
# Store previous values before updating
self.prev_energy_min = self.energy_min
self.prev_energy_max = self.energy_max
self.prev_gwp_min = self.gwp_min
self.prev_gwp_max = self.gwp_max
self.prev_adpe_min = self.adpe_min
self.prev_adpe_max = self.adpe_max
self.prev_pe_min = self.pe_min
self.prev_pe_max = self.pe_max
self.prev_usage_energy_min = self.usage_energy_min
self.prev_usage_energy_max = self.usage_energy_max
self.prev_usage_gwp_min = self.usage_gwp_min
self.prev_usage_gwp_max = self.usage_gwp_max
# Convert values to float to avoid type issues
self.prev_embodied_gwp = float(self.embodied_gwp) if self.embodied_gwp is not None else 0.0
self.prev_embodied_adpe = float(self.embodied_adpe) if self.embodied_adpe is not None else 0.0
self.prev_embodied_pe = float(self.embodied_pe) if self.embodied_pe is not None else 0.0
# Update current values
self.energy_min += impacts.energy.value.min
self.energy_max += impacts.energy.value.max
self.energy_unit = impacts.energy.unit
self.gwp_min += impacts.gwp.value.min
self.gwp_max += impacts.gwp.value.max
self.gwp_unit = impacts.gwp.unit
self.adpe_min += impacts.adpe.value.min
self.adpe_max += impacts.adpe.value.max
self.adpe_unit = impacts.adpe.unit
self.pe_min += impacts.pe.value.min
self.pe_max += impacts.pe.value.max
self.pe_unit = impacts.pe.unit
self.usage_energy_min += impacts.usage.energy.value.min
self.usage_energy_max += impacts.usage.energy.value.max
self.usage_gwp_min += impacts.usage.gwp.value.min
self.usage_gwp_max += impacts.usage.gwp.value.max
# Handle embodied impacts - they might be RangeValue objects or simple floats
if hasattr(impacts.embodied.gwp.value, 'min'):
self.embodied_gwp += impacts.embodied.gwp.value.min # Use min if it's a RangeValue
else:
self.embodied_gwp += impacts.embodied.gwp.value # Use direct value if it's a float
self.embodied_gwp_unit = impacts.embodied.gwp.unit
if hasattr(impacts.embodied.adpe.value, 'min'):
self.embodied_adpe += impacts.embodied.adpe.value.min
else:
self.embodied_adpe += impacts.embodied.adpe.value
self.embodied_adpe_unit = impacts.embodied.adpe.unit
if hasattr(impacts.embodied.pe.value, 'min'):
self.embodied_pe += impacts.embodied.pe.value.min
else:
self.embodied_pe += impacts.embodied.pe.value
self.embodied_pe_unit = impacts.embodied.pe.unit
self.generation_count += 1
# Global cumulative impacts instance
cumulative_impacts = CumulativeImpacts()
def get_response(message, history, model):
message_aggregate = []
if history:
message_aggregate.extend(history)
message_aggregate.append({"role": "user", "content": message})
print(message_aggregate)
# Use the selected model or default to mistral-tiny
if not model:
model = "mistral-tiny"
print(f"Using model: {model}")
response = client.chat.complete(
messages=message_aggregate,
model=model
)
if response.impacts.has_warnings: # type: ignore
for w in response.impacts.warnings: # type: ignore
print(w)
if response.impacts.has_errors: # type: ignore
for e in response.impacts.errors: # type: ignore
print(e)
# Get the impacts and format them
impacts = response.impacts # type: ignore
# Add impacts to cumulative total
cumulative_impacts.add_impacts(impacts)
# Get the delta for this generation
generation_delta = cumulative_impacts.get_generation_delta()
message_aggregate.append({
"role": "assistant",
"content": response.choices[0].message.content
})
# Return current generation impacts, generation delta, and cumulative totals
return (
message_aggregate,
# Current generation impacts (raw from API)
impacts.energy.value.min,
impacts.energy.value.max,
impacts.energy.unit,
impacts.gwp.value.min,
impacts.gwp.value.max,
impacts.gwp.unit,
f"{impacts.adpe.value.min:.2e}",
f"{impacts.adpe.value.max:.2e}",
impacts.adpe.unit,
impacts.pe.value.min,
impacts.pe.value.max,
impacts.pe.unit,
impacts.usage.energy.value.min,
impacts.usage.energy.value.max,
impacts.usage.gwp.value.min,
impacts.usage.gwp.value.max,
f"{impacts.embodied.gwp.value:.2e}",
impacts.embodied.gwp.unit,
f"{impacts.embodied.adpe.value:.2e}",
impacts.embodied.adpe.unit,
f"{impacts.embodied.pe.value:.2e}",
impacts.embodied.pe.unit,
# Generation delta (calculated difference)
generation_delta['energy_min'],
generation_delta['energy_max'],
generation_delta['energy_unit'],
generation_delta['gwp_min'],
generation_delta['gwp_max'],
generation_delta['gwp_unit'],
f"{generation_delta['adpe_min']:.2e}",
f"{generation_delta['adpe_max']:.2e}",
generation_delta['adpe_unit'],
generation_delta['pe_min'],
generation_delta['pe_max'],
generation_delta['pe_unit'],
generation_delta['usage_energy_min'],
generation_delta['usage_energy_max'],
generation_delta['usage_gwp_min'],
generation_delta['usage_gwp_max'],
f"{generation_delta['embodied_gwp']:.2e}",
generation_delta['embodied_gwp_unit'],
f"{generation_delta['embodied_adpe']:.2e}",
generation_delta['embodied_adpe_unit'],
f"{generation_delta['embodied_pe']:.2e}",
generation_delta['embodied_pe_unit'],
# Cumulative impacts
cumulative_impacts.energy_min,
cumulative_impacts.energy_max,
cumulative_impacts.energy_unit,
cumulative_impacts.gwp_min,
cumulative_impacts.gwp_max,
cumulative_impacts.gwp_unit,
f"{cumulative_impacts.adpe_min:.2e}",
f"{cumulative_impacts.adpe_max:.2e}",
cumulative_impacts.adpe_unit,
cumulative_impacts.pe_min,
cumulative_impacts.pe_max,
cumulative_impacts.pe_unit,
cumulative_impacts.usage_energy_min,
cumulative_impacts.usage_energy_max,
cumulative_impacts.usage_gwp_min,
cumulative_impacts.usage_gwp_max,
f"{cumulative_impacts.embodied_gwp:.2e}",
cumulative_impacts.embodied_gwp_unit,
f"{cumulative_impacts.embodied_adpe:.2e}",
cumulative_impacts.embodied_adpe_unit,
f"{cumulative_impacts.embodied_pe:.2e}",
cumulative_impacts.embodied_pe_unit,
cumulative_impacts.generation_count
)
with gr.Blocks() as demo:
gr.Markdown("# 🌱 EcoLogits Chat - Chat écologique avec Mistral")
gr.Markdown("Discutez avec l'IA tout en surveillant l'impact environnemental de chaque requête")
with gr.Row():
with gr.Column(scale=3):
chatbot = gr.Chatbot(
type="messages",
height=600,
show_label=False
)
with gr.Row():
prompt = gr.Textbox(
placeholder="Tapez votre message ici...",
scale=4,
show_label=False,
max_lines=3
)
send_btn = gr.Button("Envoyer", variant="primary", scale=1)
with gr.Row():
# Get available models from Mistral API
try:
available_models = client.models.list()
model_choices = [model.id for model in available_models.data] if available_models.data else []
except Exception as e:
print(f"Warning: Could not fetch models from API: {e}")
model_choices = ["mistral-tiny", "mistral-small", "mistral-medium"]
if not model_choices:
model_choices = ["mistral-tiny", "mistral-small", "mistral-medium"]
model = gr.Dropdown(
choices=model_choices,
value=model_choices[0] if model_choices else "mistral-tiny",
label="Modèle Mistral",
scale=1
)
with gr.Column(scale=2):
gr.Markdown("## 📊 Impact Environnemental")
# Generation counter
generation_counter = gr.Number(label="🔢 Nombre de générations", precision=0, interactive=False)
# Tabs for current vs cumulative impacts
with gr.Tabs():
with gr.TabItem("🎯 Dernier message"):
gr.Markdown("### � **Coût calculé de cette requête spécifique**")
gr.Markdown("*Différence entre le total avant et après cette génération*")
with gr.Accordion("⚡ Consommation d'énergie", open=True):
with gr.Row():
delta_energy_min = gr.Number(label="Min", precision=8, interactive=False)
delta_energy_max = gr.Number(label="Max", precision=8, interactive=False)
delta_energy_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("🌍 Empreinte carbone (GWP)", open=True):
with gr.Row():
delta_gwp_min = gr.Number(label="Min", precision=8, interactive=False)
delta_gwp_max = gr.Number(label="Max", precision=8, interactive=False)
delta_gwp_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("⛏️ Épuisement des ressources (ADPe)", open=False):
with gr.Row():
delta_adpe_min = gr.Textbox(label="Min", interactive=False)
delta_adpe_max = gr.Textbox(label="Max", interactive=False)
delta_adpe_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("🔋 Énergie primaire (PE)", open=False):
with gr.Row():
delta_pe_min = gr.Number(label="Min", precision=8, interactive=False)
delta_pe_max = gr.Number(label="Max", precision=8, interactive=False)
delta_pe_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("💻 Impact d'usage", open=False):
gr.Markdown("**Énergie**")
with gr.Row():
delta_usage_energy_min = gr.Number(label="Min", precision=8, interactive=False)
delta_usage_energy_max = gr.Number(label="Max", precision=8, interactive=False)
gr.Markdown("**GWP**")
with gr.Row():
delta_usage_gwp_min = gr.Number(label="Min", precision=8, interactive=False)
delta_usage_gwp_max = gr.Number(label="Max", precision=8, interactive=False)
with gr.Accordion("🏭 Impact incorporé", open=False):
delta_embodied_gwp = gr.Textbox(label="GWP", interactive=False)
delta_embodied_gwp_unit = gr.Textbox(label="Unité GWP", interactive=False)
delta_embodied_adpe = gr.Textbox(label="ADPe", interactive=False)
delta_embodied_adpe_unit = gr.Textbox(label="Unité ADPe", interactive=False)
delta_embodied_pe = gr.Textbox(label="PE", interactive=False)
delta_embodied_pe_unit = gr.Textbox(label="Unité PE", interactive=False)
with gr.TabItem("📈 Chat complet"):
gr.Markdown("### 🔧 **Données directes de l'API EcoLogits**")
with gr.Accordion("⚡ Consommation d'énergie", open=True):
with gr.Row():
energy_min = gr.Number(label="Min", precision=6, interactive=False)
energy_max = gr.Number(label="Max", precision=6, interactive=False)
energy_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("🌍 Empreinte carbone (GWP)", open=True):
with gr.Row():
gwp_min = gr.Number(label="Min", precision=6, interactive=False)
gwp_max = gr.Number(label="Max", precision=6, interactive=False)
gwp_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("⛏️ Épuisement des ressources (ADPe)", open=False):
with gr.Row():
adpe_min = gr.Textbox(label="Min", interactive=False)
adpe_max = gr.Textbox(label="Max", interactive=False)
adpe_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("🔋 Énergie primaire (PE)", open=False):
with gr.Row():
pe_min = gr.Number(label="Min", precision=6, interactive=False)
pe_max = gr.Number(label="Max", precision=6, interactive=False)
pe_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("💻 Impact d'usage", open=False):
gr.Markdown("**Énergie**")
with gr.Row():
usage_energy_min = gr.Number(label="Min", precision=6, interactive=False)
usage_energy_max = gr.Number(label="Max", precision=6, interactive=False)
gr.Markdown("**GWP**")
with gr.Row():
usage_gwp_min = gr.Number(label="Min", precision=6, interactive=False)
usage_gwp_max = gr.Number(label="Max", precision=6, interactive=False)
with gr.Accordion("🏭 Impact incorporé", open=False):
embodied_gwp = gr.Textbox(label="GWP", interactive=False)
embodied_gwp_unit = gr.Textbox(label="Unité GWP", interactive=False)
embodied_adpe = gr.Textbox(label="ADPe", interactive=False)
embodied_adpe_unit = gr.Textbox(label="Unité ADPe", interactive=False)
embodied_pe = gr.Textbox(label="PE", interactive=False)
embodied_pe_unit = gr.Textbox(label="Unité PE", interactive=False)
with gr.TabItem("📊 Total session"):
with gr.Accordion("⚡ Consommation d'énergie totale", open=True):
with gr.Row():
total_energy_min = gr.Number(label="Min", precision=6, interactive=False)
total_energy_max = gr.Number(label="Max", precision=6, interactive=False)
total_energy_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("🌍 Empreinte carbone totale (GWP)", open=True):
with gr.Row():
total_gwp_min = gr.Number(label="Min", precision=6, interactive=False)
total_gwp_max = gr.Number(label="Max", precision=6, interactive=False)
total_gwp_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("⛏️ Épuisement des ressources totale (ADPe)", open=False):
with gr.Row():
total_adpe_min = gr.Textbox(label="Min", interactive=False)
total_adpe_max = gr.Textbox(label="Max", interactive=False)
total_adpe_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("🔋 Énergie primaire totale (PE)", open=False):
with gr.Row():
total_pe_min = gr.Number(label="Min", precision=6, interactive=False)
total_pe_max = gr.Number(label="Max", precision=6, interactive=False)
total_pe_unit = gr.Textbox(label="Unité", interactive=False)
with gr.Accordion("💻 Impact d'usage total", open=False):
gr.Markdown("**Énergie**")
with gr.Row():
total_usage_energy_min = gr.Number(label="Min", precision=6, interactive=False)
total_usage_energy_max = gr.Number(label="Max", precision=6, interactive=False)
gr.Markdown("**GWP**")
with gr.Row():
total_usage_gwp_min = gr.Number(label="Min", precision=6, interactive=False)
total_usage_gwp_max = gr.Number(label="Max", precision=6, interactive=False)
with gr.Accordion("🏭 Impact incorporé total", open=False):
total_embodied_gwp = gr.Textbox(label="GWP", interactive=False)
total_embodied_gwp_unit = gr.Textbox(label="Unité GWP", interactive=False)
total_embodied_adpe = gr.Textbox(label="ADPe", interactive=False)
total_embodied_adpe_unit = gr.Textbox(label="Unité ADPe", interactive=False)
total_embodied_pe = gr.Textbox(label="PE", interactive=False)
total_embodied_pe_unit = gr.Textbox(label="Unité PE", interactive=False)
def handle_message(message, history, model):
if not message.strip():
return history, "", *([None]*68) # Updated for new output count with delta values
result = get_response(message, history, model)
return result[0], "", *result[1:]
def clear_chat():
"""Clear the chat and reset cumulative impacts"""
cumulative_impacts.reset()
return [], *([None]*68) # Clear chatbot and all impact displays
# Connect both prompt submit and button click
for trigger in [prompt.submit, send_btn.click]:
trigger(
handle_message,
inputs=[prompt, chatbot, model],
outputs=[chatbot, prompt,
# Current generation impacts (raw API data)
energy_min, energy_max, energy_unit,
gwp_min, gwp_max, gwp_unit,
adpe_min, adpe_max, adpe_unit,
pe_min, pe_max, pe_unit,
usage_energy_min, usage_energy_max,
usage_gwp_min, usage_gwp_max,
embodied_gwp, embodied_gwp_unit,
embodied_adpe, embodied_adpe_unit,
embodied_pe, embodied_pe_unit,
# Generation delta (calculated difference)
delta_energy_min, delta_energy_max, delta_energy_unit,
delta_gwp_min, delta_gwp_max, delta_gwp_unit,
delta_adpe_min, delta_adpe_max, delta_adpe_unit,
delta_pe_min, delta_pe_max, delta_pe_unit,
delta_usage_energy_min, delta_usage_energy_max,
delta_usage_gwp_min, delta_usage_gwp_max,
delta_embodied_gwp, delta_embodied_gwp_unit,
delta_embodied_adpe, delta_embodied_adpe_unit,
delta_embodied_pe, delta_embodied_pe_unit,
# Cumulative impacts
total_energy_min, total_energy_max, total_energy_unit,
total_gwp_min, total_gwp_max, total_gwp_unit,
total_adpe_min, total_adpe_max, total_adpe_unit,
total_pe_min, total_pe_max, total_pe_unit,
total_usage_energy_min, total_usage_energy_max,
total_usage_gwp_min, total_usage_gwp_max,
total_embodied_gwp, total_embodied_gwp_unit,
total_embodied_adpe, total_embodied_adpe_unit,
total_embodied_pe, total_embodied_pe_unit,
generation_counter]
)
# Connect clear button
chatbot.clear(
clear_chat,
outputs=[chatbot,
# Current generation impacts (raw API data)
energy_min, energy_max, energy_unit,
gwp_min, gwp_max, gwp_unit,
adpe_min, adpe_max, adpe_unit,
pe_min, pe_max, pe_unit,
usage_energy_min, usage_energy_max,
usage_gwp_min, usage_gwp_max,
embodied_gwp, embodied_gwp_unit,
embodied_adpe, embodied_adpe_unit,
embodied_pe, embodied_pe_unit,
# Generation delta (calculated difference)
delta_energy_min, delta_energy_max, delta_energy_unit,
delta_gwp_min, delta_gwp_max, delta_gwp_unit,
delta_adpe_min, delta_adpe_max, delta_adpe_unit,
delta_pe_min, delta_pe_max, delta_pe_unit,
delta_usage_energy_min, delta_usage_energy_max,
delta_usage_gwp_min, delta_usage_gwp_max,
delta_embodied_gwp, delta_embodied_gwp_unit,
delta_embodied_adpe, delta_embodied_adpe_unit,
delta_embodied_pe, delta_embodied_pe_unit,
# Cumulative impacts
total_energy_min, total_energy_max, total_energy_unit,
total_gwp_min, total_gwp_max, total_gwp_unit,
total_adpe_min, total_adpe_max, total_adpe_unit,
total_pe_min, total_pe_max, total_pe_unit,
total_usage_energy_min, total_usage_energy_max,
total_usage_gwp_min, total_usage_gwp_max,
total_embodied_gwp, total_embodied_gwp_unit,
total_embodied_adpe, total_embodied_adpe_unit,
total_embodied_pe, total_embodied_pe_unit,
generation_counter]
)
demo.launch()