mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-18 13:55:17 +02:00
feat: 修改output_path
This commit is contained in:
parent
04e72c0597
commit
4359abd84a
8 changed files with 83 additions and 73 deletions
|
|
@ -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),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ class File:
|
|||
|
||||
|
||||
class MemoryFileSystem(_MemoryFileSystem):
|
||||
|
||||
@classmethod
|
||||
def _strip_protocol(cls, path):
|
||||
return super()._strip_protocol(str(path))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue