From 99d12e2861798ea9f3d756f5fd97ff85207a7c7e Mon Sep 17 00:00:00 2001 From: XianBW <36835909+XianBW@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:37:15 +0800 Subject: [PATCH] feat: streamlit webapp demo for different scenarios (#135) add streamlit webapp demo & docs --- docs/_static/flow.png | Bin 0 -> 125836 bytes docs/demo_and_introduction.rst | 35 +- .../model_extraction_and_code/GeneralModel.py | 8 +- rdagent/log/ui/README.md | 36 - rdagent/log/ui/app.py | 744 ++++++++++++------ requirements.txt | 5 +- 6 files changed, 520 insertions(+), 308 deletions(-) create mode 100644 docs/_static/flow.png delete mode 100644 rdagent/log/ui/README.md diff --git a/docs/_static/flow.png b/docs/_static/flow.png new file mode 100644 index 0000000000000000000000000000000000000000..caca2c4c00bafe961b77ea6931ccc0f10a80f1c6 GIT binary patch literal 125836 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�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 literal 0 HcmV?d00001 diff --git a/docs/demo_and_introduction.rst b/docs/demo_and_introduction.rst index 0db9eb7a..38295a74 100644 --- a/docs/demo_and_introduction.rst +++ b/docs/demo_and_introduction.rst @@ -5,14 +5,39 @@ Demo and Introduction Introduction ============ -TODO: copy the content in the README.md +RD-Agent will generate some logs during the R&D process. These logs are very useful for debugging and understanding the R&D process. However, just viewing the terminal log is not intuitive enough. RD-Agent provides a web app to visualize the R&D process. You can easily view the R&D process and understand the R&D process better. A Quick Demo ============ -TODO: -- copy the demo content in the README.md -- Quick start for the demo. +Start Web App +------------- +In `RD-Agent/` folder, run: -TODO: link to more demos +.. code-block:: bash + + streamlit run rdagent/log/ui/app.py --server.port -- --log_dir + +This will start a web app on `http://localhost:`. + +**NOTE**: The log_dir parameter is not required. You can manually enter the log_path in the web app. If you set the log_dir parameter, you can easily select a different log_path in the web app. + +Use Web App +----------- + +1. Open the sidebar. + +2. Select the scenario you want to show. There are some pre-defined scenarios: + - Qlib Model + - Qlib Factor + - Data Mining + - Model from Paper + +3. Click the `Config⚙️` button and input the log path (if you set the log_dir parameter, you can select a log_path in the dropdown list). + +4. Click the buttons below Config⚙️ to show the scenario execution process. Buttons are: + - All Loops: Show complete scenario execution process. + - Next Loop: Show one success **R&D Loop**. + - One Evolving: Show one **evolving** step of **development** part. + - refresh logs: clear shown logs. \ No newline at end of file diff --git a/rdagent/app/model_extraction_and_code/GeneralModel.py b/rdagent/app/model_extraction_and_code/GeneralModel.py index 1b9a831b..b3194649 100644 --- a/rdagent/app/model_extraction_and_code/GeneralModel.py +++ b/rdagent/app/model_extraction_and_code/GeneralModel.py @@ -31,10 +31,10 @@ class GeneralModelScenario(Scenario): @property def rich_style_description(self) -> str: return """ -# [Model Research & Development Co-Pilot] (#_scenario) - -## [Overview](#_summary) - +### [Model Research & Development Co-Pilot](#_scenario) + +#### [Overview](#_summary) + This demo automates the extraction and development of PyTorch models from academic papers. It supports various model types through two main components: Reader and Coder. #### [Workflow Components](#_rdloops) diff --git a/rdagent/log/ui/README.md b/rdagent/log/ui/README.md deleted file mode 100644 index b5b54aa0..00000000 --- a/rdagent/log/ui/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# start web app - -in `RD-Agent/` folder, run `streamlit run rdagent/log/ui/app.py --server.port 14000` - -## custom windows - -in `rdagent.log.ui.web.py` - -StWindow is the base window, can show common log messages like logger in terminal. - -Windows can be nested. - -Simply, just write a window for one log object type, and use `isinstance()` to display messages in different windows. - -### some base windows - -- StWindow -- LLMWindow -- CodeWindow - -### multi tabs window - -More convenient to use nested windows - -- ProgressTabsWindow -- ObjectsTabsWindow - -### main trace window - -- QlibFactorTraceWindow - -## TODOS - -- make it like a living trace -- display real living trace -- Window Styles diff --git a/rdagent/log/ui/app.py b/rdagent/log/ui/app.py index 7f22d8dd..5502b072 100644 --- a/rdagent/log/ui/app.py +++ b/rdagent/log/ui/app.py @@ -1,6 +1,8 @@ -import time +import argparse +import textwrap from collections import defaultdict from datetime import datetime, timezone +from pathlib import Path from typing import Callable, Type import pandas as pd @@ -8,9 +10,11 @@ import plotly.express as px import plotly.graph_objects as go import streamlit as st from plotly.subplots import make_subplots +from st_btn_select import st_btn_select from streamlit import session_state as state from streamlit.delta_generator import DeltaGenerator +from rdagent.app.model_extraction_and_code.GeneralModel import GeneralModelScenario from rdagent.components.coder.factor_coder.CoSTEER.evaluators import ( FactorSingleFeedback, ) @@ -21,20 +25,47 @@ from rdagent.core.proposal import Hypothesis, HypothesisFeedback from rdagent.log.base import Message from rdagent.log.storage import FileStorage from rdagent.log.ui.qlib_report_figure import report_figure -from rdagent.scenarios.qlib.experiment.factor_experiment import QlibFactorExperiment +from rdagent.scenarios.data_mining.experiment.model_experiment import DMModelScenario +from rdagent.scenarios.qlib.experiment.factor_experiment import ( + QlibFactorExperiment, + QlibFactorScenario, +) from rdagent.scenarios.qlib.experiment.model_experiment import ( QlibModelExperiment, QlibModelScenario, ) -st.set_page_config(layout="wide") +st.set_page_config(layout="wide", page_title="RD-Agent", page_icon="🎓", initial_sidebar_state="expanded") -if "log_path" not in state: - state.log_path = "" +# 获取log_path参数 +parser = argparse.ArgumentParser(description="RD-Agent Streamlit App") +parser.add_argument("--log_dir", type=str, help="Path to the log directory") +args = parser.parse_args() +if args.log_dir: + main_log_path = Path(args.log_dir) + if not main_log_path.exists(): + st.error(f"Log dir `{main_log_path}` does not exist!") + st.stop() +else: + main_log_path = None + + +SELECTED_METRICS = [ + "IC", + "1day.excess_return_without_cost.annualized_return", + "1day.excess_return_without_cost.information_ratio", + "1day.excess_return_without_cost.max_drawdown", +] if "log_type" not in state: - state.log_type = "qlib_model" + state.log_type = "Qlib Model" + +if "log_path" not in state: + if main_log_path: + state.log_path = next(main_log_path.iterdir()).relative_to(main_log_path) + else: + state.log_path = "" if "fs" not in state: state.fs = None @@ -54,6 +85,9 @@ if "lround" not in state: if "erounds" not in state: state.erounds = defaultdict(int) # Evolving Rounds in each RD Loop +if "e_decisions" not in state: + state.e_decisions = defaultdict(lambda: defaultdict(tuple)) + # Summary Info if "hypotheses" not in state: # Hypotheses in each RD Loop @@ -65,17 +99,26 @@ if "h_decisions" not in state: if "metric_series" not in state: state.metric_series = [] +# Factor Task Baseline +if "alpha158_metrics" not in state: + state.alpha158_metrics = None + def refresh(): - state.fs = FileStorage(state.log_path).iter_msg() + if main_log_path: + state.fs = FileStorage(main_log_path / state.log_path).iter_msg() + else: + state.fs = FileStorage(state.log_path).iter_msg() state.msgs = defaultdict(lambda: defaultdict(list)) state.lround = 0 state.erounds = defaultdict(int) + state.e_decisions = defaultdict(lambda: defaultdict(tuple)) state.hypotheses = defaultdict(None) state.h_decisions = defaultdict(bool) state.metric_series = [] state.last_msg = None state.current_tags = [] + state.alpha158_metrics = None def should_display(msg: Message): @@ -103,54 +146,341 @@ def get_msgs_until(end_func: Callable[[Message], bool] = lambda _: True): state.current_tags = tags state.last_msg = msg - state.msgs[state.lround][msg.tag].append(msg) # Update Summary Info if "model runner result" in tags or "factor runner result" in tags or "runner result" in tags: + # factor baseline exp metrics + if state.log_type == "Qlib Factor" and state.alpha158_metrics is None: + sms = msg.content.based_experiments[0].result.loc[SELECTED_METRICS] + sms.name = "alpha158" + state.alpha158_metrics = sms + + # common metrics if msg.content.result is None: - state.metric_series.append(pd.Series([None], index=["AUROC"])) + state.metric_series.append(pd.Series([None], index=["AUROC"], name=f"Round {state.lround}")) else: - if msg.content.result.name == "AUROC": + if len(msg.content.result) < 4: ps = msg.content.result ps.index = ["AUROC"] + ps.name = f"Round {state.lround}" state.metric_series.append(ps) else: - state.metric_series.append( - msg.content.result.loc[ - [ - "IC", - "1day.excess_return_without_cost.annualized_return", - "1day.excess_return_without_cost.information_ratio", - "1day.excess_return_without_cost.max_drawdown", - ] - ] - ) + sms = msg.content.result.loc[SELECTED_METRICS] + sms.name = f"Round {state.lround}" + state.metric_series.append(sms) elif "hypothesis generation" in tags: state.hypotheses[state.lround] = msg.content elif "ef" in tags and "feedback" in tags: state.h_decisions[state.lround] = msg.content.decision + elif "d" in tags: + if "evolving code" in tags: + msg.content = [i for i in msg.content if i] + if "evolving feedback" in tags: + msg.content = [i for i in msg.content if i] + if len(msg.content) != len(state.msgs[state.lround]["d.evolving code"][-1].content): + st.toast(":red[**Evolving Feedback Length Error!**]", icon="‼️") + right_num = 0 + for wsf in msg.content: + if wsf.final_decision: + right_num += 1 + wrong_num = len(msg.content) - right_num + state.e_decisions[state.lround][state.erounds[state.lround]] = (right_num, wrong_num) + state.msgs[state.lround][msg.tag].append(msg) # Stop Getting Logs if end_func(msg): break except StopIteration: + st.toast(":red[**No More Logs to Show!**]", icon="🛑") break +def evolving_feedback_window(wsf: FactorSingleFeedback | ModelCoderFeedback): + if isinstance(wsf, FactorSingleFeedback): + ffc, efc, cfc, vfc = st.tabs( + ["**Final Feedback🏁**", "Execution Feedback🖥️", "Code Feedback📄", "Value Feedback🔢"] + ) + with ffc: + st.markdown(wsf.final_feedback) + with efc: + st.code(wsf.execution_feedback, language="log") + with cfc: + st.markdown(wsf.code_feedback) + with vfc: + st.markdown(wsf.factor_value_feedback) + elif isinstance(wsf, ModelCoderFeedback): + ffc, efc, cfc, msfc, vfc = st.tabs( + [ + "**Final Feedback🏁**", + "Execution Feedback🖥️", + "Code Feedback📄", + "Model Shape Feedback📐", + "Value Feedback🔢", + ] + ) + with ffc: + st.markdown(wsf.final_feedback) + with efc: + st.code(wsf.execution_feedback, language="log") + with cfc: + st.markdown(wsf.code_feedback) + with msfc: + st.markdown(wsf.shape_feedback) + with vfc: + st.markdown(wsf.value_feedback) + + +def display_hypotheses(hypotheses: dict[int, Hypothesis], decisions: dict[int, bool], success_only: bool = False): + if success_only: + shd = {k: v.__dict__ for k, v in hypotheses.items() if decisions[k]} + else: + shd = {k: v.__dict__ for k, v in hypotheses.items()} + df = pd.DataFrame(shd).T + if "reason" in df.columns: + df.drop(["reason"], axis=1, inplace=True) + df.columns = df.columns.map(lambda x: x.replace("_", " ").capitalize()) + + def style_rows(row): + if decisions[row.name]: + return ["color: green;"] * len(row) + return [""] * len(row) + + def style_columns(col): + if col.name != "Hypothesis": + return ["font-style: italic;"] * len(col) + return ["font-weight: bold;"] * len(col) + + # st.dataframe(df.style.apply(style_rows, axis=1).apply(style_columns, axis=0)) + st.markdown(df.style.apply(style_rows, axis=1).apply(style_columns, axis=0).to_html(), unsafe_allow_html=True) + + +def metrics_window(df: pd.DataFrame, R: int, C: int, *, height: int = 300, colors: list[str] = None): + fig = make_subplots(rows=R, cols=C, subplot_titles=df.columns) + + def hypothesis_hover_text(h: Hypothesis, d: bool = False): + color = "green" if d else "black" + text = h.hypothesis + lines = textwrap.wrap(text, width=60) + return f"{'
'.join(lines)}
" + + hover_texts = [ + hypothesis_hover_text(state.hypotheses[int(i[6:])], state.h_decisions[int(i[6:])]) + for i in df.index + if i != "alpha158" + ] + if state.alpha158_metrics is not None: + hover_texts = ["Baseline: alpha158"] + hover_texts + for ci, col in enumerate(df.columns): + row = ci // C + 1 + col_num = ci % C + 1 + fig.add_trace( + go.Scatter( + x=df.index, + y=df[col], + name=col, + mode="lines+markers", + connectgaps=True, + marker=dict(size=10, color=colors[ci]) if colors else dict(size=10), + hovertext=hover_texts, + hovertemplate="%{hovertext}

%{x} Value: %{y}", + ), + row=row, + col=col_num, + ) + fig.update_layout(showlegend=False, height=height) + + if state.alpha158_metrics is not None: + for i in range(1, R + 1): # 行 + for j in range(1, C + 1): # 列 + fig.update_xaxes( + tickvals=[df.index[0]] + list(df.index[1:]), + ticktext=[f'{df.index[0]}'] + list(df.index[1:]), + row=i, + col=j, + ) + st.plotly_chart(fig) + + +def summary_window(): + if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"]: + st.header("Summary📊", divider="rainbow", anchor="_summary") + with st.container(): + # TODO: not fixed height + with st.container(): + bc, cc = st.columns([2, 2], vertical_alignment="center") + with bc: + st.subheader("Metrics📈", anchor="_metrics") + with cc: + show_true_only = st.toggle("successful hypotheses", value=False) + + # hypotheses_c, chart_c = st.columns([2, 3]) + chart_c = st.container() + hypotheses_c = st.container() + + with hypotheses_c: + st.subheader("Hypotheses🏅", anchor="_hypotheses") + display_hypotheses(state.hypotheses, state.h_decisions, show_true_only) + + with chart_c: + if state.log_type == "Qlib Factor" and state.alpha158_metrics is not None: + df = pd.DataFrame([state.alpha158_metrics] + state.metric_series) + else: + df = pd.DataFrame(state.metric_series) + if show_true_only and len(state.hypotheses) >= len(state.metric_series): + if state.alpha158_metrics is not None: + selected = ["alpha158"] + [i for i in df.index if state.h_decisions[int(i[6:])]] + else: + selected = [i for i in df.index if state.h_decisions[int(i[6:])]] + df = df.loc[selected] + if df.shape[0] == 1: + st.table(df.iloc[0]) + elif df.shape[0] > 1: + if df.shape[1] == 1: + # suhan's scenario + fig = px.line(df, x=df.index, y=df.columns, markers=True) + fig.update_layout(xaxis_title="Loop Round", yaxis_title=None) + st.plotly_chart(fig) + else: + metrics_window(df, 1, 4, height=300, colors=["red", "blue", "orange", "green"]) + + elif state.log_type == "Model from Paper" and len(state.msgs[state.lround]["d.evolving code"]) > 0: + with st.container(border=True): + st.subheader("Summary📊", divider="rainbow", anchor="_summary") + + # pass + ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[state.lround]["d.evolving code"][-1].content + # All Tasks + + tab_names = [ + w.target_task.factor_name if isinstance(w.target_task, FactorTask) else w.target_task.name for w in ws + ] + for j in range(len(ws)): + if state.msgs[state.lround]["d.evolving feedback"][-1].content[j].final_decision: + tab_names[j] += "✔️" + else: + tab_names[j] += "❌" + + wtabs = st.tabs(tab_names) + for j, w in enumerate(ws): + with wtabs[j]: + # Evolving Code + for k, v in w.code_dict.items(): + with st.expander(f":green[`{k}`]", expanded=False): + st.code(v, language="python") + + # Evolving Feedback + evolving_feedback_window(state.msgs[state.lround]["d.evolving feedback"][-1].content[j]) + + +def tabs_hint(): + st.markdown( + "

You can navigate through the tabs using ⬅️ ➡️ or by holding Shift and scrolling with the mouse wheel🖱️.

", + unsafe_allow_html=True, + ) + + +# TODO: when tab names are too long, some tabs are not shown +def tasks_window(tasks: list[FactorTask | ModelTask]): + if isinstance(tasks[0], FactorTask): + st.markdown("**Factor Tasks🚩**") + tnames = [f.factor_name for f in tasks] + if sum(len(tn) for tn in tnames) > 100: + tabs_hint() + tabs = st.tabs(tnames) + for i, ft in enumerate(tasks): + with tabs[i]: + # st.markdown(f"**Factor Name**: {ft.factor_name}") + st.markdown(f"**Description**: {ft.factor_description}") + st.latex("Formulation") + st.latex(f"{ft.factor_formulation}") + + mks = "| Variable | Description |\n| --- | --- |\n" + for v, d in ft.variables.items(): + mks += f"| ${v}$ | {d} |\n" + st.markdown(mks) + + elif isinstance(tasks[0], ModelTask): + st.markdown("**Model Tasks🚩**") + tnames = [m.name for m in tasks] + if sum(len(tn) for tn in tnames) > 100: + tabs_hint() + tabs = st.tabs(tnames) + for i, mt in enumerate(tasks): + with tabs[i]: + # st.markdown(f"**Model Name**: {mt.name}") + st.markdown(f"**Model Type**: {mt.model_type}") + st.markdown(f"**Description**: {mt.description}") + st.latex("Formulation") + st.latex(f"{mt.formulation}") + + mks = "| Variable | Description |\n| --- | --- |\n" + for v, d in mt.variables.items(): + mks += f"| ${v}$ | {d} |\n" + st.markdown(mks) + + # Config Sidebar with st.sidebar: - st.text_input("log path", key="log_path", on_change=refresh) - st.selectbox("trace type", ["qlib_model", "qlib_factor", "model_extraction_and_implementation"], key="log_type") + st.markdown( + """ +# RD-Agent🤖 +## [Scenario Description](#_scenario) +## [Summary](#_summary) +- [**Hypotheses**](#_hypotheses) +- [**Metrics**](#_metrics) +## [RD-Loops](#_rdloops) +- [**Research**](#_research) +- [**Development**](#_development) +- [**Feedback**](#_feedback) +""" + ) - st.multiselect("excluded log tags", ["llm_messages"], ["llm_messages"], key="excluded_tags") - st.multiselect("excluded log types", ["str", "dict", "list"], ["str"], key="excluded_types") + st.selectbox( + ":green[**Scenario**]", ["Qlib Model", "Data Mining", "Qlib Factor", "Model from Paper"], key="log_type" + ) - if st.button("refresh"): + with st.popover(":orange[**Config⚙️**]"): + with st.container(border=True): + st.markdown(":blue[**log path**]") + if main_log_path: + if st.toggle("Manual Input"): + st.text_input("log path", key="log_path", on_change=refresh) + else: + folders = [ + folder.relative_to(main_log_path) for folder in main_log_path.iterdir() if folder.is_dir() + ] + st.selectbox(f"Select from `{main_log_path}`", folders, key="log_path", on_change=refresh) + else: + st.text_input("log path", key="log_path", on_change=refresh) + + with st.container(border=True): + st.markdown(":blue[**excluded configs**]") + st.multiselect("excluded log tags", ["llm_messages"], ["llm_messages"], key="excluded_tags") + st.multiselect("excluded log types", ["str", "dict", "list"], ["str"], key="excluded_types") + + if st.button("All Loops"): + if not state.fs: + refresh() + get_msgs_until(lambda m: False) + + if st.button("Next Loop"): + if not state.fs: + refresh() + get_msgs_until(lambda m: "ef.feedback" in m.tag) + + if st.button("One Evolving"): + if not state.fs: + refresh() + get_msgs_until(lambda m: "d.evolving feedback" in m.tag) + + if st.button("refresh logs", help="clear all log messages in cache"): refresh() - debug = st.checkbox("debug", value=False) + debug = st.toggle("debug", value=False) if debug: if st.button("Single Step Run"): + if not state.fs: + refresh() get_msgs_until() @@ -174,148 +504,70 @@ if debug: if isinstance(state.last_msg.content, list): st.write(state.last_msg.content[0]) elif not isinstance(state.last_msg.content, str): - st.write(state.last_msg.content) + st.write(state.last_msg.content.__dict__) # Main Window +header_c1, header_c3 = st.columns([1, 6], vertical_alignment="center") +with st.container(): + with header_c1: + st.image("https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31") + with header_c3: + st.markdown( + """ +

+ RD-Agent:
LLM-based autonomous evolving agents for industrial data-driven R&D +

+ """, + unsafe_allow_html=True, + ) # Project Info with st.container(): - image_c, toc_c = st.columns([3, 3], vertical_alignment="center") + image_c, scen_c = st.columns([3, 3], vertical_alignment="center") with image_c: - st.image("./docs/_static/scen.jpg") - with toc_c: - st.markdown( - """ -# RD-Agent🤖 -## [Scenario Description](#_scenario) -## [Summary](#_summary) -## [RD-Loops](#_rdloops) -### [Research](#_research) -### [Development](#_development) -### [Feedback](#_feedback) -""" - ) -with st.container(border=True): - st.header("Scenario Description📖", divider=True, anchor="_scenario") - # TODO: other scenarios - if state.log_type == "qlib_model": - st.markdown(QlibModelScenario().rich_style_description) - elif state.log_type == "model_extraction_and_implementation": - st.markdown( - """ -# General Model Scenario - -## Overview - -This demo automates the extraction and iterative development of models from academic papers, ensuring functionality and correctness. - -### Scenario: Auto-Developing Model Code from Academic Papers - -#### Overview - -This scenario automates the development of PyTorch models by reading academic papers or other sources. It supports various data types, including tabular, time-series, and graph data. The primary workflow involves two main components: the Reader and the Coder. - -#### Workflow Components - -1. **Reader** -- Parses and extracts relevant model information from academic papers or sources, including architectures, parameters, and implementation details. -- Uses Large Language Models to convert content into a structured format for the Coder. - -2. **Evolving Coder** -- Translates structured information from the Reader into executable PyTorch code. -- Utilizes an evolving coding mechanism to ensure correct tensor shapes, verified with sample input tensors. -- Iteratively refines the code to align with source material specifications. - -#### Supported Data Types - -- **Tabular Data:** Structured data with rows and columns, such as spreadsheets or databases. -- **Time-Series Data:** Sequential data points indexed in time order, useful for forecasting and temporal pattern recognition. -- **Graph Data:** Data structured as nodes and edges, suitable for network analysis and relational tasks. -""" - ) + st.image("./docs/_static/flow.png") + with scen_c: + st.header("Scenario Description📖", divider="violet", anchor="_scenario") + # TODO: other scenarios + if state.log_type == "Qlib Model": + st.markdown(QlibModelScenario().rich_style_description) + elif state.log_type == "Data Mining": + st.markdown(DMModelScenario().rich_style_description) + elif state.log_type == "Qlib Factor": + st.markdown(QlibFactorScenario().rich_style_description) + elif state.log_type == "Model from Paper": + st.markdown(GeneralModelScenario().rich_style_description) # Summary Window -@st.experimental_fragment() -def summary_window(): - if state.log_type in ["qlib_model", "qlib_factor"]: - with st.container(): - st.header("Summary📊", divider=True, anchor="_summary") - hypotheses_c, chart_c = st.columns([2, 3]) - # TODO: not fixed height - with hypotheses_c.container(height=600): - st.markdown("**Hypotheses🏅**") - h_str = "\n".join( - f"{id}. :green[**{h.hypothesis}**]\n\t>:green-background[*{h.__dict__.get('concise_reason', '')}*]" - if state.h_decisions[id] - else f"{id}. {h.hypothesis}\n\t>*{h.__dict__.get('concise_reason', '')}*" - for id, h in state.hypotheses.items() - ) - st.markdown(h_str) - with chart_c.container(height=600): - mt_c, ms_c = st.columns(2, vertical_alignment="center") - with mt_c: - st.markdown("**Metrics📈**") - with ms_c: - show_true_only = st.checkbox("True Decisions Only", value=False) - - labels = [f"Round {i}" for i in range(1, len(state.metric_series) + 1)] - df = pd.DataFrame(state.metric_series, index=labels) - if show_true_only and len(state.hypotheses) >= len(state.metric_series): - df = df.iloc[[i for i in range(df.shape[0]) if state.h_decisions[i + 1]]] - if df.shape[0] == 1: - st.table(df.iloc[0]) - elif df.shape[0] > 1: - # TODO: figure label - # TODO: separate into different figures - if df.shape[1] == 1: - # suhan's scenario - fig = px.line(df, x=df.index, y=df.columns, markers=True) - fig.update_layout(legend_title_text="Metrics", xaxis_title="Loop Round", yaxis_title=None) - else: - # 2*2 figure - fig = make_subplots(rows=2, cols=2, subplot_titles=df.columns) - for ci, col in enumerate(df.columns): - row = ci // 2 + 1 - col_num = ci % 2 + 1 - fig.add_trace( - go.Scatter(x=df.index, y=df[col], mode="lines+markers", name=col), row=row, col=col_num - ) - fig.update_layout(title_text="Metrics", showlegend=False) - st.plotly_chart(fig) - - summary_window() # R&D Loops Window -st.header("R&D Loops♾️", divider=True, anchor="_rdloops") -button_c1, button_c2, round_s_c = st.columns([2, 3, 18], vertical_alignment="center") -with button_c1: - if st.button("Run One Loop"): - get_msgs_until(lambda m: "ef.feedback" in m.tag) -with button_c2: - if st.button("Run One Evolving Step"): - get_msgs_until(lambda m: "d.evolving feedback" in m.tag) +if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"]: + st.header("R&D Loops♾️", divider="rainbow", anchor="_rdloops") -if len(state.msgs) > 1: - with round_s_c: - round = st.select_slider("Select RDLoop Round", options=state.msgs.keys(), value=state.lround) +if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"]: + if len(state.msgs) > 1: + r_options = list(state.msgs.keys()) + if 0 in r_options: + r_options.remove(0) + round = st_btn_select(options=r_options, index=state.lround - 1) + else: + round = 1 else: round = 1 -rf_c, d_c = st.columns([2, 2]) -# Research & Feedback Window -with rf_c: - if state.log_type in ["qlib_model", "qlib_factor"]: - # Research Window - with st.container(border=True): - st.subheader("Research🔍", divider=True, anchor="_research") +def research_window(): + with st.container(border=True): + title = "Research🔍" if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"] else "Research🔍 (reader)" + st.subheader(title, divider="blue", anchor="_research") + if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"]: # pdf image if pim := state.msgs[round]["r.extract_factors_and_implement.load_pdf_screenshot"]: for i in range(min(2, len(pim))): - st.image(pim[i].content) + st.image(pim[i].content, use_column_width=True) # Hypothesis if hg := state.msgs[round]["r.hypothesis generation"]: @@ -328,37 +580,27 @@ with rf_c: ) if eg := state.msgs[round]["r.experiment generation"]: - if isinstance(eg[0].content[0], FactorTask): - st.markdown("**Factor Tasks**") - fts = eg[0].content - tabs = st.tabs([f.factor_name for f in fts]) - for i, ft in enumerate(fts): - with tabs[i]: - # st.markdown(f"**Factor Name**: {ft.factor_name}") - st.markdown(f"**Description**: {ft.factor_description}") - st.latex(f"Formulation: {ft.factor_formulation}") + tasks_window(eg[0].content) - variables_df = pd.DataFrame(ft.variables, index=["Description"]).T - variables_df.index.name = "Variable" - st.table(variables_df) - elif isinstance(eg[0].content[0], ModelTask): - st.markdown("**Model Tasks**") - mts = eg[0].content - tabs = st.tabs([m.name for m in mts]) - for i, mt in enumerate(mts): - with tabs[i]: - # st.markdown(f"**Model Name**: {mt.name}") - st.markdown(f"**Model Type**: {mt.model_type}") - st.markdown(f"**Description**: {mt.description}") - st.latex(f"Formulation: {mt.formulation}") + elif state.log_type == "Model from Paper": + # pdf image + c1, c2 = st.columns([2, 3]) + with c1: + if pim := state.msgs[round]["r.pdf_image"]: + for i in range(len(pim)): + st.image(pim[i].content, use_column_width=True) - variables_df = pd.DataFrame(mt.variables, index=["Value"]).T - variables_df.index.name = "Variable" - st.table(variables_df) + # loaded model exp + with c2: + if mem := state.msgs[round]["d.load_experiment"]: + me: QlibModelExperiment = mem[0].content + tasks_window(me.sub_tasks) - # Feedback Window + +def feedback_window(): + if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"]: with st.container(border=True): - st.subheader("Feedback📝", divider=True, anchor="_feedback") + st.subheader("Feedback📝", divider="orange", anchor="_feedback") if fbr := state.msgs[round]["ef.Quantitative Backtesting Chart"]: st.markdown("**Returns📈**") fig = report_figure(fbr[0].content) @@ -375,104 +617,82 @@ with rf_c: - **Reason**: {h.reason}""" ) - elif state.log_type == "model_extraction_and_implementation": - # Research Window - with st.container(border=True): - # pdf image - st.subheader("Research🔍", divider=True, anchor="_research") - if pim := state.msgs[round]["r.pdf_image"]: - for i in range(len(pim)): - st.image(pim[i].content) - # loaded model exp - if mem := state.msgs[round]["d.load_experiment"]: - me: QlibModelExperiment = mem[0].content - mts: list[ModelTask] = me.sub_tasks - tabs = st.tabs([m.name for m in mts]) - for i, mt in enumerate(mts): - with tabs[i]: - # st.markdown(f"**Model Name**: {mt.name}") - st.markdown(f"**Model Type**: {mt.model_type}") - st.markdown(f"**Description**: {mt.description}") - st.latex(f"Formulation: {mt.formulation}") +if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"]: + rf_c, d_c = st.columns([2, 2]) +elif state.log_type == "Model from Paper": + rf_c = st.container() + d_c = st.container() - variables_df = pd.DataFrame(mt.variables, index=["Value"]).T - variables_df.index.name = "Variable" - st.table(variables_df) - # Feedback Window - with st.container(border=True): - st.subheader("Feedback📝", divider=True, anchor="_feedback") - if fbr := state.msgs[round]["d.developed_experiment"]: - st.markdown("**Returns📈**") - result_df = fbr[0].content.result - if result_df: - fig = report_figure(result_df) - st.plotly_chart(fig) - else: - st.markdown("Returns is None") +with rf_c: + research_window() + feedback_window() # Development Window (Evolving) with d_c.container(border=True): - st.subheader("Development🛠️", divider=True, anchor="_development") + title = ( + "Development🛠️" + if state.log_type in ["Qlib Model", "Data Mining", "Qlib Factor"] + else "Development🛠️ (evolving coder)" + ) + st.subheader(title, divider="green", anchor="_development") + + # Evolving Status + if state.erounds[round] > 0: + st.markdown("**☑️ Evolving Status**") + es = state.e_decisions[round] + e_status_mks = "".join(f"| {ei} " for ei in range(1, state.erounds[round] + 1)) + "|\n" + e_status_mks += "|--" * state.erounds[round] + "|\n" + for ei, estatus in es.items(): + if not estatus: + estatus = (0, 0) + e_status_mks += "| " + "✔️
" * estatus[0] + "❌
" * estatus[1] + " " + e_status_mks += "|\n" + st.markdown(e_status_mks, unsafe_allow_html=True) + # Evolving Tabs if state.erounds[round] > 0: - etabs = st.tabs([str(i) for i in range(1, state.erounds[round] + 1)]) + if state.erounds[round] > 1: + st.markdown("**🔄️Evolving Rounds**") + evolving_round = st_btn_select( + options=range(1, state.erounds[round] + 1), index=state.erounds[round] - 1, key="show_eround" + ) + else: + evolving_round = 1 - for i in range(0, state.erounds[round]): - with etabs[i]: - ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[round]["d.evolving code"][i].content - ws = [w for w in ws if w] - # All Tasks + ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[round]["d.evolving code"][ + evolving_round - 1 + ].content + # All Tasks - tab_names = [ - w.target_task.factor_name if isinstance(w.target_task, FactorTask) else w.target_task.name for w in ws - ] - wtabs = st.tabs(tab_names) - for j, w in enumerate(ws): - with wtabs[j]: - # Evolving Code - for k, v in w.code_dict.items(): - with st.expander(f":green[`{k}`]", expanded=True): - st.code(v, language="python") + tab_names = [ + w.target_task.factor_name if isinstance(w.target_task, FactorTask) else w.target_task.name for w in ws + ] + if len(state.msgs[round]["d.evolving feedback"]) >= evolving_round: + for j in range(len(ws)): + if state.msgs[round]["d.evolving feedback"][evolving_round - 1].content[j].final_decision: + tab_names[j] += "✔️" + else: + tab_names[j] += "❌" + if sum(len(tn) for tn in tab_names) > 100: + tabs_hint() + wtabs = st.tabs(tab_names) + for j, w in enumerate(ws): + with wtabs[j]: + # Evolving Code + for k, v in w.code_dict.items(): + with st.expander(f":green[`{k}`]", expanded=True): + st.code(v, language="python") - # Evolving Feedback - if len(state.msgs[round]["d.evolving feedback"]) > i: - wsf: list[FactorSingleFeedback | ModelCoderFeedback] = state.msgs[round]["d.evolving feedback"][ - i - ].content[j] - if isinstance(wsf, FactorSingleFeedback): - st.markdown( - f"""#### :blue[Factor Execution Feedback] -{wsf.execution_feedback} -#### :blue[Factor Code Feedback] -{wsf.code_feedback} -#### :blue[Factor Value Feedback] -{wsf.factor_value_feedback} -#### :blue[Factor Final Feedback] -{wsf.final_feedback} -#### :blue[Factor Final Decision] -This implementation is {'SUCCESS' if wsf.final_decision else 'FAIL'}. -""" - ) - elif isinstance(wsf, ModelCoderFeedback): - st.markdown( - f"""#### :blue[Model Execution Feedback] -{wsf.execution_feedback} -#### :blue[Model Shape Feedback] -{wsf.shape_feedback} -#### :blue[Model Value Feedback] -{wsf.value_feedback} -#### :blue[Model Code Feedback] -{wsf.code_feedback} -#### :blue[Model Final Feedback] -{wsf.final_feedback} -#### :blue[Model Final Decision] -This implementation is {'SUCCESS' if wsf.final_decision else 'FAIL'}. -""" - ) + # Evolving Feedback + if len(state.msgs[round]["d.evolving feedback"]) >= evolving_round: + evolving_feedback_window(state.msgs[round]["d.evolving feedback"][evolving_round - 1].content[j]) -# TODO: evolving tabs -> slider -# TODO: multi tasks SUCCESS/FAIL -# TODO: evolving progress bar, diff colors + +with st.container(border=True): + st.subheader("Disclaimer", divider="gray") + st.markdown( + "This content is AI-generated and may not be fully accurate or up-to-date; please verify with a professional for critical matters." + ) diff --git a/requirements.txt b/requirements.txt index b6d8f7e4..4d878f59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -61,4 +61,7 @@ python-dotenv # infrastructure related. docker - +# demo related +streamlit +plotly +st-btn-select