Skip to content

Commit

Permalink
Online workstation (#345)
Browse files Browse the repository at this point in the history
  • Loading branch information
rayrayraykk authored Aug 13, 2024
1 parent 100e8cb commit 56e6b50
Show file tree
Hide file tree
Showing 13 changed files with 1,316 additions and 27 deletions.
2 changes: 1 addition & 1 deletion examples/0_jupyter_example_template/main.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
8 changes: 8 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@
+ studio_requires
)

online_requires = full_requires + [
"oss2",
"flask_babel",
"babel==2.15.0",
"gunicorn",
]

with open("README.md", "r", encoding="UTF-8") as fh:
long_description = fh.read()

Expand All @@ -130,6 +137,7 @@
"distribute": distribute_requires,
"dev": dev_requires,
"full": full_requires,
"online": online_requires,
},
license="Apache License 2.0",
classifiers=[
Expand Down
6 changes: 6 additions & 0 deletions src/agentscope/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,9 @@ class ShrinkPolicy(IntEnum):
DEFAULT_CHUNK_SIZE = 1024
DEFAULT_CHUNK_OVERLAP = 20
DEFAULT_TOP_K = 5

# flask server
EXPIRATION_SECONDS = 604800 # One week
TOKEN_EXP_TIME = 1440 # One day long
FILE_SIZE_LIMIT = 1024 * 1024 # 10 MB
FILE_COUNT_LIMIT = 10
136 changes: 135 additions & 1 deletion src/agentscope/studio/_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
Flask,
request,
jsonify,
session,
render_template,
Response,
abort,
Expand All @@ -25,7 +26,12 @@
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import SocketIO, join_room, leave_room

from ..constants import _DEFAULT_SUBDIR_CODE, _DEFAULT_SUBDIR_INVOKE
from ..constants import (
_DEFAULT_SUBDIR_CODE,
_DEFAULT_SUBDIR_INVOKE,
FILE_SIZE_LIMIT,
FILE_COUNT_LIMIT,
)
from ._studio_utils import _check_and_convert_id_type
from ..utils.tools import (
_is_process_alive,
Expand Down Expand Up @@ -671,6 +677,134 @@ def _read_examples() -> Response:
return jsonify(json=data)


@_app.route("/save-workflow", methods=["POST"])
def _save_workflow() -> Response:
"""
Save the workflow JSON data to the local user folder.
"""
user_login = session.get("user_login", "local_user")
user_dir = os.path.join(_cache_dir, user_login)
if not os.path.exists(user_dir):
os.makedirs(user_dir)

data = request.json
overwrite = data.get("overwrite", False)
filename = data.get("filename")
workflow_str = data.get("workflow")
if not filename:
return jsonify({"message": "Filename is required"})

filepath = os.path.join(user_dir, f"{filename}.json")

try:
workflow = json.loads(workflow_str)
if not isinstance(workflow, dict):
raise ValueError
except (json.JSONDecodeError, ValueError):
return jsonify({"message": "Invalid workflow data"})

workflow_json = json.dumps(workflow, ensure_ascii=False, indent=4)
if len(workflow_json.encode("utf-8")) > FILE_SIZE_LIMIT:
return jsonify(
{
"message": f"The workflow file size exceeds "
f"{FILE_SIZE_LIMIT/(1024*1024)} MB limit",
},
)

user_files = [
f
for f in os.listdir(user_dir)
if os.path.isfile(os.path.join(user_dir, f))
]

if len(user_files) >= FILE_COUNT_LIMIT and not os.path.exists(filepath):
return jsonify(
{
"message": f"You have reached the limit of "
f"{FILE_COUNT_LIMIT} workflow files, please "
f"delete some files.",
},
)

if overwrite:
with open(filepath, "w", encoding="utf-8") as f:
json.dump(workflow, f, ensure_ascii=False, indent=4)
else:
if os.path.exists(filepath):
return jsonify({"message": "Workflow file exists!"})
else:
with open(filepath, "w", encoding="utf-8") as f:
json.dump(workflow, f, ensure_ascii=False, indent=4)

return jsonify({"message": "Workflow file saved successfully"})


@_app.route("/delete-workflow", methods=["POST"])
def _delete_workflow() -> Response:
"""
Deletes a workflow JSON file from the user folder.
"""
user_login = session.get("user_login", "local_user")
user_dir = os.path.join(_cache_dir, user_login)
if not os.path.exists(user_dir):
os.makedirs(user_dir)

data = request.json
filename = data.get("filename")
if not filename:
return jsonify({"error": "Filename is required"})

filepath = os.path.join(user_dir, filename)
if not os.path.exists(filepath):
return jsonify({"error": "File not found"})

try:
os.remove(filepath)
return jsonify({"message": "Workflow file deleted successfully"})
except Exception as e:
return jsonify({"error": str(e)})


@_app.route("/list-workflows", methods=["POST"])
def _list_workflows() -> Response:
"""
Get all workflow JSON files in the user folder.
"""
user_login = session.get("user_login", "local_user")
user_dir = os.path.join(_cache_dir, user_login)
if not os.path.exists(user_dir):
os.makedirs(user_dir)

files = [file for file in os.listdir(user_dir) if file.endswith(".json")]
return jsonify(files=files)


@_app.route("/load-workflow", methods=["POST"])
def _load_workflow() -> Response:
"""
Reads and returns workflow data from the specified JSON file.
"""
user_login = session.get("user_login", "local_user")
user_dir = os.path.join(_cache_dir, user_login)
if not os.path.exists(user_dir):
os.makedirs(user_dir)

data = request.json
filename = data.get("filename")
if not filename:
return jsonify({"error": "Filename is required"}), 400

filepath = os.path.join(user_dir, filename)
if not os.path.exists(filepath):
return jsonify({"error": "File not found"}), 404

with open(filepath, "r", encoding="utf-8") as f:
json_data = json.load(f)

return jsonify(json_data)


@_app.route("/")
def _home() -> str:
"""Render the home page."""
Expand Down
Loading

0 comments on commit 56e6b50

Please sign in to comment.