mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-15 11:02:36 +02:00
新修改。
This commit is contained in:
parent
f3c7da32a0
commit
9af9461b4f
152 changed files with 7692 additions and 792 deletions
|
|
@ -51,12 +51,12 @@ class Action(ABC):
|
|||
|
||||
@retry(stop=stop_after_attempt(3), wait=wait_fixed(1))
|
||||
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:
|
||||
"""Append default prefix"""
|
||||
if not system_msgs:
|
||||
|
|
|
|||
|
|
@ -40,4 +40,3 @@ class ActionOutput:
|
|||
new_class.__validator_check_name = classmethod(check_name)
|
||||
new_class.__root_validator_check_missing_fields = classmethod(check_missing_fields)
|
||||
return new_class
|
||||
|
||||
|
|
@ -10,5 +10,6 @@ from metagpt.actions import Action
|
|||
|
||||
class BossRequirement(Action):
|
||||
"""Boss Requirement without any implementation details"""
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from pathlib import Path
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
from metagpt.actions.write_code import WriteCode
|
||||
from metagpt.logs import logger
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
"""
|
||||
import re
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.actions.action import Action
|
||||
from metagpt.logs import logger
|
||||
from metagpt.utils.common import CodeParser
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
|
|
@ -24,6 +24,8 @@ The message is as follows:
|
|||
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)
|
||||
|
|
@ -33,17 +35,17 @@ class DebugError(Action):
|
|||
# f"\n\n{error}\n\nPlease try to fix the error in this code."
|
||||
# fixed_code = await self._aask(prompt)
|
||||
# return fixed_code
|
||||
|
||||
|
||||
async def run(self, context):
|
||||
if "PASS" in context:
|
||||
return "", "the original code works fine, no need to debug"
|
||||
|
||||
|
||||
file_name = re.search("## File To Rewrite:\s*(.+\\.py)", context).group(1)
|
||||
|
||||
logger.info(f"Debug and rewrite {file_name}")
|
||||
|
||||
prompt = PROMPT_TEMPLATE.format(context=context)
|
||||
|
||||
|
||||
rsp = await self._aask(prompt)
|
||||
|
||||
code = CodeParser.parse_code(block="", text=rsp)
|
||||
|
|
|
|||
|
|
@ -19,4 +19,3 @@ class DesignReview(Action):
|
|||
|
||||
api_review = await self._aask(prompt)
|
||||
return api_review
|
||||
|
||||
|
|
@ -26,4 +26,3 @@ class DesignFilenames(Action):
|
|||
logger.debug(prompt)
|
||||
logger.debug(design_filenames)
|
||||
return design_filenames
|
||||
|
||||
|
|
@ -6,7 +6,6 @@
|
|||
@File : detail_mining.py
|
||||
"""
|
||||
from metagpt.actions import Action, ActionOutput
|
||||
from metagpt.logs import logger
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
##TOPIC
|
||||
|
|
@ -43,6 +42,7 @@ OUTPUT_MAPPING = {
|
|||
class DetailMining(Action):
|
||||
"""This class allows LLM to further mine noteworthy details based on specific "##TOPIC"(discussion topic) and "##RECORD" (discussion records), thereby deepening the discussion.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ Requirement: Provide a list of questions for the interviewer to ask the intervie
|
|||
Attention: Provide as markdown block as the format above, at least 10 questions.
|
||||
"""
|
||||
|
||||
|
||||
# prepare for a interview
|
||||
|
||||
|
||||
|
|
@ -38,4 +39,3 @@ class PrepareInterview(Action):
|
|||
prompt = PROMPT_TEMPLATE.format(context=context)
|
||||
question_list = await self._aask_v1(prompt)
|
||||
return question_list
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from typing import Callable
|
||||
|
||||
from pydantic import parse_obj_as
|
||||
|
|
@ -60,7 +59,6 @@ a comprehensive summary of the text.
|
|||
{content}
|
||||
'''
|
||||
|
||||
|
||||
CONDUCT_RESEARCH_PROMPT = '''### Reference Information
|
||||
{content}
|
||||
|
||||
|
|
@ -78,12 +76,13 @@ above. The report must meet the following requirements:
|
|||
|
||||
class CollectLinks(Action):
|
||||
"""Action class to collect links from a search engine."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "",
|
||||
*args,
|
||||
rank_func: Callable[[list[str]], None] | None = None,
|
||||
**kwargs,
|
||||
self,
|
||||
name: str = "",
|
||||
*args,
|
||||
rank_func: Callable[[list[str]], None] | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(name, *args, **kwargs)
|
||||
self.desc = "Collect links from a search engine."
|
||||
|
|
@ -91,11 +90,11 @@ class CollectLinks(Action):
|
|||
self.rank_func = rank_func
|
||||
|
||||
async def run(
|
||||
self,
|
||||
topic: str,
|
||||
decomposition_nums: int = 4,
|
||||
url_per_query: int = 4,
|
||||
system_text: str | None = None,
|
||||
self,
|
||||
topic: str,
|
||||
decomposition_nums: int = 4,
|
||||
url_per_query: int = 4,
|
||||
system_text: str | None = None,
|
||||
) -> dict[str, list[str]]:
|
||||
"""Run the action to collect links.
|
||||
|
||||
|
|
@ -120,13 +119,16 @@ class CollectLinks(Action):
|
|||
|
||||
def gen_msg():
|
||||
while True:
|
||||
search_results = "\n".join(f"#### Keyword: {i}\n Search Result: {j}\n" for (i, j) in zip(keywords, results))
|
||||
prompt = SUMMARIZE_SEARCH_PROMPT.format(decomposition_nums=decomposition_nums, search_results=search_results)
|
||||
search_results = "\n".join(
|
||||
f"#### Keyword: {i}\n Search Result: {j}\n" for (i, j) in zip(keywords, results))
|
||||
prompt = SUMMARIZE_SEARCH_PROMPT.format(decomposition_nums=decomposition_nums,
|
||||
search_results=search_results)
|
||||
yield prompt
|
||||
remove = max(results, key=len)
|
||||
remove.pop()
|
||||
if len(remove) == 0:
|
||||
break
|
||||
|
||||
prompt = reduce_message_length(gen_msg(), self.llm.model, system_text, CONFIG.max_tokens_rsp)
|
||||
logger.debug(prompt)
|
||||
queries = await self._aask(prompt, [system_text])
|
||||
|
|
@ -172,11 +174,12 @@ class CollectLinks(Action):
|
|||
|
||||
class WebBrowseAndSummarize(Action):
|
||||
"""Action class to explore the web and provide summaries of articles and webpages."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
browse_func: Callable[[list[str]], None] | None = None,
|
||||
**kwargs,
|
||||
self,
|
||||
*args,
|
||||
browse_func: Callable[[list[str]], None] | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
if CONFIG.model_for_researcher_summary:
|
||||
|
|
@ -188,11 +191,11 @@ class WebBrowseAndSummarize(Action):
|
|||
self.desc = "Explore the web and provide summaries of articles and webpages."
|
||||
|
||||
async def run(
|
||||
self,
|
||||
url: str,
|
||||
*urls: str,
|
||||
query: str,
|
||||
system_text: str = RESEARCH_BASE_SYSTEM,
|
||||
self,
|
||||
url: str,
|
||||
*urls: str,
|
||||
query: str,
|
||||
system_text: str = RESEARCH_BASE_SYSTEM,
|
||||
) -> dict[str, str]:
|
||||
"""Run the action to browse the web and provide summaries.
|
||||
|
||||
|
|
@ -214,7 +217,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,
|
||||
CONFIG.max_tokens_rsp):
|
||||
logger.debug(prompt)
|
||||
summary = await self._aask(prompt, [system_text])
|
||||
if summary == "Not relevant.":
|
||||
|
|
@ -238,16 +242,17 @@ class WebBrowseAndSummarize(Action):
|
|||
|
||||
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
|
||||
|
||||
async def run(
|
||||
self,
|
||||
topic: str,
|
||||
content: str,
|
||||
system_text: str = RESEARCH_BASE_SYSTEM,
|
||||
self,
|
||||
topic: str,
|
||||
content: str,
|
||||
system_text: str = RESEARCH_BASE_SYSTEM,
|
||||
) -> str:
|
||||
"""Run the action to conduct research and generate a research report.
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class RunCode(Action):
|
|||
return stdout.decode("utf-8"), stderr.decode("utf-8")
|
||||
|
||||
async def run(
|
||||
self, code, mode="script", code_file_name="", test_code="", test_file_name="", command=[], **kwargs
|
||||
self, code, mode="script", code_file_name="", test_code="", test_file_name="", command=[], **kwargs
|
||||
) -> str:
|
||||
logger.info(f"Running {' '.join(command)}")
|
||||
if mode == "script":
|
||||
|
|
|
|||
|
|
@ -54,7 +54,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.
|
||||
|
|
@ -140,4 +139,3 @@ class SearchAndSummarize(Action):
|
|||
logger.debug(prompt)
|
||||
logger.debug(result)
|
||||
return result
|
||||
|
||||
|
|
@ -5,13 +5,14 @@
|
|||
@Author : alexanderwu
|
||||
@File : write_code.py
|
||||
"""
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||
|
||||
from metagpt.actions import WriteDesign
|
||||
from metagpt.actions.action import Action
|
||||
from metagpt.const import WORKSPACE_ROOT
|
||||
from metagpt.logs import logger
|
||||
from metagpt.schema import Message
|
||||
from metagpt.utils.common import CodeParser
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
NOTICE
|
||||
|
|
@ -79,4 +80,3 @@ class WriteCode(Action):
|
|||
# code_rsp = await self._aask_v1(prompt, "code_rsp", OUTPUT_MAPPING)
|
||||
# self._save(context, filename, code)
|
||||
return code
|
||||
|
||||
|
|
@ -6,11 +6,12 @@
|
|||
@File : write_code_review.py
|
||||
"""
|
||||
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||
|
||||
from metagpt.actions.action import Action
|
||||
from metagpt.logs import logger
|
||||
from metagpt.schema import Message
|
||||
from metagpt.utils.common import CodeParser
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
NOTICE
|
||||
|
|
@ -79,4 +80,3 @@ class WriteCodeReview(Action):
|
|||
# code_rsp = await self._aask_v1(prompt, "code_rsp", OUTPUT_MAPPING)
|
||||
# self._save(context, filename, code)
|
||||
return code
|
||||
|
||||
|
|
@ -162,9 +162,9 @@ class WriteDocstring(Action):
|
|||
self.desc = "Write docstring for code."
|
||||
|
||||
async def run(
|
||||
self, code: str,
|
||||
system_text: str = PYTHON_DOCSTRING_SYSTEM,
|
||||
style: Literal["google", "numpy", "sphinx"] = "google",
|
||||
self, code: str,
|
||||
system_text: str = PYTHON_DOCSTRING_SYSTEM,
|
||||
style: Literal["google", "numpy", "sphinx"] = "google",
|
||||
) -> str:
|
||||
"""Writes docstrings for the given code and system text in the specified style.
|
||||
|
||||
|
|
@ -202,6 +202,7 @@ def _simplify_python_code(code: str) -> None:
|
|||
if __name__ == "__main__":
|
||||
import fire
|
||||
|
||||
|
||||
async def run(filename: str, overwrite: bool = False, style: Literal["google", "numpy", "sphinx"] = "google"):
|
||||
with open(filename) as f:
|
||||
code = f.read()
|
||||
|
|
@ -211,4 +212,5 @@ if __name__ == "__main__":
|
|||
f.write(code)
|
||||
return code
|
||||
|
||||
|
||||
fire.Fire(run)
|
||||
|
|
|
|||
|
|
@ -25,4 +25,3 @@ class WritePRDReview(Action):
|
|||
prompt = self.prd_review_prompt_template.format(prd=self.prd)
|
||||
review = await self._aask(prompt)
|
||||
return review
|
||||
|
||||
|
|
@ -65,4 +65,3 @@ class WriteContent(Action):
|
|||
"""
|
||||
prompt = CONTENT_PROMPT.format(topic=topic, language=self.language, directory=self.directory)
|
||||
return await self._aask(prompt=prompt)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue