mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-08 15:05:17 +02:00
using streaming api now.
This commit is contained in:
parent
a69f07e62f
commit
1de45add2e
8 changed files with 28 additions and 14 deletions
|
|
@ -12,6 +12,7 @@ from metagpt.actions import Action
|
|||
from metagpt.const import WORKSPACE_ROOT
|
||||
from metagpt.utils.common import CodeParser
|
||||
from metagpt.schema import Message
|
||||
from metagpt.logs import logger
|
||||
from metagpt.utils.mermaid import mermaid_to_file
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
|
|
@ -56,6 +57,7 @@ class WriteDesign(Action):
|
|||
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')
|
||||
logger.info(f"Saving PRD to {prd_file}")
|
||||
prd_file.write_text(prd)
|
||||
|
||||
def _save_system_design(self, docs_path, resources_path, system_design):
|
||||
|
|
@ -64,6 +66,7 @@ class WriteDesign(Action):
|
|||
mermaid_to_file(data_api_design, resources_path / 'data_api_design')
|
||||
mermaid_to_file(seq_flow, 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(system_design)
|
||||
|
||||
def _save(self, context, system_design):
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ class WriteCode(Action):
|
|||
return any(i in filename for i in ["mp3", "wav"])
|
||||
|
||||
def _save(self, context, filename, code_rsp):
|
||||
logger.info(filename)
|
||||
logger.info(code_rsp)
|
||||
# logger.info(filename)
|
||||
# logger.info(code_rsp)
|
||||
if self._is_invalid(filename):
|
||||
return
|
||||
|
||||
|
|
@ -55,9 +55,13 @@ class WriteCode(Action):
|
|||
code_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
code = CodeParser.parse_code(block="", text=code_rsp)
|
||||
code_path.write_text(code)
|
||||
logger.info(f"Saving Code to {code_path}")
|
||||
|
||||
async def run(self, **kwargs):
|
||||
prompt = PROMPT_TEMPLATE.format(**kwargs)
|
||||
filename = kwargs['filename']
|
||||
context = kwargs['context']
|
||||
logger.info(f'Writing {filename}..')
|
||||
code_rsp = await self._aask(prompt)
|
||||
self._save(kwargs['context'], kwargs['filename'], code_rsp)
|
||||
self._save(context, filename, code_rsp)
|
||||
return code_rsp
|
||||
|
|
|
|||
|
|
@ -68,8 +68,9 @@ class WritePRD(Action):
|
|||
sas = SearchAndSummarize()
|
||||
rsp = await sas.run(context=requirements, system_text=SEARCH_AND_SUMMARIZE_SYSTEM_EN_US)
|
||||
info = f"### Search Results\n{sas.result}\n\n### Search Summary\n{rsp}"
|
||||
logger.info(sas.result)
|
||||
logger.info(rsp)
|
||||
if sas.result:
|
||||
logger.info(sas.result)
|
||||
logger.info(rsp)
|
||||
|
||||
prompt = PROMPT_TEMPLATE.format(requirements=requirements, search_information=info)
|
||||
prd = await self._aask(prompt)
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ class BaseGPTAPI(BaseChatbot):
|
|||
message = self._system_msgs(system_msgs) + [self._user_msg(msg)]
|
||||
else:
|
||||
message = [self._default_system_msg(), self._user_msg(msg)]
|
||||
rsp = await self.acompletion(message)
|
||||
rsp = await self.acompletion_text(message, stream=True)
|
||||
logger.debug(message)
|
||||
# logger.debug(rsp)
|
||||
return self.get_choice_text(rsp)
|
||||
return rsp
|
||||
|
||||
def _extract_assistant_rsp(self, context):
|
||||
return "\n".join([i["content"] for i in context if i["role"] == "assistant"])
|
||||
|
|
@ -58,14 +58,14 @@ class BaseGPTAPI(BaseChatbot):
|
|||
rsp_text = self.get_choice_text(rsp)
|
||||
context.append(self._assistant_msg(rsp_text))
|
||||
return self._extract_assistant_rsp(context)
|
||||
|
||||
async def aask_batch(self, msgs: list) -> str:
|
||||
"""Sequential questioning"""
|
||||
context = []
|
||||
for msg in msgs:
|
||||
umsg = self._user_msg(msg)
|
||||
context.append(umsg)
|
||||
rsp = await self.acompletion(context)
|
||||
rsp_text = self.get_choice_text(rsp)
|
||||
rsp_text = await self.acompletion_text(context)
|
||||
context.append(self._assistant_msg(rsp_text))
|
||||
return self._extract_assistant_rsp(context)
|
||||
|
||||
|
|
@ -100,6 +100,10 @@ class BaseGPTAPI(BaseChatbot):
|
|||
]
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
async def acompletion_text(self, messages: list[dict], stream=False) -> str:
|
||||
"""Asynchronous version of completion. Return str. Support stream-print"""
|
||||
|
||||
def get_choice_text(self, rsp: dict) -> str:
|
||||
"""Required to provide the first text of choice"""
|
||||
return rsp.get("choices")[0]["message"]["content"]
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ class OpenAIGPTAPI(BaseGPTAPI, RateLimiter):
|
|||
collected_messages.append(chunk_message) # save the message
|
||||
if "content" in chunk_message:
|
||||
print(chunk_message["content"], end="")
|
||||
print()
|
||||
|
||||
full_reply_content = ''.join([m.get('content', '') for m in collected_messages])
|
||||
return full_reply_content
|
||||
|
|
@ -206,6 +207,7 @@ class OpenAIGPTAPI(BaseGPTAPI, RateLimiter):
|
|||
return await self._achat_completion(messages)
|
||||
|
||||
async def acompletion_text(self, messages: list[dict], stream=False) -> str:
|
||||
"""when streaming, print each token in place."""
|
||||
if stream:
|
||||
return await self._achat_completion_stream(messages)
|
||||
rsp = await self._achat_completion(messages)
|
||||
|
|
|
|||
|
|
@ -150,8 +150,9 @@ class Role:
|
|||
# prompt += ROLE_TEMPLATE.format(name=self.profile, state=self.states[self.state], result=response,
|
||||
# history=self.history)
|
||||
|
||||
logger.info(f"{self._setting}: ready to {self._rc.todo}")
|
||||
response = await self._rc.todo.run(self._rc.important_memory)
|
||||
logger.info(response)
|
||||
# logger.info(response)
|
||||
msg = Message(content=response, role=self.profile, cause_by=type(self._rc.todo))
|
||||
self._rc.memory.add(msg)
|
||||
# logger.debug(f"{response}")
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ def mermaid_to_file(mermaid_code, output_file_without_suffix, width=2048, height
|
|||
"""
|
||||
# Write the Mermaid code to a temporary file
|
||||
tmp = Path(f'{output_file_without_suffix}.mmd')
|
||||
logger.info(tmp)
|
||||
logger.info(str(tmp))
|
||||
tmp.write_text(mermaid_code, encoding='utf-8')
|
||||
|
||||
if check_cmd_exists('mmdc') != 0:
|
||||
|
|
@ -35,6 +33,7 @@ def mermaid_to_file(mermaid_code, output_file_without_suffix, width=2048, height
|
|||
for suffix in ['pdf', 'svg', 'png']:
|
||||
output_file = f'{output_file_without_suffix}.{suffix}'
|
||||
# Call the `mmdc` command to convert the Mermaid code to a PNG
|
||||
logger.info(f"Generating {output_file}..")
|
||||
subprocess.run(['mmdc', '-i', str(tmp), '-o', output_file, '-w', str(width), '-H', str(height)])
|
||||
return 0
|
||||
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ async def startup(idea: str, investment: float = 3.0, n_round: int = 5):
|
|||
await company.run(n_round=n_round)
|
||||
|
||||
|
||||
def main(idea: str, investment: float = 3.0):
|
||||
def main(idea: str, investment: float = 3.0, n_round: int = 5):
|
||||
"""
|
||||
We are a software startup comprised of AI. By investing in us, you are empowering a future filled with limitless possibilities.
|
||||
:param idea: Your innovative idea, such as "Creating a snake game."
|
||||
:param investment: As an investor, you have the opportunity to contribute a certain dollar amount to this AI company.
|
||||
:return:
|
||||
"""
|
||||
asyncio.run(startup(idea, investment))
|
||||
asyncio.run(startup(idea, investment, n_round))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue