mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-27 17:56:23 +02:00
1. 动作优化
1. SummarizeCode动作:用于基于代码进行总结,思考bug、逻辑、todo
2. CodeReview动作优化:目前强制要求回答问题,有更高的成功率了
2. 数据结构
1. Document的标准化:Env->Repo->Document,其中Document/Asset/Code都只用Document
1. 原用于检索的Document改为IndexableDocument
2. Repo结构引入:用于Document装载与元数据装载
3. RepoParser引入:写了一个简单的AST parser(后续可能要换tree-sitter),给出了整库symbol
3. 配置优化
1. 默认更换为gpt-4-1106-preview,以获得最好的效果与成本
2. 提供~/.metagpt作为配置最高优先级目录,从中读取config.yaml
3. workspace可以灵活指定了,在config中配置
4. metagpt作为默认命令行,而非python startup.py
1. 使用新的METAGPT_ROOT生成方式,而非寻找git,以便cli安装
2. 命令行由fire换为了typer,它会带来相对更好的体验
3. project_name可以灵活指定了,在metagpt命令行输入中配置
5. 其他
1. BossRequirement -> UserRequirement
2. 大量错误文本的修正,增加了可读性
3. 中量提示词优化,稍微提升了一些准确率
4. 暂时屏蔽了LongtermMemory相关逻辑,这个逻辑底层调用了langchain的FAISS,会带来~5秒加载耗时
5. 修复了安装包中的部分描述错误
This commit is contained in:
parent
6f345002c4
commit
331d74059f
50 changed files with 699 additions and 387 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,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
|
||||
|
|
@ -17,7 +17,7 @@ from metagpt.schema import Message
|
|||
async def test_write_prd():
|
||||
product_manager = ProductManager()
|
||||
requirements = "开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结"
|
||||
prd = await product_manager.handle(Message(content=requirements, cause_by=BossRequirement))
|
||||
prd = await product_manager.handle(Message(content=requirements, cause_by=UserRequirement))
|
||||
logger.info(requirements)
|
||||
logger.info(prd)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.schema import Message
|
||||
from metagpt.actions import BossRequirement
|
||||
from metagpt.actions import UserRequirement
|
||||
from metagpt.roles.role import RoleContext
|
||||
from metagpt.memory import LongTermMemory
|
||||
|
||||
|
|
@ -15,24 +15,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)
|
||||
|
|
@ -48,7 +48,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
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from typing import List
|
|||
|
||||
from metagpt.memory.memory_storage import MemoryStorage
|
||||
from metagpt.schema import Message
|
||||
from metagpt.actions import BossRequirement
|
||||
from metagpt.actions import UserRequirement
|
||||
from metagpt.actions import WritePRD
|
||||
from metagpt.actions.action_output import ActionOutput
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ from metagpt.actions.action_output import ActionOutput
|
|||
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)
|
||||
|
|
@ -24,12 +24,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
|
||||
|
||||
|
|
@ -49,7 +49,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',
|
||||
|
|
|
|||
|
|
@ -9,7 +9,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
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ 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.recv(Message(content=task, cause_by=BossRequirement))
|
||||
role.recv(Message(content=task, cause_by=UserRequirement))
|
||||
|
||||
await role._think() # it will choose mathskill.Add
|
||||
assert "1100" == (await role._act()).content
|
||||
|
|
|
|||
|
|
@ -8,7 +8,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
|
||||
|
|
@ -26,7 +26,7 @@ async def test_basic_planner():
|
|||
role.import_semantic_skill_from_directory(SKILL_DIRECTORY, "WriterSkill")
|
||||
role.import_skill(TextSkill(), "TextSkill")
|
||||
# using BasicPlanner
|
||||
role.recv(Message(content=task, cause_by=BossRequirement))
|
||||
role.recv(Message(content=task, cause_by=UserRequirement))
|
||||
await role._think()
|
||||
# assuming sk_agent will think he needs WriterSkill.Brainstorm and WriterSkill.Translate
|
||||
assert "WriterSkill.Brainstorm" in role.plan.generated_plan.result
|
||||
|
|
|
|||
|
|
@ -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. 用户可以在私有知识库进行搜索,再根据大语言模型进行总结,输出的结果包括了总结
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ 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 +30,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 +215,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
|
||||
|
|
|
|||
|
|
@ -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=}")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
#
|
||||
import os
|
||||
|
||||
from metagpt.tools.sd_engine import SDEngine, WORKSPACE_ROOT
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.tools.sd_engine import SDEngine
|
||||
|
||||
|
||||
|
||||
def test_sd_engine_init():
|
||||
|
|
@ -21,5 +23,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"
|
||||
img_path = CONFIG.workspace_path / "resources" / "SD_Output" / "output_0.png"
|
||||
assert os.path.exists(img_path) == True
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import os
|
|||
|
||||
import pytest
|
||||
|
||||
from metagpt.const import get_project_root
|
||||
from metagpt.const import get_metagpt_root
|
||||
|
||||
|
||||
class TestGetProjectRoot:
|
||||
|
|
@ -20,11 +20,11 @@ class TestGetProjectRoot:
|
|||
os.chdir(abs_root)
|
||||
|
||||
def test_get_project_root(self):
|
||||
project_root = get_project_root()
|
||||
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."
|
||||
|
|
|
|||
|
|
@ -218,7 +218,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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue