Added dropdown and global page
This commit is contained in:
parent
b57173dd76
commit
06f0e0e0f8
8 changed files with 118 additions and 215 deletions
BIN
langflow1.db
Normal file
BIN
langflow1.db
Normal file
Binary file not shown.
|
|
@ -8,7 +8,6 @@ from loguru import logger
|
||||||
from langflow.api.v1.schemas import ChatMessage
|
from langflow.api.v1.schemas import ChatMessage
|
||||||
from langflow.interface.utils import try_setting_streaming_options
|
from langflow.interface.utils import try_setting_streaming_options
|
||||||
from langflow.processing.base import get_result_and_steps
|
from langflow.processing.base import get_result_and_steps
|
||||||
from langflow.utils.chat import ChatDefinition
|
|
||||||
|
|
||||||
LANGCHAIN_RUNNABLES = (Chain, Runnable, AgentExecutor)
|
LANGCHAIN_RUNNABLES = (Chain, Runnable, AgentExecutor)
|
||||||
|
|
||||||
|
|
@ -40,20 +39,6 @@ async def process_graph(
|
||||||
client_id=client_id,
|
client_id=client_id,
|
||||||
session_id=session_id,
|
session_id=session_id,
|
||||||
)
|
)
|
||||||
elif isinstance(build_result, ChatDefinition):
|
|
||||||
raw_output = await run_build_result(
|
|
||||||
build_result,
|
|
||||||
chat_inputs,
|
|
||||||
client_id=client_id,
|
|
||||||
session_id=session_id,
|
|
||||||
)
|
|
||||||
if isinstance(raw_output, dict):
|
|
||||||
if not build_result.output_key:
|
|
||||||
raise ValueError("No output key provided to ChatDefinition when returning a dict.")
|
|
||||||
result = raw_output[build_result.output_key]
|
|
||||||
else:
|
|
||||||
result = raw_output
|
|
||||||
intermediate_steps = []
|
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"Unknown type {type(build_result)}")
|
raise TypeError(f"Unknown type {type(build_result)}")
|
||||||
logger.debug("Generated result and intermediate_steps")
|
logger.debug("Generated result and intermediate_steps")
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
from typing import Any, Callable, Optional, Union
|
|
||||||
|
|
||||||
from langchain_core.prompts import PromptTemplate as LCPromptTemplate
|
|
||||||
from langflow.utils.prompt import GenericPromptTemplate
|
|
||||||
from llama_index.prompts import PromptTemplate as LIPromptTemplate
|
|
||||||
|
|
||||||
PromptTemplate = Union[LCPromptTemplate, LIPromptTemplate]
|
|
||||||
|
|
||||||
|
|
||||||
class ChatDefinition:
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
func: Callable,
|
|
||||||
inputs: list[str],
|
|
||||||
output_key: Optional[str] = None,
|
|
||||||
prompt_template: Optional[PromptTemplate] = None,
|
|
||||||
):
|
|
||||||
self.func = func
|
|
||||||
self.input_keys = inputs
|
|
||||||
self.output_key = output_key
|
|
||||||
self.prompt_template = prompt_template
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_prompt_template(cls, prompt_template: PromptTemplate, func: Callable, output_key: Optional[str] = None):
|
|
||||||
prompt = GenericPromptTemplate(prompt_template)
|
|
||||||
return cls(
|
|
||||||
func=func,
|
|
||||||
inputs=prompt.input_keys,
|
|
||||||
output_key=output_key,
|
|
||||||
prompt_template=prompt_template,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __call__(self, inputs: dict, callbacks: Optional[Any] = None) -> dict:
|
|
||||||
return self.func(inputs, callbacks)
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
from typing import Any, Union
|
|
||||||
|
|
||||||
from langchain_core.prompts import PromptTemplate as LCPromptTemplate
|
|
||||||
from llama_index.prompts import PromptTemplate as LIPromptTemplate
|
|
||||||
|
|
||||||
PromptTemplateTypes = Union[LCPromptTemplate, LIPromptTemplate]
|
|
||||||
|
|
||||||
|
|
||||||
class GenericPromptTemplate:
|
|
||||||
def __init__(self, prompt_template: PromptTemplateTypes):
|
|
||||||
object.__setattr__(self, "prompt_template", prompt_template)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def input_keys(self):
|
|
||||||
prompt_template = object.__getattribute__(self, "prompt_template")
|
|
||||||
if isinstance(prompt_template, LCPromptTemplate):
|
|
||||||
return prompt_template.input_variables
|
|
||||||
elif isinstance(prompt_template, LIPromptTemplate):
|
|
||||||
return prompt_template.template_vars
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Unknown prompt template type {type(prompt_template)}")
|
|
||||||
|
|
||||||
def to_lc_prompt(self):
|
|
||||||
prompt_template = object.__getattribute__(self, "prompt_template")
|
|
||||||
if isinstance(prompt_template, LCPromptTemplate):
|
|
||||||
return prompt_template
|
|
||||||
elif isinstance(prompt_template, LIPromptTemplate):
|
|
||||||
return LCPromptTemplate.from_template(prompt_template.get_template())
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Unknown prompt template type {type(prompt_template)}")
|
|
||||||
|
|
||||||
def to_li_prompt(self):
|
|
||||||
prompt_template = object.__getattribute__(self, "prompt_template")
|
|
||||||
if isinstance(prompt_template, LIPromptTemplate):
|
|
||||||
return prompt_template
|
|
||||||
elif isinstance(prompt_template, LCPromptTemplate):
|
|
||||||
return LIPromptTemplate(template=prompt_template.template)
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Unknown prompt template type {type(prompt_template)}")
|
|
||||||
|
|
||||||
def __or__(self, other):
|
|
||||||
prompt_template = object.__getattribute__(self, "prompt_template")
|
|
||||||
if isinstance(prompt_template, LIPromptTemplate):
|
|
||||||
return self.to_lc_prompt() | other
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Unknown prompt template type {type(other)}")
|
|
||||||
|
|
||||||
def __getattribute__(self, name: str) -> Any:
|
|
||||||
if name in {
|
|
||||||
"input_keys",
|
|
||||||
"to_lc_prompt",
|
|
||||||
"to_li_prompt",
|
|
||||||
"__or__",
|
|
||||||
"prompt_template",
|
|
||||||
}:
|
|
||||||
return object.__getattribute__(self, name)
|
|
||||||
prompt_template = object.__getattribute__(self, "prompt_template")
|
|
||||||
return getattr(prompt_template, name)
|
|
||||||
|
|
@ -314,9 +314,8 @@ export default function ParameterComponent({
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"w-full truncate text-sm" +
|
"w-full truncate text-sm flex items-center" +
|
||||||
(left ? "" : " text-end") +
|
(left ? "" : " text-end")
|
||||||
(info !== "" ? " flex items-center" : "")
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{proxy ? (
|
{proxy ? (
|
||||||
|
|
@ -429,8 +428,7 @@ export default function ParameterComponent({
|
||||||
newNode.data.node.template[name].load_from_db = true;
|
newNode.data.node.template[name].load_from_db = true;
|
||||||
return newNode;
|
return newNode;
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
setNode(data.id, (oldNode) => {
|
setNode(data.id, (oldNode) => {
|
||||||
let newNode = cloneDeep(oldNode);
|
let newNode = cloneDeep(oldNode);
|
||||||
newNode.data = {
|
newNode.data = {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import { Listbox, Transition } from "@headlessui/react";
|
import { Listbox, Transition } from "@headlessui/react";
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { Fragment, useEffect, useRef, useState } from "react";
|
import { Fragment, useEffect, useRef, useState } from "react";
|
||||||
|
import AddNewVariableButton from "../../pages/globalVariablesPage/components/addNewVariableButton";
|
||||||
import { InputComponentType } from "../../types/components";
|
import { InputComponentType } from "../../types/components";
|
||||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||||
import { classNames } from "../../utils/utils";
|
import { classNames, cn } from "../../utils/utils";
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
|
import { Separator } from "../ui/separator";
|
||||||
|
|
||||||
export default function InputComponent({
|
export default function InputComponent({
|
||||||
autoFocus = false,
|
autoFocus = false,
|
||||||
|
|
@ -26,7 +28,6 @@ export default function InputComponent({
|
||||||
const [pwdVisible, setPwdVisible] = useState(false);
|
const [pwdVisible, setPwdVisible] = useState(false);
|
||||||
const refInput = useRef<HTMLInputElement>(null);
|
const refInput = useRef<HTMLInputElement>(null);
|
||||||
const [showOptions, setShowOptions] = useState<boolean>(false);
|
const [showOptions, setShowOptions] = useState<boolean>(false);
|
||||||
const [filteredOpts, setFilteredValue] = useState<string[]>(options);
|
|
||||||
|
|
||||||
// Clear component state
|
// Clear component state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -35,13 +36,12 @@ export default function InputComponent({
|
||||||
}
|
}
|
||||||
}, [disabled]);
|
}, [disabled]);
|
||||||
|
|
||||||
const filteredOptions = filteredOpts.filter((option) =>
|
const filteredOptions = options.filter((option) =>
|
||||||
option.toLowerCase().includes(value.toLowerCase())
|
option.toLowerCase().includes(value.toLowerCase())
|
||||||
);
|
);
|
||||||
|
|
||||||
function onInputLostFocus(event): void {
|
function onInputLostFocus(event): void {
|
||||||
if (onBlur) onBlur(event);
|
if (onBlur) onBlur(event);
|
||||||
setShowOptions(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -107,103 +107,115 @@ export default function InputComponent({
|
||||||
handleKeyDown(e, value, "");
|
handleKeyDown(e, value, "");
|
||||||
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
|
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
|
||||||
}}
|
}}
|
||||||
onFocus={() => setShowOptions(true)}
|
|
||||||
/>
|
/>
|
||||||
{
|
<Listbox
|
||||||
/* options.length > 0 && filteredOptions.length > 0 */ true ? (
|
onChange={(val) => {
|
||||||
<Listbox
|
onChange(val);
|
||||||
onChange={(val) => {
|
}}
|
||||||
onChange(val);
|
>
|
||||||
}}
|
<>
|
||||||
>
|
<div className={"relative mt-1 "}>
|
||||||
<>
|
<Transition
|
||||||
<div className={"relative mt-1 "}>
|
show={showOptions}
|
||||||
<Transition
|
as={Fragment}
|
||||||
show={showOptions}
|
leave="transition ease-in duration-100"
|
||||||
as={Fragment}
|
leaveFrom="opacity-100"
|
||||||
leave="transition ease-in duration-100"
|
leaveTo="opacity-0"
|
||||||
leaveFrom="opacity-100"
|
>
|
||||||
leaveTo="opacity-0"
|
<Listbox.Options
|
||||||
>
|
className={classNames(
|
||||||
<Listbox.Options
|
editNode
|
||||||
className={classNames(
|
? "dropdown-component-true-options nowheel custom-scroll"
|
||||||
editNode
|
: "dropdown-component-false-options nowheel custom-scroll",
|
||||||
? "dropdown-component-true-options nowheel custom-scroll"
|
false ? "mb-2 w-[250px]" : "absolute w-full"
|
||||||
: "dropdown-component-false-options nowheel custom-scroll",
|
)}
|
||||||
false ? "mb-2 w-[250px]" : "absolute w-full"
|
>
|
||||||
)}
|
<div className="flex items-center justify-between px-4 pb-3 pt-2 font-semibold">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<IconComponent name="Globe" className="h-4 w-4" />
|
||||||
|
Global Variables
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<AddNewVariableButton>
|
||||||
|
<button className="text-muted-foreground hover:text-accent-foreground">
|
||||||
|
<IconComponent name="Plus" className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</AddNewVariableButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
{filteredOptions.map((option, id) => (
|
||||||
|
<Listbox.Option
|
||||||
|
key={id}
|
||||||
|
className={({ active }) =>
|
||||||
|
classNames(
|
||||||
|
active ? " bg-accent" : "",
|
||||||
|
editNode
|
||||||
|
? "dropdown-component-false-option"
|
||||||
|
: "dropdown-component-true-option",
|
||||||
|
" hover:bg-accent"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
value={option}
|
||||||
>
|
>
|
||||||
{filteredOptions.map((option, id) => (
|
{({ selected, active }) => (
|
||||||
<Listbox.Option
|
<>
|
||||||
key={id}
|
<span
|
||||||
className={({ active }) =>
|
className={classNames(
|
||||||
classNames(
|
selected ? "font-semibold" : "font-normal",
|
||||||
active ? " bg-accent" : "",
|
"block truncate "
|
||||||
editNode
|
)}
|
||||||
? "dropdown-component-false-option"
|
data-testid={`${option}-${id ?? ""}-option`}
|
||||||
: "dropdown-component-true-option",
|
>
|
||||||
" hover:bg-accent"
|
{option}
|
||||||
)
|
</span>
|
||||||
}
|
|
||||||
value={option}
|
|
||||||
>
|
|
||||||
{({ selected, active }) => (
|
|
||||||
<>
|
|
||||||
<span
|
|
||||||
className={classNames(
|
|
||||||
selected ? "font-semibold" : "font-normal",
|
|
||||||
"block truncate "
|
|
||||||
)}
|
|
||||||
data-testid={`${option}-${id ?? ""}-option`}
|
|
||||||
>
|
|
||||||
{option}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{selected ? (
|
{selected ? (
|
||||||
<span
|
<span
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active ? "text-background " : "",
|
"dropdown-component-choosal"
|
||||||
"dropdown-component-choosal"
|
)}
|
||||||
)}
|
>
|
||||||
>
|
<IconComponent
|
||||||
<IconComponent
|
name="Check"
|
||||||
name="Check"
|
className={
|
||||||
className={
|
"dropdown-component-check-icon text-foreground"
|
||||||
active
|
}
|
||||||
? "dropdown-component-check-icon"
|
aria-hidden="true"
|
||||||
: "dropdown-component-check-icon"
|
/>
|
||||||
}
|
</span>
|
||||||
aria-hidden="true"
|
) : null}
|
||||||
/>
|
</>
|
||||||
</span>
|
)}
|
||||||
) : null}
|
</Listbox.Option>
|
||||||
</>
|
))}
|
||||||
)}
|
</Listbox.Options>
|
||||||
</Listbox.Option>
|
</Transition>
|
||||||
))}
|
</div>
|
||||||
</Listbox.Options>
|
</>
|
||||||
</Transition>
|
</Listbox>
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</Listbox>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{options.length > 0 && (
|
{options.length > 0 && (
|
||||||
<span
|
<span
|
||||||
className={
|
className={cn(
|
||||||
password
|
password ? "right-8" : "right-0",
|
||||||
? "dropdown-component-arrow right-8"
|
"absolute inset-y-0 flex items-center pr-2"
|
||||||
: "dropdown-component-arrow right-0"
|
)}
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<IconComponent
|
<button
|
||||||
name="ChevronsUpDown"
|
onClick={() => {
|
||||||
className="dropdown-component-arrow-color"
|
setShowOptions(!showOptions);
|
||||||
aria-hidden="true"
|
}}
|
||||||
/>
|
className="text-muted-foreground hover:text-accent-foreground"
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="Globe"
|
||||||
|
className="h-4 w-4"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -212,6 +224,7 @@ export default function InputComponent({
|
||||||
type="button"
|
type="button"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
"mb-px",
|
||||||
editNode
|
editNode
|
||||||
? "input-component-true-button"
|
? "input-component-true-button"
|
||||||
: "input-component-false-button"
|
: "input-component-false-button"
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { useGlobalVariablesStore } from "../../../stores/globalVariables";
|
||||||
|
|
||||||
//TODO IMPLEMENT FORM LOGIC
|
//TODO IMPLEMENT FORM LOGIC
|
||||||
|
|
||||||
export default function AddNewVariableButton(): JSX.Element {
|
export default function AddNewVariableButton({children}): JSX.Element {
|
||||||
const [key, setKey] = useState("");
|
const [key, setKey] = useState("");
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
const [provider, setProvider] = useState("");
|
const [provider, setProvider] = useState("");
|
||||||
|
|
@ -33,25 +33,24 @@ export default function AddNewVariableButton(): JSX.Element {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<BaseModal open={open} setOpen={setOpen} size="small">
|
<BaseModal open={open} setOpen={setOpen} size="x-small">
|
||||||
<BaseModal.Header
|
<BaseModal.Header
|
||||||
description={"write a text variable to use anywhere on your flow"}
|
description={"write a text variable to use anywhere on your flow"}
|
||||||
>
|
>
|
||||||
<span>Create a new Variable</span>
|
<span>Create a new Variable</span>
|
||||||
</BaseModal.Header>
|
</BaseModal.Header>
|
||||||
<BaseModal.Trigger>
|
<BaseModal.Trigger>
|
||||||
<Button>Create a new variable</Button>
|
{children}
|
||||||
</BaseModal.Trigger>
|
</BaseModal.Trigger>
|
||||||
<BaseModal.Content>
|
<BaseModal.Content>
|
||||||
<div className="flex h-full w-full flex-col justify-around align-middle">
|
<div className="flex gap-4 h-full w-full flex-col align-middle">
|
||||||
<div className="h-1/2">
|
|
||||||
<Label>Variable name </Label>
|
<Label>Variable name </Label>
|
||||||
<Input
|
<Input
|
||||||
value={key}
|
value={key}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setKey(e.target.value);
|
setKey(e.target.value);
|
||||||
}}
|
}}
|
||||||
placeholder="example name"
|
placeholder="Insert a name for the variable..."
|
||||||
></Input>
|
></Input>
|
||||||
<Label>Provider (optional) </Label>
|
<Label>Provider (optional) </Label>
|
||||||
<InputComponent
|
<InputComponent
|
||||||
|
|
@ -61,19 +60,17 @@ export default function AddNewVariableButton(): JSX.Element {
|
||||||
}}
|
}}
|
||||||
password={false}
|
password={false}
|
||||||
options={["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]}
|
options={["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]}
|
||||||
placeholder="example provider"
|
placeholder="Choose a provider between the environment variables..."
|
||||||
></InputComponent>
|
></InputComponent>
|
||||||
</div>
|
|
||||||
<div className="h-1/2">
|
|
||||||
<Label>Variable Value </Label>
|
<Label>Variable Value </Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setValue(e.target.value);
|
setValue(e.target.value);
|
||||||
}}
|
}}
|
||||||
className="h-4/6 w-full resize-none custom-scroll"
|
placeholder="Insert a value for the variable..."
|
||||||
|
className="w-full resize-none custom-scroll"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</BaseModal.Content>
|
</BaseModal.Content>
|
||||||
<BaseModal.Footer>
|
<BaseModal.Footer>
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import {
|
||||||
GitBranchPlus,
|
GitBranchPlus,
|
||||||
GitFork,
|
GitFork,
|
||||||
GithubIcon,
|
GithubIcon,
|
||||||
|
Globe,
|
||||||
Group,
|
Group,
|
||||||
Hammer,
|
Hammer,
|
||||||
Heart,
|
Heart,
|
||||||
|
|
@ -326,6 +327,7 @@ export const nodeIconsLucide: iconsType = {
|
||||||
Circle,
|
Circle,
|
||||||
Clipboard,
|
Clipboard,
|
||||||
Code2,
|
Code2,
|
||||||
|
Globe,
|
||||||
Variable,
|
Variable,
|
||||||
Store,
|
Store,
|
||||||
Download,
|
Download,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue