diff --git a/src/backend/langflow/initial_setup/__init__.py b/src/backend/langflow/initial_setup/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/initial_setup/setup.py b/src/backend/langflow/initial_setup/setup.py new file mode 100644 index 000000000..3b9ed8d5e --- /dev/null +++ b/src/backend/langflow/initial_setup/setup.py @@ -0,0 +1,73 @@ +import json +from datetime import datetime +from pathlib import Path + +from loguru import logger +from sqlmodel import select + +from langflow.services.database.models.flow.model import Flow +from langflow.services.deps import get_session + +STARTER_FOLDER_NAME = "Starter Projects" + + +# In the folder ./starter_projects we have a few JSON files that represent +# starter projects. We want to load these into the database so that users +# can use them as a starting point for their own projects. +def load_starter_projects(): + # Load the starter projects from the JSON files + # using Pathlib's glob method + starter_projects = [] + folder = Path(__file__).parent / "starter_projects" + for file in folder.glob("*.json"): + with open(file, "r") as f: + starter_projects.append(json.load(f)) + logger.info(f"Loaded starter project {file}") + return starter_projects + + +# We want to load the starter projects into the database +def create_or_update_starter_projects(): + session = next(get_session()) + starter_projects = load_starter_projects() + for project in starter_projects: + # Check if the project already exists in the database + project_name = project.get("name") + project_description = project.get("description") + project_is_component = project.get("is_component") + project_updated_at = project.get("updated_at") + # 2024-03-05T21:59:59.738081 + updated_at_datetime = datetime.strptime( + project_updated_at, "%Y-%m-%dT%H:%M:%S.%f" + ) + project_data = project.get("data") + if project_name and project_data: + existing_project = session.exec( + select(Flow).where( + Flow.name == project_name, Flow.folder == STARTER_FOLDER_NAME + ) + ).first() + if existing_project: + logger.info(f"Updating starter project {project_name}") + existing_project.data = project_data + existing_project.folder = STARTER_FOLDER_NAME + existing_project.description = project_description + existing_project.is_component = project_is_component + existing_project.updated_at = updated_at_datetime + # Now we need to update the project in the database + session.add(existing_project) + else: + logger.info(f"Creating starter project {project_name}") + session.add( + Flow( + name=project_name, + description=project_description, + is_component=project_is_component, + updated_at=updated_at_datetime, + folder=STARTER_FOLDER_NAME, + data=project_data, + ) + ) + session.commit() + session.close() + logger.info("Starter projects loaded into database") diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 4b4c19a25..7c34d9b08 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -8,7 +8,9 @@ from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles + from langflow.api import router +from langflow.initial_setup.setup import create_or_update_starter_projects from langflow.interface.utils import setup_llm_caching from langflow.services.plugins.langfuse_plugin import LangfuseInstance from langflow.services.utils import initialize_services, teardown_services @@ -18,9 +20,12 @@ from langflow.utils.logger import configure def get_lifespan(fix_migration=False, socketio_server=None): @asynccontextmanager async def lifespan(app: FastAPI): - initialize_services(fix_migration=fix_migration, socketio_server=socketio_server) + initialize_services( + fix_migration=fix_migration, socketio_server=socketio_server + ) setup_llm_caching() LangfuseInstance.update() + create_or_update_starter_projects() yield teardown_services() @@ -31,7 +36,9 @@ def create_app(): """Create the FastAPI app and include the router.""" configure() - socketio_server = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", logger=True) + socketio_server = socketio.AsyncServer( + async_mode="asgi", cors_allowed_origins="*", logger=True + ) lifespan = get_lifespan(socketio_server=socketio_server) app = FastAPI(lifespan=lifespan) origins = ["*"] @@ -98,7 +105,9 @@ def get_static_files_dir(): return frontend_path / "frontend" -def setup_app(static_files_dir: Optional[Path] = None, backend_only: bool = False) -> FastAPI: +def setup_app( + static_files_dir: Optional[Path] = None, backend_only: bool = False +) -> FastAPI: """Setup the FastAPI app.""" # get the directory of the current file if not static_files_dir: @@ -114,6 +123,7 @@ def setup_app(static_files_dir: Optional[Path] = None, backend_only: bool = Fals if __name__ == "__main__": import uvicorn + from langflow.__main__ import get_number_of_workers configure()