* standardize component name style and links pt 1 * component name standardization pt 2 * standardization pt 3 * standardize component names pt 4 * peer review * fix lnk * update edit tool actions section * standardize Agent, agent, agentic * more style auditing * missing imports
175 lines
No EOL
8.2 KiB
Text
175 lines
No EOL
8.2 KiB
Text
---
|
|
title: Contribute components
|
|
slug: /contributing-components
|
|
---
|
|
|
|
|
|
New components are added as objects of the [`Component`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/custom/custom_component/component.py) class.
|
|
|
|
Dependencies are added to the [pyproject.toml](https://github.com/langflow-ai/langflow/blob/main/pyproject.toml#L148) file.
|
|
|
|
## Contribute an example component to Langflow
|
|
|
|
Anyone can contribute an example component. For example, to create a new data component called **DataFrame processor**, follow these steps to contribute it to Langflow.
|
|
|
|
1. Create a Python file called `dataframe_processor.py`.
|
|
2. Write your processor as an object of the [`Component`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/custom/custom_component/component.py) class. You'll create a new class, `DataFrameProcessor`, that will inherit from `Component` and override the base class's methods.
|
|
|
|
```python
|
|
from typing import Any, Dict, Optional
|
|
import pandas as pd
|
|
from langflow.custom import Component
|
|
|
|
class DataFrameProcessor(Component):
|
|
"""A component that processes pandas DataFrames with various operations."""
|
|
```
|
|
|
|
3. Define class attributes to provide information about your custom component:
|
|
```python
|
|
from typing import Any, Dict, Optional
|
|
import pandas as pd
|
|
from langflow.custom import Component
|
|
|
|
class DataFrameProcessor(Component):
|
|
"""A component that processes pandas DataFrames with various operations."""
|
|
|
|
display_name: str = "DataFrame Processor"
|
|
description: str = "Process and transform pandas DataFrames with various operations like filtering, sorting, and aggregation."
|
|
documentation: str = "https://docs.langflow.org/components-dataframe-processor"
|
|
icon: str = "DataframeIcon"
|
|
priority: int = 100
|
|
name: str = "dataframe_processor"
|
|
```
|
|
|
|
* `display_name`: A user-friendly name shown in the visual editor.
|
|
* `description`: A brief description of what your component does.
|
|
* `documentation`: A link to detailed documentation.
|
|
* `icon`: An emoji or icon identifier for visual representation.
|
|
For more information, see [Contributing bundles](/contributing-bundles#add-the-bundle-to-the-frontend-folder).
|
|
* `priority`: An optional integer to control display order. Lower numbers appear first.
|
|
* `name`: An optional internal identifier that defaults to class name.
|
|
|
|
4. Define the component's interface by specifying its inputs, outputs, and the method that will process them. The method name must match the `method` field in your outputs list, as this is how Langflow knows which method to call to generate each output.
|
|
This example creates a minimal custom component skeleton.
|
|
For more information on creating your custom component, see [Create custom Python components](/components-custom-components).
|
|
```python
|
|
from typing import Any, Dict, Optional
|
|
import pandas as pd
|
|
from langflow.custom import Component
|
|
|
|
class DataFrameProcessor(Component):
|
|
"""A component that processes pandas DataFrames with various operations."""
|
|
|
|
display_name: str = "DataFrame Processor"
|
|
description: str = "Process and transform pandas DataFrames with various operations like filtering, sorting, and aggregation."
|
|
documentation: str = "https://docs.langflow.org/components-dataframe-processor"
|
|
icon: str = "DataframeIcon"
|
|
priority: int = 100
|
|
name: str = "dataframe_processor"
|
|
|
|
# input and output lists
|
|
inputs = []
|
|
outputs = []
|
|
|
|
# method
|
|
def some_output_method(self):
|
|
return ...
|
|
```
|
|
|
|
5. Save the `dataframe_processor.py` to the `src > backend > base > langflow > components` directory.
|
|
This example adds a data component, so add it to the `/data` directory.
|
|
|
|
6. Add the component dependency to `src > backend > base > langflow > components > data > __init__.py` as `from .DataFrameProcessor import DataFrameProcessor`.
|
|
You can view the [/data/__init__.py](https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/components/data/__init__.py) in the Langflow repository.
|
|
|
|
7. Add any new dependencies to the [pyproject.toml](https://github.com/langflow-ai/langflow/blob/main/pyproject.toml#L20) file.
|
|
|
|
8. Submit documentation for your component. For this example component, you would submit documentation to the [Data components page](https://github.com/langflow-ai/langflow/blob/main/docs/docs/Components/components-data.mdx).
|
|
|
|
9. Submit your changes as a pull request. The Langflow team will review, suggest changes, and add your component to Langflow.
|
|
|
|
## Best practices for modifying components
|
|
|
|
When creating or updating components, follow these best practices to maintain backward compatibility and ensure a smooth experience for users.
|
|
|
|
### Don't rename the class or `name` attribute
|
|
|
|
Changing the class name or the `name` attribute breaks the component for all existing users. This happens because the frontend tests the `type` attribute, which is set to the class' name or the `name` attribute. If these names change, the component effectively becomes a new component, and the old component disappears.
|
|
|
|
Instead, do the following:
|
|
* Change only the display name if the old name is unclear.
|
|
* Change only the display name if functionality changes but remains related.
|
|
* If a new internal name is necessary, mark the old component as `legacy=true` and create a new component.
|
|
|
|
For example:
|
|
```python
|
|
class MyCustomComponent(BaseComponent):
|
|
name = "my_custom_component_internal"
|
|
legacy = True
|
|
```
|
|
|
|
### Don't remove fields and outputs
|
|
|
|
Removing fields or outputs can cause edges to disconnect and change the behavior of components.
|
|
|
|
Instead, mark fields as `deprecated` and keep them in the same location. If removal is absolutely necessary, you must define and document a migration plan. Always clearly communicate any changes in the field's information to users.
|
|
|
|
### Maintain outdated components as legacy
|
|
|
|
When updating components, create them as completely separate entities while maintaining the old component as a legacy version. Always ensure backward compatibility and never remove methods and attributes from base classes, such as `LCModelComponent`.
|
|
|
|
### Favor asynchronous methods
|
|
|
|
Always favor asynchronous methods and functions in your components. When interacting with files, use `aiofile` and `anyio.Path` for better performance and compatibility.
|
|
|
|
### Include tests with your component
|
|
|
|
Include tests for your changes using `ComponentTestBase` classes. For more information, see [Contribute component tests](/contributing-component-tests).
|
|
|
|
### Documentation
|
|
|
|
When documenting changes in pull requests, clearly explain *what* changed, such as display name updates or new fields, *why* it changed, such as improvements or bug fixes, and the *impact* on existing users.
|
|
|
|
For example:
|
|
|
|
<details>
|
|
<summary>Example PR</summary>
|
|
|
|
```markdown
|
|
# Pull request with changes to Notify component
|
|
|
|
This pull request updates the Notify component.
|
|
|
|
## What changed
|
|
- Added new `timeout` field to control how long the component waits for a response.
|
|
- Renamed `message` field to `notification_text` for clarity.
|
|
- Added support for async operations.
|
|
- Deprecated the `retry_count` field in favor of `max_retries`.
|
|
|
|
## Why it changed
|
|
- `timeout` field addresses user requests for better control over wait times.
|
|
- `message` to `notification_text` change makes the field's purpose clearer.
|
|
- Async support improves performance in complex flows.
|
|
- `retry_count` to `max_retries` aligns with common retry pattern terminology.
|
|
|
|
## Impact on users
|
|
- New `timeout` field is optional (defaults to 30 seconds).
|
|
- Users will see a deprecation warning for `retry_count`.
|
|
- Migration: Replace `retry_count` with `max_retries` in existing flows.
|
|
- Both fields will work until version 2.0.
|
|
- No action needed for async support - it's backward compatible.
|
|
```
|
|
|
|
</details>
|
|
|
|
## Example pull request flow
|
|
|
|
1. Create or update a component.
|
|
Maintain the class name and `name` attribute if the purpose remains the same.
|
|
Otherwise, create a new component and move the old component to `legacy`.
|
|
2. Add tests.
|
|
Create tests using one of the `ComponentTestBase` classes.
|
|
For more information, see [Contribute component tests](/contributing-component-tests).
|
|
3. Flag outdated fields and outputs as `deprecated` and keep them in the same location to ensure backward compatibility.
|
|
4. Document your changes.
|
|
Include migration instructions if breaking changes occur. |