From 2bbbf44b39374546bf01fe7973d99455fc8ee211 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 06:41:34 -0300 Subject: [PATCH 1/7] =?UTF-8?q?=F0=9F=90=9B=20fix(endpoints.py):=20change?= =?UTF-8?q?=20get=5Fall=20function=20signature=20to=20include=20settings?= =?UTF-8?q?=5Fmanager=20as=20a=20dependency=20to=20improve=20code=20readab?= =?UTF-8?q?ility=20=F0=9F=90=9B=20fix(flows.py):=20change=20update=5Fflow?= =?UTF-8?q?=20function=20signature=20to=20include=20settings=5Fmanager=20a?= =?UTF-8?q?s=20a=20dependency=20to=20improve=20code=20readability=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(login.py):=20change=20auto=5Flogin=20functio?= =?UTF-8?q?n=20signature=20to=20include=20settings=5Fmanager=20as=20a=20de?= =?UTF-8?q?pendency=20to=20improve=20code=20readability=20=F0=9F=90=9B=20f?= =?UTF-8?q?ix(users.py):=20change=20add=5Fuser=20function=20signature=20to?= =?UTF-8?q?=20include=20session=20as=20a=20dependency=20to=20improve=20cod?= =?UTF-8?q?e=20readability=20=F0=9F=90=9B=20fix(users.py):=20change=20read?= =?UTF-8?q?=5Fall=5Fusers=20function=20signature=20to=20include=20session?= =?UTF-8?q?=20as=20a=20dependency=20to=20improve=20code=20readability=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(users.py):=20change=20patch=5Fuser=20functio?= =?UTF-8?q?n=20signature=20to=20include=20session=20as=20a=20dependency=20?= =?UTF-8?q?to=20improve=20code=20readability=20=F0=9F=90=9B=20fix(users.py?= =?UTF-8?q?):=20change=20delete=5Fuser=20function=20signature=20to=20inclu?= =?UTF-8?q?de=20session=20as=20a=20dependency=20to=20improve=20code=20read?= =?UTF-8?q?ability=20=F0=9F=90=9B=20fix(users.py):=20change=20add=5Fsuper?= =?UTF-8?q?=5Fuser=5Ffor=5Ftesting=5Fpurposes=5Fdelete=5Fme=5Fbefore=5Fmer?= =?UTF-8?q?ge=5Finto=5Fdev=20function=20signature=20to=20include=20session?= =?UTF-8?q?=20as=20a=20dependency=20to=20improve=20code=20readability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/endpoints.py | 7 +++-- src/backend/langflow/api/v1/flows.py | 2 +- src/backend/langflow/api/v1/login.py | 6 ++-- src/backend/langflow/api/v1/users.py | 38 ++++++++++++------------ 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 813aaf415..05477a859 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -34,14 +34,15 @@ from sqlmodel import Session router = APIRouter(tags=["Base"]) -@router.get("/all") -def get_all(current_user: User = Depends(get_current_active_user)): +@router.get("/all", dependencies=[Depends(get_current_active_user)]) +def get_all( + settings_manager=Depends(get_settings_manager), +): logger.debug("Building langchain types dict") native_components = build_langchain_types_dict() # custom_components is a list of dicts # need to merge all the keys into one dict custom_components_from_file: dict[str, Any] = {} - settings_manager = get_settings_manager() if settings_manager.settings.COMPONENTS_PATH: logger.info( f"Building custom components from {settings_manager.settings.COMPONENTS_PATH}" diff --git a/src/backend/langflow/api/v1/flows.py b/src/backend/langflow/api/v1/flows.py index b215b9f95..be65048d4 100644 --- a/src/backend/langflow/api/v1/flows.py +++ b/src/backend/langflow/api/v1/flows.py @@ -83,6 +83,7 @@ def update_flow( flow_id: UUID, flow: FlowUpdate, current_user: User = Depends(get_current_active_user), + settings_manager=Depends(get_settings_manager), ): """Update a flow.""" @@ -90,7 +91,6 @@ def update_flow( if not db_flow: raise HTTPException(status_code=404, detail="Flow not found") flow_data = flow.dict(exclude_unset=True) - settings_manager = get_settings_manager() if settings_manager.settings.REMOVE_API_KEYS: flow_data = remove_api_keys(flow_data) for key, value in flow_data.items(): diff --git a/src/backend/langflow/api/v1/login.py b/src/backend/langflow/api/v1/login.py index afe67a916..4241b8d47 100644 --- a/src/backend/langflow/api/v1/login.py +++ b/src/backend/langflow/api/v1/login.py @@ -34,9 +34,9 @@ async def login_to_get_access_token( @router.get("/auto_login") -async def auto_login(db: Session = Depends(get_session)): - settings_manager = get_settings_manager() - +async def auto_login( + db: Session = Depends(get_session), settings_manager=Depends(get_settings_manager) +): if settings_manager.auth_settings.AUTO_LOGIN: return create_user_longterm_token(db) diff --git a/src/backend/langflow/api/v1/users.py b/src/backend/langflow/api/v1/users.py index 5094409cb..517dd7f69 100644 --- a/src/backend/langflow/api/v1/users.py +++ b/src/backend/langflow/api/v1/users.py @@ -29,7 +29,7 @@ router = APIRouter(tags=["Users"]) @router.post("/user", response_model=UserRead, status_code=201) def add_user( user: UserCreate, - db: Session = Depends(get_session), + session: Session = Depends(get_session), ) -> User: """ Add a new user to the database. @@ -38,11 +38,11 @@ def add_user( try: new_user.password = get_password_hash(user.password) - db.add(new_user) - db.commit() - db.refresh(new_user) + session.add(new_user) + session.commit() + session.refresh(new_user) except IntegrityError as e: - db.rollback() + session.rollback() raise HTTPException( status_code=400, detail="This username is unavailable." ) from e @@ -65,16 +65,16 @@ def read_all_users( skip: int = 0, limit: int = 10, current_user: Session = Depends(get_current_active_superuser), - db: Session = Depends(get_session), + session: Session = Depends(get_session), ) -> UsersResponse: """ Retrieve a list of users from the database with pagination. """ query = select(User).offset(skip).limit(limit) - users = db.execute(query).fetchall() + users = session.execute(query).fetchall() count_query = select(func.count()).select_from(User) # type: ignore - total_count = db.execute(count_query).scalar() + total_count = session.execute(count_query).scalar() return UsersResponse( total_count=total_count, # type: ignore @@ -87,19 +87,19 @@ def patch_user( user_id: UUID, user: UserUpdate, _: Session = Depends(get_current_active_user), - db: Session = Depends(get_session), + session: Session = Depends(get_session), ) -> User: """ Update an existing user's data. """ - return update_user(user_id, user, db) + return update_user(user_id, user, session) @router.delete("/user/{user_id}") def delete_user( user_id: UUID, current_user: User = Depends(get_current_active_superuser), - db: Session = Depends(get_session), + session: Session = Depends(get_session), ) -> dict: """ Delete a user from the database. @@ -113,12 +113,12 @@ def delete_user( status_code=403, detail="You don't have the permission to delete this user" ) - user_db = db.query(User).filter(User.id == user_id).first() + user_db = session.query(User).filter(User.id == user_id).first() if not user_db: raise HTTPException(status_code=404, detail="User not found") - db.delete(user_db) - db.commit() + session.delete(user_db) + session.commit() return {"detail": "User deleted"} @@ -126,7 +126,7 @@ def delete_user( # TODO: REMOVE - Just for testing purposes @router.post("/super_user", response_model=User) def add_super_user_for_testing_purposes_delete_me_before_merge_into_dev( - db: Session = Depends(get_session), + session: Session = Depends(get_session), ) -> User: """ Add a superuser for testing purposes. @@ -141,11 +141,11 @@ def add_super_user_for_testing_purposes_delete_me_before_merge_into_dev( ) try: - db.add(new_user) - db.commit() - db.refresh(new_user) + session.add(new_user) + session.commit() + session.refresh(new_user) except IntegrityError as e: - db.rollback() + session.rollback() raise HTTPException(status_code=400, detail="User exists") from e return new_user From 84a0d3acb39c14f8e0f51a2cd8f2dac11904fc89 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 06:42:01 -0300 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=94=A7=20fix(chat.py):=20remove=20unu?= =?UTF-8?q?sed=20imports=20and=20type=20hints=20to=20improve=20code=20read?= =?UTF-8?q?ability=20=E2=9C=A8=20feat(chat.py):=20add=20dependency=20injec?= =?UTF-8?q?tion=20for=20ChatManager=20in=20chat=20and=20init=5Fbuild=20rou?= =?UTF-8?q?tes=20to=20improve=20modularity=20and=20testability=20?= =?UTF-8?q?=F0=9F=94=A7=20fix(chat.py):=20remove=20duplicate=20instantiati?= =?UTF-8?q?on=20of=20ChatManager=20in=20chat=20and=20init=5Fbuild=20routes?= =?UTF-8?q?=20to=20improve=20efficiency=20=F0=9F=94=A7=20fix(chat.py):=20r?= =?UTF-8?q?emove=20duplicate=20instantiation=20of=20ChatManager=20in=20str?= =?UTF-8?q?eam=5Fbuild=20route=20to=20improve=20efficiency=20=F0=9F=94=A7?= =?UTF-8?q?=20fix(utils.py):=20add=20missing=20import=20for=20ChatManager?= =?UTF-8?q?=20in=20get=5Fchat=5Fmanager=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/chat.py | 20 ++++++++++---------- src/backend/langflow/services/utils.py | 8 +++++++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index 9d322b03c..2c276c75d 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -11,17 +11,14 @@ from fastapi.responses import StreamingResponse from langflow.api.utils import build_input_keys_response from langflow.api.v1.schemas import BuildStatus, BuiltResponse, InitResponse, StreamData -from langflow.services import service_manager, ServiceType from langflow.graph.graph.base import Graph from langflow.services.auth.utils import get_current_active_user, get_current_user -from langflow.services.utils import get_session +from langflow.services.utils import get_chat_manager, get_session from langflow.utils.logger import logger from cachetools import LRUCache from sqlmodel import Session -from typing import TYPE_CHECKING +from langflow.services.chat.manager import ChatManager -if TYPE_CHECKING: - from langflow.services.chat.manager import ChatManager router = APIRouter(tags=["Chat"]) @@ -34,6 +31,7 @@ async def chat( websocket: WebSocket, token: str = Query(...), db: Session = Depends(get_session), + chat_manager: "ChatManager" = Depends(get_chat_manager), ): """Websocket endpoint for chat.""" try: @@ -48,7 +46,6 @@ async def chat( code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized" ) - chat_manager: "ChatManager" = service_manager.get(ServiceType.CHAT_MANAGER) if client_id in chat_manager.in_memory_cache: await chat_manager.handle_websocket(client_id, websocket) else: @@ -72,7 +69,10 @@ async def chat( @router.post("/build/init/{flow_id}", response_model=InitResponse, status_code=201) async def init_build( - graph_data: dict, flow_id: str, current_user=Depends(get_current_active_user) + graph_data: dict, + flow_id: str, + current_user=Depends(get_current_active_user), + chat_manager: "ChatManager" = Depends(get_chat_manager), ): """Initialize the build by storing graph data and returning a unique session ID.""" @@ -87,7 +87,6 @@ async def init_build( return InitResponse(flowId=flow_id) # Delete from cache if already exists - chat_manager = service_manager.get(ServiceType.CHAT_MANAGER) if flow_id in chat_manager.in_memory_cache: with chat_manager.in_memory_cache._lock: chat_manager.in_memory_cache.delete(flow_id) @@ -123,7 +122,9 @@ async def build_status(flow_id: str): @router.get("/build/stream/{flow_id}", response_class=StreamingResponse) -async def stream_build(flow_id: str): +async def stream_build( + flow_id: str, chat_manager: "ChatManager" = Depends(get_chat_manager) +): """Stream the build process based on stored flow data.""" async def event_stream(flow_id): @@ -202,7 +203,6 @@ async def stream_build(flow_id: str): "handle_keys": [], } yield str(StreamData(event="message", data=input_keys_response)) - chat_manager = service_manager.get(ServiceType.CHAT_MANAGER) chat_manager.set_cache(flow_id, langchain_object) # We need to reset the chat history chat_manager.chat_history.empty_history(flow_id) diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index 6860f8928..708377d14 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -5,6 +5,8 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: from langflow.services.database.manager import DatabaseManager from langflow.services.settings.manager import SettingsManager + from langflow.services.chat.manager import ChatManager + from sqlmodel import Session def get_settings_manager() -> "SettingsManager": @@ -15,6 +17,10 @@ def get_db_manager() -> "DatabaseManager": return service_manager.get(ServiceType.DATABASE_MANAGER) -def get_session(): +def get_session() -> "Session": db_manager = service_manager.get(ServiceType.DATABASE_MANAGER) yield from db_manager.get_session() + + +def get_chat_manager() -> "ChatManager": + return service_manager.get(ServiceType.CHAT_MANAGER) From 37ebbf4e65bfae98f54515c888df106c1b107bfd Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 06:42:41 -0300 Subject: [PATCH 3/7] Formatting --- .../DropdownButtonComponent/index.tsx | 4 +--- src/frontend/src/contexts/tabsContext.tsx | 6 ++++-- src/frontend/src/pages/MainPage/index.tsx | 19 +++++++++++++------ src/frontend/src/types/components/index.ts | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/components/DropdownButtonComponent/index.tsx b/src/frontend/src/components/DropdownButtonComponent/index.tsx index 1ddddb3c1..784a08528 100644 --- a/src/frontend/src/components/DropdownButtonComponent/index.tsx +++ b/src/frontend/src/components/DropdownButtonComponent/index.tsx @@ -39,9 +39,7 @@ export default function DropdownButton({ }} > {!showOptions ? ( - + ) : ( )} diff --git a/src/frontend/src/contexts/tabsContext.tsx b/src/frontend/src/contexts/tabsContext.tsx index 339ad67b5..49de70974 100644 --- a/src/frontend/src/contexts/tabsContext.tsx +++ b/src/frontend/src/contexts/tabsContext.tsx @@ -315,9 +315,11 @@ export function TabsProvider({ children }: { children: ReactNode }) { input.type = "file"; input.accept = ".json"; // add a change event listener to the file input - id = await new Promise(resolve => { + id = await new Promise((resolve) => { input.onchange = async (e: Event) => { - if ((e.target as HTMLInputElement).files![0].type === "application/json") { + if ( + (e.target as HTMLInputElement).files![0].type === "application/json" + ) { const currentfile = (e.target as HTMLInputElement).files![0]; let text = await currentfile.text(); let flow: FlowType = JSON.parse(text); diff --git a/src/frontend/src/pages/MainPage/index.tsx b/src/frontend/src/pages/MainPage/index.tsx index 364519ea8..9582d4c57 100644 --- a/src/frontend/src/pages/MainPage/index.tsx +++ b/src/frontend/src/pages/MainPage/index.tsx @@ -1,5 +1,6 @@ import { useContext, useEffect } from "react"; import { Link, useNavigate } from "react-router-dom"; +import DropdownButton from "../../components/DropdownButtonComponent"; import { CardComponent } from "../../components/cardComponent"; import IconComponent from "../../components/genericIconComponent"; import Header from "../../components/headerComponent"; @@ -7,7 +8,6 @@ import { SkeletonCardComponent } from "../../components/skeletonCardComponent"; import { Button } from "../../components/ui/button"; import { USER_PROJECTS_HEADER } from "../../constants/constants"; import { TabsContext } from "../../contexts/tabsContext"; -import DropdownButton from "../../components/DropdownButtonComponent"; export default function HomePage(): JSX.Element { const { flows, @@ -15,12 +15,19 @@ export default function HomePage(): JSX.Element { downloadFlows, uploadFlows, addFlow, - removeFlow, uploadFlow, + removeFlow, + uploadFlow, isLoading, } = useContext(TabsContext); - const dropdownOptions = [{name: "Import from JSON", onBtnClick: () => uploadFlow(true).then((id) => { - navigate("/flow/" + id); - })}] + const dropdownOptions = [ + { + name: "Import from JSON", + onBtnClick: () => + uploadFlow(true).then((id) => { + navigate("/flow/" + id); + }), + }, + ]; // Set a null id useEffect(() => { @@ -73,7 +80,7 @@ export default function HomePage(): JSX.Element { - Manage your personal projects. Download or upload your collection. + Manage your personal projects. Download or upload your collection.
{isLoading && flows.length == 0 ? ( diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index b61ddf07d..4b72ef36a 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -548,5 +548,5 @@ export type fetchErrorComponentType = { export type dropdownButtonPropsType = { firstButtonName: string; onFirstBtnClick: () => void; - options: Array<{ name: string; onBtnClick: () => void; }>; + options: Array<{ name: string; onBtnClick: () => void }>; }; From 43864904efd4051a91ee9e9160e9d97f7ba40a6e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 07:00:38 -0300 Subject: [PATCH 4/7] =?UTF-8?q?=F0=9F=94=A7=20chore(Makefile):=20update=20?= =?UTF-8?q?mypy=20command=20to=20only=20check=20files=20in=20src/backend/l?= =?UTF-8?q?angflow=20directory=20to=20improve=20performance=20and=20reduce?= =?UTF-8?q?=20noise=20in=20the=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 59dd4a82d..59f326853 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ format: cd src/frontend && npm run format lint: - poetry run mypy --exclude .venv . + poetry run mypy src/backend/langflow poetry run black . --check poetry run ruff . --fix From 833fb4ad8fdefba08477c7d520293697c129265e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 07:01:05 -0300 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=94=80=20chore(utils.py):=20add=20typ?= =?UTF-8?q?e=20hint=20for=20get=5Fsession()=20function=20to=20indicate=20i?= =?UTF-8?q?t=20returns=20a=20generator=20instead=20of=20a=20Session=20obje?= =?UTF-8?q?ct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index 708377d14..8b32aef02 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -1,5 +1,5 @@ from langflow.services import ServiceType, service_manager -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Generator if TYPE_CHECKING: @@ -17,7 +17,7 @@ def get_db_manager() -> "DatabaseManager": return service_manager.get(ServiceType.DATABASE_MANAGER) -def get_session() -> "Session": +def get_session() -> Generator["Session", None, None]: db_manager = service_manager.get(ServiceType.DATABASE_MANAGER) yield from db_manager.get_session() From 53c5a3ccdeef6baca22ae2136111f79091bcce88 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 07:05:10 -0300 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20make=20front?= =?UTF-8?q?end=5Fnode=20field=20in=20PromptValidationResponse=20optional?= =?UTF-8?q?=20to=20handle=20cases=20where=20it=20is=20not=20provided?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/base.py b/src/backend/langflow/api/v1/base.py index acffc1bc3..b1071bea2 100644 --- a/src/backend/langflow/api/v1/base.py +++ b/src/backend/langflow/api/v1/base.py @@ -42,7 +42,7 @@ class CodeValidationResponse(BaseModel): class PromptValidationResponse(BaseModel): input_variables: list # object return for tweak call - frontend_node: FrontendNodeRequest | object + frontend_node: Optional[FrontendNodeRequest] = None INVALID_CHARACTERS = { From 2ab3fcb28a3fbabd3507deab7b03ae288d5555a1 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Sep 2023 10:04:21 -0300 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20set=20defaul?= =?UTF-8?q?t=20value=20of=20frontend=5Fnode=20to=20None=20in=20ValidatePro?= =?UTF-8?q?mptRequest=20class=20to=20avoid=20potential=20NoneType=20errors?= =?UTF-8?q?=20=F0=9F=90=9B=20fix(validate.py):=20set=20frontend=5Fnode=20t?= =?UTF-8?q?o=20None=20instead=20of=20an=20empty=20dictionary=20in=20post?= =?UTF-8?q?=5Fvalidate=5Fprompt=20function=20to=20align=20with=20the=20def?= =?UTF-8?q?ault=20value=20in=20ValidatePromptRequest=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/base.py | 2 +- src/backend/langflow/api/v1/validate.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/api/v1/base.py b/src/backend/langflow/api/v1/base.py index b1071bea2..f2c2f3f59 100644 --- a/src/backend/langflow/api/v1/base.py +++ b/src/backend/langflow/api/v1/base.py @@ -22,7 +22,7 @@ class ValidatePromptRequest(BaseModel): name: str template: str # optional for tweak call - frontend_node: Optional[FrontendNodeRequest] + frontend_node: Optional[FrontendNodeRequest] = None # Build ValidationResponse class for {"imports": {"errors": []}, "function": {"errors": []}} diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py index da76d25bc..64ef60549 100644 --- a/src/backend/langflow/api/v1/validate.py +++ b/src/backend/langflow/api/v1/validate.py @@ -35,7 +35,7 @@ def post_validate_prompt(prompt_request: ValidatePromptRequest): if prompt_request.frontend_node is None: return PromptValidationResponse( input_variables=input_variables, - frontend_node={}, + frontend_node=None, ) old_custom_fields = get_old_custom_fields(prompt_request)