Skip to content

Commit

Permalink
Merge branch 'master' into plugins/fix-loading-and-init
Browse files Browse the repository at this point in the history
  • Loading branch information
Pwuts committed Jul 5, 2023
2 parents f48ade4 + b9f0133 commit c1beebd
Show file tree
Hide file tree
Showing 61 changed files with 3,863 additions and 44 deletions.
6 changes: 3 additions & 3 deletions autogpt/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class ConfigBuilder(Configurable[Config]):
else:
default_tts_provider = "gtts"

defaults_settings = Config(
default_settings = Config(
name="Default Server Config",
description="This is a default server configuration",
smart_llm_model="gpt-3.5-turbo",
Expand All @@ -114,7 +114,7 @@ class ConfigBuilder(Configurable[Config]):
skip_news=False,
debug_mode=False,
plugins_dir="plugins",
plugins_config=PluginsConfig({}),
plugins_config=PluginsConfig(plugins={}),
speak_mode=False,
skip_reprompt=False,
allow_downloads=False,
Expand Down Expand Up @@ -158,7 +158,7 @@ class ConfigBuilder(Configurable[Config]):
)

@classmethod
def build_config_from_env(cls):
def build_config_from_env(cls) -> Config:
"""Initialize the Config class"""
config_dict = {
"authorise_key": os.getenv("AUTHORISE_COMMAND_KEY"),
Expand Down
54 changes: 54 additions & 0 deletions autogpt/core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Run instructions

There are two client applications for Auto-GPT included.

## CLI Application

:star2: **This is the reference application I'm working with for now** :star2:

The first app is a straight CLI application. I have not done anything yet to port all the friendly display stuff from the `logger.typewriter_log` logic.

- [Entry Point](https://github.com/Significant-Gravitas/Auto-GPT/blob/master/autogpt/core/runner/cli_app/cli.py)
- [Client Application](https://github.com/Significant-Gravitas/Auto-GPT/blob/master/autogpt/core/runner/cli_app/main.py)

To run, you first need a settings file. Run

```
python REPOSITORY_ROOT/autogpt/core/runner/cli_app/cli.py make-settings
```

where `REPOSITORY_ROOT` is the root of the Auto-GPT repository on your machine. This will write a file called `default_agent_settings.yaml` with all the user-modifiable configuration keys to `~/auto-gpt/default_agent_settings.yml` and make the `auto-gpt` directory in your user directory if it doesn't exist). At a bare minimum, you'll need to set `openai.credentials.api_key` to your OpenAI API Key to run the model.

You can then run Auto-GPT with

```
python REPOSITORY_ROOT/autogpt/core/runner/cli_app/cli.py make-settings
```

to launch the interaction loop.

## CLI Web App

The second app is still a CLI, but it sets up a local webserver that the client application talks to rather than invoking calls to the Agent library code directly. This application is essentially a sketch at this point as the folks who were driving it have had less time (and likely not enough clarity) to proceed.

- [Entry Point](https://github.com/Significant-Gravitas/Auto-GPT/blob/master/autogpt/core/runner/cli_web_app/cli.py)
- [Client Application](https://github.com/Significant-Gravitas/Auto-GPT/blob/master/autogpt/core/runner/cli_web_app/client/client.py)
- [Server API](https://github.com/Significant-Gravitas/Auto-GPT/blob/master/autogpt/core/runner/cli_web_app/server/api.py)

To run, you still need to generate a default configuration. You can do

```
python REPOSITORY_ROOT/autogpt/core/runner/cli_web_app/cli.py make-settings
```

It invokes the same command as the bare CLI app, so follow the instructions above about setting your API key.

To run, do

```
python REPOSITORY_ROOT/autogpt/core/runner/cli_web_app/cli.py client
```

This will launch a webserver and then start the client cli application to communicate with it.

:warning: I am not actively developing this application. It is a very good place to get involved if you have web application design experience and are looking to get involved in the re-arch.
Empty file added autogpt/core/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions autogpt/core/ability/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""The command system provides a way to extend the functionality of the AI agent."""
from autogpt.core.ability.base import Ability, AbilityRegistry
from autogpt.core.ability.schema import AbilityResult
from autogpt.core.ability.simple import AbilityRegistrySettings, SimpleAbilityRegistry
92 changes: 92 additions & 0 deletions autogpt/core/ability/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import abc
from pprint import pformat
from typing import ClassVar

import inflection
from pydantic import Field

from autogpt.core.ability.schema import AbilityResult
from autogpt.core.configuration import SystemConfiguration
from autogpt.core.planning.simple import LanguageModelConfiguration


class AbilityConfiguration(SystemConfiguration):
"""Struct for model configuration."""

from autogpt.core.plugin.base import PluginLocation

location: PluginLocation
packages_required: list[str] = Field(default_factory=list)
language_model_required: LanguageModelConfiguration = None
memory_provider_required: bool = False
workspace_required: bool = False


class Ability(abc.ABC):
"""A class representing an agent ability."""

default_configuration: ClassVar[AbilityConfiguration]

@classmethod
def name(cls) -> str:
"""The name of the ability."""
return inflection.underscore(cls.__name__)

@classmethod
@abc.abstractmethod
def description(cls) -> str:
"""A detailed description of what the ability does."""
...

@classmethod
@abc.abstractmethod
def arguments(cls) -> dict:
"""A dict of arguments in standard json schema format."""
...

@classmethod
def required_arguments(cls) -> list[str]:
"""A list of required arguments."""
return []

@abc.abstractmethod
async def __call__(self, *args, **kwargs) -> AbilityResult:
...

def __str__(self) -> str:
return pformat(self.dump)

def dump(self) -> dict:
return {
"name": self.name(),
"description": self.description(),
"parameters": {
"type": "object",
"properties": self.arguments(),
"required": self.required_arguments(),
},
}


class AbilityRegistry(abc.ABC):
@abc.abstractmethod
def register_ability(
self, ability_name: str, ability_configuration: AbilityConfiguration
) -> None:
...

@abc.abstractmethod
def list_abilities(self) -> list[str]:
...

@abc.abstractmethod
def dump_abilities(self) -> list[dict]:
...

@abc.abstractmethod
def get_ability(self, ability_name: str) -> Ability:
...

@abc.abstractmethod
def perform(self, ability_name: str, **kwargs) -> AbilityResult:
...
6 changes: 6 additions & 0 deletions autogpt/core/ability/builtins/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from autogpt.core.ability.builtins.create_new_ability import CreateNewAbility
from autogpt.core.ability.builtins.query_language_model import QueryLanguageModel

BUILTIN_ABILITIES = {
QueryLanguageModel.name(): QueryLanguageModel,
}
102 changes: 102 additions & 0 deletions autogpt/core/ability/builtins/create_new_ability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import logging

from autogpt.core.ability.base import Ability, AbilityConfiguration
from autogpt.core.ability.schema import AbilityResult
from autogpt.core.plugin.simple import PluginLocation, PluginStorageFormat


class CreateNewAbility(Ability):
default_configuration = AbilityConfiguration(
location=PluginLocation(
storage_format=PluginStorageFormat.INSTALLED_PACKAGE,
storage_route="autogpt.core.ability.builtins.CreateNewAbility",
),
)

def __init__(
self,
logger: logging.Logger,
configuration: AbilityConfiguration,
):
self._logger = logger
self._configuration = configuration

@classmethod
def description(cls) -> str:
return "Create a new ability by writing python code."

@classmethod
def arguments(cls) -> dict:
return {
"ability_name": {
"type": "string",
"description": "A meaningful and concise name for the new ability.",
},
"description": {
"type": "string",
"description": "A detailed description of the ability and its uses, including any limitations.",
},
"arguments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the argument.",
},
"type": {
"type": "string",
"description": "The type of the argument. Must be a standard json schema type.",
},
"description": {
"type": "string",
"description": "A detailed description of the argument and its uses.",
},
},
},
"description": "A list of arguments that the ability will accept.",
},
"required_arguments": {
"type": "array",
"items": {
"type": "string",
"description": "The names of the arguments that are required.",
},
"description": "A list of the names of the arguments that are required.",
},
"package_requirements": {
"type": "array",
"items": {
"type": "string",
"description": "The of the Python package that is required to execute the ability.",
},
"description": "A list of the names of the Python packages that are required to execute the ability.",
},
"code": {
"type": "string",
"description": "The Python code that will be executed when the ability is called.",
},
}

@classmethod
def required_arguments(cls) -> list[str]:
return [
"ability_name",
"description",
"arguments",
"required_arguments",
"package_requirements",
"code",
]

async def __call__(
self,
ability_name: str,
description: str,
arguments: list[dict],
required_arguments: list[str],
package_requirements: list[str],
code: str,
) -> AbilityResult:
raise NotImplementedError
Loading

0 comments on commit c1beebd

Please sign in to comment.