365 lines
9.9 KiB
Text
365 lines
9.9 KiB
Text
---
|
|
description: Custom Components
|
|
hide_table_of_contents: true
|
|
---
|
|
|
|
import ZoomableImage from "/src/theme/ZoomableImage.js";
|
|
import Admonition from "@theme/Admonition";
|
|
|
|
# FlowRunner Component
|
|
|
|
The CustomComponent class allows us to create components that interact with Langflow itself. In this example, we will make a component that runs other flows available in "My Collection".
|
|
|
|
<ZoomableImage
|
|
alt="Document Processor Component"
|
|
sources={{
|
|
light: "img/flow_runner.png",
|
|
}}
|
|
style={{
|
|
width: "30%",
|
|
margin: "0 auto",
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
}}
|
|
/>
|
|
|
|
We will cover how to:
|
|
|
|
- List Collection flows using the _`list_flows`_ method.
|
|
- Load a flow using the _`load_flow`_ method.
|
|
- Configure a dropdown input field using the _`options`_ parameter.
|
|
|
|
<details open>
|
|
|
|
<summary>Example Code</summary>
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
from langchain.schema import Document
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
flows = self.list_flows()
|
|
flow_names = [f.name for f in flows]
|
|
return {"flow_name": {"options": flow_names,
|
|
"display_name": "Flow Name",
|
|
},
|
|
"document": {"display_name": "Document"}
|
|
}
|
|
|
|
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
# List the flows
|
|
flows = self.list_flows()
|
|
# Get the flow that matches the selected name
|
|
# You can also get the flow by id
|
|
# using self.get_flow(flow_id=flow_id)
|
|
tweaks = {}
|
|
flow = self.get_flow(flow_name=flow_name, tweaks=tweaks)
|
|
# Get the page_content from the document
|
|
if document and isinstance(document, list):
|
|
document = document[0]
|
|
page_content = document.page_content
|
|
# Use it in the flow
|
|
result = flow(page_content)
|
|
return Document(page_content=str(result))
|
|
|
|
```
|
|
|
|
</details>
|
|
|
|
<CH.Scrollycoding rows={20} className={""}>
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
|
|
|
|
class MyComponent(CustomComponent):
|
|
display_name = "Custom Component"
|
|
description = "This is a custom component"
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self):
|
|
...
|
|
|
|
```
|
|
|
|
The typical structure of a Custom Component is composed of _`display_name`_ and _`description`_ attributes, _`build`_ and _`build_config`_ methods.
|
|
|
|
---
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
|
|
|
|
# focus
|
|
class FlowRunner(CustomComponent):
|
|
# focus
|
|
display_name = "Flow Runner"
|
|
# focus
|
|
description = "Run other flows"
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self):
|
|
...
|
|
|
|
```
|
|
|
|
Let's start by defining our component's _`display_name`_ and _`description`_.
|
|
|
|
---
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
# focus
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self):
|
|
...
|
|
|
|
```
|
|
|
|
Second, we will import _`Document`_ from the [_langchain.schema_](https://docs.langchain.com/docs/components/schema/) module. This will be the return type of the _`build`_ method.
|
|
|
|
---
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
# focus
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
# focus
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
...
|
|
|
|
```
|
|
|
|
Now, let's add the [parameters](focus://11[20:55]) and the [return type](focus://11[60:69]) to the _`build`_ method. The parameters added are:
|
|
|
|
- _`flow_name`_ is the name of the flow we want to run.
|
|
- _`document`_ is the input document to be passed to that flow.
|
|
- Since _`Document`_ is a Langchain type, it will add an input [handle](../guidelines/components) to the component ([see more](../components/custom)).
|
|
|
|
---
|
|
|
|
```python focus=13:14
|
|
from langflow import CustomComponent
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
# List the flows
|
|
flows = self.list_flows()
|
|
|
|
```
|
|
|
|
We can now start writing the _`build`_ method. Let's list available flows in "My Collection" using the _`list_flows`_ method.
|
|
|
|
---
|
|
|
|
```python focus=15:18
|
|
from langflow import CustomComponent
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
# List the flows
|
|
flows = self.list_flows()
|
|
# Get the flow that matches the selected name
|
|
# You can also get the flow by id
|
|
# using self.get_flow(flow_id=flow_id)
|
|
tweaks = {}
|
|
flow = self.get_flow(flow_name=flow_name, tweaks=tweaks)
|
|
|
|
```
|
|
|
|
And retrieve a flow that matches the selected name (we'll make a dropdown input field for the user to choose among flow names).
|
|
|
|
<Admonition type="caution">
|
|
From version 0.4.0, names are unique, which was not the case in previous
|
|
versions. This might lead to unexpected results if using flows with the same
|
|
name.
|
|
</Admonition>
|
|
|
|
---
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
# List the flows
|
|
flows = self.list_flows()
|
|
# Get the flow that matches the selected name
|
|
# You can also get the flow by id
|
|
# using self.get_flow(flow_id=flow_id)
|
|
tweaks = {}
|
|
flow = self.get_flow(flow_name=flow_name, tweaks=tweaks)
|
|
|
|
|
|
```
|
|
|
|
You can load this flow using _`get_flow`_ and set a _`tweaks`_ dictionary to customize it. Find more about tweaks in our [features guidelines](../guidelines/features#code).
|
|
|
|
---
|
|
|
|
```python
|
|
from langflow import CustomComponent
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
...
|
|
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
# List the flows
|
|
flows = self.list_flows()
|
|
# Get the flow that matches the selected name
|
|
# You can also get the flow by id
|
|
# using self.get_flow(flow_id=flow_id)
|
|
tweaks = {}
|
|
flow = self.get_flow(flow_name=flow_name, tweaks=tweaks)
|
|
# Get the page_content from the document
|
|
if document and isinstance(document, list):
|
|
document = document[0]
|
|
page_content = document.page_content
|
|
# Use it in the flow
|
|
result = flow(page_content)
|
|
return Document(page_content=str(result))
|
|
```
|
|
|
|
We are using a _`Document`_ as input because it is a straightforward way to pass text data in Langflow (specifically because you can connect it to many [loaders](../components/loaders)).
|
|
Generally, a flow will take a string or a dictionary as input because that's what LangChain components expect.
|
|
In case you are passing a dictionary, you need to build it according to the needs of the flow you are using.
|
|
|
|
The content of a document can be extracted using the _`page_content`_ attribute, which is a string, and passed as an argument to the selected flow.
|
|
|
|
---
|
|
|
|
```python focus=9:16
|
|
from langflow import CustomComponent
|
|
from langchain.schema import Document
|
|
|
|
|
|
class FlowRunner(CustomComponent):
|
|
display_name = "Flow Runner"
|
|
description = "Run other flows using a document as input."
|
|
|
|
def build_config(self):
|
|
flows = self.list_flows()
|
|
flow_names = [f.name for f in flows]
|
|
return {"flow_name": {"options": flow_names,
|
|
"display_name": "Flow Name",
|
|
},
|
|
"document": {"display_name": "Document"}
|
|
}
|
|
|
|
def build(self, flow_name: str, document: Document) -> Document:
|
|
# List the flows
|
|
flows = self.list_flows()
|
|
# Get the flow that matches the selected name
|
|
# You can also get the flow by id
|
|
# using self.get_flow(flow_id=flow_id)
|
|
tweaks = {}
|
|
flow = self.get_flow(flow_name=flow_name, tweaks=tweaks)
|
|
# Get the page_content from the document
|
|
if document and isinstance(document, list):
|
|
document = document[0]
|
|
page_content = document.page_content
|
|
# Use it in the flow
|
|
result = flow(page_content)
|
|
return Document(page_content=str(result))
|
|
```
|
|
|
|
Finally, we can add field customizations through the _`build_config`_ method. Here we added the _`options`_ key to make the _`flow_name`_ field a dropdown menu. Check out the [custom component reference](../components/custom) for a list of available keys.
|
|
|
|
<Admonition type="caution">
|
|
Make sure that the field type is _`str`_ and _`options`_ values are strings.
|
|
</Admonition>
|
|
|
|
</CH.Scrollycoding>
|
|
|
|
Done! This is what our script and custom component looks like:
|
|
|
|
<div style={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
}}>
|
|
|
|
<ZoomableImage
|
|
alt="Document Processor Code"
|
|
sources={{
|
|
light: "img/flow_runner_code.png",
|
|
}}
|
|
style={{
|
|
maxWidth: "100%",
|
|
margin: "0 auto",
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
}}
|
|
|
|
/>
|
|
|
|
<ZoomableImage
|
|
alt="Document Processor Component"
|
|
sources={{
|
|
light: "img/flow_runner.png",
|
|
}}
|
|
style={{
|
|
width: "40%",
|
|
margin: "0 auto",
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
}}
|
|
/>
|
|
|
|
</div>
|