Spaces:
Running
Running
| # SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: BSD 2-Clause License | |
| """Custom view frames.""" | |
| import json | |
| from abc import ABC, abstractmethod | |
| from dataclasses import dataclass | |
| from enum import Enum | |
| from pipecat.frames.frames import DataFrame | |
| from pydantic import BaseModel, Field | |
| from nvidia_pipecat.frames.action import ( | |
| StartActionFrame, | |
| StopActionFrame, | |
| UserActionFrame, | |
| ) | |
| # Block types | |
| class Block(BaseModel, ABC): | |
| """A block is a modular component that can be rendered in the UI. | |
| Multiple blocks can be rendered at a time. | |
| Args: | |
| id (str): A unique id for the block. | |
| """ | |
| id: str | |
| def get_type(self) -> str: | |
| """Get the type of the block. | |
| Type indicates what data is included in the block and is used to determine how to render the block in the UI. | |
| """ | |
| class HeaderBlock(Block): | |
| """A header block displays a header or subheader in the UI. | |
| Args: | |
| header (str): The text to display in the header. | |
| level (int): The level of the header, corresponding to HTML element tags for header (h1, h2, etc.). | |
| Must be between 1 and 6. | |
| """ | |
| header: str | |
| level: int = Field(ge=1, le=6) | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "header" | |
| class TextBlock(Block): | |
| """A text block displays text as a paragraph in the UI. | |
| Args: | |
| text (str): The text to display in the paragraph. | |
| """ | |
| text: str | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "paragraph" | |
| class Image(BaseModel): | |
| """Specifies the data needed to render an image. file and data fields are mutually exclusive. | |
| Args: | |
| url (str | None): The URL of the image. | |
| data (str | None): The image base64 data. | |
| """ | |
| url: str | None = None | |
| data: str | None = None | |
| class ImageBlock(Block): | |
| """An image block displays an image in the UI. | |
| Args: | |
| image (Image): The image to display. | |
| caption (str | None): The caption to display in place of the image if the image cannot be rendered. | |
| """ | |
| image: Image | |
| caption: str | None = None | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "image" | |
| class ImagePosition(str, Enum): | |
| """Enum for image position.""" | |
| LEFT = "left" | |
| RIGHT = "right" | |
| class ImageWithTextBlock(Block): | |
| """An image with text block displays an image and text in the UI. | |
| Args: | |
| image (Image): The image to display. | |
| text (str): The text to display next to the image. | |
| image_position (ImagePosition): The position of the image relative to the text. | |
| """ | |
| image: Image | |
| text: str | |
| image_position: ImagePosition | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "paragraph_with_image" | |
| class TableBlock(Block): | |
| """A table block displays a table in the UI. | |
| Args: | |
| headers (list[str]): The headers of the table. | |
| rows (list[list[str]]): The rows of the table. | |
| """ | |
| headers: list[str] | |
| rows: list[list[str]] | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "table" | |
| class Hint(BaseModel): | |
| """A hint is an example of how the user can interact with the system. | |
| Args: | |
| name (str): The name of the hint. This is used to identify the hint in the UI. | |
| text (str): The text of the hint. The text is what is displayed to the user. | |
| """ | |
| name: str | |
| text: str | |
| class HintCarouselBlock(Block): | |
| """A hint carousel block. | |
| The block rotates through a list of hints, displaying | |
| them one at a time to the user. | |
| Args: | |
| hints (list[Hint]): A list of hints to display. | |
| """ | |
| hints: list[Hint] | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "hint_carousel" | |
| class ButtonVariant(str, Enum): | |
| """Enum for button variant styles.""" | |
| OUTLINED = "outlined" | |
| CONTAINED = "contained" | |
| TEXT = "text" | |
| class Button(BaseModel): | |
| """Data format with information about a button. | |
| Args: | |
| id (str): The id of the button. | |
| active (bool): Whether the button is active. If false, the button will be grayed out and not clickable. | |
| toggled (bool): Whether the button is toggled. If true, the button will be toggled on. | |
| variant (ButtonVariant): The variant of the button. | |
| text (str): The text of the button. | |
| """ | |
| id: str | |
| active: bool | |
| toggled: bool | |
| variant: ButtonVariant | |
| text: str | |
| class ButtonListBlock(Block): | |
| """A button list block displays a list of buttons. | |
| Args: | |
| buttons (list[Button]): A list of buttons to display. | |
| """ | |
| buttons: list[Button] | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "button_list" | |
| class SelectableOption(BaseModel): | |
| """Data format for a selectable option. Can include an image and/or text. | |
| Args: | |
| id (str): The id of the selectable option. | |
| image (Image | None): The image to display within the option. | |
| text (str): The text to display within the option. | |
| active (bool): Whether the option is active. If false, the option will be grayed out and not clickable. | |
| toggled (bool): Whether the option is toggled. If true, the option will be toggled on. | |
| """ | |
| id: str | |
| image: Image | None = None | |
| text: str | |
| active: bool | |
| toggled: bool | |
| class SelectableOptionsGridBlock(Block): | |
| """A selectable options grid block. | |
| This block displays a grid of interactive options to the user. | |
| A user may select and deselect any number of options as they choose. | |
| Args: | |
| options (list[SelectableOption]): A list of selectable options to display. | |
| """ | |
| buttons: list[SelectableOption] | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "selectable_options_grid" | |
| class TextInputBlock(Block): | |
| """A text input block displays a text input to the user. | |
| Args: | |
| id (str): The id of the text input. | |
| default_value (str): The default value of the text input. | |
| value (str): The value of the text input. | |
| label (str): The label of the text input. | |
| input_type (str): The type of the text input. | |
| """ | |
| id: str | |
| default_value: str | |
| value: str | |
| label: str | |
| input_type: str | |
| def get_type(self) -> str: | |
| """Get the type of the block.""" | |
| return "text_input" | |
| class StartCustomViewFrame(StartActionFrame): | |
| """Sends data to the UI in the form of modular components to be rendered. | |
| Args: | |
| blocks (list[Block] | None): A list of modular components to display in the UI. | |
| style (Style | None): The style of the UI. | |
| """ | |
| blocks: list[Block] | None = None | |
| def to_json(self) -> str: | |
| """Convert the frame to a JSON string. | |
| This is intended to be used for serializing the frame for transmission over a WebSocket connection to the UI. | |
| """ | |
| the_json = {} | |
| if self.blocks: | |
| blocks_list_json = [] | |
| for block in self.blocks: | |
| block_json = { | |
| "id": block.id, | |
| "type": block.get_type(), | |
| "data": block.model_dump(exclude={"id"}, exclude_none=True), | |
| } | |
| blocks_list_json.append(block_json) | |
| the_json["blocks"] = blocks_list_json | |
| return json.dumps(the_json) | |
| class StopCustomViewFrame(StopActionFrame): | |
| """A frame that stops the custom view from being rendered in the UI.""" | |
| class UIInterimTextInputFrame(UserActionFrame, DataFrame): | |
| """Interim text input frame from the UI. | |
| Receives data from the UI in the form of text inputted into a textbox | |
| by the user prior to submission. | |
| Args: | |
| component_id (str): The id of the text input which is currently being typed in. | |
| interim_input (str): The interim input of the text input. | |
| """ | |
| component_id: str | |
| interim_input: str | |
| class UITextInputFrame(UserActionFrame, DataFrame): | |
| """A frame that receives data from the UI in the form of a text inputted into a textbox. | |
| This is triggered when the user submits their input. | |
| Args: | |
| enter_pressed (bool): True if the enter key was pressed to submit the text input, | |
| false if the user navigated away from the text input. | |
| component_id (str): The id of the text input which was submitted. | |
| input (str): The input of the text input. | |
| """ | |
| enter_pressed: bool | |
| component_id: str | |
| input: str | |
| class UIButtonPressFrame(UserActionFrame, DataFrame): | |
| """A frame that receives data from the UI in the form of a button press. | |
| Args: | |
| component_id (str): The id of the button which was pressed. | |
| """ | |
| component_id: str | |
| class UISelectableOptionPressFrame(UserActionFrame, DataFrame): | |
| """A frame that receives data from the UI in the form of a selectable option press. | |
| Args: | |
| component_id (str): The id of the selectable option which was pressed. | |
| toggled (bool): Whether the option is toggled. If true, the option will be toggled on. | |
| """ | |
| component_id: str | |
| toggled: bool | |