mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-14 15:25:17 +02:00
commit
7f82628630
46 changed files with 193 additions and 131 deletions
46
README.md
46
README.md
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
@ -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~~
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
18
examples/mi/README.md
Normal 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.
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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):
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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__":
|
||||
|
|
@ -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):
|
||||
|
|
|
|||
0
metagpt/actions/mi/__init__.py
Normal file
0
metagpt/actions/mi/__init__.py
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
@ -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,
|
||||
)
|
||||
0
metagpt/prompts/mi/__init__.py
Normal file
0
metagpt/prompts/mi/__init__.py
Normal file
0
metagpt/roles/mi/__init__.py
Normal file
0
metagpt/roles/mi/__init__.py
Normal 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)
|
||||
|
|
@ -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 = []
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
4
tests/data/mermaid_rsp_cache.json
Normal file
4
tests/data/mermaid_rsp_cache.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from metagpt.actions.ci.write_plan import (
|
||||
from metagpt.actions.mi.write_plan import (
|
||||
Plan,
|
||||
Task,
|
||||
WritePlan,
|
||||
|
|
@ -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
|
||||
|
|
@ -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(
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue