feat: merge geekan:main

This commit is contained in:
莘权 马 2023-11-27 17:43:20 +08:00
parent d8adba99d4
commit 66fc1b8350
25 changed files with 488 additions and 688 deletions

View file

@ -9,6 +9,7 @@ import asyncio
import fire
from metagpt.llm import LLM
from metagpt.actions import Action
from metagpt.roles import Role
from metagpt.schema import Message
@ -19,19 +20,10 @@ class SimpleWriteCode(Action):
PROMPT_TEMPLATE = """
Write a python function that can {instruction} and provide two runnnable test cases.
Return ```python your_code_here ``` with NO other texts,
example:
```python
# function
def add(a, b):
return a + b
# test cases
print(add(1, 2))
print(add(3, 4))
```
your code:
"""
def __init__(self, name="SimpleWriteCode", context=None, llm=None):
def __init__(self, name: str = "SimpleWriteCode", context=None, llm: LLM = None):
super().__init__(name, context, llm)
async def run(self, instruction: str):
@ -51,8 +43,9 @@ class SimpleWriteCode(Action):
code_text = match.group(1) if match else rsp
return code_text
class SimpleRunCode(Action):
def __init__(self, name="SimpleRunCode", context=None, llm=None):
def __init__(self, name: str = "SimpleRunCode", context=None, llm: LLM = None):
super().__init__(name, context, llm)
async def run(self, code_text: str):
@ -61,6 +54,7 @@ class SimpleRunCode(Action):
logger.info(f"{code_result=}")
return code_result
class SimpleCoder(Role):
def __init__(
self,
@ -73,16 +67,16 @@ class SimpleCoder(Role):
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
todo = self._rc.todo
todo = self._rc.todo # todo will be SimpleWriteCode()
msg = self._rc.memory.get()[-1] # retrieve the latest memory
instruction = msg.content
msg = self.get_memories(k=1)[0] # find the most recent messages
code_text = await SimpleWriteCode().run(instruction)
msg = Message(content=code_text, role=self.profile, cause_by=todo)
code_text = await todo.run(msg.content)
msg = Message(content=code_text, role=self.profile, cause_by=type(todo))
return msg
class RunnableCoder(Role):
def __init__(
self,
@ -92,43 +86,23 @@ class RunnableCoder(Role):
):
super().__init__(name, profile, **kwargs)
self._init_actions([SimpleWriteCode, SimpleRunCode])
async def _think(self) -> None:
if self._rc.todo is None:
self._set_state(0)
return
if self._rc.state + 1 < len(self._states):
self._set_state(self._rc.state + 1)
else:
self._rc.todo = None
self._set_react_mode(react_mode="by_order")
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
# By choosing the Action by order under the hood
# todo will be first SimpleWriteCode() then SimpleRunCode()
todo = self._rc.todo
msg = self._rc.memory.get()[-1]
if isinstance(todo, SimpleWriteCode):
instruction = msg.content
result = await SimpleWriteCode().run(instruction)
msg = self.get_memories(k=1)[0] # find the most k recent messages
result = await todo.run(msg.content)
elif isinstance(todo, SimpleRunCode):
code_text = msg.content
result = await SimpleRunCode().run(code_text)
msg = Message(content=result, role=self.profile, cause_by=todo)
msg = Message(content=result, role=self.profile, cause_by=type(todo))
self._rc.memory.add(msg)
return msg
async def _react(self) -> Message:
while True:
await self._think()
if self._rc.todo is None:
break
await self._act()
return Message(content="All job done", role=self.profile)
def main(msg="write a function that calculates the sum of a list"):
def main(msg="write a function that calculates the product of a list and run it"):
# role = SimpleCoder()
role = RunnableCoder()
logger.info(msg)

View file

@ -7,14 +7,14 @@ import asyncio
import platform
import fire
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from metagpt.actions import Action, BossRequirement
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.logs import logger
class ShoutOut(Action):
"""Action: Shout out loudly in a debate (quarrel)"""
class SpeakAloud(Action):
"""Action: Speak out aloud in a debate (quarrel)"""
PROMPT_TEMPLATE = """
## BACKGROUND
@ -27,7 +27,7 @@ class ShoutOut(Action):
craft a strong and emotional response in 80 words, in {name}'s rhetoric and viewpoints, your will argue:
"""
def __init__(self, name="ShoutOut", context=None, llm=None):
def __init__(self, name="SpeakAloud", context=None, llm=None):
super().__init__(name, context, llm)
async def run(self, context: str, name: str, opponent_name: str):
@ -39,96 +39,57 @@ class ShoutOut(Action):
return rsp
class Trump(Role):
class Debator(Role):
def __init__(
self,
name: str = "Trump",
profile: str = "Republican",
name: str,
profile: str,
opponent_name: str,
**kwargs,
):
super().__init__(name, profile, **kwargs)
self._init_actions([ShoutOut])
self._watch([ShoutOut])
self.name = "Trump"
self.opponent_name = "Biden"
self._init_actions([SpeakAloud])
self._watch([BossRequirement, SpeakAloud])
self.name = name
self.opponent_name = opponent_name
async def _observe(self) -> int:
await super()._observe()
# accept messages sent (from opponent) to self, disregard own messages from the last round
self._rc.news = [msg for msg in self._rc.news if msg.send_to == self.name]
self._rc.news = [msg for msg in self._rc.news if msg.send_to == self.name]
return len(self._rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
todo = self._rc.todo # An instance of SpeakAloud
msg_history = self._rc.memory.get_by_actions([ShoutOut])
context = []
for m in msg_history:
context.append(str(m))
context = "\n".join(context)
memories = self.get_memories()
context = "\n".join(f"{msg.sent_from}: {msg.content}" for msg in memories)
# print(context)
rsp = await ShoutOut().run(context=context, name=self.name, opponent_name=self.opponent_name)
rsp = await todo.run(context=context, name=self.name, opponent_name=self.opponent_name)
msg = Message(
content=rsp,
role=self.profile,
cause_by=ShoutOut,
cause_by=type(todo),
sent_from=self.name,
send_to=self.opponent_name,
)
return msg
class Biden(Role):
def __init__(
self,
name: str = "Biden",
profile: str = "Democrat",
**kwargs,
):
super().__init__(name, profile, **kwargs)
self._init_actions([ShoutOut])
self._watch([BossRequirement, ShoutOut])
self.name = "Biden"
self.opponent_name = "Trump"
async def _observe(self) -> int:
await super()._observe()
# accept the very first human instruction (the debate topic) or messages sent (from opponent) to self,
# disregard own messages from the last round
self._rc.news = [msg for msg in self._rc.news if msg.cause_by == BossRequirement or msg.send_to == self.name]
return len(self._rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
msg_history = self._rc.memory.get_by_actions([BossRequirement, ShoutOut])
context = []
for m in msg_history:
context.append(str(m))
context = "\n".join(context)
rsp = await ShoutOut().run(context=context, name=self.name, opponent_name=self.opponent_name)
msg = Message(
content=rsp,
role=self.profile,
cause_by=ShoutOut,
sent_from=self.name,
send_to=self.opponent_name,
)
self._rc.memory.add(msg)
return msg
async def startup(idea: str, investment: float = 3.0, n_round: int = 5,
code_review: bool = False, run_tests: bool = False):
"""We reuse the startup paradigm for roles to interact with each other.
Now we run a startup of presidents and watch they quarrel. :) """
company = SoftwareCompany()
company.hire([Biden(), Trump()])
company.invest(investment)
company.start_project(idea)
await company.run(n_round=n_round)
async def debate(idea: str, investment: float = 3.0, n_round: int = 5):
"""Run a team of presidents and watch they quarrel. :) """
Biden = Debator(name="Biden", profile="Democrat", opponent_name="Trump")
Trump = Debator(name="Trump", profile="Republican", opponent_name="Biden")
team = Team()
team.hire([Biden, Trump])
team.invest(investment)
team.start_project(idea, send_to="Biden") # send debate topic to Biden and let him speak first
await team.run(n_round=n_round)
def main(idea: str, investment: float = 3.0, n_round: int = 10):
@ -141,7 +102,7 @@ def main(idea: str, investment: float = 3.0, n_round: int = 10):
"""
if platform.system() == "Windows":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(startup(idea, investment, n_round))
asyncio.run(debate(idea, investment, n_round))
if __name__ == '__main__':