mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-08 15:05:17 +02:00
fixbug: test_assistant
fixbug: class view feat: +comments
This commit is contained in:
parent
5bc17f3b63
commit
3b1644b7ff
7 changed files with 92 additions and 19 deletions
|
|
@ -5,6 +5,7 @@
|
|||
@Author : mashenquan
|
||||
@File : rebuild_class_view.py
|
||||
@Desc : Reconstructs class diagram from a source code project.
|
||||
Implement RFC197, https://deepwisdom.feishu.cn/wiki/VyK0wfq56ivuvjklMKJcmHQknGt
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
|
@ -65,15 +66,18 @@ class RebuildClassView(Action):
|
|||
await self._create_mermaid_class_views()
|
||||
await self.graph_db.save()
|
||||
|
||||
async def _create_mermaid_class_views(self):
|
||||
async def _create_mermaid_class_views(self) -> str:
|
||||
"""Creates a Mermaid class diagram using data from the `graph_db` graph repository.
|
||||
|
||||
This method utilizes information stored in the graph repository to generate a Mermaid class diagram.
|
||||
Returns:
|
||||
mermaid class diagram file name.
|
||||
"""
|
||||
path = self.context.git_repo.workdir / DATA_API_DESIGN_FILE_REPO
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
pathname = path / self.context.git_repo.workdir.name
|
||||
async with aiofiles.open(str(pathname.with_suffix(".mmd")), mode="w", encoding="utf-8") as writer:
|
||||
filename = str(pathname.with_suffix(".mmd"))
|
||||
async with aiofiles.open(filename, mode="w", encoding="utf-8") as writer:
|
||||
content = "classDiagram\n"
|
||||
logger.debug(content)
|
||||
await writer.write(content)
|
||||
|
|
@ -94,6 +98,14 @@ class RebuildClassView(Action):
|
|||
relationship_distinct.update(distinct)
|
||||
logger.info(f"classes: {len(class_distinct)}, relationship: {len(relationship_distinct)}")
|
||||
|
||||
if self.i_context:
|
||||
r_filename = Path(filename).relative_to(self.context.git_repo.workdir)
|
||||
await self.graph_db.insert(
|
||||
subject=self.i_context, predicate="hasMermaidClassDiagramFile", object_=str(r_filename)
|
||||
)
|
||||
logger.info(f"{self.i_context} hasMermaidClassDiagramFile {filename}")
|
||||
return filename
|
||||
|
||||
async def _create_mermaid_class(self, ns_class_name) -> str:
|
||||
"""Generates a Mermaid class diagram for a specific class using data from the `graph_db` graph repository.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
@Author : mashenquan
|
||||
@File : rebuild_sequence_view.py
|
||||
@Desc : Reconstruct sequence view information through reverse engineering.
|
||||
Implement RFC197, https://deepwisdom.feishu.cn/wiki/VyK0wfq56ivuvjklMKJcmHQknGt
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -93,7 +94,10 @@ class RebuildSequenceView(Action):
|
|||
"""
|
||||
graph_repo_pathname = self.context.git_repo.workdir / GRAPH_REPO_FILE_REPO / self.context.git_repo.workdir.name
|
||||
self.graph_db = await DiGraphRepository.load_from(str(graph_repo_pathname.with_suffix(".json")))
|
||||
entries = await self._search_main_entry()
|
||||
if not self.i_context:
|
||||
entries = await self._search_main_entry()
|
||||
else:
|
||||
entries = [SPO(subject=self.i_context, predicate="", object_="")]
|
||||
for entry in entries:
|
||||
await self._rebuild_main_sequence_view(entry)
|
||||
while await self._merge_sequence_view(entry):
|
||||
|
|
@ -139,7 +143,7 @@ class RebuildSequenceView(Action):
|
|||
use_case_blocks = []
|
||||
for c in classes:
|
||||
use_cases = await self._get_class_use_cases(c.subject)
|
||||
use_case_blocks.extend(use_cases)
|
||||
use_case_blocks.append(use_cases)
|
||||
prompt_blocks = ["## Use Cases\n" + "\n".join(use_case_blocks)]
|
||||
block = "## Participants\n"
|
||||
for p in participants:
|
||||
|
|
@ -238,6 +242,15 @@ class RebuildSequenceView(Action):
|
|||
class_view = await self._get_uml_class_view(ns_class_name)
|
||||
source_code = await self._get_source_code(ns_class_name)
|
||||
|
||||
# prompt_blocks = [
|
||||
# "## Instruction\n"
|
||||
# "You are a python code to UML 2.0 Use Case translator.\n"
|
||||
# 'The generated UML 2.0 Use Case must include the roles or entities listed in "Participants".\n'
|
||||
# "The functional descriptions of Actors and Use Cases in the generated UML 2.0 Use Case must not "
|
||||
# 'conflict with the information in "Mermaid Class Views".\n'
|
||||
# 'The section under `if __name__ == "__main__":` of "Source Code" contains information about external '
|
||||
# "system interactions with the internal system.\n"
|
||||
# ]
|
||||
prompt_blocks = []
|
||||
block = "## Participants\n"
|
||||
for p in participants:
|
||||
|
|
@ -253,6 +266,38 @@ class RebuildSequenceView(Action):
|
|||
prompt_blocks.append(block)
|
||||
prompt = "\n---\n".join(prompt_blocks)
|
||||
|
||||
# class _UseCase(BaseModel):
|
||||
# description: str = Field(default="...", description="Describes about what the use case to do")
|
||||
# inputs: List[str] = Field(default=["input name 1", "input name 2"],
|
||||
# description="Lists the input names of the use case from external sources")
|
||||
# outputs: List[str] = Field(default=["output name 1", "output name 2"],
|
||||
# description="Lists the output names of the use case to external sources")
|
||||
# actors: List[str] = Field(default=["actor name 1", "actor name 2"],
|
||||
# description="Lists the participant actors of the use case")
|
||||
# steps: List[str] = Field(default=["Step 1", "Step 2"],
|
||||
# description="Lists the steps about how the use case works step by step")
|
||||
# reason: str = Field(default="Because ...",
|
||||
# description="Explaining under what circumstances would the external system execute this use case.")
|
||||
#
|
||||
#
|
||||
# class _UseCaseList(BaseModel):
|
||||
# description: str = Field(default="...",
|
||||
# description="A summary explains what the whole source code want to do")
|
||||
# use_cases: List[_UseCase] = Field(default=[
|
||||
# {
|
||||
# "description": "Describes about what the use case to do",
|
||||
# "inputs": ["input name 1", "input name 2"],
|
||||
# "outputs": ["output name 1", "output name 2"],
|
||||
# "actors": ["actor name 1", "actor name 2"],
|
||||
# "steps": ["Step 1", "Step 2"],
|
||||
# "reason": "Because ..."
|
||||
# }
|
||||
# ], description="List all use cases.")
|
||||
# relationship: List[str] = Field(default=["use case 1 ..."],
|
||||
# description="Lists all the descriptions of relationship among these use cases")
|
||||
|
||||
# rsp = await ActionNode.from_pydantic(_UseCaseList).fill(context=prompt, llm=self.llm)
|
||||
|
||||
rsp = await self.llm.aask(
|
||||
msg=prompt,
|
||||
system_msgs=[
|
||||
|
|
@ -452,6 +497,8 @@ class RebuildSequenceView(Action):
|
|||
"metagpt/management/skill_manager.py", then the returned value will be
|
||||
"/User/xxx/github/MetaGPT/metagpt/management/skill_manager.py"
|
||||
"""
|
||||
if re.match(r"^/.+", pathname):
|
||||
return pathname
|
||||
files = list_files(root=root)
|
||||
postfix = "/" + str(pathname)
|
||||
for i in files:
|
||||
|
|
|
|||
|
|
@ -950,12 +950,10 @@ class RepoParser(BaseModel):
|
|||
|
||||
for c in class_views:
|
||||
c.package = RepoParser._repair_ns(c.package, new_mappings)
|
||||
for i in range(len(relationship_views)):
|
||||
v = relationship_views[i]
|
||||
for _, v in enumerate(relationship_views):
|
||||
v.src = RepoParser._repair_ns(v.src, new_mappings)
|
||||
v.dest = RepoParser._repair_ns(v.dest, new_mappings)
|
||||
relationship_views[i] = v
|
||||
return class_views, relationship_views, root_path
|
||||
return class_views, relationship_views, str(path)[: len(root_path)]
|
||||
|
||||
@staticmethod
|
||||
def _repair_ns(package: str, mappings: Dict[str, str]) -> str:
|
||||
|
|
|
|||
|
|
@ -773,4 +773,6 @@ class UMLClassView(UMLClassMeta):
|
|||
for j in i.args:
|
||||
arg = UMLClassAttribute(name=j.name, value_type=j.type_, default_value=j.default_)
|
||||
method.args.append(arg)
|
||||
method.return_type = i.return_args.type_
|
||||
class_view.methods.append(method)
|
||||
return class_view
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ async def test_rebuild(context):
|
|||
context=context,
|
||||
)
|
||||
await action.run()
|
||||
rows = await action.graph_db.select()
|
||||
assert rows
|
||||
assert context.repo.docs.graph_repo.changed_files
|
||||
|
||||
|
||||
|
|
@ -45,6 +47,12 @@ def test_align_path(path, direction, diff, want):
|
|||
("/Users/x/github/MetaGPT/metagpt", "/Users/x/github/MetaGPT/metagpt", "=", "."),
|
||||
("/Users/x/github/MetaGPT", "/Users/x/github/MetaGPT/metagpt", "-", "metagpt"),
|
||||
("/Users/x/github/MetaGPT/metagpt", "/Users/x/github/MetaGPT", "+", "metagpt"),
|
||||
(
|
||||
"/Users/x/github/MetaGPT-env/lib/python3.9/site-packages/moviepy",
|
||||
"/Users/x/github/MetaGPT-env/lib/python3.9/site-packages/",
|
||||
"+",
|
||||
"moviepy",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_diff_path(path_root, package_root, want_direction, want_diff):
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ async def test_rebuild(context, mocker):
|
|||
|
||||
action = RebuildSequenceView(
|
||||
name="RedBean",
|
||||
i_context=str(Path(__file__).parent.parent.parent.parent / "metagpt"),
|
||||
i_context=str(
|
||||
Path(__file__).parent.parent.parent.parent / "metagpt/management/skill_manager.py:__name__:__main__"
|
||||
),
|
||||
llm=LLM(),
|
||||
context=context,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,17 @@ async def test_run(mocker, context):
|
|||
language: str
|
||||
agent_description: str
|
||||
cause_by: str
|
||||
agent_skills: list
|
||||
|
||||
agent_skills = [
|
||||
{"id": 1, "name": "text_to_speech", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 2, "name": "text_to_image", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 3, "name": "ai_call", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 3, "name": "data_analysis", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 5, "name": "crawler", "type": "builtin", "config": {"engine": "ddg"}, "enabled": True},
|
||||
{"id": 6, "name": "knowledge", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 6, "name": "web_search", "type": "builtin", "config": {}, "enabled": True},
|
||||
]
|
||||
|
||||
inputs = [
|
||||
{
|
||||
|
|
@ -48,6 +59,7 @@ async def test_run(mocker, context):
|
|||
"language": "English",
|
||||
"agent_description": "chatterbox",
|
||||
"cause_by": any_to_str(TalkAction),
|
||||
"agent_skills": [],
|
||||
},
|
||||
{
|
||||
"memory": {
|
||||
|
|
@ -65,24 +77,16 @@ async def test_run(mocker, context):
|
|||
"language": "English",
|
||||
"agent_description": "painter",
|
||||
"cause_by": any_to_str(SkillAction),
|
||||
"agent_skills": agent_skills,
|
||||
},
|
||||
]
|
||||
agent_skills = [
|
||||
{"id": 1, "name": "text_to_speech", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 2, "name": "text_to_image", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 3, "name": "ai_call", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 3, "name": "data_analysis", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 5, "name": "crawler", "type": "builtin", "config": {"engine": "ddg"}, "enabled": True},
|
||||
{"id": 6, "name": "knowledge", "type": "builtin", "config": {}, "enabled": True},
|
||||
{"id": 6, "name": "web_search", "type": "builtin", "config": {}, "enabled": True},
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Input(**i)
|
||||
role = Assistant(language="Chinese", context=context)
|
||||
role.context.kwargs.language = seed.language
|
||||
role.context.kwargs.agent_description = seed.agent_description
|
||||
role.context.kwargs.agent_skills = agent_skills
|
||||
role.context.kwargs.agent_skills = seed.agent_skills
|
||||
|
||||
role.memory = seed.memory # Restore historical conversation content.
|
||||
while True:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue