diff --git a/src/backend/langflow/api/chat.py b/src/backend/langflow/api/chat.py index 4afa6c22f..9de93abf0 100644 --- a/src/backend/langflow/api/chat.py +++ b/src/backend/langflow/api/chat.py @@ -9,7 +9,7 @@ from fastapi import ( from langflow.api.chat_manager import ChatManager from langflow.utils.logger import logger -router = APIRouter() +router = APIRouter(tags=["Chat"]) chat_manager = ChatManager() diff --git a/src/backend/langflow/api/database.py b/src/backend/langflow/api/database.py new file mode 100644 index 000000000..f6e5cae47 --- /dev/null +++ b/src/backend/langflow/api/database.py @@ -0,0 +1,103 @@ +from typing import List +from uuid import UUID +from langflow.api.schemas import FlowListCreate +from langflow.database.models.flow import Flow, FlowCreate, FlowRead +from langflow.database.base import get_session +from sqlmodel import Session, select +from fastapi import APIRouter, Depends, HTTPException + + +from fastapi import File, UploadFile +import json + +# build router +router = APIRouter(prefix="/flows", tags=["Flows"]) + + +@router.post("/", response_model=FlowRead) +def create_flow(*, session: Session = Depends(get_session), flow: FlowCreate): + """Create a new flow.""" + db_flow = Flow.from_orm(flow) + session.add(db_flow) + session.commit() + session.refresh(db_flow) + return db_flow + + +@router.get("/", response_model=list[FlowRead]) +def read_flows(*, session: Session = Depends(get_session)): + """Read all flows.""" + flows = session.exec(select(Flow)).all() + return flows + + +@router.get("/{flow_id}", response_model=FlowRead) +def read_flow(*, session: Session = Depends(get_session), flow_id: UUID): + """Read a flow.""" + flow = session.get(Flow, flow_id) + if not flow: + raise HTTPException(status_code=404, detail="Flow not found") + return flow + + +@router.put("/{flow_id}", response_model=FlowRead) +def update_flow( + *, session: Session = Depends(get_session), flow_id: UUID, flow: FlowCreate +): + """Update a flow.""" + db_flow = session.get(Flow, flow_id) + if not db_flow: + raise HTTPException(status_code=404, detail="Flow not found") + update_data = flow.dict(exclude_unset=True) + for key, value in update_data.items(): + setattr(db_flow, key, value) + session.add(db_flow) + session.commit() + session.refresh(db_flow) + return db_flow + + +@router.delete("/{flow_id}") +def delete_flow(*, session: Session = Depends(get_session), flow_id: UUID): + """Delete a flow.""" + flow = session.get(Flow, flow_id) + if not flow: + raise HTTPException(status_code=404, detail="Flow not found") + session.delete(flow) + session.commit() + return {"message": "Flow deleted successfully"} + + +# Define a new model to handle multiple flows + + +@router.post("/batch/", response_model=List[FlowRead]) +def create_flows(*, session: Session = Depends(get_session), flow_list: FlowListCreate): + """Create multiple new flows.""" + db_flows = [] + for flow in flow_list.flows: + db_flow = Flow.from_orm(flow) + session.add(db_flow) + db_flows.append(db_flow) + session.commit() + for db_flow in db_flows: + session.refresh(db_flow) + return db_flows + + +@router.post("/upload/", response_model=List[FlowRead]) +async def upload_file( + *, session: Session = Depends(get_session), file: UploadFile = File(...) +): + """Upload flows from a file.""" + contents = await file.read() + data = json.loads(contents) + flow_list = FlowListCreate(**data) + return create_flows(session=session, flow_list=flow_list) + + +@router.get("/download/") +async def download_file(*, session: Session = Depends(get_session)): + """Download all flows as a file.""" + flows = read_flows(session=session) + return {"file": json.dumps([flow.dict() for flow in flows])} diff --git a/src/backend/langflow/api/endpoints.py b/src/backend/langflow/api/endpoints.py index 021a81ca8..dacdad64b 100644 --- a/src/backend/langflow/api/endpoints.py +++ b/src/backend/langflow/api/endpoints.py @@ -1,7 +1,7 @@ -import logging +from langflow.utils.logger import logger from importlib.metadata import version -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, File, HTTPException, UploadFile from langflow.api.schemas import ( ExportedFlow, @@ -11,10 +11,10 @@ from langflow.api.schemas import ( ) from langflow.interface.run import process_graph_cached from langflow.interface.types import build_langchain_types_dict +from langflow.cache import cache_manager # build router -router = APIRouter() -logger = logging.getLogger(__name__) +router = APIRouter(tags=["Base"]) @router.get("/all") @@ -45,3 +45,11 @@ def get_version(): @router.get("/health") def get_health(): return {"status": "OK"} + + +# Make an endpoint to upload a file using the client_id and +# cache the file in the backend +@router.post("/uploadfile/{client_id}") +async def create_upload_file(client_id: str, file: UploadFile = File(...)): + + # TODO: Implement this endpoint diff --git a/src/backend/langflow/api/schemas.py b/src/backend/langflow/api/schemas.py index f73b0642d..a9cb4dcb6 100644 --- a/src/backend/langflow/api/schemas.py +++ b/src/backend/langflow/api/schemas.py @@ -1,4 +1,5 @@ from typing import Any, Dict, List, Union +from langflow.database.models.flow import FlowCreate from pydantic import BaseModel, validator @@ -68,3 +69,7 @@ class FileResponse(ChatMessage): if v not in ["image", "csv"]: raise ValueError("data_type must be image or csv") return v + + +class FlowListCreate(BaseModel): + flows: List[FlowCreate] diff --git a/src/backend/langflow/api/validate.py b/src/backend/langflow/api/validate.py index 0e2a7752c..fade4bdf8 100644 --- a/src/backend/langflow/api/validate.py +++ b/src/backend/langflow/api/validate.py @@ -15,7 +15,7 @@ from langflow.utils.logger import logger from langflow.utils.validate import validate_code # build router -router = APIRouter(prefix="/validate", tags=["validate"]) +router = APIRouter(prefix="/validate", tags=["Validate"]) @router.post("/code", status_code=200, response_model=CodeValidationResponse) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 56cc32e46..75c19bd25 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -4,6 +4,14 @@ from fastapi.middleware.cors import CORSMiddleware from langflow.api.chat import router as chat_router from langflow.api.endpoints import router as endpoints_router from langflow.api.validate import router as validate_router +from langflow.api.database import router as database_router +from langflow.utils.logger import logger +from langflow.database.base import create_db_and_tables +from fastapi import APIRouter, HTTPException + + +# build router +router = APIRouter() def create_app(): @@ -25,6 +33,10 @@ def create_app(): app.include_router(endpoints_router) app.include_router(validate_router) app.include_router(chat_router) + app.include_router(database_router) + + app.on_event("startup")(create_db_and_tables) + return app