diff --git a/src/frontend/src/components/promptComponent/index.tsx b/src/frontend/src/components/promptComponent/index.tsx index 7a2998354..e3f414635 100644 --- a/src/frontend/src/components/promptComponent/index.tsx +++ b/src/frontend/src/components/promptComponent/index.tsx @@ -1,6 +1,6 @@ import { useContext, useEffect, useState } from "react"; -import { TypeModal } from "../../constants/constants"; +import { TypeModal } from "../../constants/enums"; import { PopUpContext } from "../../contexts/popUpContext"; import { typesContext } from "../../contexts/typesContext"; import { postValidatePrompt } from "../../controllers/API"; diff --git a/src/frontend/src/components/textAreaComponent/index.tsx b/src/frontend/src/components/textAreaComponent/index.tsx index 7681db959..e61899215 100644 --- a/src/frontend/src/components/textAreaComponent/index.tsx +++ b/src/frontend/src/components/textAreaComponent/index.tsx @@ -1,5 +1,5 @@ import { useContext, useEffect, useState } from "react"; -import { TypeModal } from "../../constants/constants"; +import { TypeModal } from "../../constants/enums"; import { PopUpContext } from "../../contexts/popUpContext"; import { TabsContext } from "../../contexts/tabsContext"; import GenericModal from "../../modals/genericModal"; diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index c001c95b8..cce19497e 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -1,19 +1,8 @@ -// src/constants.tsx +// src/constants/constants.ts import { MessageSquare } from "lucide-react"; -import { IVarHighlightType } from "../types/components"; -import { FlowType } from "../types/flow"; -import { TabsState } from "../types/tabs"; -import { buildTweaks } from "../utils/reactflowUtils"; -import { buildInputs } from "../utils/utils"; +import { languageMap } from "../types/components"; -/** - * constants fpr programming languages box on chat form - * @constant - */ -interface languageMap { - [key: string]: string | undefined; -} /** * invalid characters for flow name * @constant @@ -42,11 +31,6 @@ export const INVALID_CHARACTERS = [ export const regexHighlight = /\{([^}]+)\}/g; -export const varHighlightHTML = ({ name }: IVarHighlightType) => { - const html = `{${name}}`; - return html; -}; - export const programmingLanguages: languageMap = { javascript: ".js", python: ".py", @@ -73,15 +57,6 @@ export const programmingLanguages: languageMap = { css: ".css", // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component }; - -/** - * enum for the different types of nodes - * @enum - */ -export enum TypeModal { - TEXT = 1, - PROMPT = 2, -} /** * Number maximum of components to scroll on tooltips * @constant @@ -153,8 +128,6 @@ export const CHAT_CANNOT_OPEN_DESCRIPTION = "This is not a chat flow."; export const FLOW_NOT_BUILT_TITLE = "Flow not built"; -export const THOUGHTS_ICON = MessageSquare; - export const FLOW_NOT_BUILT_DESCRIPTION = "Please build the flow before chatting."; @@ -164,127 +137,6 @@ export const FLOW_NOT_BUILT_DESCRIPTION = */ export const TEXT_DIALOG_SUBTITLE = "Edit your text."; -/** - * Function to get the python code for the API - * @param {string} flowId - The id of the flow - * @returns {string} - The python code - */ -export const getPythonApiCode = ( - flow: FlowType, - tweak?: any[], - tabsState?: TabsState -): string => { - const flowId = flow.id; - - // create a dictionary of node ids and the values is an empty dictionary - // flow.data.nodes.forEach((node) => { - // node.data.id - // } - const tweaks = buildTweaks(flow); - const inputs = buildInputs(tabsState, flow.id); - return `import requests -from typing import Optional - -BASE_API_URL = "${window.location.protocol}//${ - window.location.host - }/api/v1/process" -FLOW_ID = "${flowId}" -# You can tweak the flow by adding a tweaks dictionary -# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}} -TWEAKS = ${ - tweak && tweak.length > 0 - ? buildTweakObject(tweak) - : JSON.stringify(tweaks, null, 2) - } - -def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None) -> dict: - """ - Run a flow with a given message and optional tweaks. - - :param message: The message to send to the flow - :param flow_id: The ID of the flow to run - :param tweaks: Optional tweaks to customize the flow - :return: The JSON response from the flow - """ - api_url = f"{BASE_API_URL}/{flow_id}" - - payload = {"inputs": inputs} - - if tweaks: - payload["tweaks"] = tweaks - - response = requests.post(api_url, json=payload) - return response.json() - -# Setup any tweaks you want to apply to the flow -inputs = ${inputs} -print(run_flow(inputs, flow_id=FLOW_ID, tweaks=TWEAKS))`; -}; -/** - * Function to get the curl code for the API - * @param {string} flowId - The id of the flow - * @returns {string} - The curl code - */ -export const getCurlCode = ( - flow: FlowType, - tweak?: any[], - tabsState?: TabsState -): string => { - const flowId = flow.id; - const tweaks = buildTweaks(flow); - const inputs = buildInputs(tabsState, flow.id); - - return `curl -X POST \\ - ${window.location.protocol}//${ - window.location.host - }/api/v1/process/${flowId} \\ - -H 'Content-Type: application/json' \\ - -d '{"inputs": ${inputs}, "tweaks": ${ - tweak && tweak.length > 0 - ? buildTweakObject(tweak) - : JSON.stringify(tweaks, null, 2) - }}'`; -}; -/** - * Function to get the python code for the API - * @param {string} flowName - The name of the flow - * @returns {string} - The python code - */ -export const getPythonCode = ( - flow: FlowType, - tweak?: any[], - tabsState?: TabsState -): string => { - const flowName = flow.name; - const tweaks = buildTweaks(flow); - const inputs = buildInputs(tabsState, flow.id); - return `from langflow import load_flow_from_json -TWEAKS = ${ - tweak && tweak.length > 0 - ? buildTweakObject(tweak) - : JSON.stringify(tweaks, null, 2) - } -flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS) -# Now you can use it like any chain -inputs = ${inputs} -flow(inputs)`; -}; - -function buildTweakObject(tweak) { - tweak.forEach((el) => { - Object.keys(el).forEach((key) => { - for (let kp in el[key]) { - try { - el[key][kp] = JSON.parse(el[key][kp]); - } catch {} - } - }); - }); - - const tweakString = JSON.stringify(tweak, null, 2); - return tweakString; -} - /** * The base text for subtitle of Import Dialog * @constant diff --git a/src/frontend/src/constants/enums.ts b/src/frontend/src/constants/enums.ts index e69de29bb..cd25d3df4 100644 --- a/src/frontend/src/constants/enums.ts +++ b/src/frontend/src/constants/enums.ts @@ -0,0 +1,8 @@ +/** + * enum for the different types of nodes + * @enum + */ +export enum TypeModal { + TEXT = 1, + PROMPT = 2, + } \ No newline at end of file diff --git a/src/frontend/src/modals/ApiModal/index.tsx b/src/frontend/src/modals/ApiModal/index.tsx index b8899a4fb..2abf5c94c 100644 --- a/src/frontend/src/modals/ApiModal/index.tsx +++ b/src/frontend/src/modals/ApiModal/index.tsx @@ -43,16 +43,13 @@ import { } from "../../components/ui/tabs"; import { EXPORT_CODE_DIALOG, - getCurlCode, - getPythonApiCode, - getPythonCode, } from "../../constants/constants"; import { darkContext } from "../../contexts/darkContext"; import { PopUpContext } from "../../contexts/popUpContext"; import { TabsContext } from "../../contexts/tabsContext"; import { FlowType } from "../../types/flow/index"; import { buildTweaks } from "../../utils/reactflowUtils"; -import { classNames } from "../../utils/utils"; +import { classNames, getPythonApiCode, getCurlCode, getPythonCode, } from "../../utils/utils"; export default function ApiModal({ flow }: { flow: FlowType }) { const [open, setOpen] = useState(true); const { dark } = useContext(darkContext); diff --git a/src/frontend/src/modals/formModal/chatMessage/index.tsx b/src/frontend/src/modals/formModal/chatMessage/index.tsx index f2a28c622..f7928e9f6 100644 --- a/src/frontend/src/modals/formModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/formModal/chatMessage/index.tsx @@ -8,7 +8,6 @@ import MaleTechnology from "../../../assets/male-technologist.png"; import Robot from "../../../assets/robot.png"; import SanitizedHTMLWrapper from "../../../components/SanitizedHTMLWrapper"; import IconComponent from "../../../components/genericIconComponent"; -import { THOUGHTS_ICON } from "../../../constants/constants"; import { ChatMessageType } from "../../../types/chat"; import { classNames } from "../../../utils/utils"; import FileCard from "../fileComponent"; @@ -61,7 +60,7 @@ export default function ChatMessage({ onClick={() => setHidden((prev) => !prev)} className="form-modal-chat-icon-div" > - + )} {chat.thought && chat.thought !== "" && !hidden && ( diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index d4d1a561b..e6dac86d4 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -22,7 +22,7 @@ import { DialogTrigger, } from "../../components/ui/dialog"; import { Textarea } from "../../components/ui/textarea"; -import { CHAT_FORM_DIALOG_SUBTITLE, THOUGHTS_ICON } from "../../constants/constants"; +import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants"; import { TabsContext } from "../../contexts/tabsContext"; import { validateNodes } from "../../utils/reactflowUtils"; @@ -586,7 +586,7 @@ export default function FormModal({ Start a conversation and click the agent's thoughts{" "} - + {" "} to inspect the chaining process. diff --git a/src/frontend/src/modals/genericModal/index.tsx b/src/frontend/src/modals/genericModal/index.tsx index 3373d6db2..a4613d2fe 100644 --- a/src/frontend/src/modals/genericModal/index.tsx +++ b/src/frontend/src/modals/genericModal/index.tsx @@ -11,16 +11,15 @@ import { MAX_WORDS_HIGHLIGHT, PROMPT_DIALOG_SUBTITLE, TEXT_DIALOG_SUBTITLE, - TypeModal, regexHighlight, - varHighlightHTML, } from "../../constants/constants"; +import { TypeModal } from "../../constants/enums"; import { alertContext } from "../../contexts/alertContext"; import { darkContext } from "../../contexts/darkContext"; import { PopUpContext } from "../../contexts/popUpContext"; import { postValidatePrompt } from "../../controllers/API"; import { APIClassType } from "../../types/api"; -import { classNames, getRandomKeyByssmm } from "../../utils/utils"; +import { classNames, getRandomKeyByssmm, varHighlightHTML } from "../../utils/utils"; import BaseModal from "../baseModal"; export default function GenericModal({ diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 813ed28a3..0ec6056f6 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -168,3 +168,7 @@ export type IconComponentProps = { className: string; iconColor?: string; }; + +export interface languageMap { + [key: string]: string | undefined; +}; diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index e876949ba..3dd1253f4 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -61,6 +61,7 @@ import { X, XCircle, Zap, + MessageSquare, } from "lucide-react"; import { Edge, Node } from "reactflow"; import { AirbyteIcon } from "../icons/Airbyte"; @@ -266,6 +267,7 @@ export const nodeIconsLucide = { Search, Copy, Upload, + MessageSquare, }; export function getConnectedNodes(edge: Edge, nodes: Array): Array { const sourceId = edge.source; diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index 83843b28b..6f57e49eb 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -1,6 +1,10 @@ import clsx, { ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants"; +import { IVarHighlightType } from "../types/components"; +import { FlowType } from "../types/flow"; +import { TabsState } from "../types/tabs"; +import { buildTweaks } from "./reactflowUtils"; export function classNames(...classes: Array) { return classes.filter(Boolean).join(" "); @@ -251,3 +255,131 @@ export function getRandomKeyByssmm(): string { const milliseconds = String(now.getMilliseconds()).padStart(3, "0"); return seconds + milliseconds + Math.abs(Math.floor(Math.random() * 10001)); } + +export const varHighlightHTML = ({ name }: IVarHighlightType) => { + const html = `{${name}}`; + return html; +}; + +export function buildTweakObject(tweak) { + tweak.forEach((el) => { + Object.keys(el).forEach((key) => { + for (let kp in el[key]) { + try { + el[key][kp] = JSON.parse(el[key][kp]); + } catch {} + } + }); + }); + + const tweakString = JSON.stringify(tweak, null, 2); + return tweakString; +} + +/** + * Function to get the python code for the API + * @param {string} flowId - The id of the flow + * @returns {string} - The python code + */ +export const getPythonApiCode = ( + flow: FlowType, + tweak?: any[], + tabsState?: TabsState +): string => { + const flowId = flow.id; + + // create a dictionary of node ids and the values is an empty dictionary + // flow.data.nodes.forEach((node) => { + // node.data.id + // } + const tweaks = buildTweaks(flow); + const inputs = buildInputs(tabsState, flow.id); + return `import requests +from typing import Optional + +BASE_API_URL = "${window.location.protocol}//${ + window.location.host + }/api/v1/process" +FLOW_ID = "${flowId}" +# You can tweak the flow by adding a tweaks dictionary +# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}} +TWEAKS = ${ + tweak && tweak.length > 0 + ? buildTweakObject(tweak) + : JSON.stringify(tweaks, null, 2) + } + +def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None) -> dict: + """ + Run a flow with a given message and optional tweaks. + + :param message: The message to send to the flow + :param flow_id: The ID of the flow to run + :param tweaks: Optional tweaks to customize the flow + :return: The JSON response from the flow + """ + api_url = f"{BASE_API_URL}/{flow_id}" + + payload = {"inputs": inputs} + + if tweaks: + payload["tweaks"] = tweaks + + response = requests.post(api_url, json=payload) + return response.json() + +# Setup any tweaks you want to apply to the flow +inputs = ${inputs} +print(run_flow(inputs, flow_id=FLOW_ID, tweaks=TWEAKS))`; +}; + +/** + * Function to get the curl code for the API + * @param {string} flowId - The id of the flow + * @returns {string} - The curl code + */ +export const getCurlCode = ( + flow: FlowType, + tweak?: any[], + tabsState?: TabsState +): string => { + const flowId = flow.id; + const tweaks = buildTweaks(flow); + const inputs = buildInputs(tabsState, flow.id); + + return `curl -X POST \\ + ${window.location.protocol}//${ + window.location.host + }/api/v1/process/${flowId} \\ + -H 'Content-Type: application/json' \\ + -d '{"inputs": ${inputs}, "tweaks": ${ + tweak && tweak.length > 0 + ? buildTweakObject(tweak) + : JSON.stringify(tweaks, null, 2) + }}'`; +}; + +/** + * Function to get the python code for the API + * @param {string} flowName - The name of the flow + * @returns {string} - The python code + */ +export const getPythonCode = ( + flow: FlowType, + tweak?: any[], + tabsState?: TabsState +): string => { + const flowName = flow.name; + const tweaks = buildTweaks(flow); + const inputs = buildInputs(tabsState, flow.id); + return `from langflow import load_flow_from_json +TWEAKS = ${ + tweak && tweak.length > 0 + ? buildTweakObject(tweak) + : JSON.stringify(tweaks, null, 2) + } +flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS) +# Now you can use it like any chain +inputs = ${inputs} +flow(inputs)`; +};