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示例 - 代码团队

总的来说,我们需要三个步骤来建立团队并使其运作:

  1. 定义每个角色能够执行的预期动作
  2. 基于标准作业程序(SOP)确保每个角色遵守它。通过使每个角色观察上游的相应输出结果,并为下游发布自己的输出结果,可以实现这一点。
  3. 初始化所有角色,创建一个带有环境的智能体团队,并使它们之间能够进行交互。

定义三个具有各自动作的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.
'''

参考

MetaGPT day06 Environment组件源码 多智能体辩论的更多相关文章

  1. .NET开发邮件发送功能的全面教程(含邮件组件源码)

    今天,给大家分享的是如何在.NET平台中开发“邮件发送”功能.在网上搜的到的各种资料一般都介绍的比较简单,那今天我想比较细的整理介绍下: 1)         邮件基础理论知识 2)         ...

  2. 浅探element-ui2组件源码之upload

    最近不小心更新了element-ui的版本,已经到了2.1.0,以前修改的源码都失效了. 于是重新尝试下面的指令重新修改: git clone https://github.com/ElemeFE/e ...

  3. Django-restframework 源码之认证组件源码分析

    Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...

  4. element-ui 组件源码分析整理笔记目录

    element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...

  5. element-ui input组件源码分析整理笔记(六)

    input 输入框组件 源码: <template> <div :class="[ type === 'textarea' ? 'el-textarea' : 'el-in ...

  6. element-ui Message组件源码分析整理笔记(八)

    Message组件源码: main.js import Vue from 'vue'; import Main from './main.vue'; import { PopupManager } f ...

  7. element-ui Steps步骤条组件源码分析整理笔记(九)

    Steps步骤条组件源码: steps.vue <template> <!--设置 simple 可应用简洁风格,该条件下 align-center / description / ...

  8. rest_framework解析器组件源码流程

    rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...

  9. Rest_Framework之认证、权限、频率组件源码剖析

    一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...

  10. element-ui Rate组件源码分析整理笔记(十三)

    Rate组件源码比较简单,有添加部分注释 main.vue <template> <!--valuenow当前的评分 valuetext当前显示的文本--> <div c ...

随机推荐

  1. 领域知识图谱-中式菜谱知识图谱:实现知识图谱可视化和知识库智能问答系统(KBQA)

    领域知识图谱-中式菜谱知识图谱:实现知识图谱可视化和知识库智能问答系统(KBQA) A knowledge graph for Chinese cookbook(中式菜谱知识图谱),可以实现知识图谱可 ...

  2. Docker从认识到实践再到底层原理(四-1)|Docker镜像仓库|超详细详解

    前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总 然后就是博主最近最花时间的一 ...

  3. 数据分析(以kaggle上的加州房价为例)

    数据来源:House Prices - Advanced Regression Techniques 参考文献: Comprehensive data exploration with Python ...

  4. MySQL-分区表和分区介绍

    一.MySQL分区简介 1.数据库分区 MySQL是一种常用的关系型数据库管理系统,分区表是一种在MySQL数据库中处理大规模数据的最佳方案之一,其主要目的是为了在特定的SQL操作中减少数据读写的总量 ...

  5. Typora+PicGo+码云Gitee搭建本地博客环境

    Typora+PicGo+码云Gitee搭建本地博客环境 前期准备: 安装Typora 安装链接:https://typora.io/ 安装PicGo 安装链接:https://github.com/ ...

  6. CF1348

    传送门 A: 一个组 \(2^n+2^1+\dots+2^{\frac{n}{2}-1}\),另一个组剩下的. B: 考虑不停循环. 如果不同的数字超过 \(k\),无解. 否则先把原序列去重,然后把 ...

  7. Python树与树算法

    Python树与树算法 树的概念 树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>=1)个有限节点组成一个具 ...

  8. mysql 外键索引入门介绍,为什么工作中很少有人使用?

    背景 以前工作学习中,一直被告诫不要使用外键,所以也没有仔细整理过. 这里记录一下笔记. 外键 是什么? MySQL 的外键(Foreign Key)是一种关系型数据库中用于建立表与表之间关联关系的重 ...

  9. 使用winhex查看FAT16格式结构

    winhex介绍 winhex可以直接查看磁盘二进制信息, 可以比较直观地查看到各种文件系统格式的区别. winhex使用 查看硬盘要管理员权限, 即启动的时候要用邮件管理员权限启动 点击Tools- ...

  10. Java Socket设置timeout几种常用方式总结

    原文链接:https://my.oschina.net/shipley/blog/715196 最近碰到读取第三方提供socket接口需要设置超时时间问题,特此记录一下.原文中有几处拼写错误顺便改掉了 ...