update: 根据 CR 意见修改

This commit is contained in:
seeker-jie 2024-10-29 19:39:26 +08:00
parent b51dbcd260
commit 76e641ab1e
5 changed files with 58 additions and 44 deletions

View file

@ -209,7 +209,7 @@ class SearchEnhancedQA(Action):
list[str]: Summaries of relevant web content.
"""
relevant_urls = await self.collect_relevant_links(query)
relevant_urls = await self._collect_relevant_links(query)
await self._reporter.async_report({"type": "search", "stage": "searching", "urls": relevant_urls})
if not relevant_urls:
logger.warning(f"No relevant URLs found for query: {query}")
@ -226,7 +226,7 @@ class SearchEnhancedQA(Action):
return citations
async def collect_relevant_links(self, query: str) -> list[str]:
async def _collect_relevant_links(self, query: str) -> list[str]:
"""Search and rank URLs relevant to the query.
Args:

View file

@ -32,7 +32,7 @@ Triggered by software/product requests or feature enhancements, ending with the
- UI Design Draft: Basic layout and functionality
- Open Questions: Unclear aspects needing clarification
#### Mermaid Diagram Rules
#### Mermaid Diagram Rules
1. Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1
2. Example:
```mermaid
@ -67,7 +67,7 @@ Triggered by market analysis or competitor research requests, ending with the ou
Must follow this strict information gathering process:
1. Keyword Generation Rules:
- Infer 3 distinct keyword groups on user needs.
- Infer 3 distinct keyword groups on user needs(Infer directly instead of using tools).
- Each group must be a space-separated phrase containing:
* Target industry/product name (REQUIRED)
* Specific aspect or metric
@ -80,7 +80,7 @@ Must follow this strict information gathering process:
2. Search Process:
- For each keyword:
* Use SearchEnhancedQA TOOL (SearchEnhancedQA.collect_relevant_links) collect top 3 search results
* Use SearchEnhancedQA TOOL (SearchEnhancedQA.run) collect top 3 search results
* Remove duplicate URLs
3. Information Analysis:

View file

@ -6,12 +6,16 @@
@File : product_manager.py
@Modified By: liushaojie, 2024/10/17.
"""
from metagpt.actions import UserRequirement, WritePRD
from metagpt.actions.prepare_documents import PrepareDocuments
from metagpt.actions.search_enhanced_qa import SearchEnhancedQA
from metagpt.prompts.product_manager import PRODUCT_MANAGER_INSTRUCTION
from metagpt.roles.di.role_zero import RoleZero
from metagpt.roles.role import RoleReactMode
from metagpt.tools.libs.browser import Browser
from metagpt.tools.libs.editor import Editor
from metagpt.utils.common import tool2name
from metagpt.utils.common import any_to_name, any_to_str, tool2name
from metagpt.utils.git_repository import GitRepository
class ProductManager(RoleZero):
@ -33,12 +37,29 @@ class ProductManager(RoleZero):
max_react_loop: int = 50
tools: list[str] = ["RoleZero", Browser.__name__, Editor.__name__, SearchEnhancedQA.__name__]
todo_action: str = any_to_name(WritePRD)
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
self.enable_memory = False
if self.use_fixed_sop:
self.enable_memory = False
self.set_actions([PrepareDocuments(send_to=any_to_str(self)), WritePRD])
self._watch([UserRequirement, PrepareDocuments])
self.rc.react_mode = RoleReactMode.BY_ORDER
def _update_tool_execution(self):
se_qa = SearchEnhancedQA()
self.tool_execution_map.update(
tool2name(SearchEnhancedQA, ["collect_relevant_links"], se_qa.collect_relevant_links)
)
wp = WritePRD()
self.tool_execution_map.update(tool2name(WritePRD, ["run"], wp.run))
async def _think(self) -> bool:
"""Decide what to do"""
if not self.use_fixed_sop:
return await super()._think()
if GitRepository.is_git_dir(self.config.project_path) and not self.config.git_reinit:
self._set_state(1)
else:
self._set_state(0)
self.config.git_reinit = False
self.todo_action = any_to_name(WritePRD)
return bool(self.rc.todo)

View file

@ -694,7 +694,7 @@ class Plan(BaseModel):
dependent_task_ids (list[str]): The task ids that the new task depends on
instruction (str): The instruction of the new task
assignee (str): The assignee of the new task
task_type (str): The type of the new task, default is empty string
task_type (str, optional): The type of the new task, default is empty string
"""
new_task = Task(
task_id=task_id,

View file

@ -4,16 +4,10 @@ import sys
from metagpt.logs import logger
from metagpt.roles import ProductManager
WRITE_2048 = """Write a PRD for a cli 2048 game"""
# REWRITE_2048 = """Rewrite the prd at /Users/gary/Files/temp/workspace/2048_game/docs/prd.json, add a web UI"""
CASUAL_CHAT = """What's your name?"""
CASE1_GREEDY_SNAKE = "设计一个贪吃蛇游戏root path: '/Users/seeker/Projects/sdfz/mg/mgx_ops/workspace/temp'"
CASE0_WRITE_2048 = """Write a PRD for a cli 2048 game"""
CASE1_GREEDY_SNAKE = "设计一个贪吃蛇游戏"
CASE2_SMART_HOME = "搜索并分析米家、华为智能家居和海尔智家在智能家居市场中的功能、用户需求和市场定位"
CASE3_BEST_SELLING_REFRIGERATOR = "调研当前市场上最畅销的智能冰箱的五个关键特性"
OLD_PRD = """
Language
en_us
@ -62,33 +56,32 @@ Anything UNCLEAR
Currently, all aspects of the project are clear.
"""
CASE4_MUSIC_STREAMING_MEDIA = f"""We have received feedback from users regarding the current music streaming service, stating that they need better personalized recommendations. Please readjust the content of PRD {OLD_PRD} based on these feedback."""
CASE5_SMART_BIG_SCREEN = """分析2024年上半年中国家庭智能大屏行业的发展情况并输出市场分析报告"""
# CASE6 = "我想要生产一个电子烟产品,请帮我完成市场调研分析报告"
CASE6_ELECTRONIC_CIGARETTE = """我想要生产一个电子烟产品,请帮我完成市场调研分析报告"""
async def main(requirement):
product_manager = ProductManager()
await product_manager.run(requirement)
def main():
cases = [
# CASE0_WRITE_2048,
# CASE1_GREEDY_SNAKE,
# CASE2_SMART_HOME,
# CASE3_BEST_SELLING_REFRIGERATOR,
# CASE4_MUSIC_STREAMING_MEDIA,
CASE5_SMART_BIG_SCREEN,
# CASE6_ELECTRONIC_CIGARETTE,
]
root_path = "/tmp"
logger.remove()
logger.add(sys.stderr, level="INFO")
for case in cases:
case += f"\nroot path: '{root_path}'"
logger.info(f"user requirement:\n{case}")
try:
product_manager = ProductManager()
asyncio.run(product_manager.run(case))
except Exception as e:
print(e)
if __name__ == "__main__":
cases = [
# CASE1_GREEDY_SNAKE,
# CASE2_SMART_HOME,
CASE3_BEST_SELLING_REFRIGERATOR,
# CASE4_MUSIC_STREAMING_MEDIA,
# CASE5_SMART_BIG_SCREEN,
# CASE6,
# WRITE_2048,
]
logger.remove()
# logger.add(sys.stderr, level="DEBUG")
logger.add(sys.stderr, level="INFO")
for case in cases:
logger.info(f"user requirement:\n{case}")
try:
asyncio.run(main(case))
except Exception as e:
print(e)
main()