mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-18 13:55:17 +02:00
rm immature code, improve naming, add unittest test rsp cache
This commit is contained in:
parent
31a9410e6d
commit
4a7929d880
18 changed files with 275 additions and 704 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}%")
|
||||
31
tests/metagpt/roles/test_ml_engineer.py
Normal file
31
tests/metagpt/roles/test_ml_engineer.py
Normal 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
|
||||
|
|
@ -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}")
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue