docs: contribute custom components refresh (#7971)
* rewrite-to-use-data-component * code-font * cleanup * update-build-behavior * comment-out-for-build * icon-is-str * repeat-deprecation-info * code-review * Apply suggestions from code review Co-authored-by: KimberlyFields <46325568+KimberlyFields@users.noreply.github.com> * add-anchor-link --------- Co-authored-by: Edwin Jose <edwin.jose@datastax.com> Co-authored-by: KimberlyFields <46325568+KimberlyFields@users.noreply.github.com>
This commit is contained in:
parent
695942e391
commit
e8f4dba133
2 changed files with 166 additions and 14 deletions
|
|
@ -23,7 +23,7 @@ For example, if the component being tested is `PromptComponent`, then the test c
|
|||
|
||||
## Imports, inheritance, and mandatory methods
|
||||
|
||||
To standardize comoponent tests, base test classes have been created and should be imported and inherited by all component test classes. These base classes are located in the file `src/backend/tests/unit/base.py`.
|
||||
To standardize component tests, base test classes have been created and should be imported and inherited by all component test classes. These base classes are located in the file `src/backend/tests/unit/base.py`.
|
||||
|
||||
To import the base test classes:
|
||||
|
||||
|
|
|
|||
|
|
@ -4,20 +4,172 @@ slug: /contributing-components
|
|||
---
|
||||
|
||||
|
||||
New components are added as objects of the [CustomComponent](https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/custom/custom_component/custom_component.py) class.
|
||||
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.
|
||||
|
||||
Any dependencies are added to the [pyproject.toml](https://github.com/langflow-ai/langflow/blob/main/pyproject.toml#L148) file.
|
||||
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
|
||||
## Contribute an example component to Langflow
|
||||
|
||||
Anyone can contribute an example component. For example, if you created a new document loader called **MyCustomDocumentLoader**, you can follow these steps to contribute it 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. Write your loader as an object of the [CustomComponent](https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/custom/custom_component/custom_component.py) class. You'll create a new class, `MyCustomDocumentLoader`, that will inherit from `CustomComponent` and override the base class's methods.
|
||||
2. Define optional attributes like `display_name`, `description`, and `documentation` to provide information about your custom component.
|
||||
3. Implement the `build_config` method to define the configuration options for your custom component.
|
||||
4. Implement the `build` method to define the logic for taking input parameters specified in the `build_config` method and returning the desired output.
|
||||
5. Add the code to the [/components/documentloaders](https://github.com/langflow-ai/langflow/tree/dev/src/backend/base/langflow/components) folder.
|
||||
6. Add the dependency to [/documentloaders/__init__.py](https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/components/documentloaders/__init__.py) as `from .MyCustomDocumentLoader import MyCustomDocumentLoader`.
|
||||
7. Add any new dependencies to the [pyproject.toml](https://github.com/langflow-ai/langflow/blob/main/pyproject.toml#L148) file.
|
||||
8. Submit documentation for your component. For this example, you'd submit documentation to the [loaders page](https://github.com/langflow-ai/langflow/blob/main/docs/docs/Components/components-loaders.md).
|
||||
9. Submit your changes as a pull request. The Langflow team will have a look, suggest changes, and add your component 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 UI.
|
||||
* `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.md).
|
||||
|
||||
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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue