From df8d84d07f2d231234b4ab8f4ab37fb60cd7bc1d Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 28 Jul 2023 14:59:40 -0300 Subject: [PATCH 1/6] Fixed unknown node not showing --- .../src/CustomNodes/GenericNode/index.tsx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index d49544114..32ade1ad1 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -28,9 +28,6 @@ export default function GenericNode({ const updateNodeInternals = useUpdateNodeInternals(); const showError = useRef(true); const { types, deleteNode, reactFlowInstance } = useContext(typesContext); - // any to avoid type conflict - const Icon: any = - nodeIconsLucide[data.type] || nodeIconsLucide[types[data.type]]; const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; const [validationStatus, setValidationStatus] = useState(null); // State for outline color @@ -67,18 +64,6 @@ export default function GenericNode({ } }, [sseData, data.id]); - if (!Icon) { - if (showError.current) { - setErrorData({ - title: data.type - ? `The ${data.type} node could not be rendered, please review your json file` - : "There was a node that can't be rendered, please review your json file", - }); - showError.current = false; - } - deleteNode(data.id); - return; - } return ( <> From 6be4799950a791e9c34e782248f37a3863b0287f Mon Sep 17 00:00:00 2001 From: Rodrigo Nader Date: Fri, 28 Jul 2023 15:00:57 -0300 Subject: [PATCH 2/6] improve custom component docs --- docs/docs/components/custom.mdx | 112 +++++++++++----------- docs/docs/guidelines/custom-component.mdx | 15 ++- 2 files changed, 64 insertions(+), 63 deletions(-) diff --git a/docs/docs/components/custom.mdx b/docs/docs/components/custom.mdx index 9f7fa65ca..cf9c7ef85 100644 --- a/docs/docs/components/custom.mdx +++ b/docs/docs/components/custom.mdx @@ -2,78 +2,80 @@ import Admonition from "@theme/Admonition"; # Custom Component -Used to create a custom component. The code is the class that will be converted to a Custom Component with the fields and formatting you define. +Used to create a custom component, a special type of Langflow component that allows users to extend the functionality of the platform by creating their own reusable and configurable components from a user-defined Python script. + +To use a custom component, follow these steps: + +- Create a class that inherits from _`langflow.CustomComponent`_ and contains a _`build`_ method. +- Use arguments with [Type Annotations (or Type Hints)](https://docs.python.org/3/library/typing.html) of the _`build`_ method to create component fields. +- If applicable, use the _`build_config`_ method to customize how these fields look and behave. + + + +For an in depth explanation of custom components, their rules and applications, make sure to read [Custom Component guidelines](../guidelines/custom-component). + + **Params** - **Code:** The Python code to define the component. -The code must be a class that inherits from the _`langflow.CustomComponent`_ class. -The type annotations of the _`build`_ instance method will be used to create the fields of the component. +## The CustomComponent Class -| Supported types | -| --------------------------------------------------------- | -| _`str`_, _`int`_, _`float`_, _`bool`_, _`list`_, _`dict`_ | -| _`langchain.chains.base.Chain`_ | -| _`langchain.PromptTemplate`_ | -| _`langchain.llms.base.BaseLLM`_ | -| _`langchain.Tool`_ | -| _`langchain.document_loaders.base.BaseLoader`_ | -| _`langchain.schema.Document`_ | -| _`langchain.text_splitters.TextSplitter`_ | -| _`langchain.vectorstores.base.VectorStore`_ | -| _`langchain.embeddings.base.Embeddings`_ | -| _`langchain.schema.BaseRetriever`_ | -The class can have a [_`build_config`_](focus://8) instance method, which is used to define configuration fields for the component. -The [_`build_config`_](focus://8) method should always return a dictionary with specific keys representing the field names and their corresponding configurations. -It must follow the format described below: +**Methods** -The top-level keys are the field names. +- **build**: This is a required method within a Custom Component class. It defines the functionality of the component and specifies how it processes input data to produce output data. The type annotations of the _`build`_ instance method are used to create the fields of the component. -Their values are of type _`dict`_ with any of the following keys (all of them are **optional**): + | Supported types | + | --------------------------------------------------------- | + | _`str`_, _`int`_, _`float`_, _`bool`_, _`list`_, _`dict`_ | + | _`langchain.chains.base.Chain`_ | + | _`langchain.PromptTemplate`_ | + | _`langchain.llms.base.BaseLLM`_ | + | _`langchain.Tool`_ | + | _`langchain.document_loaders.base.BaseLoader`_ | + | _`langchain.schema.Document`_ | + | _`langchain.text_splitters.TextSplitter`_ | + | _`langchain.vectorstores.base.VectorStore`_ | + | _`langchain.embeddings.base.Embeddings`_ | + | _`langchain.schema.BaseRetriever`_ | -| Key | Description | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| _`field_type: str`_ | The type of the field (can be any of the types supported by the _`build`_ method, passed as a string). | -| _`is_list: bool`_ | If the field is a list. | -| _`options: List[str]`_ | This defines the options to be displayed. The _`field_type`_ should invariably be _`str`_. If you set the _`value`_ attribute to one of the options, it will be selected by default. Having _`options`_ will display a dropdown menu. | -| _`multiline: bool`_ | When the field is a string, this would allow the user to open a text editor. | -| _`input_types: List[str]`_ | To be used when you want a _`str`_ field to have connectable handles. | -| _`display_name: str`_ | To define the name of the field. | -| _`advanced: bool`_ | To hide the field in default view. This is useful when a field is for advanced users or you simply want to remove it from view. | -| _`password: bool`_ | To mask the input text. This is used to allow the user to hide the values of the text (e.g. API keys). | -| _`required: bool`_ | To make the field required. | -| _`info: str`_ | To add a tooltip to the field. | -| _`file_types: List[str]`_ | This is a requirement if the _`field_type`_ is file. Defines which file types will be accepted. For example, json, yaml or yml. | -The CustomComponent class provides the following methods: +- **build_config**: Used to define the configuration fields of the component. Should always return a dictionary with specific keys representing the field names and their corresponding configurations. It must follow the format described below: -| Method name | Description | -| -------------- | ------------------------------------------------------------- | -| _`list_flows`_ | Returns a list of Flow objects with an _`id`_ and a _`name`_. | -| _`load_flow`_ | Loads a flow from the given _`id`_. | + - Top-level keys are field names. + - Their values are also of type _`dict`_. They specify the behavior of the generated fields. -### Usage + Following are the available keys used to customize component fields: -```python -# In the CustomComponent class -def build(self, flow_name: str) - # This is a list of Flow objects with an id and a name - flows = self.list_flows() - found_flow = next((f for f in flows if f.name == flow_name), None) - if not found_flow: - raise ValueError(f"Flow {flow_name} not found") + | Key | Description | + | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | _`field_type: str`_ | The type of the field (can be any of the types supported by the _`build`_ method). | + | _`is_list: bool`_ | If the field contains a list of values. When paired with _`options`_, becomes a dropdown menu. | + | _`options: List[str]`_ | Defines the options to be displayed in a dropdown menu. If the _`value`_ attribute is set to one of the options, that option becomes the default. For this parameter to work, _`field_type`_ should invariably be _`str`_. | + | _`multiline: bool`_ | When the field is a string, if it should be multiline. Useful for longer texts when a text modal is helpful. | + | _`input_types: List[str]`_ | To be used when you want a _`str`_ field to have connectable handles. | + | _`display_name: str`_ | Defines the field name. | + | _`advanced: bool`_ | To hide the field in canvas view (shown only in the component's settings). | + | _`password: bool`_ | To mask the input text. | + | _`required: bool`_ | To make the field required. | + | _`info: str`_ | To add a tooltip with information to the field. | + | _`file_types: List[str]`_ | This is a requirement if the _`field_type`_ is *file*. Defines which file types will be accepted. For example, *json*, *yaml* or *yml*. | - flow = self.load_flow(found_flow.id) - result = flow() # Run the flow - return result -``` - +- The CustomComponent class also provides methods to load and use other flows from the Langflow platform: -[Learn more about Custom Components](../guidelines/custom-component) + | Method name | Description | + | -------------- | ------------------------------------------------------------- | + | _`list_flows`_ | Returns a list of Flow objects with an _`id`_ and a _`name`_. | + | _`load_flow`_ | Loads a flow from a given _`id`_. | - + + + + Check out the [FlowRunner](../guidelines/custom-component) example to understand how to call a flow from a custom component. + + \ No newline at end of file diff --git a/docs/docs/guidelines/custom-component.mdx b/docs/docs/guidelines/custom-component.mdx index 07619f224..404cc9594 100644 --- a/docs/docs/guidelines/custom-component.mdx +++ b/docs/docs/guidelines/custom-component.mdx @@ -8,17 +8,17 @@ import Admonition from "@theme/Admonition"; # Custom Components -In Langflow, a Custom Component is a special component type that allows users to extend the functionality of the platform by creating their own reusable and configurable components. +In Langflow, a Custom Component is a special component type that allows users to extend the platform's functionality by creating their own reusable and configurable components. A Custom Component is created from a user-defined Python script that uses the _`CustomComponent`_ class provided by the Langflow library. These components can be as simple as a basic function that takes and returns a string or as complex as a combination of multiple sub-components and API calls. -Let's take a look at the basic rules and features, then we'll go over an example. +Let's take a look at the basic rules and features. Then we'll go over an example. ## TL;DR - Create a class that inherits from _`CustomComponent`_ and contains a _`build`_ method. - Use arguments with [Type Annotations (or Type Hints)](https://docs.python.org/3/library/typing.html) of the _`build`_ method to create component fields. -- Use the _`build_config`_ method to customize these fields look and behave. +- Use the _`build_config`_ method to customize how these fields look and behave. Here is an example: @@ -87,7 +87,7 @@ class MyComponent(CustomComponent): ### Rule 2 -This class requires a _`build`_ method, which is used to run the component and defines its fields. +This class requires a _`build`_ method used to run the component and define its fields. ```python from langflow import CustomComponent @@ -108,7 +108,7 @@ class MyComponent(CustomComponent): --- -The [Return Type Annotation](https://docs.python.org/3/library/typing.html) of the _`build`_ method defines the component type (e.g., Chain, BaseLLM or basic Python types). Check out all supported types in the [component reference](../components/custom). +The [Return Type Annotation](https://docs.python.org/3/library/typing.html) of the _`build`_ method defines the component type (e.g., Chain, BaseLLM, or basic Python types). Check out all supported types in the [component reference](../components/custom). ```python from langflow import CustomComponent @@ -146,7 +146,7 @@ class MyComponent(CustomComponent): ### Rule 3 -The class can have a [_`build_config`_](focus://8) method, which is used to define configuration fields for the component. The [_`build_config`_](focus://8) method should always return a dictionary with specific keys representing the field names and their corresponding configurations. It must follow the format described below: +The class can have a [_`build_config`_](focus://8) method, which defines configuration fields for the component. The [_`build_config`_](focus://8) method should always return a dictionary with specific keys representing the field names and their corresponding configurations. It must follow the format described below: - Top-level keys are field names. - Their values are also of type _`dict`_. They specify the behavior of the generated fields. @@ -184,8 +184,7 @@ If you were to do this using Langflow's native components, you would create a To ### Pick a display name -First, let's choose a name for our component by adding a _`display_name`_ attribute. This is the component name to be displayed in the canvas. -The name of the class is not important, but let's call it _`DocumentProcessor`_. +First, let's choose a name for our component by adding a _`display_name`_ attribute. This is the component name to be displayed in the canvas. The name of the class is not important, but let's call it _`DocumentProcessor`_. ```python from langflow import CustomComponent From 638f450eadc29e3fcaefdd6643cb0819474529be Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 28 Jul 2023 15:05:10 -0300 Subject: [PATCH 3/6] Fixed bug showing on console from Unknown --- .../GenericNode/components/parameterComponent/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index c32fc8916..ee3f600a4 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -120,7 +120,8 @@ export default function ParameterComponent({ refNumberComponents.current = groupedObj[0]?.type?.length; refHtml.current = groupedObj.map((item, i) => { - const Icon: any = nodeIconsLucide[item.family]; + const Icon: any = + nodeIconsLucide[item.family] ?? nodeIconsLucide["unknown"]; return ( Date: Fri, 28 Jul 2023 15:07:03 -0300 Subject: [PATCH 4/6] GitIgnore changed --- src/backend/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/.gitignore b/src/backend/.gitignore index 6f5ccc322..ef9ed2896 100644 --- a/src/backend/.gitignore +++ b/src/backend/.gitignore @@ -133,4 +133,4 @@ dmypy.json .pyre/ # Custom Components -langflow/components +langflow/components/* From bdc62ba725a7f8c4e4350eb140b98b4dfcdbb5ab Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 28 Jul 2023 15:17:03 -0300 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=90=9B=20fix(=5F=5Fmain=5F=5F.py):=20?= =?UTF-8?q?change=20default=20value=20of=20workers=20option=20from=20-1=20?= =?UTF-8?q?to=202=20to=20limit=20the=20number=20of=20worker=20processes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/__main__.py b/src/backend/langflow/__main__.py index 411a5f217..c9c7e3fb0 100644 --- a/src/backend/langflow/__main__.py +++ b/src/backend/langflow/__main__.py @@ -122,7 +122,7 @@ def serve( "127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST" ), workers: int = typer.Option( - -1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS" + 2, help="Number of worker processes.", envvar="LANGFLOW_WORKERS" ), timeout: int = typer.Option(300, help="Worker timeout in seconds."), port: int = typer.Option(7860, help="Port to listen on.", envvar="LANGFLOW_PORT"), From 5e78f6be79f585a1b1cccd4d556c27c162ec6fdf Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 28 Jul 2023 15:19:31 -0300 Subject: [PATCH 6/6] Changed gitignore --- src/backend/.gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/backend/.gitignore b/src/backend/.gitignore index ef9ed2896..9af18a35f 100644 --- a/src/backend/.gitignore +++ b/src/backend/.gitignore @@ -131,6 +131,3 @@ dmypy.json # Pyre type checker .pyre/ - -# Custom Components -langflow/components/*