feat: Remove global configuration , enable configuration support for business isolation.

This commit is contained in:
莘权 马 2023-08-20 17:33:13 +08:00
parent d764b8e6fa
commit f45a8e5284
50 changed files with 437 additions and 278 deletions

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 14:43
@Author : alexanderwu
@File : action.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from abc import ABC
from typing import Optional
@ -11,15 +12,14 @@ from typing import Optional
from tenacity import retry, stop_after_attempt, wait_fixed
from metagpt.actions.action_output import ActionOutput
from metagpt.llm import LLM
from metagpt.utils.common import OutputParser
from metagpt.logs import logger
class Action(ABC):
def __init__(self, name: str = '', context=None, llm: LLM = None):
def __init__(self, options, name: str = '', context=None, llm=None):
self.options = options
self.name: str = name
if llm is None:
llm = LLM()
self.llm = llm
self.context = context
self.prefix = ""

View file

@ -4,6 +4,7 @@
@Time : 2023/5/19 12:01
@Author : alexanderwu
@File : analyze_dep_libs.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions import Action
@ -26,8 +27,8 @@ Focus only on the names of shared dependencies, do not add any other explanation
class AnalyzeDepLibs(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name, context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
self.desc = "根据上下文,分析程序运行依赖库"
async def run(self, requirement, filepaths_string):

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 17:46
@Author : alexanderwu
@File : debug_error.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
import re
@ -25,8 +26,8 @@ Now you should start rewriting the code:
## file name of the code to rewrite: Write code with triple quoto. Do your best to implement THIS IN ONLY ONE FILE.
"""
class DebugError(Action):
def __init__(self, name="DebugError", context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="DebugError", context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
# async def run(self, code, error):
# prompt = f"Here is a piece of Python code:\n\n{code}\n\nThe following error occurred during execution:" \

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 19:26
@Author : alexanderwu
@File : design_api.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
import shutil
from pathlib import Path
@ -90,8 +91,8 @@ OUTPUT_MAPPING = {
class WriteDesign(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name, context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=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."
@ -106,15 +107,15 @@ class WriteDesign(Action):
def _save_prd(self, docs_path, resources_path, prd):
prd_file = docs_path / 'prd.md'
quadrant_chart = CodeParser.parse_code(block="Competitive Quadrant Chart", text=prd)
mermaid_to_file(quadrant_chart, resources_path / 'competitive_analysis')
mermaid_to_file(options=self.options, mermaid_code=quadrant_chart, output_file_without_suffix=resources_path / 'competitive_analysis')
logger.info(f"Saving PRD to {prd_file}")
prd_file.write_text(prd)
def _save_system_design(self, docs_path, resources_path, content):
data_api_design = CodeParser.parse_code(block="Data structures and interface definitions", text=content)
seq_flow = CodeParser.parse_code(block="Program call flow", text=content)
mermaid_to_file(data_api_design, resources_path / 'data_api_design')
mermaid_to_file(seq_flow, resources_path / 'seq_flow')
mermaid_to_file(options=self.options, mermaid_code=data_api_design, output_file_without_suffix=resources_path / 'data_api_design')
mermaid_to_file(options=self.options, mermaid_code=seq_flow, output_file_without_suffix=resources_path / 'seq_flow')
system_design_file = docs_path / 'system_design.md'
logger.info(f"Saving System Designs to {system_design_file}")
system_design_file.write_text(content)

View file

@ -4,13 +4,14 @@
@Time : 2023/5/11 19:31
@Author : alexanderwu
@File : design_api_review.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions.action import Action
class DesignReview(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name, context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
async def run(self, prd, api_design):
prompt = f"Here is the Product Requirement Document (PRD):\n\n{prd}\n\nHere is the list of APIs designed " \

View file

@ -4,6 +4,7 @@
@Time : 2023/5/19 11:50
@Author : alexanderwu
@File : design_filenames.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions import Action
from metagpt.logs import logger
@ -15,8 +16,8 @@ Do not add any other explanations, just return a Python string list."""
class DesignFilenames(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name, context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
self.desc = "Based on the PRD, consider system design, and carry out the basic design of the corresponding " \
"APIs, data structures, and database tables. Please give your design, feedback clearly and in detail."

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 19:12
@Author : alexanderwu
@File : project_management.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from typing import List, Tuple
@ -103,8 +104,8 @@ OUTPUT_MAPPING = {
class WriteTasks(Action):
def __init__(self, name="CreateTasks", context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="CreateTasks", context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
def _save(self, context, rsp):
ws_name = CodeParser.parse_str(block="Python package name", text=context[-1].content)

View file

@ -1,5 +1,9 @@
#!/usr/bin/env python
"""
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from __future__ import annotations
import asyncio
@ -9,7 +13,6 @@ from typing import Callable
from pydantic import parse_obj_as
from metagpt.actions import Action
from metagpt.config import CONFIG
from metagpt.logs import logger
from metagpt.tools.search_engine import SearchEngine
from metagpt.tools.web_browser_engine import WebBrowserEngine, WebBrowserEngineType
@ -79,14 +82,15 @@ class CollectLinks(Action):
"""Action class to collect links from a search engine."""
def __init__(
self,
options,
name: str = "",
*args,
rank_func: Callable[[list[str]], None] | None = None,
**kwargs,
):
super().__init__(name, *args, **kwargs)
super().__init__(options=options, name=name, *args, **kwargs)
self.desc = "Collect links from a search engine."
self.search_engine = SearchEngine()
self.search_engine = SearchEngine(options=options)
self.rank_func = rank_func
async def run(
@ -126,7 +130,7 @@ class CollectLinks(Action):
remove.pop()
if len(remove) == 0:
break
prompt = reduce_message_length(gen_msg(), self.llm.model, system_text, CONFIG.max_tokens_rsp)
prompt = reduce_message_length(gen_msg(), self.llm.model, system_text, self.options.get("max_tokens_rsp"))
logger.debug(prompt)
queries = await self._aask(prompt, [system_text])
try:
@ -178,9 +182,10 @@ class WebBrowseAndSummarize(Action):
**kwargs,
):
super().__init__(*args, **kwargs)
if CONFIG.model_for_researcher_summary:
self.llm.model = CONFIG.model_for_researcher_summary
if self.options.get("model_for_researcher_summary"):
self.llm.model = self.options.get("model_for_researcher_summary")
self.web_browser_engine = WebBrowserEngine(
options=self.options,
engine=WebBrowserEngineType.CUSTOM if browse_func else None,
run_func=browse_func,
)
@ -213,7 +218,8 @@ class WebBrowseAndSummarize(Action):
for u, content in zip([url, *urls], contents):
content = content.inner_text
chunk_summaries = []
for prompt in generate_prompt_chunk(content, prompt_template, self.llm.model, system_text, CONFIG.max_tokens_rsp):
for prompt in generate_prompt_chunk(content, prompt_template, self.llm.model, system_text,
self.options.get("max_tokens_rsp")):
logger.debug(prompt)
summary = await self._aask(prompt, [system_text])
if summary == "Not relevant.":
@ -239,8 +245,8 @@ class ConductResearch(Action):
"""Action class to conduct research and generate a research report."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if CONFIG.model_for_researcher_report:
self.llm.model = CONFIG.model_for_researcher_report
if self.options.get("model_for_researcher_report"):
self.llm.model = self.options.get("model_for_researcher_report")
async def run(
self,

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 17:46
@Author : alexanderwu
@File : run_code.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
import os
import subprocess
@ -57,8 +58,8 @@ standard errors: {errs};
class RunCode(Action):
def __init__(self, name="RunCode", context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="RunCode", context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
@classmethod
async def run_text(cls, code) -> Tuple[str, str]:

View file

@ -4,11 +4,11 @@
@Time : 2023/5/23 17:26
@Author : alexanderwu
@File : search_google.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
import pydantic
from metagpt.actions import Action
from metagpt.config import Config
from metagpt.logs import logger
from metagpt.schema import Message
from metagpt.tools.search_engine import SearchEngine
@ -101,17 +101,16 @@ 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
def __init__(self, options, name="", context=None, llm=None, engine=None, search_func=None):
self.engine = engine or options.get("search_engine")
try:
self.search_engine = SearchEngine(self.engine, run_func=search_func)
self.search_engine = SearchEngine(options=options, engine=self.engine, run_func=search_func)
except pydantic.ValidationError:
self.search_engine = None
self.result = ""
super().__init__(name, context, llm)
super().__init__(options=options, name=name, context=context, llm=llm)
async def run(self, context: list[Message], system_text=SEARCH_AND_SUMMARIZE_SYSTEM) -> str:
if self.search_engine is None:

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 17:45
@Author : alexanderwu
@File : write_code.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions import WriteDesign
from metagpt.actions.action import Action
@ -43,8 +44,8 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenc
class WriteCode(Action):
def __init__(self, name="WriteCode", context: list[Message] = None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="WriteCode", context: list[Message] = None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
def _is_invalid(self, filename):
return any(i in filename for i in ["mp3", "wav"])

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 17:45
@Author : alexanderwu
@File : write_code_review.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions.action import Action
@ -62,8 +63,8 @@ FORMAT_EXAMPLE = """
class WriteCodeReview(Action):
def __init__(self, name="WriteCodeReview", context: list[Message] = None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="WriteCodeReview", context: list[Message] = None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
@retry(stop=stop_after_attempt(2), wait=wait_fixed(1))
async def write_code(self, prompt):

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 17:45
@Author : alexanderwu
@File : write_prd.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from typing import List, Tuple
@ -127,11 +128,11 @@ OUTPUT_MAPPING = {
class WritePRD(Action):
def __init__(self, name="", context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="", context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
async def run(self, requirements, *args, **kwargs) -> ActionOutput:
sas = SearchAndSummarize()
sas = SearchAndSummarize(options=self.options, llm=self.llm)
# rsp = await sas.run(context=requirements, system_text=SEARCH_AND_SUMMARIZE_SYSTEM_EN_US)
rsp = ""
info = f"### Search Results\n{sas.result}\n\n### Search Summary\n{rsp}"

View file

@ -4,13 +4,14 @@
@Time : 2023/5/11 17:45
@Author : alexanderwu
@File : write_prd_review.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions.action import Action
class WritePRDReview(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name, context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
self.prd = None
self.desc = "Based on the PRD, conduct a PRD Review, providing clear and detailed feedback"
self.prd_review_prompt_template = """

View file

@ -4,6 +4,7 @@
@Time : 2023/5/11 17:45
@Author : alexanderwu
@File : write_test.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
"""
from metagpt.actions.action import Action
from metagpt.utils.common import CodeParser
@ -30,8 +31,8 @@ you should correctly import the necessary classes based on these file locations!
class WriteTest(Action):
def __init__(self, name="WriteTest", context=None, llm=None):
super().__init__(name, context, llm)
def __init__(self, options, name="WriteTest", context=None, llm=None):
super().__init__(options=options, name=name, context=context, llm=llm)
async def write_code(self, prompt):
code_rsp = await self._aask(prompt)