mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 15:37:44 +00:00
chore: ui server updates (#951)
* ui server update * update * fix bugs * updates * use randomname * fix * fix bugs * change time interval in debug server * some change * fix CI * time interval change * updates * some changes * fix * fix curves * one IP, one pointers to show msgs return progress * enable /control * fix bugs * fix CI * fix isort
This commit is contained in:
@@ -14,8 +14,8 @@ def main(
|
||||
checkout: bool | str | Path = True,
|
||||
step_n: int | None = None,
|
||||
loop_n: int | None = None,
|
||||
all_duration: str | None = None,
|
||||
competition="bms-molecular-translation",
|
||||
timeout=None,
|
||||
replace_timer=True,
|
||||
exp_gen_cls: str | None = None,
|
||||
):
|
||||
@@ -67,7 +67,7 @@ def main(
|
||||
if exp_gen_cls is not None:
|
||||
kaggle_loop.exp_gen = import_class(exp_gen_cls)(kaggle_loop.exp_gen.scen)
|
||||
|
||||
asyncio.run(kaggle_loop.run(step_n=step_n, loop_n=loop_n, all_duration=timeout))
|
||||
asyncio.run(kaggle_loop.run(step_n=step_n, loop_n=loop_n, all_duration=all_duration))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -3,6 +3,7 @@ Factor workflow with session control
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import fire
|
||||
@@ -25,7 +26,13 @@ class FactorRDLoop(RDLoop):
|
||||
return exp
|
||||
|
||||
|
||||
def main(path=None, step_n=None, loop_n=None, all_duration=None, checkout=True):
|
||||
def main(
|
||||
path: str | None = None,
|
||||
step_n: int | None = None,
|
||||
loop_n: int | None = None,
|
||||
all_duration: str | None = None,
|
||||
checkout: bool | str | Path = True,
|
||||
):
|
||||
"""
|
||||
Auto R&D Evolving loop for fintech factors.
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ def extract_model_from_docs(docs_dict):
|
||||
|
||||
|
||||
class ModelExperimentLoaderFromDict(ModelTaskLoader):
|
||||
def load(self, model_dict: dict) -> list:
|
||||
def load(self, model_dict: dict) -> QlibModelExperiment:
|
||||
"""Load data from a dict."""
|
||||
task_l = []
|
||||
for model_name, model_data in model_dict.items():
|
||||
@@ -117,7 +117,7 @@ class ModelExperimentLoaderFromDict(ModelTaskLoader):
|
||||
|
||||
class ModelExperimentLoaderFromPDFfiles(ModelTaskLoader):
|
||||
@wait_retry(retry_n=5)
|
||||
def load(self, file_or_folder_path: str) -> dict:
|
||||
def load(self, file_or_folder_path: str) -> QlibModelExperiment:
|
||||
docs_dict = load_and_process_pdfs_by_langchain(file_or_folder_path) # dict{file_path:content}
|
||||
model_dict = extract_model_from_docs(
|
||||
docs_dict
|
||||
|
||||
@@ -116,16 +116,18 @@ Only **2** Message in one loop
|
||||
"evo_id": "0",
|
||||
"content": [ // list of task_name & codes
|
||||
{
|
||||
"evo_id": "0",
|
||||
"target_task_name": "task_1",
|
||||
"codes": { // one or more codes
|
||||
"workspace": { // one or more codes
|
||||
"a.py": "...<python codes>",
|
||||
"b.py": "...<python codes>",
|
||||
//...
|
||||
}
|
||||
},
|
||||
{
|
||||
"evo_id": "0",
|
||||
"target_task_name": "task_2",
|
||||
"codes": {
|
||||
"workspace": {
|
||||
"a.py": "...<python codes>",
|
||||
//...
|
||||
}
|
||||
@@ -155,6 +157,7 @@ Only **2** Message in one loop
|
||||
"evo_id": "0",
|
||||
"content": [ // list of feedbacks
|
||||
{
|
||||
"evo_id": "0",
|
||||
"final_decision": "True", // True or False
|
||||
"execution": "...",
|
||||
"code": "...",
|
||||
@@ -230,8 +233,21 @@ Each tag below appears only once per loop.
|
||||
"reason": "...",
|
||||
"exception": "...",
|
||||
"observations": "...", // may not exists
|
||||
"hypothesis_evaluation": "...", // may not exists
|
||||
"hypothesis_evaluation": "...", // may not existsc
|
||||
"new_hypothesis": "...", // may not exists
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
# TODO
|
||||
|
||||
## Session
|
||||
|
||||
- How to continue.
|
||||
- show & copy trace_id(name)?
|
||||
-
|
||||
|
||||
## Page
|
||||
|
||||
1. remove Medical, add Finance Whole Pipeline
|
||||
2.
|
||||
+99
-38
@@ -2,7 +2,6 @@ import os
|
||||
import random
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
@@ -12,46 +11,88 @@ import typer
|
||||
from flask import Flask, jsonify, request, send_from_directory
|
||||
from flask_cors import CORS
|
||||
|
||||
msgs_for_frontend = defaultdict(list)
|
||||
from rdagent.log.storage import FileStorage
|
||||
from rdagent.log.ui.conf import UI_SETTING
|
||||
from rdagent.log.ui.storage import WebStorage
|
||||
from rdagent.log.utils import is_valid_session
|
||||
|
||||
app = Flask(__name__, static_folder="./docs/_static")
|
||||
app = Flask(__name__, static_folder=UI_SETTING.static_path)
|
||||
CORS(app)
|
||||
|
||||
rdagent_processes = defaultdict()
|
||||
server_port = 19899
|
||||
log_folder_path = Path(UI_SETTING.trace_folder).absolute()
|
||||
|
||||
|
||||
@app.route("/favicon.ico")
|
||||
def favicon():
|
||||
return send_from_directory("./docs/_static", "favicon.ico", mimetype="image/vnd.microsoft.icon")
|
||||
return send_from_directory(app.static_folder, "favicon.ico", mimetype="image/vnd.microsoft.icon")
|
||||
|
||||
|
||||
pointers = {id: 0 for id in msgs_for_frontend.keys()}
|
||||
msgs_for_frontend = defaultdict(list)
|
||||
pointers = defaultdict(lambda: defaultdict(int)) # pointers[trace_id][user_ip]
|
||||
|
||||
|
||||
def read_trace(log_path: Path, id: str = "") -> None:
|
||||
fs = FileStorage(log_path)
|
||||
ws = WebStorage(port=1, path=log_path)
|
||||
msgs_for_frontend[id] = []
|
||||
last_timestamp = None
|
||||
for msg in fs.iter_msg():
|
||||
data = ws._obj_to_json(obj=msg.content, tag=msg.tag, id=id, timestamp=msg.timestamp.isoformat())
|
||||
if data:
|
||||
if isinstance(data, list):
|
||||
for d in data:
|
||||
msgs_for_frontend[id].append(d["msg"])
|
||||
last_timestamp = msg.timestamp
|
||||
else:
|
||||
msgs_for_frontend[id].append(data["msg"])
|
||||
last_timestamp = msg.timestamp
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
if last_timestamp and (now - last_timestamp).total_seconds() > 1800:
|
||||
msgs_for_frontend[id].append({"tag": "END", "timestamp": now.isoformat(), "content": {}})
|
||||
|
||||
|
||||
# load all traces from the log folder
|
||||
for p in log_folder_path.glob("*/*/"):
|
||||
if is_valid_session(p):
|
||||
read_trace(p, id=str(p))
|
||||
|
||||
|
||||
@app.route("/trace", methods=["POST"])
|
||||
def update_trace():
|
||||
global pointers, msgs_for_frontend
|
||||
data = request.get_json()
|
||||
trace_id = data.get("id")
|
||||
return_all = data.get("all")
|
||||
reset = data.get("reset")
|
||||
msg_num = random.randint(1, 10)
|
||||
app.logger.info(data)
|
||||
log_folder_path = Path(UI_SETTING.trace_folder).absolute()
|
||||
if not trace_id:
|
||||
return jsonify({"error": "Trace ID is required"}), 400
|
||||
trace_id = str(log_folder_path / trace_id)
|
||||
|
||||
user_ip = request.remote_addr
|
||||
|
||||
if reset:
|
||||
pointers[trace_id] = 0
|
||||
pointers[trace_id][user_ip] = 0
|
||||
|
||||
end_pointer = pointers[trace_id] + msg_num
|
||||
start_pointer = pointers[trace_id][user_ip]
|
||||
end_pointer = start_pointer + msg_num
|
||||
if end_pointer > len(msgs_for_frontend[trace_id]) or return_all:
|
||||
end_pointer = len(msgs_for_frontend[trace_id])
|
||||
|
||||
print(f"trace_id: {trace_id}, start_pointer: {pointers[trace_id]}, end_pointer: {end_pointer}")
|
||||
returned_msgs = msgs_for_frontend[trace_id][pointers[trace_id] : end_pointer]
|
||||
returned_msgs = msgs_for_frontend[trace_id][start_pointer:end_pointer]
|
||||
|
||||
pointers[trace_id] = end_pointer
|
||||
pointers[trace_id][user_ip] = end_pointer
|
||||
if returned_msgs:
|
||||
app.logger.info([msg["tag"] for msg in returned_msgs])
|
||||
return jsonify(returned_msgs), 200
|
||||
|
||||
|
||||
@app.route("/upload", methods=["GET"])
|
||||
@app.route("/upload", methods=["POST"])
|
||||
def upload_file():
|
||||
# 获取请求体中的字段
|
||||
global rdagent_processes, server_port
|
||||
@@ -62,11 +103,18 @@ def upload_file():
|
||||
all_duration = request.form.get("all_duration")
|
||||
|
||||
# scenario = "Data Science Loop"
|
||||
trace_name = randomname.get_name()
|
||||
log_folder_path = Path("./RD-Agent_server_trace").absolute()
|
||||
log_trace_path = (log_folder_path / scenario / trace_name).absolute()
|
||||
if scenario == "Data Science":
|
||||
competition = competition[10:] # Eg. MLE-Bench:aerial-cactus-competition
|
||||
trace_name = f"{competition}-{randomname.get_name()}"
|
||||
else:
|
||||
trace_name = randomname.get_name()
|
||||
trace_files_path = log_folder_path / scenario / "uploads" / trace_name
|
||||
|
||||
log_trace_path = (log_folder_path / scenario / trace_name).absolute()
|
||||
stdout_path = log_folder_path / scenario / f"{trace_name}.stdout"
|
||||
if not stdout_path.exists():
|
||||
stdout_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# save files
|
||||
for file in files:
|
||||
if file:
|
||||
@@ -87,33 +135,34 @@ def upload_file():
|
||||
else: # one file is uploaded
|
||||
rfp = str(trace_files_path / files[0].filename)
|
||||
cmds = ["rdagent", "general_model", "--report_file_path", rfp]
|
||||
if scenario == "Medical Model Implementation":
|
||||
cmds = ["rdagent", "med_model"]
|
||||
if scenario == "Data Science Loop":
|
||||
cmds = ["rdagent", "kaggle", "--competition", competition]
|
||||
if scenario == "Finance Whole Pipeline":
|
||||
cmds = ["rdagent", "fin_quant"]
|
||||
if scenario == "Data Science":
|
||||
cmds = ["rdagent", "data_science", "--competition", competition]
|
||||
|
||||
# time control parameters
|
||||
if loop_n:
|
||||
cmds += ["--loop_n", loop_n]
|
||||
if scenario != "Finance Data Building (Reports)":
|
||||
if loop_n:
|
||||
cmds += ["--loop_n", loop_n]
|
||||
if all_duration:
|
||||
cmds += ["--all_duration", all_duration]
|
||||
|
||||
rdagent_processes[str(log_trace_path)] = subprocess.Popen(
|
||||
cmds,
|
||||
# stdout=subprocess.PIPE,
|
||||
# stderr=subprocess.PIPE,
|
||||
stdout=sys.stdout,
|
||||
stderr=sys.stderr,
|
||||
env={
|
||||
"LOG_TRACE_PATH": str(log_trace_path),
|
||||
"UI_SERVER_PORT": server_port,
|
||||
},
|
||||
)
|
||||
cmds += ["--all_duration", f"{all_duration}h"]
|
||||
|
||||
app.logger.info(f"Started process for {log_trace_path} with parameters: {cmds}")
|
||||
with stdout_path.open("w") as log_file:
|
||||
rdagent_processes[str(log_trace_path)] = subprocess.Popen(
|
||||
cmds,
|
||||
stdout=log_file,
|
||||
stderr=log_file,
|
||||
env={
|
||||
**os.environ,
|
||||
"LOG_TRACE_PATH": str(log_trace_path),
|
||||
"LOG_UI_SERVER_PORT": str(server_port),
|
||||
},
|
||||
)
|
||||
return (
|
||||
jsonify(
|
||||
{
|
||||
"id": str(log_trace_path),
|
||||
"id": f"{scenario}/{trace_name}",
|
||||
}
|
||||
),
|
||||
200,
|
||||
@@ -124,6 +173,7 @@ def upload_file():
|
||||
def receive_msgs():
|
||||
try:
|
||||
data = request.get_json()
|
||||
# app.logger.info(data["msg"]["tag"])
|
||||
if not data:
|
||||
return jsonify({"error": "No JSON data received"}), 400
|
||||
except Exception as e:
|
||||
@@ -140,12 +190,13 @@ def receive_msgs():
|
||||
|
||||
@app.route("/control", methods=["POST"])
|
||||
def control_process():
|
||||
global rdagent_processes
|
||||
global rdagent_processes, msgs_for_frontend
|
||||
data = request.get_json()
|
||||
app.logger.info(data)
|
||||
if not data or "id" not in data or "action" not in data:
|
||||
return jsonify({"error": "Missing 'id' or 'action' in request"}), 400
|
||||
|
||||
id = data["id"]
|
||||
id = str(log_folder_path / data["id"])
|
||||
action = data["action"]
|
||||
|
||||
if id not in rdagent_processes or rdagent_processes[id] is None:
|
||||
@@ -175,13 +226,23 @@ def control_process():
|
||||
else:
|
||||
return jsonify({"error": "Unknown action"}), 400
|
||||
except Exception as e:
|
||||
return jsonify({"error": f"Failed to {action} process"}), 500
|
||||
return jsonify({"error": f"Failed to {action} process, {e}"}), 500
|
||||
|
||||
|
||||
@app.route("/test", methods=["GET"])
|
||||
def test():
|
||||
# return 'Hello, World!'
|
||||
global msgs_for_frontend, pointers
|
||||
msgs = {k: [i["tag"] for i in v] for k, v in msgs_for_frontend.items()}
|
||||
pointers = pointers
|
||||
return jsonify({"msgs": msgs, "pointers": pointers}), 200
|
||||
|
||||
|
||||
@app.route("/", methods=["GET"])
|
||||
def index():
|
||||
# return 'Hello, World!'
|
||||
return msgs_for_frontend
|
||||
# return {k: [i["tag"] for i in v] for k, v in msgs_for_frontend.items()}
|
||||
return send_from_directory(app.static_folder, "index.html")
|
||||
|
||||
|
||||
@app.route("/<path:fn>", methods=["GET"])
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
import multiprocessing
|
||||
import os
|
||||
import random
|
||||
import signal
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import randomname
|
||||
import typer
|
||||
from flask import Flask, jsonify, request, send_from_directory
|
||||
from flask_cors import CORS
|
||||
|
||||
from rdagent.log.ui.conf import UI_SETTING
|
||||
|
||||
app = Flask(__name__, static_folder=UI_SETTING.static_path)
|
||||
CORS(app)
|
||||
|
||||
rdagent_processes = defaultdict()
|
||||
server_port = 19899
|
||||
|
||||
|
||||
@app.route("/favicon.ico")
|
||||
def favicon():
|
||||
return send_from_directory(app.static_folder, "favicon.ico", mimetype="image/vnd.microsoft.icon")
|
||||
|
||||
|
||||
msgs_for_frontend = defaultdict(list)
|
||||
pointers = defaultdict(int)
|
||||
|
||||
|
||||
@app.route("/trace", methods=["POST"])
|
||||
def update_trace():
|
||||
global pointers, msgs_for_frontend
|
||||
data = request.get_json()
|
||||
# app.logger.info(data)
|
||||
trace_id = data.get("id")
|
||||
return_all = data.get("all")
|
||||
reset = data.get("reset")
|
||||
msg_num = random.randint(1, 10)
|
||||
|
||||
if reset:
|
||||
pointers[trace_id] = 0
|
||||
|
||||
end_pointer = pointers[trace_id] + msg_num
|
||||
if end_pointer > len(msgs_for_frontend[trace_id]) or return_all:
|
||||
end_pointer = len(msgs_for_frontend[trace_id])
|
||||
|
||||
returned_msgs = msgs_for_frontend[trace_id][pointers[trace_id] : end_pointer]
|
||||
|
||||
pointers[trace_id] = end_pointer
|
||||
# if len(returned_msgs):
|
||||
# app.logger.info(data)
|
||||
# app.logger.info([i["tag"] for i in returned_msgs])
|
||||
# try:
|
||||
# import json
|
||||
# resp = json.dumps(returned_msgs, ensure_ascii=False)
|
||||
# except Exception as e:
|
||||
# app.logger.error(f"Error in jsonify: {e}")
|
||||
# for msg in returned_msgs:
|
||||
# try:
|
||||
# rr = json.dumps(msg, ensure_ascii=False)
|
||||
# except Exception as e:
|
||||
# app.logger.error(f"Error in jsonify individual message: {e}")
|
||||
# app.logger.error(msg)
|
||||
|
||||
return jsonify(returned_msgs), 200
|
||||
|
||||
|
||||
@app.route("/upload", methods=["POST"])
|
||||
def upload_file():
|
||||
# 获取请求体中的字段
|
||||
global rdagent_processes, server_port, msgs_for_frontend
|
||||
scenario = request.form.get("scenario")
|
||||
files = request.files.getlist("files")
|
||||
competition = request.form.get("competition")
|
||||
loop_n = request.form.get("loops")
|
||||
all_duration = request.form.get("all_duration")
|
||||
|
||||
log_folder_path = Path("/home/bowen/workspace/new_traces").absolute()
|
||||
|
||||
if scenario == "Data Science":
|
||||
trace_path = log_folder_path / "o1-preview" / f"{competition[10:]}.1"
|
||||
else:
|
||||
trace_path = log_folder_path / scenario
|
||||
id = f"{scenario}/{randomname.get_name()}"
|
||||
|
||||
def read_trace(log_path: Path, t: float = 0.2, id: str = "") -> None:
|
||||
from rdagent.log.storage import FileStorage
|
||||
from rdagent.log.ui.storage import WebStorage
|
||||
|
||||
fs = FileStorage(log_path)
|
||||
ws = WebStorage(port=1, path=log_path)
|
||||
msgs_for_frontend[id] = []
|
||||
for msg in fs.iter_msg():
|
||||
data = ws._obj_to_json(obj=msg.content, tag=msg.tag, id=id, timestamp=msg.timestamp.isoformat())
|
||||
if data:
|
||||
if isinstance(data, list):
|
||||
for d in data:
|
||||
time.sleep(t)
|
||||
msgs_for_frontend[id].append(d["msg"])
|
||||
else:
|
||||
time.sleep(t)
|
||||
msgs_for_frontend[id].append(data["msg"])
|
||||
msgs_for_frontend[id].append({"tag": "END", "timestamp": datetime.now(timezone.utc).isoformat(), "content": {}})
|
||||
|
||||
# 启动后台线程,不阻塞 return
|
||||
threading.Thread(target=read_trace, args=(trace_path, 0.5, id), daemon=True).start()
|
||||
|
||||
return jsonify({"id": id}), 200
|
||||
|
||||
|
||||
@app.route("/receive", methods=["POST"])
|
||||
def receive_msgs():
|
||||
try:
|
||||
data = request.get_json()
|
||||
app.logger.info(data["msg"]["tag"])
|
||||
if not data:
|
||||
return jsonify({"error": "No JSON data received"}), 400
|
||||
except Exception as e:
|
||||
return jsonify({"error": "Internal Server Error"}), 500
|
||||
|
||||
if isinstance(data, list):
|
||||
for d in data:
|
||||
msgs_for_frontend[d["id"]].append(d["msg"])
|
||||
else:
|
||||
msgs_for_frontend[data["id"]].append(data["msg"])
|
||||
|
||||
return jsonify({"status": "success"}), 200
|
||||
|
||||
|
||||
@app.route("/control", methods=["POST"])
|
||||
def control_process():
|
||||
global rdagent_processes
|
||||
data = request.get_json()
|
||||
app.logger.info(data)
|
||||
if not data or "id" not in data or "action" not in data:
|
||||
return jsonify({"error": "Missing 'id' or 'action' in request"}), 400
|
||||
|
||||
id = data["id"]
|
||||
action = data["action"]
|
||||
|
||||
return jsonify({"status": "success", "message": f"Received action '{action}' for process with id '{id}'"})
|
||||
|
||||
|
||||
@app.route("/test", methods=["GET"])
|
||||
def test():
|
||||
# return 'Hello, World!'
|
||||
return {k: [i["tag"] for i in v] for k, v in msgs_for_frontend.items()}
|
||||
|
||||
|
||||
@app.route("/", methods=["GET"])
|
||||
def index():
|
||||
# return 'Hello, World!'
|
||||
# return {k: [i["tag"] for i in v] for k, v in msgs_for_frontend.items()}
|
||||
return send_from_directory(app.static_folder, "index.html")
|
||||
|
||||
|
||||
@app.route("/<path:fn>", methods=["GET"])
|
||||
def server_static_files(fn):
|
||||
return send_from_directory(app.static_folder, fn)
|
||||
|
||||
|
||||
def main(port: int = 19899):
|
||||
global server_port
|
||||
server_port = port
|
||||
app.run(debug=True, host="0.0.0.0", port=port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
typer.run(main)
|
||||
@@ -14,5 +14,9 @@ class UIBasePropSetting(ExtendedBaseSettings):
|
||||
|
||||
amlt_path: str = "/data/share_folder_local/amlt"
|
||||
|
||||
static_path: str = "./git_ignore_folder/static"
|
||||
|
||||
trace_folder: str = "./traces"
|
||||
|
||||
|
||||
UI_SETTING = UIBasePropSetting()
|
||||
|
||||
@@ -51,7 +51,7 @@ def curves_win(summary: dict):
|
||||
with st.container(border=True):
|
||||
st.markdown(f"**:blue[{k}] - :violet[{v['competition']}]**")
|
||||
try:
|
||||
tscores = {f"loop {k-1}": v for k, v in v["test_scores"].items()}
|
||||
tscores = {f"loop {k}": v for k, v in v["test_scores"].items()}
|
||||
vscores = {}
|
||||
for k, vs in v["valid_scores"].items():
|
||||
if not vs.index.is_unique:
|
||||
@@ -72,6 +72,13 @@ def curves_win(summary: dict):
|
||||
ensemble_row = vdf.loc[["ensemble"]]
|
||||
vdf = pd.concat([ensemble_row, vdf.drop("ensemble")])
|
||||
vdf.columns = [f"loop {i}" for i in vdf.columns]
|
||||
|
||||
# Ensure tdf has all loops present in vdf, fill missing with NaN
|
||||
for loop_name in vdf.columns:
|
||||
if loop_name not in tdf.index:
|
||||
tdf.loc[loop_name] = pd.NA
|
||||
tdf = tdf.reindex(vdf.columns)
|
||||
|
||||
fig = go.Figure()
|
||||
# Add test scores trace from tdf
|
||||
fig.add_trace(
|
||||
|
||||
+75
-59
@@ -7,6 +7,8 @@ import requests
|
||||
from rdagent.log.base import Message, Storage
|
||||
from rdagent.log.utils import extract_evoid, extract_loopid_func_name, gen_datetime
|
||||
|
||||
from .conf import UI_SETTING
|
||||
|
||||
|
||||
class WebStorage(Storage):
|
||||
"""
|
||||
@@ -30,16 +32,21 @@ class WebStorage(Storage):
|
||||
|
||||
def log(self, obj: object, tag: str, timestamp: datetime | None = None, **kwargs: Any) -> str | Path:
|
||||
timestamp = gen_datetime(timestamp)
|
||||
if "pdf_image" in tag or "load_pdf_screenshot" in tag:
|
||||
obj.save(f"{UI_SETTING.static_path}/{timestamp.isoformat()}.jpg")
|
||||
|
||||
try:
|
||||
data = self._obj_to_json(obj=obj, tag=tag, id=self.path, timestamp=timestamp.isoformat())
|
||||
if not data:
|
||||
return "Normal log, skipped"
|
||||
if isinstance(data, list):
|
||||
for d in data:
|
||||
self.msgs.append(d)
|
||||
else:
|
||||
self.msgs.append(data)
|
||||
headers = {"Content-Type": "application/json"}
|
||||
requests.post(f"{self.url}/receive", json=data, headers=headers, timeout=1)
|
||||
resp = requests.post(f"{self.url}/receive", json=data, headers=headers, timeout=1)
|
||||
return f"{resp.status_code} {resp.text}"
|
||||
except (requests.ConnectionError, requests.Timeout) as e:
|
||||
pass
|
||||
|
||||
@@ -56,6 +63,7 @@ class WebStorage(Storage):
|
||||
)
|
||||
|
||||
def _obj_to_json(
|
||||
self,
|
||||
obj: object,
|
||||
tag: str,
|
||||
id: str,
|
||||
@@ -84,13 +92,25 @@ class WebStorage(Storage):
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
elif "experiment generation" in tag:
|
||||
elif "pdf_image" in tag or "load_pdf_screenshot" in tag:
|
||||
# obj.save(f"{app.static_folder}/{timestamp}.jpg")
|
||||
data = {
|
||||
"id": id,
|
||||
"msg": {
|
||||
"tag": "research.pdf_image",
|
||||
"timestamp": timestamp,
|
||||
"loop_id": li,
|
||||
"content": {"image": f"{timestamp}.jpg"},
|
||||
},
|
||||
}
|
||||
elif "experiment generation" in tag or "load_experiment" in tag:
|
||||
from rdagent.components.coder.factor_coder.factor import FactorTask
|
||||
from rdagent.components.coder.model_coder.model import ModelTask
|
||||
from rdagent.core.experiment import Experiment
|
||||
|
||||
tasks: list[FactorTask | ModelTask] = obj
|
||||
if "load_experiment" in tag:
|
||||
tasks: list[FactorTask | ModelTask] = obj.sub_tasks
|
||||
else:
|
||||
tasks: list[FactorTask | ModelTask] = obj
|
||||
if isinstance(tasks[0], FactorTask):
|
||||
data = {
|
||||
"id": id,
|
||||
@@ -141,6 +161,7 @@ class WebStorage(Storage):
|
||||
h: DSHypothesis = obj.hypothesis
|
||||
tasks = [t[0] for t in obj.pending_tasks_list]
|
||||
t = tasks[0]
|
||||
t.name = type(t).__name__ # TODO: PipelinTask have "COMPONENT" in name, fix this when creating task.
|
||||
data = [
|
||||
{
|
||||
"id": id,
|
||||
@@ -193,36 +214,30 @@ class WebStorage(Storage):
|
||||
},
|
||||
},
|
||||
]
|
||||
elif f"evo_loop_{ei}.evolving code" in tag and "coding" in tag:
|
||||
from rdagent.components.coder.factor_coder.factor import FactorFBWorkspace
|
||||
from rdagent.components.coder.model_coder.model import (
|
||||
ModelFBWorkspace,
|
||||
ModelTask,
|
||||
)
|
||||
elif f"evo_loop_{ei}.evolving code" in tag and "running" not in tag:
|
||||
from rdagent.core.experiment import FBWorkspace
|
||||
|
||||
ws: list[FactorFBWorkspace | ModelFBWorkspace] = [i for i in obj]
|
||||
if all(isinstance(item, FactorFBWorkspace) for item in ws) or all(
|
||||
isinstance(item, ModelFBWorkspace) for item in ws
|
||||
):
|
||||
data = {
|
||||
"id": id,
|
||||
"msg": {
|
||||
"tag": "evolving.codes",
|
||||
"timestamp": timestamp,
|
||||
"loop_id": li,
|
||||
"evo_id": ei,
|
||||
"content": [
|
||||
{
|
||||
"target_task_name": w.target_task.name,
|
||||
"codes": w.file_dict,
|
||||
}
|
||||
for w in ws
|
||||
if w
|
||||
],
|
||||
},
|
||||
}
|
||||
elif f"evo_loop_{ei}.evolving feedback" in tag and "coding" in tag:
|
||||
ws: list[FBWorkspace] = [i for i in obj]
|
||||
data = {
|
||||
"id": id,
|
||||
"msg": {
|
||||
"tag": "evolving.codes",
|
||||
"timestamp": timestamp,
|
||||
"loop_id": li,
|
||||
"evo_id": ei,
|
||||
"content": [
|
||||
{
|
||||
"evo_id": ei,
|
||||
"target_task_name": (
|
||||
w.target_task.name if w.target_task else "PipelineTask"
|
||||
), # TODO: save this when proposal
|
||||
"workspace": w.file_dict,
|
||||
}
|
||||
for w in ws
|
||||
],
|
||||
},
|
||||
}
|
||||
elif f"evo_loop_{ei}.evolving feedback" in tag and "running" not in tag:
|
||||
from rdagent.components.coder.CoSTEER.evaluators import (
|
||||
CoSTEERSingleFeedback,
|
||||
)
|
||||
@@ -237,6 +252,7 @@ class WebStorage(Storage):
|
||||
"evo_id": ei,
|
||||
"content": [
|
||||
{
|
||||
"evo_id": ei,
|
||||
"final_decision": f.final_decision,
|
||||
# "final_feedback": f.final_feedback,
|
||||
"execution": f.execution,
|
||||
@@ -244,7 +260,6 @@ class WebStorage(Storage):
|
||||
"return_checking": f.return_checking,
|
||||
}
|
||||
for f in fl
|
||||
if f
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -294,31 +309,32 @@ class WebStorage(Storage):
|
||||
elif "feedback" in tag:
|
||||
from rdagent.core.proposal import ExperimentFeedback, HypothesisFeedback
|
||||
|
||||
ef: ExperimentFeedback = obj
|
||||
content = (
|
||||
{
|
||||
"observations": ef.observations,
|
||||
"hypothesis_evaluation": ef.hypothesis_evaluation,
|
||||
"new_hypothesis": ef.new_hypothesis,
|
||||
"decision": ef.decision,
|
||||
"reason": ef.reason,
|
||||
"exception": ef.exception,
|
||||
if isinstance(obj, ExperimentFeedback):
|
||||
ef: ExperimentFeedback = obj
|
||||
content = (
|
||||
{
|
||||
"observations": str(ef.observations),
|
||||
"hypothesis_evaluation": ef.hypothesis_evaluation,
|
||||
"new_hypothesis": ef.new_hypothesis,
|
||||
"decision": ef.decision,
|
||||
"reason": ef.reason,
|
||||
"exception": ef.exception,
|
||||
}
|
||||
if isinstance(ef, HypothesisFeedback)
|
||||
else {
|
||||
"decision": ef.decision,
|
||||
"reason": ef.reason,
|
||||
"exception": ef.exception,
|
||||
}
|
||||
)
|
||||
data = {
|
||||
"id": id,
|
||||
"msg": {
|
||||
"tag": "feedback.hypothesis_feedback",
|
||||
"timestamp": timestamp,
|
||||
"loop_id": li,
|
||||
"content": content,
|
||||
},
|
||||
}
|
||||
if isinstance(ef, HypothesisFeedback)
|
||||
else {
|
||||
"decision": ef.decision,
|
||||
"reason": ef.reason,
|
||||
"exception": ef.exception,
|
||||
}
|
||||
)
|
||||
data = {
|
||||
"id": id,
|
||||
"msg": {
|
||||
"tag": "feedback.hypothesis_feedback",
|
||||
"timestamp": timestamp,
|
||||
"loop_id": li,
|
||||
"content": content,
|
||||
},
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
Reference in New Issue
Block a user