Generic nodes added

This commit is contained in:
Lucas Oliveira 2023-02-14 14:50:18 -03:00
commit 8cdc38a3da
10 changed files with 435 additions and 83 deletions

View file

@ -10,6 +10,7 @@
"dependencies": {
"@headlessui/react": "^1.7.10",
"@heroicons/react": "^2.0.15",
"@tailwindcss/forms": "^0.5.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@ -3503,6 +3504,17 @@
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@tailwindcss/forms": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz",
"integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==",
"dependencies": {
"mini-svg-data-uri": "^1.2.3"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
}
},
"node_modules/@testing-library/dom": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz",
@ -12165,6 +12177,14 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",

View file

@ -5,6 +5,7 @@
"dependencies": {
"@headlessui/react": "^1.7.10",
"@heroicons/react": "^2.0.15",
"@tailwindcss/forms": "^0.5.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",

View file

@ -0,0 +1,77 @@
import {
CommandLineIcon,
ArrowUpRightIcon,
TrashIcon,
PlayIcon,
} from "@heroicons/react/24/outline";
import { Handle, Position } from "reactflow";
import Dropdown from "../../components/dropdownComponent";
import Input from "../../components/inputComponent";
import { nodeColors, nodeIcons } from "../../utils";
export default function GenericNode({ data, onDelete, onRun }) {
const Icon = nodeIcons[data.type];
return (
<div className="prompt-node relative bg-white h-96 w-96 rounded-lg solid border flex flex-col justify-center">
<Handle
type="source"
position={Position.Left}
id="b"
className="bg-gray-400 w-3 h-3 -ml-0.5"
></Handle>
<div className="w-full flex items-center justify-between p-4 bg-gray-50 border-b ">
<div className="flex items-center gap-4 text-lg">
<Icon
className="w-10 h-10 p-1 text-white rounded"
style={{ background: nodeColors[data.type] }}
/>
{data.name}
</div>
<ArrowUpRightIcon className="w-4 h-4" />
</div>
<div className="w-full p-5 h-full">
<div className="w-full text-gray-500 text-sm truncate">
{data.description}
</div>
{data.template.map((t) => (
<div className="w-full mt-5">
{t.type === "dropdown" ? (
<Dropdown
title={t.title}
value={t.options[0]}
options={t.options}
onSelect={() => {}}
/>
) : t.type === "input" ? (
<Input
title={t.title}
placeholder={t.placeholder}
onChange={() => {}}
/>
) : (
<></>
)}
</div>
))}
<div className="w-full mt-5"></div>
</div>
<div className="flex w-full justify-between items-center bg-gray-50 gap-2 border-t text-gray-600 p-4 text-sm">
<button onClick={onDelete}>
<TrashIcon className="w-6 h-6"></TrashIcon>
</button>
<button onClick={onRun}>
<PlayIcon className="w-6 h-6"></PlayIcon>
</button>
</div>
<Handle
type="target"
position={Position.Right}
id="b"
className=" w-3 h-3 -mr-0.5"
style={{ background: nodeColors[data.type] }}
></Handle>
</div>
);
}

View file

@ -2,6 +2,9 @@ import { Handle, Position } from "reactflow";
import { useContext } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { Transition } from "@headlessui/react";
import { ArrowUpRightIcon, CommandLineIcon, PlayIcon, TrashIcon } from "@heroicons/react/24/outline";
import Dropdown from "../../components/dropdownComponent";
import Input from "../../components/inputComponent";
export default function PromptNode({ data }) {
const { openPopUp } = useContext(PopUpContext);
@ -17,19 +20,39 @@ export default function PromptNode({ data }) {
leaveTo="transform opacity-0 scale-95"
>
<div
onClick={() =>
openPopUp(<div className="absolute top-1/2 left-1/2">teste</div>)
}
className="prompt-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"
className="prompt-node relative bg-white h-96 w-96 rounded-lg solid border flex flex-col justify-center"
>
<Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Prompt
</label>
<div className="w-full h-10 truncate bg-slate-50 text-xs">
{data.template}
<Handle type="source"
position={Position.Left}
id="b"
className="bg-gray-400 w-3 h-3 -ml-0.5"></Handle>
<div className="w-full flex items-center justify-between p-4 bg-gray-50 border-b ">
<div className="flex items-center gap-4 text-lg">
<CommandLineIcon className="w-10 h-10 p-1 bg-sky-600 text-white rounded" />
Prompt
</div>
<ArrowUpRightIcon className="w-4 h-4" />
</div>
<Handle type="target" position={Position.Right}></Handle>
<div className="w-full p-5 h-full">
<div className="w-full text-gray-500 text-sm truncate">
{data.template}
</div>
<div className="w-full mt-5">
<Dropdown title="Select item:" value="item" options={["item1", "item2", "item3"]} onSelect={() => {}} />
</div>
<div className="w-full mt-5">
<Input title="Enter text:" placeholder="text" onChange={() => {}} />
</div>
</div>
<div className="flex w-full justify-between items-center bg-gray-50 gap-2 border-t text-gray-600 p-4 text-sm">
<TrashIcon className="w-6 h-6"></TrashIcon>
<PlayIcon className="w-6 h-6"></PlayIcon>
</div>
<Handle type="target"
position={Position.Right}
id="b" className="bg-sky-600 w-3 h-3 -mr-0.5"></Handle>
</div>
</Transition>
);

View file

@ -0,0 +1,81 @@
import { Listbox, Transition } from "@headlessui/react";
import { ChevronUpDownIcon, CheckIcon } from "@heroicons/react/24/outline";
import { Fragment } from "react";
import { classNames } from "../../utils";
export default function Dropdown({title, value, options, onSelect}) {
return (
<>
<Listbox value={value} onChange={onSelect}>
{({ open }) => (
<>
<Listbox.Label className="block text-sm font-medium text-gray-700">
{title}
</Listbox.Label>
<div className="relative mt-1">
<Listbox.Button className="relative w-full cursor-default rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 text-left shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm">
<span className="block truncate">{value}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</span>
</Listbox.Button>
<Transition
show={open}
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{options.map((option, id) => (
<Listbox.Option
key={id}
className={({ active }) =>
classNames(
active ? "text-white bg-indigo-600" : "text-gray-900",
"relative cursor-default select-none py-2 pl-3 pr-9"
)
}
value={option}
>
{({ selected, active }) => (
<>
<span
className={classNames(
selected ? "font-semibold" : "font-normal",
"block truncate"
)}
>
{option}
</span>
{selected ? (
<span
className={classNames(
active ? "text-white" : "text-indigo-600",
"absolute inset-y-0 right-0 flex items-center pr-4"
)}
>
<CheckIcon
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
)}
</Listbox>
</>
);
}

View file

@ -0,0 +1,19 @@
export default function Input({title, placeholder, onChange}){
return (
<>
<div>
<label className="block text-sm font-medium text-gray-700">
{title}
</label>
<div className="mt-1">
<input
type="text"
className="block w-full form-input rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
placeholder={placeholder}
onChange={onChange}
/>
</div>
</div>
</>
);
}

View file

@ -8,41 +8,45 @@ import {
} from "@heroicons/react/24/outline";
import { Disclosure } from "@headlessui/react";
import { useState } from "react";
import { borderLColors } from "../../../../utils";
export default function DisclosureComponent({
button: { title, Icon, Modal = null, buttons = [] },
button: { title, Icon, buttons = [] },
children,
}) {
return (
<Disclosure as="div" key={title}>
{({ open }) => (
<>
<div className="select-none bg-gray-50 w-full flex justify-between items-center -mt-px px-3 py-2 border border-gray-200">
<div className="flex gap-4">
<Icon className="w-6 text-gray-800" />
<span className="flex items-center text-sm text-gray-800 font-medium">
{title}
</span>
</div>
<div className="flex gap-2">
{buttons.map((x, index)=>(
<button key={index} onClick={x.onClick}>
{x.Icon}
</button>
))}
<Disclosure.Button as="button">
<ChevronRightIcon
className={`${
open ? "rotate-90 transform" : ""
} h-5 w-5 text-gray-800`}
/>
</Disclosure.Button>
<div>
<div className="select-none bg-gray-50 w-full flex justify-between items-center -mt-px px-3 py-2 border border-gray-200">
<div className="flex gap-4">
<Icon className="w-6 text-gray-800" />
<span className="flex items-center text-sm text-gray-800 font-medium">
{title}
</span>
</div>
<div className="flex gap-2">
{buttons.map((x, index)=>(
<button key={index} onClick={x.onClick}>
{x.Icon}
</button>
))}
<Disclosure.Button as="button">
<ChevronRightIcon
className={`${
open ? "rotate-90 transform" : ""
} h-5 w-5 text-gray-800`}
/>
</Disclosure.Button>
</div>
</div>
</div>
<Disclosure.Panel as="div" className="-mt-px">
{children}
</Disclosure.Panel>
</>
)}
</Disclosure>
);

View file

@ -1,7 +1,16 @@
import { Bars2Icon, CommandLineIcon, CpuChipIcon, LightBulbIcon, LinkIcon, RocketLaunchIcon, ShieldCheckIcon, ViewColumnsIcon } from "@heroicons/react/24/outline";
import {
Bars2Icon,
CommandLineIcon,
CpuChipIcon,
LightBulbIcon,
LinkIcon,
RocketLaunchIcon,
ShieldCheckIcon,
} from "@heroicons/react/24/outline";
import { llm_chain } from "../../../../data_assets/llm_chain";
import { prompt } from "../../../../data_assets/prompt";
import DisclosureComponent from "../DisclosureComponent";
import { borderLColors, nodeColors } from "../../../../utils";
export function ExtraSidebar() {
function onDragStart(event: React.DragEvent<any>, nodeType) {
@ -31,68 +40,101 @@ export function ExtraSidebar() {
return (
<div className="mt-4">
<DisclosureComponent button={{ title: "Prompts", Icon: CommandLineIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "promptNode")}
>
<span className="text-black">Prompt</span>
<Bars2Icon className="w-6 text-gray-400" />
<DisclosureComponent
button={{ title: "Prompts", Icon: CommandLineIcon }}
>
<div className="p-2">
<div draggable className={" cursor-grab border-l-8 rounded-l-md"} style={{borderLeftColor: nodeColors['prompt']}} onDragStart={(event) => onDragStart(event, "promptNode")}>
<div
className="flex justify-between text-sm p-4 items-center h-12 border-dashed border-gray-400 border-l-0 rounded-md rounded-l-none border-2"
>
<span className="text-black">Prompt</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</div>
</div>
</DisclosureComponent>
<DisclosureComponent button={{ title: "Models", Icon: LightBulbIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "modelNode")}
>
<span className="text-black">Model</span>
<Bars2Icon className="w-6 text-gray-400" />
<DisclosureComponent
button={{ title: "Models", Icon: LightBulbIcon }}
>
<div className="p-2">
<div draggable className={" cursor-grab border-l-8 rounded-l-md"} style={{borderLeftColor: nodeColors['model']}} onDragStart={(event) => onDragStart(event, "promptNode")}>
<div
className="flex justify-between text-sm p-4 items-center h-12 border-dashed border-gray-400 border-l-0 rounded-md rounded-l-none border-2"
>
<span className="text-black">Model</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</div>
</div>
</DisclosureComponent>
<DisclosureComponent button={{ title: "Chains", Icon: LinkIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "chainNode")}
>
<span className="text-black">Chain</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</DisclosureComponent>
<DisclosureComponent button={{ title: "Agents", Icon: RocketLaunchIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "agentNode")}
>
<span className="text-black">Agent</span>
<Bars2Icon className="w-6 text-gray-400" />
<DisclosureComponent
button={{ title: "Agents", Icon: RocketLaunchIcon }}
>
<div className="p-2">
<div draggable className={" cursor-grab border-l-8 rounded-l-md"} style={{borderLeftColor: nodeColors['agent']}} onDragStart={(event) => onDragStart(event, "promptNode")}>
<div
className="flex justify-between text-sm p-4 items-center h-12 border-dashed border-gray-400 border-l-0 rounded-md rounded-l-none border-2"
>
<span className="text-black">Agent</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</div>
</div>
</DisclosureComponent>
<DisclosureComponent
button={{ title: "Validators", Icon: ShieldCheckIcon }}
>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "validatorNode")}
>
<span className="text-black">Validator</span>
<Bars2Icon className="w-6 text-gray-400" />
<div className="p-2">
<div draggable className={" cursor-grab border-l-8 rounded-l-md"} style={{borderLeftColor: nodeColors['validator']}} onDragStart={(event) => onDragStart(event, "promptNode")}>
<div
className="flex justify-between text-sm p-4 items-center h-12 border-dashed border-gray-400 border-l-0 rounded-md rounded-l-none border-2"
>
<span className="text-black">Validator</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</div>
</div>
</DisclosureComponent>
<DisclosureComponent
button={{ title: "Memories", Icon: CpuChipIcon }}
>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "memoryNode")}
>
<span className="text-black">Memory</span>
<Bars2Icon className="w-6 text-gray-400" />
<div className="p-2">
<div draggable className={" cursor-grab border-l-8 rounded-l-md"} style={{borderLeftColor: nodeColors['memory']}} onDragStart={(event) => onDragStart(event, "promptNode")}>
<div
className="flex justify-between text-sm p-4 items-center h-12 border-dashed border-gray-400 border-l-0 rounded-md rounded-l-none border-2"
>
<span className="text-black">Memory</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</div>
</div>
</DisclosureComponent>
<DisclosureComponent
button={{ title: "Chains", Icon: LinkIcon }}
>
<div className="p-2">
<div draggable className={" cursor-grab border-l-8 rounded-l-md"} style={{borderLeftColor: nodeColors['chain']}} onDragStart={(event) => onDragStart(event, "promptNode")}>
<div
className="flex justify-between text-sm p-4 items-center h-12 border-dashed border-gray-400 border-l-0 rounded-md rounded-l-none border-2"
>
<span className="text-black">Chain</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</div>
</div>
</DisclosureComponent>
</div>

View file

@ -1,3 +1,5 @@
import { RocketLaunchIcon, LinkIcon, CpuChipIcon, LightBulbIcon, CommandLineIcon, ShieldCheckIcon } from "@heroicons/react/24/outline";
export function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}
@ -22,8 +24,86 @@ export function classNames(...classes) {
pink: "text-pink-700",
rose: "text-rose-700",
black: "text-black-700",
gray: "bg-gray-700",
gray: "text-gray-700",
};
export const borderLColors = {
white: "border-l-white",
red: "border-l-red-500",
orange: "border-l-orange-500",
amber: "border-l-amber-500",
yellow: "border-l-yellow-500",
lime: "border-l-lime-500",
green: "border-l-green-500",
emerald: "border-l-emerald-500",
teal: "border-l-teal-500",
cyan: "border-l-cyan-500",
sky: "border-l-sky-500",
blue: "border-l-blue-500",
indigo: "border-l-indigo-500",
violet: "border-l-violet-500",
purple: "border-l-purple-500",
fuchsia: "border-l-fuchsia-500",
pink: "border-l-pink-500",
rose: "border-l-rose-500",
black: "border-l-black-500",
gray: "border-l-gray-500",
};
/* export const nodeColors = {
prompt: "#35ADAE",
model: "#4266BE",
chain: "#6344BE",
agent: "#903BBE",
validator: "#DB3392",
memory: "#FF3434",
} */
/* export const nodeColors = {
prompt: "#36D635",
model: "#4266BE",
chain: "#903BBE",
agent: "#FF3434",
validator: "#FEBB35",
memory: "#FFFF33",
} */
/* export const nodeColors = {
prompt: "#36D635",
model: "#35ADAE",
chain: "#903BBE",
agent: "#DB3392",
validator: "#FF9135",
memory: "#FFDC35",
} */
/* export const nodeColors = {
prompt: "#36D635",
model: "#35ADAE",
chain: "#903BBE",
agent: "#DB3392",
validator: "#FF3434",
memory: "#FF9135",
} */
export const nodeColors = {
prompt: "#7C7C7C",
model: "#35ADAE",
chain: "#FFDC35",
agent: "#903BBE",
validator: "#FF3434",
memory: "#FF9135",
}
export const nodeIcons = {
agent: RocketLaunchIcon,
chain: LinkIcon,
memory: CpuChipIcon,
model: LightBulbIcon,
prompt: CommandLineIcon,
validator: ShieldCheckIcon,
}
export const bgColors = {
white: "bg-white",

View file

@ -5,5 +5,10 @@ module.exports = {
theme: {
extend: {},
},
plugins: [],
plugins: [
// ...
require("@tailwindcss/forms")({
strategy: 'class', // only generate classes
}),
],
}