void;
@@ -45,7 +45,7 @@ function RefreshButton({
onClick={handleClick}
id={id}
>
-
{
data.node = nodeClass;
diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
index 92a3a7395..ae3b0b561 100644
--- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
@@ -477,6 +477,7 @@ export default function NodeToolbarComponent({
value={"Update"}
icon={"Code"}
dataTestId="update-button-modal"
+ ping={isOutdated}
/>
)}
@@ -616,12 +617,12 @@ export default function NodeToolbarComponent({
open={showModalAdvanced}
setOpen={setShowModalAdvanced}
/>
-
+ />}
{hasCode && (
{" "}
- {value}{" "}
+ className={`relative top-0.5 mr-2 h-4 w-4 ${styleObj?.iconClasses} ${
+ ping && "animate-pulse text-green-500"
+ }`}
+ />
+ {value}
+
{isMac ? (
((set, get) => ({
get().nodes.filter((node) => nodes.includes(node.id)),
get().edges
);
+
const errors = errorsObjs.map((obj) => obj.errors).flat();
if (errors.length > 0) {
setErrorData({
@@ -450,7 +451,7 @@ const useFlowStore = create((set, get) => ({
});
get().setIsBuilding(false);
const ids = errorsObjs.map((obj) => obj.id).flat();
- console.log("ids", ids);
+
get().updateBuildStatus(ids, BuildStatus.ERROR);
throw new Error("Invalid nodes");
}
@@ -490,6 +491,7 @@ const useFlowStore = create((set, get) => ({
verticesIds: newIds,
verticesLayers: newLayers,
runId: runId,
+ verticesToRun: get().verticesBuild!.verticesToRun,
});
get().updateBuildStatus(
vertexBuildData.top_level_vertices,
@@ -559,6 +561,7 @@ const useFlowStore = create((set, get) => ({
verticesIds: string[];
verticesLayers: VertexLayerElementType[][];
runId: string;
+ verticesToRun: string[];
} | null
) => {
set({ verticesBuild: vertices });
@@ -588,7 +591,7 @@ const useFlowStore = create((set, get) => ({
},
updateBuildStatus: (nodeIdList: string[], status: BuildStatus) => {
const newFlowBuildStatus = { ...get().flowBuildStatus };
- console.log("newFlowBuildStatus", newFlowBuildStatus);
+
nodeIdList.forEach((id) => {
newFlowBuildStatus[id] = {
status,
diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts
index cfbd64989..faef230a5 100644
--- a/src/frontend/src/types/api/index.ts
+++ b/src/frontend/src/types/api/index.ts
@@ -139,6 +139,7 @@ export type Component = {
export type VerticesOrderTypeAPI = {
ids: Array;
+ vertices_to_run: Array;
run_id: string;
};
diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts
index aa5893dc2..badf9a385 100644
--- a/src/frontend/src/types/components/index.ts
+++ b/src/frontend/src/types/components/index.ts
@@ -724,4 +724,5 @@ export type toolbarSelectItemProps = {
valueClasses?: string;
};
dataTestId: string;
+ ping?: boolean;
};
diff --git a/src/frontend/src/types/zustand/flow/index.ts b/src/frontend/src/types/zustand/flow/index.ts
index 0fa8c971d..71853c5a7 100644
--- a/src/frontend/src/types/zustand/flow/index.ts
+++ b/src/frontend/src/types/zustand/flow/index.ts
@@ -110,6 +110,7 @@ export type FlowStoreType = {
verticesIds: string[];
verticesLayers: VertexLayerElementType[][];
runId: string;
+ verticesToRun: string[];
} | null
) => void;
addToVerticesBuild: (vertices: string[]) => void;
@@ -118,6 +119,7 @@ export type FlowStoreType = {
verticesIds: string[];
verticesLayers: VertexLayerElementType[][];
runId: string;
+ verticesToRun: string[];
} | null;
updateBuildStatus: (nodeId: string[], status: BuildStatus) => void;
revertBuiltStatusFromBuilding: () => void;
diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts
index 1121fca04..03264d1b9 100644
--- a/src/frontend/src/utils/buildUtils.ts
+++ b/src/frontend/src/utils/buildUtils.ts
@@ -53,6 +53,7 @@ export async function updateVerticesOrder(
verticesLayers: VertexLayerElementType[][];
verticesIds: string[];
runId: string;
+ verticesToRun: string[];
}> {
return new Promise(async (resolve, reject) => {
const setErrorData = useAlertStore.getState().setErrorData;
@@ -60,7 +61,6 @@ export async function updateVerticesOrder(
try {
orderResponse = await getVerticesOrder(flowId, startNodeId, stopNodeId);
} catch (error: any) {
- console.log(error);
setErrorData({
title: "Oops! Looks like you missed something",
list: [error.response?.data?.detail ?? "Unknown Error"],
@@ -77,30 +77,16 @@ export async function updateVerticesOrder(
});
const runId = orderResponse.data.run_id;
- // if (nodeId) {
- // for (let i = 0; i < verticesOrder.length; i += 1) {
- // const innerArray = verticesOrder[i];
- // const idIndex = innerArray.indexOf(nodeId);
- // if (idIndex !== -1) {
- // // If there's a nodeId, we want to run just that component and not the entire layer
- // // because a layer contains dependencies for the next layer
- // // and we are stopping at the layer that contains the nodeId
- // verticesLayers.push([innerArray[idIndex]]);
- // break; // Stop searching after finding the first occurrence
- // }
- // // If the targetId is not found, include the entire inner array
- // verticesLayers.push(innerArray);
- // }
- // } else {
- // verticesLayers = verticesOrder;
- // }
+ const verticesToRun = orderResponse.data.vertices_to_run;
+
const verticesIds = orderResponse.data.ids;
useFlowStore.getState().updateVerticesBuild({
verticesLayers,
verticesIds,
runId,
+ verticesToRun,
});
- resolve({ verticesLayers, verticesIds, runId });
+ resolve({ verticesLayers, verticesIds, runId, verticesToRun });
});
}
@@ -122,8 +108,22 @@ export async function buildVertices({
if (startNodeId && stopNodeId) {
return;
}
+
if (!verticesBuild || startNodeId || stopNodeId) {
- verticesBuild = await updateVerticesOrder(flowId, startNodeId, stopNodeId);
+ let verticesOrderResponse = await updateVerticesOrder(
+ flowId,
+ startNodeId,
+ stopNodeId
+ );
+ if (onValidateNodes) {
+ try {
+ onValidateNodes(verticesOrderResponse.verticesToRun);
+ } catch (e) {
+ return;
+ }
+ }
+ if (onGetOrderSuccess) onGetOrderSuccess();
+ verticesBuild = useFlowStore.getState().verticesBuild;
}
const verticesIds = verticesBuild?.verticesIds!;
@@ -131,17 +131,6 @@ export async function buildVertices({
const runId = verticesBuild?.runId!;
let stop = false;
- if (onGetOrderSuccess) onGetOrderSuccess();
-
- if (onValidateNodes) {
- try {
- const nodes = useFlowStore.getState().nodes;
- onValidateNodes(nodes.map((node) => node.id));
- } catch (e) {
- return;
- }
- }
-
useFlowStore.getState().updateBuildStatus(verticesIds, BuildStatus.TO_BUILD);
useFlowStore.getState().setIsBuilding(true);
let currentLayerIndex = 0; // Start with the first layer
diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts
index 8732ed3d1..28d28fa90 100644
--- a/src/frontend/src/utils/utils.ts
+++ b/src/frontend/src/utils/utils.ts
@@ -429,7 +429,7 @@ export function getPythonCode(
const flowName = flow.name;
const tweaks = buildTweaks(flow);
const inputs = buildInputs();
- return `from langflow import load_flow_from_json
+ return `from langflow.load import load_flow_from_json
TWEAKS = ${
tweak && tweak.length > 0
? buildTweakObject(tweak)
diff --git a/src/frontend/tests/custom_component_full.ts b/src/frontend/tests/custom_component_full.ts
index c38d7ff06..d5a890a1b 100644
--- a/src/frontend/tests/custom_component_full.ts
+++ b/src/frontend/tests/custom_component_full.ts
@@ -1,4 +1,4 @@
-export const custom = `from langflow import CustomComponent
+export const custom = `from langflow.custom import CustomComponent
from langchain.llms.base import BaseLLM
from langchain.chains import LLMChain
diff --git a/src/frontend/tests/end-to-end/assets/collection.json b/src/frontend/tests/end-to-end/assets/collection.json
index 3872089d0..7b58fdadf 100644
--- a/src/frontend/tests/end-to-end/assets/collection.json
+++ b/src/frontend/tests/end-to-end/assets/collection.json
@@ -10,7 +10,10 @@
"height": 631,
"id": "ChatOpenAI-Hz56M",
"type": "genericNode",
- "position": { "x": 543.1816229116944, "y": 942.891611351432 },
+ "position": {
+ "x": 543.1816229116944,
+ "y": 942.891611351432
+ },
"data": {
"type": "ChatOpenAI",
"node": {
@@ -238,7 +241,10 @@
"height": 387,
"id": "AgentInitializer-QiQ4x",
"type": "genericNode",
- "position": { "x": 1036.6064439140812, "y": 645.1919693466587 },
+ "position": {
+ "x": 1036.6064439140812,
+ "y": 645.1919693466587
+ },
"data": {
"type": "AgentInitializer",
"node": {
@@ -299,7 +305,10 @@
"_type": "initialize_agent"
},
"description": "Construct a zero shot agent from an LLM and tools.",
- "base_classes": ["AgentExecutor", "function"],
+ "base_classes": [
+ "AgentExecutor",
+ "function"
+ ],
"display_name": "AgentInitializer"
},
"id": "AgentInitializer-QiQ4x",
@@ -316,7 +325,10 @@
"height": 437,
"id": "PythonFunctionTool-kX99N",
"type": "genericNode",
- "position": { "x": 553.050119331742, "y": 412.9533535948685 },
+ "position": {
+ "x": 553.050119331742,
+ "y": 412.9533535948685
+ },
"data": {
"type": "PythonFunctionTool",
"node": {
@@ -360,7 +372,9 @@
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
- "base_classes": ["Tool"],
+ "base_classes": [
+ "Tool"
+ ],
"display_name": "PythonFunctionTool"
},
"id": "PythonFunctionTool-kX99N",
@@ -380,7 +394,9 @@
"sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-Hz56Mœ}",
"target": "AgentInitializer-QiQ4x",
"targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-Hz56M{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-Hz56Mœ}-AgentInitializer-QiQ4x{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
@@ -409,14 +425,18 @@
"sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-kX99Nœ}",
"target": "AgentInitializer-QiQ4x",
"targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œToolœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-PythonFunctionTool-kX99N{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-kX99Nœ}-AgentInitializer-QiQ4x{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œToolœ}",
"selected": false,
"data": {
"sourceHandle": {
- "baseClasses": ["Tool"],
+ "baseClasses": [
+ "Tool"
+ ],
"dataType": "PythonFunctionTool",
"id": "PythonFunctionTool-kX99N"
},
@@ -446,7 +466,10 @@
{
"id": "CustomComponent-w4WCp",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -456,7 +479,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -478,11 +501,18 @@
},
"id": "CustomComponent-w4WCp"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "e43cf2c8-cd64-4936-8170-b207a8b109c4",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -497,7 +527,10 @@
"height": 631,
"id": "ChatOpenAI-7GFF0",
"type": "genericNode",
- "position": { "x": 543.1816229116944, "y": 942.891611351432 },
+ "position": {
+ "x": 543.1816229116944,
+ "y": 942.891611351432
+ },
"data": {
"type": "ChatOpenAI",
"node": {
@@ -725,7 +758,10 @@
"height": 387,
"id": "AgentInitializer-YJgqs",
"type": "genericNode",
- "position": { "x": 1036.6064439140812, "y": 645.1919693466587 },
+ "position": {
+ "x": 1036.6064439140812,
+ "y": 645.1919693466587
+ },
"data": {
"type": "AgentInitializer",
"node": {
@@ -786,7 +822,10 @@
"_type": "initialize_agent"
},
"description": "Construct a zero shot agent from an LLM and tools.",
- "base_classes": ["AgentExecutor", "function"],
+ "base_classes": [
+ "AgentExecutor",
+ "function"
+ ],
"display_name": "AgentInitializer"
},
"id": "AgentInitializer-YJgqs",
@@ -803,7 +842,10 @@
"height": 437,
"id": "PythonFunctionTool-gqQDg",
"type": "genericNode",
- "position": { "x": 553.050119331742, "y": 412.9533535948685 },
+ "position": {
+ "x": 553.050119331742,
+ "y": 412.9533535948685
+ },
"data": {
"type": "PythonFunctionTool",
"node": {
@@ -847,7 +889,9 @@
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
- "base_classes": ["Tool"],
+ "base_classes": [
+ "Tool"
+ ],
"display_name": "PythonFunctionTool"
},
"id": "PythonFunctionTool-gqQDg",
@@ -867,7 +911,9 @@
"sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-7GFF0œ}",
"target": "AgentInitializer-YJgqs",
"targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-7GFF0{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-7GFF0œ}-AgentInitializer-YJgqs{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
@@ -896,14 +942,18 @@
"sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-gqQDgœ}",
"target": "AgentInitializer-YJgqs",
"targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œToolœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-PythonFunctionTool-gqQDg{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-gqQDgœ}-AgentInitializer-YJgqs{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œToolœ}",
"selected": false,
"data": {
"sourceHandle": {
- "baseClasses": ["Tool"],
+ "baseClasses": [
+ "Tool"
+ ],
"dataType": "PythonFunctionTool",
"id": "PythonFunctionTool-gqQDg"
},
@@ -933,7 +983,10 @@
{
"id": "CustomComponent-iF9Zr",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -943,7 +996,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -965,11 +1018,18 @@
},
"id": "CustomComponent-iF9Zr"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "88a0e6a1-8144-4bff-b28c-d312ae5c8a10",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -984,7 +1044,10 @@
"height": 631,
"id": "ChatOpenAI-cljAK",
"type": "genericNode",
- "position": { "x": 543.1816229116944, "y": 942.891611351432 },
+ "position": {
+ "x": 543.1816229116944,
+ "y": 942.891611351432
+ },
"data": {
"type": "ChatOpenAI",
"node": {
@@ -1212,7 +1275,10 @@
"height": 387,
"id": "AgentInitializer-grV0u",
"type": "genericNode",
- "position": { "x": 1036.6064439140812, "y": 645.1919693466587 },
+ "position": {
+ "x": 1036.6064439140812,
+ "y": 645.1919693466587
+ },
"data": {
"type": "AgentInitializer",
"node": {
@@ -1273,7 +1339,10 @@
"_type": "initialize_agent"
},
"description": "Construct a zero shot agent from an LLM and tools.",
- "base_classes": ["AgentExecutor", "function"],
+ "base_classes": [
+ "AgentExecutor",
+ "function"
+ ],
"display_name": "AgentInitializer"
},
"id": "AgentInitializer-grV0u",
@@ -1290,7 +1359,10 @@
"height": 437,
"id": "PythonFunctionTool-SctM2",
"type": "genericNode",
- "position": { "x": 553.050119331742, "y": 412.9533535948685 },
+ "position": {
+ "x": 553.050119331742,
+ "y": 412.9533535948685
+ },
"data": {
"type": "PythonFunctionTool",
"node": {
@@ -1334,7 +1406,9 @@
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
- "base_classes": ["Tool"],
+ "base_classes": [
+ "Tool"
+ ],
"display_name": "PythonFunctionTool"
},
"id": "PythonFunctionTool-SctM2",
@@ -1354,7 +1428,9 @@
"sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-cljAKœ}",
"target": "AgentInitializer-grV0u",
"targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-cljAK{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-cljAKœ}-AgentInitializer-grV0u{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
@@ -1383,14 +1459,18 @@
"sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SctM2œ}",
"target": "AgentInitializer-grV0u",
"targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œToolœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-PythonFunctionTool-SctM2{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SctM2œ}-AgentInitializer-grV0u{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œToolœ}",
"selected": false,
"data": {
"sourceHandle": {
- "baseClasses": ["Tool"],
+ "baseClasses": [
+ "Tool"
+ ],
"dataType": "PythonFunctionTool",
"id": "PythonFunctionTool-SctM2"
},
@@ -1420,7 +1500,10 @@
{
"id": "CustomComponent-z5kAP",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1430,7 +1513,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1452,11 +1535,18 @@
},
"id": "CustomComponent-z5kAP"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "3128b556-35c7-4ced-a834-70fbeb1a410f",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1469,7 +1559,10 @@
{
"id": "CustomComponent-ZieNZ",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1479,7 +1572,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1501,11 +1594,18 @@
},
"id": "CustomComponent-ZieNZ"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "d3f2c379-9df5-49a0-b33d-d855c2085949",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1518,7 +1618,10 @@
{
"id": "CustomComponent-CcHG0",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1528,7 +1631,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1550,11 +1653,18 @@
},
"id": "CustomComponent-CcHG0"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "74afff1f-b540-43d5-bc66-d18f39d65d57",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1567,7 +1677,10 @@
{
"id": "CustomComponent-Q8qSr",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1577,7 +1690,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1599,11 +1712,18 @@
},
"id": "CustomComponent-Q8qSr"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "b0b1c893-6194-4748-ae10-b5f604b271c2",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1616,7 +1736,10 @@
{
"id": "CustomComponent-Lgoca",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1626,7 +1749,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1648,11 +1771,18 @@
},
"id": "CustomComponent-Lgoca"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "edf1051d-509b-46a2-84c6-b94bdcdc3a4f",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1665,7 +1795,10 @@
{
"id": "CustomComponent-6OJGW",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1675,7 +1808,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1697,11 +1830,18 @@
},
"id": "CustomComponent-6OJGW"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "65b2a4e0-4084-418a-aa86-ee914acb0ab5",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1714,7 +1854,10 @@
{
"id": "CustomComponent-tcE83",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -1724,7 +1867,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -1746,11 +1889,18 @@
},
"id": "CustomComponent-tcE83"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "534e412b-d37b-4133-8029-e5ed139fd55c",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -1765,7 +1915,10 @@
"height": 631,
"id": "ChatOpenAI-mQEi3",
"type": "genericNode",
- "position": { "x": 543.1816229116944, "y": 942.891611351432 },
+ "position": {
+ "x": 543.1816229116944,
+ "y": 942.891611351432
+ },
"data": {
"type": "ChatOpenAI",
"node": {
@@ -1993,7 +2146,10 @@
"height": 387,
"id": "AgentInitializer-EE8R4",
"type": "genericNode",
- "position": { "x": 1036.6064439140812, "y": 645.1919693466587 },
+ "position": {
+ "x": 1036.6064439140812,
+ "y": 645.1919693466587
+ },
"data": {
"type": "AgentInitializer",
"node": {
@@ -2054,7 +2210,10 @@
"_type": "initialize_agent"
},
"description": "Construct a zero shot agent from an LLM and tools.",
- "base_classes": ["AgentExecutor", "function"],
+ "base_classes": [
+ "AgentExecutor",
+ "function"
+ ],
"display_name": "AgentInitializer"
},
"id": "AgentInitializer-EE8R4",
@@ -2071,7 +2230,10 @@
"height": 437,
"id": "PythonFunctionTool-YKkDL",
"type": "genericNode",
- "position": { "x": 553.050119331742, "y": 412.9533535948685 },
+ "position": {
+ "x": 553.050119331742,
+ "y": 412.9533535948685
+ },
"data": {
"type": "PythonFunctionTool",
"node": {
@@ -2115,7 +2277,9 @@
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
- "base_classes": ["Tool"],
+ "base_classes": [
+ "Tool"
+ ],
"display_name": "PythonFunctionTool"
},
"id": "PythonFunctionTool-YKkDL",
@@ -2135,7 +2299,9 @@
"sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-mQEi3œ}",
"target": "AgentInitializer-EE8R4",
"targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-mQEi3{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-mQEi3œ}-AgentInitializer-EE8R4{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
@@ -2164,14 +2330,18 @@
"sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-YKkDLœ}",
"target": "AgentInitializer-EE8R4",
"targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œToolœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-PythonFunctionTool-YKkDL{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-YKkDLœ}-AgentInitializer-EE8R4{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œToolœ}",
"selected": false,
"data": {
"sourceHandle": {
- "baseClasses": ["Tool"],
+ "baseClasses": [
+ "Tool"
+ ],
"dataType": "PythonFunctionTool",
"id": "PythonFunctionTool-YKkDL"
},
@@ -2201,7 +2371,10 @@
{
"id": "CustomComponent-T38LS",
"type": "genericNode",
- "position": { "x": 536, "y": 337 },
+ "position": {
+ "x": 536,
+ "y": 337
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -2211,7 +2384,7 @@
"placeholder": "",
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
+ "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n",
"password": false,
"name": "code",
"advanced": false,
@@ -2233,11 +2406,18 @@
},
"id": "CustomComponent-T38LS"
},
- "positionAbsolute": { "x": 536, "y": 337 }
+ "positionAbsolute": {
+ "x": 536,
+ "y": 337
+ }
}
],
"edges": [],
- "viewport": { "x": 0, "y": 0, "zoom": 1 }
+ "viewport": {
+ "x": 0,
+ "y": 0,
+ "zoom": 1
+ }
},
"id": "ec36a3b7-7b5f-4663-983c-833bcec4d851",
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
@@ -2252,7 +2432,10 @@
"height": 631,
"id": "ChatOpenAI-E1XSb",
"type": "genericNode",
- "position": { "x": 543.1816229116944, "y": 942.891611351432 },
+ "position": {
+ "x": 543.1816229116944,
+ "y": 942.891611351432
+ },
"data": {
"type": "ChatOpenAI",
"node": {
@@ -2480,7 +2663,10 @@
"height": 387,
"id": "AgentInitializer-goPm2",
"type": "genericNode",
- "position": { "x": 1036.6064439140812, "y": 645.1919693466587 },
+ "position": {
+ "x": 1036.6064439140812,
+ "y": 645.1919693466587
+ },
"data": {
"type": "AgentInitializer",
"node": {
@@ -2541,7 +2727,10 @@
"_type": "initialize_agent"
},
"description": "Construct a zero shot agent from an LLM and tools.",
- "base_classes": ["AgentExecutor", "function"],
+ "base_classes": [
+ "AgentExecutor",
+ "function"
+ ],
"display_name": "AgentInitializer"
},
"id": "AgentInitializer-goPm2",
@@ -2558,7 +2747,10 @@
"height": 437,
"id": "PythonFunctionTool-SQikY",
"type": "genericNode",
- "position": { "x": 553.050119331742, "y": 412.9533535948685 },
+ "position": {
+ "x": 553.050119331742,
+ "y": 412.9533535948685
+ },
"data": {
"type": "PythonFunctionTool",
"node": {
@@ -2602,7 +2794,9 @@
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
- "base_classes": ["Tool"],
+ "base_classes": [
+ "Tool"
+ ],
"display_name": "PythonFunctionTool"
},
"id": "PythonFunctionTool-SQikY",
@@ -2622,7 +2816,9 @@
"sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-E1XSbœ}",
"target": "AgentInitializer-goPm2",
"targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-E1XSb{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-E1XSbœ}-AgentInitializer-goPm2{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}",
@@ -2651,14 +2847,18 @@
"sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SQikYœ}",
"target": "AgentInitializer-goPm2",
"targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œToolœ}",
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-PythonFunctionTool-SQikY{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SQikYœ}-AgentInitializer-goPm2{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œToolœ}",
"selected": false,
"data": {
"sourceHandle": {
- "baseClasses": ["Tool"],
+ "baseClasses": [
+ "Tool"
+ ],
"dataType": "PythonFunctionTool",
"id": "PythonFunctionTool-SQikY"
},
@@ -2681,4 +2881,4 @@
"user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b"
}
]
-}
+}
\ No newline at end of file
diff --git a/src/frontend/tests/end-to-end/assets/flow_group_test.json b/src/frontend/tests/end-to-end/assets/flow_group_test.json
index 9df38cfb3..efd5478b3 100644
--- a/src/frontend/tests/end-to-end/assets/flow_group_test.json
+++ b/src/frontend/tests/end-to-end/assets/flow_group_test.json
@@ -5,7 +5,10 @@
{
"id": "PythonFunctionTool-RfJui",
"type": "genericNode",
- "position": { "x": 117.54690105175428, "y": -84.2465475108354 },
+ "position": {
+ "x": 117.54690105175428,
+ "y": -84.2465475108354
+ },
"data": {
"type": "PythonFunctionTool",
"node": {
@@ -43,7 +46,9 @@
"dynamic": false,
"info": "",
"title_case": false,
- "input_types": ["Text"]
+ "input_types": [
+ "Text"
+ ]
},
"name": {
"type": "str",
@@ -61,7 +66,9 @@
"dynamic": false,
"info": "",
"title_case": false,
- "input_types": ["Text"]
+ "input_types": [
+ "Text"
+ ]
},
"return_direct": {
"type": "bool",
@@ -83,7 +90,10 @@
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
- "base_classes": ["BaseTool", "Tool"],
+ "base_classes": [
+ "BaseTool",
+ "Tool"
+ ],
"display_name": "PythonFunctionTool",
"documentation": "",
"custom_fields": {},
@@ -97,13 +107,19 @@
"selected": true,
"width": 384,
"height": 466,
- "positionAbsolute": { "x": 117.54690105175428, "y": -84.2465475108354 },
+ "positionAbsolute": {
+ "x": 117.54690105175428,
+ "y": -84.2465475108354
+ },
"dragging": false
},
{
"id": "AgentInitializer-tPdJw",
"type": "genericNode",
- "position": { "x": 677.68677055088, "y": 127.19859565276168 },
+ "position": {
+ "x": 677.68677055088,
+ "y": 127.19859565276168
+ },
"data": {
"type": "AgentInitializer",
"node": {
@@ -192,7 +208,9 @@
"dynamic": false,
"info": "",
"title_case": false,
- "input_types": ["Text"]
+ "input_types": [
+ "Text"
+ ]
},
"code": {
"type": "code",
@@ -201,7 +219,7 @@
"list": false,
"show": true,
"multiline": true,
- "value": "from typing import Callable, List, Optional, Union\n\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\nfrom langflow import CustomComponent\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\n\n\nclass AgentInitializerComponent(CustomComponent):\n display_name: str = \"Agent Initializer\"\n description: str = \"Initialize a Langchain Agent.\"\n documentation: str = \"https://python.langchain.com/docs/modules/agents/agent_types/\"\n\n def build_config(self):\n agents = list(types.AGENT_TO_CLASS.keys())\n # field_type and required are optional\n return {\n \"agent\": {\"options\": agents, \"value\": agents[0], \"display_name\": \"Agent Type\"},\n \"max_iterations\": {\"display_name\": \"Max Iterations\", \"value\": 10},\n \"memory\": {\"display_name\": \"Memory\"},\n \"tools\": {\"display_name\": \"Tools\"},\n \"llm\": {\"display_name\": \"Language Model\"},\n \"code\": {\"advanced\": True},\n }\n\n def build(\n self,\n agent: str,\n llm: BaseLanguageModel,\n tools: List[Tool],\n max_iterations: int,\n memory: Optional[BaseChatMemory] = None,\n ) -> Union[AgentExecutor, Callable]:\n agent = AgentType(agent)\n if memory:\n return initialize_agent(\n tools=tools,\n llm=llm,\n agent=agent,\n memory=memory,\n return_intermediate_steps=True,\n handle_parsing_errors=True,\n max_iterations=max_iterations,\n )\n return initialize_agent(\n tools=tools,\n llm=llm,\n agent=agent,\n return_intermediate_steps=True,\n handle_parsing_errors=True,\n max_iterations=max_iterations,\n )\n",
+ "value": "from typing import Callable, List, Optional, Union\n\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\n\n\nclass AgentInitializerComponent(CustomComponent):\n display_name: str = \"Agent Initializer\"\n description: str = \"Initialize a Langchain Agent.\"\n documentation: str = \"https://python.langchain.com/docs/modules/agents/agent_types/\"\n\n def build_config(self):\n agents = list(types.AGENT_TO_CLASS.keys())\n # field_type and required are optional\n return {\n \"agent\": {\"options\": agents, \"value\": agents[0], \"display_name\": \"Agent Type\"},\n \"max_iterations\": {\"display_name\": \"Max Iterations\", \"value\": 10},\n \"memory\": {\"display_name\": \"Memory\"},\n \"tools\": {\"display_name\": \"Tools\"},\n \"llm\": {\"display_name\": \"Language Model\"},\n \"code\": {\"advanced\": True},\n }\n\n def build(\n self,\n agent: str,\n llm: BaseLanguageModel,\n tools: List[Tool],\n max_iterations: int,\n memory: Optional[BaseChatMemory] = None,\n ) -> Union[AgentExecutor, Callable]:\n agent = AgentType(agent)\n if memory:\n return initialize_agent(\n tools=tools,\n llm=llm,\n agent=agent,\n memory=memory,\n return_intermediate_steps=True,\n handle_parsing_errors=True,\n max_iterations=max_iterations,\n )\n return initialize_agent(\n tools=tools,\n llm=llm,\n agent=agent,\n return_intermediate_steps=True,\n handle_parsing_errors=True,\n max_iterations=max_iterations,\n )\n",
"fileTypes": [],
"file_path": "",
"password": false,
@@ -251,7 +269,10 @@
"max_iterations": null,
"memory": null
},
- "output_types": ["AgentExecutor", "Callable"],
+ "output_types": [
+ "AgentExecutor",
+ "Callable"
+ ],
"field_formatters": {},
"pinned": false,
"beta": true
@@ -265,7 +286,10 @@
{
"id": "ChatOpenAISpecs-stxRM",
"type": "genericNode",
- "position": { "x": 18.226716205350385, "y": 432.6122491402193 },
+ "position": {
+ "x": 18.226716205350385,
+ "y": 432.6122491402193
+ },
"data": {
"type": "ChatOpenAISpecs",
"node": {
@@ -277,7 +301,7 @@
"list": false,
"show": true,
"multiline": true,
- "value": "from typing import Optional, Union\n\nfrom langchain.llms import BaseLLM\nfrom langchain_community.chat_models.openai import ChatOpenAI\nfrom langflow import CustomComponent\nfrom langflow.field_typing import BaseLanguageModel, NestedDict\n\n\nclass ChatOpenAIComponent(CustomComponent):\n display_name = \"ChatOpenAI\"\n description = \"`OpenAI` Chat large language models API.\"\n icon = \"OpenAI\"\n\n def build_config(self):\n return {\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": False,\n \"required\": False,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n \"required\": False,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"required\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": False,\n \"required\": False,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"advanced\": False,\n \"required\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"required\": False,\n \"value\": 0.7,\n },\n }\n\n def build(\n self,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n model_name: str = \"gpt-4-1106-preview\",\n openai_api_base: Optional[str] = None,\n openai_api_key: Optional[str] = None,\n temperature: float = 0.7,\n ) -> Union[BaseLanguageModel, BaseLLM]:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n return ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n",
+ "value": "from typing import Optional, Union\n\nfrom langchain.llms import BaseLLM\nfrom langchain_community.chat_models.openai import ChatOpenAI\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import BaseLanguageModel, NestedDict\n\n\nclass ChatOpenAIComponent(CustomComponent):\n display_name = \"ChatOpenAI\"\n description = \"`OpenAI` Chat large language models API.\"\n icon = \"OpenAI\"\n\n def build_config(self):\n return {\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": False,\n \"required\": False,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n \"required\": False,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"required\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": False,\n \"required\": False,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"advanced\": False,\n \"required\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"required\": False,\n \"value\": 0.7,\n },\n }\n\n def build(\n self,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n model_name: str = \"gpt-4-1106-preview\",\n openai_api_base: Optional[str] = None,\n openai_api_key: Optional[str] = None,\n temperature: float = 0.7,\n ) -> Union[BaseLanguageModel, BaseLLM]:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n return ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n",
"fileTypes": [],
"file_path": "",
"password": false,
@@ -348,7 +372,9 @@
"dynamic": false,
"info": "",
"title_case": false,
- "input_types": ["Text"]
+ "input_types": [
+ "Text"
+ ]
},
"openai_api_base": {
"type": "str",
@@ -366,7 +392,9 @@
"dynamic": false,
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.",
"title_case": false,
- "input_types": ["Text"]
+ "input_types": [
+ "Text"
+ ]
},
"openai_api_key": {
"type": "str",
@@ -384,7 +412,9 @@
"dynamic": false,
"info": "",
"title_case": false,
- "input_types": ["Text"]
+ "input_types": [
+ "Text"
+ ]
},
"temperature": {
"type": "float",
@@ -402,7 +432,11 @@
"advanced": false,
"dynamic": false,
"info": "",
- "rangeSpec": { "min": -1, "max": 1, "step": 0.1 },
+ "rangeSpec": {
+ "min": -1,
+ "max": 1,
+ "step": 0.1
+ },
"title_case": false
},
"_type": "CustomComponent"
@@ -428,7 +462,10 @@
"openai_api_key": null,
"temperature": null
},
- "output_types": ["BaseLanguageModel", "BaseLLM"],
+ "output_types": [
+ "BaseLanguageModel",
+ "BaseLLM"
+ ],
"field_formatters": {},
"pinned": false,
"beta": true
@@ -438,7 +475,10 @@
"selected": false,
"width": 384,
"height": 666,
- "positionAbsolute": { "x": 18.226716205350385, "y": 432.6122491402193 },
+ "positionAbsolute": {
+ "x": 18.226716205350385,
+ "y": 432.6122491402193
+ },
"dragging": false
}
],
@@ -469,7 +509,9 @@
"id": "ChatOpenAISpecs-stxRM"
}
},
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-ChatOpenAISpecs-stxRM{œbaseClassesœ:[œRunnableœ,œBaseLLMœ,œSerializableœ,œBaseLanguageModelœ,œobjectœ,œGenericœ,œRunnableSerializableœ],œdataTypeœ:œChatOpenAISpecsœ,œidœ:œChatOpenAISpecs-stxRMœ}-AgentInitializer-tPdJw{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-tPdJwœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}"
},
@@ -486,12 +528,17 @@
"type": "Tool"
},
"sourceHandle": {
- "baseClasses": ["BaseTool", "Tool"],
+ "baseClasses": [
+ "BaseTool",
+ "Tool"
+ ],
"dataType": "PythonFunctionTool",
"id": "PythonFunctionTool-RfJui"
}
},
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-PythonFunctionTool-RfJui{œbaseClassesœ:[œBaseToolœ,œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-RfJuiœ}-AgentInitializer-tPdJw{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-tPdJwœ,œinputTypesœ:null,œtypeœ:œToolœ}"
}
@@ -506,4 +553,4 @@
"name": "Untitled document (20)",
"last_tested_version": "0.7.0a0",
"is_component": false
-}
+}
\ No newline at end of file
diff --git a/src/frontend/tests/end-to-end/assets/flowtest.json b/src/frontend/tests/end-to-end/assets/flowtest.json
index 8b83ee270..6ef790455 100644
--- a/src/frontend/tests/end-to-end/assets/flowtest.json
+++ b/src/frontend/tests/end-to-end/assets/flowtest.json
@@ -8,7 +8,10 @@
"height": 461,
"id": "CustomComponent-MtJjl",
"type": "genericNode",
- "position": { "x": 534.3712097224906, "y": -135.01908566635723 },
+ "position": {
+ "x": 534.3712097224906,
+ "y": -135.01908566635723
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -20,7 +23,7 @@
"list": false,
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\nfrom langflow.field_typing import Data\nfrom pathlib import Path\nfrom platformdirs import user_cache_dir\nimport os\n\nclass Component(CustomComponent):\n documentation: str = \"http://docs.langflow.org/components/custom\"\n\n def build_config(self):\n return {\"text_input\":{\"display_name\":\"Text Input\", \"input_types\":[\"str\"]},\"save_path\":{\"display_name\":\"Save Path\",\n \"info\":\"Put the full path with the file name and extension\",\"value\":Path(user_cache_dir(\"langflow\"))/\"text.t1.txt\"}}\n\n def build(self, text_input:str,save_path:str) -> str:\n try:\n # Create the directory if it doesn't exist\n os.makedirs(os.path.dirname(save_path), exist_ok=True)\n\n # Open the file in write mode and save the text\n with open(save_path, 'w') as file:\n file.write(text_input)\n except Exception as e:\n raise e\n self.status = text_input\n return text_input",
+ "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import Data\nfrom pathlib import Path\nfrom platformdirs import user_cache_dir\nimport os\n\nclass Component(CustomComponent):\n documentation: str = \"http://docs.langflow.org/components/custom\"\n\n def build_config(self):\n return {\"text_input\":{\"display_name\":\"Text Input\", \"input_types\":[\"str\"]},\"save_path\":{\"display_name\":\"Save Path\",\n \"info\":\"Put the full path with the file name and extension\",\"value\":Path(user_cache_dir(\"langflow\"))/\"text.t1.txt\"}}\n\n def build(self, text_input:str,save_path:str) -> str:\n try:\n # Create the directory if it doesn't exist\n os.makedirs(os.path.dirname(save_path), exist_ok=True)\n\n # Open the file in write mode and save the text\n with open(save_path, 'w') as file:\n file.write(text_input)\n except Exception as e:\n raise e\n self.status = text_input\n return text_input",
"fileTypes": [],
"file_path": "",
"password": false,
@@ -59,18 +62,27 @@
"name": "text_input",
"display_name": "Text Input",
"advanced": false,
- "input_types": ["str"],
+ "input_types": [
+ "str"
+ ],
"dynamic": false,
"info": "",
"value": ""
},
"_type": "CustomComponent"
},
- "base_classes": ["str"],
+ "base_classes": [
+ "str"
+ ],
"display_name": "text checkpoint",
"documentation": "http://docs.langflow.org/components/custom",
- "custom_fields": { "save_path": null, "text_input": null },
- "output_types": ["str"],
+ "custom_fields": {
+ "save_path": null,
+ "text_input": null
+ },
+ "output_types": [
+ "str"
+ ],
"field_formatters": {},
"beta": true
},
@@ -78,14 +90,20 @@
},
"selected": false,
"dragging": false,
- "positionAbsolute": { "x": 534.3712097224906, "y": -135.01908566635723 }
+ "positionAbsolute": {
+ "x": 534.3712097224906,
+ "y": -135.01908566635723
+ }
},
{
"width": 384,
"height": 453,
"id": "CustomComponent-7NQoq",
"type": "genericNode",
- "position": { "x": 27.487979888011637, "y": -414.43998171034826 },
+ "position": {
+ "x": 27.487979888011637,
+ "y": -414.43998171034826
+ },
"data": {
"type": "CustomComponent",
"node": {
@@ -131,7 +149,7 @@
"list": false,
"show": true,
"multiline": true,
- "value": "from langflow import CustomComponent\nfrom typing import Optional, List, Dict, Union\nfrom langflow.field_typing import (\n AgentExecutor,\n BaseChatMemory,\n BaseLanguageModel,\n BaseLLM,\n BaseLoader,\n BaseMemory,\n BaseOutputParser,\n BasePromptTemplate,\n BaseRetriever,\n Callable,\n Chain,\n ChatPromptTemplate,\n Data,\n Document,\n Embeddings,\n NestedDict,\n Object,\n PromptTemplate,\n TextSplitter,\n Tool,\n VectorStore,\n)\n\nfrom openai import OpenAI\nimport os\nimport ffmpeg\n\nclass Component(CustomComponent):\n display_name: str = \"Whisper Transcriber\"\n description: str = \"Converts audio to text using OpenAI's Whisper.\"\n\n def build_config(self):\n return {\"audio\": {\"field_type\": \"file\", \"suffixes\": [\".mp3\", \".mp4\", \".m4a\"]}, \"OpenAIKey\": {\"field_type\": \"str\", \"password\": True}}\n\n def calculate_segment_duration(self, audio_path, target_chunk_size_mb=24):\n # Calculate the target chunk size in bytes\n target_chunk_size_bytes = target_chunk_size_mb * 1024 * 1024\n\n # Use ffprobe to get the audio file information\n ffprobe_output = ffmpeg.probe(audio_path)\n print(ffprobe_output)\n # Convert duration to float\n duration = float(ffprobe_output[\"format\"][\"duration\"])\n\n # Calculate the approximate bitrate\n bitrate = os.path.getsize(audio_path) / duration\n\n # Calculate the segment duration to achieve the target chunk size\n segment_duration = target_chunk_size_bytes / bitrate\n\n return segment_duration\n\n def split_audio_into_chunks(self, audio_path, target_chunk_size_mb=24):\n # Calculate the segment duration\n segment_duration = self.calculate_segment_duration(audio_path, target_chunk_size_mb)\n\n # Create a directory to store the chunks\n output_directory = f\"{os.path.splitext(audio_path)[0]}_chunks\"\n os.makedirs(output_directory, exist_ok=True)\n\n # Use ffmpeg-python to split the audio file into chunks\n (\n ffmpeg.input(audio_path)\n .output(f\"{output_directory}/%03d{os.path.splitext(audio_path)[1]}\", codec=\"copy\", f=\"segment\", segment_time=segment_duration)\n .run()\n )\n\n # Get the list of generated chunk files\n chunks = [os.path.join(output_directory, file) for file in os.listdir(output_directory)]\n\n return chunks\n\n def build(self, audio: str, OpenAIKey: str) -> str:\n # Split audio into chunks\n audio_chunks = self.split_audio_into_chunks(audio)\n\n client = OpenAI(api_key=OpenAIKey)\n transcripts = []\n\n try:\n for chunk in audio_chunks:\n with open(chunk, \"rb\") as chunk_file:\n transcript = client.audio.transcriptions.create(\n model=\"whisper-1\",\n file=chunk_file,\n response_format=\"text\"\n )\n transcripts.append(transcript)\n finally:\n # Clean up temporary chunk files\n for chunk in audio_chunks:\n os.remove(chunk)\n\n # Concatenate transcripts into the final response\n final_response = \"\\n\".join(transcripts)\n self.status = final_response\n return final_response\n",
+ "value": "from langflow.custom import CustomComponent\nfrom typing import Optional, List, Dict, Union\nfrom langflow.field_typing import (\n AgentExecutor,\n BaseChatMemory,\n BaseLanguageModel,\n BaseLLM,\n BaseLoader,\n BaseMemory,\n BaseOutputParser,\n BasePromptTemplate,\n BaseRetriever,\n Callable,\n Chain,\n ChatPromptTemplate,\n Data,\n Document,\n Embeddings,\n NestedDict,\n Object,\n PromptTemplate,\n TextSplitter,\n Tool,\n VectorStore,\n)\n\nfrom openai import OpenAI\nimport os\nimport ffmpeg\n\nclass Component(CustomComponent):\n display_name: str = \"Whisper Transcriber\"\n description: str = \"Converts audio to text using OpenAI's Whisper.\"\n\n def build_config(self):\n return {\"audio\": {\"field_type\": \"file\", \"suffixes\": [\".mp3\", \".mp4\", \".m4a\"]}, \"OpenAIKey\": {\"field_type\": \"str\", \"password\": True}}\n\n def calculate_segment_duration(self, audio_path, target_chunk_size_mb=24):\n # Calculate the target chunk size in bytes\n target_chunk_size_bytes = target_chunk_size_mb * 1024 * 1024\n\n # Use ffprobe to get the audio file information\n ffprobe_output = ffmpeg.probe(audio_path)\n print(ffprobe_output)\n # Convert duration to float\n duration = float(ffprobe_output[\"format\"][\"duration\"])\n\n # Calculate the approximate bitrate\n bitrate = os.path.getsize(audio_path) / duration\n\n # Calculate the segment duration to achieve the target chunk size\n segment_duration = target_chunk_size_bytes / bitrate\n\n return segment_duration\n\n def split_audio_into_chunks(self, audio_path, target_chunk_size_mb=24):\n # Calculate the segment duration\n segment_duration = self.calculate_segment_duration(audio_path, target_chunk_size_mb)\n\n # Create a directory to store the chunks\n output_directory = f\"{os.path.splitext(audio_path)[0]}_chunks\"\n os.makedirs(output_directory, exist_ok=True)\n\n # Use ffmpeg-python to split the audio file into chunks\n (\n ffmpeg.input(audio_path)\n .output(f\"{output_directory}/%03d{os.path.splitext(audio_path)[1]}\", codec=\"copy\", f=\"segment\", segment_time=segment_duration)\n .run()\n )\n\n # Get the list of generated chunk files\n chunks = [os.path.join(output_directory, file) for file in os.listdir(output_directory)]\n\n return chunks\n\n def build(self, audio: str, OpenAIKey: str) -> str:\n # Split audio into chunks\n audio_chunks = self.split_audio_into_chunks(audio)\n\n client = OpenAI(api_key=OpenAIKey)\n transcripts = []\n\n try:\n for chunk in audio_chunks:\n with open(chunk, \"rb\") as chunk_file:\n transcript = client.audio.transcriptions.create(\n model=\"whisper-1\",\n file=chunk_file,\n response_format=\"text\"\n )\n transcripts.append(transcript)\n finally:\n # Clean up temporary chunk files\n for chunk in audio_chunks:\n os.remove(chunk)\n\n # Concatenate transcripts into the final response\n final_response = \"\\n\".join(transcripts)\n self.status = final_response\n return final_response\n",
"fileTypes": [],
"file_path": "",
"password": false,
@@ -143,11 +161,18 @@
"_type": "CustomComponent"
},
"description": "Converts audio to text using OpenAI's Whisper.",
- "base_classes": ["str"],
+ "base_classes": [
+ "str"
+ ],
"display_name": "Whisper Transcriber",
"documentation": "",
- "custom_fields": { "OpenAIKey": null, "audio": null },
- "output_types": ["str"],
+ "custom_fields": {
+ "OpenAIKey": null,
+ "audio": null
+ },
+ "output_types": [
+ "str"
+ ],
"field_formatters": {},
"beta": true
},
@@ -171,26 +196,36 @@
"targetHandle": {
"fieldName": "text_input",
"id": "CustomComponent-MtJjl",
- "inputTypes": ["str"],
+ "inputTypes": [
+ "str"
+ ],
"type": "str"
},
"sourceHandle": {
- "baseClasses": ["str"],
+ "baseClasses": [
+ "str"
+ ],
"dataType": "CustomComponent",
"id": "CustomComponent-7NQoq"
}
},
- "style": { "stroke": "#555" },
+ "style": {
+ "stroke": "#555"
+ },
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-CustomComponent-7NQoq{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-7NQoqœ}-CustomComponent-MtJjl{œfieldNameœ:œtext_inputœ,œidœ:œCustomComponent-MtJjlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}"
}
],
- "viewport": { "x": 119.37759169012509, "y": 351.3082742479685, "zoom": 1 }
+ "viewport": {
+ "x": 119.37759169012509,
+ "y": 351.3082742479685,
+ "zoom": 1
+ }
},
"is_component": false,
"updated_at": "2023-12-13T23:51:56.874099",
"folder": null,
"id": "1b0814b7-2964-4e09-9b4b-f7413c4fb50b",
"user_id": "8b5cf798-f1b8-4108-88fd-d7274d08d471"
-}
+}
\ No newline at end of file
diff --git a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts
index 31afd7614..52f8da0a1 100644
--- a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts
+++ b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts
@@ -195,4 +195,66 @@ test("dropDownComponent", async ({ page }) => {
if (value !== "ai21.j2-ultra-v1") {
expect(false).toBeTruthy();
}
-});
+ await page.getByTestId("code-button-modal").click();
+ await page
+ .locator("#CodeEditor div")
+ .filter({ hasText: "from typing import" })
+ .nth(1)
+ .click();
+ await page.locator("textarea").press("Control+a");
+ const emptyOptionsCode = `from typing import Optional
+from langchain.llms.base import BaseLLM
+from langchain_community.llms.bedrock import Bedrock
+
+from langflow.interface.custom.custom_component import CustomComponent
+
+
+class AmazonBedrockComponent(CustomComponent):
+ display_name: str = "Amazon Bedrock"
+ description: str = "LLM model from Amazon Bedrock."
+ icon = "Amazon"
+
+ def build_config(self):
+ return {
+ "model_id": {
+ "display_name": "Model Id",
+ "options": [],
+ },
+ "credentials_profile_name": {"display_name": "Credentials Profile Name"},
+ "streaming": {"display_name": "Streaming", "field_type": "bool"},
+ "endpoint_url": {"display_name": "Endpoint URL"},
+ "region_name": {"display_name": "Region Name"},
+ "model_kwargs": {"display_name": "Model Kwargs"},
+ "cache": {"display_name": "Cache"},
+ "code": {"advanced": True},
+ }
+
+ def build(
+ self,
+ model_id: str = "anthropic.claude-instant-v1",
+ credentials_profile_name: Optional[str] = None,
+ region_name: Optional[str] = None,
+ model_kwargs: Optional[dict] = None,
+ endpoint_url: Optional[str] = None,
+ streaming: bool = False,
+ cache: Optional[bool] = None,
+ ) -> BaseLLM:
+ try:
+ output = Bedrock(
+ credentials_profile_name=credentials_profile_name,
+ model_id=model_id,
+ region_name=region_name,
+ model_kwargs=model_kwargs,
+ endpoint_url=endpoint_url,
+ streaming=streaming,
+ cache=cache,
+ ) # type: ignore
+ except Exception as e:
+ raise ValueError("Could not connect to AmazonBedrock API.") from e
+ return output
+
+ `;
+ await page.locator("textarea").fill(emptyOptionsCode);
+ await page.getByRole('button', { name: 'Check & Save' }).click();
+ await page.getByText("No parameters are available for display.").isVisible();
+})
diff --git a/src/frontend/tests/end-to-end/inputComponent.spec.ts b/src/frontend/tests/end-to-end/inputComponent.spec.ts
index a5aea8fa2..002a0e0cb 100644
--- a/src/frontend/tests/end-to-end/inputComponent.spec.ts
+++ b/src/frontend/tests/end-to-end/inputComponent.spec.ts
@@ -120,7 +120,7 @@ test("InputComponent", async ({ page }) => {
await page.getByTestId("input-collection_name-edit").click();
await page
.getByTestId("input-collection_name-edit")
- .fill("NEW_collection_name_test_123123123!@#$&*(&%$@");
+ .fill("NEW_collection_name_test_123123123!@#$&*(&%$@ÇÇÇÀõe");
await page.locator('//*[@id="saveChangesBtn"]').click();
@@ -143,7 +143,7 @@ test("InputComponent", async ({ page }) => {
let value = await page.getByTestId("input-collection_name").inputValue();
- if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@") {
+ if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@ÇÇÇÀõe") {
expect(false).toBeTruthy();
}
}
diff --git a/tests/conftest.py b/tests/conftest.py
index 7708340c9..83c7d031d 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -10,10 +10,6 @@ import orjson
import pytest
from fastapi.testclient import TestClient
from httpx import AsyncClient
-from sqlmodel import Session, SQLModel, create_engine, select
-from sqlmodel.pool import StaticPool
-from typer.testing import CliRunner
-
from langflow.graph.graph.base import Graph
from langflow.initial_setup.setup import STARTER_FOLDER_NAME
from langflow.services.auth.utils import get_password_hash
@@ -22,6 +18,9 @@ from langflow.services.database.models.flow.model import Flow, FlowCreate
from langflow.services.database.models.user.model import User, UserCreate
from langflow.services.database.utils import session_getter
from langflow.services.deps import get_db_service
+from sqlmodel import Session, SQLModel, create_engine, select
+from sqlmodel.pool import StaticPool
+from typer.testing import CliRunner
if TYPE_CHECKING:
from langflow.services.database.service import DatabaseService
@@ -263,7 +262,7 @@ def active_user(client):
is_superuser=False,
)
# check if user exists
- if active_user := session.query(User).filter(User.username == user.username).first():
+ if active_user := session.exec(select(User).where(User.username == user.username)).first():
return active_user
session.add(user)
session.commit()
@@ -368,7 +367,7 @@ def created_api_key(active_user):
)
db_manager = get_db_service()
with session_getter(db_manager) as session:
- if existing_api_key := session.query(ApiKey).filter(ApiKey.api_key == api_key.api_key).first():
+ if existing_api_key := session.exec(select(ApiKey).where(ApiKey.api_key == api_key.api_key)).first():
return existing_api_key
session.add(api_key)
session.commit()
diff --git a/tests/data/ChatInputTest.json b/tests/data/ChatInputTest.json
index 24771bab9..3c516067e 100644
--- a/tests/data/ChatInputTest.json
+++ b/tests/data/ChatInputTest.json
@@ -1 +1,918 @@
-{"name":"ChatInputTest","description":"","data":{"nodes":[{"width":384,"height":359,"id":"PromptTemplate-IKKOx","type":"genericNode","position":{"x":880,"y":646.9375},"data":{"type":"PromptTemplate","node":{"template":{"output_parser":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"output_parser","advanced":false,"dynamic":false,"info":"","type":"BaseOutputParser","list":false},"input_variables":{"required":true,"placeholder":"","show":false,"multiline":false,"password":false,"name":"input_variables","advanced":false,"dynamic":false,"info":"","type":"str","list":true,"value":["input"]},"partial_variables":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"partial_variables","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"template":{"required":true,"placeholder":"","show":true,"multiline":true,"password":false,"name":"template","advanced":false,"dynamic":false,"info":"","type":"prompt","list":false,"value":"Input: {input}\nAI:"},"template_format":{"required":false,"placeholder":"","show":false,"multiline":false,"value":"f-string","password":false,"name":"template_format","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"validate_template":{"required":false,"placeholder":"","show":false,"multiline":false,"value":true,"password":false,"name":"validate_template","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"_type":"PromptTemplate","input":{"required":false,"placeholder":"","show":true,"multiline":true,"value":"","password":false,"name":"input","display_name":"input","advanced":false,"input_types":["Document","BaseOutputParser","str"],"dynamic":false,"info":"","type":"str","list":false}},"description":"A prompt template for a language model.","base_classes":["BasePromptTemplate","PromptTemplate","StringPromptTemplate"],"name":"","display_name":"PromptTemplate","documentation":"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/","custom_fields":{"":["input"],"template":["input"]},"output_types":[],"field_formatters":{"formatters":{"openai_api_key":{}},"base_formatters":{"kwargs":{},"optional":{},"list":{},"dict":{},"union":{},"multiline":{},"show":{},"password":{},"default":{},"headers":{},"dict_code_file":{},"model_fields":{"MODEL_DICT":{"OpenAI":["text-davinci-003","text-davinci-002","text-curie-001","text-babbage-001","text-ada-001"],"ChatOpenAI":["gpt-3.5-turbo-0613","gpt-3.5-turbo","gpt-3.5-turbo-16k-0613","gpt-3.5-turbo-16k","gpt-4-0613","gpt-4-32k-0613","gpt-4","gpt-4-32k"],"Anthropic":["claude-v1","claude-v1-100k","claude-instant-v1","claude-instant-v1-100k","claude-v1.3","claude-v1.3-100k","claude-v1.2","claude-v1.0","claude-instant-v1.1","claude-instant-v1.1-100k","claude-instant-v1.0"],"ChatAnthropic":["claude-v1","claude-v1-100k","claude-instant-v1","claude-instant-v1-100k","claude-v1.3","claude-v1.3-100k","claude-v1.2","claude-v1.0","claude-instant-v1.1","claude-instant-v1.1-100k","claude-instant-v1.0"]}}}},"beta":false,"error":null},"id":"PromptTemplate-IKKOx"},"selected":false,"positionAbsolute":{"x":880,"y":646.9375},"dragging":false},{"width":384,"height":307,"id":"LLMChain-e2dhN","type":"genericNode","position":{"x":1449.330344958542,"y":880.1760221487797},"data":{"type":"LLMChain","node":{"template":{"callbacks":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"callbacks","advanced":false,"dynamic":false,"info":"","type":"langchain.callbacks.base.BaseCallbackHandler","list":true},"llm":{"required":true,"placeholder":"","show":true,"multiline":false,"password":false,"name":"llm","advanced":false,"dynamic":false,"info":"","type":"BaseLanguageModel","list":false},"memory":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"memory","advanced":false,"dynamic":false,"info":"","type":"BaseMemory","list":false},"output_parser":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"output_parser","advanced":false,"dynamic":false,"info":"","type":"BaseLLMOutputParser","list":false},"prompt":{"required":true,"placeholder":"","show":true,"multiline":false,"password":false,"name":"prompt","advanced":false,"dynamic":false,"info":"","type":"BasePromptTemplate","list":false},"llm_kwargs":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"llm_kwargs","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"metadata":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"metadata","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"output_key":{"required":true,"placeholder":"","show":true,"multiline":false,"value":"text","password":false,"name":"output_key","advanced":true,"dynamic":false,"info":"","type":"str","list":false},"return_final_only":{"required":false,"placeholder":"","show":false,"multiline":false,"value":true,"password":false,"name":"return_final_only","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"tags":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"tags","advanced":false,"dynamic":false,"info":"","type":"str","list":true},"verbose":{"required":false,"placeholder":"","show":false,"multiline":false,"value":false,"password":false,"name":"verbose","advanced":true,"dynamic":false,"info":"","type":"bool","list":false},"_type":"LLMChain"},"description":"Chain to run queries against LLMs.","base_classes":["Chain","LLMChain","function","Text"],"display_name":"LLMChain","custom_fields":{},"output_types":[],"documentation":"https://python.langchain.com/docs/modules/chains/foundational/llm_chain","beta":false,"error":null},"id":"LLMChain-e2dhN"},"positionAbsolute":{"x":1449.330344958542,"y":880.1760221487797}},{"width":384,"height":621,"id":"ChatOpenAI-2I57f","type":"genericNode","position":{"x":393.3551923753797,"y":1061.025177453298},"data":{"type":"ChatOpenAI","node":{"template":{"callbacks":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"callbacks","advanced":false,"dynamic":false,"info":"","type":"langchain.callbacks.base.BaseCallbackHandler","list":true},"cache":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"cache","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"client":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"client","advanced":false,"dynamic":false,"info":"","type":"Any","list":false},"max_retries":{"required":false,"placeholder":"","show":false,"multiline":false,"value":6,"password":false,"name":"max_retries","advanced":false,"dynamic":false,"info":"","type":"int","list":false},"max_tokens":{"required":false,"placeholder":"","show":true,"multiline":false,"password":true,"name":"max_tokens","advanced":false,"dynamic":false,"info":"","type":"int","list":false,"value":""},"metadata":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"metadata","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"model_kwargs":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"model_kwargs","advanced":true,"dynamic":false,"info":"","type":"code","list":false},"model_name":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"gpt-3.5-turbo-0613","password":false,"options":["gpt-3.5-turbo-0613","gpt-3.5-turbo","gpt-3.5-turbo-16k-0613","gpt-3.5-turbo-16k","gpt-4-0613","gpt-4-32k-0613","gpt-4","gpt-4-32k"],"name":"model_name","advanced":false,"dynamic":false,"info":"","type":"str","list":true},"n":{"required":false,"placeholder":"","show":false,"multiline":false,"value":1,"password":false,"name":"n","advanced":false,"dynamic":false,"info":"","type":"int","list":false},"openai_api_base":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"openai_api_base","display_name":"OpenAI API Base","advanced":false,"dynamic":false,"info":"\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n","type":"str","list":false},"openai_api_key":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"","password":true,"name":"openai_api_key","display_name":"OpenAI API Key","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"openai_organization":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"openai_organization","display_name":"OpenAI Organization","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"openai_proxy":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"openai_proxy","display_name":"OpenAI Proxy","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"request_timeout":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"request_timeout","advanced":false,"dynamic":false,"info":"","type":"float","list":false},"streaming":{"required":false,"placeholder":"","show":false,"multiline":false,"value":false,"password":false,"name":"streaming","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"tags":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"tags","advanced":false,"dynamic":false,"info":"","type":"str","list":true},"temperature":{"required":false,"placeholder":"","show":true,"multiline":false,"value":0.7,"password":false,"name":"temperature","advanced":false,"dynamic":false,"info":"","type":"float","list":false},"tiktoken_model_name":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"tiktoken_model_name","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"verbose":{"required":false,"placeholder":"","show":false,"multiline":false,"value":false,"password":false,"name":"verbose","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"_type":"ChatOpenAI"},"description":"`OpenAI` Chat large language models API.","base_classes":["BaseChatModel","ChatOpenAI","BaseLanguageModel","BaseLLM"],"display_name":"ChatOpenAI","custom_fields":{},"output_types":[],"documentation":"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai","beta":false,"error":null},"id":"ChatOpenAI-2I57f"},"selected":false,"positionAbsolute":{"x":393.3551923753797,"y":1061.025177453298},"dragging":false},{"width":384,"height":359,"id":"ChatInput-207IY","type":"genericNode","position":{"x":415.1018926651509,"y":506.62736462360317},"data":{"type":"ChatInput","node":{"template":{"code":{"dynamic":true,"required":true,"placeholder":"","show":false,"multiline":true,"value":"from typing import Optional\nfrom langflow import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n","password":false,"name":"code","advanced":false,"type":"code","list":false},"_type":"CustomComponent","message":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"","password":false,"name":"message","display_name":"message","advanced":false,"dynamic":false,"info":"","type":"str","list":false}},"description":"Used to get user input from the chat.","base_classes":["str"],"display_name":"Chat Input","custom_fields":{"message":null},"output_types":["ChatInput"],"documentation":"","beta":true,"error":null},"id":"ChatInput-207IY"},"positionAbsolute":{"x":415.1018926651509,"y":506.62736462360317}},{"width":384,"height":389,"id":"ChatOutput-1jlJy","type":"genericNode","position":{"x":2002.8008888732943,"y":926.1397178702218},"data":{"type":"ChatOutput","node":{"template":{"code":{"dynamic":true,"required":true,"placeholder":"","show":true,"multiline":true,"value":"from typing import Optional, Text\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n description = \"Used to send a message to the chat.\"\n\n field_config = {\n \"code\": {\n \"show\": False,\n }\n }\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"Text\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n self.repr_value = message\n return message\n","password":false,"name":"code","advanced":false,"type":"code","list":false},"_type":"CustomComponent","is_ai":{"required":true,"placeholder":"","show":true,"multiline":false,"value":true,"password":false,"name":"is_ai","display_name":"is_ai","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"message":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"message","display_name":"message","advanced":false,"input_types":["Text"],"dynamic":false,"info":"","type":"Text","list":false}},"description":"Used to send a message to the chat.","base_classes":["str"],"display_name":"Chat Output","custom_fields":{"is_ai":null,"message":null},"output_types":["ChatOutput"],"documentation":"","beta":true,"error":null},"id":"ChatOutput-1jlJy"},"selected":true,"dragging":false,"positionAbsolute":{"x":2002.8008888732943,"y":926.1397178702218}}],"edges":[{"source":"PromptTemplate-IKKOx","sourceHandle":"PromptTemplate|PromptTemplate-IKKOx|BasePromptTemplate|PromptTemplate|StringPromptTemplate","target":"LLMChain-e2dhN","targetHandle":"BasePromptTemplate|prompt|LLMChain-e2dhN","style":{"stroke":"#555"},"className":"","animated":false,"id":"reactflow__edge-PromptTemplate-IKKOxPromptTemplate|PromptTemplate-IKKOx|StringPromptTemplate|BasePromptTemplate|PromptTemplate-LLMChain-e2dhNBasePromptTemplate|prompt|LLMChain-e2dhN"},{"source":"ChatOpenAI-2I57f","sourceHandle":"ChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM","target":"LLMChain-e2dhN","targetHandle":"BaseLanguageModel|llm|LLMChain-e2dhN","style":{"stroke":"#555"},"className":"","animated":false,"id":"reactflow__edge-ChatOpenAI-2I57fChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM-LLMChain-e2dhNBaseLanguageModel|llm|LLMChain-e2dhN"},{"source":"ChatInput-207IY","sourceHandle":"ChatInput|ChatInput-207IY|str","target":"PromptTemplate-IKKOx","targetHandle":"Document;BaseOutputParser;str|input|PromptTemplate-IKKOx","style":{"stroke":"#555"},"className":"","animated":false,"id":"reactflow__edge-ChatInput-207IYChatInput|ChatInput-207IY|str-PromptTemplate-IKKOxDocument;BaseOutputParser;str|input|PromptTemplate-IKKOx"},{"source":"LLMChain-e2dhN","sourceHandle":"LLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text","target":"ChatOutput-1jlJy","targetHandle":"Text|message|ChatOutput-1jlJy","style":{"stroke":"#555"},"className":"stroke-foreground stroke-connection","animated":true,"id":"reactflow__edge-LLMChain-e2dhNLLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text-ChatOutput-1jlJyText|message|ChatOutput-1jlJy"}],"viewport":{"x":-141.98308184453367,"y":-104.98637616656356,"zoom":0.4788209787464315}},"id":"b3388ab9-b5dc-4447-b560-79caef40faa5","user_id":"c65bfea3-3eea-4e71-8fc4-106238eb0583"}
\ No newline at end of file
+{
+ "name": "ChatInputTest",
+ "description": "",
+ "data": {
+ "nodes": [
+ {
+ "width": 384,
+ "height": 359,
+ "id": "PromptTemplate-IKKOx",
+ "type": "genericNode",
+ "position": {
+ "x": 880,
+ "y": 646.9375
+ },
+ "data": {
+ "type": "PromptTemplate",
+ "node": {
+ "template": {
+ "output_parser": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "output_parser",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseOutputParser",
+ "list": false
+ },
+ "input_variables": {
+ "required": true,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "input_variables",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true,
+ "value": [
+ "input"
+ ]
+ },
+ "partial_variables": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "partial_variables",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "template": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "password": false,
+ "name": "template",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "prompt",
+ "list": false,
+ "value": "Input: {input}\nAI:"
+ },
+ "template_format": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": "f-string",
+ "password": false,
+ "name": "template_format",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "validate_template": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": true,
+ "password": false,
+ "name": "validate_template",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "PromptTemplate",
+ "input": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "value": "",
+ "password": false,
+ "name": "input",
+ "display_name": "input",
+ "advanced": false,
+ "input_types": [
+ "Document",
+ "BaseOutputParser",
+ "str"
+ ],
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ }
+ },
+ "description": "A prompt template for a language model.",
+ "base_classes": [
+ "BasePromptTemplate",
+ "PromptTemplate",
+ "StringPromptTemplate"
+ ],
+ "name": "",
+ "display_name": "PromptTemplate",
+ "documentation": "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/",
+ "custom_fields": {
+ "": [
+ "input"
+ ],
+ "template": [
+ "input"
+ ]
+ },
+ "output_types": [],
+ "field_formatters": {
+ "formatters": {
+ "openai_api_key": {}
+ },
+ "base_formatters": {
+ "kwargs": {},
+ "optional": {},
+ "list": {},
+ "dict": {},
+ "union": {},
+ "multiline": {},
+ "show": {},
+ "password": {},
+ "default": {},
+ "headers": {},
+ "dict_code_file": {},
+ "model_fields": {
+ "MODEL_DICT": {
+ "OpenAI": [
+ "text-davinci-003",
+ "text-davinci-002",
+ "text-curie-001",
+ "text-babbage-001",
+ "text-ada-001"
+ ],
+ "ChatOpenAI": [
+ "gpt-3.5-turbo-0613",
+ "gpt-3.5-turbo",
+ "gpt-3.5-turbo-16k-0613",
+ "gpt-3.5-turbo-16k",
+ "gpt-4-0613",
+ "gpt-4-32k-0613",
+ "gpt-4",
+ "gpt-4-32k"
+ ],
+ "Anthropic": [
+ "claude-v1",
+ "claude-v1-100k",
+ "claude-instant-v1",
+ "claude-instant-v1-100k",
+ "claude-v1.3",
+ "claude-v1.3-100k",
+ "claude-v1.2",
+ "claude-v1.0",
+ "claude-instant-v1.1",
+ "claude-instant-v1.1-100k",
+ "claude-instant-v1.0"
+ ],
+ "ChatAnthropic": [
+ "claude-v1",
+ "claude-v1-100k",
+ "claude-instant-v1",
+ "claude-instant-v1-100k",
+ "claude-v1.3",
+ "claude-v1.3-100k",
+ "claude-v1.2",
+ "claude-v1.0",
+ "claude-instant-v1.1",
+ "claude-instant-v1.1-100k",
+ "claude-instant-v1.0"
+ ]
+ }
+ }
+ }
+ },
+ "beta": false,
+ "error": null
+ },
+ "id": "PromptTemplate-IKKOx"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 880,
+ "y": 646.9375
+ },
+ "dragging": false
+ },
+ {
+ "width": 384,
+ "height": 307,
+ "id": "LLMChain-e2dhN",
+ "type": "genericNode",
+ "position": {
+ "x": 1449.330344958542,
+ "y": 880.1760221487797
+ },
+ "data": {
+ "type": "LLMChain",
+ "node": {
+ "template": {
+ "callbacks": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "callbacks",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "langchain.callbacks.base.BaseCallbackHandler",
+ "list": true
+ },
+ "llm": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "llm",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseLanguageModel",
+ "list": false
+ },
+ "memory": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "memory",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseMemory",
+ "list": false
+ },
+ "output_parser": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "output_parser",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseLLMOutputParser",
+ "list": false
+ },
+ "prompt": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "prompt",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BasePromptTemplate",
+ "list": false
+ },
+ "llm_kwargs": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "llm_kwargs",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "metadata": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "metadata",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "output_key": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "text",
+ "password": false,
+ "name": "output_key",
+ "advanced": true,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "return_final_only": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": true,
+ "password": false,
+ "name": "return_final_only",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "tags": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "tags",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true
+ },
+ "verbose": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "verbose",
+ "advanced": true,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "LLMChain"
+ },
+ "description": "Chain to run queries against LLMs.",
+ "base_classes": [
+ "Chain",
+ "LLMChain",
+ "function",
+ "Text"
+ ],
+ "display_name": "LLMChain",
+ "custom_fields": {},
+ "output_types": [],
+ "documentation": "https://python.langchain.com/docs/modules/chains/foundational/llm_chain",
+ "beta": false,
+ "error": null
+ },
+ "id": "LLMChain-e2dhN"
+ },
+ "positionAbsolute": {
+ "x": 1449.330344958542,
+ "y": 880.1760221487797
+ }
+ },
+ {
+ "width": 384,
+ "height": 621,
+ "id": "ChatOpenAI-2I57f",
+ "type": "genericNode",
+ "position": {
+ "x": 393.3551923753797,
+ "y": 1061.025177453298
+ },
+ "data": {
+ "type": "ChatOpenAI",
+ "node": {
+ "template": {
+ "callbacks": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "callbacks",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "langchain.callbacks.base.BaseCallbackHandler",
+ "list": true
+ },
+ "cache": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "cache",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "client": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "client",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "Any",
+ "list": false
+ },
+ "max_retries": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": 6,
+ "password": false,
+ "name": "max_retries",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "int",
+ "list": false
+ },
+ "max_tokens": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": true,
+ "name": "max_tokens",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "int",
+ "list": false,
+ "value": ""
+ },
+ "metadata": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "metadata",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "model_kwargs": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "model_kwargs",
+ "advanced": true,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "model_name": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "gpt-3.5-turbo-0613",
+ "password": false,
+ "options": [
+ "gpt-3.5-turbo-0613",
+ "gpt-3.5-turbo",
+ "gpt-3.5-turbo-16k-0613",
+ "gpt-3.5-turbo-16k",
+ "gpt-4-0613",
+ "gpt-4-32k-0613",
+ "gpt-4",
+ "gpt-4-32k"
+ ],
+ "name": "model_name",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true
+ },
+ "n": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": 1,
+ "password": false,
+ "name": "n",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "int",
+ "list": false
+ },
+ "openai_api_base": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "openai_api_base",
+ "display_name": "OpenAI API Base",
+ "advanced": false,
+ "dynamic": false,
+ "info": "\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n",
+ "type": "str",
+ "list": false
+ },
+ "openai_api_key": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "",
+ "password": true,
+ "name": "openai_api_key",
+ "display_name": "OpenAI API Key",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "openai_organization": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "openai_organization",
+ "display_name": "OpenAI Organization",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "openai_proxy": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "openai_proxy",
+ "display_name": "OpenAI Proxy",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "request_timeout": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "request_timeout",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "float",
+ "list": false
+ },
+ "streaming": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "streaming",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "tags": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "tags",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true
+ },
+ "temperature": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": 0.7,
+ "password": false,
+ "name": "temperature",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "float",
+ "list": false
+ },
+ "tiktoken_model_name": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "tiktoken_model_name",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "verbose": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "verbose",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "ChatOpenAI"
+ },
+ "description": "`OpenAI` Chat large language models API.",
+ "base_classes": [
+ "BaseChatModel",
+ "ChatOpenAI",
+ "BaseLanguageModel",
+ "BaseLLM"
+ ],
+ "display_name": "ChatOpenAI",
+ "custom_fields": {},
+ "output_types": [],
+ "documentation": "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai",
+ "beta": false,
+ "error": null
+ },
+ "id": "ChatOpenAI-2I57f"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 393.3551923753797,
+ "y": 1061.025177453298
+ },
+ "dragging": false
+ },
+ {
+ "width": 384,
+ "height": 359,
+ "id": "ChatInput-207IY",
+ "type": "genericNode",
+ "position": {
+ "x": 415.1018926651509,
+ "y": 506.62736462360317
+ },
+ "data": {
+ "type": "ChatInput",
+ "node": {
+ "template": {
+ "code": {
+ "dynamic": true,
+ "required": true,
+ "placeholder": "",
+ "show": false,
+ "multiline": true,
+ "value": "from typing import Optional\nfrom langflow.custom import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n",
+ "password": false,
+ "name": "code",
+ "advanced": false,
+ "type": "code",
+ "list": false
+ },
+ "_type": "CustomComponent",
+ "message": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "",
+ "password": false,
+ "name": "message",
+ "display_name": "message",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ }
+ },
+ "description": "Used to get user input from the chat.",
+ "base_classes": [
+ "str"
+ ],
+ "display_name": "Chat Input",
+ "custom_fields": {
+ "message": null
+ },
+ "output_types": [
+ "ChatInput"
+ ],
+ "documentation": "",
+ "beta": true,
+ "error": null
+ },
+ "id": "ChatInput-207IY"
+ },
+ "positionAbsolute": {
+ "x": 415.1018926651509,
+ "y": 506.62736462360317
+ }
+ },
+ {
+ "width": 384,
+ "height": 389,
+ "id": "ChatOutput-1jlJy",
+ "type": "genericNode",
+ "position": {
+ "x": 2002.8008888732943,
+ "y": 926.1397178702218
+ },
+ "data": {
+ "type": "ChatOutput",
+ "node": {
+ "template": {
+ "code": {
+ "dynamic": true,
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "value": "from typing import Optional, Text\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow.custom import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n description = \"Used to send a message to the chat.\"\n\n field_config = {\n \"code\": {\n \"show\": False,\n }\n }\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"Text\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n self.repr_value = message\n return message\n",
+ "password": false,
+ "name": "code",
+ "advanced": false,
+ "type": "code",
+ "list": false
+ },
+ "_type": "CustomComponent",
+ "is_ai": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": true,
+ "password": false,
+ "name": "is_ai",
+ "display_name": "is_ai",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "message": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "message",
+ "display_name": "message",
+ "advanced": false,
+ "input_types": [
+ "Text"
+ ],
+ "dynamic": false,
+ "info": "",
+ "type": "Text",
+ "list": false
+ }
+ },
+ "description": "Used to send a message to the chat.",
+ "base_classes": [
+ "str"
+ ],
+ "display_name": "Chat Output",
+ "custom_fields": {
+ "is_ai": null,
+ "message": null
+ },
+ "output_types": [
+ "ChatOutput"
+ ],
+ "documentation": "",
+ "beta": true,
+ "error": null
+ },
+ "id": "ChatOutput-1jlJy"
+ },
+ "selected": true,
+ "dragging": false,
+ "positionAbsolute": {
+ "x": 2002.8008888732943,
+ "y": 926.1397178702218
+ }
+ }
+ ],
+ "edges": [
+ {
+ "source": "PromptTemplate-IKKOx",
+ "sourceHandle": "PromptTemplate|PromptTemplate-IKKOx|BasePromptTemplate|PromptTemplate|StringPromptTemplate",
+ "target": "LLMChain-e2dhN",
+ "targetHandle": "BasePromptTemplate|prompt|LLMChain-e2dhN",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "",
+ "animated": false,
+ "id": "reactflow__edge-PromptTemplate-IKKOxPromptTemplate|PromptTemplate-IKKOx|StringPromptTemplate|BasePromptTemplate|PromptTemplate-LLMChain-e2dhNBasePromptTemplate|prompt|LLMChain-e2dhN"
+ },
+ {
+ "source": "ChatOpenAI-2I57f",
+ "sourceHandle": "ChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM",
+ "target": "LLMChain-e2dhN",
+ "targetHandle": "BaseLanguageModel|llm|LLMChain-e2dhN",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "",
+ "animated": false,
+ "id": "reactflow__edge-ChatOpenAI-2I57fChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM-LLMChain-e2dhNBaseLanguageModel|llm|LLMChain-e2dhN"
+ },
+ {
+ "source": "ChatInput-207IY",
+ "sourceHandle": "ChatInput|ChatInput-207IY|str",
+ "target": "PromptTemplate-IKKOx",
+ "targetHandle": "Document;BaseOutputParser;str|input|PromptTemplate-IKKOx",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "",
+ "animated": false,
+ "id": "reactflow__edge-ChatInput-207IYChatInput|ChatInput-207IY|str-PromptTemplate-IKKOxDocument;BaseOutputParser;str|input|PromptTemplate-IKKOx"
+ },
+ {
+ "source": "LLMChain-e2dhN",
+ "sourceHandle": "LLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text",
+ "target": "ChatOutput-1jlJy",
+ "targetHandle": "Text|message|ChatOutput-1jlJy",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "stroke-foreground stroke-connection",
+ "animated": true,
+ "id": "reactflow__edge-LLMChain-e2dhNLLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text-ChatOutput-1jlJyText|message|ChatOutput-1jlJy"
+ }
+ ],
+ "viewport": {
+ "x": -141.98308184453367,
+ "y": -104.98637616656356,
+ "zoom": 0.4788209787464315
+ }
+ },
+ "id": "b3388ab9-b5dc-4447-b560-79caef40faa5",
+ "user_id": "c65bfea3-3eea-4e71-8fc4-106238eb0583"
+}
\ No newline at end of file
diff --git a/tests/data/TwoOutputsTest.json b/tests/data/TwoOutputsTest.json
index 9dfb5cd43..4cd060249 100644
--- a/tests/data/TwoOutputsTest.json
+++ b/tests/data/TwoOutputsTest.json
@@ -1 +1,1024 @@
-{"name":"TwoOutputsTest","description":"","data":{"nodes":[{"width":384,"height":359,"id":"PromptTemplate-CweKz","type":"genericNode","position":{"x":969.6448076246203,"y":528.7788853763968},"data":{"type":"PromptTemplate","node":{"template":{"output_parser":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"output_parser","advanced":false,"dynamic":false,"info":"","type":"BaseOutputParser","list":false},"input_variables":{"required":true,"placeholder":"","show":false,"multiline":false,"password":false,"name":"input_variables","advanced":false,"dynamic":false,"info":"","type":"str","list":true,"value":["input"]},"partial_variables":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"partial_variables","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"template":{"required":true,"placeholder":"","show":true,"multiline":true,"password":false,"name":"template","advanced":false,"dynamic":false,"info":"","type":"prompt","list":false,"value":"Input: {input}\nAI:"},"template_format":{"required":false,"placeholder":"","show":false,"multiline":false,"value":"f-string","password":false,"name":"template_format","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"validate_template":{"required":false,"placeholder":"","show":false,"multiline":false,"value":true,"password":false,"name":"validate_template","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"_type":"PromptTemplate","input":{"required":false,"placeholder":"","show":true,"multiline":true,"value":"","password":false,"name":"input","display_name":"input","advanced":false,"input_types":["Document","BaseOutputParser","str"],"dynamic":false,"info":"","type":"str","list":false}},"description":"A prompt template for a language model.","base_classes":["BasePromptTemplate","StringPromptTemplate","PromptTemplate"],"name":"","display_name":"PromptTemplate","documentation":"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/","custom_fields":{"":["input"],"template":["input"]},"output_types":[],"field_formatters":{"formatters":{"openai_api_key":{}},"base_formatters":{"kwargs":{},"optional":{},"list":{},"dict":{},"union":{},"multiline":{},"show":{},"password":{},"default":{},"headers":{},"dict_code_file":{},"model_fields":{"MODEL_DICT":{"OpenAI":["text-davinci-003","text-davinci-002","text-curie-001","text-babbage-001","text-ada-001"],"ChatOpenAI":["gpt-3.5-turbo-0613","gpt-3.5-turbo","gpt-3.5-turbo-16k-0613","gpt-3.5-turbo-16k","gpt-4-0613","gpt-4-32k-0613","gpt-4","gpt-4-32k"],"Anthropic":["claude-v1","claude-v1-100k","claude-instant-v1","claude-instant-v1-100k","claude-v1.3","claude-v1.3-100k","claude-v1.2","claude-v1.0","claude-instant-v1.1","claude-instant-v1.1-100k","claude-instant-v1.0"],"ChatAnthropic":["claude-v1","claude-v1-100k","claude-instant-v1","claude-instant-v1-100k","claude-v1.3","claude-v1.3-100k","claude-v1.2","claude-v1.0","claude-instant-v1.1","claude-instant-v1.1-100k","claude-instant-v1.0"]}}}},"beta":false,"error":null},"id":"PromptTemplate-CweKz"},"selected":false,"positionAbsolute":{"x":969.6448076246203,"y":528.7788853763968}},{"width":384,"height":307,"id":"LLMChain-HUM6g","type":"genericNode","position":{"x":1515.3241458756393,"y":732.4536491407735},"data":{"type":"LLMChain","node":{"template":{"callbacks":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"callbacks","advanced":false,"dynamic":false,"info":"","type":"langchain.callbacks.base.BaseCallbackHandler","list":true},"llm":{"required":true,"placeholder":"","show":true,"multiline":false,"password":false,"name":"llm","advanced":false,"dynamic":false,"info":"","type":"BaseLanguageModel","list":false},"memory":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"memory","advanced":false,"dynamic":false,"info":"","type":"BaseMemory","list":false},"output_parser":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"output_parser","advanced":false,"dynamic":false,"info":"","type":"BaseLLMOutputParser","list":false},"prompt":{"required":true,"placeholder":"","show":true,"multiline":false,"password":false,"name":"prompt","advanced":false,"dynamic":false,"info":"","type":"BasePromptTemplate","list":false},"llm_kwargs":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"llm_kwargs","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"metadata":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"metadata","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"output_key":{"required":true,"placeholder":"","show":true,"multiline":false,"value":"text","password":false,"name":"output_key","advanced":true,"dynamic":false,"info":"","type":"str","list":false},"return_final_only":{"required":false,"placeholder":"","show":false,"multiline":false,"value":true,"password":false,"name":"return_final_only","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"tags":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"tags","advanced":false,"dynamic":false,"info":"","type":"str","list":true},"verbose":{"required":false,"placeholder":"","show":false,"multiline":false,"value":false,"password":false,"name":"verbose","advanced":true,"dynamic":false,"info":"","type":"bool","list":false},"_type":"LLMChain"},"description":"Chain to run queries against LLMs.","base_classes":["LLMChain","Chain","function","Text"],"display_name":"LLMChain","custom_fields":{},"output_types":[],"documentation":"https://python.langchain.com/docs/modules/chains/foundational/llm_chain","beta":false,"error":null},"id":"LLMChain-HUM6g"},"selected":false,"positionAbsolute":{"x":1515.3241458756393,"y":732.4536491407735},"dragging":false},{"width":384,"height":621,"id":"ChatOpenAI-02kOF","type":"genericNode","position":{"x":483,"y":942.8665628296949},"data":{"type":"ChatOpenAI","node":{"template":{"callbacks":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"callbacks","advanced":false,"dynamic":false,"info":"","type":"langchain.callbacks.base.BaseCallbackHandler","list":true},"cache":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"cache","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"client":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"client","advanced":false,"dynamic":false,"info":"","type":"Any","list":false},"max_retries":{"required":false,"placeholder":"","show":false,"multiline":false,"value":6,"password":false,"name":"max_retries","advanced":false,"dynamic":false,"info":"","type":"int","list":false},"max_tokens":{"required":false,"placeholder":"","show":true,"multiline":false,"password":true,"name":"max_tokens","advanced":false,"dynamic":false,"info":"","type":"int","list":false,"value":""},"metadata":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"metadata","advanced":false,"dynamic":false,"info":"","type":"code","list":false},"model_kwargs":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"model_kwargs","advanced":true,"dynamic":false,"info":"","type":"code","list":false},"model_name":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"gpt-3.5-turbo-0613","password":false,"options":["gpt-3.5-turbo-0613","gpt-3.5-turbo","gpt-3.5-turbo-16k-0613","gpt-3.5-turbo-16k","gpt-4-0613","gpt-4-32k-0613","gpt-4","gpt-4-32k"],"name":"model_name","advanced":false,"dynamic":false,"info":"","type":"str","list":true},"n":{"required":false,"placeholder":"","show":false,"multiline":false,"value":1,"password":false,"name":"n","advanced":false,"dynamic":false,"info":"","type":"int","list":false},"openai_api_base":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"openai_api_base","display_name":"OpenAI API Base","advanced":false,"dynamic":false,"info":"\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n","type":"str","list":false},"openai_api_key":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"","password":true,"name":"openai_api_key","display_name":"OpenAI API Key","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"openai_organization":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"openai_organization","display_name":"OpenAI Organization","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"openai_proxy":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"openai_proxy","display_name":"OpenAI Proxy","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"request_timeout":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"request_timeout","advanced":false,"dynamic":false,"info":"","type":"float","list":false},"streaming":{"required":false,"placeholder":"","show":false,"multiline":false,"value":false,"password":false,"name":"streaming","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"tags":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"tags","advanced":false,"dynamic":false,"info":"","type":"str","list":true},"temperature":{"required":false,"placeholder":"","show":true,"multiline":false,"value":0.7,"password":false,"name":"temperature","advanced":false,"dynamic":false,"info":"","type":"float","list":false},"tiktoken_model_name":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"tiktoken_model_name","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"verbose":{"required":false,"placeholder":"","show":false,"multiline":false,"value":false,"password":false,"name":"verbose","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"_type":"ChatOpenAI"},"description":"`OpenAI` Chat large language models API.","base_classes":["ChatOpenAI","BaseLanguageModel","BaseChatModel","BaseLLM"],"display_name":"ChatOpenAI","custom_fields":{},"output_types":[],"documentation":"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai","beta":false,"error":null},"id":"ChatOpenAI-02kOF"},"selected":false,"positionAbsolute":{"x":483,"y":942.8665628296949}},{"width":384,"height":389,"id":"ChatOutput-8SWFf","type":"genericNode","position":{"x":2035.5749798606498,"y":651.0174452514373},"data":{"type":"ChatOutput","node":{"template":{"code":{"dynamic":true,"required":true,"placeholder":"","show":true,"multiline":true,"value":"from typing import Optional\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\nfrom langflow.field_typing import Text\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"str\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n\n return message\n","password":false,"name":"code","advanced":false,"type":"code","list":false},"_type":"CustomComponent","is_ai":{"required":true,"placeholder":"","show":true,"multiline":false,"value":false,"password":false,"name":"is_ai","display_name":"is_ai","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"message":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"message","display_name":"message","advanced":false,"input_types":["Text"],"dynamic":false,"info":"","type":"Text","list":false}},"description":"Used to send a message to the chat.","base_classes":["str"],"display_name":"Chat Output","custom_fields":{"is_ai":null,"message":null},"output_types":["ChatOutput"],"documentation":"","beta":true,"error":null},"id":"ChatOutput-8SWFf"},"selected":false,"positionAbsolute":{"x":2035.5749798606498,"y":651.0174452514373}},{"width":384,"height":273,"id":"ChatInput-PqtHe","type":"genericNode","position":{"x":504.7467002897712,"y":388.46875},"data":{"type":"ChatInput","node":{"template":{"code":{"dynamic":true,"required":true,"placeholder":"","show":false,"multiline":true,"value":"from typing import Optional\nfrom langflow import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n","password":false,"name":"code","advanced":false,"type":"code","list":false},"_type":"CustomComponent","message":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"","password":false,"name":"message","display_name":"message","advanced":false,"dynamic":false,"info":"","type":"str","list":false}},"description":"Used to get user input from the chat.","base_classes":["str"],"display_name":"Chat Input","custom_fields":{"message":null},"output_types":["ChatInput"],"documentation":"","beta":true,"error":null},"id":"ChatInput-PqtHe"},"selected":false,"positionAbsolute":{"x":504.7467002897712,"y":388.46875}},{"width":384,"height":475,"id":"Tool-jyI4N","type":"genericNode","position":{"x":2044.485030617051,"y":1131.4250055845532},"data":{"type":"Tool","node":{"template":{"func":{"required":true,"placeholder":"","show":true,"multiline":true,"password":false,"name":"func","advanced":false,"dynamic":false,"info":"","type":"function","list":false},"description":{"required":true,"placeholder":"","show":true,"multiline":true,"value":"Test tool","password":false,"name":"description","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"name":{"required":true,"placeholder":"","show":true,"multiline":true,"value":"Tool","password":false,"name":"name","advanced":false,"dynamic":false,"info":"","type":"str","list":false},"return_direct":{"required":true,"placeholder":"","show":true,"multiline":false,"value":false,"password":false,"name":"return_direct","advanced":false,"dynamic":false,"info":"","type":"bool","list":false},"_type":"Tool"},"description":"Converts a chain, agent or function into a tool.","base_classes":["Tool","BaseTool"],"display_name":"Tool","custom_fields":{},"output_types":[],"documentation":"","beta":false,"error":null},"id":"Tool-jyI4N"},"selected":true,"positionAbsolute":{"x":2044.485030617051,"y":1131.4250055845532},"dragging":false}],"edges":[{"source":"PromptTemplate-CweKz","target":"LLMChain-HUM6g","sourceHandle":"PromptTemplate|PromptTemplate-CweKz|BasePromptTemplate|StringPromptTemplate|PromptTemplate","targetHandle":"BasePromptTemplate|prompt|LLMChain-HUM6g","id":"reactflow__edge-PromptTemplate-CweKzPromptTemplate|PromptTemplate-CweKz|BasePromptTemplate|StringPromptTemplate|PromptTemplate-LLMChain-HUM6gBasePromptTemplate|prompt|LLMChain-HUM6g","style":{"stroke":"#555"},"className":"stroke-gray-900 ","animated":false,"selected":false},{"source":"ChatOpenAI-02kOF","target":"LLMChain-HUM6g","sourceHandle":"ChatOpenAI|ChatOpenAI-02kOF|ChatOpenAI|BaseLanguageModel|BaseChatModel|BaseLLM","targetHandle":"BaseLanguageModel|llm|LLMChain-HUM6g","id":"reactflow__edge-ChatOpenAI-02kOFChatOpenAI|ChatOpenAI-02kOF|ChatOpenAI|BaseLanguageModel|BaseChatModel|BaseLLM-LLMChain-HUM6gBaseLanguageModel|llm|LLMChain-HUM6g","style":{"stroke":"#555"},"className":"stroke-gray-900 ","animated":false,"selected":false},{"source":"ChatInput-PqtHe","target":"PromptTemplate-CweKz","sourceHandle":"ChatInput|ChatInput-PqtHe|str","targetHandle":"Document;BaseOutputParser;str|input|PromptTemplate-CweKz","id":"reactflow__edge-ChatInput-PqtHeChatInput|ChatInput-PqtHe|str-PromptTemplate-CweKzDocument;BaseOutputParser;str|input|PromptTemplate-CweKz","style":{"stroke":"#555"},"className":"stroke-gray-900 ","animated":false,"selected":false},{"source":"LLMChain-HUM6g","sourceHandle":"LLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text","target":"ChatOutput-8SWFf","targetHandle":"Text|message|ChatOutput-8SWFf","style":{"stroke":"#555"},"className":"stroke-foreground stroke-connection","animated":true,"id":"reactflow__edge-LLMChain-HUM6gLLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text-ChatOutput-8SWFfText|message|ChatOutput-8SWFf"},{"source":"LLMChain-HUM6g","sourceHandle":"LLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text","target":"Tool-jyI4N","targetHandle":"function|func|Tool-jyI4N","style":{"stroke":"#555"},"className":"stroke-foreground stroke-connection","animated":false,"id":"reactflow__edge-LLMChain-HUM6gLLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text-Tool-jyI4Nfunction|func|Tool-jyI4N"}],"viewport":{"x":-401.32668426335044,"y":-129.59138346130635,"zoom":0.5073779796520557}},"id":"cf923ccb-e14c-4754-96eb-a8a3b5bbe082","user_id":"c65bfea3-3eea-4e71-8fc4-106238eb0583"}
\ No newline at end of file
+{
+ "name": "TwoOutputsTest",
+ "description": "",
+ "data": {
+ "nodes": [
+ {
+ "width": 384,
+ "height": 359,
+ "id": "PromptTemplate-CweKz",
+ "type": "genericNode",
+ "position": {
+ "x": 969.6448076246203,
+ "y": 528.7788853763968
+ },
+ "data": {
+ "type": "PromptTemplate",
+ "node": {
+ "template": {
+ "output_parser": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "output_parser",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseOutputParser",
+ "list": false
+ },
+ "input_variables": {
+ "required": true,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "input_variables",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true,
+ "value": [
+ "input"
+ ]
+ },
+ "partial_variables": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "partial_variables",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "template": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "password": false,
+ "name": "template",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "prompt",
+ "list": false,
+ "value": "Input: {input}\nAI:"
+ },
+ "template_format": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": "f-string",
+ "password": false,
+ "name": "template_format",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "validate_template": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": true,
+ "password": false,
+ "name": "validate_template",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "PromptTemplate",
+ "input": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "value": "",
+ "password": false,
+ "name": "input",
+ "display_name": "input",
+ "advanced": false,
+ "input_types": [
+ "Document",
+ "BaseOutputParser",
+ "str"
+ ],
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ }
+ },
+ "description": "A prompt template for a language model.",
+ "base_classes": [
+ "BasePromptTemplate",
+ "StringPromptTemplate",
+ "PromptTemplate"
+ ],
+ "name": "",
+ "display_name": "PromptTemplate",
+ "documentation": "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/",
+ "custom_fields": {
+ "": [
+ "input"
+ ],
+ "template": [
+ "input"
+ ]
+ },
+ "output_types": [],
+ "field_formatters": {
+ "formatters": {
+ "openai_api_key": {}
+ },
+ "base_formatters": {
+ "kwargs": {},
+ "optional": {},
+ "list": {},
+ "dict": {},
+ "union": {},
+ "multiline": {},
+ "show": {},
+ "password": {},
+ "default": {},
+ "headers": {},
+ "dict_code_file": {},
+ "model_fields": {
+ "MODEL_DICT": {
+ "OpenAI": [
+ "text-davinci-003",
+ "text-davinci-002",
+ "text-curie-001",
+ "text-babbage-001",
+ "text-ada-001"
+ ],
+ "ChatOpenAI": [
+ "gpt-3.5-turbo-0613",
+ "gpt-3.5-turbo",
+ "gpt-3.5-turbo-16k-0613",
+ "gpt-3.5-turbo-16k",
+ "gpt-4-0613",
+ "gpt-4-32k-0613",
+ "gpt-4",
+ "gpt-4-32k"
+ ],
+ "Anthropic": [
+ "claude-v1",
+ "claude-v1-100k",
+ "claude-instant-v1",
+ "claude-instant-v1-100k",
+ "claude-v1.3",
+ "claude-v1.3-100k",
+ "claude-v1.2",
+ "claude-v1.0",
+ "claude-instant-v1.1",
+ "claude-instant-v1.1-100k",
+ "claude-instant-v1.0"
+ ],
+ "ChatAnthropic": [
+ "claude-v1",
+ "claude-v1-100k",
+ "claude-instant-v1",
+ "claude-instant-v1-100k",
+ "claude-v1.3",
+ "claude-v1.3-100k",
+ "claude-v1.2",
+ "claude-v1.0",
+ "claude-instant-v1.1",
+ "claude-instant-v1.1-100k",
+ "claude-instant-v1.0"
+ ]
+ }
+ }
+ }
+ },
+ "beta": false,
+ "error": null
+ },
+ "id": "PromptTemplate-CweKz"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 969.6448076246203,
+ "y": 528.7788853763968
+ }
+ },
+ {
+ "width": 384,
+ "height": 307,
+ "id": "LLMChain-HUM6g",
+ "type": "genericNode",
+ "position": {
+ "x": 1515.3241458756393,
+ "y": 732.4536491407735
+ },
+ "data": {
+ "type": "LLMChain",
+ "node": {
+ "template": {
+ "callbacks": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "callbacks",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "langchain.callbacks.base.BaseCallbackHandler",
+ "list": true
+ },
+ "llm": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "llm",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseLanguageModel",
+ "list": false
+ },
+ "memory": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "memory",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseMemory",
+ "list": false
+ },
+ "output_parser": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "output_parser",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BaseLLMOutputParser",
+ "list": false
+ },
+ "prompt": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "prompt",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "BasePromptTemplate",
+ "list": false
+ },
+ "llm_kwargs": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "llm_kwargs",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "metadata": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "metadata",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "output_key": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "text",
+ "password": false,
+ "name": "output_key",
+ "advanced": true,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "return_final_only": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": true,
+ "password": false,
+ "name": "return_final_only",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "tags": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "tags",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true
+ },
+ "verbose": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "verbose",
+ "advanced": true,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "LLMChain"
+ },
+ "description": "Chain to run queries against LLMs.",
+ "base_classes": [
+ "LLMChain",
+ "Chain",
+ "function",
+ "Text"
+ ],
+ "display_name": "LLMChain",
+ "custom_fields": {},
+ "output_types": [],
+ "documentation": "https://python.langchain.com/docs/modules/chains/foundational/llm_chain",
+ "beta": false,
+ "error": null
+ },
+ "id": "LLMChain-HUM6g"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 1515.3241458756393,
+ "y": 732.4536491407735
+ },
+ "dragging": false
+ },
+ {
+ "width": 384,
+ "height": 621,
+ "id": "ChatOpenAI-02kOF",
+ "type": "genericNode",
+ "position": {
+ "x": 483,
+ "y": 942.8665628296949
+ },
+ "data": {
+ "type": "ChatOpenAI",
+ "node": {
+ "template": {
+ "callbacks": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "callbacks",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "langchain.callbacks.base.BaseCallbackHandler",
+ "list": true
+ },
+ "cache": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "cache",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "client": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "client",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "Any",
+ "list": false
+ },
+ "max_retries": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": 6,
+ "password": false,
+ "name": "max_retries",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "int",
+ "list": false
+ },
+ "max_tokens": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": true,
+ "name": "max_tokens",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "int",
+ "list": false,
+ "value": ""
+ },
+ "metadata": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "metadata",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "model_kwargs": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "model_kwargs",
+ "advanced": true,
+ "dynamic": false,
+ "info": "",
+ "type": "code",
+ "list": false
+ },
+ "model_name": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "gpt-3.5-turbo-0613",
+ "password": false,
+ "options": [
+ "gpt-3.5-turbo-0613",
+ "gpt-3.5-turbo",
+ "gpt-3.5-turbo-16k-0613",
+ "gpt-3.5-turbo-16k",
+ "gpt-4-0613",
+ "gpt-4-32k-0613",
+ "gpt-4",
+ "gpt-4-32k"
+ ],
+ "name": "model_name",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true
+ },
+ "n": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": 1,
+ "password": false,
+ "name": "n",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "int",
+ "list": false
+ },
+ "openai_api_base": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "openai_api_base",
+ "display_name": "OpenAI API Base",
+ "advanced": false,
+ "dynamic": false,
+ "info": "\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n",
+ "type": "str",
+ "list": false
+ },
+ "openai_api_key": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "",
+ "password": true,
+ "name": "openai_api_key",
+ "display_name": "OpenAI API Key",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "openai_organization": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "openai_organization",
+ "display_name": "OpenAI Organization",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "openai_proxy": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "openai_proxy",
+ "display_name": "OpenAI Proxy",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "request_timeout": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "request_timeout",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "float",
+ "list": false
+ },
+ "streaming": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "streaming",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "tags": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "tags",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": true
+ },
+ "temperature": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": 0.7,
+ "password": false,
+ "name": "temperature",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "float",
+ "list": false
+ },
+ "tiktoken_model_name": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "password": false,
+ "name": "tiktoken_model_name",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "verbose": {
+ "required": false,
+ "placeholder": "",
+ "show": false,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "verbose",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "ChatOpenAI"
+ },
+ "description": "`OpenAI` Chat large language models API.",
+ "base_classes": [
+ "ChatOpenAI",
+ "BaseLanguageModel",
+ "BaseChatModel",
+ "BaseLLM"
+ ],
+ "display_name": "ChatOpenAI",
+ "custom_fields": {},
+ "output_types": [],
+ "documentation": "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai",
+ "beta": false,
+ "error": null
+ },
+ "id": "ChatOpenAI-02kOF"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 483,
+ "y": 942.8665628296949
+ }
+ },
+ {
+ "width": 384,
+ "height": 389,
+ "id": "ChatOutput-8SWFf",
+ "type": "genericNode",
+ "position": {
+ "x": 2035.5749798606498,
+ "y": 651.0174452514373
+ },
+ "data": {
+ "type": "ChatOutput",
+ "node": {
+ "template": {
+ "code": {
+ "dynamic": true,
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "value": "from typing import Optional\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow.custom import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\nfrom langflow.field_typing import Text\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"str\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n\n return message\n",
+ "password": false,
+ "name": "code",
+ "advanced": false,
+ "type": "code",
+ "list": false
+ },
+ "_type": "CustomComponent",
+ "is_ai": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "is_ai",
+ "display_name": "is_ai",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "message": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "password": false,
+ "name": "message",
+ "display_name": "message",
+ "advanced": false,
+ "input_types": [
+ "Text"
+ ],
+ "dynamic": false,
+ "info": "",
+ "type": "Text",
+ "list": false
+ }
+ },
+ "description": "Used to send a message to the chat.",
+ "base_classes": [
+ "str"
+ ],
+ "display_name": "Chat Output",
+ "custom_fields": {
+ "is_ai": null,
+ "message": null
+ },
+ "output_types": [
+ "ChatOutput"
+ ],
+ "documentation": "",
+ "beta": true,
+ "error": null
+ },
+ "id": "ChatOutput-8SWFf"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 2035.5749798606498,
+ "y": 651.0174452514373
+ }
+ },
+ {
+ "width": 384,
+ "height": 273,
+ "id": "ChatInput-PqtHe",
+ "type": "genericNode",
+ "position": {
+ "x": 504.7467002897712,
+ "y": 388.46875
+ },
+ "data": {
+ "type": "ChatInput",
+ "node": {
+ "template": {
+ "code": {
+ "dynamic": true,
+ "required": true,
+ "placeholder": "",
+ "show": false,
+ "multiline": true,
+ "value": "from typing import Optional\nfrom langflow.custom import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n",
+ "password": false,
+ "name": "code",
+ "advanced": false,
+ "type": "code",
+ "list": false
+ },
+ "_type": "CustomComponent",
+ "message": {
+ "required": false,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": "",
+ "password": false,
+ "name": "message",
+ "display_name": "message",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ }
+ },
+ "description": "Used to get user input from the chat.",
+ "base_classes": [
+ "str"
+ ],
+ "display_name": "Chat Input",
+ "custom_fields": {
+ "message": null
+ },
+ "output_types": [
+ "ChatInput"
+ ],
+ "documentation": "",
+ "beta": true,
+ "error": null
+ },
+ "id": "ChatInput-PqtHe"
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 504.7467002897712,
+ "y": 388.46875
+ }
+ },
+ {
+ "width": 384,
+ "height": 475,
+ "id": "Tool-jyI4N",
+ "type": "genericNode",
+ "position": {
+ "x": 2044.485030617051,
+ "y": 1131.4250055845532
+ },
+ "data": {
+ "type": "Tool",
+ "node": {
+ "template": {
+ "func": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "password": false,
+ "name": "func",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "function",
+ "list": false
+ },
+ "description": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "value": "Test tool",
+ "password": false,
+ "name": "description",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "name": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": true,
+ "value": "Tool",
+ "password": false,
+ "name": "name",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "str",
+ "list": false
+ },
+ "return_direct": {
+ "required": true,
+ "placeholder": "",
+ "show": true,
+ "multiline": false,
+ "value": false,
+ "password": false,
+ "name": "return_direct",
+ "advanced": false,
+ "dynamic": false,
+ "info": "",
+ "type": "bool",
+ "list": false
+ },
+ "_type": "Tool"
+ },
+ "description": "Converts a chain, agent or function into a tool.",
+ "base_classes": [
+ "Tool",
+ "BaseTool"
+ ],
+ "display_name": "Tool",
+ "custom_fields": {},
+ "output_types": [],
+ "documentation": "",
+ "beta": false,
+ "error": null
+ },
+ "id": "Tool-jyI4N"
+ },
+ "selected": true,
+ "positionAbsolute": {
+ "x": 2044.485030617051,
+ "y": 1131.4250055845532
+ },
+ "dragging": false
+ }
+ ],
+ "edges": [
+ {
+ "source": "PromptTemplate-CweKz",
+ "target": "LLMChain-HUM6g",
+ "sourceHandle": "PromptTemplate|PromptTemplate-CweKz|BasePromptTemplate|StringPromptTemplate|PromptTemplate",
+ "targetHandle": "BasePromptTemplate|prompt|LLMChain-HUM6g",
+ "id": "reactflow__edge-PromptTemplate-CweKzPromptTemplate|PromptTemplate-CweKz|BasePromptTemplate|StringPromptTemplate|PromptTemplate-LLMChain-HUM6gBasePromptTemplate|prompt|LLMChain-HUM6g",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "stroke-gray-900 ",
+ "animated": false,
+ "selected": false
+ },
+ {
+ "source": "ChatOpenAI-02kOF",
+ "target": "LLMChain-HUM6g",
+ "sourceHandle": "ChatOpenAI|ChatOpenAI-02kOF|ChatOpenAI|BaseLanguageModel|BaseChatModel|BaseLLM",
+ "targetHandle": "BaseLanguageModel|llm|LLMChain-HUM6g",
+ "id": "reactflow__edge-ChatOpenAI-02kOFChatOpenAI|ChatOpenAI-02kOF|ChatOpenAI|BaseLanguageModel|BaseChatModel|BaseLLM-LLMChain-HUM6gBaseLanguageModel|llm|LLMChain-HUM6g",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "stroke-gray-900 ",
+ "animated": false,
+ "selected": false
+ },
+ {
+ "source": "ChatInput-PqtHe",
+ "target": "PromptTemplate-CweKz",
+ "sourceHandle": "ChatInput|ChatInput-PqtHe|str",
+ "targetHandle": "Document;BaseOutputParser;str|input|PromptTemplate-CweKz",
+ "id": "reactflow__edge-ChatInput-PqtHeChatInput|ChatInput-PqtHe|str-PromptTemplate-CweKzDocument;BaseOutputParser;str|input|PromptTemplate-CweKz",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "stroke-gray-900 ",
+ "animated": false,
+ "selected": false
+ },
+ {
+ "source": "LLMChain-HUM6g",
+ "sourceHandle": "LLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text",
+ "target": "ChatOutput-8SWFf",
+ "targetHandle": "Text|message|ChatOutput-8SWFf",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "stroke-foreground stroke-connection",
+ "animated": true,
+ "id": "reactflow__edge-LLMChain-HUM6gLLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text-ChatOutput-8SWFfText|message|ChatOutput-8SWFf"
+ },
+ {
+ "source": "LLMChain-HUM6g",
+ "sourceHandle": "LLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text",
+ "target": "Tool-jyI4N",
+ "targetHandle": "function|func|Tool-jyI4N",
+ "style": {
+ "stroke": "#555"
+ },
+ "className": "stroke-foreground stroke-connection",
+ "animated": false,
+ "id": "reactflow__edge-LLMChain-HUM6gLLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text-Tool-jyI4Nfunction|func|Tool-jyI4N"
+ }
+ ],
+ "viewport": {
+ "x": -401.32668426335044,
+ "y": -129.59138346130635,
+ "zoom": 0.5073779796520557
+ }
+ },
+ "id": "cf923ccb-e14c-4754-96eb-a8a3b5bbe082",
+ "user_id": "c65bfea3-3eea-4e71-8fc4-106238eb0583"
+}
\ No newline at end of file
diff --git a/tests/data/component.py b/tests/data/component.py
index e801d2feb..5de63fcd5 100644
--- a/tests/data/component.py
+++ b/tests/data/component.py
@@ -1,6 +1,6 @@
import random
-from langflow import CustomComponent
+from langflow.custom import CustomComponent
class TestComponent(CustomComponent):
diff --git a/tests/data/component_with_templatefield.py b/tests/data/component_with_templatefield.py
index 6b2ce011b..26d7e834b 100644
--- a/tests/data/component_with_templatefield.py
+++ b/tests/data/component_with_templatefield.py
@@ -1,6 +1,6 @@
import random
-from langflow import CustomComponent
+from langflow.custom import CustomComponent
from langflow.field_typing import TemplateField
diff --git a/tests/test_endpoints.py b/tests/test_endpoints.py
index 4494934fd..7b1ccd2ef 100644
--- a/tests/test_endpoints.py
+++ b/tests/test_endpoints.py
@@ -1,14 +1,12 @@
import time
+from uuid import uuid4
import pytest
from fastapi import status
from fastapi.testclient import TestClient
from langflow.interface.custom.directory_reader.directory_reader import DirectoryReader
-from langflow.services.auth.utils import get_password_hash
-from langflow.services.database.models.api_key.model import ApiKey
-from langflow.services.database.utils import session_getter
-from langflow.services.deps import get_db_service, get_settings_service
+from langflow.services.deps import get_settings_service
from langflow.template.frontend_node.chains import TimeTravelGuideChainNode
@@ -112,25 +110,6 @@ PROMPT_REQUEST = {
}
-@pytest.fixture
-def created_api_key(active_user):
- hashed = get_password_hash("random_key")
- api_key = ApiKey(
- name="test_api_key",
- user_id=active_user.id,
- api_key="random_key",
- hashed_api_key=hashed,
- )
- db_manager = get_db_service()
- with session_getter(db_manager) as session:
- if existing_api_key := session.query(ApiKey).filter(ApiKey.api_key == api_key.api_key).first():
- return existing_api_key
- session.add(api_key)
- session.commit()
- session.refresh(api_key)
- return api_key
-
-
# def test_process_flow_invalid_api_key(client, flow, monkeypatch):
# # Mock de process_graph_cached
# from langflow.api.v1 import endpoints
@@ -452,18 +431,24 @@ def test_successful_run(client, starter_project, created_api_key):
assert response.status_code == status.HTTP_200_OK, response.text
# Add more assertions here to validate the response content
json_response = response.json()
+ assert "session_id" in json_response
assert "outputs" in json_response
outer_outputs = json_response["outputs"]
assert len(outer_outputs) == 1
- outputs = outer_outputs[0]
- assert len(outputs) == 2
- keys = ["results", "artifacts", "messages"]
- for output in outputs:
- assert all(key in output for key in keys)
- output = outputs[0]
- result = output["results"]["result"]
- assert result == "Write a press release \n\n- Cars\n- Bottle\n\n\nAnswer:\n\n"
- assert "session_id" in json_response
+ outputs_dict = outer_outputs[0]
+ assert len(outputs_dict) == 2
+ assert "inputs" in outputs_dict
+ assert "outputs" in outputs_dict
+ assert outputs_dict.get("inputs") == {"input_value": ""}
+ assert isinstance(outputs_dict.get("outputs"), list)
+ assert len(outputs_dict.get("outputs")) == 2
+ ids = [output.get("component_id") for output in outputs_dict.get("outputs")]
+ assert all([id in ids for id in ["TextOutput-fTp5e", "ChatOutput-AVN8s"]])
+ display_names = [output.get("component_display_name") for output in outputs_dict.get("outputs")]
+ assert all([name in display_names for name in ["Prompt Output", "Chat Output"]])
+ inner_results = [output.get("results").get("result") for output in outputs_dict.get("outputs")]
+ expected_results = ["Write a press release \n\n- Cars\n- Bottle\n\n\nAnswer:\n\n", ""]
+ assert all([result in inner_results for result in expected_results])
def test_run_with_inputs_and_outputs(client, starter_project, created_api_key):
@@ -484,3 +469,89 @@ def test_invalid_flow_id(client, created_api_key):
response = client.post(f"/api/v1/run/{flow_id}", headers=headers)
assert response.status_code == status.HTTP_404_NOT_FOUND
# Check if the error detail is as expected
+
+
+def test_run_flow_with_caching_success(client: TestClient, starter_project, created_api_key):
+ flow_id = starter_project["id"]
+ headers = {"x-api-key": created_api_key.api_key}
+ payload = {
+ "inputs": [
+ {"components": ["component1"], "input_value": "value1"},
+ {"components": ["component3"], "input_value": "value2"},
+ ],
+ "outputs": ["Component Name", "component_id"],
+ "tweaks": {
+ "parameter_name": "value",
+ "Component Name": {"parameter_name": "value"},
+ "component_id": {"parameter_name": "value"},
+ },
+ "stream": False,
+ }
+ response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers)
+ assert response.status_code == status.HTTP_200_OK
+ data = response.json()
+ assert "outputs" in data
+ assert "session_id" in data
+
+
+def test_run_flow_with_caching_invalid_flow_id(client: TestClient, created_api_key):
+ invalid_flow_id = uuid4()
+ headers = {"x-api-key": created_api_key.api_key}
+ payload = {"inputs": [], "outputs": [], "tweaks": {}, "stream": False}
+ response = client.post(f"/api/v1/run/{invalid_flow_id}", json=payload, headers=headers)
+ assert response.status_code == status.HTTP_404_NOT_FOUND
+ data = response.json()
+ assert "detail" in data
+ assert f"Flow {invalid_flow_id} not found" in data["detail"]
+
+
+def test_run_flow_with_caching_invalid_input_format(client: TestClient, starter_project, created_api_key):
+ flow_id = starter_project["id"]
+ headers = {"x-api-key": created_api_key.api_key}
+ payload = {"inputs": [{"invalid_key": "value"}], "outputs": [], "tweaks": {}, "stream": False}
+ # This should raise an http 422 error not validation error
+ response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers)
+ assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
+
+
+def test_run_flow_with_session_id(client, starter_project, created_api_key):
+ headers = {"x-api-key": created_api_key.api_key}
+ flow_id = starter_project["id"]
+ payload = {
+ "inputs": [{"components": ["component1"], "input_value": "value1"}],
+ "outputs": ["Component Name", "component_id"],
+ "session_id": "test-session-id",
+ }
+ response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers)
+ assert response.status_code == status.HTTP_200_OK
+ data = response.json()
+ assert "outputs" in data
+ assert "session_id" in data
+ assert data["session_id"] == "test-session-id"
+
+
+def test_run_flow_with_invalid_session_id(client, starter_project, created_api_key):
+ headers = {"x-api-key": created_api_key.api_key}
+ flow_id = starter_project["id"]
+ payload = {
+ "inputs": [{"components": ["component1"], "input_value": "value1"}],
+ "outputs": ["Component Name", "component_id"],
+ "session_id": "invalid-session-id",
+ }
+ response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers)
+ assert response.status_code == status.HTTP_404_NOT_FOUND
+ data = response.json()
+ assert "detail" in data
+ assert f"Session {payload['session_id']} not found" in data["detail"]
+
+
+def test_run_flow_with_invalid_tweaks(client, starter_project, created_api_key):
+ headers = {"x-api-key": created_api_key.api_key}
+ flow_id = starter_project["id"]
+ payload = {
+ "inputs": [{"components": ["component1"], "input_value": "value1"}],
+ "outputs": ["Component Name", "component_id"],
+ "tweaks": {"invalid_tweak": "value"},
+ }
+ response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers)
+ assert response.status_code == status.HTTP_200_OK