update basic code for serialize

This commit is contained in:
stellahsr 2023-11-27 21:12:50 +08:00 committed by better629
parent 949bc747f9
commit c8570036fc
14 changed files with 270 additions and 246 deletions

View file

@ -6,10 +6,9 @@
@File : action.py
"""
from abc import ABC
from typing import Optional
from typing import Optional, Any
from tenacity import retry, stop_after_attempt, wait_random_exponential
from pydantic import BaseModel, Field
from metagpt.actions.action_output import ActionOutput
from metagpt.llm import LLM
@ -20,25 +19,22 @@ from metagpt.utils.utils import general_after_log
from metagpt.utils.utils import import_class
class Action(ABC):
def __init__(self, name: str = "", context=None, llm: LLM = None):
self.name: str = name
if llm is None:
llm = LLM()
self.llm = llm
self.context = context
self.prefix = "" # aask*时会加上prefix作为system_message
self.profile = "" # FIXME: USELESS
self.desc = "" # for skill manager
self.nodes = ...
action_subclass_registry = {}
# Output, useless
# self.content = ""
# self.instruct_content = None
# self.env = None
# def set_env(self, env):
# self.env = env
class Action(BaseModel):
name: str = ""
llm: LLM = Field(default_factory=LLM)
context = None
prefix = "" # aask*时会加上prefix作为system_message
profile = "" # FIXME: USELESS
desc = "" # for skill manager
nodes = None
# content: Optional[str] = None
# instruct_content: Optional[str] = None
def __init__(self, **kwargs: Any):
super().__init__(**kwargs)
def set_prefix(self, prefix, profile):
"""Set prefix for later usage"""
@ -95,27 +91,26 @@ class Action(ABC):
after=general_after_log(logger),
)
async def _aask_v1(
self,
prompt: str,
output_class_name: str,
output_data_mapping: dict,
system_msgs: Optional[list[str]] = None,
format="markdown", # compatible to original format
self,
prompt: str,
output_class_name: str,
output_data_mapping: dict,
system_msgs: Optional[list[str]] = None,
format="markdown", # compatible to original format
) -> ActionOutput:
content = await self.llm.aask(prompt, system_msgs)
logger.debug(f"llm raw output:\n{content}")
output_class = ActionOutput.create_model_class(output_class_name, output_data_mapping)
if format == "json":
parsed_data = llm_output_postprecess(output=content, schema=output_class.schema(), req_key="[/CONTENT]")
else: # using markdown parser
parsed_data = OutputParser.parse_data_with_mapping(content, output_data_mapping)
logger.debug(f"parsed_data:\n{parsed_data}")
logger.debug(parsed_data)
instruct_content = output_class(**parsed_data)
return ActionOutput(content, instruct_content)
async def run(self, *args, **kwargs):
"""Run action"""
raise NotImplementedError("The run method should be implemented in a subclass.")

View file

@ -11,9 +11,12 @@
"""
import json
from pathlib import Path
from typing import Optional
from pydantic import Field
from metagpt.actions import Action, ActionOutput
from metagpt.actions.design_api_an import DESIGN_API_NODE
from metagpt.llm import LLM
from metagpt.config import CONFIG
from metagpt.const import (
DATA_API_DESIGN_FILE_REPO,
@ -25,12 +28,8 @@ from metagpt.const import (
from metagpt.logs import logger
from metagpt.schema import Document, Documents
from metagpt.utils.file_repository import FileRepository
# from metagpt.utils.get_template import get_template
from metagpt.utils.mermaid import mermaid_to_file
# from typing import List
NEW_REQ_TEMPLATE = """
### Legacy Content
@ -42,13 +41,12 @@ NEW_REQ_TEMPLATE = """
class WriteDesign(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
self.desc = (
"Based on the PRD, think about the system design, and design the corresponding APIs, "
"data structures, library tables, processes, and paths. Please provide your design, feedback "
"clearly and in detail."
)
name: str = ""
context: Optional[str] = None
llm: LLM = Field(default_factory=LLM)
desc: str = "Based on the PRD, think about the system design, and design the corresponding APIs, "
"data structures, library tables, processes, and paths. Please provide your design, feedback "
"clearly and in detail."
async def run(self, with_messages, format=CONFIG.prompt_format):
# Use `git diff` to identify which PRD documents have been modified in the `docs/prds` directory.

View file

@ -9,11 +9,15 @@
2. Move the document storage operations related to WritePRD from the save operation of WriteDesign.
3. According to the design in Section 2.2.3.5.4 of RFC 135, add incremental iteration functionality.
"""
import json
from typing import List, Optional, Any
from pydantic import Field
from metagpt.actions import ActionOutput
from metagpt.actions.action import Action
from metagpt.actions.project_management_an import PM_NODE
from metagpt.llm import LLM
from metagpt.config import CONFIG
from metagpt.const import (
PACKAGE_REQUIREMENTS_FILENAME,
@ -24,10 +28,8 @@ from metagpt.const import (
from metagpt.logs import logger
from metagpt.schema import Document, Documents
from metagpt.utils.file_repository import FileRepository
from metagpt.provider.base_gpt_api import BaseGPTAPI
# from typing import List
# from metagpt.utils.get_template import get_template
NEW_REQ_TEMPLATE = """
### Legacy Content
@ -39,8 +41,9 @@ NEW_REQ_TEMPLATE = """
class WriteTasks(Action):
def __init__(self, name="CreateTasks", context=None, llm=None):
super().__init__(name, context, llm)
name: str = "CreateTasks"
context: Optional[str] = None
llm: BaseGPTAPI = Field(default_factory=LLM)
async def run(self, with_messages, format=CONFIG.prompt_format):
system_design_file_repo = CONFIG.git_repo.new_file_repository(SYSTEM_DESIGN_FILE_REPO)

View file

@ -6,12 +6,16 @@
@File : search_google.py
"""
import pydantic
from typing import Optional, Any
from pydantic import BaseModel, Field
from metagpt.actions import Action
from metagpt.llm import LLM
from metagpt.config import Config
from metagpt.logs import logger
from metagpt.schema import Message
from metagpt.tools.search_engine import SearchEngine
from pydantic import root_validator
SEARCH_AND_SUMMARIZE_SYSTEM = """### Requirements
1. Please summarize the latest dialogue based on the reference information (secondary) and dialogue history (primary). Do not include text that is irrelevant to the conversation.
@ -54,7 +58,6 @@ SEARCH_AND_SUMMARIZE_PROMPT = """
"""
SEARCH_AND_SUMMARIZE_SALES_SYSTEM = """## Requirements
1. Please summarize the latest dialogue based on the reference information (secondary) and dialogue history (primary). Do not include text that is irrelevant to the conversation.
- The context is for reference only. If it is irrelevant to the user's search request history, please reduce its reference and usage.
@ -101,23 +104,38 @@ You are a member of a professional butler team and will provide helpful suggesti
class SearchAndSummarize(Action):
def __init__(self, name="", context=None, llm=None, engine=None, search_func=None):
self.config = Config()
self.engine = engine or self.config.search_engine
name: str = ""
content: Optional[str] = None
llm: None = Field(default_factory=LLM)
config: None = Field(default_factory=Config)
engine: Optional[str] = None
search_func: Optional[str] = None
search_engine: SearchEngine = None
try:
self.search_engine = SearchEngine(self.engine, run_func=search_func)
except pydantic.ValidationError:
self.search_engine = None
result = ""
self.result = ""
super().__init__(name, context, llm)
@root_validator
def validate_engine_and_run_func(cls, values):
engine = values.get('engine')
search_func = values.get('search_func')
config = Config()
if engine is None:
engine = config.search_engine
config_data = {
'engine': engine,
'run_func': search_func
}
search_engine = SearchEngine(**config_data)
values['search_engine'] = search_engine
return values
async def run(self, context: list[Message], system_text=SEARCH_AND_SUMMARIZE_SYSTEM) -> str:
if self.search_engine is None:
logger.warning("Configure one of SERPAPI_API_KEY, SERPER_API_KEY, GOOGLE_API_KEY to unlock full feature")
return ""
query = context[-1].content
# logger.debug(query)
rsp = await self.search_engine.run(query)
@ -126,9 +144,9 @@ class SearchAndSummarize(Action):
logger.error("empty rsp...")
return ""
# logger.info(rsp)
system_prompt = [system_text]
prompt = SEARCH_AND_SUMMARIZE_PROMPT.format(
# PREFIX = self.prefix,
ROLE=self.profile,

View file

@ -14,10 +14,17 @@
3. Encapsulate the input of RunCode into RunCodeContext and encapsulate the output of RunCode into
RunCodeResult to standardize and unify parameter passing between WriteCode, RunCode, and DebugError.
"""
import json
from tenacity import retry, stop_after_attempt, wait_random_exponential
from typing import List, Optional, Any
from pydantic import Field
from tenacity import retry, stop_after_attempt, wait_fixed
from metagpt.actions.action import Action
from metagpt.config import CONFIG
from metagpt.const import (
@ -27,6 +34,8 @@ from metagpt.const import (
TASK_FILE_REPO,
TEST_OUTPUTS_FILE_REPO,
)
from metagpt.actions import WriteDesign
from metagpt.llm import LLM
from metagpt.logs import logger
from metagpt.schema import CodingContext, Document, RunCodeResult
from metagpt.utils.common import CodeParser
@ -84,8 +93,9 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenc
class WriteCode(Action):
def __init__(self, name="WriteCode", context=None, llm=None):
super().__init__(name, context, llm)
name: str = "WriteCode"
context: Optional[str] = None
llm: LLM = Field(default_factory=LLM)
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
async def write_code(self, prompt) -> str:

View file

@ -8,9 +8,12 @@
WriteCode object, rather than passing them in when calling the run function.
"""
from typing import List, Optional, Any
from pydantic import Field
from tenacity import retry, stop_after_attempt, wait_random_exponential
from metagpt.actions import WriteCode
from metagpt.llm import LLM
from metagpt.actions.action import Action
from metagpt.config import CONFIG
from metagpt.logs import logger
@ -119,8 +122,9 @@ REWRITE_CODE_TEMPLATE = """
class WriteCodeReview(Action):
def __init__(self, name="WriteCodeReview", context=None, llm=None):
super().__init__(name, context, llm)
name: str = "WriteCodeReview"
context: Optional[str] = None
llm: LLM = Field(default_factory=LLM)
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
async def write_code_review_and_rewrite(self, context_prompt, cr_prompt, filename):

View file

@ -10,10 +10,13 @@
3. Move the document storage operations related to WritePRD from the save operation of WriteDesign.
@Modified By: mashenquan, 2023/12/5. Move the generation logic of the project name to WritePRD.
"""
from __future__ import annotations
import json
from pathlib import Path
from typing import List, Optional, Any
from pydantic import BaseModel, Field
from metagpt.actions import Action, ActionOutput
from metagpt.actions.action_node import ActionNode
@ -23,6 +26,8 @@ from metagpt.actions.write_prd_an import (
WP_ISSUE_TYPE_NODE,
WRITE_PRD_NODE,
)
from metagpt.llm import LLM
from metagpt.actions.search_and_summarize import SearchAndSummarize
from metagpt.config import CONFIG
from metagpt.const import (
BUGFIX_FILENAME,
@ -36,12 +41,8 @@ from metagpt.logs import logger
from metagpt.schema import BugFixContext, Document, Documents, Message
from metagpt.utils.common import CodeParser
from metagpt.utils.file_repository import FileRepository
# from metagpt.utils.get_template import get_template
from metagpt.utils.mermaid import mermaid_to_file
# from typing import List
CONTEXT_TEMPLATE = """
### Project Name
@ -64,8 +65,9 @@ NEW_REQ_TEMPLATE = """
class WritePRD(Action):
def __init__(self, name="", context=None, llm=None):
super().__init__(name, context, llm)
name: str = ""
content: Optional[str] = None
llm: LLM = Field(default_factory=LLM)
async def run(self, with_messages, format=CONFIG.prompt_format, *args, **kwargs) -> ActionOutput | Message:
# Determine which requirement documents need to be rewritten: Use LLM to assess whether new requirements are