Skip to content

Commit

Permalink
refactor(backend): Make block fields consistently use SchemaField (#8360
Browse files Browse the repository at this point in the history
)
  • Loading branch information
majdyz authored Oct 18, 2024
1 parent 7f6354c commit 26b1bca
Show file tree
Hide file tree
Showing 18 changed files with 338 additions and 150 deletions.
11 changes: 11 additions & 0 deletions autogpt_platform/backend/backend/blocks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ def all_subclasses(clz):
f"{block.name} `error` field in output_schema must be a string"
)

# Make sure all fields in input_schema and output_schema are annotated and has a value
for field_name, field in [*input_schema.items(), *output_schema.items()]:
if field.annotation is None:
raise ValueError(
f"{block.name} has a field {field_name} that is not annotated"
)
if field.json_schema_extra is None:
raise ValueError(
f"{block.name} has a field {field_name} not defined as SchemaField"
)

for field in block.input_schema.model_fields.values():
if field.annotation is bool and field.default not in (True, False):
raise ValueError(f"{block.name} has a boolean field with no default value")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from enum import Enum

import requests
from pydantic import Field

from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import BlockSecret, SchemaField, SecretField
Expand Down Expand Up @@ -129,9 +128,13 @@ class Input(BlockSchema):
description="""1. Use short and punctuated sentences\n\n2. Use linebreaks to create a new clip\n\n3. Text outside of brackets is spoken by the AI, and [text between brackets] will be used to guide the visual generation. For example, [close-up of a cat] will show a close-up of a cat.""",
placeholder="[close-up of a cat] Meow!",
)
ratio: str = Field(description="Aspect ratio of the video", default="9 / 16")
resolution: str = Field(description="Resolution of the video", default="720p")
frame_rate: int = Field(description="Frame rate of the video", default=60)
ratio: str = SchemaField(
description="Aspect ratio of the video", default="9 / 16"
)
resolution: str = SchemaField(
description="Resolution of the video", default="720p"
)
frame_rate: int = SchemaField(description="Frame rate of the video", default=60)
generation_preset: GenerationPreset = SchemaField(
description="Generation preset for visual style - only effects AI generated visuals",
default=GenerationPreset.LEONARDO,
Expand All @@ -154,8 +157,8 @@ class Input(BlockSchema):
)

class Output(BlockSchema):
video_url: str = Field(description="The URL of the created video")
error: str = Field(description="Error message if the request failed")
video_url: str = SchemaField(description="The URL of the created video")
error: str = SchemaField(description="Error message if the request failed")

def __init__(self):
super().__init__(
Expand Down
21 changes: 11 additions & 10 deletions autogpt_platform/backend/backend/blocks/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from typing import Any, List

from jinja2 import BaseLoader, Environment
from pydantic import Field

from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema, BlockType
from backend.data.model import SchemaField
Expand All @@ -19,18 +18,18 @@ class StoreValueBlock(Block):
"""

class Input(BlockSchema):
input: Any = Field(
input: Any = SchemaField(
description="Trigger the block to produce the output. "
"The value is only used when `data` is None."
)
data: Any = Field(
data: Any = SchemaField(
description="The constant data to be retained in the block. "
"This value is passed as `output`.",
default=None,
)

class Output(BlockSchema):
output: Any
output: Any = SchemaField(description="The stored data retained in the block.")

def __init__(self):
super().__init__(
Expand All @@ -56,10 +55,10 @@ def run(self, input_data: Input, **kwargs) -> BlockOutput:

class PrintToConsoleBlock(Block):
class Input(BlockSchema):
text: str
text: str = SchemaField(description="The text to print to the console.")

class Output(BlockSchema):
status: str
status: str = SchemaField(description="The status of the print operation.")

def __init__(self):
super().__init__(
Expand All @@ -79,12 +78,14 @@ def run(self, input_data: Input, **kwargs) -> BlockOutput:

class FindInDictionaryBlock(Block):
class Input(BlockSchema):
input: Any = Field(description="Dictionary to lookup from")
key: str | int = Field(description="Key to lookup in the dictionary")
input: Any = SchemaField(description="Dictionary to lookup from")
key: str | int = SchemaField(description="Key to lookup in the dictionary")

class Output(BlockSchema):
output: Any = Field(description="Value found for the given key")
missing: Any = Field(description="Value of the input that missing the key")
output: Any = SchemaField(description="Value found for the given key")
missing: Any = SchemaField(
description="Value of the input that missing the key"
)

def __init__(self):
super().__init__(
Expand Down
13 changes: 10 additions & 3 deletions autogpt_platform/backend/backend/blocks/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Type

from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import SchemaField


class BlockInstallationBlock(Block):
Expand All @@ -15,11 +16,17 @@ class BlockInstallationBlock(Block):
"""

class Input(BlockSchema):
code: str
code: str = SchemaField(
description="Python code of the block to be installed",
)

class Output(BlockSchema):
success: str
error: str
success: str = SchemaField(
description="Success message if the block is installed successfully",
)
error: str = SchemaField(
description="Error message if the block installation fails",
)

def __init__(self):
super().__init__(
Expand Down
50 changes: 39 additions & 11 deletions autogpt_platform/backend/backend/blocks/csv.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import ContributorDetails
from backend.data.model import ContributorDetails, SchemaField


class ReadCsvBlock(Block):
class Input(BlockSchema):
contents: str
delimiter: str = ","
quotechar: str = '"'
escapechar: str = "\\"
has_header: bool = True
skip_rows: int = 0
strip: bool = True
skip_columns: list[str] = []
contents: str = SchemaField(
description="The contents of the CSV file to read",
placeholder="a, b, c\n1,2,3\n4,5,6",
)
delimiter: str = SchemaField(
description="The delimiter used in the CSV file",
default=",",
)
quotechar: str = SchemaField(
description="The character used to quote fields",
default='"',
)
escapechar: str = SchemaField(
description="The character used to escape the delimiter",
default="\\",
)
has_header: bool = SchemaField(
description="Whether the CSV file has a header row",
default=True,
)
skip_rows: int = SchemaField(
description="The number of rows to skip from the start of the file",
default=0,
)
strip: bool = SchemaField(
description="Whether to strip whitespace from the values",
default=True,
)
skip_columns: list[str] = SchemaField(
description="The columns to skip from the start of the row",
default=[],
)

class Output(BlockSchema):
row: dict[str, str]
all_data: list[dict[str, str]]
row: dict[str, str] = SchemaField(
description="The data produced from each row in the CSV file"
)
all_data: list[dict[str, str]] = SchemaField(
description="All the data in the CSV file as a list of rows"
)

def __init__(self):
super().__init__(
Expand Down
21 changes: 12 additions & 9 deletions autogpt_platform/backend/backend/blocks/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,28 @@

import aiohttp
import discord
from pydantic import Field

from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import BlockSecret, SecretField
from backend.data.model import BlockSecret, SchemaField, SecretField


class ReadDiscordMessagesBlock(Block):
class Input(BlockSchema):
discord_bot_token: BlockSecret = SecretField(
key="discord_bot_token", description="Discord bot token"
)
continuous_read: bool = Field(
continuous_read: bool = SchemaField(
description="Whether to continuously read messages", default=True
)

class Output(BlockSchema):
message_content: str = Field(description="The content of the message received")
channel_name: str = Field(
message_content: str = SchemaField(
description="The content of the message received"
)
channel_name: str = SchemaField(
description="The name of the channel the message was received from"
)
username: str = Field(
username: str = SchemaField(
description="The username of the user who sent the message"
)

Expand Down Expand Up @@ -134,13 +135,15 @@ class Input(BlockSchema):
discord_bot_token: BlockSecret = SecretField(
key="discord_bot_token", description="Discord bot token"
)
message_content: str = Field(description="The content of the message received")
channel_name: str = Field(
message_content: str = SchemaField(
description="The content of the message received"
)
channel_name: str = SchemaField(
description="The name of the channel the message was received from"
)

class Output(BlockSchema):
status: str = Field(
status: str = SchemaField(
description="The status of the operation (e.g., 'Message sent', 'Error')"
)

Expand Down
8 changes: 4 additions & 4 deletions autogpt_platform/backend/backend/blocks/email_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, ConfigDict

from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import BlockSecret, SchemaField, SecretField


class EmailCredentials(BaseModel):
smtp_server: str = Field(
smtp_server: str = SchemaField(
default="smtp.gmail.com", description="SMTP server address"
)
smtp_port: int = Field(default=25, description="SMTP port number")
smtp_port: int = SchemaField(default=25, description="SMTP port number")
smtp_username: BlockSecret = SecretField(key="smtp_username")
smtp_password: BlockSecret = SecretField(key="smtp_password")

Expand All @@ -30,7 +30,7 @@ class Input(BlockSchema):
body: str = SchemaField(
description="Body of the email", placeholder="Enter the email body"
)
creds: EmailCredentials = Field(
creds: EmailCredentials = SchemaField(
description="SMTP credentials",
default=EmailCredentials(),
)
Expand Down
27 changes: 20 additions & 7 deletions autogpt_platform/backend/backend/blocks/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import requests

from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import SchemaField


class HttpMethod(Enum):
Expand All @@ -18,15 +19,27 @@ class HttpMethod(Enum):

class SendWebRequestBlock(Block):
class Input(BlockSchema):
url: str
method: HttpMethod = HttpMethod.POST
headers: dict[str, str] = {}
body: object = {}
url: str = SchemaField(
description="The URL to send the request to",
placeholder="https://api.example.com",
)
method: HttpMethod = SchemaField(
description="The HTTP method to use for the request",
default=HttpMethod.POST,
)
headers: dict[str, str] = SchemaField(
description="The headers to include in the request",
default={},
)
body: object = SchemaField(
description="The body of the request",
default={},
)

class Output(BlockSchema):
response: object
client_error: object
server_error: object
response: object = SchemaField(description="The response from the server")
client_error: object = SchemaField(description="The error on 4xx status codes")
server_error: object = SchemaField(description="The error on 5xx status codes")

def __init__(self):
super().__init__(
Expand Down
6 changes: 0 additions & 6 deletions autogpt_platform/backend/backend/blocks/ideogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,24 @@ class Input(BlockSchema):
description="The name of the Image Generation Model, e.g., V_2",
default=IdeogramModelName.V2,
title="Image Generation Model",
enum=IdeogramModelName,
advanced=False,
)
aspect_ratio: AspectRatio = SchemaField(
description="Aspect ratio for the generated image",
default=AspectRatio.ASPECT_1_1,
title="Aspect Ratio",
enum=AspectRatio,
advanced=False,
)
upscale: UpscaleOption = SchemaField(
description="Upscale the generated image",
default=UpscaleOption.NO_UPSCALE,
title="Upscale Image",
enum=UpscaleOption,
advanced=False,
)
magic_prompt_option: MagicPromptOption = SchemaField(
description="Whether to use MagicPrompt for enhancing the request",
default=MagicPromptOption.AUTO,
title="Magic Prompt Option",
enum=MagicPromptOption,
advanced=True,
)
seed: Optional[int] = SchemaField(
Expand All @@ -109,7 +105,6 @@ class Input(BlockSchema):
description="Style type to apply, applicable for V_2 and above",
default=StyleType.AUTO,
title="Style Type",
enum=StyleType,
advanced=True,
)
negative_prompt: Optional[str] = SchemaField(
Expand All @@ -122,7 +117,6 @@ class Input(BlockSchema):
description="Color palette preset name, choose 'None' to skip",
default=ColorPalettePreset.NONE,
title="Color Palette Preset",
enum=ColorPalettePreset,
advanced=True,
)

Expand Down
Loading

0 comments on commit 26b1bca

Please sign in to comment.