From 28ec8338f016dfe8f58c621178ff3db9a0d72093 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Tue, 30 May 2023 23:40:32 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(endpoints.py):=20import=20sa?= =?UTF-8?q?ve=5Fuploaded=5Ffile=20function=20from=20cache.base=20module=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(graph/base.py):=20change=20file=5Fpath=20ass?= =?UTF-8?q?ignment=20to=20use=20the=20new=20file=5Fpath=20key=20in=20value?= =?UTF-8?q?=20dict=20=F0=9F=90=9B=20fix(template/field/base.py):=20change?= =?UTF-8?q?=20content=20key=20to=20file=5Fpath=20key=20in=20result=20dict?= =?UTF-8?q?=20=E2=9C=A8=20feat(endpoints.py):=20add=20endpoint=20to=20uplo?= =?UTF-8?q?ad=20file=20=E2=9C=A8=20feat(cache/base.py):=20add=20function?= =?UTF-8?q?=20to=20save=20uploaded=20file=20to=20cache=20The=20save=5Fuplo?= =?UTF-8?q?aded=5Ffile=20function=20was=20not=20being=20imported=20in=20th?= =?UTF-8?q?e=20endpoints.py=20module,=20causing=20a=20NameError=20when=20t?= =?UTF-8?q?rying=20to=20use=20it.=20The=20file=5Fpath=20variable=20in=20th?= =?UTF-8?q?e=20Node=20class=20was=20being=20assigned=20the=20value=20of=20?= =?UTF-8?q?the=20content=20key=20in=20the=20value=20dict,=20but=20it=20sho?= =?UTF-8?q?uld=20be=20assigned=20the=20value=20of=20the=20file=5Fpath=20ke?= =?UTF-8?q?y=20instead.=20The=20content=20key=20in=20the=20TemplateFieldCr?= =?UTF-8?q?eator=20class=20was=20changed=20to=20file=5Fpath=20to=20better?= =?UTF-8?q?=20reflect=20its=20purpose.=20An=20endpoint=20to=20upload=20fil?= =?UTF-8?q?es=20was=20added=20to=20the=20endpoints.py=20module,=20which=20?= =?UTF-8?q?uses=20the=20save=5Fuploaded=5Ffile=20function=20from=20the=20c?= =?UTF-8?q?ache.base=20module=20to=20save=20the=20uploaded=20file=20to=20t?= =?UTF-8?q?he=20cache.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/endpoints.py | 12 +++++++++++- src/backend/langflow/api/validate.py | 7 ++++++- src/backend/langflow/cache/base.py | 13 +++++++++++++ src/backend/langflow/graph/base.py | 7 +------ src/backend/langflow/template/field/base.py | 4 ++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/backend/langflow/api/endpoints.py b/src/backend/langflow/api/endpoints.py index 021a81ca8..2d4e96abf 100644 --- a/src/backend/langflow/api/endpoints.py +++ b/src/backend/langflow/api/endpoints.py @@ -1,7 +1,7 @@ import logging from importlib.metadata import version -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, UploadFile from langflow.api.schemas import ( ExportedFlow, @@ -9,6 +9,7 @@ from langflow.api.schemas import ( PredictRequest, PredictResponse, ) +from langflow.cache.base import save_uploaded_file from langflow.interface.run import process_graph_cached from langflow.interface.types import build_langchain_types_dict @@ -36,6 +37,15 @@ async def get_load(predict_request: PredictRequest): raise HTTPException(status_code=500, detail=str(e)) from e +# Endpoint to upload file +@router.post("/upload/{client_id}") +async def create_upload_file(file: UploadFile, client_id: str): + # Cache file + file_path = save_uploaded_file(file.file, file_name=client_id) + + return {"filename": file_path} + + # get endpoint to return version of langflow @router.get("/version") def get_version(): diff --git a/src/backend/langflow/api/validate.py b/src/backend/langflow/api/validate.py index 0e2a7752c..4d397b8b4 100644 --- a/src/backend/langflow/api/validate.py +++ b/src/backend/langflow/api/validate.py @@ -51,7 +51,12 @@ def post_validate_node(node_id: str, data: dict): raise ValueError(f"Node {node_id} not found") if not isinstance(node, VectorStoreNode): node.build() - return json.dumps({"valid": True, "params": str(node._built_object_repr())}) + return json.dumps( + { + "valid": True, + "params": f"{str(node._built_object_repr())[:300]}...", + } + ) except Exception as e: logger.exception(e) return json.dumps({"valid": False, "params": str(e)}) diff --git a/src/backend/langflow/cache/base.py b/src/backend/langflow/cache/base.py index 0f1ff5d92..f5ef69bc4 100644 --- a/src/backend/langflow/cache/base.py +++ b/src/backend/langflow/cache/base.py @@ -135,6 +135,19 @@ def save_binary_file(content: str, file_name: str, accepted_types: list[str]) -> return file_path +@create_cache_folder +def save_uploaded_file(file, file_name): + cache_path = Path(tempfile.gettempdir()) / PREFIX + file_path = cache_path / file_name + + with open(file_path, "wb") as new_file: + # Iterate over the uploaded file in small chunks to conserve memory + while chunk := file.read(8192): # Read 8KB at a time (adjust as needed) + new_file.write(chunk) + + return file_path + + @create_cache_folder def save_cache(hash_val: str, chat_data, clean_old_cache_files: bool): cache_path = Path(tempfile.gettempdir()) / PREFIX / f"{hash_val}.dill" diff --git a/src/backend/langflow/graph/base.py b/src/backend/langflow/graph/base.py index cc5e2902b..3e048e4f6 100644 --- a/src/backend/langflow/graph/base.py +++ b/src/backend/langflow/graph/base.py @@ -87,12 +87,7 @@ class Node: # Load the type in value.get('suffixes') using # what is inside value.get('content') # value.get('value') is the file name - file_name = value.get("value") - content = value.get("content") - type_to_load = value.get("suffixes") - file_path = cache_utils.save_binary_file( - content=content, file_name=file_name, accepted_types=type_to_load - ) + file_path = value.get("file_path") params[key] = file_path diff --git a/src/backend/langflow/template/field/base.py b/src/backend/langflow/template/field/base.py index a1de2c1b6..a9c18ff63 100644 --- a/src/backend/langflow/template/field/base.py +++ b/src/backend/langflow/template/field/base.py @@ -15,7 +15,7 @@ class TemplateFieldCreator(BaseModel, ABC): suffixes: list[str] = [] fileTypes: list[str] = [] file_types: list[str] = [] - content: Union[str, None] = None + file_path: Union[str, None] = None password: bool = False options: list[str] = [] name: str = "" @@ -35,7 +35,7 @@ class TemplateFieldCreator(BaseModel, ABC): result["fileTypes"] = result.pop("file_types") if self.field_type == "file": - result["content"] = self.content + result["file_path"] = self.file_path return result