Skip to content

Commit

Permalink
refactor: change alerts to status messages and split impacts and output
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelrince committed Dec 7, 2024
1 parent 0bb7acf commit 59452e2
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

EcoLogits may encounter situations where the calculation of environmental impacts has **high risk of inaccuracies or uncertainties** (reported as **warnings**), or where the calculation **fails** due to certain reasons like misconfiguration (reported as **errors**).

Warnings and errors are reported in the [`Impacts`][impacts.modeling.Impacts] pydantic model within the `warnings` and `errors` fields respectively. Each warning or error contains a `code` (all listed below) and a `message` explaining the issue.
Warnings and errors are reported in the [`ImpactsOutput`][tracers.utils.ImpactsOutput] pydantic model within the `warnings` and `errors` fields respectively. Each warning or error contains a `code` (all listed below) and a `message` explaining the issue.

!!! note "Silent reporting of warnings and errors"

Expand Down
58 changes: 0 additions & 58 deletions ecologits/alerts.py

This file was deleted.

35 changes: 7 additions & 28 deletions ecologits/impacts/modeling.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from functools import total_ordering
from typing import Optional, TypeVar
from typing import TypeVar

from pydantic import BaseModel

from ecologits.alerts import AlertMessage
from ecologits.exceptions import ModelingError
from ecologits.utils.range_value import ValueOrRange

Expand Down Expand Up @@ -200,29 +199,9 @@ class Impacts(BaseModel):
usage: Impacts for the usage phase
embodied: Impacts for the embodied phase
"""
energy: Optional[Energy] = None
gwp: Optional[GWP] = None
adpe: Optional[ADPe] = None
pe: Optional[PE] = None
usage: Optional[Usage] = None
embodied: Optional[Embodied] = None
warnings: list[AlertMessage] = []
errors: list[AlertMessage] = []

@property
def has_warnings(self) -> bool:
return len(self.warnings) > 0

@property
def has_errors(self) -> bool:
return len(self.errors) > 0

def add_warning(self, warning: AlertMessage) -> None:
if self.warnings is None:
self.warnings = []
self.warnings.append(warning)

def add_errors(self, error: AlertMessage) -> None:
if self.errors is None:
self.errors = []
self.errors.append(error)
energy: Energy
gwp: GWP
adpe: ADPe
pe: PE
usage: Usage
embodied: Embodied
6 changes: 3 additions & 3 deletions ecologits/model_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import BaseModel

from ecologits.alerts import AlertMessage
from ecologits.status_messages import WarningMessage
from ecologits.utils.range_value import ValueOrRange


Expand Down Expand Up @@ -43,7 +43,7 @@ class Model(BaseModel):
provider: Providers
name: str
architecture: Architecture
warnings: list[AlertMessage] = []
warnings: list[WarningMessage] = []
sources: list[str] = []

@property
Expand All @@ -54,7 +54,7 @@ def has_warnings(self) -> bool:
def from_json(cls, data: dict[str, Any]) -> "Model":
warnings = []
if data["warnings"] is not None:
warnings = [AlertMessage.from_code(code) for code in data["warnings"]]
warnings = [WarningMessage.from_code(code) for code in data["warnings"]]
return cls(
provider=Providers(data["provider"]),
name=data["name"],
Expand Down
73 changes: 73 additions & 0 deletions ecologits/status_messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from pydantic import BaseModel

STATUS_DOCS_URL = "https://ecologits/tutorial/warnings_and_errors/#{code}"


class _StatusMessage(BaseModel):
"""
Base status message used for warnings or errors.
Attributes:
code: Status code.
message: Message explaining the issue.
"""
code: str
message: str

def __str__(self) -> str:
return f"{self.message}\n\nFor further information visit {STATUS_DOCS_URL.format(code=self.code)}"

@classmethod
def from_code(cls, code: str) -> type["_StatusMessage"]:
raise NotImplementedError("Should be called from WarningMessage or ErrorMessage.")


class WarningMessage(_StatusMessage):

@classmethod
def from_code(cls, code: str) -> "WarningMessage":
if code in _warning_codes:
return _warning_codes[code]()
else:
raise ValueError(f"Warning code `{code}` does not exist.")


class ErrorMessage(_StatusMessage):

@classmethod
def from_code(cls, code: str) -> "ErrorMessage":
if code in _error_codes:
return _error_codes[code]()
else:
raise ValueError(f"Error code `{code}` does not exist.")


class ModelArchNotReleasedWarning(WarningMessage):
code: str = "model-arch-not-released"
message: str = "The model architecture has not been released, expect lower precision."


class ModelArchMultimodalWarning(WarningMessage):
code: str = "model-arch-multimodal"
message: str = "The model architecture is multimodal, expect lower precision."


class ModelNotRegisteredError(ErrorMessage):
code: str = "model-not-registered"
message: str = "The model is not registered in the model repository."


class ZoneNotRegisteredError(ErrorMessage):
code: str = "zone-not-registered"
message: str = "The zone is not registered."


_warning_codes: dict[str, type[WarningMessage]] = {
"model-arch-not-released": ModelArchNotReleasedWarning,
"model-arch-multimodal": ModelArchMultimodalWarning
}

_error_codes: dict[str, type[ErrorMessage]] = {
"model-not-registered": ModelNotRegisteredError,
"zone-not-registered": ZoneNotRegisteredError
}
9 changes: 4 additions & 5 deletions ecologits/tracers/anthropic_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts

PROVIDER = "anthropic"

Expand All @@ -23,11 +22,11 @@


class Message(_Message):
impacts: Impacts
impacts: ImpactsOutput


class MessageStream(_MessageStream):
impacts: Optional[Impacts] = None
impacts: Optional[ImpactsOutput] = None

@override
def __stream_text__(self) -> Iterator[str]: # type: ignore[misc]
Expand Down Expand Up @@ -62,7 +61,7 @@ def __init__(self, parent) -> None: # noqa: ANN001


class AsyncMessageStream(_AsyncMessageStream):
impacts: Optional[Impacts] = None
impacts: Optional[ImpactsOutput] = None

@override
async def __stream_text__(self) -> AsyncIterator[str]: # type: ignore[misc]
Expand Down
7 changes: 3 additions & 4 deletions ecologits/tracers/cohere_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts

PROVIDER = "cohere"


class NonStreamedChatResponse(_NonStreamedChatResponse):
impacts: Optional[Impacts] = None
impacts: Optional[ImpactsOutput] = None

class Config:
arbitrary_types_allowed = True


class StreamEndStreamedChatResponse(_StreamEndStreamedChatResponse):
impacts: Optional[Impacts] = None
impacts: Optional[ImpactsOutput] = None

class Config:
arbitrary_types_allowed = True
Expand Down
7 changes: 3 additions & 4 deletions ecologits/tracers/huggingface_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts

PROVIDER = "huggingface_hub"


@dataclass
class ChatCompletionOutput(_ChatCompletionOutput):
impacts: Impacts
impacts: ImpactsOutput


@dataclass
class ChatCompletionStreamOutput(_ChatCompletionStreamOutput):
impacts: Impacts
impacts: ImpactsOutput


def huggingface_chat_wrapper(
Expand Down
7 changes: 3 additions & 4 deletions ecologits/tracers/litellm_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.model_repository import models
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts


class ChatCompletion(ModelResponse):
impacts: Impacts
impacts: ImpactsOutput


class ChatCompletionChunk(ModelResponse):
impacts: Impacts
impacts: ImpactsOutput


_model_choices = [f"{m.provider.value}/{m.name}" for m in models.list_models()]
Expand Down
7 changes: 3 additions & 4 deletions ecologits/tracers/mistralai_tracer_v0.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,17 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts

PROVIDER = "mistralai"


class ChatCompletionResponse(_ChatCompletionResponse):
impacts: Impacts
impacts: ImpactsOutput


class ChatCompletionStreamResponse(_ChatCompletionStreamResponse):
impacts: Impacts
impacts: ImpactsOutput



Expand Down
7 changes: 3 additions & 4 deletions ecologits/tracers/mistralai_tracer_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts

PROVIDER = "mistralai"


class ChatCompletionResponse(_ChatCompletionResponse):
impacts: Impacts
impacts: ImpactsOutput


class CompletionChunk(_CompletionChunk):
impacts: Impacts
impacts: ImpactsOutput



Expand Down
7 changes: 3 additions & 4 deletions ecologits/tracers/openai_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@
from wrapt import wrap_function_wrapper # type: ignore[import-untyped]

from ecologits._ecologits import EcoLogits
from ecologits.impacts import Impacts
from ecologits.tracers.utils import llm_impacts
from ecologits.tracers.utils import ImpactsOutput, llm_impacts

PROVIDER = "openai"


class ChatCompletion(_ChatCompletion):
impacts: Impacts
impacts: ImpactsOutput


class ChatCompletionChunk(_ChatCompletionChunk):
impacts: Impacts
impacts: ImpactsOutput


def openai_chat_wrapper(
Expand Down
Loading

0 comments on commit 59452e2

Please sign in to comment.