Update categories and components

This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-03-04 17:40:32 -03:00
commit 73b3013763
33 changed files with 163 additions and 265 deletions

View file

@ -40,7 +40,9 @@ class UrlLoaderComponent(CustomComponent):
except Exception as e:
raise ValueError(f"No loader found for: {web_path}") from e
docs = loader_instance.load()
avg_length = sum(len(doc.page_content) for doc in docs if hasattr(doc, "page_content")) / len(docs)
avg_length = sum(
len(doc.page_content) for doc in docs if hasattr(doc, "page_content")
) / len(docs)
self.status = f"""{len(docs)} documents)
\nAvg. Document Length (characters): {int(avg_length)}
Documents: {docs[:3]}..."""

View file

@ -1,6 +1,6 @@
from typing import Optional, Union
from langflow.components.io.base.chat import ChatComponent
from langflow.base.io.chat import ChatComponent
from langflow.field_typing import Text
from langflow.schema import Record

View file

@ -1,6 +1,6 @@
from typing import Optional
from langflow.components.io.base.text import TextComponent
from langflow.base.io.text import TextComponent
from langflow.field_typing import Text

View file

@ -1,6 +1,6 @@
from typing import Optional, Union
from langflow.components.io.base.chat import ChatComponent
from langflow.base.io.chat import ChatComponent
from langflow.field_typing import Text
from langflow.schema import Record

View file

@ -1,6 +1,6 @@
from typing import Optional
from langflow.components.io.base.text import TextComponent
from langflow.base.io.text import TextComponent
from langflow.field_typing import Text

View file

@ -0,0 +1,109 @@
import asyncio
from typing import List, Optional, Union
import httpx
import requests
from langflow import CustomComponent
from langflow.schema import Record
from langflow.services.database.models.base import orjson_dumps
class APIRequest(CustomComponent):
display_name: str = "API Request"
description: str = "Make an HTTP request to the given URL."
output_types: list[str] = ["Record"]
documentation: str = "https://docs.langflow.org/components/utilities#api-request"
beta: bool = True
field_config = {
"url": {"display_name": "URL", "info": "The URL to make the request to."},
"method": {
"display_name": "Method",
"info": "The HTTP method to use.",
"field_type": "str",
"options": ["GET", "POST", "PATCH", "PUT"],
"value": "GET",
},
"headers": {
"display_name": "Headers",
"info": "The headers to send with the request.",
},
"record": {
"display_name": "Record",
"info": "The record to send with the request (for POST, PATCH, PUT).",
},
"timeout": {
"display_name": "Timeout",
"field_type": "int",
"info": "The timeout to use for the request.",
"value": 5,
},
}
async def make_request(
self,
session: requests.Session,
method: str,
url: str,
headers: Optional[dict] = None,
record: Optional[Record] = None,
timeout: int = 5,
) -> Record:
method = method.upper()
if method not in ["GET", "POST", "PATCH", "PUT"]:
raise ValueError(f"Unsupported method: {method}")
data = record.text if record else None
try:
async with httpx.AsyncClient() as client:
response = await client.request(
method, url, headers=headers, content=data, timeout=timeout
)
try:
response_json = response.json()
result = orjson_dumps(response_json, indent_2=False)
except Exception:
result = response.text
return Record(
text=result,
data={
"source": url,
"headers": headers,
"status_code": response.status_code,
},
)
except httpx.TimeoutException:
return Record(
text="Request Timed Out",
data={"source": url, "headers": headers, "status_code": 408},
)
except Exception as exc:
return Record(
text=str(exc),
data={"source": url, "headers": headers, "status_code": 500},
)
async def build(
self,
method: str,
url: List[str],
headers: Optional[dict] = None,
record: Optional[Union[Record, List[Record]]] = None,
timeout: int = 5,
) -> List[Record]:
if headers is None:
headers = {}
urls = url if isinstance(url, list) else [url]
records = (
record
if isinstance(record, list)
else [record] if record else [None] * len(urls)
)
results = await asyncio.gather(
*[
self.make_request(method, u, headers, doc, timeout)
for u, doc in zip(urls, records)
]
)
return results

View file

@ -4,6 +4,7 @@ from langflow.field_typing import Data
class Component(CustomComponent):
documentation: str = "http://docs.langflow.org/components/custom"
icon = "custom_components"
def build_config(self):
return {"param": {"display_name": "Parameter"}}

View file

@ -1,75 +0,0 @@
from typing import Optional, Text
import requests
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.services.database.models.base import orjson_dumps
class GetRequest(CustomComponent):
display_name: str = "GET Request"
description: str = "Make a GET request to the given URL."
output_types: list[str] = ["Document"]
documentation: str = "https://docs.langflow.org/components/utilities#get-request"
beta: bool = True
field_config = {
"url": {
"display_name": "URL",
"info": "The URL to make the request to",
"is_list": True,
},
"headers": {
"display_name": "Headers",
"info": "The headers to send with the request.",
},
"code": {"show": False},
"timeout": {
"display_name": "Timeout",
"field_type": "int",
"info": "The timeout to use for the request.",
"value": 5,
},
}
def get_document(self, session: requests.Session, url: str, headers: Optional[dict], timeout: int) -> Document:
try:
response = session.get(url, headers=headers, timeout=int(timeout))
try:
response_json = response.json()
result = orjson_dumps(response_json, indent_2=False)
except Exception:
result = response.text
self.repr_value = result
return Document(
page_content=result,
metadata={
"source": url,
"headers": headers,
"status_code": response.status_code,
},
)
except requests.Timeout:
return Document(
page_content="Request Timed Out",
metadata={"source": url, "headers": headers, "status_code": 408},
)
except Exception as exc:
return Document(
page_content=Text(exc),
metadata={"source": url, "headers": headers, "status_code": 500},
)
def build(
self,
url: str,
headers: Optional[dict] = None,
timeout: int = 5,
) -> list[Document]:
if headers is None:
headers = {}
urls = url if isinstance(url, list) else [url]
with requests.Session() as session:
documents = [self.get_document(session, u, headers, timeout) for u in urls]
self.repr_value = documents
return documents

View file

@ -1,78 +0,0 @@
from typing import Optional, Text
import requests
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.services.database.models.base import orjson_dumps
class PostRequest(CustomComponent):
display_name: str = "POST Request"
description: str = "Make a POST request to the given URL."
output_types: list[str] = ["Document"]
documentation: str = "https://docs.langflow.org/components/utilities#post-request"
beta: bool = True
field_config = {
"url": {"display_name": "URL", "info": "The URL to make the request to."},
"headers": {
"display_name": "Headers",
"info": "The headers to send with the request.",
},
"code": {"show": False},
"document": {"display_name": "Document"},
}
def post_document(
self,
session: requests.Session,
document: Document,
url: str,
headers: Optional[dict] = None,
) -> Document:
try:
response = session.post(url, headers=headers, data=document.page_content)
try:
response_json = response.json()
result = orjson_dumps(response_json, indent_2=False)
except Exception:
result = response.text
self.repr_value = result
return Document(
page_content=result,
metadata={
"source": url,
"headers": headers,
"status_code": response,
},
)
except Exception as exc:
return Document(
page_content=Text(exc),
metadata={
"source": url,
"headers": headers,
"status_code": 500,
},
)
def build(
self,
document: Document,
url: str,
headers: Optional[dict] = None,
) -> list[Document]:
if headers is None:
headers = {}
if not isinstance(document, list) and isinstance(document, Document):
documents: list[Document] = [document]
elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document):
documents = document
else:
raise ValueError("document must be a Document or a list of Documents")
with requests.Session() as session:
documents = [self.post_document(session, doc, url, headers) for doc in documents]
self.repr_value = documents
return documents

View file

@ -1,89 +0,0 @@
from typing import List, Optional, Text
import requests
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.services.database.models.base import orjson_dumps
class UpdateRequest(CustomComponent):
display_name: str = "Update Request"
description: str = "Make a PATCH request to the given URL."
output_types: list[str] = ["Document"]
documentation: str = "https://docs.langflow.org/components/utilities#update-request"
beta: bool = True
field_config = {
"url": {"display_name": "URL", "info": "The URL to make the request to."},
"headers": {
"display_name": "Headers",
"field_type": "NestedDict",
"info": "The headers to send with the request.",
},
"code": {"show": False},
"document": {"display_name": "Document"},
"method": {
"display_name": "Method",
"field_type": "str",
"info": "The HTTP method to use.",
"options": ["PATCH", "PUT"],
"value": "PATCH",
},
}
def update_document(
self,
session: requests.Session,
document: Document,
url: str,
headers: Optional[dict] = None,
method: str = "PATCH",
) -> Document:
try:
if method == "PATCH":
response = session.patch(url, headers=headers, data=document.page_content)
elif method == "PUT":
response = session.put(url, headers=headers, data=document.page_content)
else:
raise ValueError(f"Unsupported method: {method}")
try:
response_json = response.json()
result = orjson_dumps(response_json, indent_2=False)
except Exception:
result = response.text
self.repr_value = result
return Document(
page_content=result,
metadata={
"source": url,
"headers": headers,
"status_code": response.status_code,
},
)
except Exception as exc:
return Document(
page_content=Text(exc),
metadata={"source": url, "headers": headers, "status_code": 500},
)
def build(
self,
method: str,
document: Document,
url: str,
headers: Optional[dict] = None,
) -> List[Document]:
if headers is None:
headers = {}
if not isinstance(document, list) and isinstance(document, Document):
documents: list[Document] = [document]
elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document):
documents = document
else:
raise ValueError("document must be a Document or a list of Documents")
with requests.Session() as session:
documents = [self.update_document(session, doc, url, headers, method) for doc in documents]
self.repr_value = documents
return documents

View file

@ -26,6 +26,7 @@ import {
} from "../../../../utils/utils";
import DisclosureComponent from "../DisclosureComponent";
import SidebarDraggableComponent from "./sideBarDraggableComponent";
import { sortKeys } from "./utils";
export default function ExtraSidebar(): JSX.Element {
const data = useTypesStore((state) => state.data);
@ -320,19 +321,7 @@ export default function ExtraSidebar(): JSX.Element {
<div className="side-bar-components-div-arrangement">
{Object.keys(dataFilter)
.sort((a, b) => {
if (a.toLowerCase() === "saved_components") {
return -1;
} else if (b.toLowerCase() === "saved_components") {
return 1;
} else if (a.toLowerCase() === "custom_components") {
return -2;
} else if (b.toLowerCase() === "custom_components") {
return 2;
} else {
return a.localeCompare(b);
}
})
.sort(sortKeys)
.map((SBSectionName: keyof APIObjectType, index) =>
Object.keys(dataFilter[SBSectionName]).length > 0 ? (
<DisclosureComponent

View file

@ -0,0 +1,31 @@
export function sortKeys(a: string, b: string) {
// Define the order of specific keys
const order = [
"saved_components",
"inputs",
"outputs",
"data",
"utilities",
"models",
];
const indexA = order.indexOf(a.toLowerCase());
const indexB = order.indexOf(b.toLowerCase());
// Check if both keys are in the predefined order
if (indexA !== -1 && indexB !== -1) {
return indexA - indexB;
}
// If only 'a' is in the predefined order, it should come first
if (indexA !== -1) {
return -1;
}
// If only 'b' is in the predefined order, it should come first
if (indexB !== -1) {
return 1;
}
// If neither 'a' nor 'b' are in the predefined order, sort them alphabetically
return a.localeCompare(b);
}

View file

@ -8,7 +8,6 @@ import {
Bot,
Boxes,
Braces,
Cable,
Check,
CheckCircle2,
ChevronDown,
@ -46,6 +45,7 @@ import {
FileUp,
Fingerprint,
FlaskConical,
FolderOpen,
FolderPlus,
FormInput,
Forward,
@ -205,6 +205,9 @@ export const gradients = [
];
export const nodeColors: { [char: string]: string } = {
inputs: "#9AAE42",
outputs: "#AA2411",
data: "#6344BE",
prompts: "#4367BF",
models: "#AA2411",
model_specs: "#6344BE",
@ -225,16 +228,19 @@ export const nodeColors: { [char: string]: string } = {
toolkits: "#DB2C2C",
wrappers: "#E6277A",
utilities: "#31A3CC",
langchain_utilities: "#31A3CC",
output_parsers: "#E6A627",
str: "#31a3cc",
Text: "#31a3cc",
retrievers: "#e6b25a",
unknown: "#9CA3AF",
custom_components: "#ab11ab",
io: "#e6b25a",
};
export const nodeNames: { [char: string]: string } = {
inputs: "Inputs",
outputs: "Outputs",
data: "Data",
prompts: "Prompts",
models: "Language Models",
model_specs: "Model Specs",
@ -253,13 +259,16 @@ export const nodeNames: { [char: string]: string } = {
textsplitters: "Text Splitters",
retrievers: "Retrievers",
utilities: "Utilities",
langchain_utilities: "Langchain Utilities",
output_parsers: "Output Parsers",
custom_components: "Custom",
io: "I/O",
unknown: "Other",
};
export const nodeIconsLucide: iconsType = {
inputs: Download,
outputs: Upload,
data: FolderOpen,
AzureChatOpenAi: AzureIcon,
Ollama: OllamaIcon,
ChatOllama: OllamaIcon,
@ -342,6 +351,7 @@ export const nodeIconsLucide: iconsType = {
textsplitters: Scissors,
wrappers: Gift,
utilities: Wand2,
langchain_utilities: Wand2,
WolframAlphaAPIWrapper: SvgWolfram,
output_parsers: Compass,
retrievers: FileSearch,
@ -443,13 +453,11 @@ export const nodeIconsLucide: iconsType = {
Link,
ToyBrick,
RefreshCcw,
ListRestart,
Combine,
TerminalIcon,
TerminalSquare,
TextCursorInput,
Repeat,
io: Cable,
Sliders,
ScreenShare,
Code,