mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-21 14:05:17 +02:00
fix conflict
This commit is contained in:
commit
14d88cc712
47 changed files with 1269 additions and 587 deletions
|
|
@ -110,7 +110,7 @@ async def test_write_refined_code(context, git_dir):
|
|||
|
||||
# old_workspace contains the legacy code
|
||||
await context.repo.with_src_path(context.repo.old_workspace).srcs.save(
|
||||
filename="game.py", content=CodeParser.parse_code(block="", text=REFINED_CODE_INPUT_SAMPLE)
|
||||
filename="game.py", content=CodeParser.parse_code(text=REFINED_CODE_INPUT_SAMPLE)
|
||||
)
|
||||
|
||||
ccontext = CodingContext(
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ async def test_write_code_plan_and_change_an(mocker, context, git_dir):
|
|||
await context.repo.docs.task.save(filename="2.json", content=json.dumps(REFINED_TASK_JSON))
|
||||
|
||||
await context.repo.with_src_path(context.repo.old_workspace).srcs.save(
|
||||
filename="game.py", content=CodeParser.parse_code(block="", text=REFINED_CODE_INPUT_SAMPLE)
|
||||
filename="game.py", content=CodeParser.parse_code(text=REFINED_CODE_INPUT_SAMPLE)
|
||||
)
|
||||
|
||||
root = ActionNode.from_children(
|
||||
|
|
|
|||
78
tests/metagpt/environment/mgx_env/run_mgx_env.py
Normal file
78
tests/metagpt/environment/mgx_env/run_mgx_env.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import asyncio
|
||||
import threading
|
||||
|
||||
from metagpt.environment.mgx.mgx_env import MGXEnv
|
||||
from metagpt.roles import (
|
||||
Architect,
|
||||
Engineer,
|
||||
ProductManager,
|
||||
ProjectManager,
|
||||
QaEngineer,
|
||||
)
|
||||
from metagpt.roles.di.data_analyst import DataAnalyst
|
||||
from metagpt.roles.di.team_leader import TeamLeader
|
||||
from metagpt.schema import Message
|
||||
|
||||
|
||||
async def main(requirement, enable_human_input=False):
|
||||
env = MGXEnv()
|
||||
env.add_roles(
|
||||
[
|
||||
TeamLeader(),
|
||||
ProductManager(),
|
||||
Architect(),
|
||||
ProjectManager(),
|
||||
Engineer(n_borg=5, use_code_review=False),
|
||||
QaEngineer(),
|
||||
DataAnalyst(tools=["<all>"]),
|
||||
]
|
||||
)
|
||||
|
||||
if enable_human_input:
|
||||
# simulate human sending messages in chatbox
|
||||
send_human_input(env)
|
||||
|
||||
env.publish_message(Message(content=requirement))
|
||||
|
||||
while not env.is_idle:
|
||||
await env.run()
|
||||
|
||||
|
||||
def send_human_input(env):
|
||||
"""
|
||||
Simulate sending message in chatbox
|
||||
Note in local environment, the message is consumed only after current round of env.run is finished
|
||||
"""
|
||||
|
||||
def send_messages():
|
||||
while True:
|
||||
message = input("Enter a message any time: ")
|
||||
env.publish_message(Message(content=message))
|
||||
|
||||
# Start a thread for sending messages
|
||||
send_thread = threading.Thread(target=send_messages, args=())
|
||||
send_thread.start()
|
||||
|
||||
|
||||
GAME_REQ = "create a 2048 game"
|
||||
SIMPLE_REQ = "print statistic summary of sklearn iris dataset"
|
||||
WINE_REQ = "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."
|
||||
PAPER_LIST_REQ = """
|
||||
Get data from `paperlist` table in https://papercopilot.com/statistics/iclr-statistics/iclr-2024-statistics/,
|
||||
and save it to a csv file. paper title must include `multiagent` or `large language model`. *notice: print key variables*
|
||||
"""
|
||||
ECOMMERCE_REQ = """
|
||||
Get products data from website https://scrapeme.live/shop/ and save it as a csv file.
|
||||
**Notice: Firstly parse the web page encoding and the text HTML structure;
|
||||
The first page product name, price, product URL, and image URL must be saved in the csv;**
|
||||
"""
|
||||
data_path = "data/titanic"
|
||||
train_path = f"{data_path}/split_train.csv"
|
||||
eval_path = f"{data_path}/split_eval.csv"
|
||||
TITANIC_REQ = 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: '{train_path}', eval data path: '{eval_path}'."
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# NOTE: Change the requirement to the one you want to test
|
||||
# Set enable_human_input to True if you want to simulate sending messages in chatbox
|
||||
asyncio.run(main(requirement=SIMPLE_REQ, enable_human_input=False))
|
||||
|
|
@ -91,7 +91,7 @@ target_code = """task_list = [
|
|||
|
||||
|
||||
def test_parse_code():
|
||||
code = CodeParser.parse_code("Task list", TASKS, lang="python")
|
||||
code = CodeParser.parse_code(block="Task list", text=TASKS, lang="python")
|
||||
logger.info(code)
|
||||
assert isinstance(code, str)
|
||||
assert target_code == code
|
||||
|
|
|
|||
|
|
@ -11,17 +11,44 @@ from pathlib import Path
|
|||
import pytest
|
||||
|
||||
from metagpt.actions import UserRequirement
|
||||
from metagpt.actions.prepare_documents import PrepareDocuments
|
||||
from metagpt.context import Context
|
||||
from metagpt.environment import Environment
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles import Architect, ProductManager, Role
|
||||
from metagpt.schema import Message
|
||||
from metagpt.roles import (
|
||||
Architect,
|
||||
Engineer,
|
||||
ProductManager,
|
||||
ProjectManager,
|
||||
QaEngineer,
|
||||
Role,
|
||||
)
|
||||
from metagpt.schema import Message, UserMessage
|
||||
from metagpt.utils.common import any_to_str, is_send_to
|
||||
|
||||
serdeser_path = Path(__file__).absolute().parent.joinpath("../data/serdeser_storage")
|
||||
|
||||
|
||||
class MockEnv(Environment):
|
||||
def publish_message(self, message: Message, peekable: bool = True) -> bool:
|
||||
consumers = []
|
||||
for role, addrs in self.member_addrs.items():
|
||||
if is_send_to(message, addrs):
|
||||
role.put_message(message)
|
||||
consumers.append(role)
|
||||
if not consumers:
|
||||
logger.warning(f"Message no recipients: {message.dump()}")
|
||||
if message.cause_by in [any_to_str(UserRequirement), any_to_str(PrepareDocuments)]:
|
||||
assert len(consumers) == 1
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env():
|
||||
return Environment()
|
||||
context = Context()
|
||||
context.kwargs.tag = __file__
|
||||
return MockEnv(context=context)
|
||||
|
||||
|
||||
def test_add_role(env: Environment):
|
||||
|
|
@ -54,10 +81,56 @@ async def test_publish_and_process_message(env: Environment):
|
|||
|
||||
env.add_roles([product_manager, architect])
|
||||
|
||||
env.publish_message(Message(role="User", content="需要一个基于LLM做总结的搜索引擎", cause_by=UserRequirement))
|
||||
env.publish_message(UserMessage(content="需要一个基于LLM做总结的搜索引擎", cause_by=UserRequirement, send_to=product_manager))
|
||||
await env.run(k=2)
|
||||
logger.info(f"{env.history=}")
|
||||
assert len(env.history) > 10
|
||||
logger.info(f"{env.history}")
|
||||
assert len(env.history.storage) == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
("content", "send_to"),
|
||||
[
|
||||
("snake game", any_to_str(ProductManager)),
|
||||
(
|
||||
"Rewrite the PRD file of the project at '/Users/iorishinier/github/MetaGPT/workspace/snake_game', add 'moving enemy' to the original requirement",
|
||||
any_to_str(ProductManager),
|
||||
),
|
||||
(
|
||||
"Add 'random moving enemy, and dispears after 10 seconds' design to the project at '/Users/iorishinier/github/MetaGPT/workspace/snake_game'",
|
||||
any_to_str(Architect),
|
||||
),
|
||||
(
|
||||
'Rewrite the tasks file of the project at "/Users/iorishinier/github/MetaGPT/workspace/snake_game"',
|
||||
any_to_str(ProjectManager),
|
||||
),
|
||||
(
|
||||
"Rewrite 'main.py' of the project at '/Users/iorishinier/github/MetaGPT/workspace/snake_game'",
|
||||
any_to_str(Engineer),
|
||||
),
|
||||
(
|
||||
"Rewrite the unit test of 'main.py' at '/Users/iorishinier/github/MetaGPT/workspace/snake_game'",
|
||||
any_to_str(QaEngineer),
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_env(content, send_to):
|
||||
context = Context()
|
||||
env = MockEnv(context=context)
|
||||
env.add_roles(
|
||||
[
|
||||
ProductManager(context=context),
|
||||
Architect(context=context),
|
||||
ProjectManager(context=context),
|
||||
Engineer(n_borg=5, use_code_review=True, context=context),
|
||||
QaEngineer(context=context, test_round_allowed=2),
|
||||
]
|
||||
)
|
||||
msg = UserMessage(content=content, send_to=send_to)
|
||||
env.publish_message(msg)
|
||||
while not env.is_idle:
|
||||
await env.run()
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -350,5 +350,47 @@ class TestPlan:
|
|||
assert plan.current_task_id == "2"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("content", "key_descriptions"),
|
||||
[
|
||||
(
|
||||
"""
|
||||
Traceback (most recent call last):
|
||||
File "/Users/iorishinier/github/MetaGPT/workspace/game_2048_1/game_2048/main.py", line 38, in <module>
|
||||
Main().main()
|
||||
File "/Users/iorishinier/github/MetaGPT/workspace/game_2048_1/game_2048/main.py", line 28, in main
|
||||
self.user_interface.draw()
|
||||
File "/Users/iorishinier/github/MetaGPT/workspace/game_2048_1/game_2048/user_interface.py", line 16, in draw
|
||||
if grid[i][j] != 0:
|
||||
TypeError: 'Grid' object is not subscriptable
|
||||
""",
|
||||
{
|
||||
"filename": "the string type of the path name of the source code where the bug resides",
|
||||
"line": "the integer type of the line error occurs",
|
||||
"function_name": "the string type of the function name the error occurs in",
|
||||
"code": "the string type of the codes where the error occurs at",
|
||||
"info": "the string type of the error information",
|
||||
},
|
||||
),
|
||||
(
|
||||
"将代码提交到github上的iorisa/repo1的branch1分支,发起pull request ,合并到master分支。",
|
||||
{
|
||||
"repo_name": "the string type of github repo to create pull",
|
||||
"head": "the string type of github branch to be pushed",
|
||||
"base": "the string type of github branch to merge the changes into",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_parse_resources(context, content: str, key_descriptions):
|
||||
msg = Message(content=content)
|
||||
llm = context.llm_with_cost_manager_from_llm_config(context.config.llm)
|
||||
result = await msg.parse_resources(llm=llm, key_descriptions=key_descriptions)
|
||||
assert result
|
||||
assert result.get("resources")
|
||||
for k in key_descriptions.keys():
|
||||
assert k in result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-s"])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from github import Auth, Github
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.tools.libs.git import git_checkout, git_clone
|
||||
|
|
@ -13,10 +17,15 @@ class SWEBenchItem(BaseModel):
|
|||
repo: str
|
||||
|
||||
|
||||
def get_env(key):
|
||||
return os.environ.get(key)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
["url", "commit_id"], [("https://github.com/sqlfluff/sqlfluff.git", "d19de0ecd16d298f9e3bfb91da122734c40c01e5")]
|
||||
)
|
||||
@pytest.mark.skip
|
||||
async def test_git(url: str, commit_id: str):
|
||||
repo_dir = await git_clone(url)
|
||||
assert repo_dir
|
||||
|
|
@ -27,5 +36,67 @@ async def test_git(url: str, commit_id: str):
|
|||
repo.delete_repository()
|
||||
|
||||
|
||||
@pytest.mark.skip
|
||||
def test_login():
|
||||
auth = Auth.Login(get_env("GITHUB_USER"), get_env("GITHUB_PWD"))
|
||||
g = Github(auth=auth)
|
||||
repo = g.get_repo("geekan/MetaGPT")
|
||||
topics = repo.get_topics()
|
||||
assert topics
|
||||
open_issues = repo.get_issues(state="open")
|
||||
issues = [i for i in open_issues]
|
||||
assert issues
|
||||
|
||||
|
||||
@pytest.mark.skip
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_issue():
|
||||
issue = await GitRepository.create_issue(
|
||||
repo_name="iorisa/MetaGPT",
|
||||
title="This is a new issue",
|
||||
body="This is the issue body",
|
||||
access_token=get_env("GITHUB_PERSONAL_ACCESS_TOKEN"),
|
||||
)
|
||||
print(issue)
|
||||
assert issue.number
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skip
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_pr():
|
||||
body = """
|
||||
>>> SUMMARY
|
||||
>>> Change HTTP library used to send requests
|
||||
>>>
|
||||
>>> TESTS
|
||||
>>> - [x] Send 'GET' request
|
||||
>>> - [x] Send 'POST' request with/without body
|
||||
"""
|
||||
pr = await GitRepository.create_pull(
|
||||
repo_name="iorisa/MetaGPT",
|
||||
base="send18",
|
||||
head="fixbug/gbk",
|
||||
title="Test pr",
|
||||
body=body,
|
||||
access_token=get_env("GITHUB_PERSONAL_ACCESS_TOKEN"),
|
||||
)
|
||||
print(pr)
|
||||
assert pr
|
||||
|
||||
|
||||
@pytest.mark.skip
|
||||
def test_auth():
|
||||
access_token = get_env("GITHUB_PERSONAL_ACCESS_TOKEN")
|
||||
auth = Auth.Token(access_token)
|
||||
g = Github(auth=auth)
|
||||
u = g.get_user()
|
||||
v = u.get_repos(visibility="public")
|
||||
a = [i.full_name for i in v]
|
||||
assert a
|
||||
print(a)
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-s"])
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class TestCodeParser:
|
|||
assert "game.py" in result
|
||||
|
||||
def test_parse_code(self, parser, text):
|
||||
result = parser.parse_code("Task list", text, "python")
|
||||
result = parser.parse_code(block="Task list", text=text, lang="python")
|
||||
print(result)
|
||||
assert "game.py" in result
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue