Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
collindutter committed Aug 28, 2024
1 parent ef61c53 commit b9426c7
Show file tree
Hide file tree
Showing 53 changed files with 347 additions and 403 deletions.
Empty file added .ignore
Empty file.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Parameter `meta: dict` on `BaseEvent`.
- `TableArtifact` for storing CSV data.

### Changed
- **BREAKING**: Parameter `driver` on `BaseConversationMemory` renamed to `conversation_memory_driver`.
- **BREAKING**: `BaseConversationMemory.add_to_prompt_stack` now takes a `prompt_driver` parameter.
- **BREAKING**: `BaseConversationMemoryDriver.load` now returns `tuple[list[Run], Optional[dict]]`.
- **BREAKING**: `BaseConversationMemoryDriver.store` now takes `runs: list[Run]` and `metadata: Optional[dict]` as input.
- **BREAKING**: Parameter `file_path` on `LocalConversationMemoryDriver` renamed to `persist_file` and is now type `Optional[str]`.
- **BREAKING**: `CsvLoader` now returns a `TableArtifact` instead of a `list[CsvRowArtifact]`.
- `Defaults.drivers_config.conversation_memory_driver` now defaults to `LocalConversationMemoryDriver` instead of `None`.

### Fixed
Expand Down
7 changes: 0 additions & 7 deletions docs/griptape-framework/data/artifacts.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ An [ImageArtifact](../../reference/griptape/artifacts/image_artifact.md) is used

An [AudioArtifact](../../reference/griptape/artifacts/audio_artifact.md) allows the Framework to interact with audio content. An Audio Artifact includes binary audio content as well as metadata like format, duration, and prompt and model information for audio returned generative models. It inherits from [BlobArtifact](#blob).

## Boolean

A [BooleanArtifact](../../reference/griptape/artifacts/boolean_artifact.md) is used for passing boolean values around the framework.

!!! info
Any object passed on init to `BooleanArtifact` will be coerced into a `bool` type. This might lead to unintended behavior: `BooleanArtifact("False").value is True`. Use [BooleanArtifact.parse_bool](../../reference/griptape/artifacts/boolean_artifact.md#griptape.artifacts.boolean_artifact.BooleanArtifact.parse_bool) to convert case-insensitive string literal values `"True"` and `"False"` into a `BooleanArtifact`: `BooleanArtifact.parse_bool("False").value is False`.

## Generic

A [GenericArtifact](../../reference/griptape/artifacts/generic_artifact.md) can be used as an escape hatch for passing any type of data around the framework.
Expand Down
21 changes: 16 additions & 5 deletions griptape/artifacts/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
from .base_artifact import BaseArtifact

from .base_system_artifact import BaseSystemArtifact
from .error_artifact import ErrorArtifact
from .info_artifact import InfoArtifact

from .base_text_artifact import BaseTextArtifact
from .text_artifact import TextArtifact
from .json_artifact import JsonArtifact
from .blob_artifact import BlobArtifact
from .boolean_artifact import BooleanArtifact
from .csv_row_artifact import CsvRowArtifact
from .table_artifact import TableArtifact

from .list_artifact import ListArtifact
from .media_artifact import MediaArtifact

from .blob_artifact import BlobArtifact

from .base_media_artifact import BaseMediaArtifact
from .image_artifact import ImageArtifact
from .audio_artifact import AudioArtifact

from .action_artifact import ActionArtifact

from .generic_artifact import GenericArtifact


__all__ = [
"BaseArtifact",
"BaseMediaArtifact",
"BaseSystemArtifact",
"BaseTextArtifact",
"ErrorArtifact",
"InfoArtifact",
"TextArtifact",
"JsonArtifact",
"BlobArtifact",
"BooleanArtifact",
"CsvRowArtifact",
"ListArtifact",
"MediaArtifact",
"ImageArtifact",
"AudioArtifact",
"ActionArtifact",
"GenericArtifact",
"TableArtifact",
]
7 changes: 3 additions & 4 deletions griptape/artifacts/action_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
from attrs import define, field

from griptape.artifacts import BaseArtifact
from griptape.mixins import SerializableMixin

if TYPE_CHECKING:
from griptape.common import ToolAction


@define()
class ActionArtifact(BaseArtifact, SerializableMixin):
class ActionArtifact(BaseArtifact):
value: ToolAction = field(metadata={"serializable": True})

def __add__(self, other: BaseArtifact) -> ActionArtifact:
raise NotImplementedError
def to_text(self) -> str:
return str(self.value)
4 changes: 2 additions & 2 deletions griptape/artifacts/audio_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

from attrs import define

from griptape.artifacts import MediaArtifact
from griptape.artifacts import BaseMediaArtifact


@define
class AudioArtifact(MediaArtifact):
class AudioArtifact(BaseMediaArtifact):
"""AudioArtifact is a type of MediaArtifact representing audio."""

media_type: str = "audio"
19 changes: 1 addition & 18 deletions griptape/artifacts/base_artifact.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import json
import uuid
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Optional
Expand All @@ -25,22 +24,6 @@ class BaseArtifact(SerializableMixin, ABC):
)
value: Any = field()

@classmethod
def value_to_bytes(cls, value: Any) -> bytes:
if isinstance(value, bytes):
return value
else:
return str(value).encode()

@classmethod
def value_to_dict(cls, value: Any) -> dict:
dict_value = value if isinstance(value, dict) else json.loads(value)

return dict(dict_value.items())

def to_text(self) -> str:
return str(self.value)

def __str__(self) -> str:
return self.to_text()

Expand All @@ -51,4 +34,4 @@ def __len__(self) -> int:
return len(self.value)

@abstractmethod
def __add__(self, other: BaseArtifact) -> BaseArtifact: ...
def to_text(self) -> str: ...
27 changes: 27 additions & 0 deletions griptape/artifacts/base_media_artifact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from __future__ import annotations

from attrs import define, field

from griptape.artifacts import BaseArtifact


@define
class BaseMediaArtifact(BaseArtifact):
"""BaseMediaArtifact is a type of Artifact that represents media (image, audio, video, etc.) and can be extended to support a specific media type.
Attributes:
value: Raw bytes representing media data.
media_type: Main type of an IANA media type, such as "text", "audio", or "image".
format: Subtype of an IANA media type, such as "plain", "mp3", or "jpeg".
"""

value: bytes = field(metadata={"serializable": True})
media_type: str = field(kw_only=True, metadata={"serializable": True})
format: str = field(kw_only=True, metadata={"serializable": True})

@property
def mime_type(self) -> str:
return f"{self.media_type}/{self.format}"

def to_text(self) -> str:
return f"Media, type: {self.mime_type}, size: {len(self.value)} bytes"
12 changes: 12 additions & 0 deletions griptape/artifacts/base_system_artifact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from abc import ABC

from griptape.artifacts import BaseArtifact


class BaseSystemArtifact(BaseArtifact, ABC):
"""Base class for Artifacts specific to Griptape."""

...

def to_text(self) -> str:
return self.value
20 changes: 20 additions & 0 deletions griptape/artifacts/base_text_artifact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from __future__ import annotations

from abc import ABC, abstractmethod

from attrs import field

from griptape.artifacts import BaseArtifact


class BaseTextArtifact(BaseArtifact, ABC):
"""Base class for Artifacts specific to Griptape."""

...
value: str = field(converter=str, metadata={"serializable": True})

@abstractmethod
def __add__(self, other: BaseArtifact) -> BaseTextArtifact: ...

def to_text(self) -> str:
return self.value

Check warning on line 20 in griptape/artifacts/base_text_artifact.py

View check run for this annotation

Codecov / codecov/patch

griptape/artifacts/base_text_artifact.py#L20

Added line #L20 was not covered by tests
26 changes: 14 additions & 12 deletions griptape/artifacts/blob_artifact.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
from __future__ import annotations

import os.path
from typing import Optional
from typing import Any

from attrs import define, field
from attrs import Converter, define, field

from griptape.artifacts import BaseArtifact


@define
class BlobArtifact(BaseArtifact):
value: bytes = field(converter=BaseArtifact.value_to_bytes, metadata={"serializable": True})
dir_name: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True})
value: bytes = field(
converter=Converter(lambda value: BlobArtifact.value_to_bytes(value)),
metadata={"serializable": True},
)
encoding: str = field(default="utf-8", kw_only=True)
encoding_error_handler: str = field(default="strict", kw_only=True)

def __add__(self, other: BaseArtifact) -> BlobArtifact:
return BlobArtifact(self.value + other.value, name=self.name)

@property
def full_path(self) -> str:
return os.path.join(self.dir_name, self.name) if self.dir_name else self.name
media_type: str = field(default="application", kw_only=True)

@classmethod
def value_to_bytes(cls, value: Any) -> bytes:
if isinstance(value, bytes):
return value
else:
return str(value).encode()

def to_text(self) -> str:
return self.value.decode(encoding=self.encoding, errors=self.encoding_error_handler)
31 changes: 0 additions & 31 deletions griptape/artifacts/boolean_artifact.py

This file was deleted.

19 changes: 13 additions & 6 deletions griptape/artifacts/csv_row_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,30 @@

import csv
import io
import json
from typing import Any

from attrs import define, field
from attrs import Converter, define, field

from griptape.artifacts import BaseArtifact, TextArtifact
from griptape.artifacts import TextArtifact


@define
class CsvRowArtifact(TextArtifact):
value: dict[str, str] = field(converter=BaseArtifact.value_to_dict, metadata={"serializable": True})
value: dict[str, str] = field(
converter=Converter(lambda value: CsvRowArtifact.value_to_dict(value)), metadata={"serializable": True}
)
delimiter: str = field(default=",", kw_only=True, metadata={"serializable": True})

def __add__(self, other: BaseArtifact) -> CsvRowArtifact:
return CsvRowArtifact(self.value | other.value)

def __bool__(self) -> bool:
return len(self) > 0

@classmethod
def value_to_dict(cls, value: Any) -> dict:
dict_value = value if isinstance(value, dict) else json.loads(value)

return dict(dict_value.items())

def to_text(self) -> str:
with io.StringIO() as csvfile:
writer = csv.DictWriter(
Expand Down
7 changes: 2 additions & 5 deletions griptape/artifacts/error_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@

from attrs import define, field

from griptape.artifacts import BaseArtifact
from griptape.artifacts import BaseSystemArtifact


@define
class ErrorArtifact(BaseArtifact):
class ErrorArtifact(BaseSystemArtifact):
value: str = field(converter=str, metadata={"serializable": True})
exception: Optional[Exception] = field(default=None, kw_only=True, metadata={"serializable": False})

def __add__(self, other: BaseArtifact) -> ErrorArtifact:
return ErrorArtifact(self.value + other.value)
4 changes: 2 additions & 2 deletions griptape/artifacts/generic_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
class GenericArtifact(BaseArtifact):
value: Any = field(metadata={"serializable": True})

def __add__(self, other: BaseArtifact) -> BaseArtifact:
raise NotImplementedError
def to_text(self) -> str:
return str(self.value)
13 changes: 11 additions & 2 deletions griptape/artifacts/image_artifact.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from __future__ import annotations

import base64

from attrs import define, field

from griptape.artifacts import MediaArtifact
from griptape.artifacts import BaseMediaArtifact


@define
class ImageArtifact(MediaArtifact):
class ImageArtifact(BaseMediaArtifact):
"""ImageArtifact is a type of MediaArtifact representing an image.
Attributes:
Expand All @@ -21,3 +23,10 @@ class ImageArtifact(MediaArtifact):
media_type: str = "image"
width: int = field(kw_only=True, metadata={"serializable": True})
height: int = field(kw_only=True, metadata={"serializable": True})

@property
def base64(self) -> str:
return base64.b64encode(self.value).decode("utf-8")

def to_text(self) -> str:
return self.base64
7 changes: 2 additions & 5 deletions griptape/artifacts/info_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

from attrs import define, field

from griptape.artifacts import BaseArtifact
from griptape.artifacts import BaseSystemArtifact


@define
class InfoArtifact(BaseArtifact):
class InfoArtifact(BaseSystemArtifact):
value: str = field(converter=str, metadata={"serializable": True})

def __add__(self, other: BaseArtifact) -> InfoArtifact:
return InfoArtifact(self.value + other.value)
Loading

0 comments on commit b9426c7

Please sign in to comment.