|
|
from __future__ import annotations |
|
|
|
|
|
from dataclasses import dataclass |
|
|
from enum import Enum |
|
|
from typing import TYPE_CHECKING, Any, Optional, TypedDict |
|
|
|
|
|
from taskweaver.utils import create_id |
|
|
|
|
|
|
|
|
class AttachmentType(Enum): |
|
|
|
|
|
init_plan = "init_plan" |
|
|
plan = "plan" |
|
|
current_plan_step = "current_plan_step" |
|
|
|
|
|
|
|
|
thought = "thought" |
|
|
python = "python" |
|
|
|
|
|
|
|
|
sample = "sample" |
|
|
|
|
|
|
|
|
verification = "verification" |
|
|
|
|
|
|
|
|
text = "text" |
|
|
|
|
|
|
|
|
code_error = "code_error" |
|
|
execution_status = "execution_status" |
|
|
execution_result = "execution_result" |
|
|
artifact_paths = "artifact_paths" |
|
|
|
|
|
|
|
|
revise_message = "revise_message" |
|
|
|
|
|
|
|
|
function = "function" |
|
|
|
|
|
|
|
|
invalid_response = "invalid_response" |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class Attachment: |
|
|
if TYPE_CHECKING: |
|
|
AttachmentDict = TypedDict( |
|
|
"AttachmentDict", |
|
|
{"type": str, "content": str, "id": Optional[str], "extra": Optional[Any]}, |
|
|
) |
|
|
|
|
|
"""Attachment is the unified interface for responses attached to the text massage. |
|
|
|
|
|
Args: |
|
|
type: the type of the attachment, which can be "thought", "code", "markdown", or "execution_result". |
|
|
content: the content of the response element. |
|
|
id: the unique id of the response element. |
|
|
""" |
|
|
|
|
|
id: str |
|
|
type: AttachmentType |
|
|
content: str |
|
|
extra: Optional[Any] = None |
|
|
|
|
|
@staticmethod |
|
|
def create( |
|
|
type: AttachmentType, |
|
|
content: str, |
|
|
id: Optional[str] = None, |
|
|
) -> Attachment: |
|
|
import builtins |
|
|
|
|
|
if builtins.type(type) is str: |
|
|
type = AttachmentType(type) |
|
|
assert type in AttachmentType, f"Invalid attachment type: {type}" |
|
|
id = id if id is not None else "atta-" + create_id() |
|
|
return Attachment( |
|
|
type=type, |
|
|
content=content, |
|
|
id=id, |
|
|
) |
|
|
|
|
|
def __repr__(self) -> str: |
|
|
return f"{self.type.value.upper()}: {self.content}" |
|
|
|
|
|
def __str__(self) -> str: |
|
|
return self.__repr__() |
|
|
|
|
|
def to_dict(self) -> AttachmentDict: |
|
|
return { |
|
|
"id": self.id, |
|
|
"type": self.type.value, |
|
|
"content": self.content, |
|
|
"extra": self.extra, |
|
|
} |
|
|
|
|
|
@staticmethod |
|
|
def from_dict(content: AttachmentDict) -> Attachment: |
|
|
type = AttachmentType(content["type"]) |
|
|
return Attachment.create( |
|
|
type=type, |
|
|
content=content["content"], |
|
|
id=content["id"] if "id" in content else None, |
|
|
) |
|
|
|