This commit is contained in:
2024-09-13 16:58:34 +08:00
commit b06a9ecee0
103 changed files with 5440 additions and 0 deletions

View File

@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>PyTorchBoot Project</title><link href=/static/css/app.5383ee564f9a1a656786665504aa6b98.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.9f7b4785a30f0533ee08.js></script><script type=text/javascript src=/static/js/app.230235873e25a72eeacb.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 542 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={2:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,"a",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p="/",t.oe=function(r){throw console.error(r),r}}([]);
//# sourceMappingURL=manifest.2ae2e69a05c33dfc65f8.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap def2f39c04517bb0de2d"],"names":["parentJsonpFunction","window","chunkIds","moreModules","executeModules","moduleId","chunkId","result","i","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","call","modules","shift","__webpack_require__","s","installedModules","2","exports","module","l","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","p","oe","err","console","error"],"mappings":"aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,IAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA","file":"static/js/manifest.2ae2e69a05c33dfc65f8.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap def2f39c04517bb0de2d"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,233 @@
import os
import threading
import socket
import logging
import psutil
import GPUtil
import platform
from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
from tensorboard import program
from PytorchBoot.utils.project_util import ProjectUtil
from PytorchBoot.stereotype import get_all_component_classes, get_all_component_comments
from PytorchBoot.application import application_class
from PytorchBoot.status import status_manager
from PytorchBoot.utils.log_util import Log
from PytorchBoot.utils.timer_util import Timer
app = Flask(__name__, static_folder="../client")
app.logger.setLevel("WARNING")
logging.getLogger("werkzeug").disabled = True
CORS(app)
root_path = os.getcwd()
ProjectUtil.scan_project(root_path)
configs = ProjectUtil.scan_configs(root_path)
running_tensorboard = {}
@app.route("/")
def serve_index():
return send_from_directory(app.static_folder, "index.html")
@app.route("/<path:path>")
def serve_file(path):
return send_from_directory(app.static_folder, path)
@app.route("/test", methods=["POST"])
def hello_world():
return jsonify(message="Hello, World!")
@app.route("/project/structure", methods=["POST"])
def project_structure():
component_info = {}
for st, cls_dict in get_all_component_classes().items():
component_info[st] = {k: v.__name__ for k, v in cls_dict.items()}
comment_info = get_all_component_comments()
app_info = {}
for app_name, app_cls in application_class.items():
app_info[app_name] = app_cls.__name__
return jsonify(
components=component_info,
comments=comment_info,
applications=app_info,
configs=configs,
root_path=root_path,
)
@app.route("/project/run_app", methods=["POST"])
def run_application():
data = request.json
app_name = data.get("app_name")
app_cls = application_class.get(app_name)
if app_cls is None:
Log.error(
f"No class annotated with @PytorchBootApplication found with the name '{app_name}'.",
True,
)
return jsonify(
{
"message": f"No application found with the name '{app_name}'",
"status": "error",
}
)
if not hasattr(app_cls, "start"):
Log.error(
"The class annotated with @PytorchBootApplication should have a 'start' method.",
True,
)
return jsonify(
{"message": "The class should have a 'start' method", "status": "error"}
)
def run_in_background():
Log.info(f"Application '{app_cls.__name__}' started.")
timer = Timer("Application")
timer.start()
status_manager.run_app(app_name, app_cls)
app_cls.start()
status_manager.end_app(app_name)
timer.stop()
Log.info(timer.get_elasped_time_str(Timer.HOURS))
Log.success("Application finished.")
threading.Thread(target=run_in_background).start()
return jsonify(
{"message": f"Application '{app_name}' is running now.", "status": "success"}
)
@app.route("/project/get_status", methods=["POST"])
def get_status():
cpu_info = {
"model": platform.processor(),
"usage_percent": psutil.cpu_percent(interval=1),
}
virtual_memory = psutil.virtual_memory()
memory_info = {
"used": round(virtual_memory.used / (1024**3), 3),
"total": round(virtual_memory.total / (1024**3), 3),
}
gpus = GPUtil.getGPUs()
gpu_info = []
for gpu in gpus:
gpu_info.append(
{
"name": gpu.name,
"memory_used": gpu.memoryUsed,
"memory_total": gpu.memoryTotal,
}
)
return jsonify(
curr_status=status_manager.get_status(),
last_status=status_manager.get_last_status(),
logs=status_manager.get_log(),
progress=status_manager.get_progress(),
running_apps=status_manager.get_running_apps(),
cpu=cpu_info,
memory=memory_info,
gpus=gpu_info,
)
@app.route("/project/set_status", methods=["POST"])
def set_status():
status = request.json.get("status")
progress = request.json.get("progress")
if status:
status_manager.set_status(
app_name=status["app_name"],
runner_name=status["runner_name"],
key=status["key"],
value=status["value"],
)
if progress:
status_manager.set_progress(
app_name=progress["app_name"],
runner_name=progress["runner_name"],
key=progress["key"],
curr_value=progress["curr_value"],
max_value=progress["max_value"],
)
return jsonify({"status": "success"})
@app.route("/project/add_log", methods=["POST"])
def add_log():
log = request.json.get("log")
Log.log(log["message"], log["log_type"])
return jsonify({"status": "success"})
def find_free_port(start_port):
"""Find a free port starting from start_port."""
port = start_port
while True:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
result = sock.connect_ex(("localhost", port))
if result != 0:
return port
port += 1
def start_tensorboard(log_dir, port):
"""Starts TensorBoard in a separate thread."""
tb = program.TensorBoard()
tb.configure(argv=[None, "--logdir", log_dir, "--port", str(port)])
tb.launch()
@app.route("/tensorboard/run", methods=["POST"])
def run_tensorboard():
data = request.json
log_dir = data.get("log_dir")
if log_dir in running_tensorboard:
return jsonify(
{
"message": f"TensorBoard ({running_tensorboard[log_dir]}) is already running for <{log_dir}>",
"url": running_tensorboard[log_dir],
"status": "warning",
}
)
if not os.path.isdir(log_dir):
return jsonify({"message": "Log directory does not exist", "status": "error"})
port = find_free_port(10000)
try:
tb_thread = threading.Thread(target=start_tensorboard, args=(log_dir, port))
tb_thread.start()
except Exception as e:
return jsonify(
{"message": f"Error starting TensorBoard: {str(e)}", "status": "error"}
)
url = f"http://localhost:{port}"
running_tensorboard[log_dir] = url
return jsonify(
{"url": url, "message": f"TensorBoard is running at {url}", "status": "success"}
)
@app.route("/tensorboard/dirs", methods=["POST"])
def get_tensorboard_dirs():
tensorboard_dirs = []
for root, dirs, _ in os.walk(root_path):
for dir_name in dirs:
if dir_name == "tensorboard":
tensorboard_dirs.append(os.path.join(root, dir_name))
return jsonify({"tensorboard_dirs": tensorboard_dirs})
@app.route("/tensorboard/running_tensorboards", methods=["POST"])
def get_running_tensorboards():
return jsonify(running_tensorboards=running_tensorboard)