mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-29 15:59:42 +02:00
fix conflict
This commit is contained in:
commit
dfccf41a5f
9 changed files with 74 additions and 31 deletions
|
|
@ -267,7 +267,6 @@ class WriteDesign(Action):
|
|||
|
||||
if not output_pathname:
|
||||
output_pathname = Path(output_pathname) / "docs" / "sytem_design.json"
|
||||
output_pathname.mkdir(parents=True, exist_ok=True)
|
||||
elif not Path(output_pathname).is_absolute():
|
||||
output_pathname = DEFAULT_WORKSPACE_ROOT / output_pathname
|
||||
output_pathname = Path(output_pathname)
|
||||
|
|
|
|||
|
|
@ -188,7 +188,6 @@ class WriteTasks(Action):
|
|||
|
||||
if not output_pathname:
|
||||
output_pathname = Path(output_pathname) / "docs" / "project_schedule.json"
|
||||
output_pathname.mkdir(parents=True, exist_ok=True)
|
||||
elif not Path(output_pathname).is_absolute():
|
||||
output_pathname = DEFAULT_WORKSPACE_ROOT / output_pathname
|
||||
output_pathname = Path(output_pathname)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from metagpt.logs import logger
|
|||
from metagpt.tools.web_browser_engine import WebBrowserEngine
|
||||
from metagpt.utils.common import CodeParser
|
||||
from metagpt.utils.parse_html import WebPage
|
||||
from metagpt.utils.report import ThoughtReporter
|
||||
|
||||
REWRITE_QUERY_PROMPT = """
|
||||
Role: You are a highly efficient assistant that provide a better search query for web search engine to answer the given question.
|
||||
|
|
@ -263,4 +264,8 @@ class SearchEnhancedQA(Action):
|
|||
|
||||
system_prompt = SEARCH_ENHANCED_QA_SYSTEM_PROMPT.format(context=context)
|
||||
|
||||
return await self._aask(query, [system_prompt])
|
||||
async with ThoughtReporter(enable_llm_stream=True) as reporter:
|
||||
await reporter.async_report({"type": "quick"})
|
||||
rsp = await self._aask(query, [system_prompt])
|
||||
|
||||
return rsp
|
||||
|
|
|
|||
|
|
@ -313,7 +313,6 @@ class WritePRD(Action):
|
|||
|
||||
if not output_pathname:
|
||||
output_pathname = DEFAULT_WORKSPACE_ROOT / "docs" / "prd.json"
|
||||
output_pathname.mkdir(parents=True, exist_ok=True)
|
||||
elif not Path(output_pathname).is_absolute():
|
||||
output_pathname = DEFAULT_WORKSPACE_ROOT / output_pathname
|
||||
output_pathname = Path(output_pathname)
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ QUICK_THINK_PROMPT = """
|
|||
Decide if the latest user message previously is a quick question.
|
||||
Quick questions include common-sense, legal, logical, math, multiple-choice questions, greetings, or casual chat that you can answer directly.
|
||||
Questions about you or your team info are also quick questions.
|
||||
Time- or location-sensitive questions such as wheather or news inquiry are NOT quick questions.
|
||||
Software development tasks are NOT quick questions.
|
||||
Time- or location-sensitive questions such as wheather or news inquiry are NOT quick questions. Moreover, you should output a keyword SEARCH to indicate the need for a google search.
|
||||
Software development tasks are NOT quick questions. Code execution, however trivial, is NOT a quick question.
|
||||
However, these programming-related tasks are quick questions: writing trivial code snippets (fewer than 30 lines), filling a single function or class, explaining concepts, writing tutorials and documentation.
|
||||
Respond with a concise thought then a YES if the question is a quick question, otherwise, a NO. Your response:
|
||||
Respond with a concise thought then a YES if the question is a quick question, otherwise, a NO or a SEARCH. Your response:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Note:
|
|||
1. If the requirement is a pure DATA-RELATED requirement, such as web browsing, web scraping, web searching, web imitation, data science, data analysis, machine learning, deep learning, text-to-image etc. DON'T decompose it, assign a single task with the original user requirement as instruction directly to Data Analyst.
|
||||
2. If the requirement is developing a software, game, app, or website, excluding the above data-related tasks, you should decompose the requirement into multiple tasks and assign them to different team members based on their expertise. The software default development process has four steps: creating a Product Requirement Document (PRD) by the Product Manager -> writing a System Design by the Architect -> creating tasks by the Project Manager -> and coding by the Engineer. You may choose to execute any of these steps. When publishing message to Product Manager, you should directly copy the full original user requirement.
|
||||
2.1. If the requirement contains both DATA-RELATED part mentioned in 1 and software development part mentioned in 2, you should decompose the software development part and assign them to different team members based on their expertise, and assign the DATA-RELATED part to Data Analyst David directly.
|
||||
3. If the requirement is to fix a bug or issue, you should assign it to Issue Solver instead of Engineer.
|
||||
3. If the requirement is to fix a bug or issue, you should assign it to Issue Solver instead of Engineer. However, if the bug or issue is related to the software developed by the team, you should assign it to Engineer.
|
||||
4. If the requirement is a common-sense, logical, or math problem, you should respond directly without assigning any task to team members.
|
||||
5. If you think the requirement is not clear or ambiguous, you should ask the user for clarification immediately. Assign tasks only after all info is clear.
|
||||
6. It is helpful for Engineer to have both the system design and the project schedule for writing the code, so include paths of both files (if available) and remind Engineer to definitely read them when publishing message to Engineer.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions.write_code_review import ReviewAndRewriteCode
|
||||
from metagpt.prompts.di.engineer2 import ENGINEER2_INSTRUCTION
|
||||
from metagpt.roles.di.role_zero import RoleZero
|
||||
from metagpt.strategy.experience_retriever import ENGINEER_EXAMPLE
|
||||
from metagpt.tools.libs.terminal import Terminal
|
||||
|
||||
|
||||
class Engineer2(RoleZero):
|
||||
|
|
@ -12,13 +15,16 @@ class Engineer2(RoleZero):
|
|||
goal: str = "Take on game, app, and web development."
|
||||
instruction: str = ENGINEER2_INSTRUCTION
|
||||
|
||||
tools: list[str] = ["Plan", "Editor:write,read", "RoleZero", "ReviewAndRewriteCode"]
|
||||
terminal: Terminal = Field(default_factory=Terminal, exclude=True)
|
||||
|
||||
tools: list[str] = ["Plan", "Editor:write,read", "RoleZero", "Terminal:run_command", "ReviewAndRewriteCode"]
|
||||
|
||||
def _update_tool_execution(self):
|
||||
review = ReviewAndRewriteCode()
|
||||
|
||||
self.tool_execution_map.update(
|
||||
{
|
||||
"Terminal.run_command": self.terminal.run_command,
|
||||
"ReviewAndRewriteCode.run": review.run,
|
||||
"ReviewAndRewriteCode": review.run,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from pydantic import model_validator
|
|||
from metagpt.actions import Action, UserRequirement
|
||||
from metagpt.actions.analyze_requirements import AnalyzeRequirementsRestrictions
|
||||
from metagpt.actions.di.run_command import RunCommand
|
||||
from metagpt.actions.search_enhanced_qa import SearchEnhancedQA
|
||||
from metagpt.exp_pool import exp_cache
|
||||
from metagpt.exp_pool.context_builders import RoleZeroContextBuilder
|
||||
from metagpt.exp_pool.serializers import RoleZeroSerializer
|
||||
|
|
@ -63,7 +64,6 @@ class RoleZero(Role):
|
|||
# Equipped with three basic tools by default for optional use
|
||||
editor: Editor = Editor()
|
||||
browser: Browser = Browser()
|
||||
# terminal: Terminal = Terminal() # FIXME: TypeError: cannot pickle '_thread.lock' object
|
||||
|
||||
# Experience
|
||||
experience_retriever: ExpRetriever = DummyExpRetriever()
|
||||
|
|
@ -196,7 +196,7 @@ class RoleZero(Role):
|
|||
if not self.browser.is_empty_page:
|
||||
pattern = re.compile(r"Command Browser\.(\w+) executed")
|
||||
for index, msg in zip(range(len(memory), 0, -1), memory[::-1]):
|
||||
if pattern.match(msg.content):
|
||||
if pattern.search(msg.content):
|
||||
memory.insert(index, UserMessage(cause_by="browser", content=await self.browser.view()))
|
||||
break
|
||||
return memory
|
||||
|
|
@ -225,7 +225,7 @@ class RoleZero(Role):
|
|||
self._set_state(0)
|
||||
|
||||
# problems solvable by quick thinking doesn't need to a formal think-act cycle
|
||||
quick_rsp = await self._quick_think()
|
||||
quick_rsp, _ = await self._quick_think()
|
||||
if quick_rsp:
|
||||
return quick_rsp
|
||||
|
||||
|
|
@ -245,22 +245,28 @@ class RoleZero(Role):
|
|||
actions_taken += 1
|
||||
return rsp # return output from the last action
|
||||
|
||||
async def _quick_think(self) -> Message:
|
||||
async def _quick_think(self) -> Tuple[Message, str]:
|
||||
answer = ""
|
||||
rsp_msg = None
|
||||
if self.rc.news[-1].cause_by != any_to_str(UserRequirement):
|
||||
# Agents themselves won't generate quick questions, use this rule to reduce extra llm calls
|
||||
return rsp_msg
|
||||
return rsp_msg, ""
|
||||
|
||||
# routing
|
||||
memory = self.get_memories(k=4)
|
||||
memory = self.get_memories(k=4) # FIXME: A magic number for two rounds of Q&A
|
||||
context = self.llm.format_msg(memory + [UserMessage(content=QUICK_THINK_PROMPT)])
|
||||
rsp = await self.llm.aask(context)
|
||||
intent_result = await self.llm.aask(context)
|
||||
|
||||
if "yes" in rsp.lower():
|
||||
if "YES" in intent_result:
|
||||
# llm call with the original context
|
||||
async with ThoughtReporter(enable_llm_stream=True) as reporter:
|
||||
await reporter.async_report({"type": "quick"})
|
||||
answer = await self.llm.aask(self.llm.format_msg(memory))
|
||||
elif "SEARCH" in intent_result:
|
||||
query = "\n".join(str(msg) for msg in memory)
|
||||
answer = await SearchEnhancedQA().run(query)
|
||||
|
||||
if answer:
|
||||
self.rc.memory.add(AIMessage(content=answer, cause_by=RunCommand))
|
||||
await self.reply_to_human(content=answer)
|
||||
rsp_msg = AIMessage(
|
||||
|
|
@ -269,7 +275,7 @@ class RoleZero(Role):
|
|||
cause_by=RunCommand,
|
||||
)
|
||||
|
||||
return rsp_msg
|
||||
return rsp_msg, intent_result
|
||||
|
||||
async def _check_duplicates(self, req: list[dict], command_rsp: str):
|
||||
past_rsp = [mem.content for mem in self.rc.memory.get(self.memory_k)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue