feat: 修改output_path

This commit is contained in:
莘权 马 2024-06-05 12:11:45 +08:00
parent 04e72c0597
commit 4359abd84a
8 changed files with 83 additions and 73 deletions

View file

@ -26,7 +26,11 @@ from metagpt.actions.design_api_an import (
REFINED_DESIGN_NODE,
REFINED_PROGRAM_CALL_FLOW,
)
from metagpt.const import DATA_API_DESIGN_FILE_REPO, SEQ_FLOW_FILE_REPO
from metagpt.const import (
DATA_API_DESIGN_FILE_REPO,
DEFAULT_WORKSPACE_ROOT,
SEQ_FLOW_FILE_REPO,
)
from metagpt.logs import logger
from metagpt.schema import AIMessage, Document, Documents, Message
from metagpt.tools.tool_registry import register_tool
@ -64,7 +68,7 @@ class WriteDesign(Action):
prd_filename: str = "",
legacy_design_filename: str = "",
extra_info: str = "",
output_path: str = "",
output_pathname: str = "",
**kwargs,
) -> AIMessage:
"""
@ -75,7 +79,7 @@ class WriteDesign(Action):
prd_filename (str, optional): The filename of the Product Requirement Document (PRD).
legacy_design_filename (str, optional): The filename of the legacy design document.
extra_info (str, optional): Additional information to be included in the system design.
output_path (str, optional): The output path where the system design should be saved.
output_pathname (str, optional): The output path name of file that the system design should be saved to.
Returns:
AIMessage: An AIMessage object containing the system design.
@ -87,7 +91,7 @@ class WriteDesign(Action):
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info)
>>> print(result.content)
The design is balabala...
System Design filename: "/path/to/design/filename"
# Modify an exists system design.
>>> user_requirement = "Your user requirements"
@ -96,7 +100,7 @@ class WriteDesign(Action):
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, legacy_design_filename=legacy_design_filename)
>>> print(result.content)
The design is balabala...
System Design filename: "/path/to/design/filename"
# Write a new system design with the given PRD(Product Requirement Document).
>>> user_requirement = "Your user requirements"
@ -105,7 +109,7 @@ class WriteDesign(Action):
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, prd_filename=prd_filename)
>>> print(result.content)
The design is balabala...
System Design filename: "/path/to/design/filename"
# Modify an exists system design with the given PRD(Product Requirement Document).
>>> user_requirement = "Your user requirements"
@ -115,45 +119,45 @@ class WriteDesign(Action):
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, legacy_design_filename=legacy_design_filename, prd_filename=prd_filename)
>>> print(result.content)
The design is balabala...
TSystem Design filename: "/path/to/design/filename"
# Write a new system design and save to the directory.
# Write a new system design and save to the path name.
>>> user_requirement = "Your user requirements"
>>> extra_info = "Your extra information"
>>> output_path = "/path/to/save/"
>>> output_pathname = "/path/to/design/filename"
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, output_path=output_path)
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, output_pathname=output_pathname)
>>> print(result.content)
System Design filename: "/path/to/design/filename"
# Modify an exists system design and save to the directory.
# Modify an exists system design and save to the path name.
>>> user_requirement = "Your user requirements"
>>> extra_info = "Your extra information"
>>> legacy_design_filename = "/path/to/exists/design/filename"
>>> output_path = "/path/to/save/"
>>> output_pathname = "/path/to/design/filename"
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, legacy_design_filename=legacy_design_filename)
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, legacy_design_filename=legacy_design_filename, output_pathname=output_pathname)
>>> print(result.content)
System Design filename: "/path/to/design/filename"
# Write a new system design with the given PRD(Product Requirement Document) and save to the directory.
# Write a new system design with the given PRD(Product Requirement Document) and save to the path name.
>>> user_requirement = "Your user requirements"
>>> extra_info = "Your extra information"
>>> prd_filename = "/path/to/prd/filename"
>>> output_path = "/path/to/save/"
>>> output_pathname = "/path/to/design/filename"
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, prd_filename=prd_filename)
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, prd_filename=prd_filename, output_pathname=output_pathname)
>>> print(result.content)
System Design filename: "/path/to/design/filename"
# Modify an exists system design with the given PRD(Product Requirement Document) and save to the directory.
# Modify an exists system design with the given PRD(Product Requirement Document) and save to the path name.
>>> user_requirement = "Your user requirements"
>>> extra_info = "Your extra information"
>>> prd_filename = "/path/to/prd/filename"
>>> legacy_design_filename = "/path/to/exists/design/filename"
>>> output_path = "/path/to/save/"
>>> output_pathname = "/path/to/design/filename"
>>> action = WriteDesign()
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, legacy_design_filename=legacy_design_filename, prd_filename=prd_filename)
>>> result = await action.run(user_requirement=user_requirement, extra_info=extra_info, legacy_design_filename=legacy_design_filename, prd_filename=prd_filename, output_pathname=output_pathname)
>>> print(result.content)
System Design filename: "/path/to/design/filename"
"""
@ -163,7 +167,7 @@ class WriteDesign(Action):
prd_filename=prd_filename,
legacy_design_filename=legacy_design_filename,
extra_info=extra_info,
output_path=output_path,
output_pathname=output_pathname,
)
self.input_args = with_messages[-1].instruct_content
@ -268,14 +272,16 @@ class WriteDesign(Action):
prd_filename: str = "",
legacy_design_filename: str = "",
extra_info: str = "",
output_path: str = "",
output_pathname: str = "",
) -> AIMessage:
context = to_markdown_code_block(user_requirement)
if extra_info:
context = to_markdown_code_block(extra_info)
prd_content = ""
if prd_filename:
prd_content = await aread(filename=prd_filename)
context += to_markdown_code_block(prd_content)
context = "### User Requirements\n{user_requirement}\n### Extra_info\n{extra_info}\n### PRD\n{prd}\n".format(
user_requirement=to_markdown_code_block(user_requirement),
extra_info=to_markdown_code_block(extra_info),
prd=to_markdown_code_block(prd_content),
)
if not legacy_design_filename:
node = await self._new_system_design(context=context)
design = Document(content=node.instruct_content.model_dump_json())
@ -285,13 +291,14 @@ class WriteDesign(Action):
prd_doc=Document(content=context), system_design_doc=Document(content=old_design_content)
)
if not output_path:
return AIMessage(content=design.content)
output_filename = Path(output_path) / f"{uuid.uuid4().hex}.json"
await awrite(filename=output_filename, data=design.content)
kvs = {"changed_system_design_filenames": [output_filename]}
if not output_pathname:
output_path = DEFAULT_WORKSPACE_ROOT
output_path.mkdir(parents=True, exist_ok=True)
output_pathname = Path(output_path) / f"{uuid.uuid4().hex}.json"
await awrite(filename=output_pathname, data=design.content)
kvs = {"changed_system_design_filenames": [output_pathname]}
return AIMessage(
content=f'System Design filename: "{str(output_filename)}"',
content=f'System Design filename: "{str(output_pathname)}"',
instruct_content=AIMessage.create_instruct_value(kvs=kvs),
)

View file

@ -35,6 +35,7 @@ from metagpt.actions.write_prd_an import (
from metagpt.const import (
BUGFIX_FILENAME,
COMPETITIVE_ANALYSIS_FILE_REPO,
DEFAULT_WORKSPACE_ROOT,
REQUIREMENT_FILENAME,
)
from metagpt.logs import logger
@ -82,7 +83,7 @@ class WritePRD(Action):
with_messages: List[Message] = None,
*,
user_requirement: str = "",
output_path: str = "",
output_pathname: str = "",
legacy_prd_filename: str = "",
extra_info: str = "",
**kwargs,
@ -92,7 +93,7 @@ class WritePRD(Action):
Args:
user_requirement (str): A string detailing the user's requirements.
output_path (str, optional): The file path where the output document should be saved. Defaults to "".
output_pathname (str, optional): The path name of file that the output document should be saved to. Defaults to "".
legacy_prd_filename (str, optional): The file path of the legacy Product Requirement Document to use as a reference. Defaults to "".
extra_info (str, optional): Additional information to include in the document. Defaults to "".
**kwargs: Additional keyword arguments.
@ -107,7 +108,7 @@ class WritePRD(Action):
>>> write_prd = WritePRD()
>>> result = await write_prd.run(user_requirement=user_requirement, extra_info=extra_info)
>>> print(result.content)
The PRD is about balabala...
PRD filename: "/path/to/prd/directory/213434ad.json"
# Modify a exists PRD(Product Requirement Document)
>>> user_requirement = "YOUR REQUIREMENTS"
@ -116,24 +117,24 @@ class WritePRD(Action):
>>> write_prd = WritePRD()
>>> result = await write_prd.run(user_requirement=user_requirement, extra_info=extra_info, legacy_prd_filename=legacy_prd_filename)
>>> print(result.content)
The PRD is about balabala...
PRD filename: "/path/to/prd/directory/213434ad.json"
# Write and save a new PRD(Product Requirement Document) to the directory.
# Write and save a new PRD(Product Requirement Document) to the path name.
>>> user_requirement = "YOUR REQUIREMENTS"
>>> extra_info = "YOUR EXTRA INFO"
>>> output_path = "/path/to/prd/directory/"
>>> output_pathname = "/path/to/prd/directory/213434ad.json"
>>> write_prd = WritePRD()
>>> result = await write_prd.run(user_requirement=user_requirement, extra_info=extra_info, output_path=output_path)
>>> result = await write_prd.run(user_requirement=user_requirement, extra_info=extra_info, output_pathname=output_pathname)
>>> print(result.content)
PRD filename: "/path/to/prd/directory/213434ad.json"
# Modify a exists PRD(Product Requirement Document) and save to the directory.
# Modify a exists PRD(Product Requirement Document) and save to the path name.
>>> user_requirement = "YOUR REQUIREMENTS"
>>> extra_info = "YOUR EXTRA INFO"
>>> legacy_prd_filename = "/path/to/exists/prd_filename"
>>> output_path = "/path/to/prd/directory/"
>>> output_pathname = "/path/to/prd/directory/213434ad.json"
>>> write_prd = WritePRD()
>>> result = await write_prd.run(user_requirement=user_requirement, extra_info=extra_info, legacy_prd_filename=legacy_prd_filename, output_path=output_path)
>>> result = await write_prd.run(user_requirement=user_requirement, extra_info=extra_info, legacy_prd_filename=legacy_prd_filename, output_pathname=output_pathname)
>>> print(result.content)
PRD filename: "/path/to/prd/directory/213434ad.json"
@ -141,7 +142,7 @@ class WritePRD(Action):
if not with_messages:
return await self._execute_api(
user_requirement=user_requirement,
output_path=output_path,
output_pathname=output_pathname,
legacy_prd_filename=legacy_prd_filename,
extra_info=extra_info,
)
@ -306,12 +307,12 @@ class WritePRD(Action):
self.repo.git_repo.rename_root(self.project_name)
async def _execute_api(
self, user_requirement: str, output_path: str, legacy_prd_filename: str, extra_info: str
self, user_requirement: str, output_pathname: str, legacy_prd_filename: str, extra_info: str
) -> AIMessage:
content = to_markdown_code_block(val=user_requirement, type_="text")
if extra_info:
content += to_markdown_code_block(val=extra_info)
content = "#### User Requirements\n{user_requirement}\n#### Extra Info\n{extra_info}\n".format(
user_requirement=to_markdown_code_block(val=user_requirement),
extra_info=to_markdown_code_block(val=extra_info),
)
req = Document(content=content)
if not legacy_prd_filename:
node = await self._new_prd(requirement=req.content)
@ -321,10 +322,10 @@ class WritePRD(Action):
old_prd = Document(content=content)
new_prd = await self._merge(req=req, related_doc=old_prd)
if not output_path:
return AIMessage(content=new_prd.content)
output_filename = Path(output_path) / f"{uuid.uuid4().hex}.json"
await awrite(filename=output_filename, data=new_prd.content)
kvs = AIMessage.create_instruct_value({"changed_prd_filenames": [str(output_filename)]})
return AIMessage(content=f'PRD filename: "{str(output_filename)}"', instruct_content=kvs)
if not output_pathname:
output_path = DEFAULT_WORKSPACE_ROOT
output_path.mkdir(parents=True, exist_ok=True)
output_pathname = Path(output_path) / f"{uuid.uuid4().hex}.json"
await awrite(filename=output_pathname, data=new_prd.content)
kvs = AIMessage.create_instruct_value({"changed_prd_filenames": [str(output_pathname)]})
return AIMessage(content=f'PRD filename: "{str(output_pathname)}"', instruct_content=kvs)

View file

@ -1,11 +1,13 @@
from __future__ import annotations
import contextlib
from uuid import uuid4
from playwright.async_api import async_playwright
from metagpt.utils.file import MemoryFileSystem
from uuid import uuid4
from metagpt.const import DEFAULT_WORKSPACE_ROOT
from metagpt.tools.tool_registry import register_tool
from metagpt.utils.file import MemoryFileSystem
from metagpt.utils.parse_html import simplify_html
from metagpt.utils.report import BrowserReporter
@ -64,7 +66,6 @@ class Browser:
# Since RAG is an optional optimization, if it fails, the simplified HTML can be used as a fallback.
with contextlib.suppress(Exception):
from metagpt.rag.engines import SimpleEngine # avoid circular import
# TODO make `from_docs` asynchronous

View file

@ -945,5 +945,7 @@ def get_markdown_code_block_type(filename: str) -> str:
def to_markdown_code_block(val: str, type_: str = "") -> str:
if not val:
return val or ""
val = val.replace("```", "\\`\\`\\`")
return f"\n```{type_}\n{val}\n```\n"

View file

@ -72,7 +72,6 @@ class File:
class MemoryFileSystem(_MemoryFileSystem):
@classmethod
def _strip_protocol(cls, path):
return super()._strip_protocol(str(path))

View file

@ -4,11 +4,10 @@ from __future__ import annotations
from typing import Generator, Optional
from urllib.parse import urljoin, urlparse
import htmlmin
from bs4 import BeautifulSoup
from pydantic import BaseModel, PrivateAttr
import htmlmin
class WebPage(BaseModel):
inner_text: str

View file

@ -6,12 +6,12 @@
@File : test_design_api.py
@Modifiled By: mashenquan, 2023-12-6. According to RFC 135
"""
import json
from pathlib import Path
import pytest
from metagpt.actions.design_api import WriteDesign
from metagpt.const import METAGPT_ROOT
from metagpt.const import DEFAULT_WORKSPACE_ROOT, METAGPT_ROOT
from metagpt.logs import logger
from metagpt.schema import AIMessage, Message
from metagpt.utils.project_repo import ProjectRepo
@ -74,8 +74,7 @@ async def test_design_api(context, user_requirement, prd_filename, legacy_design
)
assert isinstance(result, AIMessage)
assert result.content
m = json.loads(result.content)
assert m
assert str(DEFAULT_WORKSPACE_ROOT) in result.content
@pytest.mark.parametrize(
@ -97,7 +96,7 @@ async def test_design_api_dir(context, user_requirement, prd_filename, legacy_de
user_requirement=user_requirement,
prd_filename=prd_filename,
legacy_design_filename=legacy_design_filename,
output_path=context.config.project_path,
output_pathname=str(Path(context.config.project_path) / "1.txt"),
)
assert isinstance(result, AIMessage)
assert result.content

View file

@ -6,12 +6,13 @@
@File : test_write_prd.py
@Modified By: mashenquan, 2023-11-1. According to Chapter 2.2.1 and 2.2.2 of RFC 116, replace `handle` with `run`.
"""
import json
import uuid
from pathlib import Path
import pytest
from metagpt.actions import UserRequirement, WritePRD
from metagpt.const import REQUIREMENT_FILENAME
from metagpt.const import DEFAULT_WORKSPACE_ROOT, REQUIREMENT_FILENAME
from metagpt.logs import logger
from metagpt.roles.product_manager import ProductManager
from metagpt.roles.role import RoleReactMode
@ -80,10 +81,12 @@ async def test_write_prd_api(context):
result = await action.run(user_requirement="write a snake game.")
assert isinstance(result, AIMessage)
assert result.content
m = json.loads(result.content)
assert m
assert str(DEFAULT_WORKSPACE_ROOT) in result.content
result = await action.run(user_requirement="write a snake game.", output_path=str(context.config.project_path))
result = await action.run(
user_requirement="write a snake game.",
output_pathname=str(Path(context.config.project_path) / f"{uuid.uuid4().hex}.json"),
)
assert isinstance(result, AIMessage)
assert result.content
assert result.instruct_content
@ -94,12 +97,11 @@ async def test_write_prd_api(context):
result = await action.run(user_requirement="Add moving enemy.", legacy_prd_filename=legacy_prd_filename)
assert isinstance(result, AIMessage)
assert result.content
m = json.loads(result.content)
assert m
assert str(DEFAULT_WORKSPACE_ROOT) in result.content
result = await action.run(
user_requirement="Add moving enemy.",
output_path=str(context.config.project_path),
output_pathname=str(Path(context.config.project_path) / f"{uuid.uuid4().hex}.json"),
legacy_prd_filename=legacy_prd_filename,
)
assert isinstance(result, AIMessage)