rm immature code, improve naming, add unittest test rsp cache

This commit is contained in:
yzlin 2024-01-30 21:04:33 +08:00
parent 31a9410e6d
commit 4a7929d880
18 changed files with 275 additions and 704 deletions

View file

@ -3,11 +3,8 @@ import asyncio
import pytest
from metagpt.actions.execute_code import ExecutePyCode
from metagpt.actions.write_analysis_code import (
WriteCodeByGenerate,
WriteCodeWithTools,
WriteCodeWithToolsML,
)
from metagpt.actions.ml_action import WriteCodeWithToolsML
from metagpt.actions.write_analysis_code import WriteCodeByGenerate, WriteCodeWithTools
from metagpt.logs import logger
from metagpt.plan.planner import STRUCTURAL_CONTEXT
from metagpt.schema import Message, Plan, Task

View file

@ -9,7 +9,7 @@ from metagpt.schema import Plan
from metagpt.utils.recovery_util import load_history, save_history
async def run_code_interpreter(role_class, requirement, auto_run, use_tools, use_code_steps, save_dir, tools):
async def run_code_interpreter(role_class, requirement, auto_run, use_tools, save_dir, tools):
"""
The main function to run the MLEngineer with optional history loading.
@ -28,7 +28,6 @@ async def run_code_interpreter(role_class, requirement, auto_run, use_tools, use
role = MLEngineer(
auto_run=auto_run,
use_tools=use_tools,
use_code_steps=use_code_steps,
tools=tools,
)
@ -75,10 +74,9 @@ if __name__ == "__main__":
requirement: str = requirement,
auto_run: bool = auto_run,
use_tools: bool = use_tools,
use_code_steps: bool = False,
save_dir: str = save_dir,
tools=tools,
):
await run_code_interpreter(role_class, requirement, auto_run, use_tools, use_code_steps, save_dir, tools)
await run_code_interpreter(role_class, requirement, auto_run, use_tools, save_dir, tools)
fire.Fire(main)

View file

@ -3,11 +3,24 @@ import pytest
from metagpt.logs import logger
from metagpt.roles.code_interpreter import CodeInterpreter
# from metagpt.const import DATA_PATH
@pytest.mark.asyncio
async def test_code_interpreter():
@pytest.mark.parametrize("use_tools", [(True)])
async def test_code_interpreter(use_tools):
requirement = "Run data analysis on sklearn Iris dataset, include a plot"
ci = CodeInterpreter(goal=requirement, auto_run=True, use_tools=False)
# requirement = "Run data analysis on sklearn Wine recognition dataset, include a plot, and train a model to predict wine class (20% as validation), and show validation accuracy"
# data_path = f"{DATA_PATH}/titanic"
# requirement = f"This is a titanic passenger survival dataset, your goal is to predict passenger survival outcome. The target column is Survived. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report accuracy on the eval data. Train data path: '{data_path}/split_train.csv', eval data path: '{data_path}/split_eval.csv'."
# data_path = f"{DATA_PATH}/icr-identify-age-related-conditions"
# requirement = f"This is a medical dataset with over fifty anonymized health characteristics linked to three age-related conditions. Your goal is to predict whether a subject has or has not been diagnosed with one of these conditions.The target column is Class. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report f1 score on the eval data. Train data path: {data_path}/split_train.csv, eval data path: {data_path}/split_eval.csv."
# data_path = f"{DATA_PATH}/house-prices-advanced-regression-techniques"
# requirement = f"This is a house price dataset, your goal is to predict the sale price of a property based on its features. The target column is SalePrice. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report RMSE between the logarithm of the predicted value and the logarithm of the observed sales price on the eval data. Train data path: '{data_path}/split_train.csv', eval data path: '{data_path}/split_eval.csv'."
tools = []
# tools = ["FillMissingValue", "CatCross", "a"]
ci = CodeInterpreter(auto_run=True, use_tools=use_tools, tools=tools)
rsp = await ci.run(requirement)
logger.info(rsp)
assert len(rsp.content) > 0

View file

@ -1,50 +0,0 @@
import pytest
from tqdm import tqdm
from metagpt.logs import logger
from metagpt.roles.ml_engineer import ExecutePyCode, MLEngineer
from metagpt.schema import Plan
def reset(role):
"""Restart role with the same goal."""
role.working_memory.clear()
role.planner.plan = Plan(goal=role.planner.plan.goal)
role.execute_code = ExecutePyCode()
async def make_use_tools(requirement: str, auto_run: bool = True):
"""make and use tools for requirement."""
role = MLEngineer(goal=requirement, auto_run=auto_run)
# make udfs
role.use_tools = False
role.use_code_steps = False
role.make_udfs = True
role.use_udfs = False
await role.run(requirement)
# use udfs
reset(role)
role.make_udfs = False
role.use_udfs = True
role.use_code_steps = False
role.use_tools = False
await role.run(requirement)
@pytest.mark.asyncio
async def test_make_use_tools():
requirements = [
"Run data analysis on sklearn Iris dataset, include a plot",
"Run data analysis on sklearn Diabetes dataset, include a plot",
"Run data analysis on sklearn Wine recognition dataset, include a plot, and train a model to predict wine class (20% as validation), and show validation accuracy",
"Run data analysis on sklearn Wisconsin Breast Cancer dataset, include a plot, train a model to predict targets (20% as validation), and show validation accuracy",
"Run EDA and visualization on this dataset, train a model to predict survival, report metrics on validation set (20%), dataset: tests/data/titanic.csv",
]
success = 0
for requirement in tqdm(requirements, total=len(requirements)):
try:
await make_use_tools(requirement)
success += 1
except Exception as e:
logger.error(f"Found Error in {requirement}, {e}")
logger.info(f"success: {round(success/len(requirements), 1)*100}%")

View file

@ -0,0 +1,31 @@
import pytest
from metagpt.const import DATA_PATH
from metagpt.logs import logger
from metagpt.roles.ml_engineer import MLEngineer
def test_mle_init():
ci = MLEngineer(goal="test", auto_run=True, use_tools=True, tools=["tool1", "tool2"])
assert ci.tools == []
@pytest.mark.asyncio
@pytest.mark.parametrize("use_tools", [(True)])
async def test_code_interpreter(use_tools):
# requirement = "Run data analysis on sklearn Iris dataset, include a plot"
# requirement = "Run data analysis on sklearn Wine recognition dataset, include a plot, and train a model to predict wine class (20% as validation), and show validation accuracy"
data_path = f"{DATA_PATH}/titanic"
requirement = f"This is a titanic passenger survival dataset, your goal is to predict passenger survival outcome. The target column is Survived. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report accuracy on the eval data. Train data path: '{data_path}/split_train.csv', eval data path: '{data_path}/split_eval.csv'."
# data_path = f"{DATA_PATH}/icr-identify-age-related-conditions"
# requirement = f"This is a medical dataset with over fifty anonymized health characteristics linked to three age-related conditions. Your goal is to predict whether a subject has or has not been diagnosed with one of these conditions.The target column is Class. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report f1 score on the eval data. Train data path: {data_path}/split_train.csv, eval data path: {data_path}/split_eval.csv."
# data_path = f"{DATA_PATH}/santander-customer-transaction-prediction"
# requirement = f"This is a customers financial dataset. Your goal is to predict which customers will make a specific transaction in the future. The target column is target. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report AUC Score on the eval data. Train data path: '{data_path}/split_train.csv', eval data path: '{data_path}/split_eval.csv' ."
# data_path = f"{DATA_PATH}/house-prices-advanced-regression-techniques"
# requirement = f"This is a house price dataset, your goal is to predict the sale price of a property based on its features. The target column is SalePrice. Perform data analysis, data preprocessing, feature engineering, and modeling to predict the target. Report RMSE between the logarithm of the predicted value and the logarithm of the observed sales price on the eval data. Train data path: '{data_path}/split_train.csv', eval data path: '{data_path}/split_eval.csv'."
tools = ["FillMissingValue", "CatCross", "dummy_tool"]
mle = MLEngineer(goal=requirement, auto_run=True, use_tools=use_tools, tools=tools)
rsp = await mle.run(requirement)
logger.info(rsp)
assert len(rsp.content) > 0

View file

@ -1,49 +0,0 @@
import json
import yaml
from metagpt.logs import logger
from metagpt.tools.libs.udf import UDFS, UDFS_YAML, docstring_to_yaml
def test_udfs():
assert len(UDFS) > 0
assert "udf_name" in UDFS[0]
assert "udf_doc" in UDFS[0]
logger.info(UDFS)
def test_docstring2yaml():
docstring = """Calculate the duration in hours between two datetime columns.
Args:
dataframe (pd.DataFrame): The dataframe containing the datetime columns.
Returns:
pd.DataFrame: The dataframe with an additional column 'duration_hour' added.
"""
yaml_result = docstring_to_yaml(docstring, return_vars="dataframe")
assert "parameters" in yaml_result
assert "properties" in yaml_result["parameters"]
assert "dataframe" in yaml_result["parameters"]["properties"]
def test_UDFS_YAML():
assert len(UDFS_YAML) > 0
logger.info(f"\n\n{json.dumps(UDFS_YAML, indent=2, ensure_ascii=False)}")
function_schema = UDFS_YAML
assert "description" in function_schema[list(function_schema.keys())[0]]
assert "type" in function_schema[list(function_schema.keys())[0]]
assert "parameters" in function_schema[list(function_schema.keys())[0]]
assert "properties" in function_schema[list(function_schema.keys())[0]]["parameters"]
assert "required" in function_schema[list(function_schema.keys())[0]]["parameters"]
assert "returns" in function_schema[list(function_schema.keys())[0]]
# 指定要保存的文件路径
file_path = "./tests/data/function_schema.yaml"
# 使用 PyYAML 将字典保存为 YAML 文件
with open(file_path, "w") as file:
yaml.dump(function_schema, file, default_flow_style=False)
print(f"Data has been saved to {file_path}")

View file

@ -9,7 +9,6 @@ import nbformat
import pytest
from metagpt.actions.execute_code import ExecutePyCode
from metagpt.actions.write_analysis_code import WriteCodeByGenerate
from metagpt.utils.save_code import DATA_PATH, save_code_file
@ -17,11 +16,6 @@ def test_save_code_file_python():
save_code_file("example", "print('Hello, World!')")
file_path = DATA_PATH / "output" / "example" / "code.py"
assert os.path.exists(file_path), f"File does not exist: {file_path}"
def test_save_code_file_python():
save_code_file("example", "print('Hello, World!')")
file_path = DATA_PATH / "output" / "example" / "code.py"
with open(file_path, "r", encoding="utf-8") as fp:
content = fp.read()
assert "print('Hello, World!')" in content, "File content does not match"
@ -38,7 +32,7 @@ def test_save_code_file_json():
@pytest.mark.asyncio
async def test_save_code_file_notebook():
code = await WriteCodeByGenerate().run(context="basic python, hello world", plan="", code_steps="", temperature=0.0)
code = "print('Hello, World!')"
executor = ExecutePyCode()
await executor.run(code)
# Save as a Notebook file