Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update messages #476

Merged
merged 20 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1b17969
refactor: optimize data processing logic for enhanced performance
ohdearquant Dec 16, 2024
5931d22
feat: add custom IDError class for ID validation issues
ohdearquant Dec 16, 2024
04b852f
decision: lion2 base models, set
ohdearquant Dec 16, 2024
2878437
decision: LION2 component
ohdearquant Dec 16, 2024
35b45b6
decision: LION2 element
ohdearquant Dec 16, 2024
7027fa4
decision: include nested utils, useful stuff
ohdearquant Dec 16, 2024
f33e4d9
refactor: rename ln_id to id in Element class for consistency
ohdearquant Dec 16, 2024
4cc0c08
updated log
ohdearquant Dec 16, 2024
97b55e5
feat: add class registry for dynamic class retrieval and registration
ohdearquant Dec 16, 2024
9f29829
feat: add utility functions for dynamic class retrieval and file path…
ohdearquant Dec 16, 2024
c853809
decision: LION2 protocol folder is now `set`
ohdearquant Dec 16, 2024
7bb9098
decision: settled on LION2 messages
ohdearquant Dec 16, 2024
4a9912a
test: add unit tests for BaseMail and System message classes
ohdearquant Dec 16, 2024
67133e3
feat: expose BaseMail in message types for improved accessibility
ohdearquant Dec 16, 2024
5efb115
refactor: reorganize field modules and update imports for consistency
ohdearquant Dec 16, 2024
219adcc
refactor: simplify Action class by removing unused fields and methods
ohdearquant Dec 16, 2024
d81b5a0
refactor: clean up imports and add HashableModel class for improved f…
ohdearquant Dec 16, 2024
fb2705f
refactor: update __all__ exports in tool.py for improved module visib…
ohdearquant Dec 16, 2024
f461bcc
refactor: update imports to use lionagi.fields for consistency across…
ohdearquant Dec 16, 2024
eb44251
refactor: update imports for consistency and remove unused models acr…
ohdearquant Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/lionagi/_class_registry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os
from typing import TypeVar

from .utils import get_class_file_registry, get_class_objects

T = TypeVar("T")
LION_CLASS_REGISTRY: dict[str, type[T]] = {}
LION_CLASS_FILE_REGISTRY: dict[str, str] = {}

folders = (
"action",
"messages",
"protocols",
"session",
)
pattern_list = [f"lionagi/{folder}" for folder in folders]

if not LION_CLASS_FILE_REGISTRY:
script_path = os.path.abspath(__file__)
script_dir = os.path.dirname(script_path)

LION_CLASS_FILE_REGISTRY = get_class_file_registry(
script_dir, pattern_list
)


def get_class(class_name: str) -> type:
"""
Retrieve a class by name from the registry or dynamically import it.

This function first checks the LION_CLASS_REGISTRY for the requested class.
If not found, it uses mor to dynamically import the class. The
function ensures that the retrieved class is a subclass of the specified
base_class.

Note:
This function automatically registers newly found classes in the
LION_CLASS_REGISTRY for future quick access.
"""
if class_name in LION_CLASS_REGISTRY:
return LION_CLASS_REGISTRY[class_name]

try:
found_class_filepath = LION_CLASS_FILE_REGISTRY[class_name]
found_class_dict = get_class_objects(found_class_filepath)
return found_class_dict[class_name]
except Exception as e:
raise ValueError(f"Unable to find class {class_name}: {e}")


# File: lion/core/util/class_registry_util.py
133 changes: 31 additions & 102 deletions src/lionagi/action/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,119 +2,48 @@
#
# SPDX-License-Identifier: Apache-2.0

from abc import ABC, abstractmethod
from typing import Any, NoReturn

from pydantic import Field
from pydantic import PrivateAttr

from ..protocols.types import BaseAutoModel, Event, EventStatus, Log
from lionagi.protocols.types import (
AccessError,
Element,
Event,
EventStatus,
Log,
)

__all__ = ("Action",)

class Action(Element, Event):

class Action(BaseAutoModel, Event, ABC):
"""
Base class for executable actions with status tracking and result management.

An Action represents a discrete unit of work that can be executed asynchronously.
It tracks its execution state, timing, results, and any errors that occur during
execution.

Attributes:
status (EventStatus): Current execution status. Defaults to PENDING.
execution_time (Optional[float]): Time taken for execution in seconds.
execution_result (Optional[Any]): Result produced by the action execution.
error (Optional[str]): Error message if execution failed.

Properties:
request (dict[str, Any]): Request parameters for permission checking.
"""

status: EventStatus = Field(
default=EventStatus.PENDING,
description="Current status of the action execution",
)
execution_time: float | None = Field(
default=None, description="Time taken to execute the action in seconds"
)
execution_result: Any | None = Field(
default=None, description="Result produced by the action execution"
)
error: str | None = Field(
default=None, description="Error message if execution failed"
)

model_config = {
"arbitrary_types_allowed": True,
"validate_assignment": True,
"use_enum_values": False,
}

def from_dict(self, *args: Any, **kwargs: Any) -> NoReturn:
"""
Explicitly prevents recreation from dictionary.

Actions are meant to be created and executed once, not recreated from
serialized state.

Raises:
NotImplementedError: Always, as Actions cannot be recreated.
"""
raise NotImplementedError(
"Actions cannot be re-created from dictionaries. Create a new Action instance instead."
)
status: EventStatus = EventStatus.PENDING
execution_time: float | None = None
execution_response: Any = None
execution_error: str | None = None
_content_fields: list = PrivateAttr(["execution_response"])

def to_log(self) -> Log:
"""
Converts the action instance to a Log entry.

Creates a log entry capturing the current state of the action for
tracking and auditing purposes.

Returns:
Log: A log entry representing the current action state.
"""
return Log(
content={
"id": str(self.id),
"created_timestamp": self.created_timestamp,
"status": self.status,
"execution_time": self.execution_time,
"execution_result": self.execution_result,
"error": self.error,
}
)

@property
def request(self) -> dict[str, Any]:
"""
Gets request parameters for permission checking.

Override this in subclasses to provide custom permission parameters.
Convert the action to a log entry. Will forcefully convert all fields
into a dictionary or json serializable format.

Returns:
Empty dict by default. Subclasses should override to provide
relevant permission parameters.
"""
return {}

def __repr__(self) -> str:
"""
Returns a string representation of the Action instance.

Returns:
String containing key action state (status and execution time).
"""
return (
f"Action(status={self.status.name}, "
f"execution_time={self.execution_time})"
BaseLog: A log entry representing the action.
"""
dict_ = self.to_dict()
dict_["status"] = self.status.value
content = {k: dict_[k] for k in self._content_fields if k in dict_}
loginfo = {k: dict_[k] for k in dict_ if k not in self._content_fields}
return Log(content=content, loginfo=loginfo)

@classmethod
def from_dict(cls, data: dict, /, **kwargs: Any) -> NoReturn:
"""Event cannot be re-created."""
raise AccessError(
"An event cannot be recreated. Once it's done, it's done."
)

@abstractmethod
async def invoke(self) -> None:
"""Execute the action.

This method must be implemented by subclasses to define the actual
execution behavior of the action.
"""
pass
__all__ = ["ObservableAction"]
# File: lion_core/action/base.py
Loading
Loading