feat: archive

This commit is contained in:
莘权 马 2023-11-22 20:40:42 +08:00
parent e9471ed206
commit 9339eab20c
5 changed files with 97 additions and 9 deletions

View file

@ -11,7 +11,7 @@ from typing import List
from metagpt.actions import Action, ActionOutput
from metagpt.config import CONFIG
from metagpt.const import PRDS_FILE_REPO, SYS_DESIGN_FILE_REPO, WORKSPACE_ROOT
from metagpt.const import PRDS_FILE_REPO, SYSTEM_DESIGN_FILE_REPO, WORKSPACE_ROOT
from metagpt.logs import logger
from metagpt.schema import Document, Documents
from metagpt.utils.common import CodeParser
@ -208,7 +208,7 @@ class WriteDesign(Action):
prds_file_repo = CONFIG.git_repo.new_file_repository(PRDS_FILE_REPO)
changed_prds = prds_file_repo.changed_files
# 通过git diff来识别docs/system_designs下那些设计文档发生了变动
system_design_file_repo = CONFIG.git_repo.new_file_repository(SYS_DESIGN_FILE_REPO)
system_design_file_repo = CONFIG.git_repo.new_file_repository(SYSTEM_DESIGN_FILE_REPO)
changed_system_designs = system_design_file_repo.changed_files
# 对于那些发生变动的PRD和设计文档重新生成设计内容
@ -219,7 +219,7 @@ class WriteDesign(Action):
if not old_system_design_doc:
system_design = await self._run(context=prd.content)
doc = Document(
root_path=SYS_DESIGN_FILE_REPO, filename=filename, content=system_design.instruct_content.json()
root_path=SYSTEM_DESIGN_FILE_REPO, filename=filename, content=system_design.instruct_content.json()
)
else:
doc = await self._merge(prd_doc=prd, system_design_doc=old_system_design_doc)
@ -234,7 +234,9 @@ class WriteDesign(Action):
prd_doc = await prds_file_repo.get(filename=filename)
old_system_design_doc = await system_design_file_repo.get(filename)
new_system_design_doc = await self._merge(prd_doc, old_system_design_doc)
await system_design_file_repo.save(filename=filename, content=new_system_design_doc.content)
await system_design_file_repo.save(
filename=filename, content=new_system_design_doc.content, dependencies={prd_doc.root_relative_path}
)
changed_files.docs[filename] = new_system_design_doc
# 等docs/system_designs/下所有文件都处理完才发publish message给后续做全局优化留空间。
@ -251,8 +253,18 @@ class WriteDesign(Action):
"Python package name",
system_design.instruct_content.dict()["Python package name"].strip().strip("'").strip('"'),
)
# await self._save(context, system_design)
await self._rename_workspace(system_design)
return system_design
async def _merge(self, prd_doc, system_design_doc):
return system_design_doc
async def _rename_workspace(self, system_design):
if CONFIG.WORKDIR: # 已经指定了在旧版本上更新
return
if isinstance(system_design, ActionOutput):
ws_name = system_design.instruct_content.dict()["Python package name"]
else:
ws_name = CodeParser.parse_str(block="Python package name", text=system_design)
CONFIG.git_repo.rename_root(ws_name)

View file

@ -5,11 +5,14 @@
@Author : alexanderwu
@File : project_management.py
"""
import json
from typing import List
from metagpt.actions import ActionOutput
from metagpt.actions.action import Action
from metagpt.config import CONFIG
from metagpt.const import WORKSPACE_ROOT
from metagpt.const import SYSTEM_DESIGN_FILE_REPO, TASK_FILE_REPO, WORKSPACE_ROOT
from metagpt.schema import Document, Documents
from metagpt.utils.common import CodeParser
from metagpt.utils.get_template import get_template
from metagpt.utils.json_to_markdown import json_to_markdown
@ -178,13 +181,69 @@ class WriteTasks(Action):
requirements_path = WORKSPACE_ROOT / ws_name / "requirements.txt"
requirements_path.write_text("\n".join(rsp.instruct_content.dict().get("Required Python third-party packages")))
async def run(self, context, format=CONFIG.prompt_format):
async def run(self, with_messages, format=CONFIG.prompt_format):
system_design_file_repo = CONFIG.git_repo.new_file_repository(SYSTEM_DESIGN_FILE_REPO)
changed_system_designs = system_design_file_repo.changed_files
tasks_file_repo = CONFIG.git_repo.new_file_repository(TASK_FILE_REPO)
changed_tasks = tasks_file_repo.changed_files
change_files = Documents()
# 根据docs/system_designs/下的git head diff识别哪些task文档需要重写
for filename in changed_system_designs:
system_design_doc = await system_design_file_repo.get(filename)
task_doc = await tasks_file_repo.get(filename)
if task_doc:
task_doc = await self._merge(system_design_doc, task_doc)
else:
rsp = await self._run(system_design_doc.content)
task_doc = Document(root_path=TASK_FILE_REPO, filename=filename, content=rsp.instruct_content.json())
await tasks_file_repo.save(
filename=filename, content=task_doc.content, dependencies={system_design_doc.root_relative_path}
)
await self._update_requirements(task_doc)
change_files.docs[filename] = task_doc
# 根据docs/tasks/下的git head diff识别哪些task文件被用户修改了需要重写
for filename in changed_tasks:
if filename in change_files.docs:
continue
system_design_doc = await system_design_file_repo.get(filename)
task_doc = await tasks_file_repo.get(filename)
task_doc = await self._merge(system_design_doc, task_doc)
await tasks_file_repo.save(
filename=filename, content=task_doc.content, dependencies={system_design_doc.root_relative_path}
)
await self._update_requirements(task_doc)
change_files.docs[filename] = task_doc
# 等docs/tasks/下所有文件都处理完才发publish message给后续做全局优化留空间。
return ActionOutput(content=change_files.json(), instruct_content=change_files)
async def _run(self, context, format=CONFIG.prompt_format):
prompt_template, format_example = get_template(templates, format)
prompt = prompt_template.format(context=context, format_example=format_example)
rsp = await self._aask_v1(prompt, "task", OUTPUT_MAPPING, format=format)
self._save(context, rsp)
return rsp
async def _merge(self, system_design_doc, task_dock) -> Document:
return task_dock
async def _update_requirements(self, doc):
m = json.loads(doc.content)
packages = set(m.get("Required Python third-party packages", set()))
file_repo = CONFIG.git_repo.new_file_repository()
filename = "requirements.txt"
requirement_doc = await file_repo.get(filename)
if not requirement_doc:
requirement_doc = Document(filename=filename, root_path=".", content="")
lines = requirement_doc.content.splitlines()
for pkg in lines:
if pkg == "":
continue
packages.add(pkg)
await file_repo.save(filename, content="\n".join(packages))
class AssignTasks(Action):
async def run(self, *args, **kwargs):

View file

@ -53,4 +53,5 @@ MESSAGE_ROUTE_TO_ALL = "<all>"
REQUIREMENT_FILENAME = "requirement.txt"
DOCS_FILE_REPO = "docs"
PRDS_FILE_REPO = "docs/prds"
SYS_DESIGN_FILE_REPO = "docs/system_design"
SYSTEM_DESIGN_FILE_REPO = "docs/system_design"
TASK_FILE_REPO = "docs/tasks"

View file

@ -166,4 +166,4 @@ class FileRepository:
"""
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
guid_suffix = str(uuid.uuid4())[:8]
return f"{current_time}t{guid_suffix}"
return f"{current_time}x{guid_suffix}"

View file

@ -17,6 +17,7 @@ from git.repo import Repo
from git.repo.fun import is_git_dir
from metagpt.const import WORKSPACE_ROOT
from metagpt.logs import logger
from metagpt.utils.dependency_file import DependencyFile
from metagpt.utils.file_repository import FileRepository
@ -170,6 +171,21 @@ class GitRepository:
self._dependency = DependencyFile(workdir=self.workdir)
return self._dependency
def rename_root(self, new_dir_name):
"""Rename the root directory of the Git repository.
:param new_dir_name: The new name for the root directory.
"""
if self.workdir.name == new_dir_name:
return
new_path = self.workdir.parent / new_dir_name
if new_path.exists():
logger.info(f"Delete directory {str(new_path)}")
shutil.rmtree(new_path)
self.workdir.rename(new_path)
logger.info(f"Rename directory {str(self.workdir)} to {str(new_path)}")
self._repository = Repo(new_path)
if __name__ == "__main__":
path = WORKSPACE_ROOT / "git"