From 5e30aac39999bac015f360d7947425194cb4494e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:25:13 -0300 Subject: [PATCH 01/56] Add successors to VertexBuildResponse and return only first layer --- src/backend/langflow/api/v1/chat.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index c5090b3e1..bd2068d56 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -85,7 +85,7 @@ async def try_running_celery_task(vertex, user_id): @router.get("/build/{flow_id}/vertices", response_model=VerticesOrderResponse) async def get_vertices( flow_id: str, - component_id: Optional[str] = None, + stop_vertex_id: Optional[str] = None, chat_service: "ChatService" = Depends(get_chat_service), session=Depends(get_session), ): @@ -96,9 +96,9 @@ async def get_vertices( if cache := chat_service.get_cache(flow_id): graph: Graph = cache.get("result") graph = build_and_cache_graph(flow_id, session, chat_service, graph) - if component_id: + if stop_vertex_id: try: - vertices = graph.sort_vertices(component_id) + vertices = graph.sort_vertices(stop_vertex_id) except Exception as exc: logger.error(exc) vertices = graph.sort_vertices() @@ -189,6 +189,7 @@ async def build_vertex( vertex.add_build_time(timedelta) return VertexBuildResponse( + successors=vertex.successors_ids, valid=valid, params=params, id=vertex.id, From d79c8283a679fb81e9bfb13c55ac8a1c31e66a30 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:25:38 -0300 Subject: [PATCH 02/56] Add successors field to VertexBuildResponse --- src/backend/langflow/api/v1/schemas.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/schemas.py b/src/backend/langflow/api/v1/schemas.py index c50787b97..8da328195 100644 --- a/src/backend/langflow/api/v1/schemas.py +++ b/src/backend/langflow/api/v1/schemas.py @@ -4,12 +4,13 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Union from uuid import UUID +from pydantic import BaseModel, Field, field_serializer, field_validator + from langflow.api.utils import serialize_field from langflow.services.database.models.api_key.model import ApiKeyRead from langflow.services.database.models.base import orjson_dumps from langflow.services.database.models.flow import FlowCreate, FlowRead from langflow.services.database.models.user import UserRead -from pydantic import BaseModel, Field, field_serializer, field_validator class BuildStatus(Enum): @@ -235,6 +236,7 @@ class ResultData(BaseModel): class VertexBuildResponse(BaseModel): id: Optional[str] = None + successors: Optional[List[str]] = Field(default_factory=list) valid: bool params: Optional[str] """JSON string of the params.""" From a48b497b28affcaf2f4dc0b3359779d0fed68bef Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:26:09 -0300 Subject: [PATCH 03/56] Add vertices_layers attribute and stop_vertex attribute to Graph class --- src/backend/langflow/graph/graph/base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/backend/langflow/graph/graph/base.py b/src/backend/langflow/graph/graph/base.py index 3f831332a..ba625bba3 100644 --- a/src/backend/langflow/graph/graph/base.py +++ b/src/backend/langflow/graph/graph/base.py @@ -43,6 +43,8 @@ class Graph: self._vertices = self._graph_data["nodes"] self._edges = self._graph_data["edges"] + self.vertices_layers = [] + self.stop_vertex = None self._build_graph() self.build_graph_maps() @@ -518,17 +520,20 @@ class Graph: return vertices_layers - def sort_vertices(self, component_id: Optional[str] = None) -> List[List[str]]: + def sort_vertices(self, stop_vertex_id: Optional[str] = None) -> List[List[str]]: """Sorts the vertices in the graph.""" - if component_id: - vertices = self.sort_up_to_vertex(component_id) + if stop_vertex_id: + self.stop_vertex = stop_vertex_id + vertices = self.sort_up_to_vertex(stop_vertex_id) else: vertices = self.vertices vertices_layers = self.layered_topological_sort(vertices) vertices_layers = self.sort_by_avg_build_time(vertices_layers) vertices_layers = self.sort_chat_inputs_first(vertices_layers) self.increment_run_count() - return vertices_layers + self.vertices_layers = vertices_layers + # Return just the first layer + return vertices_layers[0] def sort_interface_components_first(self, vertices_layers: List[List[str]]) -> List[List[str]]: """Sorts the vertices in the graph so that vertices containing ChatInput or ChatOutput come first.""" From 8a4e9a722690befb19e81d11056bff4c300401e3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:26:32 -0300 Subject: [PATCH 04/56] Add successors_ids property to Vertex class --- src/backend/langflow/graph/vertex/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/graph/vertex/base.py b/src/backend/langflow/graph/vertex/base.py index a3753ab0e..5d5a6ea60 100644 --- a/src/backend/langflow/graph/vertex/base.py +++ b/src/backend/langflow/graph/vertex/base.py @@ -3,6 +3,8 @@ import inspect import types from typing import TYPE_CHECKING, Any, Callable, Coroutine, Dict, List, Optional +from loguru import logger + from langflow.graph.schema import InterfaceComponentTypes from langflow.graph.utils import UnbuiltObject, UnbuiltResult from langflow.graph.vertex.utils import generate_result @@ -11,7 +13,6 @@ from langflow.interface.listing import lazy_load_dict from langflow.services.deps import get_storage_service from langflow.utils.constants import DIRECT_TYPES from langflow.utils.util import sync_to_async -from loguru import logger if TYPE_CHECKING: from langflow.api.v1.schemas import ResultData @@ -121,6 +122,10 @@ class Vertex: def successors(self) -> List["Vertex"]: return self.graph.get_successors(self) + @property + def successors_ids(self) -> List[str]: + return self.graph.successor_map.get(self.id, []) + def __getstate__(self): return { "_data": self._data, From e3c42d36bae411c7291cb8eec8ad146fac6fe1f5 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:26:55 -0300 Subject: [PATCH 05/56] Refactor RoutingVertex to handle successors based on boolean value --- src/backend/langflow/graph/vertex/types.py | 40 ++++++---------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/src/backend/langflow/graph/vertex/types.py b/src/backend/langflow/graph/vertex/types.py index 5a9576fe5..34d6d8554 100644 --- a/src/backend/langflow/graph/vertex/types.py +++ b/src/backend/langflow/graph/vertex/types.py @@ -4,6 +4,7 @@ from typing import Callable, Dict, List, Optional, Union import yaml from langchain_core.messages import AIMessage + from langflow.graph.utils import UnbuiltObject, flatten_list from langflow.graph.vertex.base import StatefulVertex, StatelessVertex from langflow.interface.utils import extract_input_variables_from_prompt @@ -366,42 +367,21 @@ class RoutingVertex(StatelessVertex): def __init__(self, data: Dict, graph): super().__init__(data, graph=graph, base_type="routing") self.use_result = True - self.steps = [self._build, self._run] + self.steps = [self._build] def _built_object_repr(self): if self.artifacts and "repr" in self.artifacts: return self.artifacts["repr"] or super()._built_object_repr() return super()._built_object_repr() - def _build(self, *args, **kwargs): - super()._build(*args, **kwargs) - - # After building, the _built_object should be a dict with - # {"result": Any, "condition": bool} - # if true, we need to set should_run attr in the target of true edge - # to true and should_run attr in the target of false edge to false - # TODO: Add support for multiple conditions - - def _run(self, *args, **kwargs): - if self._built_object: - condition = self._built_object.get("condition") - result = self._built_object.get("result") - if condition is not None: - for edge in self.edges: - if edge.source_id == self.id: - target_vertex = self.graph.get_vertex(edge.target_id) - # source_handle.channel and condition should be the same - channel_bool = edge.source_handle.channel == "true" - if condition == channel_bool: - target_vertex.should_run = True - else: - target_vertex.should_run = False - else: - raise ValueError(f"RoutingVertex {self.id} must have a condition in the _built_object") - - self._built_result = result - else: - raise ValueError(f"RoutingVertex {self.id} must have a _built_object with a condition and a result") + @property + def successors_ids(self): + if isinstance(self._built_object, bool): + ids = super().successors_ids + if self._built_object: + return ids + return [] + raise ValueError("RoutingVertex should return a boolean value.") def dict_to_codeblock(d: dict) -> str: From 58769f587f72b8354aad32037a44f786b419e494 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:28:27 -0300 Subject: [PATCH 06/56] Rename stop_vertex to component --- src/backend/langflow/api/v1/chat.py | 6 +++--- src/backend/langflow/graph/graph/base.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index bd2068d56..fd59f0126 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -85,7 +85,7 @@ async def try_running_celery_task(vertex, user_id): @router.get("/build/{flow_id}/vertices", response_model=VerticesOrderResponse) async def get_vertices( flow_id: str, - stop_vertex_id: Optional[str] = None, + stop_component_id: Optional[str] = None, chat_service: "ChatService" = Depends(get_chat_service), session=Depends(get_session), ): @@ -96,9 +96,9 @@ async def get_vertices( if cache := chat_service.get_cache(flow_id): graph: Graph = cache.get("result") graph = build_and_cache_graph(flow_id, session, chat_service, graph) - if stop_vertex_id: + if stop_component_id: try: - vertices = graph.sort_vertices(stop_vertex_id) + vertices = graph.sort_vertices(stop_component_id) except Exception as exc: logger.error(exc) vertices = graph.sort_vertices() diff --git a/src/backend/langflow/graph/graph/base.py b/src/backend/langflow/graph/graph/base.py index ba625bba3..4078bac89 100644 --- a/src/backend/langflow/graph/graph/base.py +++ b/src/backend/langflow/graph/graph/base.py @@ -520,11 +520,11 @@ class Graph: return vertices_layers - def sort_vertices(self, stop_vertex_id: Optional[str] = None) -> List[List[str]]: + def sort_vertices(self, stop_component_id: Optional[str] = None) -> List[List[str]]: """Sorts the vertices in the graph.""" - if stop_vertex_id: - self.stop_vertex = stop_vertex_id - vertices = self.sort_up_to_vertex(stop_vertex_id) + if stop_component_id: + self.stop_vertex = stop_component_id + vertices = self.sort_up_to_vertex(stop_component_id) else: vertices = self.vertices vertices_layers = self.layered_topological_sort(vertices) From 176f6b16409e1de3f2bed035b587328dbad9b8ef Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:41:18 -0300 Subject: [PATCH 07/56] Refactor ConversationChainComponent class to handle different types of result objects --- src/backend/langflow/components/chains/ConversationChain.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/backend/langflow/components/chains/ConversationChain.py b/src/backend/langflow/components/chains/ConversationChain.py index 43f71e67b..46c33447e 100644 --- a/src/backend/langflow/components/chains/ConversationChain.py +++ b/src/backend/langflow/components/chains/ConversationChain.py @@ -35,13 +35,10 @@ class ConversationChainComponent(CustomComponent): # result is an AIMessage which is a subclass of BaseMessage # We need to check if it is a string or a BaseMessage if hasattr(result, "content") and isinstance(result.content, str): - self.status = "is message" result = result.content elif isinstance(result, str): - self.status = "is_string" result = result else: - # is dict result = result.get("response") self.status = result return result From 9192d50e72e95ff72ee0b2dd9e9649bb0461e18e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:41:29 -0300 Subject: [PATCH 08/56] Remove unnecessary comments and improve result handling in ConversationChainComponent --- src/backend/langflow/components/chains/ConversationChain.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/langflow/components/chains/ConversationChain.py b/src/backend/langflow/components/chains/ConversationChain.py index 46c33447e..dd465c511 100644 --- a/src/backend/langflow/components/chains/ConversationChain.py +++ b/src/backend/langflow/components/chains/ConversationChain.py @@ -32,8 +32,6 @@ class ConversationChainComponent(CustomComponent): else: chain = ConversationChain(llm=llm, memory=memory) result = chain.invoke(inputs) - # result is an AIMessage which is a subclass of BaseMessage - # We need to check if it is a string or a BaseMessage if hasattr(result, "content") and isinstance(result.content, str): result = result.content elif isinstance(result, str): From 1c237f2b6e829439fca4724199ccf4a811322909 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:45:19 -0300 Subject: [PATCH 09/56] Add ShouldRunNext component --- .../components/routing/ShouldRunNext.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/backend/langflow/components/routing/ShouldRunNext.py diff --git a/src/backend/langflow/components/routing/ShouldRunNext.py b/src/backend/langflow/components/routing/ShouldRunNext.py new file mode 100644 index 000000000..3cfde3c22 --- /dev/null +++ b/src/backend/langflow/components/routing/ShouldRunNext.py @@ -0,0 +1,48 @@ +# Implement ShouldRunNext component +from langchain_core.prompts import PromptTemplate + +from langflow import CustomComponent +from langflow.field_typing import BaseLanguageModel, Prompt + + +class ShouldRunNext(CustomComponent): + display_name = "Should Run Next" + description = "Decides whether to run the next component." + + def build_config(self): + return { + "prompt": { + "display_name": "Prompt", + "info": "The prompt to use for the decision. It should generate a boolean response (True or False).", + }, + "llm": { + "display_name": "LLM", + "info": "The language model to use for the decision.", + }, + } + + def build(self, template: Prompt, llm: BaseLanguageModel, **kwargs) -> bool: + # This is a simple component that always returns True + prompt_template = PromptTemplate.from_template(template) + + attributes_to_check = ["text", "page_content"] + for key, value in kwargs.items(): + for attribute in attributes_to_check: + if hasattr(value, attribute): + kwargs[key] = getattr(value, attribute) + + chain = prompt_template | llm + result = chain.invoke(kwargs) + if hasattr(result, "content") and isinstance(result.content, str): + result = result.content + elif isinstance(result, str): + result = result + else: + result = result.get("response") + + if result.lower() not in ["true", "false"]: + raise ValueError("The prompt should generate a boolean response (True or False).") + # The string should be the words true or false + # if not raise an error + bool_result = result.lower() == "true" + return bool_result From be7220b5618da2e0eeca75f537b178f1acc54db7 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:45:46 -0300 Subject: [PATCH 10/56] Add routing component to backend --- src/backend/langflow/components/routing/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/backend/langflow/components/routing/__init__.py diff --git a/src/backend/langflow/components/routing/__init__.py b/src/backend/langflow/components/routing/__init__.py new file mode 100644 index 000000000..e69de29bb From 0003e4b7e9bbebeccd02b9d927892a743e77a46d Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:46:21 -0300 Subject: [PATCH 11/56] Add routing component to vertex types --- src/backend/langflow/graph/graph/constants.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/graph/graph/constants.py b/src/backend/langflow/graph/graph/constants.py index f85761ed4..4317ac99d 100644 --- a/src/backend/langflow/graph/graph/constants.py +++ b/src/backend/langflow/graph/graph/constants.py @@ -15,7 +15,9 @@ from langflow.interface.tools.base import tool_creator from langflow.interface.wrappers.base import wrapper_creator from langflow.utils.lazy_load import LazyLoadDictBase -chat_components = ["ChatInput", "ChatOutput", "TextInput", "SessionID"] +chat_components = ["ChatInput", "ChatOutput", "TextInput"] +# For now the only routing we support is to stop or run the next component +routing_components = ["ShouldRunNext"] class VertexTypesDict(LazyLoadDictBase): @@ -51,6 +53,7 @@ class VertexTypesDict(LazyLoadDictBase): **{t: types.CustomComponentVertex for t in custom_component_creator.to_list()}, **{t: types.RetrieverVertex for t in retriever_creator.to_list()}, **{t: types.ChatVertex for t in chat_components}, + **{t: types.RoutingVertex for t in routing_components}, } def get_custom_component_vertex_type(self): From 94c40aa91a00858d961bb113690b2ad6b578751b Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:58:27 -0300 Subject: [PATCH 12/56] implement routing and next_vertex_to_build --- src/backend/langflow/api/v1/chat.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index fd59f0126..dd0d5da6c 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -20,6 +20,7 @@ from langflow.api.v1.schemas import ( VerticesOrderResponse, ) from langflow.graph.graph.base import Graph +from langflow.graph.vertex.types import RoutingVertex from langflow.services.auth.utils import ( get_current_active_user, get_current_user_for_websocket, @@ -161,6 +162,12 @@ async def build_vertex( artifacts = vertex.artifacts else: raise ValueError(f"No result found for vertex {vertex_id}") + if isinstance(vertex, RoutingVertex): + if vertex._built_object is True: + next_vertex_id = next(graph.next_vertex_to_build()) + else: + next_vertex_id = None + chat_service.set_cache(flow_id, graph) except Exception as exc: params = str(exc) @@ -189,7 +196,7 @@ async def build_vertex( vertex.add_build_time(timedelta) return VertexBuildResponse( - successors=vertex.successors_ids, + next_vertex_id=next_vertex_id, valid=valid, params=params, id=vertex.id, From 528c75933f915d991cf8a865541539899b02586b Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 18:59:48 -0300 Subject: [PATCH 13/56] Update VertexBuildResponse schema field name --- src/backend/langflow/api/v1/schemas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/schemas.py b/src/backend/langflow/api/v1/schemas.py index 8da328195..ca15ad207 100644 --- a/src/backend/langflow/api/v1/schemas.py +++ b/src/backend/langflow/api/v1/schemas.py @@ -236,7 +236,7 @@ class ResultData(BaseModel): class VertexBuildResponse(BaseModel): id: Optional[str] = None - successors: Optional[List[str]] = Field(default_factory=list) + next_vertex_id: Optional[str] = None valid: bool params: Optional[str] """JSON string of the params.""" From b17bbf064a638caefaca26d808174c53da5be4d8 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 22 Feb 2024 19:00:11 -0300 Subject: [PATCH 14/56] Add next_vertex_to_build method to Graph class --- src/backend/langflow/graph/graph/base.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/graph/graph/base.py b/src/backend/langflow/graph/graph/base.py index 4078bac89..0ec5a7923 100644 --- a/src/backend/langflow/graph/graph/base.py +++ b/src/backend/langflow/graph/graph/base.py @@ -1,4 +1,5 @@ from collections import defaultdict, deque +from itertools import chain from typing import Dict, Generator, List, Optional, Type, Union from langchain.chains.base import Chain @@ -49,6 +50,14 @@ class Graph: self._build_graph() self.build_graph_maps() + # vertices_layers is a list of lists ordered by the order the vertices + # should be built. + # We need to create a new method that will take the vertices_layers + # and return the next vertex to be built. + def next_vertex_to_build(self): + """Returns the next vertex to be built.""" + yield from chain.from_iterable(self.vertices_layers) + @property def metadata(self): return { @@ -531,9 +540,11 @@ class Graph: vertices_layers = self.sort_by_avg_build_time(vertices_layers) vertices_layers = self.sort_chat_inputs_first(vertices_layers) self.increment_run_count() - self.vertices_layers = vertices_layers + first_layer = vertices_layers[0] + # save the only the rest + self.vertices_layers = vertices_layers[1:] # Return just the first layer - return vertices_layers[0] + return first_layer def sort_interface_components_first(self, vertices_layers: List[List[str]]) -> List[List[str]]: """Sorts the vertices in the graph so that vertices containing ChatInput or ChatOutput come first.""" From 04f6ee7beacf2f0ff131f0496881294486f71209 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Sat, 2 Mar 2024 16:14:05 -0300 Subject: [PATCH 15/56] Update page size in ComponentsComponent --- .../src/pages/MainPage/components/components/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/components/index.tsx b/src/frontend/src/pages/MainPage/components/components/index.tsx index 6e971b635..86ee65d0c 100644 --- a/src/frontend/src/pages/MainPage/components/components/index.tsx +++ b/src/frontend/src/pages/MainPage/components/components/index.tsx @@ -27,7 +27,7 @@ export default function ComponentsComponent({ const flows = useFlowsManagerStore((state) => state.flows); const setSuccessData = useAlertStore((state) => state.setSuccessData); const setErrorData = useAlertStore((state) => state.setErrorData); - const [pageSize, setPageSize] = useState(10); + const [pageSize, setPageSize] = useState(20); const [pageIndex, setPageIndex] = useState(1); const [loadingScreen, setLoadingScreen] = useState(true); @@ -96,7 +96,7 @@ export default function ComponentsComponent({ function resetFilter() { setPageIndex(1); - setPageSize(10); + setPageSize(20); } return ( From 28edf41fa54e6c2148150eacfbf505238fbee2cd Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Sat, 2 Mar 2024 18:11:46 -0300 Subject: [PATCH 16/56] Fix bug in PromptComponent --- src/backend/langflow/components/prompts/Prompt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/components/prompts/Prompt.py b/src/backend/langflow/components/prompts/Prompt.py index d8afbcb43..975998919 100644 --- a/src/backend/langflow/components/prompts/Prompt.py +++ b/src/backend/langflow/components/prompts/Prompt.py @@ -23,7 +23,7 @@ class PromptComponent(CustomComponent): prompt_template = PromptTemplate.from_template(Text(template)) attributes_to_check = ["text", "page_content"] - for key, value in kwargs.items(): + for key, value in kwargs.copy().items(): for attribute in attributes_to_check: if hasattr(value, attribute): kwargs[key] = getattr(value, attribute) From c44c574c99206238aa217ce807d03309d61838c6 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Sun, 3 Mar 2024 01:24:39 +0100 Subject: [PATCH 17/56] Fixed flexbox in io --- src/frontend/src/components/IOview/index.tsx | 2 +- src/frontend/src/components/codeTabsComponent/index.tsx | 8 +++----- .../src/components/newChatView/chatMessage/index.tsx | 8 ++++---- src/frontend/src/style/applies.css | 6 +++--- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/components/IOview/index.tsx b/src/frontend/src/components/IOview/index.tsx index 87bd8de20..b30136ef7 100644 --- a/src/frontend/src/components/IOview/index.tsx +++ b/src/frontend/src/components/IOview/index.tsx @@ -263,7 +263,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element { )} {haveChat ? ( -
+
{selectedViewField && (
)} - {tab.code} - +
) : idx === 4 ? ( <> diff --git a/src/frontend/src/components/newChatView/chatMessage/index.tsx b/src/frontend/src/components/newChatView/chatMessage/index.tsx index 7c606679f..a619f3f57 100644 --- a/src/frontend/src/components/newChatView/chatMessage/index.tsx +++ b/src/frontend/src/components/newChatView/chatMessage/index.tsx @@ -155,9 +155,9 @@ export default function ChatMessage({ /> )} {chat.thought && chat.thought !== "" && !hidden &&

} -
-
-
+
+
+
{useMemo( () => chatMessage === "" && lockChat ? ( @@ -169,7 +169,7 @@ export default function ChatMessage({ Date: Sun, 3 Mar 2024 01:26:39 +0100 Subject: [PATCH 18/56] Fixed text output not showing display name --- src/frontend/src/components/IOview/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/components/IOview/index.tsx b/src/frontend/src/components/IOview/index.tsx index b30136ef7..1f14ac417 100644 --- a/src/frontend/src/components/IOview/index.tsx +++ b/src/frontend/src/components/IOview/index.tsx @@ -220,7 +220,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element { >
- {output.displayName} + {node.data.node.display_name}
From 67814608697e0b06f654d22311872455bb04cf87 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Sun, 3 Mar 2024 14:40:43 -0300 Subject: [PATCH 19/56] Refactor buildVertices process one layer at a time --- src/frontend/src/stores/flowStore.ts | 23 ++++++--- src/frontend/src/types/api/index.ts | 2 + src/frontend/src/utils/buildUtils.ts | 77 +++++++++++++++------------- 3 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/frontend/src/stores/flowStore.ts b/src/frontend/src/stores/flowStore.ts index a373123e8..9bdd5c9a0 100644 --- a/src/frontend/src/stores/flowStore.ts +++ b/src/frontend/src/stores/flowStore.ts @@ -223,12 +223,10 @@ const useFlowStore = create((set, get) => ({ selection.nodes.some((node) => node.data.type === "ChatInput") && checkChatInput(get().nodes) ) { - useAlertStore - .getState() - .setErrorData({ - title: "Error pasting components", - list: ["You can only have one ChatInput component in the flow"], - }); + useAlertStore.getState().setErrorData({ + title: "Error pasting components", + list: ["You can only have one ChatInput component in the flow"], + }); return; } let minimumX = Infinity; @@ -451,10 +449,23 @@ const useFlowStore = create((set, get) => ({ if (vertexBuildData && vertexBuildData.inactive_vertices) { get().removeFromVerticesBuild(vertexBuildData.inactive_vertices); } + get().verticesBuild && + get().updateVerticesBuild({ + verticesIds: [ + ...get().verticesBuild!.verticesIds, + vertexBuildData.id, + ], + verticesLayers: [ + ...get().verticesBuild!.verticesLayers, + vertexBuildData.next_vertices_ids, + ], + runId: vertexBuildData.run_id, + }); get().addDataToFlowPool( { ...vertexBuildData, buildId }, vertexBuildData.id ); + useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status); } await buildVertices({ diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 6663692dc..06f30fb2c 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -140,7 +140,9 @@ export type VerticesOrderTypeAPI = { export type VertexBuildTypeAPI = { id: string; + next_vertices_ids: Array; inactive_vertices: Array | null; + run_id: string; valid: boolean; params: string; data: VertexDataTypeAPI; diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts index 77fafd029..ce3a542ab 100644 --- a/src/frontend/src/utils/buildUtils.ts +++ b/src/frontend/src/utils/buildUtils.ts @@ -125,50 +125,57 @@ export async function buildVertices({ useFlowStore.getState().updateBuildStatus(verticesIds, BuildStatus.TO_BUILD); useFlowStore.getState().setIsBuilding(true); - + let currentLayerIndex = 0; // Start with the first layer // Set each vertex state to building const buildResults: Array = []; console.log(verticesLayers); - for (const layer of verticesLayers) { - if (onBuildStart) onBuildStart(layer); - for (const id of layer) { - // Check if id is in the list of inactive nodes - if (!verticesIds.includes(id) && onBuildUpdate) { - // If it is, skip building and set the state to inactive - onBuildUpdate(getInactiveVertexData(id), BuildStatus.INACTIVE, runId); - buildResults.push(false); - continue; - } - await buildVertex({ - flowId, - id, - input_value, - onBuildUpdate: (data: VertexBuildTypeAPI, status: BuildStatus) => { - if (onBuildUpdate) onBuildUpdate(data, status, runId); - }, - onBuildError, - verticesIds, - buildResults, - stopBuild: () => { - stop = true; - }, - }); - if (stop) { - break; - } - } + while (currentLayerIndex < verticesLayers.length) { + const currentLayer = verticesLayers[currentLayerIndex]; + if (onBuildStart) onBuildStart(currentLayer); + await Promise.all( + currentLayer.map(async (vertexId) => { + // Check if id is in the list of inactive nodes + if (!verticesIds.includes(vertexId) && onBuildUpdate) { + // If it is, skip building and set the state to inactive + onBuildUpdate( + getInactiveVertexData(vertexId), + BuildStatus.INACTIVE, + runId + ); + buildResults.push(false); + return; + } + await buildVertex({ + flowId, + id: vertexId, + input_value, + onBuildUpdate: (data: VertexBuildTypeAPI, status: BuildStatus) => { + if (onBuildUpdate) onBuildUpdate(data, status, runId); + }, + onBuildError, + verticesIds, + buildResults, + stopBuild: () => { + stop = true; + }, + }); + if (stop) { + return; + } + }) + ); + if (stop) { break; } - } - if (onBuildComplete) { - const allNodesValid = buildResults.every((result) => result); - onBuildComplete(allNodesValid); - useFlowStore.getState().setIsBuilding(false); + if (onBuildComplete) { + const allNodesValid = buildResults.every((result) => result); + onBuildComplete(allNodesValid); + useFlowStore.getState().setIsBuilding(false); + } } } - async function buildVertex({ flowId, id, From c917eeec4ab2a9ac17e617d44778aaa573fa625d Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Sun, 3 Mar 2024 17:05:48 -0300 Subject: [PATCH 20/56] Refactor GenericNode component --- .../src/CustomNodes/GenericNode/index.tsx | 88 +++++++++++-------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index c9844a47d..1f5a168f8 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -138,9 +138,8 @@ export default function GenericNode({ const iconColor = nodeColors[types[data.type]]; const iconName = iconElement || (data.node?.flow ? "group_components" : name); - const iconClassName = `generic-node-icon ${ - !showNode ? " absolute inset-x-6 h-12 w-12 " : "" - }`; + const iconClassName = `generic-node-icon ${!showNode ? " absolute inset-x-6 h-12 w-12 " : "" + }`; if (iconElement && isEmoji) { return nodeIconFragment(iconElement); } else { @@ -268,7 +267,7 @@ export default function GenericNode({ numberOfHandles={handles} showNode={showNode} openAdvancedModal={false} - onCloseAdvancedModal={() => {}} + onCloseAdvancedModal={() => { }} selected={selected} > @@ -390,13 +389,28 @@ export default function GenericNode({ })} data={data} color={ - nodeColors[ - types[data.node?.template[templateField].type!] - ] ?? - nodeColors[ + data.node?.template[templateField].input_types && + data.node?.template[templateField].input_types! + .length > 0 + ? nodeColors[ + data.node?.template[templateField] + .input_types![data.node?.template[templateField] + .input_types!.length - 1] + ] ?? + nodeColors[ + types[ + data.node?.template[templateField] + .input_types![data.node?.template[templateField] + .input_types!.length - 1] + ] + ] + : nodeColors[ data.node?.template[templateField].type! - ] ?? - nodeColors.unknown + ] ?? + nodeColors[ + types[data.node?.template[templateField].type!] + ] ?? + nodeColors.unknown } title={getFieldTitle( data.node?.template!, @@ -440,7 +454,7 @@ export default function GenericNode({ color={nodeColors[types[data.type]] ?? nodeColors.unknown} title={ data.node?.output_types && - data.node.output_types.length > 0 + data.node.output_types.length > 0 ? data.node.output_types.join(" | ") : data.type } @@ -479,10 +493,10 @@ export default function GenericNode({
{typeof validationStatus.params === "string" ? `${durationString}\n${validationStatus.params}` - .split("\n") - .map((line, index) => ( -
{line}
- )) + .split("\n") + .map((line, index) => ( +
{line}
+ )) : durationString}
) @@ -569,7 +583,7 @@ export default function GenericNode({ }} > {(data.node?.description === "" || !data.node?.description) && - nameEditable + nameEditable ? "Double Click to Edit Description" : data.node?.description}
@@ -590,7 +604,7 @@ export default function GenericNode({ .map((templateField: string, idx) => (
{data.node!.template[templateField].show && - !data.node!.template[templateField].advanced ? ( + !data.node!.template[templateField].advanced ? ( 0 + data.node?.template[templateField].input_types! + .length > 0 ? nodeColors[ - data.node?.template[templateField] - .input_types![0] - ] ?? - nodeColors[ - types[ - data.node?.template[templateField] - .input_types![0] - ] - ] + data.node?.template[templateField] + .input_types![data.node?.template[templateField] + .input_types!.length - 1] + ] ?? + nodeColors[ + types[ + data.node?.template[templateField] + .input_types![data.node?.template[templateField] + .input_types!.length - 1] + ] + ] : nodeColors[ - data.node?.template[templateField].type! - ] ?? - nodeColors[ - types[data.node?.template[templateField].type!] - ] ?? - nodeColors.unknown + data.node?.template[templateField].type! + ] ?? + nodeColors[ + types[data.node?.template[templateField].type!] + ] ?? + nodeColors.unknown } title={getFieldTitle( data.node?.template!, @@ -674,9 +690,9 @@ export default function GenericNode({ data={data} color={ (data.node?.output_types && - data.node.output_types.length > 0 + data.node.output_types.length > 0 ? nodeColors[data.node.output_types[0]] ?? - nodeColors[types[data.node.output_types[0]]] + nodeColors[types[data.node.output_types[0]]] : nodeColors[types[data.type]]) ?? nodeColors.unknown } title={ From 4e63f2a6ca60f63ea549fd25786b236138cb0d00 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Sun, 3 Mar 2024 17:36:43 -0300 Subject: [PATCH 21/56] Refactor getFieldTitle function in utils.ts --- src/frontend/src/utils/utils.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index d6ebff378..22fe93185 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -640,7 +640,5 @@ export function getFieldTitle( ): string { return template[templateField].display_name ? template[templateField].display_name! - : template[templateField].name - ? toTitleCase(template[templateField].name!, true) - : toTitleCase(templateField, true); + : template[templateField].name ?? templateField; } From 05d53c54283c632d7ae0d36f7009a8d062bd0f0d Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Sun, 3 Mar 2024 17:42:34 -0300 Subject: [PATCH 22/56] Fix build button running on text selection --- .../src/CustomNodes/GenericNode/index.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 1f5a168f8..8e95946f0 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -395,13 +395,13 @@ export default function GenericNode({ ? nodeColors[ data.node?.template[templateField] .input_types![data.node?.template[templateField] - .input_types!.length - 1] + .input_types!.length - 1] ] ?? nodeColors[ types[ data.node?.template[templateField] .input_types![data.node?.template[templateField] - .input_types!.length - 1] + .input_types!.length - 1] ] ] : nodeColors[ @@ -475,12 +475,6 @@ export default function GenericNode({