feat: merge geekan:cli-etc

This commit is contained in:
莘权 马 2023-11-28 18:16:50 +08:00
commit 78548c2ddc
84 changed files with 2982 additions and 1000 deletions

View file

@ -90,7 +90,7 @@ Python's in-built data structures like lists and dictionaries will be used exten
For testing, we can use the PyTest framework. This is a mature full-featured Python testing tool that helps you write better programs.
## Python package name:
## project_name:
```python
"adventure_game"
```
@ -100,7 +100,7 @@ For testing, we can use the PyTest framework. This is a mature full-featured Pyt
file_list = ["main.py", "room.py", "player.py", "game.py", "object.py", "puzzle.py", "test_game.py"]
```
## Data structures and interface definitions:
## Data structures and interfaces:
```mermaid
classDiagram
class Room{
@ -209,7 +209,7 @@ Shared knowledge for this project includes understanding the basic principles of
"""
```
## Anything UNCLEAR: Provide as Plain text. Make clear here. For example, don't forget a main entry. don't forget to init 3rd party libs.
## Anything UNCLEAR: Provide as Plain text. Try to clarify it. For example, don't forget a main entry. don't forget to init 3rd party libs.
```python
"""
The original requirements did not specify whether the game should have a save/load feature, multiplayer support, or any specific graphical user interface. More information on these aspects could help in further refining the product design and requirements.

View file

@ -8,7 +8,7 @@
"""
import pytest
from metagpt.actions import BossRequirement
from metagpt.actions import UserRequirement
from metagpt.logs import logger
from metagpt.roles.product_manager import ProductManager
from metagpt.schema import Message
@ -18,7 +18,7 @@ from metagpt.schema import Message
async def test_write_prd():
product_manager = ProductManager()
requirements = "开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结"
prd = await product_manager.run(Message(content=requirements, cause_by=BossRequirement))
prd = await product_manager.run(Message(content=requirements, cause_by=UserRequirement))
logger.info(requirements)
logger.info(prd)

View file

@ -7,22 +7,22 @@
"""
import pytest
from metagpt.const import DATA_PATH
from metagpt.document_store.document import Document
from metagpt.const import METAGPT_ROOT
from metagpt.document import IndexableDocument
CASES = [
("st/faq.xlsx", "Question", "Answer", 1),
("cases/faq.csv", "Question", "Answer", 1),
("requirements.txt", None, None, 0),
# ("cases/faq.csv", "Question", "Answer", 1),
# ("cases/faq.json", "Question", "Answer", 1),
("docx/faq.docx", None, None, 1),
("cases/faq.pdf", None, None, 0), # 这是因为pdf默认没有分割段落
("cases/faq.txt", None, None, 0), # 这是因为txt按照256分割段落
# ("docx/faq.docx", None, None, 1),
# ("cases/faq.pdf", None, None, 0), # 这是因为pdf默认没有分割段落
# ("cases/faq.txt", None, None, 0), # 这是因为txt按照256分割段落
]
@pytest.mark.parametrize("relative_path, content_col, meta_col, threshold", CASES)
def test_document(relative_path, content_col, meta_col, threshold):
doc = Document(DATA_PATH / relative_path, content_col, meta_col)
doc = IndexableDocument.from_path(METAGPT_ROOT / relative_path, content_col, meta_col)
rsp = doc.get_docs_and_metadatas()
assert len(rsp[0]) > threshold
assert len(rsp[1]) > threshold

View file

@ -4,7 +4,7 @@
@Desc : unittest of `metagpt/memory/longterm_memory.py`
"""
from metagpt.actions import BossRequirement
from metagpt.actions import UserRequirement
from metagpt.config import CONFIG
from metagpt.memory import LongTermMemory
from metagpt.roles.role import RoleContext
@ -17,24 +17,24 @@ def test_ltm_search():
assert len(openai_api_key) > 20
role_id = "UTUserLtm(Product Manager)"
rc = RoleContext(watch=[BossRequirement])
rc = RoleContext(watch=[UserRequirement])
ltm = LongTermMemory()
ltm.recover_memory(role_id, rc)
idea = "Write a cli snake game"
message = Message(role="BOSS", content=idea, cause_by=BossRequirement)
message = Message(role="User", content=idea, cause_by=UserRequirement)
news = ltm.find_news([message])
assert len(news) == 1
ltm.add(message)
sim_idea = "Write a game of cli snake"
sim_message = Message(role="BOSS", content=sim_idea, cause_by=BossRequirement)
sim_message = Message(role="User", content=sim_idea, cause_by=UserRequirement)
news = ltm.find_news([sim_message])
assert len(news) == 0
ltm.add(sim_message)
new_idea = "Write a 2048 web game"
new_message = Message(role="BOSS", content=new_idea, cause_by=BossRequirement)
new_message = Message(role="User", content=new_idea, cause_by=UserRequirement)
news = ltm.find_news([new_message])
assert len(news) == 1
ltm.add(new_message)
@ -50,7 +50,7 @@ def test_ltm_search():
assert len(news) == 0
new_idea = "Write a Battle City"
new_message = Message(role="BOSS", content=new_idea, cause_by=BossRequirement)
new_message = Message(role="User", content=new_idea, cause_by=UserRequirement)
news = ltm_new.find_news([new_message])
assert len(news) == 1

View file

@ -7,7 +7,7 @@
from typing import List
from metagpt.actions import BossRequirement, WritePRD
from metagpt.actions import UserRequirement, WritePRD
from metagpt.actions.action_output import ActionOutput
from metagpt.memory.memory_storage import MemoryStorage
from metagpt.schema import Message
@ -16,7 +16,7 @@ from metagpt.schema import Message
def test_idea_message():
idea = "Write a cli snake game"
role_id = "UTUser1(Product Manager)"
message = Message(role="BOSS", content=idea, cause_by=BossRequirement)
message = Message(role="User", content=idea, cause_by=UserRequirement)
memory_storage: MemoryStorage = MemoryStorage()
messages = memory_storage.recover_memory(role_id)
@ -26,12 +26,12 @@ def test_idea_message():
assert memory_storage.is_initialized is True
sim_idea = "Write a game of cli snake"
sim_message = Message(role="BOSS", content=sim_idea, cause_by=BossRequirement)
sim_message = Message(role="User", content=sim_idea, cause_by=UserRequirement)
new_messages = memory_storage.search(sim_message)
assert len(new_messages) == 0 # similar, return []
new_idea = "Write a 2048 web game"
new_message = Message(role="BOSS", content=new_idea, cause_by=BossRequirement)
new_message = Message(role="User", content=new_idea, cause_by=UserRequirement)
new_messages = memory_storage.search(new_message)
assert new_messages[0].content == message.content
@ -45,7 +45,7 @@ def test_actionout_message():
ic_obj = ActionOutput.create_model_class("prd", out_mapping)
role_id = "UTUser2(Architect)"
content = "The boss has requested the creation of a command-line interface (CLI) snake game"
content = "The user has requested the creation of a command-line interface (CLI) snake game"
message = Message(
content=content, instruct_content=ic_obj(**out_data), role="user", cause_by=WritePRD
) # WritePRD as test action

View file

@ -11,7 +11,7 @@ import pytest
from semantic_kernel.core_skills import FileIOSkill, MathSkill, TextSkill, TimeSkill
from semantic_kernel.planning.action_planner.action_planner import ActionPlanner
from metagpt.actions import BossRequirement
from metagpt.actions import UserRequirement
from metagpt.roles.sk_agent import SkAgent
from metagpt.schema import Message
@ -25,7 +25,8 @@ async def test_action_planner():
role.import_skill(TimeSkill(), "time")
role.import_skill(TextSkill(), "text")
task = "What is the sum of 110 and 990?"
role.put_message(Message(content=task, cause_by=BossRequirement))
role.put_message(Message(content=task, cause_by=UserRequirement))
await role._observe()
await role._think() # it will choose mathskill.Add
assert "1100" == (await role._act()).content

View file

@ -10,7 +10,7 @@
import pytest
from semantic_kernel.core_skills import TextSkill
from metagpt.actions import BossRequirement
from metagpt.actions import UserRequirement
from metagpt.const import SKILL_DIRECTORY
from metagpt.roles.sk_agent import SkAgent
from metagpt.schema import Message
@ -28,7 +28,7 @@ async def test_basic_planner():
role.import_semantic_skill_from_directory(SKILL_DIRECTORY, "WriterSkill")
role.import_skill(TextSkill(), "TextSkill")
# using BasicPlanner
role.put_message(Message(content=task, cause_by=BossRequirement))
role.put_message(Message(content=task, cause_by=UserRequirement))
await role._observe()
await role._think()
# assuming sk_agent will think he needs WriterSkill.Brainstorm and WriterSkill.Translate

View file

@ -0,0 +1,80 @@
import pytest
from metagpt.provider.openai_api import OpenAIGPTAPI
from metagpt.schema import UserMessage
@pytest.mark.asyncio
async def test_aask_code():
llm = OpenAIGPTAPI()
msg = [{"role": "user", "content": "Write a python hello world code."}]
rsp = await llm.aask_code(msg) # -> {'language': 'python', 'code': "print('Hello, World!')"}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
@pytest.mark.asyncio
async def test_aask_code_str():
llm = OpenAIGPTAPI()
msg = "Write a python hello world code."
rsp = await llm.aask_code(msg) # -> {'language': 'python', 'code': "print('Hello, World!')"}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
@pytest.mark.asyncio
async def test_aask_code_Message():
llm = OpenAIGPTAPI()
msg = UserMessage("Write a python hello world code.")
rsp = await llm.aask_code(msg) # -> {'language': 'python', 'code': "print('Hello, World!')"}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
def test_ask_code():
llm = OpenAIGPTAPI()
msg = [{"role": "user", "content": "Write a python hello world code."}]
rsp = llm.ask_code(msg) # -> {'language': 'python', 'code': "print('Hello, World!')"}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
def test_ask_code_str():
llm = OpenAIGPTAPI()
msg = "Write a python hello world code."
rsp = llm.ask_code(msg) # -> {'language': 'python', 'code': "print('Hello, World!')"}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
def test_ask_code_Message():
llm = OpenAIGPTAPI()
msg = UserMessage("Write a python hello world code.")
rsp = llm.ask_code(msg) # -> {'language': 'python', 'code': "print('Hello, World!')"}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
def test_ask_code_list_Message():
llm = OpenAIGPTAPI()
msg = [UserMessage("a=[1,2,5,10,-10]"), UserMessage("写出求a中最大值的代码python")]
rsp = llm.ask_code(msg) # -> {'language': 'python', 'code': 'max_value = max(a)\nmax_value'}
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0
def test_ask_code_list_str():
llm = OpenAIGPTAPI()
msg = ["a=[1,2,5,10,-10]", "写出求a中最大值的代码python"]
rsp = llm.ask_code(msg) # -> {'language': 'python', 'code': 'max_value = max(a)\nmax_value'}
print(rsp)
assert "language" in rsp
assert "code" in rsp
assert len(rsp["code"]) > 0

View file

@ -0,0 +1,37 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Desc : the unittest of ZhiPuAIGPTAPI
import pytest
from metagpt.provider.zhipuai_api import ZhiPuAIGPTAPI
default_resp = {"code": 200, "data": {"choices": [{"role": "assistant", "content": "I'm chatglm-turbo"}]}}
messages = [{"role": "user", "content": "who are you"}]
def mock_llm_ask(self, messages: list[dict]) -> dict:
return default_resp
def test_zhipuai_completion(mocker):
mocker.patch("metagpt.provider.zhipuai_api.ZhiPuAIGPTAPI.completion", mock_llm_ask)
resp = ZhiPuAIGPTAPI().completion(messages)
assert resp["code"] == 200
assert "chatglm-turbo" in resp["data"]["choices"][0]["content"]
async def mock_llm_aask(self, messgaes: list[dict], stream: bool = False) -> dict:
return default_resp
@pytest.mark.asyncio
async def test_zhipuai_acompletion(mocker):
mocker.patch("metagpt.provider.zhipuai_api.ZhiPuAIGPTAPI.acompletion_text", mock_llm_aask)
resp = await ZhiPuAIGPTAPI().acompletion_text(messages, stream=False)
assert resp["code"] == 200
assert "chatglm-turbo" in resp["data"]["choices"][0]["content"]

View file

@ -5,10 +5,10 @@
@Author : alexanderwu
@File : mock.py
"""
from metagpt.actions import BossRequirement, WriteDesign, WritePRD, WriteTasks
from metagpt.actions import UserRequirement, WriteDesign, WritePRD, WriteTasks
from metagpt.schema import Message
BOSS_REQUIREMENT = """开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结"""
USER_REQUIREMENT = """开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结"""
DETAIL_REQUIREMENT = """需求开发一个基于LLM大语言模型与私有知识库的搜索引擎希望有几点能力
1. 用户可以在私有知识库进行搜索再根据大语言模型进行总结输出的结果包括了总结
@ -71,7 +71,7 @@ PRD = '''## 原始需求
```
'''
SYSTEM_DESIGN = """## Python package name
SYSTEM_DESIGN = """## project_name
```python
"smart_search_engine"
```
@ -94,7 +94,7 @@ SYSTEM_DESIGN = """## Python package name
]
```
## Data structures and interface definitions
## Data structures and interfaces
```mermaid
classDiagram
class Main {
@ -252,7 +252,7 @@ a = 'a'
class MockMessages:
req = Message(role="Boss", content=BOSS_REQUIREMENT, cause_by=BossRequirement)
req = Message(role="User", content=USER_REQUIREMENT, cause_by=UserRequirement)
prd = Message(role="Product Manager", content=PRD, cause_by=WritePRD)
system_design = Message(role="Architect", content=SYSTEM_DESIGN, cause_by=WriteDesign)
tasks = Message(role="Project Manager", content=TASKS, cause_by=WriteTasks)

View file

@ -3,7 +3,7 @@
# @Author : stellahong (stellahong@fuzhi.ai)
#
from metagpt.roles import ProductManager
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from tests.metagpt.roles.ui_role import UI
@ -14,8 +14,8 @@ def test_add_ui():
async def test_ui_role(idea: str, investment: float = 3.0, n_round: int = 5):
"""Run a startup. Be a boss."""
company = SoftwareCompany()
company = Team()
company.hire([ProductManager(), UI()])
company.invest(investment)
company.start_project(idea)
company.run_project(idea)
await company.run(n_round=n_round)

View file

@ -8,7 +8,9 @@ from functools import wraps
from importlib import import_module
from metagpt.actions import Action, ActionOutput, WritePRD
from metagpt.const import WORKSPACE_ROOT
# from metagpt.const import WORKSPACE_ROOT
from metagpt.config import CONFIG
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
@ -29,7 +31,7 @@ Attention: Use '##' to split sections, not '#', and '## <SECTION_NAME>' SHOULD W
## Selected Elements:Provide as Plain text, up to 5 specified elements, clear and simple
## HTML Layout:Provide as Plain text, use standard HTML code
## CSS Styles (styles.css):Provide as Plain text,use standard css code
## Anything UNCLEAR:Provide as Plain text. Make clear here.
## Anything UNCLEAR:Provide as Plain text. Try to clarify it.
"""
@ -214,7 +216,7 @@ class UIDesign(Action):
logger.info("Finish icon design using StableDiffusion API")
async def _save(self, css_content, html_content):
save_dir = WORKSPACE_ROOT / "resources" / "codes"
save_dir = CONFIG.workspace_path / "resources" / "codes"
if not os.path.exists(save_dir):
os.makedirs(save_dir, exist_ok=True)
# Save CSS and HTML content to files

View file

@ -8,7 +8,7 @@
import pytest
from metagpt.actions import BossRequirement
from metagpt.actions import UserRequirement
from metagpt.environment import Environment
from metagpt.logs import logger
from metagpt.manager import Manager
@ -49,7 +49,7 @@ async def test_publish_and_process_message(env: Environment):
env.add_roles([product_manager, architect])
env.set_manager(Manager())
env.publish_message(Message(role="BOSS", content="需要一个基于LLM做总结的搜索引擎", cause_by=BossRequirement))
env.publish_message(Message(role="User", content="需要一个基于LLM做总结的搜索引擎", cause_by=UserRequirement))
await env.run(k=2)
logger.info(f"{env.history=}")

View file

@ -1,19 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/5/15 11:40
@Author : alexanderwu
@File : test_software_company.py
"""
import pytest
from metagpt.logs import logger
from metagpt.software_company import SoftwareCompany
@pytest.mark.asyncio
async def test_software_company():
company = SoftwareCompany()
company.start_project("做一个基础搜索引擎,可以支持知识库")
history = await company.run(n_round=5)
logger.info(history)

View file

@ -0,0 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/5/15 11:40
@Author : alexanderwu
@File : test_startup.py
"""
import pytest
from typer.testing import CliRunner
from metagpt.logs import logger
from metagpt.team import Team
runner = CliRunner()
@pytest.mark.asyncio
async def test_team():
company = Team()
company.run_project("做一个基础搜索引擎,可以支持知识库")
history = await company.run(n_round=5)
logger.info(history)
# def test_startup():
# args = ["Make a 2048 game"]
# result = runner.invoke(app, args)

View file

@ -4,7 +4,8 @@
#
import os
from metagpt.tools.sd_engine import WORKSPACE_ROOT, SDEngine
from metagpt.config import CONFIG
from metagpt.tools.sd_engine import SDEngine
def test_sd_engine_init():
@ -21,5 +22,5 @@ def test_sd_engine_generate_prompt():
async def test_sd_engine_run_t2i():
sd_engine = SDEngine()
await sd_engine.run_t2i(prompts=["test"])
img_path = WORKSPACE_ROOT / "resources" / "SD_Output" / "output_0.png"
assert os.path.exists(img_path) == True
img_path = CONFIG.workspace_path / "resources" / "SD_Output" / "output_0.png"
assert os.path.exists(img_path)

View file

@ -14,7 +14,7 @@ import pytest
from pydantic import BaseModel
from metagpt.actions import RunCode
from metagpt.const import get_project_root
from metagpt.const import get_metagpt_root
from metagpt.roles.tutorial_assistant import TutorialAssistant
from metagpt.schema import Message
from metagpt.utils.common import any_to_str, any_to_str_set
@ -27,13 +27,13 @@ class TestGetProjectRoot:
os.chdir(abs_root)
def test_get_project_root(self):
project_root = get_project_root()
assert project_root.name == "MetaGPT"
project_root = get_metagpt_root()
assert project_root.name == "metagpt"
def test_get_root_exception(self):
with pytest.raises(Exception) as exc_info:
self.change_etc_dir()
get_project_root()
get_metagpt_root()
assert str(exc_info.value) == "Project root not found."
def test_any_to_str(self):

View file

@ -220,7 +220,7 @@ We need clarification on how the high score should be stored. Should it persist
}
t_text1 = """## Original Requirements:
The boss wants to create a web-based version of the game "Fly Bird".
The user wants to create a web-based version of the game "Fly Bird".
## Product Goals:

View file

@ -6,12 +6,12 @@
@File : test_read_docx.py
"""
from metagpt.const import PROJECT_ROOT
from metagpt.const import METAGPT_ROOT
from metagpt.utils.read_document import read_docx
class TestReadDocx:
def test_read_docx(self):
docx_sample = PROJECT_ROOT / "tests/data/docx_for_test.docx"
docx_sample = METAGPT_ROOT / "tests/data/docx_for_test.docx"
docx = read_docx(docx_sample)
assert len(docx) == 6