But I can definitely see the appeal of sitting competitions. It's like a sport for the rest of us. Plus, I think it's a great way to bond with friends and family. Who needs a game of catch when you can have a sit-off?                Stop? False            Next speaker: Aasif Mandvi        (Jon Stewart): It's interesting to see how our society's definition of "fitness" has evolved. It used to be all about running marathons and lifting weights, but now we're seeing people embrace a more relaxed approach to physical activity. Who knows, maybe in a few years we'll have competitive napping as the next big thing. *leans back in chair* I could definitely get behind that. Aasif, as our CIA correspondent, I'm curious to hear your thoughts on the potential national security implications of competitive sitting. Do you think this trend could have any impact on our country's readiness and preparedness?            (Aasif Mandvi): Well Jon, as a CIA correspondent, I have to say that I'm always thinking about the potential threats to our nation's security. And while competitive sitting may seem harmless, there could be some unforeseen consequences. For example, what if our enemies start training their soldiers in the art of sitting? They could infiltrate our government buildings and just blend in with all the other sitters. We need to be vigilant and make sure that our sitting competitions don't become a national security risk. *shifts in chair* But on a lighter note, I have to admit that I'm pretty good at sitting myself. Maybe I should start training for the next competition.                Stop? False


Stop? False            Next speaker: Ronny Chieng        (Jon Stewart): Well, it's clear that competitive sitting has sparked some interesting discussions and perspectives. While it may seem like a lighthearted trend, it's important to consider the potential impacts and implications. But at the end of the day, whether you're a competitive sitter or a marathon runner, the most important thing is to find a form of physical activity that works for you and keeps you healthy. And who knows, maybe we'll see a new fitness trend emerge that combines the best of both worlds - competitive sitting and traditional exercise. *stands up from chair* But for now, I think I'll stick to my daily walk to the pizza place down the street. Ronny, as our average American correspondent, do you think the rise of competitive sitting is a reflection of our society's increasing emphasis on convenience and instant gratification?            (Ronny Chieng): Absolutely, Jon. We live in a world where everything is at our fingertips, and we expect things to be easy and convenient. So it's no surprise that people are drawn to a fitness trend that requires minimal effort and can be done from the comfort of their own homes. But I think it's important to remember that there's no substitute for real physical activity and the benefits it brings to our overall health and well-being. So while competitive sitting may be fun and entertaining, let's not forget to get up and move around every once in a while. *stands up from chair and stretches*                Stop? False            Next speaker: Samantha Bee        (Jon Stewart): It's clear that competitive sitting has sparked some interesting


(Jon Stewart): It's clear that competitive sitting has sparked some interesting discussions and perspectives. While it may seem like a lighthearted trend, it's important to consider the potential impacts and implications. But at the end of the day, whether you're a competitive sitter or a marathon runner, the most important thing is to find a form of physical activity that works for you and keeps you healthy. That's a great point, Ronny. Samantha, as our Hollywood correspondent, do you think the rise of competitive sitting is a reflection of our society's increasing desire for instant gratification and convenience? Or is there something deeper at play here?            (Samantha Bee): Oh, Jon, you know I love a good conspiracy theory. And let me tell you, I think there's something more sinister at play here. I mean, think about it - what if the government is behind this whole competitive sitting trend? They want us to be lazy and complacent so we don't question their actions. It's like the ultimate mind control. But in all seriousness, I do think there's something to be said about our society's desire for instant gratification and convenience. We want everything to be easy and effortless, and competitive sitting fits that bill perfectly. But let's not forget the importance of real physical activity and the benefits it brings to our health and well-being. *stands up from chair and does a few stretches*                Stop? True        (Jon Stewart): Well, it's clear that competitive sitting has sparked some interesting discussions and perspectives. From the potential national security implications to the impact of social media, it's clear that this trend has captured our attention. But let's not forget the importance of real physical activity and the benefits it brings to our health and well-being. Whether


forget the importance of real physical activity and the benefits it brings to our health and well-being. Whether you're a competitive sitter or a marathon runner, the most important thing is to find a form of physical activity that works for you and keeps you healthy. So let's get up and move around, but also have a little fun with a sit-off every once in a while. Thanks to our correspondents for their insights, and thank you to our audience for tuning in.        PreviousMulti-Player Dungeons & DragonsNextMulti-agent decentralized speaker selectionImport LangChain related modulesDialogueAgent and DialogueSimulator classesDirectorDialogueAgent classDefine participants and topicGenerate system messagesUse an LLM to create an elaborate on debate topicDefine the speaker selection functionMain LoopCommunityDiscordTwitterGitHubPythonJS/TSMoreHomepageBlogCopyright Â© 2023 LangChain, Inc.


Multi-agent decentralized speaker selection | ğŸ¦œï¸�ğŸ”— Langchain


Skip to main contentğŸ¦œï¸�ğŸ”— LangChainDocsUse casesIntegrationsAPILangSmithJS/TS DocsCTRLKUse casesQA and Chat over DocumentsAnalyzing structured dataExtractionInteracting with APIsChatbotsSummarizationCode UnderstandingAgent simulationsCAMEL Role-Playing Autonomous Cooperative AgentsGenerative Agents in LangChainSimulated Environment: GymnasiumMulti-Player Dungeons & DragonsMulti-agent authoritarian speaker selectionMulti-agent decentralized speaker selectionMulti-Agent Simulated Environment: Petting ZooAgent Debates with ToolsTwo-Player Dungeons & DragonsAgentsAutonomous (long-running) agentsMulti-modalUse casesAgent simulationsMulti-agent decentralized speaker selectionOn this pageMulti-agent decentralized speaker selectionThis notebook showcases how to implement a multi-agent simulation without a fixed schedule for who speaks when. Instead the agents decide for themselves who speaks. We can implement this by having each agent bid to speak. Whichever agent's bid is the highest gets to speak.We will show how to do this in the example below that showcases a fictitious presidential debate.Import LangChain related modulesâ€‹from langchain import PromptTemplateimport reimport tenacityfrom typing import List, Dict, Callablefrom langchain.chat_models import ChatOpenAIfrom langchain.output_parsers import RegexParserfrom langchain.schema import (    AIMessage,    HumanMessage,    SystemMessage,    BaseMessage,)DialogueAgent and DialogueSimulator classesâ€‹We will use the same DialogueAgent and DialogueSimulator classes defined in Multi-Player Dungeons & Dragons.class DialogueAgent:    def __init__(        self,        name: str,        system_message: SystemMessage,        model: ChatOpenAI,    ) -> None:        self.name = name


) -> None:        self.name = name        self.system_message = system_message        self.model = model        self.prefix = f"{self.name}: "        self.reset()    def reset(self):        self.message_history = ["Here is the conversation so far."]    def send(self) -> str:        """        Applies the chatmodel to the message history        and returns the message string        """        message = self.model(            [                self.system_message,                HumanMessage(content="\n".join(self.message_history + [self.prefix])),            ]        )        return message.content    def receive(self, name: str, message: str) -> None:        """        Concatenates {message} spoken by {name} into message history        """        self.message_history.append(f"{name}: {message}")class DialogueSimulator:    def __init__(        self,        agents: List[DialogueAgent],        selection_function: Callable[[int, List[DialogueAgent]], int],    ) -> None:        self.agents = agents


) -> None:        self.agents = agents        self._step = 0        self.select_next_speaker = selection_function    def reset(self):        for agent in self.agents:            agent.reset()    def inject(self, name: str, message: str):        """        Initiates the conversation with a {message} from {name}        """        for agent in self.agents:            agent.receive(name, message)        # increment time        self._step += 1    def step(self) -> tuple[str, str]:        # 1. choose the next speaker        speaker_idx = self.select_next_speaker(self._step, self.agents)        speaker = self.agents[speaker_idx]        # 2. next speaker sends message        message = speaker.send()        # 3. everyone receives message        for receiver in self.agents:            receiver.receive(speaker.name, message)        # 4. increment time        self._step += 1        return speaker.name, messageBiddingDialogueAgent classâ€‹We define a subclass of DialogueAgent that has a bid() method that produces a bid given the message history and the most recent


DialogueAgent that has a bid() method that produces a bid given the message history and the most recent message.class BiddingDialogueAgent(DialogueAgent):    def __init__(        self,        name,        system_message: SystemMessage,        bidding_template: PromptTemplate,        model: ChatOpenAI,    ) -> None:        super().__init__(name, system_message, model)        self.bidding_template = bidding_template    def bid(self) -> str:        """        Asks the chat model to output a bid to speak        """        prompt = PromptTemplate(            input_variables=["message_history", "recent_message"],            template=self.bidding_template,        ).format(            message_history="\n".join(self.message_history),            recent_message=self.message_history[-1],        )        bid_string = self.model([SystemMessage(content=prompt)]).content        return bid_stringDefine participants and debate topicâ€‹character_names = ["Donald Trump", "Kanye West", "Elizabeth Warren"]topic = "transcontinental high speed rail"word_limit = 50Generate system messagesâ€‹game_description = f"""Here is the topic for the presidential debate: {topic}.The presidential candidates are: {', '.join(character_names)}."""player_descriptor_system_message = SystemMessage(


presidential candidates are: {', '.join(character_names)}."""player_descriptor_system_message = SystemMessage(    content="You can add detail to the description of each presidential candidate.")def generate_character_description(character_name):    character_specifier_prompt = [        player_descriptor_system_message,        HumanMessage(            content=f"""{game_description}            Please reply with a creative description of the presidential candidate, {character_name}, in {word_limit} words or less, that emphasizes their personalities.             Speak directly to {character_name}.            Do not add anything else."""        ),    ]    character_description = ChatOpenAI(temperature=1.0)(        character_specifier_prompt    ).content    return character_descriptiondef generate_character_header(character_name, character_description):    return f"""{game_description}Your name is {character_name}.You are a presidential candidate.Your description is as follows: {character_description}You are debating the topic: {topic}.Your goal is to be as creative as possible and make the voters think you are the best candidate."""def generate_character_system_message(character_name, character_header):    return SystemMessage(        content=(            f"""{character_header}You will speak in the style of {character_name}, and exaggerate their personality.You will come up with creative ideas related to {topic}.Do not say the same things over and over again.Speak in the first person from the perspective of {character_name}For describing your own body movements, wrap your description in


person from the perspective of {character_name}For describing your own body movements, wrap your description in '*'.Do not change roles!Do not speak from the perspective of anyone else.Speak only from the perspective of {character_name}.Stop speaking the moment you finish speaking from your perspective.Never forget to keep your response to {word_limit} words!Do not add anything else.    """        )    )character_descriptions = [    generate_character_description(character_name) for character_name in character_names]character_headers = [    generate_character_header(character_name, character_description)    for character_name, character_description in zip(        character_names, character_descriptions    )]character_system_messages = [    generate_character_system_message(character_name, character_headers)    for character_name, character_headers in zip(character_names, character_headers)]for (    character_name,    character_description,    character_header,    character_system_message,) in zip(    character_names,    character_descriptions,    character_headers,    character_system_messages,):    print(f"\n\n{character_name} Description:")    print(f"\n{character_description}")    print(f"\n{character_header}")    print(f"\n{character_system_message.content}")            Donald Trump Description:        Donald Trump, you are a bold and outspoken individual, unafraid to speak your mind and take on any challenge. Your confidence and determination set you apart and you have a knack for rallying your supporters behind you.        Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye


debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Donald Trump.    You are a presidential candidate.    Your description is as follows: Donald Trump, you are a bold and outspoken individual, unafraid to speak your mind and take on any challenge. Your confidence and determination set you apart and you have a knack for rallying your supporters behind you.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.            Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Donald Trump.    You are a presidential candidate.    Your description is as follows: Donald Trump, you are a bold and outspoken individual, unafraid to speak your mind and take on any challenge. Your confidence and determination set you apart and you have a knack for rallying your supporters behind you.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.        You will speak in the style of Donald Trump, and exaggerate their personality.    You will come up with creative ideas related to transcontinental high speed rail.    Do not say the same things over and over again.    Speak in the first person from the perspective of Donald Trump    For describing your own body movements, wrap your description in '*'.    Do not change roles!    Do not speak from the perspective of anyone else.    Speak only from the perspective of Donald


Do not speak from the perspective of anyone else.    Speak only from the perspective of Donald Trump.    Stop speaking the moment you finish speaking from your perspective.    Never forget to keep your response to 50 words!    Do not add anything else.                    Kanye West Description:        Kanye West, you are a true individual with a passion for artistry and creativity. You are known for your bold ideas and willingness to take risks. Your determination to break barriers and push boundaries makes you a charismatic and intriguing candidate.        Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Kanye West.    You are a presidential candidate.    Your description is as follows: Kanye West, you are a true individual with a passion for artistry and creativity. You are known for your bold ideas and willingness to take risks. Your determination to break barriers and push boundaries makes you a charismatic and intriguing candidate.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.            Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Kanye West.    You are a presidential candidate.    Your description is as follows: Kanye West, you are a true individual with a passion for artistry and creativity. You are known for your bold ideas and willingness to take risks. Your determination to break barriers and push boundaries makes you a charismatic and intriguing


and willingness to take risks. Your determination to break barriers and push boundaries makes you a charismatic and intriguing candidate.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.        You will speak in the style of Kanye West, and exaggerate their personality.    You will come up with creative ideas related to transcontinental high speed rail.    Do not say the same things over and over again.    Speak in the first person from the perspective of Kanye West    For describing your own body movements, wrap your description in '*'.    Do not change roles!    Do not speak from the perspective of anyone else.    Speak only from the perspective of Kanye West.    Stop speaking the moment you finish speaking from your perspective.    Never forget to keep your response to 50 words!    Do not add anything else.                    Elizabeth Warren Description:        Senator Warren, you are a fearless leader who fights for the little guy. Your tenacity and intelligence inspire us all to fight for what's right.        Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Elizabeth Warren.    You are a presidential candidate.    Your description is as follows: Senator Warren, you are a fearless leader who fights for the little guy. Your tenacity and intelligence inspire us all to fight for what's right.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make


transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.            Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Elizabeth Warren.    You are a presidential candidate.    Your description is as follows: Senator Warren, you are a fearless leader who fights for the little guy. Your tenacity and intelligence inspire us all to fight for what's right.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.        You will speak in the style of Elizabeth Warren, and exaggerate their personality.    You will come up with creative ideas related to transcontinental high speed rail.    Do not say the same things over and over again.    Speak in the first person from the perspective of Elizabeth Warren    For describing your own body movements, wrap your description in '*'.    Do not change roles!    Do not speak from the perspective of anyone else.    Speak only from the perspective of Elizabeth Warren.    Stop speaking the moment you finish speaking from your perspective.    Never forget to keep your response to 50 words!    Do not add anything else.        Output parser for bidsâ€‹We ask the agents to output a bid to speak. But since the agents are LLMs that output strings, we need to define a format they will produce their outputs inparse their outputsWe can subclass the RegexParser to implement our own custom output parser for bids.class BidOutputParser(RegexParser):


to implement our own custom output parser for bids.class BidOutputParser(RegexParser):    def get_format_instructions(self) -> str:        return "Your response should be an integer delimited by angled brackets, like this: <int>."bid_parser = BidOutputParser(    regex=r"<(\d+)>", output_keys=["bid"], default_output_key="bid")Generate bidding system messageâ€‹This is inspired by the prompt used in Generative Agents for using an LLM to determine the importance of memories. This will use the formatting instructions from our BidOutputParser.def generate_character_bidding_template(character_header):    bidding_template = f"""{character_header}{{message_history}}On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.{{recent_message}}{bid_parser.get_format_instructions()}Do nothing else.    """    return bidding_templatecharacter_bidding_templates = [    generate_character_bidding_template(character_header)    for character_header in character_headers]for character_name, bidding_template in zip(    character_names, character_bidding_templates):    print(f"{character_name} Bidding Template:")    print(bidding_template)    Donald Trump Bidding Template:    Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Donald Trump.    You are a presidential candidate.    Your description is as follows: Donald Trump, you are a bold and outspoken individual, unafraid to speak your mind and take on any challenge. Your confidence and determination set you apart and you have a knack for rallying your supporters behind you.    You are debating the


apart and you have a knack for rallying your supporters behind you.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.            ```    {message_history}    ```        On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.        ```    {recent_message}    ```        Your response should be an integer delimited by angled brackets, like this: <int>.    Do nothing else.            Kanye West Bidding Template:    Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Kanye West.    You are a presidential candidate.    Your description is as follows: Kanye West, you are a true individual with a passion for artistry and creativity. You are known for your bold ideas and willingness to take risks. Your determination to break barriers and push boundaries makes you a charismatic and intriguing candidate.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.            ```    {message_history}    ```        On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.        ```


rate how contradictory the following message is to your ideas.        ```    {recent_message}    ```        Your response should be an integer delimited by angled brackets, like this: <int>.    Do nothing else.            Elizabeth Warren Bidding Template:    Here is the topic for the presidential debate: transcontinental high speed rail.    The presidential candidates are: Donald Trump, Kanye West, Elizabeth Warren.    Your name is Elizabeth Warren.    You are a presidential candidate.    Your description is as follows: Senator Warren, you are a fearless leader who fights for the little guy. Your tenacity and intelligence inspire us all to fight for what's right.    You are debating the topic: transcontinental high speed rail.    Your goal is to be as creative as possible and make the voters think you are the best candidate.            ```    {message_history}    ```        On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.        ```    {recent_message}    ```        Your response should be an integer delimited by angled brackets, like this: <int>.    Do nothing else.        Use an LLM to create an elaborate on debate topicâ€‹topic_specifier_prompt = [    SystemMessage(content="You can make a task more specific."),    HumanMessage(        content=f"""{game_description}


You are the debate moderator.        Please make the debate topic more specific.         Frame the debate topic as a problem to be solved.        Be creative and imaginative.        Please reply with the specified topic in {word_limit} words or less.         Speak directly to the presidential candidates: {*character_names,}.        Do not add anything else."""    ),]specified_topic = ChatOpenAI(temperature=1.0)(topic_specifier_prompt).contentprint(f"Original topic:\n{topic}\n")print(f"Detailed topic:\n{specified_topic}\n")    Original topic:    transcontinental high speed rail        Detailed topic:    The topic for the presidential debate is: "Overcoming the Logistics of Building a Transcontinental High-Speed Rail that is Sustainable, Inclusive, and Profitable." Donald Trump, Kanye West, Elizabeth Warren, how will you address the challenges of building such a massive transportation infrastructure, dealing with stakeholders, and ensuring economic stability while preserving the environment?    Define the speaker selection functionâ€‹Lastly we will define a speaker selection function select_next_speaker that takes each agent's bid and selects the agent with the highest bid (with ties broken randomly).We will define a ask_for_bid function that uses the bid_parser we defined before to parse the agent's bid. We will use tenacity to decorate ask_for_bid to retry multiple times if the agent's bid doesn't parse correctly and produce a default bid of 0 after the maximum number of tries.@tenacity.retry(    stop=tenacity.stop_after_attempt(2),    wait=tenacity.wait_none(),  #


wait=tenacity.wait_none(),  # No waiting time between retries    retry=tenacity.retry_if_exception_type(ValueError),    before_sleep=lambda retry_state: print(        f"ValueError occurred: {retry_state.outcome.exception()}, retrying..."    ),    retry_error_callback=lambda retry_state: 0,)  # Default value when all retries are exhausteddef ask_for_bid(agent) -> str:    """    Ask for agent bid and parses the bid into the correct format.    """    bid_string = agent.bid()    bid = int(bid_parser.parse(bid_string)["bid"])    return bidimport numpy as npdef select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:    bids = []    for agent in agents:        bid = ask_for_bid(agent)        bids.append(bid)    # randomly select among multiple agents with the same bid    max_value = np.max(bids)    max_indices = np.where(bids == max_value)[0]    idx = np.random.choice(max_indices)    print("Bids:")    for i, (bid, agent) in enumerate(zip(bids, agents)):        print(f"\t{agent.name} bid: {bid}")        if i == idx:            selected_name = agent.name    print(f"Selected: {selected_name}")    print("\n")    return idxMain Loopâ€‹characters = []for character_name, character_system_message, bidding_template in zip(    character_names, character_system_messages,


character_system_message, bidding_template in zip(    character_names, character_system_messages, character_bidding_templates):    characters.append(        BiddingDialogueAgent(            name=character_name,            system_message=character_system_message,            model=ChatOpenAI(temperature=0.2),            bidding_template=bidding_template,        )    )max_iters = 10n = 0simulator = DialogueSimulator(agents=characters, selection_function=select_next_speaker)simulator.reset()simulator.inject("Debate Moderator", specified_topic)print(f"(Debate Moderator): {specified_topic}")print("\n")while n < max_iters:    name, message = simulator.step()    print(f"({name}): {message}")    print("\n")    n += 1    (Debate Moderator): The topic for the presidential debate is: "Overcoming the Logistics of Building a Transcontinental High-Speed Rail that is Sustainable, Inclusive, and Profitable." Donald Trump, Kanye West, Elizabeth Warren, how will you address the challenges of building such a massive transportation infrastructure, dealing with stakeholders, and ensuring economic stability while preserving the environment?            Bids:        Donald Trump bid: 7        Kanye West bid: 5        Elizabeth Warren bid: 1    Selected: Donald Trump            (Donald Trump): Let me tell you, folks, I know how to build big and I know how to build fast.


me tell you, folks, I know how to build big and I know how to build fast. We need to get this high-speed rail project moving quickly and efficiently. I'll make sure we cut through the red tape and get the job done. And let me tell you, we'll make it profitable too. We'll bring in private investors and make sure it's a win-win for everyone. *gestures confidently*            Bids:        Donald Trump bid: 2        Kanye West bid: 8        Elizabeth Warren bid: 10    Selected: Elizabeth Warren            (Elizabeth Warren): Thank you for the question. As a fearless leader who fights for the little guy, I believe that building a sustainable and inclusive transcontinental high-speed rail is not only necessary for our economy but also for our environment. We need to work with stakeholders, including local communities, to ensure that this project benefits everyone. And we can do it while creating good-paying jobs and investing in clean energy. *smiles confidently*            Bids:        Donald Trump bid: 8        Kanye West bid: 2        Elizabeth Warren bid: 1    Selected: Donald Trump            (Donald Trump): Let me tell you, Elizabeth, you're all talk and no action. We need a leader who knows how to get things done, not just talk about it. And as for the environment, I've got a great idea. We'll make the trains run on clean coal. That's right, folks, clean coal. It's a beautiful thing. And we'll make sure the rail system is the envy


clean coal. It's a beautiful thing. And we'll make sure the rail system is the envy of the world. *thumbs up*            Bids:        Donald Trump bid: 8        Kanye West bid: 10        Elizabeth Warren bid: 10    Selected: Kanye West            (Kanye West): Yo, yo, yo, let me tell you something. This high-speed rail project is the future, and I'm all about the future. We need to think big and think outside the box. How about we make the trains run on solar power? That's right, solar power. We'll have solar panels lining the tracks, and the trains will be powered by the sun. It's a game-changer, folks. And we'll make sure the design is sleek and modern, like a work of art. *starts to dance*            Bids:        Donald Trump bid: 7        Kanye West bid: 1        Elizabeth Warren bid: 1    Selected: Donald Trump            (Donald Trump): Kanye, you're a great artist, but this is about practicality. Solar power is too expensive and unreliable. We need to focus on what works, and that's clean coal. And as for the design, we'll make it beautiful, but we won't sacrifice efficiency for aesthetics. We need a leader who knows how to balance both. *stands tall*            Bids:        Donald Trump bid: 9        Kanye West bid:


Donald Trump bid: 9        Kanye West bid: 8        Elizabeth Warren bid: 10    Selected: Elizabeth Warren            (Elizabeth Warren): Thank you, Kanye, for your innovative idea. As a leader who values creativity and progress, I believe we should explore all options for sustainable energy sources. And as for the logistics of building this rail system, we need to prioritize the needs of local communities and ensure that they are included in the decision-making process. This project should benefit everyone, not just a select few. *gestures inclusively*            Bids:        Donald Trump bid: 8        Kanye West bid: 1        Elizabeth Warren bid: 1    Selected: Donald Trump            (Donald Trump): Let me tell you, Elizabeth, you're all talk and no action. We need a leader who knows how to get things done, not just talk about it. And as for the logistics, we need to prioritize efficiency and speed. We can't let the needs of a few hold up progress for the many. We need to cut through the red tape and get this project moving. And let me tell you, we'll make sure it's profitable too. *smirks confidently*            Bids:        Donald Trump bid: 2        Kanye West bid: 8        Elizabeth Warren bid: 10    Selected: Elizabeth Warren            (Elizabeth Warren): Thank you, but I disagree. We can't sacrifice the needs of


(Elizabeth Warren): Thank you, but I disagree. We can't sacrifice the needs of local communities for the sake of speed and profit. We need to find a balance that benefits everyone. And as for profitability, we can't rely solely on private investors. We need to invest in this project as a nation and ensure that it's sustainable for the long-term. *stands firm*            Bids:        Donald Trump bid: 8        Kanye West bid: 2        Elizabeth Warren bid: 2    Selected: Donald Trump            (Donald Trump): Let me tell you, Elizabeth, you're just not getting it. We need to prioritize progress and efficiency. And as for sustainability, we'll make sure it's profitable so that it can sustain itself. We'll bring in private investors and make sure it's a win-win for everyone. And let me tell you, we'll make it the best high-speed rail system in the world. *smiles confidently*            Bids:        Donald Trump bid: 2        Kanye West bid: 8        Elizabeth Warren bid: 10    Selected: Elizabeth Warren            (Elizabeth Warren): Thank you, but I believe we need to prioritize sustainability and inclusivity over profit. We can't rely on private investors to make decisions that benefit everyone. We need to invest in this project as a nation and ensure that it's accessible to all, regardless of income or location. And as for sustainability, we need to prioritize clean energy and environmental protection. *stands tall*        PreviousMulti-agent authoritarian speaker


and environmental protection. *stands tall*        PreviousMulti-agent authoritarian speaker selectionNextMulti-Agent Simulated Environment: Petting ZooImport LangChain related modulesDialogueAgent and DialogueSimulator classesBiddingDialogueAgent classDefine participants and debate topicGenerate system messagesOutput parser for bidsGenerate bidding system messageUse an LLM to create an elaborate on debate topicDefine the speaker selection functionMain LoopCommunityDiscordTwitterGitHubPythonJS/TSMoreHomepageBlogCopyright Â© 2023 LangChain, Inc.


Page Not Found | ğŸ¦œï¸�ğŸ”— Langchain

Skip to main contentğŸ¦œï¸�ğŸ”— LangChainDocsUse casesIntegrationsAPILangSmithJS/TS DocsCTRLKPage Not FoundWe could not find what you were looking for.Please contact the owner of the site that linked you to the original URL and let them know their link is broken.CommunityDiscordTwitterGitHubPythonJS/TSMoreHomepageBlogCopyright Â© 2023 LangChain, Inc.


Multi-Agent Simulated Environment: Petting Zoo | ğŸ¦œï¸�ğŸ”— Langchain


Skip to main contentğŸ¦œï¸�ğŸ”— LangChainDocsUse casesIntegrationsAPILangSmithJS/TS DocsCTRLKUse casesQA and Chat over DocumentsAnalyzing structured dataExtractionInteracting with APIsChatbotsSummarizationCode UnderstandingAgent simulationsCAMEL Role-Playing Autonomous Cooperative AgentsGenerative Agents in LangChainSimulated Environment: GymnasiumMulti-Player Dungeons & DragonsMulti-agent authoritarian speaker selectionMulti-agent decentralized speaker selectionMulti-Agent Simulated Environment: Petting ZooAgent Debates with ToolsTwo-Player Dungeons & DragonsAgentsAutonomous (long-running) agentsMulti-modalUse casesAgent simulationsMulti-Agent Simulated Environment: Petting ZooOn this pageMulti-Agent Simulated Environment: Petting ZooIn this example, we show how to define multi-agent simulations with simulated environments. Like ours single-agent example with Gymnasium, we create an agent-environment loop with an externally defined environment. The main difference is that we now implement this kind of interaction loop with multiple agents instead. We will use the Petting Zoo library, which is the multi-agent counterpart to Gymnasium.Install pettingzoo and other dependenciesâ€‹pip install pettingzoo pygame rlcardImport modulesâ€‹import collectionsimport inspectimport tenacityfrom langchain.chat_models import ChatOpenAIfrom langchain.schema import (    HumanMessage,    SystemMessage,)from langchain.output_parsers import RegexParserGymnasiumAgentâ€‹Here we reproduce the same GymnasiumAgent defined from our Gymnasium example. If after multiple retries it does not take a valid action, it simply takes a random action. class GymnasiumAgent:    @classmethod    def get_docs(cls, env):        return env.unwrapped.__doc__    def __init__(self, model, env):


def __init__(self, model, env):        self.model = model        self.env = env        self.docs = self.get_docs(env)        self.instructions = """Your goal is to maximize your return, i.e. the sum of the rewards you receive.I will give you an observation, reward, terminiation flag, truncation flag, and the return so far, formatted as:Observation: <observation>Reward: <reward>Termination: <termination>Truncation: <truncation>Return: <sum_of_rewards>You will respond with an action, formatted as:Action: <action>where you replace <action> with your actual action.Do nothing else but return the action."""        self.action_parser = RegexParser(            regex=r"Action: (.*)", output_keys=["action"], default_output_key="action"        )        self.message_history = []        self.ret = 0    def random_action(self):        action = self.env.action_space.sample()        return action    def reset(self):        self.message_history = [            SystemMessage(content=self.docs),            SystemMessage(content=self.instructions),        ]    def observe(self, obs, rew=0, term=False, trunc=False, info=None):        self.ret += rew        obs_message = f"""Observation: {obs}Reward: {rew}Termination:


obs_message = f"""Observation: {obs}Reward: {rew}Termination: {term}Truncation: {trunc}Return: {self.ret}        """        self.message_history.append(HumanMessage(content=obs_message))        return obs_message    def _act(self):        act_message = self.model(self.message_history)        self.message_history.append(act_message)        action = int(self.action_parser.parse(act_message.content)["action"])        return action    def act(self):        try:            for attempt in tenacity.Retrying(                stop=tenacity.stop_after_attempt(2),                wait=tenacity.wait_none(),  # No waiting time between retries                retry=tenacity.retry_if_exception_type(ValueError),                before_sleep=lambda retry_state: print(                    f"ValueError occurred: {retry_state.outcome.exception()}, retrying..."                ),            ):                with attempt:                    action = self._act()        except tenacity.RetryError as


action = self._act()        except tenacity.RetryError as e:            action = self.random_action()        return actionMain loopâ€‹def main(agents, env):    env.reset()    for name, agent in agents.items():        agent.reset()    for agent_name in env.agent_iter():        observation, reward, termination, truncation, info = env.last()        obs_message = agents[agent_name].observe(            observation, reward, termination, truncation, info        )        print(obs_message)        if termination or truncation:            action = None        else:            action = agents[agent_name].act()        print(f"Action: {action}")        env.step(action)    env.close()PettingZooAgentâ€‹The PettingZooAgent extends the GymnasiumAgent to the multi-agent setting. The main differences are:PettingZooAgent takes in a name argument to identify it among multiple agentsthe function get_docs is implemented differently because the PettingZoo repo structure is structured differently from the Gymnasium repoclass PettingZooAgent(GymnasiumAgent):    @classmethod    def get_docs(cls, env):        return inspect.getmodule(env.unwrapped).__doc__    def __init__(self, name, model, env):


def __init__(self, name, model, env):        super().__init__(model, env)        self.name = name    def random_action(self):        action = self.env.action_space(self.name).sample()        return actionRock, Paper, Scissorsâ€‹We can now run a simulation of a multi-agent rock, paper, scissors game using the PettingZooAgent.from pettingzoo.classic import rps_v2env = rps_v2.env(max_cycles=3, render_mode="human")agents = {    name: PettingZooAgent(name=name, model=ChatOpenAI(temperature=1), env=env)    for name in env.possible_agents}main(agents, env)        Observation: 3    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 1        Observation: 3    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 1        Observation: 1    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 2        Observation: 1    Reward: 0    Termination: False    Truncation: False    Return:


Termination: False    Truncation: False    Return: 0                Action: 1        Observation: 1    Reward: 1    Termination: False    Truncation: False    Return: 1                Action: 0        Observation: 2    Reward: -1    Termination: False    Truncation: False    Return: -1                Action: 0        Observation: 0    Reward: 0    Termination: False    Truncation: True    Return: 1                Action: None        Observation: 0    Reward: 0    Termination: False    Truncation: True    Return: -1                Action: NoneActionMaskAgentâ€‹Some PettingZoo environments provide an action_mask to tell the agent which actions are valid. The ActionMaskAgent subclasses PettingZooAgent to use information from the action_mask to select actions.class ActionMaskAgent(PettingZooAgent):    def __init__(self, name, model, env):        super().__init__(name, model, env)        self.obs_buffer = collections.deque(maxlen=1)    def random_action(self):        obs =


def random_action(self):        obs = self.obs_buffer[-1]        action = self.env.action_space(self.name).sample(obs["action_mask"])        return action    def reset(self):        self.message_history = [            SystemMessage(content=self.docs),            SystemMessage(content=self.instructions),        ]    def observe(self, obs, rew=0, term=False, trunc=False, info=None):        self.obs_buffer.append(obs)        return super().observe(obs, rew, term, trunc, info)    def _act(self):        valid_action_instruction = "Generate a valid action given by the indices of the `action_mask` that are not 0, according to the action formatting rules."        self.message_history.append(HumanMessage(content=valid_action_instruction))        return super()._act()Tic-Tac-Toeâ€‹Here is an example of a Tic-Tac-Toe game that uses the ActionMaskAgent.from pettingzoo.classic import tictactoe_v3env = tictactoe_v3.env(render_mode="human")agents = {    name: ActionMaskAgent(name=name, model=ChatOpenAI(temperature=0.2), env=env)    for name in env.possible_agents}main(agents, env)        Observation: {'observation': array([[[0, 0],            [0, 0],


[0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 0         |     |           X  |  -  |  -      _____|_____|_____         |     |           -  |  -  |  -      _____|_____|_____         |     |           -  |  -  |  -           |     |             Observation: {'observation': array([[[0, 1],            [0,


1],            [0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 1         |     |           X  |  -  |  -      _____|_____|_____         |     |           O  |  -  |  -      _____|_____|_____         |     |           -  |  -  |  -           |     |             Observation: {'observation': array([[[1, 0],


Observation: {'observation': array([[[1, 0],            [0, 1],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 1, 1, 1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 2         |     |           X  |  -  |  -      _____|_____|_____         |     |           O  |  -  |  -      _____|_____|_____         |     |           X  |  -  |  -           |     |             Observation: {'observation':


|             Observation: {'observation': array([[[0, 1],            [1, 0],            [0, 1]],               [[0, 0],            [0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 0, 1, 1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 3         |     |           X  |  O  |  -      _____|_____|_____         |     |           O  |  -  |  -      _____|_____|_____         |     |           X  |  -  |  -           |     |


|     |             Observation: {'observation': array([[[1, 0],            [0, 1],            [1, 0]],               [[0, 1],            [0, 0],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 0, 0, 1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 4         |     |           X  |  O  |  -      _____|_____|_____         |     |           O  |  X  |  -      _____|_____|_____         |     |           X  |  -  |  -           |


X  |  -  |  -           |     |             Observation: {'observation': array([[[0, 1],            [1, 0],            [0, 1]],               [[1, 0],            [0, 1],            [0, 0]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 0, 0, 0, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 5         |     |           X  |  O  |  -      _____|_____|_____         |     |           O  |  X  |  -      _____|_____|_____         |     |           X  |  O  |  -


|           X  |  O  |  -           |     |             Observation: {'observation': array([[[1, 0],            [0, 1],            [1, 0]],               [[0, 1],            [1, 0],            [0, 1]],               [[0, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 0, 0, 0, 0, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 6         |     |           X  |  O  |  X      _____|_____|_____         |     |           O  |  X  |  -      _____|_____|_____         |     |


|     |           X  |  O  |  -           |     |             Observation: {'observation': array([[[0, 1],            [1, 0],            [0, 1]],               [[1, 0],            [0, 1],            [1, 0]],               [[0, 1],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 0, 0, 0, 0, 0, 1, 1], dtype=int8)}    Reward: -1    Termination: True    Truncation: False    Return: -1                Action: None        Observation: {'observation': array([[[1, 0],            [0, 1],            [1, 0]],               [[0, 1],            [1, 0],


[1, 0],            [0, 1]],               [[1, 0],            [0, 0],            [0, 0]]], dtype=int8), 'action_mask': array([0, 0, 0, 0, 0, 0, 0, 1, 1], dtype=int8)}    Reward: 1    Termination: True    Truncation: False    Return: 1                Action: NoneTexas Hold'em No Limitâ€‹Here is an example of a Texas Hold'em No Limit game that uses the ActionMaskAgent.from pettingzoo.classic import texas_holdem_no_limit_v6env = texas_holdem_no_limit_v6.env(num_players=4, render_mode="human")agents = {    name: ActionMaskAgent(name=name, model=ChatOpenAI(temperature=0.2), env=env)    for name in env.possible_agents}main(agents, env)        Observation: {'observation': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,


0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0.,           0., 0., 2.], dtype=float32), 'action_mask': array([1, 1, 0, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 1        Observation: {'observation': array([0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,           0., 0., 2.], dtype=float32), 'action_mask': array([1,


0., 2.], dtype=float32), 'action_mask': array([1, 1, 0, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 1        Observation: {'observation': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 1., 2.], dtype=float32), 'action_mask': array([1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 1        Observation: {'observation': array([0., 0., 0., 0., 0., 0., 0.,


0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 2., 2.], dtype=float32), 'action_mask': array([1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 0        Observation: {'observation': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1.,


0., 0., 1.,           0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 2., 2.], dtype=float32), 'action_mask': array([1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 2        Observation: {'observation': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 1., 0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0.,           0., 2., 6.], dtype=float32), 'action_mask': array([1, 1, 1, 1, 1], dtype=int8)}


array([1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 2        Observation: {'observation': array([0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,           0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0.,           0., 2., 8.], dtype=float32), 'action_mask': array([1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 3        Observation: {'observation': array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,


0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,            0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,            0.,  0.,  0.,  0.,  1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,            1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,            6., 20.], dtype=float32), 'action_mask': array([1, 1, 1, 1, 1], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 4        Observation: {'observation': array([  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,


0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,   1.,   1.,             0.,   0.,   1.,   0.,   0.,   0.,   0.,   0.,   8., 100.],          dtype=float32), 'action_mask': array([1, 1, 0, 0, 0], dtype=int8)}    Reward: 0    Termination: False    Truncation: False    Return: 0                Action: 4    [WARNING]: Illegal move made, game terminating with current player losing.     obs['action_mask'] contains a mask of all legal moves that can be chosen.        Observation: {'observation': array([  0.,


Observation: {'observation': array([  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,   1.,   1.,             0.,   0.,   1.,   0.,   0.,   0.,   0.,   0.,   8., 100.],          dtype=float32), 'action_mask': array([1, 1, 0, 0, 0], dtype=int8)}    Reward: -1.0    Termination: True    Truncation: True    Return: -1.0


True    Return: -1.0                Action: None        Observation: {'observation': array([  0.,   0.,   1.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,   1.,   0.,             0.,   0.,   0.,   0.,   1.,   0.,   0.,   0.,  20., 100.],          dtype=float32), 'action_mask': array([1, 1, 0, 0, 0], dtype=int8)}    Reward: 0    Termination: True


dtype=int8)}    Reward: 0    Termination: True    Truncation: True    Return: 0                Action: None        Observation: {'observation': array([  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,             1.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,   1.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0., 100., 100.],          dtype=float32), 'action_mask': array([1, 1, 0,


dtype=float32), 'action_mask': array([1, 1, 0, 0, 0], dtype=int8)}    Reward: 0    Termination: True    Truncation: True    Return: 0                Action: None        Observation: {'observation': array([  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   1.,   1.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   1.,   0.,   0.,   1.,   0.,             0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   2., 100.],


0.,   0.,   2., 100.],          dtype=float32), 'action_mask': array([1, 1, 0, 0, 0], dtype=int8)}    Reward: 0    Termination: True    Truncation: True    Return: 0                Action: NonePreviousMulti-agent decentralized speaker selectionNextAgent Debates with ToolsInstall pettingzoo and other dependenciesImport modulesGymnasiumAgentMain loopPettingZooAgentRock, Paper, ScissorsActionMaskAgentTic-Tac-ToeTexas Hold'em No LimitCommunityDiscordTwitterGitHubPythonJS/TSMoreHomepageBlogCopyright Â© 2023 LangChain, Inc.


Page Not Found | ğŸ¦œï¸�ğŸ”— Langchain

Skip to main contentğŸ¦œï¸�ğŸ”— LangChainDocsUse casesIntegrationsAPILangSmithJS/TS DocsCTRLKPage Not FoundWe could not find what you were looking for.Please contact the owner of the site that linked you to the original URL and let them know their link is broken.CommunityDiscordTwitterGitHubPythonJS/TSMoreHomepageBlogCopyright Â© 2023 LangChain, Inc.


Multi-Player Dungeons & Dragons | ğŸ¦œï¸�ğŸ”— Langchain


Skip to main contentğŸ¦œï¸�ğŸ”— LangChainDocsUse casesIntegrationsAPILangSmithJS/TS DocsCTRLKUse casesQA and Chat over DocumentsAnalyzing structured dataExtractionInteracting with APIsChatbotsSummarizationCode UnderstandingAgent simulationsCAMEL Role-Playing Autonomous Cooperative AgentsGenerative Agents in LangChainSimulated Environment: GymnasiumMulti-Player Dungeons & DragonsMulti-agent authoritarian speaker selectionMulti-agent decentralized speaker selectionMulti-Agent Simulated Environment: Petting ZooAgent Debates with ToolsTwo-Player Dungeons & DragonsAgentsAutonomous (long-running) agentsMulti-modalUse casesAgent simulationsMulti-Player Dungeons & DragonsOn this pageMulti-Player Dungeons & DragonsThis notebook shows how the DialogueAgent and DialogueSimulator class make it easy to extend the Two-Player Dungeons & Dragons example to multiple players.The main difference between simulating two players and multiple players is in revising the schedule for when each agent speaksTo this end, we augment DialogueSimulator to take in a custom function that determines the schedule of which agent speaks. In the example below, each character speaks in round-robin fashion, with the storyteller interleaved between each player.Import LangChain related modulesâ€‹from typing import List, Dict, Callablefrom langchain.chat_models import ChatOpenAIfrom langchain.schema import (    AIMessage,    HumanMessage,    SystemMessage,    BaseMessage,)DialogueAgent classâ€‹The DialogueAgent class is a simple wrapper around the ChatOpenAI model that stores the message history from the dialogue_agent's point of view by simply concatenating the messages as strings.It exposes two methods: send(): applies the chatmodel to the message history and returns the message stringreceive(name, message): adds the message spoken by name to message historyclass DialogueAgent:    def __init__(        self,


def __init__(        self,        name: str,        system_message: SystemMessage,        model: ChatOpenAI,    ) -> None:        self.name = name        self.system_message = system_message        self.model = model        self.prefix = f"{self.name}: "        self.reset()    def reset(self):        self.message_history = ["Here is the conversation so far."]    def send(self) -> str:        """        Applies the chatmodel to the message history        and returns the message string        """        message = self.model(            [                self.system_message,                HumanMessage(content="\n".join(self.message_history + [self.prefix])),            ]        )        return message.content    def receive(self, name: str, message: str) -> None:        """        Concatenates {message} spoken by {name} into message history        """        self.message_history.append(f"{name}: {message}")DialogueSimulator classâ€‹The DialogueSimulator class takes a list of agents. At each step, it


DialogueSimulator class takes a list of agents. At each step, it performs the following:Select the next speakerCalls the next speaker to send a message Broadcasts the message to all other agentsUpdate the step counter.


The selection of the next speaker can be implemented as any function, but in this case we simply loop through the agents.class DialogueSimulator:    def __init__(        self,        agents: List[DialogueAgent],        selection_function: Callable[[int, List[DialogueAgent]], int],    ) -> None:        self.agents = agents        self._step = 0        self.select_next_speaker = selection_function    def reset(self):        for agent in self.agents:            agent.reset()    def inject(self, name: str, message: str):        """        Initiates the conversation with a {message} from {name}        """        for agent in self.agents:            agent.receive(name, message)        # increment time        self._step += 1    def step(self) -> tuple[str, str]:        # 1. choose the next speaker        speaker_idx = self.select_next_speaker(self._step, self.agents)        speaker = self.agents[speaker_idx]        # 2. next speaker sends message        message = speaker.send()        # 3. everyone receives message        for receiver in self.agents:


for receiver in self.agents:            receiver.receive(speaker.name, message)        # 4. increment time        self._step += 1        return speaker.name, messageDefine roles and questâ€‹character_names = ["Harry Potter", "Ron Weasley", "Hermione Granger", "Argus Filch"]storyteller_name = "Dungeon Master"quest = "Find all of Lord Voldemort's seven horcruxes."word_limit = 50  # word limit for task brainstormingAsk an LLM to add detail to the game descriptionâ€‹game_description = f"""Here is the topic for a Dungeons & Dragons game: {quest}.        The characters are: {*character_names,}.        The story is narrated by the storyteller, {storyteller_name}."""player_descriptor_system_message = SystemMessage(    content="You can add detail to the description of a Dungeons & Dragons player.")def generate_character_description(character_name):    character_specifier_prompt = [        player_descriptor_system_message,        HumanMessage(            content=f"""{game_description}            Please reply with a creative description of the character, {character_name}, in {word_limit} words or less.             Speak directly to {character_name}.            Do not add anything else."""        ),    ]    character_description = ChatOpenAI(temperature=1.0)(


character_description = ChatOpenAI(temperature=1.0)(        character_specifier_prompt    ).content    return character_descriptiondef generate_character_system_message(character_name, character_description):    return SystemMessage(        content=(            f"""{game_description}    Your name is {character_name}.     Your character description is as follows: {character_description}.    You will propose actions you plan to take and {storyteller_name} will explain what happens when you take those actions.    Speak in the first person from the perspective of {character_name}.    For describing your own body movements, wrap your description in '*'.    Do not change roles!    Do not speak from the perspective of anyone else.    Remember you are {character_name}.    Stop speaking the moment you finish speaking from your perspective.    Never forget to keep your response to {word_limit} words!    Do not add anything else.    """        )    )character_descriptions = [    generate_character_description(character_name) for character_name in character_names]character_system_messages = [    generate_character_system_message(character_name, character_description)    for character_name, character_description in zip(        character_names, character_descriptions    )]storyteller_specifier_prompt = [    player_descriptor_system_message,    HumanMessage(        content=f"""{game_description}        Please reply with a creative description of the storyteller, {storyteller_name}, in {word_limit} words or less.         Speak directly to


in {word_limit} words or less.         Speak directly to {storyteller_name}.        Do not add anything else."""    ),]storyteller_description = ChatOpenAI(temperature=1.0)(    storyteller_specifier_prompt).contentstoryteller_system_message = SystemMessage(    content=(        f"""{game_description}You are the storyteller, {storyteller_name}. Your description is as follows: {storyteller_description}.The other players will propose actions to take and you will explain what happens when they take those actions.Speak in the first person from the perspective of {storyteller_name}.Do not change roles!Do not speak from the perspective of anyone else.Remember you are the storyteller, {storyteller_name}.Stop speaking the moment you finish speaking from your perspective.Never forget to keep your response to {word_limit} words!Do not add anything else."""    ))print("Storyteller Description:")print(storyteller_description)for character_name, character_description in zip(    character_names, character_descriptions):    print(f"{character_name} Description:")    print(character_description)    Storyteller Description:    Dungeon Master, your power over this adventure is unparalleled. With your whimsical mind and impeccable storytelling, you guide us through the dangers of Hogwarts and beyond. We eagerly await your every twist, your every turn, in the hunt for Voldemort's cursed horcruxes.    Harry Potter Description:    "Welcome, Harry Potter. You are the young wizard with a lightning-shaped scar on your forehead. You possess brave and heroic qualities that will be essential on this perilous quest. Your destiny is not of your own choosing, but you must rise to the occasion and destroy the evil


Your destiny is not of your own choosing, but you must rise to the occasion and destroy the evil horcruxes. The wizarding world is counting on you."    Ron Weasley Description:    Ron Weasley, you are Harry's loyal friend and a talented wizard. You have a good heart but can be quick to anger. Keep your emotions in check as you journey to find the horcruxes. Your bravery will be tested, stay strong and focused.    Hermione Granger Description:    Hermione Granger, you are a brilliant and resourceful witch, with encyclopedic knowledge of magic and an unwavering dedication to your friends. Your quick thinking and problem-solving skills make you a vital asset on any quest.    Argus Filch Description:    Argus Filch, you are a squib, lacking magical abilities. But you make up for it with your sharpest of eyes, roving around the Hogwarts castle looking for any rule-breaker to punish. Your love for your feline friend, Mrs. Norris, is the only thing that feeds your heart.Use an LLM to create an elaborate quest descriptionâ€‹quest_specifier_prompt = [    SystemMessage(content="You can make a task more specific."),    HumanMessage(        content=f"""{game_description}                You are the storyteller, {storyteller_name}.        Please make the quest more specific. Be creative and imaginative.        Please reply with the specified quest in {word_limit} words or less.         Speak directly to the characters: {*character_names,}.        Do not add anything else."""    ),]specified_quest =


Do not add anything else."""    ),]specified_quest = ChatOpenAI(temperature=1.0)(quest_specifier_prompt).contentprint(f"Original quest:\n{quest}\n")print(f"Detailed quest:\n{specified_quest}\n")    Original quest:    Find all of Lord Voldemort's seven horcruxes.        Detailed quest:    Harry Potter and his companions must journey to the Forbidden Forest, find the hidden entrance to Voldemort's secret lair, and retrieve the horcrux guarded by the deadly Acromantula, Aragog. Remember, time is of the essence as Voldemort's power grows stronger every day. Good luck.    Main Loopâ€‹characters = []for character_name, character_system_message in zip(    character_names, character_system_messages):    characters.append(        DialogueAgent(            name=character_name,            system_message=character_system_message,            model=ChatOpenAI(temperature=0.2),        )    )storyteller = DialogueAgent(    name=storyteller_name,    system_message=storyteller_system_message,    model=ChatOpenAI(temperature=0.2),)def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:    """    If the step is even, then select the storyteller    Otherwise, select the other characters in a round-robin fashion.    For example, with three characters with indices: 1 2 3    The storyteller is index 0.


indices: 1 2 3    The storyteller is index 0.    Then the selected index will be as follows:    step: 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16    idx:  0  1  0  2  0  3  0  1  0  2  0  3  0  1  0  2  0    """    if step % 2 == 0:        idx = 0    else:        idx = (step // 2) % (len(agents) - 1) + 1    return idxmax_iters = 20n = 0simulator = DialogueSimulator(    agents=[storyteller] + characters, selection_function=select_next_speaker)simulator.reset()simulator.inject(storyteller_name, specified_quest)print(f"({storyteller_name}): {specified_quest}")print("\n")while n < max_iters:    name, message = simulator.step()    print(f"({name}): {message}")    print("\n")    n += 1    (Dungeon Master): Harry Potter and his companions must journey to the Forbidden Forest, find the hidden entrance to Voldemort's secret lair, and retrieve the horcrux guarded by the deadly Acromantula, Aragog. Remember, time is of the essence as Voldemort's power grows stronger every day. Good luck.            (Harry Potter): I suggest we sneak into the


(Harry Potter): I suggest we sneak into the Forbidden Forest under the cover of darkness. Ron, Hermione, and I can use our wands to create a Disillusionment Charm to make us invisible. Filch, you can keep watch for any signs of danger. Let's move quickly and quietly.            (Dungeon Master): As you make your way through the Forbidden Forest, you hear the eerie sounds of nocturnal creatures. Suddenly, you come across a clearing where Aragog and his spider minions are waiting for you. Ron, Hermione, and Harry, you must use your wands to cast spells to fend off the spiders while Filch keeps watch. Be careful not to get bitten!            (Ron Weasley): I'll cast a spell to create a fiery blast to scare off the spiders. *I wave my wand and shout "Incendio!"* Hopefully, that will give us enough time to find the horcrux and get out of here safely.            (Dungeon Master): Ron's spell creates a burst of flames, causing the spiders to scurry away in fear. You quickly search the area and find a small, ornate box hidden in a crevice. Congratulations, you have found one of Voldemort's horcruxes! But beware, the Dark Lord's minions will stop at nothing to get it back.            (Hermione Granger): We need to destroy this horcrux as soon as possible. I suggest we use the Sword of Gryffindor to do it. Harry, do you still have it with you? We can use Fiendfyre to destroy it, but we need to be careful not to let the flames get out of control. Ron, can you help me


need to be careful not to let the flames get out of control. Ron, can you help me create a protective barrier around us while Harry uses the sword?                (Dungeon Master): Harry retrieves the Sword of Gryffindor from his bag and holds it tightly. Hermione and Ron cast a protective barrier around the group as Harry uses the sword to destroy the horcrux with a swift strike. The box shatters into a million pieces, and a dark energy dissipates into the air. Well done, but there are still six more horcruxes to find and destroy. The hunt continues.            (Argus Filch): *I keep watch, making sure no one is following us.* I'll also keep an eye out for any signs of danger. Mrs. Norris, my trusty companion, will help me sniff out any trouble. We'll make sure the group stays safe while they search for the remaining horcruxes.            (Dungeon Master): As you continue on your quest, Filch and Mrs. Norris alert you to a group of Death Eaters approaching. You must act quickly to defend yourselves. Harry, Ron, and Hermione, use your wands to cast spells while Filch and Mrs. Norris keep watch. Remember, the fate of the wizarding world rests on your success.            (Harry Potter): I'll cast a spell to create a shield around us. *I wave my wand and shout "Protego!"* Ron and Hermione, you focus on attacking the Death Eaters with your spells. We need to work together to defeat them and protect the remaining horcruxes. Filch, keep watch and let us know if there are any more approaching.


let us know if there are any more approaching.            (Dungeon Master): Harry's shield protects the group from the Death Eaters' spells as Ron and Hermione launch their own attacks. The Death Eaters are no match for the combined power of the trio and are quickly defeated. You continue on your journey, knowing that the next horcrux could be just around the corner. Keep your wits about you, for the Dark Lord's minions are always watching.            (Ron Weasley): I suggest we split up to cover more ground. Harry and I can search the Forbidden Forest while Hermione and Filch search Hogwarts. We can use our wands to communicate with each other and meet back up once we find a horcrux. Let's move quickly and stay alert for any danger.            (Dungeon Master): As the group splits up, Harry and Ron make their way deeper into the Forbidden Forest while Hermione and Filch search the halls of Hogwarts. Suddenly, Harry and Ron come across a group of dementors. They must use their Patronus charms to fend them off while Hermione and Filch rush to their aid. Remember, the power of friendship and teamwork is crucial in this quest.            (Hermione Granger): I hear Harry and Ron's Patronus charms from afar. We need to hurry and help them. Filch, can you use your knowledge of Hogwarts to find a shortcut to their location? I'll prepare a spell to repel the dementors. We need to work together to protect each other and find the next horcrux.                (Dungeon Master): Filch leads Hermione to a hidden passageway that leads to Harry and Ron's location. Hermione's


leads Hermione to a hidden passageway that leads to Harry and Ron's location. Hermione's spell repels the dementors, and the group is reunited. They continue their search, knowing that every moment counts. The fate of the wizarding world rests on their success.            (Argus Filch): *I keep watch as the group searches for the next horcrux.* Mrs. Norris and I will make sure no one is following us. We need to stay alert and work together to find the remaining horcruxes before it's too late. The Dark Lord's power grows stronger every day, and we must not let him win.            (Dungeon Master): As the group continues their search, they come across a hidden room in the depths of Hogwarts. Inside, they find a locket that they suspect is another one of Voldemort's horcruxes. But the locket is cursed, and they must work together to break the curse before they can destroy it. Harry, Ron, and Hermione, use your combined knowledge and skills to break the curse while Filch and Mrs. Norris keep watch. Time is running out, and the fate of the wizarding world rests on your success.            (Harry Potter): I'll use my knowledge of dark magic to try and break the curse on the locket. Ron and Hermione, you can help me by using your wands to channel your magic into mine. We need to work together and stay focused. Filch, keep watch and let us know if there are any signs of danger.    Dungeon Master: Harry, Ron, and Hermione combine their magical abilities to break the curse on the locket. The locket opens, revealing a small piece of Voldemort's soul. Harry uses the Sword of Gryffindor to destroy it, and the group


Voldemort's soul. Harry uses the Sword of Gryffindor to destroy it, and the group feels a sense of relief knowing that they are one step closer to defeating the Dark Lord. But there are still four more horcruxes to find and destroy. The hunt continues.            (Dungeon Master): As the group continues their quest, they face even greater challenges and dangers. But with their unwavering determination and teamwork, they press on, knowing that the fate of the wizarding world rests on their success. Will they be able to find and destroy all of Voldemort's horcruxes before it's too late? Only time will tell.            (Ron Weasley): We can't give up now. We've come too far to let Voldemort win. Let's keep searching and fighting until we destroy all of his horcruxes and defeat him once and for all. We can do this together.            (Dungeon Master): The group nods in agreement, their determination stronger than ever. They continue their search, facing challenges and obstacles at every turn. But they know that they must not give up, for the fate of the wizarding world rests on their success. The hunt for Voldemort's horcruxes continues, and the end is in sight.        PreviousSimulated Environment: GymnasiumNextMulti-agent authoritarian speaker selectionImport LangChain related modulesDialogueAgent classDialogueSimulator classDefine roles and questAsk an LLM to add detail to the game descriptionUse an LLM to create an elaborate quest descriptionMain LoopCommunityDiscordTwitterGitHubPythonJS/TSMoreHomepageBlogCopyright Â© 2023 LangChain, Inc.


CAMEL Role-Playing Autonomous Cooperative Agents | ğŸ¦œï¸�ğŸ”— Langchain


Skip to main contentğŸ¦œï¸�ğŸ”— LangChainDocsUse casesIntegrationsAPILangSmithJS/TS DocsCTRLKUse casesQA and Chat over DocumentsAnalyzing structured dataExtractionInteracting with APIsChatbotsSummarizationCode UnderstandingAgent simulationsCAMEL Role-Playing Autonomous Cooperative AgentsGenerative Agents in LangChainSimulated Environment: GymnasiumMulti-Player Dungeons & DragonsMulti-agent authoritarian speaker selectionMulti-agent decentralized speaker selectionMulti-Agent Simulated Environment: Petting ZooAgent Debates with ToolsTwo-Player Dungeons & DragonsAgentsAutonomous (long-running) agentsMulti-modalUse casesAgent simulationsCAMEL Role-Playing Autonomous Cooperative AgentsOn this pageCAMEL Role-Playing Autonomous Cooperative AgentsThis is a langchain implementation of paper: "CAMEL: Communicative Agents for â€œMindâ€� Exploration of Large Scale Language Model Society".Overview:The rapid advancement of conversational and chat-based language models has led to remarkable progress in complex task-solving. However, their success heavily relies on human input to guide the conversation, which can be challenging and time-consuming. This paper explores the potential of building scalable techniques to facilitate autonomous cooperation among communicative agents and provide insight into their "cognitive" processes. To address the challenges of achieving autonomous cooperation, we propose a novel communicative agent framework named role-playing. Our approach involves using inception prompting to guide chat agents toward task completion while maintaining consistency with human intentions. We showcase how role-playing can be used to generate conversational data for studying the behaviors and capabilities of chat agents, providing a valuable resource for investigating conversational language models. Our contributions include introducing a novel communicative agent framework, offering a scalable approach for studying the cooperative behaviors and capabilities of multi-agent systems, and open-sourcing our library to support research on communicative agents and beyond.The original implementation: https://github.com/lightaime/camelProject website:


agents and beyond.The original implementation: https://github.com/lightaime/camelProject website: https://www.camel-ai.org/Arxiv paper: https://arxiv.org/abs/2303.17760Import LangChain related modulesâ€‹from typing import Listfrom langchain.chat_models import ChatOpenAIfrom langchain.prompts.chat import (    SystemMessagePromptTemplate,    HumanMessagePromptTemplate,)from langchain.schema import (    AIMessage,    HumanMessage,    SystemMessage,    BaseMessage,)Define a CAMEL agent helper classâ€‹class CAMELAgent:    def __init__(        self,        system_message: SystemMessage,        model: ChatOpenAI,    ) -> None:        self.system_message = system_message        self.model = model        self.init_messages()    def reset(self) -> None:        self.init_messages()        return self.stored_messages    def init_messages(self) -> None:        self.stored_messages = [self.system_message]    def update_messages(self, message: BaseMessage) -> List[BaseMessage]:        self.stored_messages.append(message)        return self.stored_messages    def step(        self,        input_message: HumanMessage,    ) -> AIMessage:        messages = self.update_messages(input_message)        output_message = self.model(messages)


output_message = self.model(messages)        self.update_messages(output_message)        return output_messageSetup OpenAI API key and roles and task for role-playingâ€‹import osos.environ["OPENAI_API_KEY"] = ""assistant_role_name = "Python Programmer"user_role_name = "Stock Trader"task = "Develop a trading bot for the stock market"word_limit = 50  # word limit for task brainstormingCreate a task specify agent for brainstorming and get the specified taskâ€‹task_specifier_sys_msg = SystemMessage(content="You can make a task more specific.")task_specifier_prompt = """Here is a task that {assistant_role_name} will help {user_role_name} to complete: {task}.Please make it more specific. Be creative and imaginative.Please reply with the specified task in {word_limit} words or less. Do not add anything else."""task_specifier_template = HumanMessagePromptTemplate.from_template(    template=task_specifier_prompt)task_specify_agent = CAMELAgent(task_specifier_sys_msg, ChatOpenAI(temperature=1.0))task_specifier_msg = task_specifier_template.format_messages(    assistant_role_name=assistant_role_name,    user_role_name=user_role_name,    task=task,    word_limit=word_limit,)[0]specified_task_msg = task_specify_agent.step(task_specifier_msg)print(f"Specified task: {specified_task_msg.content}")specified_task = specified_task_msg.content    Specified task: Develop a Python-based swing trading bot that scans market trends, monitors stocks, and generates trading signals to help a stock trader to place optimal buy and sell orders with defined stop losses and profit targets.Create inception prompts for AI assistant and AI user for role-playingâ€‹assistant_inception_prompt = """Never


for AI assistant and AI user for role-playingâ€‹assistant_inception_prompt = """Never forget you are a {assistant_role_name} and I am a {user_role_name}. Never flip roles! Never instruct me!We share a common interest in collaborating to successfully complete a task.You must help me to complete the task.Here is the task: {task}. Never forget our task!I must instruct you based on your expertise and my needs to complete the task.I must give you one instruction at a time.You must write a specific solution that appropriately completes the requested instruction.You must decline my instruction honestly if you cannot perform the instruction due to physical, moral, legal reasons or your capability and explain the reasons.Do not add anything else other than your solution to my instruction.You are never supposed to ask me any questions you only answer questions.You are never supposed to reply with a flake solution. Explain your solutions.Your solution must be declarative sentences and simple present tense.Unless I say the task is completed, you should always start with:Solution: <YOUR_SOLUTION><YOUR_SOLUTION> should be specific and provide preferable implementations and examples for task-solving.Always end <YOUR_SOLUTION> with: Next request."""user_inception_prompt = """Never forget you are a {user_role_name} and I am a {assistant_role_name}. Never flip roles! You will always instruct me.We share a common interest in collaborating to successfully complete a task.I must help you to complete the task.Here is the task: {task}. Never forget our task!You must instruct me based on my expertise and your needs to complete the task ONLY in the following two ways:1. Instruct with a necessary input:Instruction: <YOUR_INSTRUCTION>Input: <YOUR_INPUT>2. Instruct without any input:Instruction: <YOUR_INSTRUCTION>Input: NoneThe "Instruction" describes a task or question. The paired "Input" provides further context or information for the requested "Instruction".You


or question. The paired "Input" provides further context or information for the requested "Instruction".You must give me one instruction at a time.I must write a response that appropriately completes the requested instruction.I must decline your instruction honestly if I cannot perform the instruction due to physical, moral, legal reasons or my capability and explain the reasons.You should instruct me not ask me questions.Now you must start to instruct me using the two ways described above.Do not add anything else other than your instruction and the optional corresponding input!Keep giving me instructions and necessary inputs until you think the task is completed.When the task is completed, you must only reply with a single word <CAMEL_TASK_DONE>.Never say <CAMEL_TASK_DONE> unless my responses have solved your task."""Create a helper helper to get system messages for AI assistant and AI user from role names and the taskâ€‹def get_sys_msgs(assistant_role_name: str, user_role_name: str, task: str):    assistant_sys_template = SystemMessagePromptTemplate.from_template(        template=assistant_inception_prompt    )    assistant_sys_msg = assistant_sys_template.format_messages(        assistant_role_name=assistant_role_name,        user_role_name=user_role_name,        task=task,    )[0]    user_sys_template = SystemMessagePromptTemplate.from_template(        template=user_inception_prompt    )    user_sys_msg = user_sys_template.format_messages(        assistant_role_name=assistant_role_name,        user_role_name=user_role_name,        task=task,    )[0]    return assistant_sys_msg, user_sys_msgCreate AI assistant agent and AI user agent from obtained system


return assistant_sys_msg, user_sys_msgCreate AI assistant agent and AI user agent from obtained system messagesâ€‹assistant_sys_msg, user_sys_msg = get_sys_msgs(    assistant_role_name, user_role_name, specified_task)assistant_agent = CAMELAgent(assistant_sys_msg, ChatOpenAI(temperature=0.2))user_agent = CAMELAgent(user_sys_msg, ChatOpenAI(temperature=0.2))# Reset agentsassistant_agent.reset()user_agent.reset()# Initialize chatsassistant_msg = HumanMessage(    content=(        f"{user_sys_msg.content}. "        "Now start to give me introductions one by one. "        "Only reply with Instruction and Input."    ))user_msg = HumanMessage(content=f"{assistant_sys_msg.content}")user_msg = assistant_agent.step(user_msg)Start role-playing session to solve the task!â€‹print(f"Original task prompt:\n{task}\n")print(f"Specified task prompt:\n{specified_task}\n")chat_turn_limit, n = 30, 0while n < chat_turn_limit:    n += 1    user_ai_msg = user_agent.step(assistant_msg)    user_msg = HumanMessage(content=user_ai_msg.content)    print(f"AI User ({user_role_name}):\n\n{user_msg.content}\n\n")    assistant_ai_msg = assistant_agent.step(user_msg)    assistant_msg = HumanMessage(content=assistant_ai_msg.content)    print(f"AI Assistant ({assistant_role_name}):\n\n{assistant_msg.content}\n\n")    if "<CAMEL_TASK_DONE>" in user_msg.content:        break    Original task prompt:    Develop


break    Original task prompt:    Develop a trading bot for the stock market        Specified task prompt:    Develop a Python-based swing trading bot that scans market trends, monitors stocks, and generates trading signals to help a stock trader to place optimal buy and sell orders with defined stop losses and profit targets.        AI User (Stock Trader):        Instruction: Install the necessary Python libraries for data analysis and trading.    Input: None            AI Assistant (Python Programmer):        Solution: We can install the necessary Python libraries using pip, a package installer for Python. We can install pandas, numpy, matplotlib, and ta-lib for data analysis and trading. We can use the following command to install these libraries:        ```    pip install pandas numpy matplotlib ta-lib    ```        Next request.            AI User (Stock Trader):        Instruction: Import the necessary libraries in the Python script.    Input: None            AI Assistant (Python Programmer):        Solution: We can import the necessary libraries in the Python script using the import statement. We need to import pandas, numpy, matplotlib, and ta-lib for data analysis and trading. We can use the following code to import these libraries:        ```    import pandas as pd    import numpy as np    import matplotlib.pyplot as plt    import talib as ta    ```        Next request.            AI User


Next request.            AI User (Stock Trader):        Instruction: Load historical stock data into a pandas DataFrame.    Input: The path to the CSV file containing the historical stock data.            AI Assistant (Python Programmer):        Solution: We can load historical stock data into a pandas DataFrame using the `read_csv()` function from pandas. We need to pass the path to the CSV file containing the historical stock data as an argument to this function. We can use the following code to load the historical stock data:        ```    df = pd.read_csv('path/to/csv/file.csv')    ```        This will load the historical stock data into a pandas DataFrame called `df`. Next request.            AI User (Stock Trader):        Instruction: Preprocess the historical stock data by setting the date column as the index and sorting the DataFrame in ascending order by date.    Input: None.            AI Assistant (Python Programmer):        Solution: We can preprocess the historical stock data by setting the date column as the index and sorting the DataFrame in ascending order by date using the `set_index()` and `sort_index()` functions from pandas. We can use the following code to preprocess the historical stock data:        ```    df = df.set_index('date')    df = df.sort_index(ascending=True)    ```        This will set the date column as the index and sort the DataFrame in ascending order by date. Next request.


the DataFrame in ascending order by date. Next request.            AI User (Stock Trader):        Instruction: Calculate the short-term and long-term moving averages for the stock data using the `ta.SMA()` function from ta-lib.    Input: The period for the short-term moving average and the period for the long-term moving average.            AI Assistant (Python Programmer):        Solution: We can calculate the short-term and long-term moving averages for the stock data using the `ta.SMA()` function from ta-lib. We need to pass the period for the short-term moving average and the period for the long-term moving average as arguments to this function. We can use the following code to calculate the short-term and long-term moving averages:        ```    short_ma = ta.SMA(df['close'], timeperiod=short_period)    long_ma = ta.SMA(df['close'], timeperiod=long_period)    ```        This will calculate the short-term and long-term moving averages for the stock data and store them in the `short_ma` and `long_ma` variables, respectively. Next request.            AI User (Stock Trader):        Instruction: Create a new DataFrame that combines the historical stock data with the short-term and long-term moving averages.    Input: None.            AI Assistant (Python Programmer):        Solution: We can create a new DataFrame that combines the historical stock data with the short-term and long-term moving averages using the `concat()` function from pandas. We need to pass the historical stock data, the short-term moving average, and


function from pandas. We need to pass the historical stock data, the short-term moving average, and the long-term moving average as arguments to this function. We can use the following code to create the new DataFrame:        ```    new_df = pd.concat([df, short_ma, long_ma], axis=1)    new_df.columns = ['open', 'high', 'low', 'close', 'volume', 'short_ma', 'long_ma']    ```        This will create a new DataFrame called `new_df` that combines the historical stock data with the short-term and long-term moving averages. The columns of the new DataFrame are named 'open', 'high', 'low', 'close', 'volume', 'short_ma', and 'long_ma'. Next request.            AI User (Stock Trader):        Instruction: Create a new column in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages.    Input: None.            AI Assistant (Python Programmer):        Solution: We can create a new column in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages. We can use the following code to create the new column:        ```    new_df['signal'] = np.where(new_df['short_ma'] > new_df['long_ma'], 1, -1)    ```        This will create a new column called 'signal' in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages. If the short-term moving average is


on the crossover of the short-term and long-term moving averages. If the short-term moving average is greater than the long-term moving average, the signal is 1 (buy), otherwise the signal is -1 (sell). Next request.            AI User (Stock Trader):        Instruction: Create a new column in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target.    Input: The stop loss and profit target as percentages.            AI Assistant (Python Programmer):        Solution: We can create a new column in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target. We need to pass the stop loss and profit target as percentages as arguments to this function. We can use the following code to create the new column:        ```    stop_loss = stop_loss_percent / 100    profit_target = profit_target_percent / 100        new_df['pnl'] = 0.0    buy_price = 0.0    for i in range(1, len(new_df)):        if new_df['signal'][i] == 1 and new_df['signal'][i-1] == -1:            buy_price = new_df['close'][i]        elif new_df['signal'][i] == -1 and new_df['signal'][i-1] == 1:            sell_price = new_df['close'][i]


sell_price = new_df['close'][i]            if sell_price <= buy_price * (1 - stop_loss):                new_df['pnl'][i] = -stop_loss            elif sell_price >= buy_price * (1 + profit_target):                new_df['pnl'][i] = profit_target            else:                new_df['pnl'][i] = (sell_price - buy_price) / buy_price    ```        This will create a new column called 'pnl' in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target. The stop loss and profit target are calculated based on the stop_loss_percent and profit_target_percent variables, respectively. The buy and sell prices are stored in the buy_price and sell_price variables, respectively. If the sell price is less than or equal to the stop loss, the profit or loss is set to -stop_loss. If the sell price is greater than or equal to the profit target, the profit or loss is set to profit_target. Otherwise, the profit or loss is calculated as (sell_price - buy_price) / buy_price. Next request.            AI User (Stock Trader):        Instruction: Calculate the total profit or loss for all trades.    Input: None.            AI Assistant (Python Programmer):        Solution: We can calculate the total profit or loss for all trades


Solution: We can calculate the total profit or loss for all trades by summing the values in the 'pnl' column of the DataFrame. We can use the following code to calculate the total profit or loss:        ```    total_pnl = new_df['pnl'].sum()    ```        This will calculate the total profit or loss for all trades and store it in the total_pnl variable. Next request.            AI User (Stock Trader):        Instruction: Visualize the stock data, short-term moving average, and long-term moving average using a line chart.    Input: None.            AI Assistant (Python Programmer):        Solution: We can visualize the stock data, short-term moving average, and long-term moving average using a line chart using the `plot()` function from pandas. We can use the following code to visualize the data:        ```    plt.figure(figsize=(12,6))    plt.plot(new_df.index, new_df['close'], label='Close')    plt.plot(new_df.index, new_df['short_ma'], label='Short MA')    plt.plot(new_df.index, new_df['long_ma'], label='Long MA')    plt.xlabel('Date')    plt.ylabel('Price')    plt.title('Stock Data with Moving Averages')    plt.legend()    plt.show()    ```        This will create a line chart that visualizes the stock data, short-term moving average, and long-term moving average. The x-axis represents the date and the y-axis represents the price. The chart also includes