Validation_fix (#317)
This commit is contained in:
commit
0ed4475c6d
4 changed files with 142 additions and 116 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
from importlib.metadata import version
|
|
||||||
import logging
|
import logging
|
||||||
|
from importlib.metadata import version
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,4 +54,4 @@ def post_validate_node(node_id: str, data: dict):
|
||||||
return json.dumps({"valid": True, "params": str(node._built_object_repr())})
|
return json.dumps({"valid": True, "params": str(node._built_object_repr())})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
return json.dumps({"valid": False})
|
return json.dumps({"valid": False, "params": str(e)})
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ import io
|
||||||
from typing import Any, Dict, List, Tuple
|
from typing import Any, Dict, List, Tuple
|
||||||
|
|
||||||
from chromadb.errors import NotEnoughElementsException # type: ignore
|
from chromadb.errors import NotEnoughElementsException # type: ignore
|
||||||
|
from langchain.schema import AgentAction
|
||||||
|
|
||||||
from langflow.api.callback import AsyncStreamingLLMCallbackHandler, StreamingLLMCallbackHandler # type: ignore
|
from langflow.api.callback import AsyncStreamingLLMCallbackHandler, StreamingLLMCallbackHandler # type: ignore
|
||||||
from langflow.cache.base import compute_dict_hash, load_cache, memoize_dict
|
from langflow.cache.base import compute_dict_hash, load_cache, memoize_dict
|
||||||
from langflow.graph.graph import Graph
|
from langflow.graph.graph import Graph
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
from langchain.schema import AgentAction
|
|
||||||
|
|
||||||
|
|
||||||
def load_langchain_object(data_graph, is_first_message=False):
|
def load_langchain_object(data_graph, is_first_message=False):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,12 @@
|
||||||
import { BugAntIcon, Cog6ToothIcon, ExclamationCircleIcon, InformationCircleIcon, TrashIcon } from "@heroicons/react/24/outline";
|
import {
|
||||||
|
BugAntIcon,
|
||||||
|
CheckCircleIcon,
|
||||||
|
Cog6ToothIcon,
|
||||||
|
EllipsisHorizontalCircleIcon,
|
||||||
|
ExclamationCircleIcon,
|
||||||
|
InformationCircleIcon,
|
||||||
|
TrashIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
import { classNames, nodeColors, nodeIcons, toNormalCase } from "../../utils";
|
import { classNames, nodeColors, nodeIcons, toNormalCase } from "../../utils";
|
||||||
import ParameterComponent from "./components/parameterComponent";
|
import ParameterComponent from "./components/parameterComponent";
|
||||||
import { typesContext } from "../../contexts/typesContext";
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
|
|
@ -12,11 +20,11 @@ import { TabsContext } from "../../contexts/tabsContext";
|
||||||
import { debounce } from "../../utils";
|
import { debounce } from "../../utils";
|
||||||
import Tooltip from "../../components/TooltipComponent";
|
import Tooltip from "../../components/TooltipComponent";
|
||||||
export default function GenericNode({
|
export default function GenericNode({
|
||||||
data,
|
data,
|
||||||
selected,
|
selected,
|
||||||
}: {
|
}: {
|
||||||
data: NodeDataType;
|
data: NodeDataType;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
const showError = useRef(true);
|
const showError = useRef(true);
|
||||||
|
|
@ -30,32 +38,28 @@ export default function GenericNode({
|
||||||
const { reactFlowInstance } = useContext(typesContext);
|
const { reactFlowInstance } = useContext(typesContext);
|
||||||
const [params, setParams] = useState([]);
|
const [params, setParams] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (reactFlowInstance) {
|
if (reactFlowInstance) {
|
||||||
setParams(Object.values(reactFlowInstance.toObject()));
|
setParams(Object.values(reactFlowInstance.toObject()));
|
||||||
}
|
}
|
||||||
}, [save]);
|
}, [save]);
|
||||||
|
|
||||||
const validateNode = useCallback(
|
const validateNode = useCallback(
|
||||||
debounce(async () => {
|
debounce(async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/validate/node/${data.id}`, {
|
const response = await fetch(`/validate/node/${data.id}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(reactFlowInstance.toObject()),
|
body: JSON.stringify(reactFlowInstance.toObject()),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
let jsonResponse = await response.json();
|
let jsonResponse = await response.json();
|
||||||
let jsonResponseParsed = await JSON.parse(jsonResponse);
|
let jsonResponseParsed = await JSON.parse(jsonResponse);
|
||||||
console.log(jsonResponseParsed);
|
console.log(jsonResponseParsed);
|
||||||
if(jsonResponseParsed.valid){
|
setValidationStatus(jsonResponseParsed);
|
||||||
setValidationStatus(jsonResponseParsed.params);
|
|
||||||
} else {
|
|
||||||
setValidationStatus("error");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.error("Error validating node:", error);
|
// console.error("Error validating node:", error);
|
||||||
|
|
@ -70,31 +74,22 @@ export default function GenericNode({
|
||||||
}
|
}
|
||||||
}, [params, validateNode]);
|
}, [params, validateNode]);
|
||||||
|
|
||||||
useEffect(() => {
|
if (!Icon) {
|
||||||
if (validationStatus !== "error") {
|
if (showError.current) {
|
||||||
setIsValid(true);
|
setErrorData({
|
||||||
} else {
|
title: data.type
|
||||||
setIsValid(false);
|
? `The ${data.type} node could not be rendered, please review your json file`
|
||||||
|
: "There was a node that can't be rendered, please review your json file",
|
||||||
|
});
|
||||||
|
showError.current = false;
|
||||||
}
|
}
|
||||||
}, [validationStatus]);
|
deleteNode(data.id);
|
||||||
|
return;
|
||||||
if (!Icon) {
|
}
|
||||||
if (showError.current) {
|
|
||||||
setErrorData({
|
|
||||||
title: data.type
|
|
||||||
? `The ${data.type} node could not be rendered, please review your json file`
|
|
||||||
: "There was a node that can't be rendered, please review your json file",
|
|
||||||
});
|
|
||||||
showError.current = false;
|
|
||||||
}
|
|
||||||
deleteNode(data.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
isValid ? "animate-pulse-green" : "border-red-outline",
|
|
||||||
selected ? "border border-blue-500" : "border dark:border-gray-700",
|
selected ? "border border-blue-500" : "border dark:border-gray-700",
|
||||||
"prompt-node relative bg-white dark:bg-gray-900 w-96 rounded-lg flex flex-col justify-center"
|
"prompt-node relative bg-white dark:bg-gray-900 w-96 rounded-lg flex flex-col justify-center"
|
||||||
)}
|
)}
|
||||||
|
|
@ -108,15 +103,46 @@ export default function GenericNode({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="ml-2 truncate">{data.type}</div>
|
<div className="ml-2 truncate">{data.type}</div>
|
||||||
{validationStatus && validationStatus !== "error" ?
|
<div>
|
||||||
<Tooltip title={
|
<Tooltip
|
||||||
<div className="max-h-96 overflow-auto">
|
title={
|
||||||
{validationStatus}
|
!validationStatus ? (
|
||||||
</div>}>
|
"Validating..."
|
||||||
<ExclamationCircleIcon className="w-5 hover:text-gray-500 hover:dark:text-gray-300" />
|
) : (
|
||||||
</Tooltip>
|
<div className="max-h-96 overflow-auto">
|
||||||
: <></>
|
{validationStatus.params}
|
||||||
}
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="relative w-5 h-5">
|
||||||
|
<CheckCircleIcon
|
||||||
|
className={classNames(
|
||||||
|
validationStatus && validationStatus.valid
|
||||||
|
? "text-green-500 opacity-100"
|
||||||
|
: "text-green-500 opacity-0 animate-spin",
|
||||||
|
"absolute w-5 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ExclamationCircleIcon
|
||||||
|
className={classNames(
|
||||||
|
validationStatus && !validationStatus.valid
|
||||||
|
? "text-red-500 opacity-100"
|
||||||
|
: "text-red-500 opacity-0 animate-spin",
|
||||||
|
"w-5 absolute hover:text-gray-500 hover:dark:text-gray-600 transition-all ease-in-out duration-200"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<EllipsisHorizontalCircleIcon
|
||||||
|
className={classNames(
|
||||||
|
!validationStatus
|
||||||
|
? "text-yellow-500 opacity-100"
|
||||||
|
: "text-yellow-500 opacity-0 animate-spin",
|
||||||
|
"w-5 absolute hover:text-gray-500 hover:dark:text-gray-600 transition-all ease-in-out duration-300"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<button
|
<button
|
||||||
|
|
@ -162,12 +188,12 @@ export default function GenericNode({
|
||||||
{data.node.description}
|
{data.node.description}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<>
|
<>
|
||||||
{Object.keys(data.node.template)
|
{Object.keys(data.node.template)
|
||||||
.filter((t) => t.charAt(0) !== "_")
|
.filter((t) => t.charAt(0) !== "_")
|
||||||
.map((t: string, idx) => (
|
.map((t: string, idx) => (
|
||||||
<div key={idx}>
|
<div key={idx}>
|
||||||
{/* {idx === 0 ? (
|
{/* {idx === 0 ? (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"px-5 py-2 mt-2 dark:text-white text-center",
|
"px-5 py-2 mt-2 dark:text-white text-center",
|
||||||
|
|
@ -186,59 +212,59 @@ export default function GenericNode({
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)} */}
|
)} */}
|
||||||
{data.node.template[t].show &&
|
{data.node.template[t].show &&
|
||||||
!data.node.template[t].advanced ? (
|
!data.node.template[t].advanced ? (
|
||||||
<ParameterComponent
|
<ParameterComponent
|
||||||
data={data}
|
data={data}
|
||||||
color={
|
color={
|
||||||
nodeColors[types[data.node.template[t].type]] ??
|
nodeColors[types[data.node.template[t].type]] ??
|
||||||
nodeColors.unknown
|
nodeColors.unknown
|
||||||
}
|
}
|
||||||
title={
|
title={
|
||||||
data.node.template[t].display_name
|
data.node.template[t].display_name
|
||||||
? data.node.template[t].display_name
|
? data.node.template[t].display_name
|
||||||
: data.node.template[t].name
|
: data.node.template[t].name
|
||||||
? toNormalCase(data.node.template[t].name)
|
? toNormalCase(data.node.template[t].name)
|
||||||
: toNormalCase(t)
|
: toNormalCase(t)
|
||||||
}
|
}
|
||||||
name={t}
|
name={t}
|
||||||
tooltipTitle={
|
tooltipTitle={
|
||||||
"Type: " +
|
"Type: " +
|
||||||
data.node.template[t].type +
|
data.node.template[t].type +
|
||||||
(data.node.template[t].list ? " list" : "")
|
(data.node.template[t].list ? " list" : "")
|
||||||
}
|
}
|
||||||
required={data.node.template[t].required}
|
required={data.node.template[t].required}
|
||||||
id={data.node.template[t].type + "|" + t + "|" + data.id}
|
id={data.node.template[t].type + "|" + t + "|" + data.id}
|
||||||
left={true}
|
left={true}
|
||||||
type={data.node.template[t].type}
|
type={data.node.template[t].type}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
Object.keys(data.node.template).length < 1 ? "hidden" : "",
|
Object.keys(data.node.template).length < 1 ? "hidden" : "",
|
||||||
"w-full flex justify-center"
|
"w-full flex justify-center"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="px-5 py-2 mt-2 dark:text-white text-center">
|
{/* <div className="px-5 py-2 mt-2 dark:text-white text-center">
|
||||||
Output
|
Output
|
||||||
</div> */}
|
</div> */}
|
||||||
<ParameterComponent
|
<ParameterComponent
|
||||||
data={data}
|
data={data}
|
||||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||||
title={data.type}
|
title={data.type}
|
||||||
tooltipTitle={`Type: ${data.node.base_classes.join(" | ")}`}
|
tooltipTitle={`Type: ${data.node.base_classes.join(" | ")}`}
|
||||||
id={[data.type, data.id, ...data.node.base_classes].join("|")}
|
id={[data.type, data.id, ...data.node.base_classes].join("|")}
|
||||||
type={data.node.base_classes.join("|")}
|
type={data.node.base_classes.join("|")}
|
||||||
left={false}
|
left={false}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue