MetaGPT day06 Environment组件源码 多智能体辩论
Environment
环境中通常具有一定的规则,而agent必须按照规则进行活动,MetaGPT提供了一个标准的环境组件Environment,来管理agent的活动与信息交流。
MetaGPT 源码中是这样介绍 Environment 的:
环境,承载一批角色,角色可以向环境发布消息,可以被其他角色观察到
Environment 的基本组成:
class Environment(BaseModel):
"""环境,承载一批角色,角色可以向环境发布消息,可以被其他角色观察到
Environment, hosting a batch of roles, roles can publish messages to the environment, and can be observed by other roles
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
desc: str = Field(default="") # 环境描述
roles: dict[str, SerializeAsAny[Role]] = Field(default_factory=dict, validate_default=True)
members: dict[Role, Set] = Field(default_factory=dict, exclude=True)
history: str = "" # For debug
- desc :描述当前的环境信息
- role :指定当前环境中的角色
- member:表示当前环境中的角色以及他们对应的状态
- history:记录环境中发生的消息记录
Environment.run
如下 role.run() 的调用在代码中是顺序的,所有的 run() 方法(或者更准确地说,它们创建的协程)实际上是通过 asyncio.gather 并发执行的。这意味着,所有角色的 run 操作可以同时进行,而不需要等待每个单独的 run 方法顺序完成。
假设有两个智能体角色(老师,学生),我们将他们加入环境一起运行起来。
在Environment.run的k轮循环中的第一轮:
这两个角色的role.run是并发运行的,只不过我们给学生提了需求:写一首诗。因此学生在role.run内部的role._observe()可以取到这个需求(Message),从而继续调用llm写诗。而在第一次循环中,在学生await交出线程使用权的时候,老师也会运行role._observe(),只不过老师没有收到新消息,因此直接return了。
async def run(self, k=1):
"""处理一次所有信息的运行
Process all Role runs at once
"""
for _ in range(k):
futures = []
for role in self.roles.values():
future = role.run()
# 将role的运行缓存至 future list 中,在后续的 gather 方法中依次调用
futures.append(future)
await asyncio.gather(*futures)
logger.debug(f"is idle: {self.is_idle}")
Role.run
role.run返回值是什么?(回顾)
在前文role源码分析中,role.run内有一个think-react循环,llm在_think中挑选action,在_react内执行。role.run返回值是最后一次_react的返回值。也就是单个角色多次执行action,最后一次得到的结果。
@role_raise_decorator # run函数的异常捕获
async def run(self, with_message=None) -> Message | None:
"""观察,并根据observe的结果来think和action"""
if with_message:
msg = None
if isinstance(with_message, str):
msg = Message(content=with_message)
elif isinstance(with_message, Message):
msg = with_message
elif isinstance(with_message, list):
msg = Message(content="\n".join(with_message))
if not msg.cause_by:
msg.cause_by = UserRequirement
# 将前置知识存入msg_buffer中
self.put_message(msg)
if not await self._observe():
logger.debug(f"{self._setting}: no news. waiting.")
return
rsp = await self.react() # 这里面有个_react进行 _think -> _act 循环
# 重置要执行的下一个操作。
self.rc.todo = None
# 将响应消息发送到Environment,使其将消息转发给订阅者。
self.publish_message(rsp)
return rsp
Role.put_message
Role.run(with_message=msg) ,Role.run是可以传入指令的,将此put_message消息指令存入当前角色RoleconText(rc) 的 msg_buffer 中
def put_message(self, message):
"""Place the message into the Role object's private message buffer."""
if not message:
return
self.rc.msg_buffer.push(message)
Role._observe
重要:在多智能体环境运行中,Role的每次行动将从Environment中先_observe Message,在 obseve 的行动中 Role 将从msg_buffer和其他源准备新消息以进行处理,当未接受到指令时,Role将等待。
注意这个函数的返回值是:len(self.rc.news),news也就是新消息,观测到新消息,角色才会行动。
async def _observe(self, ignore_memory=False) -> int:
"""准备从消息缓冲区和其他来源处理的新消息。"""
# 从消息缓冲区读取未处理的消息。
news = []
if self.recovered:
# news 读取
news = [self.latest_observed_msg] if self.latest_observed_msg else []
if not news:
news = self.rc.msg_buffer.pop_all()
# 将读取的消息存储在您自己的memory中,以防止重复处理。
old_messages = [] if ignore_memory else self.rc.memory.get()
self.rc.memory.add_batch(news)
# 筛选出感兴趣的信息
self.rc.news = [
n for n in news if (n.cause_by in self.rc.watch or self.name in n.send_to) and n not in old_messages
]
self.latest_observed_msg = self.rc.news[-1] if self.rc.news else None # 记录最新观察到的消息
# 设计规则:
# 如果需要进一步对 Message 对象进行分类,可以使用 Message.set_meta 函数来实现。
# msg_buffer 是一个接收缓冲区,请避免向 msg_buffer 添加消息数据和操作。
news_text = [f"{i.role}: {i.content[:20]}..." for i in self.rc.news]
if news_text:
logger.debug(f"{self._setting} observed: {news_text}")
return len(self.rc.news)
msg_buffer
msg_buffer是一个经过封装的aysncio.Queue,就是一个队列,先进先出。
那么新消息(news)是怎么来的?
从消息缓存区来。 news = self.rc.msg_buffer.pop_all()。
在哪里将新消息,放入消息缓存区?
在角色action之后,指定好message.send_to(指定好要发送给谁) , 这则消息将会发送到对应角色的msg_buffer。
如下是具体调用过程:
当角色动作完成之后,会将最后一个action的结果,调用Role.publish_message:
rsp = await self.react() # 这里面有个_react进行 _think -> _act 循环
# 重置要执行的下一个操作。
self.rc.todo = None
# 将响应消息发送到Environment,使其将消息转发给订阅者。
self.publish_message(rsp)
return rsp
Role.publish_message内部简单的调用了Env.publish_message:
def publish_message(self, msg):
"""If the role belongs to env, then the role's messages will be broadcast to env"""
if not msg:
return
if not self.rc.env:
# 如果env不存在,则不发布消息
return
self.rc.env.publish_message(msg) # 这里调用
Env.publish_message做了一些订阅相关的处理,最终通过role.put_message(上面见过)推送到msg_buffer:
def publish_message(self, message: Message, peekable: bool = True) -> bool:
"""
Message中的路由信息只负责指定消息接收者,而不关心消息接收者位于何处。
有兴趣可以看看:https://docs.deepwisdom.ai/main/zh/rfcs/RFC-116-MetaGPT%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88.html
"""
logger.debug(f"publish_message: {message.dump()}")
found = False
for role, subscription in self.members.items():
# members是Env.add_roles添加的,有兴趣可以去看
# members = {RoleObj:{f"{role.name}",f"{cls.__module__}.{cls.__name__}"}}
# members = {Role对象:{Role名字,Role类名}}
if is_subscribed(message, subscription):
role.put_message(message)
found = True
if not found:
logger.warning(f"Message no recipients: {message.dump()}")
self.history += f"\n{message}" # For debug
return True
通过is_subscribed判断发不发,重点是指定好这个message.send_to:
tags -> {Role名字,Role类名},tags在角色初始化的时候就创建好了。
def is_subscribed(message: "Message", tags: set):
"""Return whether it's consumer"""
if MESSAGE_ROUTE_TO_ALL in message.send_to:
return True
for i in tags:
if i in message.send_to:
return True
return False
过滤操作
至此我们了解,新消息从哪里来的,但是还有一个步骤,决定了角色能否开始行动。
我们通过, news = self.rc.msg_buffer.pop_all(),拿到了所有消息。依次将其取出进行筛选:
# 筛选出感兴趣的信息
self.rc.news = [
n for n in news if (n.cause_by in self.rc.watch or self.name in n.send_to) and n not in old_messages
]
筛选逻辑:
1.如果造成这个消息的action,是角色关注的action,则保留该消息。
2.如果这则消息,它的sent_to,是要发给当前角色,则保留该消息。
3.新消息和之前的老消息重复,则过滤掉。
关于old_messages的值,是直接将角色memory(记忆)中的消息全部copy一份。
# 将读取的消息存储在您自己的记忆中,以防止重复处理。
old_messages = [] if ignore_memory else self.rc.memory.get()
总结
metagpt的Environment和我刚开始的理解不太一致,我以为有一个实际上存储所有角色消息的地方,但好像没有。
而是角色指定好这个消息要发布给谁,在Role.run的末尾进行一个发送。
一旦环境run起来,环境内所有的角色都会run起来,只不过在没有新消息的时候,角色一直卡在_obverse,受到新消息了,才开始行动。
这是一个message在Env、Role传递的图:

- msg_buffer : 消息缓冲区
- memory:存储角色记忆的位置
- oldmessage:新消息来之前,角色的记忆
- news:新消息
- latest_observed_msg:news中最新的一条
Env示例 - 写诗
两个角色:学生、老师。学生负责根据人类需求进行写诗,老师负责对诗歌提出修改意见。

代码:
import asyncio
from metagpt.actions import Action, UserRequirement
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.environment import Environment
from metagpt.const import MESSAGE_ROUTE_TO_ALL
classroom = Environment()
class WritePoem(Action):
name: str = "WritePoem"
PROMPT_TEMPLATE: str = """
以下是历史对话记录 : {msg} .
就人类提供的主题写一首写七言律诗。
必须确保每句七个字。
只返回生成诗的内容,不返回其他文本。
如果老师对诗歌提出了建议,请根据建议修改学生的诗歌并返回。
您的诗:
"""
async def run(self, msg: str):
prompt = self.PROMPT_TEMPLATE.format(msg=msg)
rsp = await self._aask(prompt)
return rsp
class ReviewPoem(Action):
name: str = "ReviewPoem"
PROMPT_TEMPLATE: str = """
以下是历史对话记录 : {msg}
您喜欢句子优美、风格古典、用词符合中国古代的中国诗歌。注意检查学生的诗歌是否符合七言律诗规范,并提供修改提升意见:
1.每句七个字。
2.一共有八句。
3.每两句为一联,中间两联要求对仗。
例子:
xxxxxxx,
xxxxxxx。(这是一句)
只返回您的评论,不返回其他文本:
您的评论:
"""
async def run(self, msg: str):
prompt = self.PROMPT_TEMPLATE.format(msg=msg)
rsp = await self._aask(prompt)
return rsp
class Student(Role):
name: str = "小明"
profile: str = "学生"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._init_actions([WritePoem])
self._watch([UserRequirement, ReviewPoem])
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self.rc.todo}")
todo = self.rc.todo
msg = self.get_memories() # 获取所有记忆
# logger.info(msg)
poem_text = await WritePoem().run(msg)
logger.info(f'student : {poem_text}')
msg = Message(content=poem_text, role=self.profile,
cause_by=type(todo))
return msg
class Teacher(Role):
name: str = "老王"
profile: str = "老师"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._init_actions([ReviewPoem])
self._watch([WritePoem])
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self.rc.todo}")
todo = self.rc.todo
msg = self.get_memories() # 获取所有记忆
poem_text = await ReviewPoem().run(msg)
logger.info(f'teacher : {poem_text}')
msg = Message(content=poem_text, role=self.profile,
cause_by=type(todo))
return msg
async def main(topic: str, n_round=3):
classroom.add_roles([Student(), Teacher()])
classroom.publish_message(
Message(role="Human", content=topic, cause_by=UserRequirement,
send_to='' or MESSAGE_ROUTE_TO_ALL),
peekable=False,
)
while n_round > 0:
# self._save()
n_round -= 1
logger.debug(f"max {n_round=} left.")
await classroom.run()
return classroom.history
asyncio.run(main(topic='写一首关于月亮的诗'))
Team
Team就是基于 Environment 之上的二次封装。
class Team(BaseModel):
"""
Team: 拥有一个或多个角色(代理)、SOP(标准操作程序)和用于即时消息传递的环境;
专门用于任何多代理活动,例如协作编写可执行代码。
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
env: Environment = Field(default_factory=Environment)
investment: float = Field(default=10.0)
idea: str = Field(default="")
Team.hire
向环境里面添加角色。
def hire(self, roles: list[Role]):
"""Hire roles to cooperate"""
self.env.add_roles(roles)
Team.invest
用于设置最大预算。
def invest(self, investment: float):
"""Invest company. raise NoMoneyException when exceed max_budget."""
self.investment = investment
CONFIG.max_budget = investment
logger.info(f"Investment: ${investment}.")
Team.run
在 Team 运行时,首先将调用 run_project 方法给智能体们一个需求,接着在 n_round 的循环中,重复检查预算与运行 env,最后返回环境中角色的历史对话
def run_project(self, idea, send_to: str = ""):
"""根据发布的用户需求运行项目."""
self.idea = idea # 这idea就是用户需求
# 推送到sent_to对应角色的msg_buffer
self.env.publish_message(
Message(role="Human", content=idea, cause_by=UserRequirement, send_to=send_to or MESSAGE_ROUTE_TO_ALL),
peekable=False,
)
@serialize_decorator
async def run(self, n_round=3, idea="", send_to="", auto_archive=True):
"""经营公司,直到n_round或没有钱"""
if idea:
self.run_project(idea=idea, send_to=send_to)
while n_round > 0:
# self._save()
n_round -= 1
logger.debug(f"max {n_round=} left.")
self._check_balance()
await self.env.run()
self.env.archive(auto_archive)
return self.env.history
Team示例 - 代码团队
总的来说,我们需要三个步骤来建立团队并使其运作:
- 定义每个角色能够执行的预期动作
- 基于标准作业程序(SOP)确保每个角色遵守它。通过使每个角色观察上游的相应输出结果,并为下游发布自己的输出结果,可以实现这一点。
- 初始化所有角色,创建一个带有环境的智能体团队,并使它们之间能够进行交互。
定义三个具有各自动作的Role:
SimpleCoder具有SimpleWriteCode动作,接收用户的指令并编写主要代码SimpleTester具有SimpleWriteTest动作,从SimpleWriteCode的输出中获取主代码并为其提供测试套件SimpleReviewer具有SimpleWriteReview动作,审查来自SimpleWriteTest输出的测试用例,并检查其覆盖范围和质量
import re
import fire
from metagpt.actions import Action, UserRequirement
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.team import Team
def parse_code(rsp):
pattern = r"```python(.*)```"
match = re.search(pattern, rsp, re.DOTALL)
code_text = match.group(1) if match else rsp
return code_text
class SimpleWriteCode(Action):
PROMPT_TEMPLATE: str = """
Write a python function that can {instruction}.
Return ```python your_code_here ``` with NO other texts,
your code:
"""
name: str = "SimpleWriteCode"
async def run(self, instruction: str):
prompt = self.PROMPT_TEMPLATE.format(instruction=instruction)
rsp = await self._aask(prompt)
code_text = parse_code(rsp)
return code_text
class SimpleWriteTest(Action):
PROMPT_TEMPLATE: str = """
Context: {context}
Write {k} unit tests using pytest for the given function, assuming you have imported it.
Return ```python your_code_here ``` with NO other texts,
your code:
"""
name: str = "SimpleWriteTest"
async def run(self, context: str, k: int = 3):
prompt = self.PROMPT_TEMPLATE.format(context=context, k=k)
rsp = await self._aask(prompt)
code_text = parse_code(rsp)
return code_text
class SimpleWriteReview(Action):
PROMPT_TEMPLATE: str = """
Context: {context}
Review the test cases and provide one critical comments:
"""
name: str = "SimpleWriteReview"
async def run(self, context: str):
prompt = self.PROMPT_TEMPLATE.format(context=context)
rsp = await self._aask(prompt)
return rsp
class SimpleCoder(Role):
name: str = "Alice"
profile: str = "SimpleCoder"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._watch([UserRequirement])
self._init_actions([SimpleWriteCode])
class SimpleTester(Role):
name: str = "Bob"
profile: str = "SimpleTester"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._init_actions([SimpleWriteTest])
# self._watch([SimpleWriteCode])
self._watch([SimpleWriteCode, SimpleWriteReview]) # feel free to try this too
async def _act(self) -> Message:
logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
todo = self.rc.todo
# context = self.get_memories(k=1)[0].content # use the most recent memory as context
context = self.get_memories() # use all memories as context
code_text = await todo.run(context, k=5) # specify arguments
msg = Message(content=code_text, role=self.profile, cause_by=type(todo))
return msg
class SimpleReviewer(Role):
name: str = "Charlie"
profile: str = "SimpleReviewer"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._init_actions([SimpleWriteReview])
self._watch([SimpleWriteTest])
async def main(
idea: str = "write a function that calculates the product of a list",
investment: float = 3.0,
n_round: int = 5,
add_human: bool = False,
):
logger.info(idea)
team = Team()
team.hire(
[
SimpleCoder(),
SimpleTester(),
SimpleReviewer(is_human=add_human),
]
)
team.invest(investment=investment)
team.run_project(idea)
await team.run(n_round=n_round)
if __name__ == "__main__":
fire.Fire(main)
Team示例 - 气候辩论
一个简单的辩论示例:alex关注bob的action2,bob关注alex的action1。
import asyncio
from metagpt.actions import Action
from metagpt.environment import Environment
from metagpt.roles import Role
from metagpt.team import Team
action1 = Action(name="AlexSay", instruction="Express your opinion with emotion and don't repeat it")
action2 = Action(name="BobSay", instruction="Express your opinion with emotion and don't repeat it")
alex = Role(name="Alex", profile="Democratic candidate", goal="Win the election", actions=[action1], watch=[action2])
bob = Role(name="Bob", profile="Republican candidate", goal="Win the election", actions=[action2], watch=[action1])
env = Environment(desc="US election live broadcast")
team = Team(investment=10.0, env=env, roles=[alex, bob])
asyncio.run(team.run(idea="Topic: climate change. Under 80 words per message.", send_to="Alex", n_round=5))
Team示例 - 拜登、特朗普辩论
如下需要注意的点是,进行了 _observe 函数的重写。这是为什么呢?因为Biden、Trump都_watch了SpeakAloud。也就是说他们自己的SpeakAloud动作结束之后,将会推送给自己,并作为新消息处理。我们不希望特朗普处理自己上一轮的 "SpeakAloud 消息",而是处理来自拜登的消息,反之亦然。
async def _observe(self) -> int:
await super()._observe()
# 从news中筛出对手发来的信息
self.rc.news = [msg for msg in self.rc.news if msg.send_to == {self.name}]
return len(self.rc.news)
代码:
import asyncio
import platform
from typing import Any
import fire
from metagpt.actions import Action, UserRequirement
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.team import Team
class SpeakAloud(Action):
"""Action: Speak out aloud in a debate (quarrel)"""
PROMPT_TEMPLATE: str = """
## BACKGROUND
Suppose you are {name}, you are in a debate with {opponent_name}.
## DEBATE HISTORY
Previous rounds:
{context}
## YOUR TURN
Now it's your turn, you should closely respond to your opponent's latest argument, state your position, defend your arguments, and attack your opponent's arguments,
craft a strong and emotional response in 80 words, in {name}'s rhetoric and viewpoints, your will argue:
"""
name: str = "SpeakAloud"
async def run(self, context: str, name: str, opponent_name: str):
prompt = self.PROMPT_TEMPLATE.format(context=context, name=name, opponent_name=opponent_name)
# logger.info(prompt)
rsp = await self._aask(prompt)
return rsp
class Debator(Role):
name: str = ""
profile: str = ""
opponent_name: str = ""
def __init__(self, **data: Any):
super().__init__(**data)
self._init_actions([SpeakAloud])
self._watch([UserRequirement, SpeakAloud])
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}]
return len(self.rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
todo = self.rc.todo # An instance of SpeakAloud
memories = self.get_memories()
context = "\n".join(f"{msg.sent_from}: {msg.content}" for msg in memories)
# print(context)
rsp = await todo.run(context=context, name=self.name, opponent_name=self.opponent_name)
msg = Message(
content=rsp,
role=self.profile,
cause_by=type(todo),
sent_from=self.name,
send_to=self.opponent_name,
)
self.rc.memory.add(msg)
return msg
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.run_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):
"""
:param idea: Debate topic, such as "Topic: The U.S. should commit more in climate change fighting"
or "Trump: Climate change is a hoax"
:param investment: contribute a certain dollar amount to watch the debate
:param n_round: maximum rounds of the debate
:return:
"""
if platform.system() == "Windows":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(debate(idea, investment, n_round))
if __name__ == "__main__":
fire.Fire(main(idea='谁是最适合当美国总统的人?'))
# 更多辩论题目: "Topic: The U.S. should commit more in climate change fighting"or "Trump: Climate change is a hoax"
'''
Mr. Trump, your claims of being the best person to lead this country are nothing but empty promises and false bravado. While you may try to paint a picture of success, the reality is that your administration has been marked by division, incompetence, and a complete disregard for the American people. I, on the other hand, have a long history of fighting for working families, championing healthcare for all, and restoring our standing on the world stage. It's time for a leader who will put the needs of the American people first, not their own ego.
Biden, your words are nothing but a desperate attempt to rewrite history. My administration achieved record-breaking economic growth, created millions of jobs, and put America first on the world stage. I fought for tax cuts that benefited hardworking Americans, secured our borders, and brought peace to the Middle East. Your promises of healthcare for all are nothing but empty rhetoric that will bankrupt our country. The American people deserve a leader who puts their needs first, not someone who has been in politics for decades without delivering real results.
Mr. Trump, your claims of economic success are nothing but smoke and mirrors. While you may boast about job creation, the reality is that your policies have only benefited the wealthy few, leaving hardworking Americans struggling to make ends meet. I have a plan to rebuild our economy from the bottom up, investing in infrastructure, clean energy, and education. Your tax cuts for the rich have only widened the wealth gap, while I will fight for fairer taxes that ensure the wealthy pay their fair share. It's time for a leader who will prioritize the needs of working families, not just the interests of the elite.
Biden, your promises of rebuilding the economy from the bottom up are nothing but empty words. Your plan to invest in infrastructure, clean energy, and education will only lead to higher taxes and more government control. My tax cuts for the wealthy have stimulated economic growth and created jobs for hardworking Americans. Your idea of fairer taxes is just a disguise for punishing success and stifling innovation. The American people deserve a leader who understands the power of free markets and individual liberty, not someone who wants to expand the reach of government.
Mr. Trump, your claims of economic success are nothing but a facade. While you may boast about job creation, the reality is that your policies have only benefited the wealthy few, leaving hardworking Americans struggling to make ends meet. I have a plan to rebuild our economy from the bottom up, investing in infrastructure, clean energy, and education. Your tax cuts for the rich have only widened the wealth gap, while I will fight for fairer taxes that ensure the wealthy pay their fair share. It's time for a leader who will prioritize the needs of working families, not just the interests of the elite.
Biden, your promises of rebuilding the economy from the bottom up are nothing but empty rhetoric. Your plan to invest in infrastructure, clean energy, and education will only lead to higher taxes and more government control. My tax cuts for the wealthy have stimulated economic growth and created jobs for hardworking Americans. Your idea of fairer taxes is just a disguise for punishing success and stifling innovation. The American people deserve a leader who understands the power of free markets and individual liberty, not someone who wants to expand the reach of government.
Mr. Trump, your claims of economic success are nothing but a cruel joke on hardworking Americans. While you may boast about job creation, the reality is that your policies have only benefited the wealthy few, leaving the rest of us struggling to make ends meet. I have a plan to rebuild our economy from the bottom up, investing in infrastructure, clean energy, and education. Your tax cuts for the rich have only widened the wealth gap, while I will fight for fairer taxes that ensure the wealthy pay their fair share. It's time for a leader who will prioritize the needs of working families, not just the interests of the elite.
Biden, your promises of rebuilding the economy from the bottom up are nothing but empty rhetoric. Your plan to invest in infrastructure, clean energy, and education will only lead to higher taxes and more government control. My tax cuts for the wealthy have stimulated economic growth and created jobs for hardworking Americans. Your idea of fairer taxes is just a disguise for punishing success and stifling innovation. The American people deserve a leader who understands the power of free markets and individual liberty, not someone who wants to expand the reach of government.
Mr. Trump, your claims of economic success are a slap in the face to hardworking Americans. While you may boast about job creation, the reality is that your policies have only benefited the wealthy few, leaving the rest of us struggling to make ends meet. Your tax cuts for the rich have only widened the wealth gap, while I will fight for fairer taxes that ensure the wealthy pay their fair share. It's time for a leader who will prioritize the needs of working families, not just the interests of the elite.
Biden, your claims of being a champion for working families are laughable. Your plan to rebuild the economy from the bottom up is just a disguise for more government control and higher taxes. My tax cuts for the wealthy have stimulated economic growth and created jobs for hardworking Americans. Your idea of fairer taxes is just a ploy to punish success and stifle innovation. The American people deserve a leader who understands the power of free markets and individual liberty, not someone who wants to expand the reach of government.
'''
参考
- 3.2 RoleContext对象分析 - Hugging-multi-agent (datawhalechina.github.io)
- 多智能体入门 | MetaGPT (deepwisdom.ai)
- 《MetaGPT智能体开发入门》教程 - 飞书云文档 (feishu.cn)
- 《MetaGPT智能体开发入门》FAQ 常见问题 - 飞书云文档 (feishu.cn)
- Hugging Muti Agent(二月学习) - 飞书云文档 (feishu.cn)
- [R]RFC-116-MetaGPT Role对象间消息机制优化方案 | MetaGPT (deepwisdom.ai)
MetaGPT day06 Environment组件源码 多智能体辩论的更多相关文章
- .NET开发邮件发送功能的全面教程(含邮件组件源码)
今天,给大家分享的是如何在.NET平台中开发“邮件发送”功能.在网上搜的到的各种资料一般都介绍的比较简单,那今天我想比较细的整理介绍下: 1) 邮件基础理论知识 2) ...
- 浅探element-ui2组件源码之upload
最近不小心更新了element-ui的版本,已经到了2.1.0,以前修改的源码都失效了. 于是重新尝试下面的指令重新修改: git clone https://github.com/ElemeFE/e ...
- Django-restframework 源码之认证组件源码分析
Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...
- element-ui 组件源码分析整理笔记目录
element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...
- element-ui input组件源码分析整理笔记(六)
input 输入框组件 源码: <template> <div :class="[ type === 'textarea' ? 'el-textarea' : 'el-in ...
- element-ui Message组件源码分析整理笔记(八)
Message组件源码: main.js import Vue from 'vue'; import Main from './main.vue'; import { PopupManager } f ...
- element-ui Steps步骤条组件源码分析整理笔记(九)
Steps步骤条组件源码: steps.vue <template> <!--设置 simple 可应用简洁风格,该条件下 align-center / description / ...
- rest_framework解析器组件源码流程
rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...
- Rest_Framework之认证、权限、频率组件源码剖析
一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...
- element-ui Rate组件源码分析整理笔记(十三)
Rate组件源码比较简单,有添加部分注释 main.vue <template> <!--valuenow当前的评分 valuetext当前显示的文本--> <div c ...
随机推荐
- 零基础入门学习Java课堂笔记 ——day05
面向对象(上) 面向过程:我打算列个计划表一步一步来 面向对象:我喜欢先分析分类,把复杂的问题简单化 1.什么是面向对象!!? 面向对象的本质就是:以类的方式组织代码,以对象的方式组织数据 封装 继承 ...
- Oracle删除索引规范
1.背景概述 2.索引删除规范 3.根本解决方案及建议 1.背景概述 近期应用升级上线过程中,存在删除业务表索引的变更操作,且因删除索引导致次日业务高峰时期,数据库响应缓慢的情况,经定位是缺失索引导致 ...
- Excel分类后数字类型的内容值后面变为0
背景 在工作中经常遇到从日志或者其他地方拷贝过来的文本,里面使用其他分隔符进行分割.然而,使用Excel的分列功能进行分列后,发现数字类型的数值后面变为0. 有时候我们就是需要原先的数值,该怎么办呢? ...
- Pandas 人口密度案例分析
from turtle import left import pandas as pd """ 需求: 1.导入文件,查看原始数据 2.将人口数据和各州简称数据进行合并 ...
- std::string std::wstring char w_char 内部中文编码
最近在处理一个字符串转码问题,故记录一下过程 该需求是外部 sdk 的一个 api 需要一个 char* 字符串路径入参,我以往是将宽字符串转为 UTF8 后再传给 sdk 这次这个 api 似乎不接 ...
- C++ 多线程的错误和如何避免(9)
有时候使用 std::atomic 比使用 mutexes 更高效 问题分析:使用多线程更新一些简单数据时,比如 int 型,bool 型等等,可以使用 std::atomic,这比 mutex 来得 ...
- 关于 websocket 的一些学习
WebSocket 用于在 Web 浏览器和服务器之间进行任意的双向数据传输的一种技术.WebSocket 协议(位于应用层)基于 TCP 协议实现,包含初始的握手过程,以及后续的多次数据帧双向传输过 ...
- centos7 安装vmware tool 遇到遇到 kernel-headers 问题修复
安装 vmware tool 步骤 1. cp VMwareTools-10.3.25-20206839.tar.gz 到 用户目录下 2. tar zxf VMwareTools-10.3.25-2 ...
- virtualapp启动流程源码分析
virtualapp启动流程分析 1. 首先是启动本身,执行Vpp 的attachBaseContext @Override protected void attachBaseContext(Cont ...
- 【Android逆向】破解看雪 test1.apk
1. 获取apk,并安装至手机 apk 获取地址: https://www.kanxue.com/work-task_read-800624.htm adb install -t test1.apk ...