mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-11 22:09:44 +00:00
feat: Add flow2.0 examples
This commit is contained in:
@@ -19,6 +19,7 @@ from dbgpt.core.awel.util.parameter_util import BaseDynamicOptions, OptionValue
|
|||||||
from dbgpt.core.interface.serialization import Serializable
|
from dbgpt.core.interface.serialization import Serializable
|
||||||
|
|
||||||
from .exceptions import FlowMetadataException, FlowParameterMetadataException
|
from .exceptions import FlowMetadataException, FlowParameterMetadataException
|
||||||
|
from .ui import UIComponent
|
||||||
|
|
||||||
_TYPE_REGISTRY: Dict[str, Type] = {}
|
_TYPE_REGISTRY: Dict[str, Type] = {}
|
||||||
|
|
||||||
@@ -136,6 +137,7 @@ _OPERATOR_CATEGORY_DETAIL = {
|
|||||||
"agent": _CategoryDetail("Agent", "The agent operator"),
|
"agent": _CategoryDetail("Agent", "The agent operator"),
|
||||||
"rag": _CategoryDetail("RAG", "The RAG operator"),
|
"rag": _CategoryDetail("RAG", "The RAG operator"),
|
||||||
"experimental": _CategoryDetail("EXPERIMENTAL", "EXPERIMENTAL operator"),
|
"experimental": _CategoryDetail("EXPERIMENTAL", "EXPERIMENTAL operator"),
|
||||||
|
"example": _CategoryDetail("Example", "Example operator"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +153,7 @@ class OperatorCategory(str, Enum):
|
|||||||
AGENT = "agent"
|
AGENT = "agent"
|
||||||
RAG = "rag"
|
RAG = "rag"
|
||||||
EXPERIMENTAL = "experimental"
|
EXPERIMENTAL = "experimental"
|
||||||
|
EXAMPLE = "example"
|
||||||
|
|
||||||
def label(self) -> str:
|
def label(self) -> str:
|
||||||
"""Get the label of the category."""
|
"""Get the label of the category."""
|
||||||
@@ -193,6 +196,7 @@ _RESOURCE_CATEGORY_DETAIL = {
|
|||||||
"embeddings": _CategoryDetail("Embeddings", "The embeddings resource"),
|
"embeddings": _CategoryDetail("Embeddings", "The embeddings resource"),
|
||||||
"rag": _CategoryDetail("RAG", "The resource"),
|
"rag": _CategoryDetail("RAG", "The resource"),
|
||||||
"vector_store": _CategoryDetail("Vector Store", "The vector store resource"),
|
"vector_store": _CategoryDetail("Vector Store", "The vector store resource"),
|
||||||
|
"example": _CategoryDetail("Example", "The example resource"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -209,6 +213,7 @@ class ResourceCategory(str, Enum):
|
|||||||
EMBEDDINGS = "embeddings"
|
EMBEDDINGS = "embeddings"
|
||||||
RAG = "rag"
|
RAG = "rag"
|
||||||
VECTOR_STORE = "vector_store"
|
VECTOR_STORE = "vector_store"
|
||||||
|
EXAMPLE = "example"
|
||||||
|
|
||||||
def label(self) -> str:
|
def label(self) -> str:
|
||||||
"""Get the label of the category."""
|
"""Get the label of the category."""
|
||||||
@@ -343,6 +348,9 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
alias: Optional[List[str]] = Field(
|
alias: Optional[List[str]] = Field(
|
||||||
None, description="The alias of the parameter(Compatible with old version)"
|
None, description="The alias of the parameter(Compatible with old version)"
|
||||||
)
|
)
|
||||||
|
ui: Optional[UIComponent] = Field(
|
||||||
|
None, description="The UI component of the parameter"
|
||||||
|
)
|
||||||
|
|
||||||
@model_validator(mode="before")
|
@model_validator(mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -398,6 +406,7 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
label: str,
|
label: str,
|
||||||
name: str,
|
name: str,
|
||||||
type: Type,
|
type: Type,
|
||||||
|
is_list: bool = False,
|
||||||
optional: bool = False,
|
optional: bool = False,
|
||||||
default: Optional[Union[DefaultParameterType, _MISSING_TYPE]] = _MISSING_VALUE,
|
default: Optional[Union[DefaultParameterType, _MISSING_TYPE]] = _MISSING_VALUE,
|
||||||
placeholder: Optional[DefaultParameterType] = None,
|
placeholder: Optional[DefaultParameterType] = None,
|
||||||
@@ -405,6 +414,7 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
options: Optional[Union[BaseDynamicOptions, List[OptionValue]]] = None,
|
options: Optional[Union[BaseDynamicOptions, List[OptionValue]]] = None,
|
||||||
resource_type: ResourceType = ResourceType.INSTANCE,
|
resource_type: ResourceType = ResourceType.INSTANCE,
|
||||||
alias: Optional[List[str]] = None,
|
alias: Optional[List[str]] = None,
|
||||||
|
ui: Optional[UIComponent] = None,
|
||||||
):
|
):
|
||||||
"""Build the parameter from the type."""
|
"""Build the parameter from the type."""
|
||||||
type_name = type.__qualname__
|
type_name = type.__qualname__
|
||||||
@@ -419,6 +429,7 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
name=name,
|
name=name,
|
||||||
type_name=type_name,
|
type_name=type_name,
|
||||||
type_cls=type_cls,
|
type_cls=type_cls,
|
||||||
|
is_list=is_list,
|
||||||
category=category.value,
|
category=category.value,
|
||||||
resource_type=resource_type,
|
resource_type=resource_type,
|
||||||
optional=optional,
|
optional=optional,
|
||||||
@@ -427,6 +438,7 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
description=description or label,
|
description=description or label,
|
||||||
options=options,
|
options=options,
|
||||||
alias=alias,
|
alias=alias,
|
||||||
|
ui=ui,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -456,11 +468,12 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
description=data["description"],
|
description=data["description"],
|
||||||
options=data["options"],
|
options=data["options"],
|
||||||
value=data["value"],
|
value=data["value"],
|
||||||
|
ui=data.get("ui"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_dict(self) -> Dict:
|
def to_dict(self) -> Dict:
|
||||||
"""Convert current metadata to json dict."""
|
"""Convert current metadata to json dict."""
|
||||||
dict_value = model_to_dict(self, exclude={"options", "alias"})
|
dict_value = model_to_dict(self, exclude={"options", "alias", "ui"})
|
||||||
if not self.options:
|
if not self.options:
|
||||||
dict_value["options"] = None
|
dict_value["options"] = None
|
||||||
elif isinstance(self.options, BaseDynamicOptions):
|
elif isinstance(self.options, BaseDynamicOptions):
|
||||||
@@ -468,6 +481,9 @@ class Parameter(TypeMetadata, Serializable):
|
|||||||
dict_value["options"] = [value.to_dict() for value in values]
|
dict_value["options"] = [value.to_dict() for value in values]
|
||||||
else:
|
else:
|
||||||
dict_value["options"] = [value.to_dict() for value in self.options]
|
dict_value["options"] = [value.to_dict() for value in self.options]
|
||||||
|
|
||||||
|
if self.ui:
|
||||||
|
dict_value["ui"] = self.ui.to_dict()
|
||||||
return dict_value
|
return dict_value
|
||||||
|
|
||||||
def get_dict_options(self) -> Optional[List[Dict]]:
|
def get_dict_options(self) -> Optional[List[Dict]]:
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
"""UI components for AWEL flow."""
|
"""UI components for AWEL flow."""
|
||||||
|
|
||||||
from typing import Any, Dict, List, Literal, Optional
|
from typing import Any, Dict, List, Literal, Optional, Union
|
||||||
|
|
||||||
from dbgpt._private.pydantic import BaseModel, Field
|
from dbgpt._private.pydantic import BaseModel, Field, model_to_dict
|
||||||
|
from dbgpt.core.interface.serialization import Serializable
|
||||||
|
|
||||||
from .exceptions import FlowUIComponentException
|
from .exceptions import FlowUIComponentException
|
||||||
|
|
||||||
@@ -36,37 +37,6 @@ class RefreshableMixin(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UIComponent(RefreshableMixin, BaseModel):
|
|
||||||
"""UI component."""
|
|
||||||
|
|
||||||
class UIRange(BaseModel):
|
|
||||||
"""UI range."""
|
|
||||||
|
|
||||||
min: int | float | str | None = Field(None, description="Minimum value")
|
|
||||||
max: int | float | str | None = Field(None, description="Maximum value")
|
|
||||||
step: int | float | str | None = Field(None, description="Step value")
|
|
||||||
format: str | None = Field(None, description="Format")
|
|
||||||
|
|
||||||
ui_type: _UI_TYPE = Field(..., description="UI component type")
|
|
||||||
|
|
||||||
disabled: bool = Field(
|
|
||||||
False,
|
|
||||||
description="Whether the component is disabled",
|
|
||||||
)
|
|
||||||
|
|
||||||
def check_parameter(self, parameter_dict: Dict[str, Any]):
|
|
||||||
"""Check parameter.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FlowUIParameterException: If the parameter is invalid.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _check_options(self, options: Dict[str, Any]):
|
|
||||||
"""Check options."""
|
|
||||||
if not options:
|
|
||||||
raise FlowUIComponentException("options is required", self.ui_type)
|
|
||||||
|
|
||||||
|
|
||||||
class StatusMixin(BaseModel):
|
class StatusMixin(BaseModel):
|
||||||
"""Status mixin."""
|
"""Status mixin."""
|
||||||
|
|
||||||
@@ -76,40 +46,6 @@ class StatusMixin(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RangeMixin(BaseModel):
|
|
||||||
"""Range mixin."""
|
|
||||||
|
|
||||||
ui_range: Optional[UIComponent.UIRange] = Field(
|
|
||||||
None,
|
|
||||||
description="Range for the component",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class InputMixin(BaseModel):
|
|
||||||
"""Input mixin."""
|
|
||||||
|
|
||||||
class Count(BaseModel):
|
|
||||||
"""Count."""
|
|
||||||
|
|
||||||
show: Optional[bool] = Field(
|
|
||||||
None,
|
|
||||||
description="Whether to show count",
|
|
||||||
)
|
|
||||||
max: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The maximum count",
|
|
||||||
)
|
|
||||||
exceed_strategy: Optional[Literal["cut", "warning"]] = Field(
|
|
||||||
None,
|
|
||||||
description="The strategy when the count exceeds",
|
|
||||||
)
|
|
||||||
|
|
||||||
count: Optional[Count] = Field(
|
|
||||||
None,
|
|
||||||
description="Count configuration",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PanelEditorMixin(BaseModel):
|
class PanelEditorMixin(BaseModel):
|
||||||
"""Edit the content in the panel."""
|
"""Edit the content in the panel."""
|
||||||
|
|
||||||
@@ -126,19 +62,62 @@ class PanelEditorMixin(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
editor: Optional[Editor] = Field(
|
editor: Optional[Editor] = Field(
|
||||||
None,
|
default_factory=lambda: PanelEditorMixin.Editor(width=800, height=400),
|
||||||
description="The editor configuration",
|
description="The editor configuration",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UICascader(StatusMixin, UIComponent):
|
class UIComponent(RefreshableMixin, Serializable, BaseModel):
|
||||||
|
"""UI component."""
|
||||||
|
|
||||||
|
class UIAttribute(StatusMixin, BaseModel):
|
||||||
|
"""Base UI attribute."""
|
||||||
|
|
||||||
|
disabled: bool = Field(
|
||||||
|
False,
|
||||||
|
description="Whether the component is disabled",
|
||||||
|
)
|
||||||
|
|
||||||
|
ui_type: _UI_TYPE = Field(..., description="UI component type")
|
||||||
|
|
||||||
|
attr: Optional[UIAttribute] = Field(
|
||||||
|
None,
|
||||||
|
description="The attributes of the component",
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_parameter(self, parameter_dict: Dict[str, Any]):
|
||||||
|
"""Check parameter.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FlowUIParameterException: If the parameter is invalid.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _check_options(self, options: Dict[str, Any]):
|
||||||
|
"""Check options."""
|
||||||
|
if not options:
|
||||||
|
raise FlowUIComponentException("options is required", self.ui_type)
|
||||||
|
|
||||||
|
def to_dict(self) -> Dict:
|
||||||
|
"""Convert current metadata to json dict."""
|
||||||
|
return model_to_dict(self)
|
||||||
|
|
||||||
|
|
||||||
|
class UICascader(UIComponent):
|
||||||
"""Cascader component."""
|
"""Cascader component."""
|
||||||
|
|
||||||
|
class UIAttribute(UIComponent.UIAttribute):
|
||||||
|
"""Cascader attribute."""
|
||||||
|
|
||||||
|
show_search: bool = Field(
|
||||||
|
False,
|
||||||
|
description="Whether to show search input",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["cascader"] = Field("cascader", frozen=True)
|
ui_type: Literal["cascader"] = Field("cascader", frozen=True)
|
||||||
|
|
||||||
show_search: bool = Field(
|
attr: Optional[UIAttribute] = Field(
|
||||||
False,
|
None,
|
||||||
description="Whether to show search input",
|
description="The attributes of the component",
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_parameter(self, parameter_dict: Dict[str, Any]):
|
def check_parameter(self, parameter_dict: Dict[str, Any]):
|
||||||
@@ -163,53 +142,81 @@ class UICheckbox(UIComponent):
|
|||||||
self._check_options(parameter_dict.get("options", {}))
|
self._check_options(parameter_dict.get("options", {}))
|
||||||
|
|
||||||
|
|
||||||
class UIDatePicker(StatusMixin, RangeMixin, UIComponent):
|
class UIDatePicker(UIComponent):
|
||||||
"""Date picker component."""
|
"""Date picker component."""
|
||||||
|
|
||||||
|
class UIAttribute(UIComponent.UIAttribute):
|
||||||
|
"""Date picker attribute."""
|
||||||
|
|
||||||
|
placement: Optional[
|
||||||
|
Literal["topLeft", "topRight", "bottomLeft", "bottomRight"]
|
||||||
|
] = Field(
|
||||||
|
None,
|
||||||
|
description="The position of the picker panel, None means bottomLeft",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["date_picker"] = Field("date_picker", frozen=True)
|
ui_type: Literal["date_picker"] = Field("date_picker", frozen=True)
|
||||||
|
|
||||||
placement: Optional[
|
attr: Optional[UIAttribute] = Field(
|
||||||
Literal["topLeft", "topRight", "bottomLeft", "bottomRight"]
|
|
||||||
] = Field(
|
|
||||||
None,
|
None,
|
||||||
description="The position of the picker panel, None means bottomLeft",
|
description="The attributes of the component",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UIInput(StatusMixin, InputMixin, UIComponent):
|
class UIInput(UIComponent):
|
||||||
"""Input component."""
|
"""Input component."""
|
||||||
|
|
||||||
|
class UIAttribute(UIComponent.UIAttribute):
|
||||||
|
"""Input attribute."""
|
||||||
|
|
||||||
|
prefix: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="The prefix, icon or text",
|
||||||
|
examples=["$", "icon:UserOutlined"],
|
||||||
|
)
|
||||||
|
suffix: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="The suffix, icon or text",
|
||||||
|
examples=["$", "icon:SearchOutlined"],
|
||||||
|
)
|
||||||
|
show_count: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Whether to show count",
|
||||||
|
)
|
||||||
|
maxlength: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The maximum length of the input",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["input"] = Field("input", frozen=True)
|
ui_type: Literal["input"] = Field("input", frozen=True)
|
||||||
|
|
||||||
prefix: Optional[str] = Field(
|
attr: Optional[UIAttribute] = Field(
|
||||||
None,
|
None,
|
||||||
description="The prefix, icon or text",
|
description="The attributes of the component",
|
||||||
examples=["$", "icon:UserOutlined"],
|
|
||||||
)
|
|
||||||
suffix: Optional[str] = Field(
|
|
||||||
None,
|
|
||||||
description="The suffix, icon or text",
|
|
||||||
examples=["$", "icon:SearchOutlined"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UITextArea(PanelEditorMixin, UIInput):
|
class UITextArea(PanelEditorMixin, UIInput):
|
||||||
"""Text area component."""
|
"""Text area component."""
|
||||||
|
|
||||||
|
class AutoSize(BaseModel):
|
||||||
|
"""Auto size configuration."""
|
||||||
|
|
||||||
|
min_rows: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The minimum number of rows",
|
||||||
|
)
|
||||||
|
max_rows: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The maximum number of rows",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["text_area"] = Field("text_area", frozen=True) # type: ignore
|
ui_type: Literal["text_area"] = Field("text_area", frozen=True) # type: ignore
|
||||||
auto_size: Optional[bool] = Field(
|
autosize: Optional[Union[bool, AutoSize]] = Field(
|
||||||
None,
|
None,
|
||||||
description="Whether the height of the textarea automatically adjusts based "
|
description="Whether the height of the textarea automatically adjusts based "
|
||||||
"on the content",
|
"on the content",
|
||||||
)
|
)
|
||||||
min_rows: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The minimum number of rows",
|
|
||||||
)
|
|
||||||
max_rows: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The maximum number of rows",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UIAutoComplete(UIInput):
|
class UIAutoComplete(UIInput):
|
||||||
@@ -220,44 +227,73 @@ class UIAutoComplete(UIInput):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UISlider(RangeMixin, UIComponent):
|
class UISlider(UIComponent):
|
||||||
"""Slider component."""
|
"""Slider component."""
|
||||||
|
|
||||||
|
class UIAttribute(UIComponent.UIAttribute):
|
||||||
|
"""Slider attribute."""
|
||||||
|
|
||||||
|
min: Optional[int | float] = Field(
|
||||||
|
None,
|
||||||
|
description="The minimum value",
|
||||||
|
)
|
||||||
|
max: Optional[int | float] = Field(
|
||||||
|
None,
|
||||||
|
description="The maximum value",
|
||||||
|
)
|
||||||
|
step: Optional[int | float] = Field(
|
||||||
|
None,
|
||||||
|
description="The step of the slider",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["slider"] = Field("slider", frozen=True)
|
ui_type: Literal["slider"] = Field("slider", frozen=True)
|
||||||
|
|
||||||
show_input: bool = Field(
|
show_input: bool = Field(
|
||||||
False, description="Whether to display the value in a input component"
|
False, description="Whether to display the value in a input component"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
attr: Optional[UIAttribute] = Field(
|
||||||
|
None,
|
||||||
|
description="The attributes of the component",
|
||||||
|
)
|
||||||
|
|
||||||
class UITimePicker(StatusMixin, UIComponent):
|
|
||||||
|
class UITimePicker(UIComponent):
|
||||||
"""Time picker component."""
|
"""Time picker component."""
|
||||||
|
|
||||||
|
class UIAttribute(UIComponent.UIAttribute):
|
||||||
|
"""Time picker attribute."""
|
||||||
|
|
||||||
|
format: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="The format of the time",
|
||||||
|
examples=["HH:mm:ss", "HH:mm"],
|
||||||
|
)
|
||||||
|
hour_step: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The step of the hour input",
|
||||||
|
)
|
||||||
|
minute_step: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The step of the minute input",
|
||||||
|
)
|
||||||
|
second_step: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The step of the second input",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["time_picker"] = Field("time_picker", frozen=True)
|
ui_type: Literal["time_picker"] = Field("time_picker", frozen=True)
|
||||||
|
|
||||||
format: Optional[str] = Field(
|
attr: Optional[UIAttribute] = Field(
|
||||||
None,
|
None,
|
||||||
description="The format of the time",
|
description="The attributes of the component",
|
||||||
examples=["HH:mm:ss", "HH:mm"],
|
|
||||||
)
|
|
||||||
hour_step: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The step of the hour input",
|
|
||||||
)
|
|
||||||
minute_step: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The step of the minute input",
|
|
||||||
)
|
|
||||||
second_step: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The step of the second input",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UITreeSelect(StatusMixin, UIComponent):
|
class UITreeSelect(UICascader):
|
||||||
"""Tree select component."""
|
"""Tree select component."""
|
||||||
|
|
||||||
ui_type: Literal["tree_select"] = Field("tree_select", frozen=True)
|
ui_type: Literal["tree_select"] = Field("tree_select", frozen=True) # type: ignore
|
||||||
|
|
||||||
def check_parameter(self, parameter_dict: Dict[str, Any]):
|
def check_parameter(self, parameter_dict: Dict[str, Any]):
|
||||||
"""Check parameter."""
|
"""Check parameter."""
|
||||||
@@ -271,19 +307,24 @@ class UITreeSelect(StatusMixin, UIComponent):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UIUpload(StatusMixin, UIComponent):
|
class UIUpload(UIComponent):
|
||||||
"""Upload component."""
|
"""Upload component."""
|
||||||
|
|
||||||
|
class UIAttribute(UIComponent.UIAttribute):
|
||||||
|
"""Upload attribute."""
|
||||||
|
|
||||||
|
max_count: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The maximum number of files that can be uploaded",
|
||||||
|
)
|
||||||
|
|
||||||
ui_type: Literal["upload"] = Field("upload", frozen=True)
|
ui_type: Literal["upload"] = Field("upload", frozen=True)
|
||||||
|
|
||||||
max_file_size: Optional[int] = Field(
|
max_file_size: Optional[int] = Field(
|
||||||
None,
|
None,
|
||||||
description="The maximum size of the file, in bytes",
|
description="The maximum size of the file, in bytes",
|
||||||
)
|
)
|
||||||
max_count: Optional[int] = Field(
|
|
||||||
None,
|
|
||||||
description="The maximum number of files that can be uploaded",
|
|
||||||
)
|
|
||||||
file_types: Optional[List[str]] = Field(
|
file_types: Optional[List[str]] = Field(
|
||||||
None,
|
None,
|
||||||
description="The file types that can be accepted",
|
description="The file types that can be accepted",
|
||||||
@@ -346,3 +387,13 @@ class UICodeEditor(UITextArea):
|
|||||||
"python",
|
"python",
|
||||||
description="The language of the code",
|
description="The language of the code",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultUITextArea(UITextArea):
|
||||||
|
"""Default text area component."""
|
||||||
|
|
||||||
|
autosize: Union[bool, UITextArea.AutoSize] = Field(
|
||||||
|
default_factory=lambda: UITextArea.AutoSize(min_rows=2, max_rows=40),
|
||||||
|
description="Whether the height of the textarea automatically adjusts based "
|
||||||
|
"on the content",
|
||||||
|
)
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Any, Callable, Dict, List
|
from typing import Any, Callable, Dict, List, Optional
|
||||||
|
|
||||||
from dbgpt._private.pydantic import BaseModel, Field, model_validator
|
from dbgpt._private.pydantic import BaseModel, Field, model_validator
|
||||||
from dbgpt.core.interface.serialization import Serializable
|
from dbgpt.core.interface.serialization import Serializable
|
||||||
@@ -16,6 +16,9 @@ class OptionValue(Serializable, BaseModel):
|
|||||||
label: str = Field(..., description="The label of the option")
|
label: str = Field(..., description="The label of the option")
|
||||||
name: str = Field(..., description="The name of the option")
|
name: str = Field(..., description="The name of the option")
|
||||||
value: Any = Field(..., description="The value of the option")
|
value: Any = Field(..., description="The value of the option")
|
||||||
|
children: Optional[List["OptionValue"]] = Field(
|
||||||
|
None, description="The children of the option"
|
||||||
|
)
|
||||||
|
|
||||||
def to_dict(self) -> Dict:
|
def to_dict(self) -> Dict:
|
||||||
"""Convert current metadata to json dict."""
|
"""Convert current metadata to json dict."""
|
||||||
|
@@ -24,6 +24,7 @@ from dbgpt.core.awel.flow import (
|
|||||||
OperatorType,
|
OperatorType,
|
||||||
Parameter,
|
Parameter,
|
||||||
ViewMetadata,
|
ViewMetadata,
|
||||||
|
ui,
|
||||||
)
|
)
|
||||||
from dbgpt.core.interface.llm import (
|
from dbgpt.core.interface.llm import (
|
||||||
LLMClient,
|
LLMClient,
|
||||||
@@ -69,6 +70,10 @@ class RequestBuilderOperator(MapOperator[RequestInput, ModelRequest]):
|
|||||||
optional=True,
|
optional=True,
|
||||||
default=None,
|
default=None,
|
||||||
description=_("The temperature of the model request."),
|
description=_("The temperature of the model request."),
|
||||||
|
ui=ui.UISlider(
|
||||||
|
show_input=True,
|
||||||
|
attr=ui.UISlider.UIAttribute(min=0.0, max=2.0, step=0.1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Parameter.build_from(
|
Parameter.build_from(
|
||||||
_("Max New Tokens"),
|
_("Max New Tokens"),
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
"""The prompt operator."""
|
"""The prompt operator."""
|
||||||
|
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ from dbgpt.core.awel.flow import (
|
|||||||
ResourceCategory,
|
ResourceCategory,
|
||||||
ViewMetadata,
|
ViewMetadata,
|
||||||
register_resource,
|
register_resource,
|
||||||
|
ui,
|
||||||
)
|
)
|
||||||
from dbgpt.core.interface.message import BaseMessage
|
from dbgpt.core.interface.message import BaseMessage
|
||||||
from dbgpt.core.interface.operators.llm_operator import BaseLLM
|
from dbgpt.core.interface.operators.llm_operator import BaseLLM
|
||||||
@@ -48,6 +50,7 @@ from dbgpt.util.i18n_utils import _
|
|||||||
optional=True,
|
optional=True,
|
||||||
default="You are a helpful AI Assistant.",
|
default="You are a helpful AI Assistant.",
|
||||||
description=_("The system message."),
|
description=_("The system message."),
|
||||||
|
ui=ui.DefaultUITextArea(),
|
||||||
),
|
),
|
||||||
Parameter.build_from(
|
Parameter.build_from(
|
||||||
label=_("Message placeholder"),
|
label=_("Message placeholder"),
|
||||||
@@ -65,6 +68,7 @@ from dbgpt.util.i18n_utils import _
|
|||||||
default="{user_input}",
|
default="{user_input}",
|
||||||
placeholder="{user_input}",
|
placeholder="{user_input}",
|
||||||
description=_("The human message."),
|
description=_("The human message."),
|
||||||
|
ui=ui.DefaultUITextArea(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@@ -209,7 +209,7 @@ async def query_page(
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/nodes", dependencies=[Depends(check_api_key)])
|
@router.get("/nodes", dependencies=[Depends(check_api_key)])
|
||||||
async def get_nodes() -> Result[List[Union[ViewMetadata, ResourceMetadata]]]:
|
async def get_nodes():
|
||||||
"""Get the operator or resource nodes
|
"""Get the operator or resource nodes
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -218,7 +218,8 @@ async def get_nodes() -> Result[List[Union[ViewMetadata, ResourceMetadata]]]:
|
|||||||
"""
|
"""
|
||||||
from dbgpt.core.awel.flow.base import _OPERATOR_REGISTRY
|
from dbgpt.core.awel.flow.base import _OPERATOR_REGISTRY
|
||||||
|
|
||||||
return Result.succ(_OPERATOR_REGISTRY.metadata_list())
|
metadata_list = _OPERATOR_REGISTRY.metadata_list()
|
||||||
|
return Result.succ(metadata_list)
|
||||||
|
|
||||||
|
|
||||||
def init_endpoints(system_app: SystemApp) -> None:
|
def init_endpoints(system_app: SystemApp) -> None:
|
||||||
|
583
examples/awel/awel_flow_ui_components.py
Normal file
583
examples/awel/awel_flow_ui_components.py
Normal file
@@ -0,0 +1,583 @@
|
|||||||
|
"""Some UI components for the AWEL flow."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from dbgpt.core.awel import MapOperator
|
||||||
|
from dbgpt.core.awel.flow import (
|
||||||
|
IOField,
|
||||||
|
OperatorCategory,
|
||||||
|
OptionValue,
|
||||||
|
Parameter,
|
||||||
|
ViewMetadata,
|
||||||
|
ui,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowCascaderOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes a cascader as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Cascader",
|
||||||
|
name="example_flow_cascader",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a cascader as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Address Selector",
|
||||||
|
"address",
|
||||||
|
type=str,
|
||||||
|
is_list=True,
|
||||||
|
optional=True,
|
||||||
|
default=None,
|
||||||
|
placeholder="Select the address",
|
||||||
|
description="The address of the location.",
|
||||||
|
options=[
|
||||||
|
OptionValue(
|
||||||
|
label="Zhejiang",
|
||||||
|
name="zhejiang",
|
||||||
|
value="zhejiang",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Hangzhou",
|
||||||
|
name="hangzhou",
|
||||||
|
value="hangzhou",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Xihu",
|
||||||
|
name="xihu",
|
||||||
|
value="xihu",
|
||||||
|
),
|
||||||
|
OptionValue(
|
||||||
|
label="Feilaifeng",
|
||||||
|
name="feilaifeng",
|
||||||
|
value="feilaifeng",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
OptionValue(
|
||||||
|
label="Jiangsu",
|
||||||
|
name="jiangsu",
|
||||||
|
value="jiangsu",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Nanjing",
|
||||||
|
name="nanjing",
|
||||||
|
value="nanjing",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Zhonghua Gate",
|
||||||
|
name="zhonghuamen",
|
||||||
|
value="zhonghuamen",
|
||||||
|
),
|
||||||
|
OptionValue(
|
||||||
|
label="Zhongshanling",
|
||||||
|
name="zhongshanling",
|
||||||
|
value="zhongshanling",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ui=ui.UICascader(attr=ui.UICascader.UIAttribute(show_search=True)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Address",
|
||||||
|
"address",
|
||||||
|
str,
|
||||||
|
description="User's address.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __int__(self, address: Optional[List[str]] = None, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.address = address or []
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the address."""
|
||||||
|
full_address_str = " ".join(self.address)
|
||||||
|
return "Your name is %s, and your address is %s." % (
|
||||||
|
user_name,
|
||||||
|
full_address_str,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowCheckboxOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes a checkbox as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Checkbox",
|
||||||
|
name="example_flow_checkbox",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a checkbox as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Fruits Selector",
|
||||||
|
"fruits",
|
||||||
|
type=str,
|
||||||
|
is_list=True,
|
||||||
|
optional=True,
|
||||||
|
default=None,
|
||||||
|
placeholder="Select the fruits",
|
||||||
|
description="The fruits you like.",
|
||||||
|
options=[
|
||||||
|
OptionValue(label="Apple", name="apple", value="apple"),
|
||||||
|
OptionValue(label="Banana", name="banana", value="banana"),
|
||||||
|
OptionValue(label="Orange", name="orange", value="orange"),
|
||||||
|
OptionValue(label="Pear", name="pear", value="pear"),
|
||||||
|
],
|
||||||
|
ui=ui.UICheckbox(attr=ui.UICheckbox.UIAttribute(show_search=True)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Fruits",
|
||||||
|
"fruits",
|
||||||
|
str,
|
||||||
|
description="User's favorite fruits.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, fruits: Optional[List[str]] = None, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.fruits = fruits or []
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the fruits."""
|
||||||
|
return "Your name is %s, and you like %s." % (user_name, ", ".join(self.fruits))
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowDatePickerOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes a date picker as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Date Picker",
|
||||||
|
name="example_flow_date_picker",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a date picker as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Date Selector",
|
||||||
|
"date",
|
||||||
|
type=str,
|
||||||
|
placeholder="Select the date",
|
||||||
|
description="The date you choose.",
|
||||||
|
ui=ui.UIDatePicker(
|
||||||
|
attr=ui.UIDatePicker.UIAttribute(placement="bottomLeft")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Date",
|
||||||
|
"date",
|
||||||
|
str,
|
||||||
|
description="User's selected date.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, date: str, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.date = date
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the date."""
|
||||||
|
return "Your name is %s, and you choose the date %s." % (user_name, self.date)
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowInputOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes an input as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Input",
|
||||||
|
name="example_flow_input",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a input as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Your hobby",
|
||||||
|
"hobby",
|
||||||
|
type=str,
|
||||||
|
placeholder="Please input your hobby",
|
||||||
|
description="The hobby you like.",
|
||||||
|
ui=ui.UIInput(
|
||||||
|
attr=ui.UIInput.UIAttribute(
|
||||||
|
prefix="icon:UserOutlined", show_count=True, maxlength=200
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Hobby",
|
||||||
|
"hobby",
|
||||||
|
str,
|
||||||
|
description="User's hobby.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, hobby: str, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.hobby = hobby
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the input."""
|
||||||
|
return "Your name is %s, and your hobby is %s." % (user_name, self.hobby)
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowTextAreaOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes a text area as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Text Area",
|
||||||
|
name="example_flow_text_area",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a text area as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Your comment",
|
||||||
|
"comment",
|
||||||
|
type=str,
|
||||||
|
placeholder="Please input your comment",
|
||||||
|
description="The comment you want to say.",
|
||||||
|
ui=ui.UITextArea(
|
||||||
|
attr=ui.UITextArea.UIAttribute(show_count=True, maxlength=1000),
|
||||||
|
autosize=ui.UITextArea.AutoSize(min_rows=2, max_rows=6),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Comment",
|
||||||
|
"comment",
|
||||||
|
str,
|
||||||
|
description="User's comment.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, comment: str, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.comment = comment
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the text area."""
|
||||||
|
return "Your name is %s, and your comment is %s." % (user_name, self.comment)
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowSliderOperator(MapOperator[float, float]):
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Slider",
|
||||||
|
name="example_flow_slider",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a slider as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Default Temperature",
|
||||||
|
"default_temperature",
|
||||||
|
type=float,
|
||||||
|
optional=True,
|
||||||
|
default=0.7,
|
||||||
|
placeholder="Set the default temperature, e.g., 0.7",
|
||||||
|
description="The default temperature to pass to the LLM.",
|
||||||
|
ui=ui.UISlider(
|
||||||
|
show_input=True,
|
||||||
|
attr=ui.UISlider.UIAttribute(min=0.0, max=2.0, step=0.1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Temperature",
|
||||||
|
"temperature",
|
||||||
|
float,
|
||||||
|
description="The temperature.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Temperature",
|
||||||
|
"temperature",
|
||||||
|
float,
|
||||||
|
description="The temperature to pass to the LLM.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, default_temperature: float = 0.7, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.default_temperature = default_temperature
|
||||||
|
|
||||||
|
async def map(self, temperature: float) -> float:
|
||||||
|
"""Map the temperature to the result."""
|
||||||
|
if temperature < 0.0 or temperature > 2.0:
|
||||||
|
logger.warning("Temperature out of range: %s", temperature)
|
||||||
|
return self.default_temperature
|
||||||
|
else:
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowSliderListOperator(MapOperator[float, float]):
|
||||||
|
"""An example flow operator that includes a slider list as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Slider List",
|
||||||
|
name="example_flow_slider_list",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a slider list as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Temperature Selector",
|
||||||
|
"temperature_range",
|
||||||
|
type=float,
|
||||||
|
is_list=True,
|
||||||
|
optional=True,
|
||||||
|
default=None,
|
||||||
|
placeholder="Set the temperature, e.g., [0.1, 0.9]",
|
||||||
|
description="The temperature range to pass to the LLM.",
|
||||||
|
ui=ui.UISlider(
|
||||||
|
show_input=True,
|
||||||
|
attr=ui.UISlider.UIAttribute(min=0.0, max=2.0, step=0.1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Temperature",
|
||||||
|
"temperature",
|
||||||
|
float,
|
||||||
|
description="The temperature.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Temperature",
|
||||||
|
"temperature",
|
||||||
|
float,
|
||||||
|
description="The temperature to pass to the LLM.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, temperature_range: Optional[List[float]] = None, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
temperature_range = temperature_range or [0.1, 0.9]
|
||||||
|
if temperature_range and len(temperature_range) != 2:
|
||||||
|
raise ValueError("The length of temperature range must be 2.")
|
||||||
|
self.temperature_range = temperature_range
|
||||||
|
|
||||||
|
async def map(self, temperature: float) -> float:
|
||||||
|
"""Map the temperature to the result."""
|
||||||
|
min_temperature, max_temperature = self.temperature_range
|
||||||
|
if temperature < min_temperature or temperature > max_temperature:
|
||||||
|
logger.warning(
|
||||||
|
"Temperature out of range: %s, min: %s, max: %s",
|
||||||
|
temperature,
|
||||||
|
min_temperature,
|
||||||
|
max_temperature,
|
||||||
|
)
|
||||||
|
return min_temperature
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowTimePickerOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes a time picker as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Time Picker",
|
||||||
|
name="example_flow_time_picker",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a time picker as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Time Selector",
|
||||||
|
"time",
|
||||||
|
type=str,
|
||||||
|
placeholder="Select the time",
|
||||||
|
description="The time you choose.",
|
||||||
|
ui=ui.UITimePicker(
|
||||||
|
attr=ui.UITimePicker.UIAttribute(
|
||||||
|
format="HH:mm:ss", hour_step=2, minute_step=10, second_step=10
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Time",
|
||||||
|
"time",
|
||||||
|
str,
|
||||||
|
description="User's selected time.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, time: str, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.time = time
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the time."""
|
||||||
|
return "Your name is %s, and you choose the time %s." % (user_name, self.time)
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleFlowTreeSelectOperator(MapOperator[str, str]):
|
||||||
|
"""An example flow operator that includes a tree select as parameter."""
|
||||||
|
|
||||||
|
metadata = ViewMetadata(
|
||||||
|
label="Example Flow Tree Select",
|
||||||
|
name="example_flow_tree_select",
|
||||||
|
category=OperatorCategory.EXAMPLE,
|
||||||
|
description="An example flow operator that includes a tree select as parameter.",
|
||||||
|
parameters=[
|
||||||
|
Parameter.build_from(
|
||||||
|
"Address Selector",
|
||||||
|
"address",
|
||||||
|
type=str,
|
||||||
|
is_list=True,
|
||||||
|
optional=True,
|
||||||
|
default=None,
|
||||||
|
placeholder="Select the address",
|
||||||
|
description="The address of the location.",
|
||||||
|
options=[
|
||||||
|
OptionValue(
|
||||||
|
label="Zhejiang",
|
||||||
|
name="zhejiang",
|
||||||
|
value="zhejiang",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Hangzhou",
|
||||||
|
name="hangzhou",
|
||||||
|
value="hangzhou",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Xihu",
|
||||||
|
name="xihu",
|
||||||
|
value="xihu",
|
||||||
|
),
|
||||||
|
OptionValue(
|
||||||
|
label="Feilaifeng",
|
||||||
|
name="feilaifeng",
|
||||||
|
value="feilaifeng",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
OptionValue(
|
||||||
|
label="Jiangsu",
|
||||||
|
name="jiangsu",
|
||||||
|
value="jiangsu",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Nanjing",
|
||||||
|
name="nanjing",
|
||||||
|
value="nanjing",
|
||||||
|
children=[
|
||||||
|
OptionValue(
|
||||||
|
label="Zhonghua Gate",
|
||||||
|
name="zhonghuamen",
|
||||||
|
value="zhonghuamen",
|
||||||
|
),
|
||||||
|
OptionValue(
|
||||||
|
label="Zhongshanling",
|
||||||
|
name="zhongshanling",
|
||||||
|
value="zhongshanling",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ui=ui.UITreeSelect(attr=ui.UITreeSelect.UIAttribute(show_search=True)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
inputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"User Name",
|
||||||
|
"user_name",
|
||||||
|
str,
|
||||||
|
description="The name of the user.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IOField.build_from(
|
||||||
|
"Address",
|
||||||
|
"address",
|
||||||
|
str,
|
||||||
|
description="User's address.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def __int__(self, address: Optional[List[str]] = None, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.address = address or []
|
||||||
|
|
||||||
|
async def map(self, user_name: str) -> str:
|
||||||
|
"""Map the user name to the address."""
|
||||||
|
full_address_str = " ".join(self.address)
|
||||||
|
return "Your name is %s, and your address is %s." % (
|
||||||
|
user_name,
|
||||||
|
full_address_str,
|
||||||
|
)
|
Reference in New Issue
Block a user