Added dropdown and global page

This commit is contained in:
Lucas Oliveira 2024-03-18 13:12:31 +01:00
commit 06f0e0e0f8
8 changed files with 118 additions and 215 deletions

BIN
langflow1.db Normal file

Binary file not shown.

View file

@ -8,7 +8,6 @@ from loguru import logger
from langflow.api.v1.schemas import ChatMessage
from langflow.interface.utils import try_setting_streaming_options
from langflow.processing.base import get_result_and_steps
from langflow.utils.chat import ChatDefinition
LANGCHAIN_RUNNABLES = (Chain, Runnable, AgentExecutor)
@ -40,20 +39,6 @@ async def process_graph(
client_id=client_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:
raise TypeError(f"Unknown type {type(build_result)}")
logger.debug("Generated result and intermediate_steps")

View file

@ -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)

View file

@ -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)

View file

@ -314,9 +314,8 @@ export default function ParameterComponent({
<>
<div
className={
"w-full truncate text-sm" +
(left ? "" : " text-end") +
(info !== "" ? " flex items-center" : "")
"w-full truncate text-sm flex items-center" +
(left ? "" : " text-end")
}
>
{proxy ? (
@ -429,8 +428,7 @@ export default function ParameterComponent({
newNode.data.node.template[name].load_from_db = true;
return newNode;
});
}
else{
} else {
setNode(data.id, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {

View file

@ -1,11 +1,13 @@
import { Listbox, Transition } from "@headlessui/react";
import * as Form from "@radix-ui/react-form";
import { Fragment, useEffect, useRef, useState } from "react";
import AddNewVariableButton from "../../pages/globalVariablesPage/components/addNewVariableButton";
import { InputComponentType } from "../../types/components";
import { handleKeyDown } from "../../utils/reactflowUtils";
import { classNames } from "../../utils/utils";
import { classNames, cn } from "../../utils/utils";
import IconComponent from "../genericIconComponent";
import { Input } from "../ui/input";
import { Separator } from "../ui/separator";
export default function InputComponent({
autoFocus = false,
@ -26,7 +28,6 @@ export default function InputComponent({
const [pwdVisible, setPwdVisible] = useState(false);
const refInput = useRef<HTMLInputElement>(null);
const [showOptions, setShowOptions] = useState<boolean>(false);
const [filteredOpts, setFilteredValue] = useState<string[]>(options);
// Clear component state
useEffect(() => {
@ -35,13 +36,12 @@ export default function InputComponent({
}
}, [disabled]);
const filteredOptions = filteredOpts.filter((option) =>
const filteredOptions = options.filter((option) =>
option.toLowerCase().includes(value.toLowerCase())
);
function onInputLostFocus(event): void {
if (onBlur) onBlur(event);
setShowOptions(false);
}
return (
@ -107,103 +107,115 @@ export default function InputComponent({
handleKeyDown(e, value, "");
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
}}
onFocus={() => setShowOptions(true)}
/>
{
/* options.length > 0 && filteredOptions.length > 0 */ true ? (
<Listbox
onChange={(val) => {
onChange(val);
}}
>
<>
<div className={"relative mt-1 "}>
<Transition
show={showOptions}
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options
className={classNames(
editNode
? "dropdown-component-true-options nowheel custom-scroll"
: "dropdown-component-false-options nowheel custom-scroll",
false ? "mb-2 w-[250px]" : "absolute w-full"
)}
<Listbox
onChange={(val) => {
onChange(val);
}}
>
<>
<div className={"relative mt-1 "}>
<Transition
show={showOptions}
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options
className={classNames(
editNode
? "dropdown-component-true-options nowheel custom-scroll"
: "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) => (
<Listbox.Option
key={id}
className={({ active }) =>
classNames(
active ? " bg-accent" : "",
editNode
? "dropdown-component-false-option"
: "dropdown-component-true-option",
" hover:bg-accent"
)
}
value={option}
>
{({ selected, active }) => (
<>
<span
className={classNames(
selected ? "font-semibold" : "font-normal",
"block truncate "
)}
data-testid={`${option}-${id ?? ""}-option`}
>
{option}
</span>
{({ selected, active }) => (
<>
<span
className={classNames(
selected ? "font-semibold" : "font-normal",
"block truncate "
)}
data-testid={`${option}-${id ?? ""}-option`}
>
{option}
</span>
{selected ? (
<span
className={classNames(
active ? "text-background " : "",
"dropdown-component-choosal"
)}
>
<IconComponent
name="Check"
className={
active
? "dropdown-component-check-icon"
: "dropdown-component-check-icon"
}
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
</Listbox>
) : null
}
{selected ? (
<span
className={classNames(
"dropdown-component-choosal"
)}
>
<IconComponent
name="Check"
className={
"dropdown-component-check-icon text-foreground"
}
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
</Listbox>
</>
)}
{options.length > 0 && (
<span
className={
password
? "dropdown-component-arrow right-8"
: "dropdown-component-arrow right-0"
}
className={cn(
password ? "right-8" : "right-0",
"absolute inset-y-0 flex items-center pr-2"
)}
>
<IconComponent
name="ChevronsUpDown"
className="dropdown-component-arrow-color"
aria-hidden="true"
/>
<button
onClick={() => {
setShowOptions(!showOptions);
}}
className="text-muted-foreground hover:text-accent-foreground"
>
<IconComponent
name="Globe"
className="h-4 w-4"
aria-hidden="true"
/>
</button>
</span>
)}
@ -212,6 +224,7 @@ export default function InputComponent({
type="button"
tabIndex={-1}
className={classNames(
"mb-px",
editNode
? "input-component-true-button"
: "input-component-false-button"

View file

@ -10,7 +10,7 @@ import { useGlobalVariablesStore } from "../../../stores/globalVariables";
//TODO IMPLEMENT FORM LOGIC
export default function AddNewVariableButton(): JSX.Element {
export default function AddNewVariableButton({children}): JSX.Element {
const [key, setKey] = useState("");
const [value, setValue] = useState("");
const [provider, setProvider] = useState("");
@ -33,25 +33,24 @@ export default function AddNewVariableButton(): JSX.Element {
});
}
return (
<BaseModal open={open} setOpen={setOpen} size="small">
<BaseModal open={open} setOpen={setOpen} size="x-small">
<BaseModal.Header
description={"write a text variable to use anywhere on your flow"}
>
<span>Create a new Variable</span>
</BaseModal.Header>
<BaseModal.Trigger>
<Button>Create a new variable</Button>
{children}
</BaseModal.Trigger>
<BaseModal.Content>
<div className="flex h-full w-full flex-col justify-around align-middle">
<div className="h-1/2">
<div className="flex gap-4 h-full w-full flex-col align-middle">
<Label>Variable name </Label>
<Input
value={key}
onChange={(e) => {
setKey(e.target.value);
}}
placeholder="example name"
placeholder="Insert a name for the variable..."
></Input>
<Label>Provider (optional) </Label>
<InputComponent
@ -61,19 +60,17 @@ export default function AddNewVariableButton(): JSX.Element {
}}
password={false}
options={["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]}
placeholder="example provider"
placeholder="Choose a provider between the environment variables..."
></InputComponent>
</div>
<div className="h-1/2">
<Label>Variable Value </Label>
<Textarea
value={value}
onChange={(e) => {
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>
</BaseModal.Content>
<BaseModal.Footer>

View file

@ -40,6 +40,7 @@ import {
GitBranchPlus,
GitFork,
GithubIcon,
Globe,
Group,
Hammer,
Heart,
@ -326,6 +327,7 @@ export const nodeIconsLucide: iconsType = {
Circle,
Clipboard,
Code2,
Globe,
Variable,
Store,
Download,