Merge pull request #900 from garylin2099/ci_dev

Unified naming
This commit is contained in:
garylin2099 2024-02-18 17:15:09 +08:00 committed by GitHub
commit 7f82628630
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 193 additions and 131 deletions

View file

@ -26,6 +26,8 @@ # MetaGPT: The Multi-Agent Framework
</p>
## News
🚀 Feb. 08, 2024: [v0.7.0](https://github.com/geekan/MetaGPT/releases/tag/v0.7.0) released, supporting assigning different LLMs to different Roles. We also introduced [Interpreter](https://github.com/geekan/MetaGPT/blob/main/examples/mi/README.md), a powerful agent capable of solving a wide range of real-world problems.
🚀 Jan. 16, 2024: Our paper [MetaGPT: Meta Programming for A Multi-Agent Collaborative Framework
](https://arxiv.org/abs/2308.00352) accepted for oral presentation **(top 1.2%)** at ICLR 2024, **ranking #1** in the LLM-based Agent category.
@ -60,7 +62,27 @@ ### Pip installation
```bash
pip install metagpt
metagpt --init-config # create ~/.metagpt/config2.yaml, modify it to your own config
# https://docs.deepwisdom.ai/main/en/guide/get_started/configuration.html
metagpt --init-config # it will create ~/.metagpt/config2.yaml, just modify it to your needs
```
### Configuration
You can configure `~/.metagpt/config2.yaml` according to the [example](https://github.com/geekan/MetaGPT/blob/main/config/config2.example.yaml) and [doc](https://docs.deepwisdom.ai/main/en/guide/get_started/configuration.html):
```yaml
llm:
api_type: "openai" # or azure / ollama / open_llm etc. Check LLMType for more options
model: "gpt-4-turbo-preview" # or gpt-3.5-turbo-1106 / gpt-4-1106-preview
base_url: "https://api.openai.com/v1" # or forward url / other llm url
api_key: "YOUR_API_KEY"
```
### Usage
After installation, you can use it as CLI
```bash
metagpt "Create a 2048 game" # this will create a repo in ./workspace
```
@ -73,27 +95,7 @@ ### Pip installation
```
detail installation please refer to [cli_install](https://docs.deepwisdom.ai/main/en/guide/get_started/installation.html#install-stable-version)
### Docker installation
> Note: In the Windows, you need to replace "/opt/metagpt" with a directory that Docker has permission to create, such as "D:\Users\x\metagpt"
```bash
# Step 1: Download metagpt official image and prepare config2.yaml
docker pull metagpt/metagpt:latest
mkdir -p /opt/metagpt/{config,workspace}
docker run --rm metagpt/metagpt:latest cat /app/metagpt/config/config2.yaml > /opt/metagpt/config/config2.yaml
vim /opt/metagpt/config/config2.yaml # Change the config
# Step 2: Run metagpt demo with container
docker run --rm \
--privileged \
-v /opt/metagpt/config/config2.yaml:/app/metagpt/config/config2.yaml \
-v /opt/metagpt/workspace:/app/metagpt/workspace \
metagpt/metagpt:latest \
metagpt "Create a 2048 game"
```
detail installation please refer to [docker_install](https://docs.deepwisdom.ai/main/en/guide/get_started/installation.html#install-with-docker)
or [docker_install](https://docs.deepwisdom.ai/main/en/guide/get_started/installation.html#install-with-docker)
### QuickStart & Demo Video
- Try it on [MetaGPT Huggingface Space](https://huggingface.co/spaces/deepwisdom/MetaGPT)

View file

@ -1,10 +1,12 @@
llm:
api_type: "openai" # or azure / ollama etc.
api_type: "openai" # or azure / ollama / open_llm etc. Check LLMType for more options
base_url: "YOUR_BASE_URL"
api_key: "YOUR_API_KEY"
model: "gpt-4-turbo-preview" # or gpt-3.5-turbo-1106 / gpt-4-1106-preview
repair_llm_output: true # when the output is not a valid json, try to repair it
proxy: "YOUR_PROXY" # for LLM API requests
proxy: "YOUR_PROXY"
proxy: "YOUR_PROXY" # for tools like requests, playwright, selenium, etc.
search:
api_type: "google"
@ -41,5 +43,3 @@ iflytek_api_key: "YOUR_API_KEY"
iflytek_api_secret: "YOUR_API_SECRET"
metagpt_tti_url: "YOUR_MODEL_URL"
repair_llm_output: true

View file

@ -1,3 +1,7 @@
# Full Example: https://github.com/geekan/MetaGPT/blob/main/config/config2.example.yaml
# Reflected Code: https://github.com/geekan/MetaGPT/blob/main/metagpt/config2.py
llm:
api_key: "YOUR_API_KEY"
model: "gpt-4-turbo-preview" # or gpt-3.5-turbo-1106 / gpt-4-1106-preview
api_type: "openai" # or azure / ollama / open_llm etc. Check LLMType for more options
model: "gpt-4-turbo-preview" # or gpt-3.5-turbo-1106 / gpt-4-1106-preview
base_url: "https://api.openai.com/v1" # or forward url / other llm url
api_key: "YOUR_API_KEY"

View file

@ -35,14 +35,14 @@ ### Tasks
3. Strategies
1. Support ReAct strategy (experimentation done with game agents)
2. Support CoT strategy (experimentation done with game agents)
3. Support ToT strategy
3. ~~Support ToT strategy~~ (v0.6.0)
4. Support Reflection strategy (experimentation done with game agents)
5. Support planning
5. ~~Support planning~~ (v0.7.0)
4. Actions
1. ~~Implementation: Search~~ (v0.2.1)
2. Implementation: Knowledge search, supporting 10+ data formats
3. Implementation: Data EDA (expected v0.7.0)
4. Implementation: Review & Revise (expected v0.7.0)
3. ~~Implementation: Data EDA~~ (v0.7.0)
4. ~~Implementation: Review & Revise~~ (v0.7.0)
5. ~~Implementation: Add Document~~ (v0.5.0)
6. ~~Implementation: Delete Document~~ (v0.5.0)
7. Implementation: Self-training
@ -50,7 +50,7 @@ ### Tasks
9. Implementation: Generate reliable unit tests based on YAPI
10. Implementation: Self-evaluation
11. Implementation: AI Invocation
12. Implementation: Learning and using third-party standard libraries
12. ~~Implementation: Learning and using third-party standard libraries~~ (v0.7.0)
13. Implementation: Data collection
14. Implementation: AI training
15. ~~Implementation: Run code~~ (v0.2.1)
@ -63,14 +63,14 @@ ### Tasks
7. Roles
1. Perfect the action pool/skill pool for each role
2. E-commerce seller
3. Data analyst (expected v0.7.0)
3. ~~Data analyst~~ (v0.7.0)
4. News observer
5. ~~Institutional researcher~~ (v0.2.1)
8. Evaluation
1. Support an evaluation on a game dataset (experimentation done with game agents)
2. Reproduce papers, implement full skill acquisition for a single game role, achieving SOTA results (experimentation done with game agents)
3. Support an evaluation on a math dataset (expected v0.7.0)
4. Reproduce papers, achieving SOTA results for current mathematical problem solving process
3. Support an evaluation on a math dataset (expected v0.8.0)
4. Reproduce papers, achieving SOTA results for current mathematical problem solving process (expected v0.8.0)
9. LLM
1. Support Claude underlying API
2. ~~Support Azure asynchronous API~~

View file

@ -1 +1 @@
coverage run --source ./metagpt -m pytest --durations=0 --timeout=100 && coverage report -m && coverage html && open htmlcov/index.html
coverage run --source ./metagpt -m pytest -n 8 --durations=0 --timeout=100 && coverage report -m && coverage html && open htmlcov/index.html

View file

@ -1,18 +0,0 @@
# Code Interpreter (CI)
## What is CodeInterpreter
CodeInterpreter is an agent who solves problems through codes. It understands user requirements, makes plans, writes codes for execution, and uses tools if necessary. These capabilities enable it to tackle a wide range of scenarios, please check out the examples below.
## Example List
- Data visualization
- Machine learning modeling
- Image background removal
- Solve math problems
- Receipt OCR
- Tool usage: web page imitation
- Tool usage: web crawling
- Tool usage: text2image
- Tool usage: email summarization and response
- More on the way!
Please see [here](https://docs.deepwisdom.ai/main/en/guide/use_cases/agent/code_interpreter/ci_intro.html) for detailed explanation.

18
examples/mi/README.md Normal file
View file

@ -0,0 +1,18 @@
# MetaGPT Interpreter (MI)
## What is Interpreter
Interpreter is an agent who solves problems through codes. It understands user requirements, makes plans, writes codes for execution, and uses tools if necessary. These capabilities enable it to tackle a wide range of scenarios, please check out the examples below.
## Example List
- Data visualization
- Machine learning modeling
- Image background removal
- Solve math problems
- Receipt OCR
- Tool usage: web page imitation
- Tool usage: web crawling
- Tool usage: text2image
- Tool usage: email summarization and response
- More on the way!
Please see [here](https://docs.deepwisdom.ai/main/en/guide/use_cases/agent/interpreter/mi_intro.html) for detailed explanation.

View file

@ -5,15 +5,15 @@
@File : crawl_webpage.py
"""
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main():
prompt = """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*"""
ci = CodeInterpreter(goal=prompt, use_tools=True)
mi = Interpreter(use_tools=True)
await ci.run(prompt)
await mi.run(prompt)
if __name__ == "__main__":

View file

@ -1,11 +1,11 @@
import asyncio
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main(requirement: str = ""):
code_interpreter = CodeInterpreter(use_tools=False)
await code_interpreter.run(requirement)
mi = Interpreter(use_tools=False)
await mi.run(requirement)
if __name__ == "__main__":

View file

@ -6,7 +6,7 @@
"""
import os
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main():
@ -22,9 +22,9 @@ async def main():
Firstly, Please help me fetch the latest 5 senders and full letter contents.
Then, summarize each of the 5 emails into one sentence (you can do this by yourself, no need to import other models to do this) and output them in a markdown format."""
ci = CodeInterpreter(use_tools=True)
mi = Interpreter(use_tools=True)
await ci.run(prompt)
await mi.run(prompt)
if __name__ == "__main__":

View file

@ -5,7 +5,7 @@
@Author : mannaandpoem
@File : imitate_webpage.py
"""
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main():
@ -15,9 +15,9 @@ Firstly, utilize Selenium and WebDriver for rendering.
Secondly, convert image to a webpage including HTML, CSS and JS in one go.
Finally, save webpage in a text file.
Note: All required dependencies and environments have been fully installed and configured."""
ci = CodeInterpreter(use_tools=True)
mi = Interpreter(use_tools=True)
await ci.run(prompt)
await mi.run(prompt)
if __name__ == "__main__":

View file

@ -1,11 +1,11 @@
import asyncio
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main(requirement: str):
role = CodeInterpreter(auto_run=True, use_tools=False)
await role.run(requirement)
mi = Interpreter(auto_run=True, use_tools=False)
await mi.run(requirement)
if __name__ == "__main__":

View file

@ -1,6 +1,6 @@
import asyncio
from metagpt.roles.ci.ml_engineer import MLEngineer
from metagpt.roles.mi.ml_engineer import MLEngineer
async def main(requirement: str):

View file

@ -1,16 +1,16 @@
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main():
# Notice: pip install metagpt[ocr] before using this example
image_path = "image.jpg"
language = "English"
requirement = f"""This is a {language} invoice image.
requirement = f"""This is a {language} receipt image.
Your goal is to perform OCR on images using PaddleOCR, then extract the total amount from ocr text results, and finally save as table. Image path: {image_path}.
NOTE: The environments for Paddle and PaddleOCR are all ready and has been fully installed."""
ci = CodeInterpreter()
mi = Interpreter()
await ci.run(requirement)
await mi.run(requirement)
if __name__ == "__main__":

View file

@ -1,11 +1,11 @@
import asyncio
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main(requirement: str = ""):
code_interpreter = CodeInterpreter(use_tools=False)
await code_interpreter.run(requirement)
mi = Interpreter(use_tools=False)
await mi.run(requirement)
if __name__ == "__main__":

View file

@ -4,12 +4,12 @@
# @Desc :
import asyncio
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main(requirement: str = ""):
code_interpreter = CodeInterpreter(use_tools=True, goal=requirement)
await code_interpreter.run(requirement)
mi = Interpreter(use_tools=True, goal=requirement)
await mi.run(requirement)
if __name__ == "__main__":

View file

@ -1,11 +1,11 @@
import asyncio
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
async def main(requirement: str = ""):
code_interpreter = CodeInterpreter(use_tools=False)
await code_interpreter.run(requirement)
mi = Interpreter(use_tools=False)
await mi.run(requirement)
if __name__ == "__main__":

View file

@ -22,9 +22,9 @@ from metagpt.actions.write_code_review import WriteCodeReview
from metagpt.actions.write_prd import WritePRD
from metagpt.actions.write_prd_review import WritePRDReview
from metagpt.actions.write_test import WriteTest
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode
from metagpt.actions.ci.write_analysis_code import WriteCodeWithoutTools, WriteCodeWithTools
from metagpt.actions.ci.write_plan import WritePlan
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode
from metagpt.actions.mi.write_analysis_code import WriteCodeWithoutTools, WriteCodeWithTools
from metagpt.actions.mi.write_plan import WritePlan
class ActionType(Enum):

View file

View file

@ -1,6 +1,6 @@
from __future__ import annotations
from metagpt.actions.ci.write_analysis_code import BaseWriteAnalysisCode
from metagpt.actions.mi.write_analysis_code import BaseWriteAnalysisCode
from metagpt.logs import logger
from metagpt.schema import Message
from metagpt.utils.common import create_func_call_config

View file

@ -3,14 +3,14 @@ from __future__ import annotations
from typing import Tuple
from metagpt.actions import Action
from metagpt.actions.ci.write_analysis_code import WriteCodeWithTools
from metagpt.prompts.ci.ml_action import (
from metagpt.actions.mi.write_analysis_code import WriteCodeWithTools
from metagpt.prompts.mi.ml_action import (
ML_GENERATE_CODE_PROMPT,
ML_TOOL_USAGE_PROMPT,
PRINT_DATA_COLUMNS,
UPDATE_DATA_COLUMNS,
)
from metagpt.prompts.ci.write_analysis_code import CODE_GENERATOR_WITH_TOOLS
from metagpt.prompts.mi.write_analysis_code import CODE_GENERATOR_WITH_TOOLS
from metagpt.schema import Message, Plan
from metagpt.utils.common import create_func_call_config, remove_comments

View file

@ -10,7 +10,7 @@ from typing import Tuple
from metagpt.actions import Action
from metagpt.logs import logger
from metagpt.prompts.ci.write_analysis_code import (
from metagpt.prompts.mi.write_analysis_code import (
CODE_GENERATOR_WITH_TOOLS,
SELECT_FUNCTION_TOOLS,
TOOL_RECOMMENDATION_PROMPT,

View file

@ -12,7 +12,7 @@ from typing import Tuple
from metagpt.actions import Action
from metagpt.logs import logger
from metagpt.prompts.ci.write_analysis_code import (
from metagpt.prompts.mi.write_analysis_code import (
ASSIGN_TASK_TYPE_CONFIG,
ASSIGN_TASK_TYPE_PROMPT,
)

View file

View file

View file

@ -2,9 +2,9 @@ from __future__ import annotations
from pydantic import Field
from metagpt.actions.ci.ask_review import ReviewConst
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode
from metagpt.actions.ci.write_analysis_code import (
from metagpt.actions.mi.ask_review import ReviewConst
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode
from metagpt.actions.mi.write_analysis_code import (
WriteCodeWithoutTools,
WriteCodeWithTools,
)
@ -13,9 +13,9 @@ from metagpt.roles import Role
from metagpt.schema import Message, Task, TaskResult
class CodeInterpreter(Role):
name: str = "Charlie"
profile: str = "CodeInterpreter"
class Interpreter(Role):
name: str = "Ivy"
profile: str = "Interpreter"
auto_run: bool = True
use_tools: bool = False
execute_code: ExecuteNbCode = Field(default_factory=ExecuteNbCode, exclude=True)

View file

@ -1,13 +1,13 @@
from metagpt.actions.ci.debug_code import DebugCode
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode
from metagpt.actions.ci.ml_action import UpdateDataColumns, WriteCodeWithToolsML
from metagpt.actions.mi.debug_code import DebugCode
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode
from metagpt.actions.mi.ml_action import UpdateDataColumns, WriteCodeWithToolsML
from metagpt.logs import logger
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
from metagpt.tools.tool_type import ToolType
from metagpt.utils.common import any_to_str
class MLEngineer(CodeInterpreter):
class MLEngineer(Interpreter):
name: str = "Mark"
profile: str = "MLEngineer"
debug_context: list = []

View file

@ -4,8 +4,8 @@ import json
from pydantic import BaseModel, Field
from metagpt.actions.ci.ask_review import AskReview, ReviewConst
from metagpt.actions.ci.write_plan import (
from metagpt.actions.mi.ask_review import AskReview, ReviewConst
from metagpt.actions.mi.write_plan import (
WritePlan,
precheck_update_plan_from_rsp,
update_plan_from_rsp,

View file

@ -49,8 +49,8 @@ class TOTSolver(BaseSolver):
raise NotImplementedError
class CodeInterpreterSolver(BaseSolver):
"""CodeInterpreterSolver: Write&Run code in the graph"""
class InterpreterSolver(BaseSolver):
"""InterpreterSolver: Write&Run code in the graph"""
async def solve(self):
raise NotImplementedError

View file

@ -14,6 +14,7 @@ import re
import uuid
from typing import Callable
import aiohttp.web
import pytest
from metagpt.const import DEFAULT_WORKSPACE_ROOT, TEST_DATA_PATH
@ -171,9 +172,8 @@ def new_filename(mocker):
yield mocker
@pytest.fixture(scope="session")
def search_rsp_cache():
rsp_cache_file_path = TEST_DATA_PATH / "search_rsp_cache.json" # read repo-provided
def _rsp_cache(name):
rsp_cache_file_path = TEST_DATA_PATH / f"{name}.json" # read repo-provided
if os.path.exists(rsp_cache_file_path):
with open(rsp_cache_file_path, "r") as f1:
rsp_cache_json = json.load(f1)
@ -184,6 +184,16 @@ def search_rsp_cache():
json.dump(rsp_cache_json, f2, indent=4, ensure_ascii=False)
@pytest.fixture(scope="session")
def search_rsp_cache():
yield from _rsp_cache("search_rsp_cache")
@pytest.fixture(scope="session")
def mermaid_rsp_cache():
yield from _rsp_cache("mermaid_rsp_cache")
@pytest.fixture
def aiohttp_mocker(mocker):
MockResponse = type("MockResponse", (MockAioResponse,), {})
@ -231,3 +241,32 @@ def search_engine_mocker(aiohttp_mocker, curl_cffi_mocker, httplib2_mocker, sear
aiohttp_mocker.rsp_cache = httplib2_mocker.rsp_cache = curl_cffi_mocker.rsp_cache = search_rsp_cache
aiohttp_mocker.check_funcs = httplib2_mocker.check_funcs = curl_cffi_mocker.check_funcs = check_funcs
yield check_funcs
@pytest.fixture
def http_server():
async def handler(request):
return aiohttp.web.Response(
text="""<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8">
<title>MetaGPT</title></head><body><h1>MetaGPT</h1></body></html>""",
content_type="text/html",
)
async def start():
server = aiohttp.web.Server(handler)
runner = aiohttp.web.ServerRunner(server)
await runner.setup()
site = aiohttp.web.TCPSite(runner, "localhost", 0)
await site.start()
host, port = site._server.sockets[0].getsockname()
return site, f"http://{host}:{port}"
return start
@pytest.fixture
def mermaid_mocker(aiohttp_mocker, mermaid_rsp_cache):
check_funcs: dict[tuple[str, str], Callable[[dict], str]] = {}
aiohttp_mocker.rsp_cache = mermaid_rsp_cache
aiohttp_mocker.check_funcs = check_funcs
yield check_funcs

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
import pytest
from metagpt.actions.ci.ask_review import AskReview
from metagpt.actions.mi.ask_review import AskReview
@pytest.mark.asyncio

View file

@ -5,7 +5,7 @@
import pytest
from metagpt.actions.ci.debug_code import DebugCode
from metagpt.actions.mi.debug_code import DebugCode
from metagpt.schema import Message
ErrorStr = """Tested passed:

View file

@ -1,6 +1,6 @@
import pytest
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode, truncate
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode, truncate
@pytest.mark.asyncio

View file

@ -1,6 +1,6 @@
import pytest
from metagpt.actions.ci.ml_action import WriteCodeWithToolsML
from metagpt.actions.mi.ml_action import WriteCodeWithToolsML
from metagpt.schema import Plan, Task

View file

@ -2,8 +2,8 @@ import asyncio
import pytest
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode
from metagpt.actions.ci.write_analysis_code import (
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode
from metagpt.actions.mi.write_analysis_code import (
WriteCodeWithoutTools,
WriteCodeWithTools,
)

View file

@ -1,6 +1,6 @@
import pytest
from metagpt.actions.ci.write_plan import (
from metagpt.actions.mi.write_plan import (
Plan,
Task,
WritePlan,

View file

@ -1,23 +1,23 @@
import pytest
from metagpt.logs import logger
from metagpt.roles.ci.code_interpreter import CodeInterpreter
from metagpt.roles.mi.interpreter import Interpreter
@pytest.mark.asyncio
@pytest.mark.parametrize("auto_run", [(True), (False)])
async def test_code_interpreter(mocker, auto_run):
mocker.patch("metagpt.actions.ci.execute_nb_code.ExecuteNbCode.run", return_value=("a successful run", True))
async def test_interpreter(mocker, auto_run):
mocker.patch("metagpt.actions.mi.execute_nb_code.ExecuteNbCode.run", return_value=("a successful run", True))
mocker.patch("builtins.input", return_value="confirm")
requirement = "Run data analysis on sklearn Iris dataset, include a plot"
tools = []
ci = CodeInterpreter(auto_run=auto_run, use_tools=True, tools=tools)
rsp = await ci.run(requirement)
mi = Interpreter(auto_run=auto_run, use_tools=True, tools=tools)
rsp = await mi.run(requirement)
logger.info(rsp)
assert len(rsp.content) > 0
finished_tasks = ci.planner.plan.get_finished_tasks()
finished_tasks = mi.planner.plan.get_finished_tasks()
assert len(finished_tasks) > 0
assert len(finished_tasks[0].code) > 0 # check one task to see if code is recorded

View file

@ -1,16 +1,16 @@
import pytest
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode
from metagpt.logs import logger
from metagpt.roles.ci.ml_engineer import MLEngineer
from metagpt.roles.mi.ml_engineer import MLEngineer
from metagpt.schema import Message, Plan, Task
from metagpt.tools.tool_type import ToolType
from tests.metagpt.actions.ci.test_debug_code import CODE, DebugContext, ErrorStr
from tests.metagpt.actions.mi.test_debug_code import CODE, DebugContext, ErrorStr
def test_mle_init():
ci = MLEngineer(goal="test", auto_run=True, use_tools=True, tools=["tool1", "tool2"])
assert ci.tools == []
mle = MLEngineer(goal="test", auto_run=True, use_tools=True, tools=["tool1", "tool2"])
assert mle.tools == []
MockPlan = Plan(

View file

@ -14,7 +14,7 @@ from metagpt.utils.mermaid import MMC1, mermaid_to_file
@pytest.mark.asyncio
@pytest.mark.parametrize("engine", ["nodejs", "ink"]) # TODO: playwright and pyppeteer
async def test_mermaid(engine, context):
async def test_mermaid(engine, context, mermaid_mocker):
# nodejs prerequisites: npm install -g @mermaid-js/mermaid-cli
# ink prerequisites: connected to internet
# playwright prerequisites: playwright install --with-deps chromium

View file

@ -6,7 +6,7 @@
import nbformat
import pytest
from metagpt.actions.ci.execute_nb_code import ExecuteNbCode
from metagpt.actions.mi.execute_nb_code import ExecuteNbCode
from metagpt.utils.common import read_json_file
from metagpt.utils.save_code import DATA_PATH, save_code_file

View file

@ -10,6 +10,7 @@ class MockAioResponse:
check_funcs: dict[tuple[str, str], Callable[[dict], str]] = {}
rsp_cache: dict[str, str] = {}
name = "aiohttp"
status = 200
def __init__(self, session, method, url, **kwargs) -> None:
fn = self.check_funcs.get((method, url))
@ -22,6 +23,7 @@ class MockAioResponse:
async def __aenter__(self):
if self.response:
await self.response.__aenter__()
self.status = self.response.status
elif self.mng:
self.response = await self.mng.__aenter__()
return self
@ -41,6 +43,17 @@ class MockAioResponse:
self.rsp_cache[self.key] = data
return data
@property
def content(self):
return self
async def read(self):
if self.key in self.rsp_cache:
return eval(self.rsp_cache[self.key])
data = await self.response.content.read()
self.rsp_cache[self.key] = str(data)
return data
def raise_for_status(self):
if self.response:
self.response.raise_for_status()