Merge remote-tracking branch 'origin/dev' into fix_toolkits
This commit is contained in:
commit
410ba005cd
85 changed files with 2322 additions and 273 deletions
390
poetry.lock
generated
390
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "langflow"
|
||||
version = "0.0.78"
|
||||
version = "0.0.79"
|
||||
description = "A Python package with a built-in web application"
|
||||
authors = ["Logspace <contact@logspace.ai>"]
|
||||
maintainers = [
|
||||
|
|
@ -29,7 +29,7 @@ google-search-results = "^2.4.1"
|
|||
google-api-python-client = "^2.79.0"
|
||||
typer = "^0.7.0"
|
||||
gunicorn = "^20.1.0"
|
||||
langchain = "^0.0.184"
|
||||
langchain = "^0.0.186"
|
||||
openai = "^0.27.7"
|
||||
types-pyyaml = "^6.0.12.8"
|
||||
dill = "^0.3.6"
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ llms:
|
|||
- OpenAI
|
||||
# - AzureOpenAI
|
||||
- ChatOpenAI
|
||||
- HuggingFaceHub
|
||||
- LlamaCpp
|
||||
- CTransformers
|
||||
- Cohere
|
||||
|
|
@ -66,9 +65,9 @@ prompts:
|
|||
- ZeroShotPrompt
|
||||
textsplitters:
|
||||
- CharacterTextSplitter
|
||||
- RecursiveCharacterTextSplitter
|
||||
- LatexTextSplitter
|
||||
- PythonCodeTextSplitter
|
||||
# - RecursiveCharacterTextSplitter
|
||||
# - LatexTextSplitter
|
||||
# - PythonCodeTextSplitter
|
||||
toolkits:
|
||||
- OpenAPIToolkit
|
||||
- JsonToolkit
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import contextlib
|
|||
import inspect
|
||||
import types
|
||||
import warnings
|
||||
from copy import deepcopy
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from langflow.cache import base as cache_utils
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Dict, List, Optional
|
||||
|
||||
from langchain.agents import loading
|
||||
from langchain.agents import types
|
||||
|
||||
from langflow.custom.customs import get_custom_nodes
|
||||
from langflow.interface.agents.custom import CUSTOM_AGENTS
|
||||
|
|
@ -16,7 +16,7 @@ class AgentCreator(LangChainTypeCreator):
|
|||
@property
|
||||
def type_to_loader_dict(self) -> Dict:
|
||||
if self.type_dict is None:
|
||||
self.type_dict = loading.AGENT_TO_CLASS
|
||||
self.type_dict = types.AGENT_TO_CLASS
|
||||
# Add JsonAgent to the list of agents
|
||||
for name, agent in CUSTOM_AGENTS.items():
|
||||
# TODO: validate AgentType
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ from langflow.utils import util, validate
|
|||
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:
|
||||
"""Instantiate class from module type and key, and params"""
|
||||
params = convert_params_to_sets(params)
|
||||
|
||||
params = convert_kwargs(params)
|
||||
if node_type in CUSTOM_AGENTS:
|
||||
custom_agent = CUSTOM_AGENTS.get(node_type)
|
||||
if custom_agent:
|
||||
|
|
@ -50,6 +50,16 @@ def convert_params_to_sets(params):
|
|||
return params
|
||||
|
||||
|
||||
def convert_kwargs(params):
|
||||
# if *kwargs are passed as a string, convert to dict
|
||||
# first find any key that has kwargs in it
|
||||
kwargs_keys = [key for key in params.keys() if "kwargs" in key]
|
||||
for key in kwargs_keys:
|
||||
if isinstance(params[key], str):
|
||||
params[key] = json.loads(params[key])
|
||||
return params
|
||||
|
||||
|
||||
def instantiate_based_on_type(class_object, base_type, node_type, params):
|
||||
if base_type == "agents":
|
||||
return instantiate_agent(class_object, params)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class TextSplitterCreator(LangChainTypeCreator):
|
|||
"type": "int",
|
||||
"required": True,
|
||||
"show": True,
|
||||
"value": 4000,
|
||||
"value": 1000,
|
||||
"name": "chunk_size",
|
||||
"display_name": "Chunk Size",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -3,7 +3,7 @@ from typing import List, Optional
|
|||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from langflow.template.constants import FORCE_SHOW_FIELDS
|
||||
from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS
|
||||
from langflow.template.field.base import TemplateField
|
||||
from langflow.template.template.base import Template
|
||||
from langflow.utils import constants
|
||||
|
|
|
|||
32
src/backend/langflow/template/frontend_node/constants.py
Normal file
32
src/backend/langflow/template/frontend_node/constants.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
FORCE_SHOW_FIELDS = [
|
||||
"allowed_tools",
|
||||
"memory",
|
||||
"prefix",
|
||||
"examples",
|
||||
"temperature",
|
||||
"model_name",
|
||||
"headers",
|
||||
"max_value_length",
|
||||
"max_tokens",
|
||||
]
|
||||
|
||||
DEFAULT_PROMPT = """
|
||||
I want you to act as a naming consultant for new companies.
|
||||
|
||||
Here are some examples of good company names:
|
||||
|
||||
- search engine, Google
|
||||
- social media, Facebook
|
||||
- video sharing, YouTube
|
||||
|
||||
The name should be short, catchy and easy to remember.
|
||||
|
||||
What is a good name for a company that makes {product}?
|
||||
"""
|
||||
|
||||
SYSTEM_PROMPT = """
|
||||
You are a helpful assistant that talks casually about life in general.
|
||||
You are a good listener and you can talk about anything.
|
||||
"""
|
||||
|
||||
HUMAN_PROMPT = "{input}"
|
||||
|
|
@ -2,7 +2,11 @@ from typing import Optional
|
|||
|
||||
from langchain.agents.mrkl import prompt
|
||||
|
||||
from langflow.template.constants import DEFAULT_PROMPT, HUMAN_PROMPT, SYSTEM_PROMPT
|
||||
from langflow.template.frontend_node.constants import (
|
||||
DEFAULT_PROMPT,
|
||||
HUMAN_PROMPT,
|
||||
SYSTEM_PROMPT,
|
||||
)
|
||||
from langflow.template.field.base import TemplateField
|
||||
from langflow.template.frontend_node.base import FrontendNode
|
||||
from langflow.template.template.base import Template
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import ast
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
|
|
@ -12,7 +13,7 @@ class UtilitiesFrontendNode(FrontendNode):
|
|||
# field.field_type could be "Literal['news', 'search', 'places', 'images']
|
||||
# we need to convert it to a list
|
||||
if "Literal" in field.field_type:
|
||||
field.options = eval(field.field_type.replace("Literal", ""))
|
||||
field.options = ast.literal_eval(field.field_type.replace("Literal", ""))
|
||||
field.is_list = True
|
||||
field.field_type = "str"
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -6,7 +6,7 @@ from typing import Dict, Optional
|
|||
|
||||
from docstring_parser import parse # type: ignore
|
||||
|
||||
from langflow.template.constants import FORCE_SHOW_FIELDS
|
||||
from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS
|
||||
from langflow.utils import constants
|
||||
|
||||
|
||||
|
|
|
|||
32
src/frontend/package-lock.json
generated
32
src/frontend/package-lock.json
generated
|
|
@ -32,6 +32,7 @@
|
|||
"react-router-dom": "^6.8.1",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-tabs": "^6.0.0",
|
||||
"react-tooltip": "^5.13.1",
|
||||
"reactflow": "^11.5.5",
|
||||
"rehype-mathjax": "^4.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
|
|
@ -897,6 +898,19 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.6.tgz",
|
||||
"integrity": "sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg=="
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.9.tgz",
|
||||
"integrity": "sha512-sosQxsqgxMNkV3C+3UqTS6LxP7isRLwX8WMepp843Rb3/b0Wz8+MdUkxJksByip3C2WwLugLHN1b4ibn//zKwQ==",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@headlessui/react": {
|
||||
"version": "1.7.10",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.10.tgz",
|
||||
|
|
@ -2938,6 +2952,11 @@
|
|||
"resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz",
|
||||
"integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g=="
|
||||
},
|
||||
"node_modules/classnames": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
|
||||
},
|
||||
"node_modules/client-only": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||
|
|
@ -6265,6 +6284,19 @@
|
|||
"react": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-tooltip": {
|
||||
"version": "5.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.13.1.tgz",
|
||||
"integrity": "sha512-9NstDFdjyy6cIH9zjeT70zXTHlW/TIGCOWQmhkAyqLFeQioLg1FXvb9ec7AxSpn0zyFUkFSLdFYxZRuewti3Aw==",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.0.0",
|
||||
"classnames": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.14.0",
|
||||
"react-dom": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
"react-router-dom": "^6.8.1",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-tabs": "^6.0.0",
|
||||
"react-tooltip": "^5.13.1",
|
||||
"reactflow": "^11.5.5",
|
||||
"rehype-mathjax": "^4.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ export default function ParameterComponent({
|
|||
) : left === true && type === "float" ? (
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
disableCopyPaste={true}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t) => {
|
||||
data.node.template[name].value = t;
|
||||
|
|
@ -184,6 +185,7 @@ export default function ParameterComponent({
|
|||
) : left === true && type === "int" ? (
|
||||
<IntComponent
|
||||
disabled={disabled}
|
||||
disableCopyPaste={true}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t) => {
|
||||
data.node.template[name].value = t;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import NodeModal from "../../modals/NodeModal";
|
|||
import { useCallback } from "react";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { debounce } from "../../utils";
|
||||
import TooltipReact from "../../components/ReactTooltipComponent";
|
||||
import Tooltip from "../../components/TooltipComponent";
|
||||
export default function GenericNode({
|
||||
data,
|
||||
|
|
@ -96,6 +97,7 @@ export default function GenericNode({
|
|||
deleteNode(data.id);
|
||||
return;
|
||||
}
|
||||
console.log(data);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -112,50 +114,15 @@ export default function GenericNode({
|
|||
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
|
||||
}}
|
||||
/>
|
||||
<Tooltip title={data.type} placement="top">
|
||||
<div className="ml-2 truncate">{data.type}</div>
|
||||
</Tooltip>
|
||||
<div>
|
||||
<Tooltip
|
||||
title={
|
||||
!validationStatus ? (
|
||||
"Validating..."
|
||||
) : (
|
||||
<div className="max-h-96 overflow-auto">
|
||||
{validationStatus.params.split("\n").map((line, index) => (
|
||||
<div key={index}>{line}</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className="ml-2 truncate">
|
||||
<TooltipReact
|
||||
delayShow={1000}
|
||||
selector={`node-selector-${data.type}`}
|
||||
htmlContent={data.type}
|
||||
position="top"
|
||||
>
|
||||
<div className="relative h-5 w-5">
|
||||
<CheckCircleIcon
|
||||
className={classNames(
|
||||
validationStatus && validationStatus.valid
|
||||
? "text-green-500 opacity-100"
|
||||
: "animate-spin text-green-500 opacity-0",
|
||||
"absolute w-5 transition-all duration-200 ease-in-out hover:text-gray-500 hover:dark:text-gray-300"
|
||||
)}
|
||||
/>
|
||||
<ExclamationCircleIcon
|
||||
className={classNames(
|
||||
validationStatus && !validationStatus.valid
|
||||
? "text-red-500 opacity-100"
|
||||
: "animate-spin text-red-500 opacity-0",
|
||||
"absolute w-5 transition-all duration-200 ease-in-out hover:text-gray-500 hover:dark:text-gray-600"
|
||||
)}
|
||||
/>
|
||||
<EllipsisHorizontalCircleIcon
|
||||
className={classNames(
|
||||
!validationStatus
|
||||
? "text-yellow-500 opacity-100"
|
||||
: "animate-spin text-yellow-500 opacity-0",
|
||||
"absolute w-5 transition-all duration-300 ease-in-out hover:text-gray-500 hover:dark:text-gray-600"
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className="ml-2 truncate">{data.type}</div>
|
||||
</TooltipReact>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
|
|
@ -183,17 +150,61 @@ export default function GenericNode({
|
|||
)
|
||||
? ""
|
||||
: "hidden",
|
||||
"h-6 w-6 hover:animate-spin dark:text-gray-300"
|
||||
"w-5 h-5 dark:text-gray-300"
|
||||
)}
|
||||
></Cog6ToothIcon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
deleteNode(data.id);
|
||||
}}
|
||||
>
|
||||
<TrashIcon className="h-6 w-6 hover:text-red-500 dark:text-gray-300 dark:hover:text-red-500"></TrashIcon>
|
||||
<TrashIcon className="w-5 h-5 dark:text-gray-300"></TrashIcon>
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<Tooltip
|
||||
title={
|
||||
!validationStatus ? (
|
||||
"Validating..."
|
||||
) : (
|
||||
<div className="max-h-96 overflow-auto">
|
||||
{validationStatus.params.split("\n").map((line, index) => (
|
||||
<div key={index}>{line}</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="w-5 h-5 relative top-[3px]">
|
||||
<div
|
||||
className={classNames(
|
||||
validationStatus && validationStatus.valid
|
||||
? "w-4 h-4 rounded-full bg-green-500 opacity-100"
|
||||
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||
)}
|
||||
></div>
|
||||
<div
|
||||
className={classNames(
|
||||
validationStatus && !validationStatus.valid
|
||||
? "w-4 h-4 rounded-full bg-red-500 opacity-100"
|
||||
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||
)}
|
||||
></div>
|
||||
<div
|
||||
className={classNames(
|
||||
!validationStatus
|
||||
? "w-4 h-4 rounded-full bg-yellow-500 opacity-100"
|
||||
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||
)}
|
||||
></div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
54
src/frontend/src/components/ReactTooltipComponent/index.tsx
Normal file
54
src/frontend/src/components/ReactTooltipComponent/index.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
"use client";
|
||||
import type { FC } from "react";
|
||||
import React from "react";
|
||||
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||
import "react-tooltip/dist/react-tooltip.css";
|
||||
import { classNames } from "../../utils";
|
||||
|
||||
type TooltipProps = {
|
||||
selector: string;
|
||||
content?: string;
|
||||
disabled?: boolean;
|
||||
htmlContent?: React.ReactNode;
|
||||
className?: string; // This should use !impornant to override the default styles eg: '!bg-white'
|
||||
position?: "top" | "right" | "bottom" | "left";
|
||||
clickable?: boolean;
|
||||
children: React.ReactNode;
|
||||
delayShow?: number;
|
||||
};
|
||||
|
||||
const TooltipReact: FC<TooltipProps> = ({
|
||||
selector,
|
||||
content,
|
||||
disabled,
|
||||
position = "top",
|
||||
children,
|
||||
htmlContent,
|
||||
className,
|
||||
clickable,
|
||||
delayShow,
|
||||
}) => {
|
||||
return (
|
||||
<div className="tooltip-container">
|
||||
{React.cloneElement(children as React.ReactElement, {
|
||||
"data-tooltip-id": selector,
|
||||
})}
|
||||
<ReactTooltip
|
||||
id={selector}
|
||||
content={content}
|
||||
className={classNames(
|
||||
"!bg-white !text-xs !font-normal !text-gray-700 !shadow-md !opacity-100 z-20",
|
||||
className
|
||||
)}
|
||||
place={position}
|
||||
clickable={clickable}
|
||||
isOpen={disabled ? false : undefined}
|
||||
delayShow={delayShow}
|
||||
>
|
||||
{htmlContent && htmlContent}
|
||||
</ReactTooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TooltipReact;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue