From 97ee2f0c98f2c3fe0ccb285a7ce0992b67416038 Mon Sep 17 00:00:00 2001 From: geekan Date: Thu, 11 Jan 2024 18:08:04 +0800 Subject: [PATCH] refine code --- examples/example.pkl | Bin 624 -> 624 bytes metagpt/actions/action.py | 2 +- metagpt/context.py | 79 ---------------------- metagpt/context_mixin.py | 95 +++++++++++++++++++++++++++ metagpt/document_store/base_store.py | 1 - metagpt/roles/role.py | 2 +- tests/data/rsp_cache.json | 8 ++- tests/metagpt/test_config.py | 16 ++--- 8 files changed, 112 insertions(+), 91 deletions(-) create mode 100644 metagpt/context_mixin.py diff --git a/examples/example.pkl b/examples/example.pkl index b7454edeee4a61125ae0fbdb5560f6c8bbfb0d89..caa0cbd31ec5615c929d03bbc05aae73a25f6446 100644 GIT binary patch delta 86 zcmWN^K@ET~3 Config: - """Role config: role config > context config""" - if self._config: - return self._config - return self.context.config - - @config.setter - def config(self, config: Config) -> None: - """Set config""" - self.set_config(config) - - @property - def context(self) -> Context: - """Role context: role context > context""" - if self._context: - return self._context - return CONTEXT - - @context.setter - def context(self, context: Context) -> None: - """Set context""" - self.set_context(context) - - @property - def llm(self) -> BaseLLM: - """Role llm: if not existed, init from role.config""" - # print(f"class:{self.__class__.__name__}({self.name}), llm: {self._llm}, llm_config: {self._llm_config}") - if not self._llm: - self._llm = self.context.llm_with_cost_manager_from_llm_config(self.config.llm) - return self._llm - - @llm.setter - def llm(self, llm: BaseLLM) -> None: - """Set llm""" - self._llm = llm - - # Global context, not in Env CONTEXT = Context() diff --git a/metagpt/context_mixin.py b/metagpt/context_mixin.py new file mode 100644 index 000000000..536620b1a --- /dev/null +++ b/metagpt/context_mixin.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@Time : 2024/1/11 17:25 +@Author : alexanderwu +@File : context_mixin.py +""" +from typing import Optional + +from pydantic import BaseModel, ConfigDict, Field + +from metagpt.config2 import Config +from metagpt.context import CONTEXT, Context +from metagpt.provider.base_llm import BaseLLM + + +class ContextMixin(BaseModel): + """Mixin class for context and config""" + + model_config = ConfigDict(arbitrary_types_allowed=True) + + # Env/Role/Action will use this context as private context, or use self.context as public context + private_context: Optional[Context] = Field(default=None, exclude=True) + # Env/Role/Action will use this config as private config, or use self.context.config as public config + private_config: Optional[Config] = Field(default=None, exclude=True) + + # Env/Role/Action will use this llm as private llm, or use self.context._llm instance + private_llm: Optional[BaseLLM] = Field(default=None, exclude=True) + + def __init__( + self, + context: Optional[Context] = CONTEXT, + config: Optional[Config] = None, + llm: Optional[BaseLLM] = None, + **kwargs, + ): + """Initialize with config""" + super().__init__(**kwargs) + self.set_context(context) + self.set_config(config) + self.set_llm(llm) + + def set(self, k, v, override=False): + """Set attribute""" + if override or not self.__dict__.get(k): + self.__dict__[k] = v + + def set_context(self, context: Context, override=True): + """Set context""" + self.set("_context", context, override) + + def set_config(self, config: Config, override=False): + """Set config""" + self.set("_config", config, override) + + def set_llm(self, llm: BaseLLM, override=False): + """Set llm""" + self.set("_llm", llm, override) + + @property + def config(self) -> Config: + """Role config: role config > context config""" + if self.private_config: + return self.private_config + return self.context.config + + @config.setter + def config(self, config: Config) -> None: + """Set config""" + self.set_config(config) + + @property + def context(self) -> Context: + """Role context: role context > context""" + if self.private_context: + return self.private_context + return CONTEXT + + @context.setter + def context(self, context: Context) -> None: + """Set context""" + self.set_context(context) + + @property + def llm(self) -> BaseLLM: + """Role llm: if not existed, init from role.config""" + # print(f"class:{self.__class__.__name__}({self.name}), llm: {self._llm}, llm_config: {self._llm_config}") + if not self.private_llm: + self.private_llm = self.context.llm_with_cost_manager_from_llm_config(self.config.llm) + return self.private_llm + + @llm.setter + def llm(self, llm: BaseLLM) -> None: + """Set llm""" + self.private_llm = llm diff --git a/metagpt/document_store/base_store.py b/metagpt/document_store/base_store.py index 8228cfab7..ddc1d626b 100644 --- a/metagpt/document_store/base_store.py +++ b/metagpt/document_store/base_store.py @@ -29,7 +29,6 @@ class LocalStore(BaseStore, ABC): def __init__(self, raw_data_path: Path, cache_dir: Path = None): if not raw_data_path: raise FileNotFoundError - self.config = Config() self.raw_data_path = raw_data_path self.fname = self.raw_data_path.stem if not cache_dir: diff --git a/metagpt/roles/role.py b/metagpt/roles/role.py index e467ef83e..a20fe89e5 100644 --- a/metagpt/roles/role.py +++ b/metagpt/roles/role.py @@ -30,7 +30,7 @@ from pydantic import BaseModel, ConfigDict, Field, SerializeAsAny, model_validat from metagpt.actions import Action, ActionOutput from metagpt.actions.action_node import ActionNode from metagpt.actions.add_requirement import UserRequirement -from metagpt.context import ContextMixin +from metagpt.context_mixin import ContextMixin from metagpt.logs import logger from metagpt.memory import Memory from metagpt.provider import HumanProvider diff --git a/tests/data/rsp_cache.json b/tests/data/rsp_cache.json index 25f7ae0b4..9d51334c7 100644 --- a/tests/data/rsp_cache.json +++ b/tests/data/rsp_cache.json @@ -179,5 +179,11 @@ "\n## context\n\n### Project Name\n20240110221009\n\n### Original Requirements\n['开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"zh_cn\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]", "\n## context\n\n### Project Name\n20240110221525\n\n### Original Requirements\n['需要一个基于LLM做总结的搜索引擎']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"zh_cn\",\n \"Programming Language\": \"LLM\",\n \"Original Requirements\": \"需要一个基于LLM做总结的搜索引擎\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]", "\n## context\n\n### Project Name\n20240110221737\n\n### Original Requirements\n['开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"zh_cn\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]", - "\n## context\n\n### Project Name\n20240110221737\n\n### Original Requirements\n['']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]" + "\n## context\n\n### Project Name\n20240110221737\n\n### Original Requirements\n['']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]", + "\n## context\n\n### Project Name\n20240111154514\n\n### Original Requirements\n['需要一个基于LLM做总结的搜索引擎']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"zh_cn\",\n \"Programming Language\": \"LLM\",\n \"Original Requirements\": \"需要一个基于LLM做总结的搜索引擎\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]", + "You are a python code to Mermaid Sequence Diagram translator in function detail#SYSTEM_MSG_END#```python\n#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@Time : 2023/5/23 18:27\n@Author : alexanderwu\n@File : search_engine_serpapi.py\n\"\"\"\nfrom typing import Any, Dict, Optional, Tuple\n\nimport aiohttp\nfrom pydantic import BaseModel, ConfigDict, Field, field_validator\n\nfrom metagpt.config2 import config\n\n\nclass SerpAPIWrapper(BaseModel):\n model_config = ConfigDict(arbitrary_types_allowed=True)\n\n search_engine: Any = None #: :meta private:\n params: dict = Field(\n default_factory=lambda: {\n \"engine\": \"google\",\n \"google_domain\": \"google.com\",\n \"gl\": \"us\",\n \"hl\": \"en\",\n }\n )\n # should add `validate_default=True` to check with default value\n serpapi_api_key: Optional[str] = Field(default=None, validate_default=True)\n aiosession: Optional[aiohttp.ClientSession] = None\n\n @field_validator(\"serpapi_api_key\", mode=\"before\")\n @classmethod\n def check_serpapi_api_key(cls, val: str):\n val = val or config.search.api_key\n if not val:\n raise ValueError(\n \"To use, make sure you provide the serpapi_api_key when constructing an object. Alternatively, \"\n \"ensure that the environment variable SERPAPI_API_KEY is set with your API key. You can obtain \"\n \"an API key from https://serpapi.com/.\"\n )\n return val\n\n async def run(self, query, max_results: int = 8, as_string: bool = True, **kwargs: Any) -> str:\n \"\"\"Run query through SerpAPI and parse result async.\"\"\"\n result = await self.results(query, max_results)\n return self._process_response(result, as_string=as_string)\n\n async def results(self, query: str, max_results: int) -> dict:\n \"\"\"Use aiohttp to run query through SerpAPI and return the results async.\"\"\"\n\n def construct_url_and_params() -> Tuple[str, Dict[str, str]]:\n params = self.get_params(query)\n params[\"source\"] = \"python\"\n params[\"num\"] = max_results\n params[\"output\"] = \"json\"\n url = \"https://serpapi.com/search\"\n return url, params\n\n url, params = construct_url_and_params()\n if not self.aiosession:\n async with aiohttp.ClientSession() as session:\n async with session.get(url, params=params) as response:\n res = await response.json()\n else:\n async with self.aiosession.get(url, params=params) as response:\n res = await response.json()\n\n return res\n\n def get_params(self, query: str) -> Dict[str, str]:\n \"\"\"Get parameters for SerpAPI.\"\"\"\n _params = {\n \"api_key\": self.serpapi_api_key,\n \"q\": query,\n }\n params = {**self.params, **_params}\n return params\n\n @staticmethod\n def _process_response(res: dict, as_string: bool) -> str:\n \"\"\"Process response from SerpAPI.\"\"\"\n # logger.debug(res)\n focus = [\"title\", \"snippet\", \"link\"]\n get_focused = lambda x: {i: j for i, j in x.items() if i in focus}\n\n if \"error\" in res.keys():\n raise ValueError(f\"Got error from SerpAPI: {res['error']}\")\n if \"answer_box\" in res.keys() and \"answer\" in res[\"answer_box\"].keys():\n toret = res[\"answer_box\"][\"answer\"]\n elif \"answer_box\" in res.keys() and \"snippet\" in res[\"answer_box\"].keys():\n toret = res[\"answer_box\"][\"snippet\"]\n elif \"answer_box\" in res.keys() and \"snippet_highlighted_words\" in res[\"answer_box\"].keys():\n toret = res[\"answer_box\"][\"snippet_highlighted_words\"][0]\n elif \"sports_results\" in res.keys() and \"game_spotlight\" in res[\"sports_results\"].keys():\n toret = res[\"sports_results\"][\"game_spotlight\"]\n elif \"knowledge_graph\" in res.keys() and \"description\" in res[\"knowledge_graph\"].keys():\n toret = res[\"knowledge_graph\"][\"description\"]\n elif \"snippet\" in res[\"organic_results\"][0].keys():\n toret = res[\"organic_results\"][0][\"snippet\"]\n else:\n toret = \"No good search result found\"\n\n toret_l = []\n if \"answer_box\" in res.keys() and \"snippet\" in res[\"answer_box\"].keys():\n toret_l += [get_focused(res[\"answer_box\"])]\n if res.get(\"organic_results\"):\n toret_l += [get_focused(i) for i in res.get(\"organic_results\")]\n\n return str(toret) + \"\\n\" + str(toret_l) if as_string else toret_l\n\n\nif __name__ == \"__main__\":\n import fire\n\n fire.Fire(SerpAPIWrapper().run)\n\n```\n\n---\nTranslate the code above into Mermaid Sequence Diagram.": "```mermaid\nsequenceDiagram\n participant SerpAPIWrapper\n participant aiohttp\n participant config\n participant session\n participant response\n participant fire\n\n Note over SerpAPIWrapper: Initialization\n SerpAPIWrapper->>config: get search.api_key\n config-->>SerpAPIWrapper: return search.api_key\n SerpAPIWrapper->>SerpAPIWrapper: check_serpapi_api_key()\n SerpAPIWrapper->>SerpAPIWrapper: get_params()\n SerpAPIWrapper->>SerpAPIWrapper: results()\n SerpAPIWrapper->>aiohttp: ClientSession()\n aiohttp->>session: get(url, params)\n session->>response: json()\n response-->>session: return json response\n session-->>aiohttp: return json response\n aiohttp-->>SerpAPIWrapper: return json response\n SerpAPIWrapper-->>SerpAPIWrapper: _process_response()\n SerpAPIWrapper-->>fire: run()\n```", + "You are a python code to Mermaid Sequence Diagram translator in function detail#SYSTEM_MSG_END#```python\n#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@Time : 2023/5/23 18:27\n@Author : alexanderwu\n@File : search_engine_serpapi.py\n\"\"\"\nimport json\nfrom typing import Any, Dict, Optional, Tuple\n\nimport aiohttp\nfrom pydantic import BaseModel, ConfigDict, Field, field_validator\n\nfrom metagpt.config2 import config\n\n\nclass SerperWrapper(BaseModel):\n model_config = ConfigDict(arbitrary_types_allowed=True)\n\n search_engine: Any = None #: :meta private:\n payload: dict = Field(default_factory=lambda: {\"page\": 1, \"num\": 10})\n serper_api_key: Optional[str] = Field(default=None, validate_default=True)\n aiosession: Optional[aiohttp.ClientSession] = None\n\n @field_validator(\"serper_api_key\", mode=\"before\")\n @classmethod\n def check_serper_api_key(cls, val: str):\n val = val or config.search.api_key\n if not val:\n raise ValueError(\n \"To use, make sure you provide the serper_api_key when constructing an object. Alternatively, \"\n \"ensure that the environment variable SERPER_API_KEY is set with your API key. You can obtain \"\n \"an API key from https://serper.dev/.\"\n )\n return val\n\n async def run(self, query: str, max_results: int = 8, as_string: bool = True, **kwargs: Any) -> str:\n \"\"\"Run query through Serper and parse result async.\"\"\"\n if isinstance(query, str):\n return self._process_response((await self.results([query], max_results))[0], as_string=as_string)\n else:\n results = [self._process_response(res, as_string) for res in await self.results(query, max_results)]\n return \"\\n\".join(results) if as_string else results\n\n async def results(self, queries: list[str], max_results: int = 8) -> dict:\n \"\"\"Use aiohttp to run query through Serper and return the results async.\"\"\"\n\n def construct_url_and_payload_and_headers() -> Tuple[str, Dict[str, str]]:\n payloads = self.get_payloads(queries, max_results)\n url = \"https://google.serper.dev/search\"\n headers = self.get_headers()\n return url, payloads, headers\n\n url, payloads, headers = construct_url_and_payload_and_headers()\n if not self.aiosession:\n async with aiohttp.ClientSession() as session:\n async with session.post(url, data=payloads, headers=headers) as response:\n res = await response.json()\n else:\n async with self.aiosession.get.post(url, data=payloads, headers=headers) as response:\n res = await response.json()\n\n return res\n\n def get_payloads(self, queries: list[str], max_results: int) -> Dict[str, str]:\n \"\"\"Get payloads for Serper.\"\"\"\n payloads = []\n for query in queries:\n _payload = {\n \"q\": query,\n \"num\": max_results,\n }\n payloads.append({**self.payload, **_payload})\n return json.dumps(payloads, sort_keys=True)\n\n def get_headers(self) -> Dict[str, str]:\n headers = {\"X-API-KEY\": self.serper_api_key, \"Content-Type\": \"application/json\"}\n return headers\n\n @staticmethod\n def _process_response(res: dict, as_string: bool = False) -> str:\n \"\"\"Process response from SerpAPI.\"\"\"\n # logger.debug(res)\n focus = [\"title\", \"snippet\", \"link\"]\n\n def get_focused(x):\n return {i: j for i, j in x.items() if i in focus}\n\n if \"error\" in res.keys():\n raise ValueError(f\"Got error from SerpAPI: {res['error']}\")\n if \"answer_box\" in res.keys() and \"answer\" in res[\"answer_box\"].keys():\n toret = res[\"answer_box\"][\"answer\"]\n elif \"answer_box\" in res.keys() and \"snippet\" in res[\"answer_box\"].keys():\n toret = res[\"answer_box\"][\"snippet\"]\n elif \"answer_box\" in res.keys() and \"snippet_highlighted_words\" in res[\"answer_box\"].keys():\n toret = res[\"answer_box\"][\"snippet_highlighted_words\"][0]\n elif \"sports_results\" in res.keys() and \"game_spotlight\" in res[\"sports_results\"].keys():\n toret = res[\"sports_results\"][\"game_spotlight\"]\n elif \"knowledge_graph\" in res.keys() and \"description\" in res[\"knowledge_graph\"].keys():\n toret = res[\"knowledge_graph\"][\"description\"]\n elif \"snippet\" in res[\"organic\"][0].keys():\n toret = res[\"organic\"][0][\"snippet\"]\n else:\n toret = \"No good search result found\"\n\n toret_l = []\n if \"answer_box\" in res.keys() and \"snippet\" in res[\"answer_box\"].keys():\n toret_l += [get_focused(res[\"answer_box\"])]\n if res.get(\"organic\"):\n toret_l += [get_focused(i) for i in res.get(\"organic\")]\n\n return str(toret) + \"\\n\" + str(toret_l) if as_string else toret_l\n\n\nif __name__ == \"__main__\":\n import fire\n\n fire.Fire(SerperWrapper().run)\n\n```\n\n---\nTranslate the code above into Mermaid Sequence Diagram.": "```mermaid\nsequenceDiagram\n participant User\n participant SerperWrapper\n participant aiohttp\n participant config\n\n User ->> SerperWrapper: run(query, max_results, as_string, **kwargs)\n SerperWrapper ->> SerperWrapper: _process_response(response, as_string)\n SerperWrapper ->> SerperWrapper: results(queries, max_results)\n SerperWrapper ->> aiohttp: post(url, data, headers)\n aiohttp ->> SerperWrapper: response\n SerperWrapper ->> User: return result\n SerperWrapper ->> config: search.api_key\n```", + "You are a python code to Mermaid Sequence Diagram translator in function detail#SYSTEM_MSG_END#```python\n#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom __future__ import annotations\n\nimport asyncio\nimport json\nfrom concurrent import futures\nfrom typing import Optional\nfrom urllib.parse import urlparse\n\nimport httplib2\nfrom pydantic import BaseModel, ConfigDict, Field, field_validator\n\nfrom metagpt.config2 import config\nfrom metagpt.logs import logger\n\ntry:\n from googleapiclient.discovery import build\n from googleapiclient.errors import HttpError\nexcept ImportError:\n raise ImportError(\n \"To use this module, you should have the `google-api-python-client` Python package installed. \"\n \"You can install it by running the command: `pip install -e.[search-google]`\"\n )\n\n\nclass GoogleAPIWrapper(BaseModel):\n model_config = ConfigDict(arbitrary_types_allowed=True)\n\n google_api_key: Optional[str] = Field(default=None, validate_default=True)\n google_cse_id: Optional[str] = Field(default=None, validate_default=True)\n loop: Optional[asyncio.AbstractEventLoop] = None\n executor: Optional[futures.Executor] = None\n\n @field_validator(\"google_api_key\", mode=\"before\")\n @classmethod\n def check_google_api_key(cls, val: str):\n val = val or config.search.api_key\n if not val:\n raise ValueError(\n \"To use, make sure you provide the google_api_key when constructing an object. Alternatively, \"\n \"ensure that the environment variable GOOGLE_API_KEY is set with your API key. You can obtain \"\n \"an API key from https://console.cloud.google.com/apis/credentials.\"\n )\n return val\n\n @field_validator(\"google_cse_id\", mode=\"before\")\n @classmethod\n def check_google_cse_id(cls, val: str):\n val = val or config.search.cse_id\n if not val:\n raise ValueError(\n \"To use, make sure you provide the google_cse_id when constructing an object. Alternatively, \"\n \"ensure that the environment variable GOOGLE_CSE_ID is set with your API key. You can obtain \"\n \"an API key from https://programmablesearchengine.google.com/controlpanel/create.\"\n )\n return val\n\n @property\n def google_api_client(self):\n build_kwargs = {\"developerKey\": self.google_api_key}\n if config.proxy:\n parse_result = urlparse(config.proxy)\n proxy_type = parse_result.scheme\n if proxy_type == \"https\":\n proxy_type = \"http\"\n build_kwargs[\"http\"] = httplib2.Http(\n proxy_info=httplib2.ProxyInfo(\n getattr(httplib2.socks, f\"PROXY_TYPE_{proxy_type.upper()}\"),\n parse_result.hostname,\n parse_result.port,\n ),\n )\n service = build(\"customsearch\", \"v1\", **build_kwargs)\n return service.cse()\n\n async def run(\n self,\n query: str,\n max_results: int = 8,\n as_string: bool = True,\n focus: list[str] | None = None,\n ) -> str | list[dict]:\n \"\"\"Return the results of a Google search using the official Google API.\n\n Args:\n query: The search query.\n max_results: The number of results to return.\n as_string: A boolean flag to determine the return type of the results. If True, the function will\n return a formatted string with the search results. If False, it will return a list of dictionaries\n containing detailed information about each search result.\n focus: Specific information to be focused on from each search result.\n\n Returns:\n The results of the search.\n \"\"\"\n loop = self.loop or asyncio.get_event_loop()\n future = loop.run_in_executor(\n self.executor, self.google_api_client.list(q=query, num=max_results, cx=self.google_cse_id).execute\n )\n try:\n result = await future\n # Extract the search result items from the response\n search_results = result.get(\"items\", [])\n\n except HttpError as e:\n # Handle errors in the API call\n logger.exception(f\"fail to search {query} for {e}\")\n search_results = []\n\n focus = focus or [\"snippet\", \"link\", \"title\"]\n details = [{i: j for i, j in item_dict.items() if i in focus} for item_dict in search_results]\n # Return the list of search result URLs\n if as_string:\n return safe_google_results(details)\n\n return details\n\n\ndef safe_google_results(results: str | list) -> str:\n \"\"\"Return the results of a google search in a safe format.\n\n Args:\n results: The search results.\n\n Returns:\n The results of the search.\n \"\"\"\n if isinstance(results, list):\n safe_message = json.dumps([result for result in results])\n else:\n safe_message = results.encode(\"utf-8\", \"ignore\").decode(\"utf-8\")\n return safe_message\n\n\nif __name__ == \"__main__\":\n import fire\n\n fire.Fire(GoogleAPIWrapper().run)\n\n```\n\n---\nTranslate the code above into Mermaid Sequence Diagram.": "```mermaid\nsequenceDiagram\n participant BaseModel\n participant httplib2\n participant asyncio\n participant futures\n participant urlparse\n participant json\n participant config\n participant logger\n participant googleapiclient.discovery\n participant googleapiclient.errors\n participant fire\n\n BaseModel->>ConfigDict: model_config\n BaseModel->>Optional: google_api_key\n BaseModel->>Optional: google_cse_id\n BaseModel->>Optional: loop\n BaseModel->>Optional: executor\n BaseModel->>googleapiclient.discovery: check_google_api_key\n BaseModel->>googleapiclient.discovery: check_google_cse_id\n BaseModel->>googleapiclient.discovery: google_api_client\n BaseModel->>asyncio: run\n asyncio->>futures: run_in_executor\n futures->>googleapiclient.discovery: list\n googleapiclient.discovery->>googleapiclient.discovery: execute\n googleapiclient.discovery-->>futures: result\n futures-->>asyncio: result\n asyncio-->>BaseModel: result\n BaseModel-->>BaseModel: safe_google_results\n BaseModel-->>BaseModel: run\n BaseModel-->>fire: run\n```", + "\n## context\n\n### Project Name\n20240111154819\n\n### Original Requirements\n['开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"zh_cn\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"开发一个基于大语言模型与私有知识库的搜索引擎,希望可以基于大语言模型进行搜索总结\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]", + "\n## context\n\n### Project Name\n20240111154819\n\n### Original Requirements\n['']\n\n### Search Information\n-\n\n\n-----\n\n## format example\n[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"Create a 2048 game\",\n \"Product Goals\": [\n \"Create an engaging user experience\",\n \"Improve accessibility, be responsive\",\n \"More beautiful UI\"\n ],\n \"User Stories\": [\n \"As a player, I want to be able to choose difficulty levels\",\n \"As a player, I want to see my score after each game\",\n \"As a player, I want to get restart button when I lose\",\n \"As a player, I want to see beautiful UI that make me feel good\",\n \"As a player, I want to play game via mobile phone\"\n ],\n \"Competitive Analysis\": [\n \"2048 Game A: Simple interface, lacks responsive features\",\n \"play2048.co: Beautiful and responsive UI with my best score shown\",\n \"2048game.com: Responsive UI with my best score shown, but many ads\"\n ],\n \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Reach and engagement of campaigns\\\"\\n x-axis \\\"Low Reach\\\" --> \\\"High Reach\\\"\\n y-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n quadrant-1 \\\"We should expand\\\"\\n quadrant-2 \\\"Need to promote\\\"\\n quadrant-3 \\\"Re-evaluate\\\"\\n quadrant-4 \\\"May be improved\\\"\\n \\\"Campaign A\\\": [0.3, 0.6]\\n \\\"Campaign B\\\": [0.45, 0.23]\\n \\\"Campaign C\\\": [0.57, 0.69]\\n \\\"Campaign D\\\": [0.78, 0.34]\\n \\\"Campaign E\\\": [0.40, 0.34]\\n \\\"Campaign F\\\": [0.35, 0.78]\\n \\\"Our Target Product\\\": [0.5, 0.6]\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [\n [\n \"P0\",\n \"The main code ...\"\n ],\n [\n \"P0\",\n \"The game algorithm ...\"\n ]\n ],\n \"UI Design draft\": \"Basic function description with a simple style and layout.\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]\n\n## nodes: \": # \"\n- Language: # Provide the language used in the project, typically matching the user's requirement language.\n- Programming Language: # Python/JavaScript or other mainstream programming language.\n- Original Requirements: # Place the original user's requirements here.\n- Product Goals: typing.List[str] # Provide up to three clear, orthogonal product goals.\n- User Stories: typing.List[str] # Provide up to 3 to 5 scenario-based user stories.\n- Competitive Analysis: typing.List[str] # Provide 5 to 7 competitive products.\n- Competitive Quadrant Chart: # Use mermaid quadrantChart syntax. Distribute scores evenly between 0 and 1\n- Requirement Analysis: # Provide a detailed analysis of the requirements.\n- Requirement Pool: typing.List[typing.List[str]] # List down the top-5 requirements with their priority (P0, P1, P2).\n- UI Design draft: # Provide a simple description of UI elements, functions, style, and layout.\n- Anything UNCLEAR: # Mention any aspects of the project that are unclear and try to clarify them.\n\n\n## constraint\nLanguage: Please use the same language as Human INPUT.\nFormat: output wrapped inside [CONTENT][/CONTENT] like format example, nothing else.\n\n## action\nFollow instructions of nodes, generate output and make sure it follows the format example.\n": "[CONTENT]\n{\n \"Language\": \"en_us\",\n \"Programming Language\": \"Python\",\n \"Original Requirements\": \"\",\n \"Product Goals\": [],\n \"User Stories\": [],\n \"Competitive Analysis\": [],\n \"Competitive Quadrant Chart\": \"\",\n \"Requirement Analysis\": \"\",\n \"Requirement Pool\": [],\n \"UI Design draft\": \"\",\n \"Anything UNCLEAR\": \"\"\n}\n[/CONTENT]" } \ No newline at end of file diff --git a/tests/metagpt/test_config.py b/tests/metagpt/test_config.py index 97d84ed09..efd054858 100644 --- a/tests/metagpt/test_config.py +++ b/tests/metagpt/test_config.py @@ -9,7 +9,7 @@ from pydantic import BaseModel from metagpt.config2 import Config from metagpt.configs.llm_config import LLMType -from metagpt.context import ContextMixin +from metagpt.context_mixin import ContextMixin from tests.metagpt.provider.mock_llm_config import ( mock_llm_config, mock_llm_config_proxy, @@ -53,12 +53,12 @@ def test_config_mixin_2(): i = Config(llm=mock_llm_config) j = Config(llm=mock_llm_config_proxy) obj = ModelX(config=i) - assert obj._config == i - assert obj._config.llm == mock_llm_config + assert obj.private_config == i + assert obj.private_config.llm == mock_llm_config obj.set_config(j) # obj already has a config, so it will not be set - assert obj._config == i + assert obj.private_config == i def test_config_mixin_3(): @@ -66,13 +66,13 @@ def test_config_mixin_3(): i = Config(llm=mock_llm_config) j = Config(llm=mock_llm_config_proxy) obj = ModelY(config=i) - assert obj._config == i - assert obj._config.llm == mock_llm_config + assert obj.private_config == i + assert obj.private_config.llm == mock_llm_config obj.set_config(j) # obj already has a config, so it will not be set - assert obj._config == i - assert obj._config.llm == mock_llm_config + assert obj.private_config == i + assert obj.private_config.llm == mock_llm_config assert obj.a == "a" assert obj.b == "b"