File size: 2,782 Bytes
3d3d712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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):
    # Planner Type
    init_plan = "init_plan"
    plan = "plan"
    current_plan_step = "current_plan_step"

    # CodeInterpreter - generate code
    thought = "thought"
    python = "python"

    # CodeInterpreter - sample code
    sample = "sample"

    # CodeInterpreter - verification
    verification = "verification"

    # CodeInterpreter - text message
    text = "text"

    # CodeInterpreter - execute code
    code_error = "code_error"
    execution_status = "execution_status"
    execution_result = "execution_result"
    artifact_paths = "artifact_paths"  # TODO: remove and store artifacts to extra info

    # CodeInterpreter - revise code
    revise_message = "revise_message"

    # function calling
    function = "function"

    # Misc
    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,
        )