<@ULVA73B9P> is it possible to define a pydantic m...
# ask-marvin
k
@Marvin is it possible to define a pydantic model that expects a file upload and then that gets exposed via the prefect UI
m
thought for 168.0 seconds
Short answer: not directly. In Prefect 3.x, you can define a flow parameter as a Pydantic model and it will render in the Prefect UI as a nested form, but the UI does not provide a native “file upload” widget. The parameter form is generated from the model’s JSON Schema; files aren’t a supported widget type. Common workarounds: - Base64 content in a string field (good for small files) - A URL to the file (download during the flow) - A reference to a Prefect storage block + path (e.g., S3/RemoteFileSystem), then read the file in the flow Examples 1) Base64 string
Copy code
from pydantic import BaseModel, Field
from prefect import flow
import base64

class FileInput(BaseModel):
    filename: str = Field(description="Original filename")
    file_b64: str = Field(description="Base64-encoded file content")

@flow
def process_file(inp: FileInput):
    content = base64.b64decode(inp.file_b64)
    # ... process content ...
2) URL to download
Copy code
from pydantic import BaseModel, HttpUrl
from prefect import flow
import httpx

class FileRef(BaseModel):
    file_url: HttpUrl

@flow
def process_remote_file(ref: FileRef):
    resp = httpx.get(str(ref.file_url))
    resp.raise_for_status()
    content = resp.content
    # ... process content ...
3) Storage block + path (Prefect-native) - Create/configure a storage block (e.g., an S3 or RemoteFileSystem block) in Prefect. - Pass the block name and a path as parameters; load and read in the flow.
Copy code
from pydantic import BaseModel, Field
from prefect import flow
from prefect.filesystems import RemoteFileSystem  # or use an S3/GCS-specific block

class FileLocation(BaseModel):
    block_name: str = Field(description="Name of the storage block")
    path: str = Field(description="Path within the storage")

@flow
def process_from_storage(loc: FileLocation):
    fs = RemoteFileSystem.load(loc.block_name)
    content = fs.read_path(loc.path)
    # ... process content ...
Notes - Large files are not a good fit for parameters (including base64) due to request size and UX; prefer URLs or storage blocks. - Pydantic types like Literal/Enum render nicely (e.g., dropdowns), and
Field(description=...)
shows up as help text in the UI, but there’s no file picker widget. If you can share your expected file sizes and where the files live (local, S3, GCS, HTTP), I can suggest the most ergonomic model shape and block setup.