aboutsummaryrefslogtreecommitdiff
path: root/autogpts/autogpt/autogpt/agents/utils/prompt_scratchpad.py
blob: 07b324254f33f33dce484109cf59c44b14f21459 (plain)
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
107
108
import logging
from typing import Callable

from pydantic import BaseModel, Field

from autogpt.core.resource.model_providers.schema import CompletionModelFunction
from autogpt.core.utils.json_schema import JSONSchema

logger = logging.getLogger("PromptScratchpad")


class CallableCompletionModelFunction(CompletionModelFunction):
    method: Callable


class PromptScratchpad(BaseModel):
    commands: dict[str, CallableCompletionModelFunction] = Field(default_factory=dict)
    resources: list[str] = Field(default_factory=list)
    constraints: list[str] = Field(default_factory=list)
    best_practices: list[str] = Field(default_factory=list)

    def add_constraint(self, constraint: str) -> None:
        """
        Add a constraint to the constraints list.

        Params:
            constraint (str): The constraint to be added.
        """
        if constraint not in self.constraints:
            self.constraints.append(constraint)

    def add_command(
        self,
        name: str,
        description: str,
        params: dict[str, str | dict],
        function: Callable,
    ) -> None:
        """
        Registers a command.

        *Should only be used by plugins.* Native commands should be added
        directly to the CommandRegistry.

        Params:
            name (str): The name of the command (e.g. `command_name`).
            description (str): The description of the command.
            params (dict, optional): A dictionary containing argument names and their
              types. Defaults to an empty dictionary.
            function (callable, optional): A callable function to be called when
                the command is executed. Defaults to None.
        """
        for p, s in params.items():
            invalid = False
            if type(s) == str and s not in JSONSchema.Type._value2member_map_:
                invalid = True
                logger.warning(
                    f"Cannot add command '{name}':"
                    f" parameter '{p}' has invalid type '{s}'."
                    f" Valid types are: {JSONSchema.Type._value2member_map_.keys()}"
                )
            elif isinstance(s, dict):
                try:
                    JSONSchema.from_dict(s)
                except KeyError:
                    invalid = True
            if invalid:
                return

        command = CallableCompletionModelFunction(
            name=name,
            description=description,
            parameters={
                name: JSONSchema(type=JSONSchema.Type._value2member_map_[spec])
                if type(spec) == str
                else JSONSchema.from_dict(spec)
                for name, spec in params.items()
            },
            method=function,
        )

        if name in self.commands:
            if description == self.commands[name].description:
                return
            logger.warning(
                f"Replacing command {self.commands[name]} with conflicting {command}"
            )
        self.commands[name] = command

    def add_resource(self, resource: str) -> None:
        """
        Add a resource to the resources list.

        Params:
            resource (str): The resource to be added.
        """
        if resource not in self.resources:
            self.resources.append(resource)

    def add_best_practice(self, best_practice: str) -> None:
        """
        Add an item to the list of best practices.

        Params:
            best_practice (str): The best practice item to be added.
        """
        if best_practice not in self.best_practices:
            self.best_practices.append(best_practice)