From 6b7ab2adedbf31c103c654941614da328be6d519 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 27 Jul 2023 06:58:10 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs(custom-component.mdx):=20ad?= =?UTF-8?q?d=20documentation=20for=20custom=20components=20=F0=9F=8E=A8=20?= =?UTF-8?q?style(custom.css):=20update=20styling=20for=20code=20blocks=20a?= =?UTF-8?q?nd=20sidebar=20in=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs/guidelines/custom-component.mdx | 317 ++++++++++++++++++++++ docs/src/css/custom.css | 32 ++- 2 files changed, 338 insertions(+), 11 deletions(-) create mode 100644 docs/docs/guidelines/custom-component.mdx diff --git a/docs/docs/guidelines/custom-component.mdx b/docs/docs/guidelines/custom-component.mdx new file mode 100644 index 000000000..96a55ccd7 --- /dev/null +++ b/docs/docs/guidelines/custom-component.mdx @@ -0,0 +1,317 @@ +--- +description: Custom Components +hide_table_of_contents: true +--- + +# Custom Components + +A Custom Component has almost infinite possibilities. It can be a simple function that takes a string and returns a string, +or it can be a complex function that takes other components, calls APIs, and returns a custom object only you know how to use (which might not be ideal). + +Let's take a look at the basic rules, then we'll talk about the ones that are not so basic. + +## TL;DR + +This is a simple example of a Custom Component. We will go over the rules in detail later. + + + +```python +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Best Component" + description = "This is the best component ever" + + def build_config(self) -> dict: + cool_tool_names = ["Cool Tool", + "Cooler Tool", + "Coolest Tool"] + return { + "description": {"multiline": True}, + "name": {"is_list": True, + "options": cool_tool_names}} + + def build(self, name: str, description: str, chain: Chain) -> Tool: + return Tool(name=name, + description=description, + func=chain.run) +``` + + + +## Rules: + + + +## Rule 1 + +The class must inherit from _`CustomComponent`_. + +```python +# focus +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +# focus +class BestComponent(CustomComponent): + display_name = "Custom Component" + description = "This is a custom component" + + def build_config(self) -> dict: + ... + + def build(self): + ... +``` + +--- + +## Rule 2: + +The class must have a _`build`_ method + +```python +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Custom Component" + description = "This is a custom component" + + def build_config(self) -> dict: + ... + + # focus[5:13] + def build(self): + ... +``` + +--- + +## Rule 3 + +The type annotations of the _`build`_ method will be used to create the fields of the component + +The types supported are: + +- _`str`_, _`int`_, _`float`_, _`bool`_, _`list`_, _`dict`_ +- [_`langchain.chains.base.Chain`_](focus://3) +- [_`langchain.PromptTemplate`_](focus://4) +- [_`langchain.llms.base.BaseLLM`_](focus://5) +- [_`langchain.Tool`_](focus://6) +- _`langchain.document_loaders.base.BaseLoader`_ +- _`langchain.schema.Document`_ +- _`langchain.text_splitters.TextSplitter`_ +- _`langchain.vectorstores.base.VectorStore`_ +- _`langchain.embeddings.base.Embeddings`_ +- _`langchain.schema.BaseRetriever`_ + +```python +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Custom Component" + description = "This is a custom component" + + def build_config(self) -> dict: + ... + + # focus[14:75] + def build(self): + ... +``` + +--- + +```python +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Custom Component" + description = "This is a custom component" + + # focus + def build_config(self) -> dict: + ... + + def build(self): + ... +``` + +## Rule 4: + +The class can have a [_`build_config`_](focus://11:19) method + +- The _`build_config`_ method will be used to create the config fields of the component (if any) +- It should always return a _`dict`_ + +The _`dict`_ should have the following format: + +- The top level keys are the names of the fields +- The values are _`dict`_ with the following keys: + + - _`field_type: str`_: The type of the field (can be str, int, float, bool, file or any of the types supported by the _`build`_ method) + - _`is_list: bool`_: If the field is a list + - _`options: List[str]`_: If the field is a list, the options that will be displayed + - _`multiline: bool`_: If the field is a string, if it should be multiline + - _`input_types: List[str]`_: To be used when you want a _`str`_ field to have connectable handles. + - _`dispaly_name: str`_: To change the name of the field + - _`advanced: bool`_: To hide the field in the default view + - _`password: bool`_: To mask the input + - _`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' + (must be used in conjunction with _`suffixes`_) + + Example: _`["json", "yaml", "yml"]`_ + + - _`suffixes: List[str]`_: This is a requirement if the _`field_type`_ is 'file' (must be used in conjunction with _`file_types`_, and it must be a list of strings like 'json') + + Example: _`[".json", ".yaml", ".yml"]`_ + +--- + +# Change the name + +We can change the name of the component by adding a _`display_name`_ attribute. + +```python focus=9 +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Best Component" + description = "This is a custom component" + + def build_config(self) -> dict: + ... + + def build(self): + ... +``` + +--- + +# Change the description + +We can change the description of the component by adding a _`description`_ attribute. + +```python focus=10 +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Best Component" + description = "This is the best component ever" + + def build_config(self) -> dict: + ... + + def build(self): + ... +``` + +--- + +# Add a config + +The _`build_config`_ method will be used to create the config fields of the component (if any). + +- _`multiline`_ is a special option that will give the option to open a text editor. + +- _`is_list`_ is a special option that will give the option to add multiple values. When paired with _`options`_ it will transform it into a select field. + +```python focus=12:19 +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Best Component" + description = "This is the best component ever" + + def build_config(self) -> dict: + cool_tool_names = ["Cool Tool", + "Cooler Tool", + "Coolest Tool"] + return { + "description": {"multiline": True}, + "name": {"is_list": True, + "options": cool_tool_names}} + + def build(self): + ... +``` + +--- + +```python focus=21:25 +from langflow import CustomComponent +from langchain.chains import LLMChain +from langchain.chains.base import Chain +from langchain import PromptTemplate +from langchain.llms.base import BaseLLM +from langchain import Tool + +class BestComponent(CustomComponent): + display_name = "Best Component" + description = "This is the best component ever" + + def build_config(self) -> dict: + cool_tool_names = ["Cool Tool", + "Cooler Tool", + "Coolest Tool"] + return { + "description": {"multiline": True}, + "name": {"is_list": True, + "options": cool_tool_names}} + + def build(self, name: str, description: str, chain: Chain) -> Tool: + return Tool(name=name, + description=description, + func=chain.run) +``` + +# Add the build method + +- name is a string +- description is a string +- chain is a Chain +- The return type is Tool + + diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 2f6f992f3..a81f8ed7d 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -3,17 +3,19 @@ * bundles Infima by default. Infima is a CSS framework designed to * work well for content-centric websites. */ - :root { +:root { --ifm-background-color: var(--token-primary-bg-c); --ifm-navbar-link-hover-color: initial; --ifm-navbar-padding-vertical: 0; --ifm-navbar-item-padding-vertical: 0; - --ifm-font-family-base: -apple-system, BlinkMacSystemFont, Inter, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI emoji'; - --ifm-font-family-monospace: 'SFMono-Regular', 'Roboto Mono', Consolas, 'Liberation Mono', Menlo, Courier, monospace; + --ifm-font-family-base: -apple-system, BlinkMacSystemFont, Inter, Helvetica, + Arial, sans-serif, "Apple Color Emoji", "Segoe UI emoji"; + --ifm-font-family-monospace: "SFMono-Regular", "Roboto Mono", Consolas, + "Liberation Mono", Menlo, Courier, monospace; } .theme-doc-sidebar-item-category.menu__list-item:not(:first-child) { - margin-top: 1.5rem!important; + margin-top: 1.5rem !important; } .docusaurus-highlight-code-line { @@ -31,7 +33,7 @@ transform: skewY(6deg); } -[class^='announcementBar'] { +[class^="announcementBar"] { z-index: 10; } @@ -112,7 +114,7 @@ body { } .header-github-link:before { - content: ''; + content: ""; width: 24px; height: 24px; display: flex; @@ -126,7 +128,7 @@ body { } .header-twitter-link::before { - content: ''; + content: ""; width: 24px; height: 24px; display: flex; @@ -140,7 +142,7 @@ body { } .header-discord-link::before { - content: ''; + content: ""; width: 24px; height: 24px; display: flex; @@ -148,7 +150,6 @@ body { background-size: contain; } - /* Images */ .image-rendering-crisp { image-rendering: crisp-edges; @@ -164,7 +165,7 @@ body { .img-center { display: flex; justify-content: center; - width: 100%, + width: 100%; } .resized-image { @@ -188,4 +189,13 @@ body { .mendable-search { width: 140px; } -} \ No newline at end of file +} + +.ch-scrollycoding-content { + max-width: 40% !important; +} + +.ch-scrollycoding-sticker { + max-width: 60% !important; + min-width: 60% !important; +}