Node modal (#174)
This commit is contained in:
commit
5489717dab
17 changed files with 692 additions and 333 deletions
|
|
@ -15,6 +15,11 @@ CUSTOM_NODES = {
|
|||
"utilities": {
|
||||
"SQLDatabase": nodes.SQLDatabaseNode(),
|
||||
},
|
||||
"chains": {
|
||||
"SeriesCharacterChain": nodes.SeriesCharacterChainNode(),
|
||||
"TimeTravelGuideChain": nodes.TimeTravelGuideChainNode(),
|
||||
"MidJourneyPromptChain": nodes.MidJourneyPromptChainNode(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class TemplateFieldCreator(BaseModel, ABC):
|
|||
options: list[str] = []
|
||||
name: str = ""
|
||||
display_name: Optional[str] = None
|
||||
advanced: bool = True
|
||||
|
||||
def to_dict(self):
|
||||
result = self.dict()
|
||||
|
|
@ -232,3 +233,12 @@ class FrontendNode(BaseModel):
|
|||
# other conditions are to make sure that it is not an input or output variable
|
||||
if "api" in key.lower() and "key" in key.lower():
|
||||
field.required = False
|
||||
|
||||
if "kwargs" in field.name.lower():
|
||||
field.advanced = True
|
||||
field.required = False
|
||||
field.show = False
|
||||
# If the field.name contains api or api and key, then it might be an api key
|
||||
# other conditions are to make sure that it is not an input or output variable
|
||||
if "api" in key.lower() and "key" in key.lower():
|
||||
field.required = False
|
||||
|
|
|
|||
|
|
@ -101,6 +101,107 @@ class PythonFunctionNode(FrontendNode):
|
|||
return super().to_dict()
|
||||
|
||||
|
||||
class MidJourneyPromptChainNode(FrontendNode):
|
||||
name: str = "MidJourneyPromptChain"
|
||||
template: Template = Template(
|
||||
type_name="MidJourneyPromptChain",
|
||||
fields=[
|
||||
TemplateField(
|
||||
field_type="BaseLanguageModel",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
advanced=False,
|
||||
multiline=False,
|
||||
name="llm",
|
||||
),
|
||||
],
|
||||
)
|
||||
description: str = "MidJourneyPromptChain is a chain you can use to generate new MidJourney prompts."
|
||||
base_classes: list[str] = [
|
||||
"LLMChain",
|
||||
"BaseCustomChain",
|
||||
"Chain",
|
||||
"ConversationChain",
|
||||
"MidJourneyPromptChain",
|
||||
]
|
||||
|
||||
|
||||
class TimeTravelGuideChainNode(FrontendNode):
|
||||
name: str = "TimeTravelGuideChain"
|
||||
template: Template = Template(
|
||||
type_name="TimeTravelGuideChain",
|
||||
fields=[
|
||||
TemplateField(
|
||||
field_type="BaseLanguageModel",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
advanced=False,
|
||||
multiline=False,
|
||||
name="llm",
|
||||
),
|
||||
],
|
||||
)
|
||||
description: str = "Time travel guide chain to be used in the flow."
|
||||
base_classes: list[str] = [
|
||||
"LLMChain",
|
||||
"BaseCustomChain",
|
||||
"TimeTravelGuideChain",
|
||||
"Chain",
|
||||
"ConversationChain",
|
||||
]
|
||||
|
||||
|
||||
class SeriesCharacterChainNode(FrontendNode):
|
||||
name: str = "SeriesCharacterChain"
|
||||
template: Template = Template(
|
||||
type_name="SeriesCharacterChain",
|
||||
fields=[
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
advanced=False,
|
||||
multiline=False,
|
||||
name="character",
|
||||
),
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
advanced=False,
|
||||
multiline=False,
|
||||
name="series",
|
||||
),
|
||||
TemplateField(
|
||||
field_type="BaseLanguageModel",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
advanced=False,
|
||||
multiline=False,
|
||||
name="llm",
|
||||
),
|
||||
],
|
||||
)
|
||||
description: str = "SeriesCharacterChain is a chain you can use to have a conversation with a character from a series." # noqa
|
||||
base_classes: list[str] = [
|
||||
"LLMChain",
|
||||
"BaseCustomChain",
|
||||
"Chain",
|
||||
"ConversationChain",
|
||||
"SeriesCharacterChain",
|
||||
]
|
||||
|
||||
|
||||
class ToolNode(FrontendNode):
|
||||
name: str = "Tool"
|
||||
template: Template = Template(
|
||||
|
|
@ -418,17 +519,29 @@ class ChainFrontendNode(FrontendNode):
|
|||
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
||||
FrontendNode.format_field(field, name)
|
||||
|
||||
field.advanced = False
|
||||
if "key" in field.name:
|
||||
field.password = False
|
||||
field.show = False
|
||||
if field.name in ["input_key", "output_key"]:
|
||||
field.required = True
|
||||
field.show = True
|
||||
field.advanced = True
|
||||
|
||||
# Separated for possible future changes
|
||||
if field.name == "prompt":
|
||||
# if no prompt is provided, use the default prompt
|
||||
field.required = False
|
||||
field.show = True
|
||||
field.advanced = False
|
||||
if field.name == "memory":
|
||||
field.required = False
|
||||
field.show = True
|
||||
field.advanced = False
|
||||
if field.name == "verbose":
|
||||
field.required = False
|
||||
field.show = True
|
||||
field.advanced = True
|
||||
|
||||
|
||||
class LLMFrontendNode(FrontendNode):
|
||||
|
|
@ -438,7 +551,7 @@ class LLMFrontendNode(FrontendNode):
|
|||
"huggingfacehub_api_token": "HuggingFace Hub API Token",
|
||||
}
|
||||
FrontendNode.format_field(field, name)
|
||||
SHOW_FIELDS = ["repo_id", "task", "model_kwargs"]
|
||||
SHOW_FIELDS = ["repo_id"]
|
||||
if field.name in SHOW_FIELDS:
|
||||
field.show = True
|
||||
|
||||
|
|
@ -448,14 +561,21 @@ class LLMFrontendNode(FrontendNode):
|
|||
# Required should be False to support
|
||||
# loading the API key from environment variables
|
||||
field.required = False
|
||||
field.advanced = False
|
||||
|
||||
if field.name == "task":
|
||||
field.required = True
|
||||
field.show = True
|
||||
field.is_list = True
|
||||
field.options = ["text-generation", "text2text-generation"]
|
||||
field.advanced = True
|
||||
|
||||
if display_name := display_names_dict.get(field.name):
|
||||
field.display_name = display_name
|
||||
if field.name == "model_kwargs":
|
||||
field.field_type = "code"
|
||||
field.advanced = True
|
||||
field.show = True
|
||||
elif field.name in ["model_name", "temperature"]:
|
||||
field.advanced = False
|
||||
field.show = True
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { TrashIcon } from "@heroicons/react/24/outline";
|
||||
import { Cog6ToothIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
import {
|
||||
classNames,
|
||||
nodeColors,
|
||||
|
|
@ -10,6 +10,8 @@ import { typesContext } from "../../contexts/typesContext";
|
|||
import { useContext, useRef } from "react";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import NodeModal from "../../modals/NodeModal";
|
||||
|
||||
export default function GenericNode({
|
||||
data,
|
||||
|
|
@ -21,6 +23,7 @@ export default function GenericNode({
|
|||
const { setErrorData } = useContext(alertContext);
|
||||
const showError = useRef(true);
|
||||
const { types, deleteNode } = useContext(typesContext);
|
||||
const { openPopUp } = useContext(PopUpContext);
|
||||
const Icon = nodeIcons[types[data.type]];
|
||||
if (!Icon) {
|
||||
if (showError.current) {
|
||||
|
|
@ -51,17 +54,46 @@ export default function GenericNode({
|
|||
/>
|
||||
<div className="truncate">{data.type}</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
deleteNode(data.id);
|
||||
}}
|
||||
>
|
||||
<TrashIcon className="w-6 h-6 hover:text-red-500 dark:text-gray-500 dark:hover:text-red-500"></TrashIcon>
|
||||
</button>
|
||||
<div className="flex gap-3">
|
||||
<button
|
||||
className="relative"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
openPopUp(<NodeModal data={data} />);
|
||||
}}
|
||||
>
|
||||
<div className=" absolute text-red-600 -top-2 -right-1">
|
||||
{Object.keys(data.node.template).some(
|
||||
(t) =>
|
||||
data.node.template[t].advanced &&
|
||||
data.node.template[t].required
|
||||
)
|
||||
? " *"
|
||||
: ""}
|
||||
</div>
|
||||
<Cog6ToothIcon
|
||||
className={classNames(
|
||||
Object.keys(data.node.template).some(
|
||||
(t) => data.node.template[t].advanced && data.node.template[t].show
|
||||
)
|
||||
? ""
|
||||
: "hidden",
|
||||
"w-6 h-6 dark:text-gray-500 hover:animate-spin"
|
||||
)}
|
||||
></Cog6ToothIcon>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
deleteNode(data.id);
|
||||
}}
|
||||
>
|
||||
<TrashIcon className="w-6 h-6 hover:text-red-500 dark:text-gray-500 dark:hover:text-red-500"></TrashIcon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full h-full py-5">
|
||||
<div className="w-full text-gray-500 px-5 text-sm">
|
||||
<div className="w-full text-gray-500 px-5 pb-3 text-sm">
|
||||
{data.node.description}
|
||||
</div>
|
||||
|
||||
|
|
@ -70,7 +102,7 @@ export default function GenericNode({
|
|||
.filter((t) => t.charAt(0) !== "_")
|
||||
.map((t: string, idx) => (
|
||||
<div key={idx}>
|
||||
{idx === 0 ? (
|
||||
{/* {idx === 0 ? (
|
||||
<div
|
||||
className={classNames(
|
||||
"px-5 py-2 mt-2 dark:text-white text-center",
|
||||
|
|
@ -86,8 +118,8 @@ export default function GenericNode({
|
|||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{data.node.template[t].show ? (
|
||||
)} */}
|
||||
{data.node.template[t].show && !data.node.template[t].advanced ? (
|
||||
<ParameterComponent
|
||||
data={data}
|
||||
color={
|
||||
|
|
@ -117,9 +149,17 @@ export default function GenericNode({
|
|||
)}
|
||||
</div>
|
||||
))}
|
||||
<div className="px-5 py-2 mt-2 dark:text-white text-center">
|
||||
Output
|
||||
<div
|
||||
className={classNames(
|
||||
Object.keys(data.node.template).length < 1 ? "hidden" : "",
|
||||
"w-full flex justify-center"
|
||||
)}
|
||||
>
|
||||
{" "}
|
||||
</div>
|
||||
{/* <div className="px-5 py-2 mt-2 dark:text-white text-center">
|
||||
Output
|
||||
</div> */}
|
||||
<ParameterComponent
|
||||
data={data}
|
||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
|
|||
return Object.keys(template).reduce(
|
||||
(errors: Array<string>, t) =>
|
||||
errors.concat(
|
||||
(template[t].required && template[t].show) &&
|
||||
(!template[t].value || template[t].value === "") &&
|
||||
(template[t].required) &&
|
||||
(template[t].value===undefined || template[t].value === "") &&
|
||||
!reactFlowInstance
|
||||
.getEdges()
|
||||
.some(
|
||||
|
|
|
|||
|
|
@ -19,9 +19,24 @@ export default function CodeAreaComponent({
|
|||
}
|
||||
}, [disabled, onChange]);
|
||||
return (
|
||||
<div className={disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"}>
|
||||
<div
|
||||
className={
|
||||
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
|
||||
}
|
||||
>
|
||||
<div className="w-full flex items-center gap-3">
|
||||
<span
|
||||
onClick={() => {
|
||||
openPopUp(
|
||||
<CodeAreaModal
|
||||
value={myValue}
|
||||
setValue={(t: string) => {
|
||||
setMyValue(t);
|
||||
onChange(t);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
className={
|
||||
"truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
||||
(disabled ? " bg-gray-200" : "")
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ export default function InputFileComponent({
|
|||
>
|
||||
<div className="w-full flex items-center gap-3">
|
||||
<span
|
||||
onClick={handleButtonClick}
|
||||
className={
|
||||
"truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
||||
(disabled ? " bg-gray-200" : "")
|
||||
|
|
|
|||
|
|
@ -6,30 +6,61 @@ import TextAreaModal from "../../modals/textAreaModal";
|
|||
import { TextAreaComponentType } from "../../types/components";
|
||||
import PromptAreaModal from "../../modals/promptModal";
|
||||
|
||||
export default function PromptAreaComponent({ value, onChange, disabled }:TextAreaComponentType) {
|
||||
const [myValue, setMyValue] = useState(value);
|
||||
const { openPopUp } = useContext(PopUpContext);
|
||||
useEffect(() => {
|
||||
if (disabled) {
|
||||
setMyValue("");
|
||||
onChange("");
|
||||
}
|
||||
}, [disabled, onChange]);
|
||||
return (
|
||||
<div className={disabled ? "pointer-events-none cursor-not-allowed w-full" : " w-full"}>
|
||||
<div className="w-full flex items-center gap-3">
|
||||
<span
|
||||
className={
|
||||
"truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
||||
(disabled ? " bg-gray-200" : "")
|
||||
}
|
||||
>
|
||||
{myValue !== "" ? myValue : 'Text empty'}
|
||||
</span>
|
||||
<button onClick={()=>{openPopUp(<PromptAreaModal value={myValue} setValue={(t:string) => {setMyValue(t); onChange(t);}}/>)}}>
|
||||
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-blue-600" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
export default function PromptAreaComponent({
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
}: TextAreaComponentType) {
|
||||
const [myValue, setMyValue] = useState(value);
|
||||
const { openPopUp } = useContext(PopUpContext);
|
||||
useEffect(() => {
|
||||
if (disabled) {
|
||||
setMyValue("");
|
||||
onChange("");
|
||||
}
|
||||
}, [disabled, onChange]);
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
disabled ? "pointer-events-none cursor-not-allowed w-full" : " w-full"
|
||||
}
|
||||
>
|
||||
<div className="w-full flex items-center gap-3">
|
||||
<span
|
||||
onClick={() => {
|
||||
openPopUp(
|
||||
<PromptAreaModal
|
||||
value={myValue}
|
||||
setValue={(t: string) => {
|
||||
setMyValue(t);
|
||||
onChange(t);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
className={
|
||||
"truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
||||
(disabled ? " bg-gray-200" : "")
|
||||
}
|
||||
>
|
||||
{myValue !== "" ? myValue : "Text empty"}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => {
|
||||
openPopUp(
|
||||
<PromptAreaModal
|
||||
value={myValue}
|
||||
setValue={(t: string) => {
|
||||
setMyValue(t);
|
||||
onChange(t);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-blue-600" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import CodeAreaModal from "../../modals/codeAreaModal";
|
||||
import TextAreaModal from "../../modals/textAreaModal";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
|
||||
|
|
@ -17,7 +16,7 @@ export default function TextAreaComponent({ value, onChange, disabled }:TextArea
|
|||
return (
|
||||
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
|
||||
<div className="w-full flex items-center gap-3">
|
||||
<span
|
||||
<span onClick={()=>{openPopUp(<TextAreaModal value={myValue} setValue={(t:string) => {setMyValue(t); onChange(t);}}/>)}}
|
||||
className={
|
||||
"truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
||||
(disabled ? " bg-gray-200" : "")
|
||||
|
|
|
|||
|
|
@ -12,15 +12,13 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
|
|||
<>
|
||||
<DarkProvider>
|
||||
<LocationProvider>
|
||||
<AlertProvider>
|
||||
<TabsProvider>
|
||||
<PopUpProvider>
|
||||
<TypesProvider>
|
||||
{children}
|
||||
</TypesProvider>
|
||||
</PopUpProvider>
|
||||
</TabsProvider>
|
||||
</AlertProvider>
|
||||
<TypesProvider>
|
||||
<AlertProvider>
|
||||
<TabsProvider>
|
||||
<PopUpProvider>{children}</PopUpProvider>
|
||||
</TabsProvider>
|
||||
</AlertProvider>
|
||||
</TypesProvider>
|
||||
</LocationProvider>
|
||||
</DarkProvider>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
import { createContext } from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
//context to set JSX element on the DOM
|
||||
// context to set JSX element on the DOM
|
||||
export const PopUpContext = createContext({
|
||||
openPopUp: (popUpElement: JSX.Element) => {},
|
||||
closePopUp: () => {},
|
||||
closePopUp: () => {},
|
||||
});
|
||||
|
||||
interface PopUpProviderProps {
|
||||
children: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const PopUpProvider = ({ children }: PopUpProviderProps) => {
|
||||
const [popUpElement, setPopUpElement] = useState<JSX.Element | null>(null);
|
||||
const [popUpElements, setPopUpElements] = useState<JSX.Element[]>([]);
|
||||
|
||||
const openPopUp = (element: JSX.Element) => {
|
||||
setPopUpElement(element);
|
||||
};
|
||||
const openPopUp = (element: JSX.Element) => {
|
||||
setPopUpElements(prevPopUps => [element, ...prevPopUps]);
|
||||
};
|
||||
|
||||
const closePopUp = () => {
|
||||
setPopUpElement(null);
|
||||
};
|
||||
const closePopUp = () => {
|
||||
setPopUpElements(prevPopUps => prevPopUps.slice(1));
|
||||
};
|
||||
|
||||
return (
|
||||
<PopUpContext.Provider value={{ openPopUp, closePopUp }}>
|
||||
{children}
|
||||
{popUpElement}
|
||||
</PopUpContext.Provider>
|
||||
);
|
||||
return (
|
||||
<PopUpContext.Provider value={{ openPopUp, closePopUp }}>
|
||||
{children}
|
||||
{popUpElements[0]}
|
||||
</PopUpContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default PopUpProvider;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,166 @@
|
|||
import { useContext, useState } from "react";
|
||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import Dropdown from "../../../../components/dropdownComponent";
|
||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
import ToggleComponent from "../../../../components/toggleComponent";
|
||||
import FloatComponent from "../../../../components/floatComponent";
|
||||
import IntComponent from "../../../../components/intComponent";
|
||||
import InputFileComponent from "../../../../components/inputFileComponent";
|
||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import { classNames } from "../../../../utils";
|
||||
|
||||
export default function ModalField({ data, title, required, id, name, type }) {
|
||||
const { save } = useContext(TabsContext);
|
||||
const [enabled, setEnabled] = useState(
|
||||
data.node.template[name]?.value ?? false
|
||||
);
|
||||
const display =
|
||||
type === "str" ||
|
||||
type === "int" ||
|
||||
type === "prompt" ||
|
||||
type === "bool" ||
|
||||
type === "float" ||
|
||||
type === "file" ||
|
||||
type === "code";
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"flex flex-row w-full items-center justify-between",
|
||||
display ? "" : "hidden"
|
||||
)}
|
||||
>
|
||||
{display && (
|
||||
<div>
|
||||
<span className="mx-2">{title}</span>
|
||||
<span className="text-red-600">{required ? " *" : ""}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{type === "str" && !data.node.template[name].options ? (
|
||||
<div className="w-1/2">
|
||||
{data.node.template[name].list ? (
|
||||
<InputListComponent
|
||||
disabled={false}
|
||||
value={
|
||||
!data.node.template[name].value ||
|
||||
data.node.template[name].value === ""
|
||||
? [""]
|
||||
: data.node.template[name].value
|
||||
}
|
||||
onChange={(t: string[]) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
) : data.node.template[name].multiline ? (
|
||||
<TextAreaComponent
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t: string) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<InputComponent
|
||||
disabled={false}
|
||||
password={data.node.template[name].password ?? false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : type === "bool" ? (
|
||||
<div className="ml-auto">
|
||||
{" "}
|
||||
<ToggleComponent
|
||||
disabled={false}
|
||||
enabled={enabled}
|
||||
setEnabled={(t) => {
|
||||
data.node.template[name].value = t;
|
||||
setEnabled(t);
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : type === "float" ? (
|
||||
<div className="w-1/2">
|
||||
<FloatComponent
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : type === "str" && data.node.template[name].options ? (
|
||||
<div className="w-1/2">
|
||||
<Dropdown
|
||||
options={data.node.template[name].options}
|
||||
onSelect={(newValue) => (data.node.template[name].value = newValue)}
|
||||
value={data.node.template[name].value ?? "Choose an option"}
|
||||
></Dropdown>
|
||||
</div>
|
||||
) : type === "int" ? (
|
||||
<div className="w-1/2">
|
||||
<IntComponent
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : type === "file" ? (
|
||||
<div className="w-1/2">
|
||||
<InputFileComponent
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t: string) => {
|
||||
data.node.template[name].value = t;
|
||||
}}
|
||||
fileTypes={data.node.template[name].fileTypes}
|
||||
suffixes={data.node.template[name].suffixes}
|
||||
onFileChange={(t: string) => {
|
||||
data.node.template[name].content = t;
|
||||
save();
|
||||
}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
) : type === "prompt" ? (
|
||||
<div className="w-1/2">
|
||||
<PromptAreaComponent
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t: string) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : type === "code" ? (
|
||||
<div className="w-1/2">
|
||||
<CodeAreaComponent
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={(t: string) => {
|
||||
data.node.template[name].value = t;
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="hidden"></div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
144
src/frontend/src/modals/NodeModal/index.tsx
Normal file
144
src/frontend/src/modals/NodeModal/index.tsx
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { nodeColors, nodeIcons, snakeToNormalCase } from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import ModalField from "./components/ModalField";
|
||||
|
||||
export default function NodeModal({ data }: { data: NodeDataType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
const { closePopUp } = useContext(PopUpContext);
|
||||
const { types } = useContext(typesContext);
|
||||
const ref = useRef();
|
||||
function setModalOpen(x: boolean) {
|
||||
setOpen(x);
|
||||
if (x === false) {
|
||||
setTimeout(() => {
|
||||
closePopUp();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
const Icon = nodeIcons[types[data.type]];
|
||||
return (
|
||||
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||
<Dialog
|
||||
as="div"
|
||||
className="relative z-10"
|
||||
onClose={setModalOpen}
|
||||
initialFocus={ref}
|
||||
>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-gray-500 dark:bg-gray-600 dark:bg-opacity-75 bg-opacity-75 transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div className="flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative flex flex-col justify-between transform h-[600px] overflow-hidden rounded-lg bg-white dark:bg-gray-800 text-left shadow-xl transition-all sm:my-8 w-[700px]">
|
||||
<div className=" z-50 absolute top-0 right-0 hidden pt-4 pr-4 sm:block">
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Close</span>
|
||||
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="h-full w-full flex flex-col justify-center items-center">
|
||||
<div className="flex w-full pb-4 z-10 justify-center shadow-sm">
|
||||
<Icon
|
||||
className="w-10 mt-4 h-10 p-1 rounded"
|
||||
style={{
|
||||
color:
|
||||
nodeColors[types[data.type]] ?? nodeColors.unknown,
|
||||
}}
|
||||
/>
|
||||
<div className="mt-4 text-center sm:ml-4 sm:text-left">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
|
||||
>
|
||||
{data.type}
|
||||
</Dialog.Title>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-full w-full bg-gray-200 dark:bg-gray-900 p-4 gap-4 flex flex-row justify-center items-center">
|
||||
<div className="flex h-full w-full">
|
||||
<div className="overflow-hidden px-4 sm:p-4 w-full rounded-lg bg-white dark:bg-gray-800 shadow">
|
||||
<div className="flex flex-col h-full gap-5">
|
||||
{
|
||||
Object.keys(data.node.template)
|
||||
.filter((t) => t.charAt(0) !== "_"&& data.node.template[t].advanced && data.node.template[t].show)
|
||||
.map((t: string, idx) => {
|
||||
return (
|
||||
<ModalField
|
||||
key={idx}
|
||||
data={data}
|
||||
title={
|
||||
data.node.template[t].display_name
|
||||
? data.node.template[t].display_name
|
||||
: data.node.template[t].name
|
||||
? snakeToNormalCase(
|
||||
data.node.template[t].name
|
||||
)
|
||||
: snakeToNormalCase(t)
|
||||
}
|
||||
required={data.node.template[t].required}
|
||||
id={
|
||||
data.node.template[t].type +
|
||||
"|" +
|
||||
t +
|
||||
"|" +
|
||||
data.id
|
||||
}
|
||||
name={t}
|
||||
type={data.node.template[t].type}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-gray-200 dark:bg-gray-900 w-full pb-3 flex flex-row-reverse px-4">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
>
|
||||
Done
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
);
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ def test_zero_shot_agent(client: TestClient):
|
|||
"name": "llm_chain",
|
||||
"type": "LLMChain",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["allowed_tools"] == {
|
||||
"required": False,
|
||||
|
|
@ -46,6 +47,7 @@ def test_zero_shot_agent(client: TestClient):
|
|||
"name": "allowed_tools",
|
||||
"type": "Tool",
|
||||
"list": True,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -68,6 +70,7 @@ def test_json_agent(client: TestClient):
|
|||
"name": "toolkit",
|
||||
"type": "BaseToolkit",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -78,6 +81,7 @@ def test_json_agent(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -104,6 +108,7 @@ def test_csv_agent(client: TestClient):
|
|||
"type": "file",
|
||||
"list": False,
|
||||
"content": None,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -114,6 +119,7 @@ def test_csv_agent(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -143,6 +149,7 @@ def test_initialize_agent(client: TestClient):
|
|||
"name": "agent",
|
||||
"type": "str",
|
||||
"list": True,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["memory"] == {
|
||||
"required": False,
|
||||
|
|
@ -153,6 +160,7 @@ def test_initialize_agent(client: TestClient):
|
|||
"name": "memory",
|
||||
"type": "BaseChatMemory",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["tools"] == {
|
||||
"required": False,
|
||||
|
|
@ -163,6 +171,7 @@ def test_initialize_agent(client: TestClient):
|
|||
"name": "tools",
|
||||
"type": "Tool",
|
||||
"list": True,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -173,4 +182,5 @@ def test_initialize_agent(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,16 +31,18 @@ def test_conversation_chain(client: TestClient):
|
|||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -51,6 +53,7 @@ def test_conversation_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -62,6 +65,7 @@ def test_conversation_chain(client: TestClient):
|
|||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -73,6 +77,7 @@ def test_conversation_chain(client: TestClient):
|
|||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["_type"] == "ConversationChain"
|
||||
|
||||
|
|
@ -102,17 +107,19 @@ def test_llm_chain(client: TestClient):
|
|||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -123,6 +130,7 @@ def test_llm_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -134,6 +142,7 @@ def test_llm_chain(client: TestClient):
|
|||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -156,17 +165,19 @@ def test_llm_checker_chain(client: TestClient):
|
|||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -177,6 +188,7 @@ def test_llm_checker_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLLM",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -188,6 +200,7 @@ def test_llm_checker_chain(client: TestClient):
|
|||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -199,6 +212,7 @@ def test_llm_checker_chain(client: TestClient):
|
|||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["_type"] == "LLMCheckerChain"
|
||||
|
||||
|
|
@ -228,17 +242,19 @@ def test_llm_math_chain(client: TestClient):
|
|||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
|
|
@ -249,6 +265,7 @@ def test_llm_math_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -260,6 +277,7 @@ def test_llm_math_chain(client: TestClient):
|
|||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
|
|
@ -271,6 +289,7 @@ def test_llm_math_chain(client: TestClient):
|
|||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["_type"] == "LLMMathChain"
|
||||
|
||||
|
|
@ -298,35 +317,7 @@ def test_series_character_chain(client: TestClient):
|
|||
"SeriesCharacterChain",
|
||||
}
|
||||
template = chain["template"]
|
||||
assert template["memory"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": {
|
||||
"chat_memory": {"messages": []},
|
||||
"output_key": None,
|
||||
"input_key": None,
|
||||
"return_messages": False,
|
||||
"human_prefix": "Human",
|
||||
"ai_prefix": "AI",
|
||||
"memory_key": "history",
|
||||
},
|
||||
"password": False,
|
||||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
}
|
||||
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
|
|
@ -336,50 +327,7 @@ def test_series_character_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
}
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "input",
|
||||
"password": False,
|
||||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "response",
|
||||
"password": False,
|
||||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["template"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": True,
|
||||
"value": "I want you to act like {character} from {series}.\nI want you to respond and answer like {character}. do not write any explanations. only answer like {character}.\nYou must know all of the knowledge of {character}.\nCurrent conversation:\n{history}\nHuman: {input}\n{character}:", # noqa: E501
|
||||
"password": False,
|
||||
"name": "template",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["ai_prefix_value"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"value": "character",
|
||||
"password": False,
|
||||
"name": "ai_prefix_value",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["character"] == {
|
||||
"required": True,
|
||||
|
|
@ -390,6 +338,7 @@ def test_series_character_chain(client: TestClient):
|
|||
"name": "character",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["series"] == {
|
||||
"required": True,
|
||||
|
|
@ -400,6 +349,7 @@ def test_series_character_chain(client: TestClient):
|
|||
"name": "series",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["_type"] == "SeriesCharacterChain"
|
||||
|
||||
|
|
@ -429,55 +379,7 @@ def test_mid_journey_prompt_chain(client: TestClient):
|
|||
|
||||
# Test the template object
|
||||
template = chain["template"]
|
||||
assert template["memory"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": {
|
||||
"chat_memory": {"messages": []},
|
||||
"output_key": None,
|
||||
"input_key": None,
|
||||
"return_messages": False,
|
||||
"human_prefix": "Human",
|
||||
"ai_prefix": "AI",
|
||||
"memory_key": "history",
|
||||
},
|
||||
"password": False,
|
||||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
}
|
||||
# Continue with other template object assertions
|
||||
assert template["prompt"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": {
|
||||
"input_variables": ["history", "input"],
|
||||
"output_parser": None,
|
||||
"partial_variables": {},
|
||||
"template": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n\nCurrent conversation:\n{history}\nHuman: {input}\nAI:", # noqa: E501
|
||||
"template_format": "f-string",
|
||||
"validate_template": True,
|
||||
"_type": "prompt",
|
||||
},
|
||||
"password": False,
|
||||
"name": "prompt",
|
||||
"type": "BasePromptTemplate",
|
||||
"list": False,
|
||||
}
|
||||
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
|
|
@ -487,49 +389,7 @@ def test_mid_journey_prompt_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "response",
|
||||
"password": False,
|
||||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "input",
|
||||
"password": False,
|
||||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["template"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": True,
|
||||
"value": 'I want you to act as a prompt generator for Midjourney\'s artificial intelligence program.\n Your job is to provide detailed and creative descriptions that will inspire unique and interesting images from the AI.\n Keep in mind that the AI is capable of understanding a wide range of language and can interpret abstract concepts, so feel free to be as imaginative and descriptive as possible.\n For example, you could describe a scene from a futuristic city, or a surreal landscape filled with strange creatures.\n The more detailed and imaginative your description, the more interesting the resulting image will be. Here is your first prompt:\n "A field of wildflowers stretches out as far as the eye can see, each one a different color and shape. In the distance, a massive tree towers over the landscape, its branches reaching up to the sky like tentacles."\n\n Current conversation:\n {history}\n Human: {input}\n AI:', # noqa: E501
|
||||
"password": False,
|
||||
"name": "template",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["ai_prefix_value"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "ai_prefix_value",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
# Test the description object
|
||||
assert (
|
||||
|
|
@ -557,55 +417,7 @@ def test_time_travel_guide_chain(client: TestClient):
|
|||
|
||||
# Test the template object
|
||||
template = chain["template"]
|
||||
assert template["memory"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": {
|
||||
"chat_memory": {"messages": []},
|
||||
"output_key": None,
|
||||
"input_key": None,
|
||||
"return_messages": False,
|
||||
"human_prefix": "Human",
|
||||
"ai_prefix": "AI",
|
||||
"memory_key": "history",
|
||||
},
|
||||
"password": False,
|
||||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
}
|
||||
|
||||
assert template["prompt"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": {
|
||||
"input_variables": ["history", "input"],
|
||||
"output_parser": None,
|
||||
"partial_variables": {},
|
||||
"template": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n\nCurrent conversation:\n{history}\nHuman: {input}\nAI:", # noqa: E501
|
||||
"template_format": "f-string",
|
||||
"validate_template": True,
|
||||
"_type": "prompt",
|
||||
},
|
||||
"password": False,
|
||||
"name": "prompt",
|
||||
"type": "BasePromptTemplate",
|
||||
"list": False,
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
|
|
@ -615,50 +427,7 @@ def test_time_travel_guide_chain(client: TestClient):
|
|||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "response",
|
||||
"password": False,
|
||||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "input",
|
||||
"password": False,
|
||||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
|
||||
assert template["template"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": True,
|
||||
"value": "I want you to act as my time travel guide. You are helpful and creative. I will provide you with the historical period or future time I want to visit and you will suggest the best events, sights, or people to experience. Provide the suggestions and any necessary information.\n Current conversation:\n {history}\n Human: {input}\n AI:", # noqa: E501
|
||||
"password": False,
|
||||
"name": "template",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert template["ai_prefix_value"] == {
|
||||
"required": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "ai_prefix_value",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
}
|
||||
assert chain["description"] == ""
|
||||
assert chain["description"] == "Time travel guide chain to be used in the flow."
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"name": "cache",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
|
|
@ -39,6 +40,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["client"] == {
|
||||
"required": False,
|
||||
|
|
@ -49,6 +51,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"name": "client",
|
||||
"type": "Any",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["repo_id"] == {
|
||||
"required": False,
|
||||
|
|
@ -60,6 +63,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"name": "repo_id",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["task"] == {
|
||||
"required": True,
|
||||
|
|
@ -71,6 +75,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"name": "task",
|
||||
"type": "str",
|
||||
"list": True,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["model_kwargs"] == {
|
||||
"required": False,
|
||||
|
|
@ -81,6 +86,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"name": "model_kwargs",
|
||||
"type": "code",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["huggingfacehub_api_token"] == {
|
||||
"required": False,
|
||||
|
|
@ -92,6 +98,7 @@ def test_hugging_face_hub(client: TestClient):
|
|||
"display_name": "HuggingFace Hub API Token",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -113,6 +120,7 @@ def test_openai(client: TestClient):
|
|||
"name": "cache",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
|
|
@ -123,6 +131,7 @@ def test_openai(client: TestClient):
|
|||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["client"] == {
|
||||
"required": False,
|
||||
|
|
@ -133,6 +142,7 @@ def test_openai(client: TestClient):
|
|||
"name": "client",
|
||||
"type": "Any",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["model_name"] == {
|
||||
"required": False,
|
||||
|
|
@ -151,6 +161,7 @@ def test_openai(client: TestClient):
|
|||
"name": "model_name",
|
||||
"type": "str",
|
||||
"list": True,
|
||||
"advanced": False,
|
||||
}
|
||||
# Add more assertions for other properties here
|
||||
assert template["temperature"] == {
|
||||
|
|
@ -163,6 +174,7 @@ def test_openai(client: TestClient):
|
|||
"name": "temperature",
|
||||
"type": "float",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["max_tokens"] == {
|
||||
"required": False,
|
||||
|
|
@ -174,6 +186,7 @@ def test_openai(client: TestClient):
|
|||
"name": "max_tokens",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["top_p"] == {
|
||||
"required": False,
|
||||
|
|
@ -185,6 +198,7 @@ def test_openai(client: TestClient):
|
|||
"name": "top_p",
|
||||
"type": "float",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["frequency_penalty"] == {
|
||||
"required": False,
|
||||
|
|
@ -196,6 +210,7 @@ def test_openai(client: TestClient):
|
|||
"name": "frequency_penalty",
|
||||
"type": "float",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["presence_penalty"] == {
|
||||
"required": False,
|
||||
|
|
@ -207,6 +222,7 @@ def test_openai(client: TestClient):
|
|||
"name": "presence_penalty",
|
||||
"type": "float",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["n"] == {
|
||||
"required": False,
|
||||
|
|
@ -218,6 +234,7 @@ def test_openai(client: TestClient):
|
|||
"name": "n",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["best_of"] == {
|
||||
"required": False,
|
||||
|
|
@ -229,6 +246,7 @@ def test_openai(client: TestClient):
|
|||
"name": "best_of",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["model_kwargs"] == {
|
||||
"required": False,
|
||||
|
|
@ -239,6 +257,7 @@ def test_openai(client: TestClient):
|
|||
"name": "model_kwargs",
|
||||
"type": "code",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["openai_api_key"] == {
|
||||
"required": False,
|
||||
|
|
@ -251,6 +270,7 @@ def test_openai(client: TestClient):
|
|||
"display_name": "OpenAI API Key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["batch_size"] == {
|
||||
"required": False,
|
||||
|
|
@ -262,6 +282,7 @@ def test_openai(client: TestClient):
|
|||
"name": "batch_size",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["request_timeout"] == {
|
||||
"required": False,
|
||||
|
|
@ -272,6 +293,7 @@ def test_openai(client: TestClient):
|
|||
"name": "request_timeout",
|
||||
"type": "Union[float, Tuple[float, float], NoneType]",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["logit_bias"] == {
|
||||
"required": False,
|
||||
|
|
@ -282,6 +304,7 @@ def test_openai(client: TestClient):
|
|||
"name": "logit_bias",
|
||||
"type": "code",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["max_retries"] == {
|
||||
"required": False,
|
||||
|
|
@ -293,6 +316,7 @@ def test_openai(client: TestClient):
|
|||
"name": "max_retries",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["streaming"] == {
|
||||
"required": False,
|
||||
|
|
@ -304,6 +328,7 @@ def test_openai(client: TestClient):
|
|||
"name": "streaming",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -326,6 +351,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["client"] == {
|
||||
"required": False,
|
||||
|
|
@ -336,6 +362,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "client",
|
||||
"type": "Any",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["model_name"] == {
|
||||
"required": False,
|
||||
|
|
@ -348,6 +375,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "model_name",
|
||||
"type": "str",
|
||||
"list": True,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["temperature"] == {
|
||||
"required": False,
|
||||
|
|
@ -359,6 +387,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "temperature",
|
||||
"type": "float",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["model_kwargs"] == {
|
||||
"required": False,
|
||||
|
|
@ -369,6 +398,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "model_kwargs",
|
||||
"type": "code",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["openai_api_key"] == {
|
||||
"required": False,
|
||||
|
|
@ -381,6 +411,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"display_name": "OpenAI API Key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
}
|
||||
assert template["request_timeout"] == {
|
||||
"required": False,
|
||||
|
|
@ -392,6 +423,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "request_timeout",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["max_retries"] == {
|
||||
"required": False,
|
||||
|
|
@ -403,6 +435,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "max_retries",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["streaming"] == {
|
||||
"required": False,
|
||||
|
|
@ -414,6 +447,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "streaming",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["n"] == {
|
||||
"required": False,
|
||||
|
|
@ -425,6 +459,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "n",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
assert template["max_tokens"] == {
|
||||
|
|
@ -436,6 +471,7 @@ def test_chat_open_ai(client: TestClient):
|
|||
"name": "max_tokens",
|
||||
"type": "int",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["_type"] == "ChatOpenAI"
|
||||
assert (
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ def test_prompt_template(client: TestClient):
|
|||
"name": "input_variables",
|
||||
"type": "str",
|
||||
"list": True,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["output_parser"] == {
|
||||
"required": False,
|
||||
|
|
@ -37,6 +38,7 @@ def test_prompt_template(client: TestClient):
|
|||
"name": "output_parser",
|
||||
"type": "BaseOutputParser",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["partial_variables"] == {
|
||||
"required": False,
|
||||
|
|
@ -47,6 +49,7 @@ def test_prompt_template(client: TestClient):
|
|||
"name": "partial_variables",
|
||||
"type": "code",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["template"] == {
|
||||
"required": True,
|
||||
|
|
@ -57,6 +60,7 @@ def test_prompt_template(client: TestClient):
|
|||
"name": "template",
|
||||
"type": "prompt",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["template_format"] == {
|
||||
"required": False,
|
||||
|
|
@ -68,6 +72,7 @@ def test_prompt_template(client: TestClient):
|
|||
"name": "template_format",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["validate_template"] == {
|
||||
"required": False,
|
||||
|
|
@ -79,6 +84,7 @@ def test_prompt_template(client: TestClient):
|
|||
"name": "validate_template",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -100,6 +106,7 @@ def test_few_shot_prompt_template(client: TestClient):
|
|||
"name": "examples",
|
||||
"type": "prompt",
|
||||
"list": True,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["example_selector"] == {
|
||||
"required": False,
|
||||
|
|
@ -110,6 +117,7 @@ def test_few_shot_prompt_template(client: TestClient):
|
|||
"name": "example_selector",
|
||||
"type": "BaseExampleSelector",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["example_prompt"] == {
|
||||
"required": True,
|
||||
|
|
@ -120,6 +128,7 @@ def test_few_shot_prompt_template(client: TestClient):
|
|||
"name": "example_prompt",
|
||||
"type": "PromptTemplate",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["suffix"] == {
|
||||
"required": True,
|
||||
|
|
@ -130,6 +139,7 @@ def test_few_shot_prompt_template(client: TestClient):
|
|||
"name": "suffix",
|
||||
"type": "prompt",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["example_separator"] == {
|
||||
"required": False,
|
||||
|
|
@ -141,6 +151,7 @@ def test_few_shot_prompt_template(client: TestClient):
|
|||
"name": "example_separator",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["prefix"] == {
|
||||
"required": False,
|
||||
|
|
@ -152,6 +163,7 @@ def test_few_shot_prompt_template(client: TestClient):
|
|||
"name": "prefix",
|
||||
"type": "prompt",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -172,6 +184,7 @@ def test_zero_shot_prompt(client: TestClient):
|
|||
"name": "prefix",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["suffix"] == {
|
||||
"required": True,
|
||||
|
|
@ -183,6 +196,7 @@ def test_zero_shot_prompt(client: TestClient):
|
|||
"name": "suffix",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
assert template["format_instructions"] == {
|
||||
"required": False,
|
||||
|
|
@ -194,4 +208,5 @@ def test_zero_shot_prompt(client: TestClient):
|
|||
"name": "format_instructions",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue