Merge branch 'python_custom_node_component' of personal:logspace-ai/langflow into python_custom_node_component
This commit is contained in:
commit
735f2556c2
6 changed files with 67 additions and 83 deletions
|
|
@ -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.
|
||||
|
||||
<Admonition type="info" label="Tip">
|
||||
|
||||
For an in depth explanation of custom components, their rules and applications, make sure to read [Custom Component guidelines](../guidelines/custom-component).
|
||||
|
||||
</Admonition>
|
||||
|
||||
**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
|
||||
|
||||
```
|
||||
|
||||
<Admonition type="info" label="Tip">
|
||||
- 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`_. |
|
||||
|
||||
</Admonition>
|
||||
|
||||
<Admonition type="info" label="Tip">
|
||||
|
||||
Check out the [FlowRunner](../guidelines/custom-component) example to understand how to call a flow from a custom component.
|
||||
|
||||
</Admonition>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
3
src/backend/.gitignore
vendored
3
src/backend/.gitignore
vendored
|
|
@ -131,6 +131,3 @@ dmypy.json
|
|||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# Custom Components
|
||||
langflow/components
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<span
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<>
|
||||
<NodeToolbar>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue