mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-15 11:02:36 +02:00
feat: Remove global configuration , enable configuration support for business isolation.
This commit is contained in:
parent
d764b8e6fa
commit
f45a8e5284
50 changed files with 437 additions and 278 deletions
|
|
@ -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 = ""
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:" \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 " \
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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]:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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}"
|
||||
|
|
|
|||
|
|
@ -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 = """
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue