From 3166922dd12d05a4740fac3fc701351021eeb283 Mon Sep 17 00:00:00 2001 From: Chandra Irugalbandara Date: Fri, 13 Sep 2024 23:01:38 +0000 Subject: [PATCH] restructed the folder structure --- README.md | 4 +- examples/personality_finder_vision.py | 9 +-- semantix/__init__.py | 5 +- semantix/decorators.py | 3 +- semantix/inference.py | 2 +- semantix/types/__init__.py | 5 ++ semantix/{ => types}/media.py | 4 +- semantix/{types.py => types/prompt.py} | 76 +------------------------- semantix/types/semantic.py | 76 ++++++++++++++++++++++++++ 9 files changed, 98 insertions(+), 86 deletions(-) create mode 100644 semantix/types/__init__.py rename semantix/{ => types}/media.py (97%) rename semantix/{types.py => types/prompt.py} (75%) create mode 100644 semantix/types/semantic.py diff --git a/README.md b/README.md index 383101c..c12757f 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@ [![PyPI version](https://img.shields.io/pypi/v/semantix.svg)](https://pypi.org/project/semantix/) [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/chandralegend/semantix/blob/main/try.ipynb) ![License](https://img.shields.io/badge/License-MIT-blue.svg) - -Semantix provides a simple but powerful way to infuse meaning into functions, variables and classes to leverage the power of Large Language models to generate structured typed outputs without the need of JSON Schema or any other abstractions. +Semantix provides a simple but powerful way to infuse meaning into functions, variables and classes to leverage the power of Large Language models to generate structured typed outputs `without the need of JSON Schema or any other abstractions.` + ## Key Features: diff --git a/examples/personality_finder_vision.py b/examples/personality_finder_vision.py index f430443..77d59df 100644 --- a/examples/personality_finder_vision.py +++ b/examples/personality_finder_vision.py @@ -1,9 +1,10 @@ -from semantix import Semantic, with_llm -from semantix.llms.openai import OpenAI -from semantix.media import Image from enum import Enum from typing import List +from semantix import Semantic, with_llm +from semantix.llms.openai import OpenAI +from semantix.types import Image + llm = OpenAI() @@ -61,5 +62,5 @@ def get_person_info( if __name__ == "__main__": - person_obj = get_person_info(img=Image("mandela.jpg")) + person_obj = get_person_info(img=Image("examples/mandela.jpg")) print(person_obj) diff --git a/semantix/__init__.py b/semantix/__init__.py index 0e34f2e..f8d7ad4 100644 --- a/semantix/__init__.py +++ b/semantix/__init__.py @@ -1,7 +1,6 @@ """Semantix is a Python library that give superpowers to your code.""" from semantix.decorators import tool, with_llm -from semantix.media import Image, Video -from semantix.types import Semantic, SemanticClass +from semantix.types.semantic import Semantic, SemanticClass -__all__ = ["Semantic", "with_llm", "tool", "Image", "Video", "SemanticClass"] +__all__ = ["Semantic", "with_llm", "tool", "SemanticClass"] diff --git a/semantix/decorators.py b/semantix/decorators.py index 67176d3..e291dd0 100644 --- a/semantix/decorators.py +++ b/semantix/decorators.py @@ -10,7 +10,8 @@ PromptInfo, ) from semantix.llms.base import BaseLLM -from semantix.types import Information, OutputHint, Semantic, Tool, TypeExplanation +from semantix.types.prompt import Information, OutputHint, Tool, TypeExplanation +from semantix.types.semantic import Semantic from semantix.utils import get_semstr diff --git a/semantix/inference.py b/semantix/inference.py index bae9e6c..cc39f51 100644 --- a/semantix/inference.py +++ b/semantix/inference.py @@ -4,7 +4,7 @@ from typing import List from semantix.llms.base import BaseLLM -from semantix.types import Information, OutputHint, Tool, TypeExplanation +from semantix.types.prompt import Information, OutputHint, Tool, TypeExplanation class PromptInfo: diff --git a/semantix/types/__init__.py b/semantix/types/__init__.py new file mode 100644 index 0000000..faaaef4 --- /dev/null +++ b/semantix/types/__init__.py @@ -0,0 +1,5 @@ +"""Type definitions for Semantix.""" + +from semantix.types.media import Image, Video + +__all__ = ["Image", "Video"] diff --git a/semantix/media.py b/semantix/types/media.py similarity index 97% rename from semantix/media.py rename to semantix/types/media.py index 383980f..50e5916 100644 --- a/semantix/media.py +++ b/semantix/types/media.py @@ -67,14 +67,14 @@ def __init__(self, file_path: str) -> None: """Initializes the Image class.""" assert ( PILImage is not None - ), "Please install the required dependencies by running `pip install mtllm[image]`." + ), "Please install the required dependencies by running `pip install semantix[image]`." self.file_path = file_path def process(self) -> Tuple[str, str]: """Processes the image and returns a base64 encoded image and its format.""" assert ( PILImage is not None - ), "Please install the required dependencies by running `pip install mtllm[image]`." + ), "Please install the required dependencies by running `pip install semantix[image]`." image = PILImage.open(self.file_path) img_format = image.format with BytesIO() as buffer: diff --git a/semantix/types.py b/semantix/types/prompt.py similarity index 75% rename from semantix/types.py rename to semantix/types/prompt.py index d677feb..c576d59 100644 --- a/semantix/types.py +++ b/semantix/types/prompt.py @@ -1,11 +1,10 @@ -"""This module contains the classes and functions to represent the types and information needed for the library.""" +"""Module to represent the prompt types.""" -import inspect -import sys from enum import Enum from types import FrameType -from typing import Any, Callable, Dict, Generic, List, Type, TypeVar, Union +from typing import Any, Callable, Dict, List, Type, Union +from semantix.types.semantic import Semantic from semantix.utils import ( extract_non_primary_type, get_object_string, @@ -14,75 +13,6 @@ ) -T = TypeVar("T") - - -class SemanticMeta(type): - """Metaclass for the Semantic class.""" - - def __new__( - mcs, name: str, bases: tuple, namespace: dict, **kwargs: dict # noqa: N804 - ) -> Any: # noqa: ANN401 - """Creates a new instance of the class.""" - cls = super().__new__(mcs, name, bases, namespace) - if "meaning" in kwargs and hasattr(cls, "meaning"): - cls._meaning = kwargs["meaning"] # type: ignore - return cls - - def __getitem__(cls, params: tuple) -> Type[T]: - """Get the item from the class.""" - if not isinstance(params, tuple) or len(params) != 2: - raise TypeError("Semantic requires two parameters: type and meaning") - typ, meaning = params - curr_frame = inspect.currentframe() - if curr_frame: - frame = curr_frame.f_back - if not frame: - raise Exception("Cannot get the current frame.") - var_name = list(frame.f_locals.keys())[-1] - # Set the meaning of the variable in the module's global scope - if var_name: - setattr( - sys.modules[frame.f_globals["__name__"]], f"{var_name}_meaning", meaning - ) - return type( - f"MT_{get_type(typ)}", (cls,), {"wrapped_type": typ, "_meaning": meaning} - ) - - -class Semantic(Generic[T], metaclass=SemanticMeta): - """Class to represent the semantic type.""" - - wrapped_type: Type[T] - _meaning: str = "" - - def __new__(cls, *args: list, **kwargs: dict) -> Any: # noqa: ANN401 - """Creates a new instance of the class.""" - return cls.wrapped_type(*args, **kwargs) - - def __instancecheck__(self, instance: Any) -> bool: # noqa: ANN401 - """Check if the instance is of the class.""" - return isinstance(instance, self.wrapped_type) - - def __subclasscheck__(self, subclass: Type) -> bool: - """Check if the subclass is of the class.""" - return issubclass(subclass, self.wrapped_type) - - def __repr__(self) -> str: - """Get the representation of the class.""" - return f"{self.wrapped_type.__name__} {self._meaning}" - - -class SemanticClass: - """Class to represent the semantic class.""" - - @classmethod - def init(cls, *args: list, **kwargs: dict) -> Any: # noqa: ANN401 - """Initialize the class.""" - # TODO: Implement the initialization of the class with llms - return cls.__class__(*args, **kwargs) - - class TypeExplanation: """Class to represent the type explanation.""" diff --git a/semantix/types/semantic.py b/semantix/types/semantic.py new file mode 100644 index 0000000..838444f --- /dev/null +++ b/semantix/types/semantic.py @@ -0,0 +1,76 @@ +"""This module contains the classes and functions to represent the types and information needed for the library.""" + +import inspect +import sys +from typing import Any, Generic, Type, TypeVar + +from semantix.utils import get_type + + +T = TypeVar("T") + + +class SemanticMeta(type): + """Metaclass for the Semantic class.""" + + def __new__( + mcs, name: str, bases: tuple, namespace: dict, **kwargs: dict # noqa: N804 + ) -> Any: # noqa: ANN401 + """Creates a new instance of the class.""" + cls = super().__new__(mcs, name, bases, namespace) + if "meaning" in kwargs and hasattr(cls, "meaning"): + cls._meaning = kwargs["meaning"] # type: ignore + return cls + + def __getitem__(cls, params: tuple) -> Type[T]: + """Get the item from the class.""" + if not isinstance(params, tuple) or len(params) != 2: + raise TypeError("Semantic requires two parameters: type and meaning") + typ, meaning = params + curr_frame = inspect.currentframe() + if curr_frame: + frame = curr_frame.f_back + if not frame: + raise Exception("Cannot get the current frame.") + var_name = list(frame.f_locals.keys())[-1] + # Set the meaning of the variable in the module's global scope + if var_name: + setattr( + sys.modules[frame.f_globals["__name__"]], f"{var_name}_meaning", meaning + ) + return type( + f"MT_{get_type(typ)}", (cls,), {"wrapped_type": typ, "_meaning": meaning} + ) + + +class Semantic(Generic[T], metaclass=SemanticMeta): + """Class to represent the semantic type.""" + + wrapped_type: Type[T] + _meaning: str = "" + + def __new__(cls, *args: list, **kwargs: dict) -> Any: # noqa: ANN401 + """Creates a new instance of the class.""" + return cls.wrapped_type(*args, **kwargs) + + def __instancecheck__(self, instance: Any) -> bool: # noqa: ANN401 + """Check if the instance is of the class.""" + return isinstance(instance, self.wrapped_type) + + def __subclasscheck__(self, subclass: Type) -> bool: + """Check if the subclass is of the class.""" + return issubclass(subclass, self.wrapped_type) + + def __repr__(self) -> str: + """Get the representation of the class.""" + return f"{self.wrapped_type.__name__} {self._meaning}" + + +class SemanticClass: + """Class to represent the semantic class.""" + + @classmethod + def init(cls, *args: list, **kwargs: dict) -> Any: # noqa: ANN401 + """Initialize the class.""" + # TODO: Implement the initialization of the class with llms + return cls.__class__(*args, **kwargs)