In this last lesson, you will dive deeper into multi-agent group chats and build a custom group chat that collaborates to generate a detailed report and stocks performance over the past month. Finishing this complex task involves planning, which is realized by including a planning agent in the group chat. You will also learn how to customize the speaker's transition into group chat. Let's dive into the code. All right. In this lesson, we're going to learn about one last agentic design pattern, planning. And we're going to also learn a new conversation pattern called group chat. Okay. Let's get started. First, let's define our LLM configuration to be using GPT-4 turbo. Let's define our task. So this is a fairly complex task. In previous lessons, we learned about one conversation pattern called sequential chat that can perform multi-step tasks. But that requires a human to design The concrete steps and the concrete agents involved in each step. But if we want to simplify the problem, what if we want to simply define agents and make them work together to solve these tasks without getting on the specific, detailed instructions for every step? How can you do that? In this lesson, let's try a new conversation pattern called Group chat. Which doesn't require many design steps. First, let's import AutoGen, and then try to create a few agents that are needed for this task. Let's think about what do we need. Initially, we need a user proxy agent that can send other agents about this initial task. So, we'll define a conversable agent named Admin, we'll give it a system message about "Give the task and send instructions to writer to refine the blog post." And we'll set the code execution configuration to be "false" and give it a large language model configuration and set human input to be "always". So the this agent will always ask for human's input when it's his turn to speak. And if the human skips the input, it will send instructions to some writer agent to refine blog post. Let's think about what other agents do we need. Since this is a complex task, we probably need a planning agent that can help us decompose the task to simpler, smaller tasks and send those sub-tasks to other agents to solve them. So how about we create a planner agent. This is the conversable agent with name Planner. We give it some instructions: "Given a task, please determine what information is needed to complete the task. Please note that information will all be retrieved using Python code. Please only suggests information that can be achieved using Python code. After each step is done by others, it checks the progress and instructs the remaining steps. If a step fails, try to workaround." You also see an adding field called a description. What's the difference between the description and system message? The system message is an instruction and telling the agent only and only this agent needs to know. And the description, I am using that to let other agents know about the role of this agent. And for example, a manager could decides when to use this agent based on the description. So the description is planner. Given a task, determine what information is needed to complete the task after each step is done by others, check progress and instruct the remaining steps. So less detailed but more manageable and from a different person's point of view, we can know what this is about. And we also give it the large language model configuration. So the planner might suggest some tasks that requires using Python code. So, you might need some agent that's capable of writing Python code. So let's define an agent engineer. And going to use the default assistant agent from AutoGen as it comes from this agent. This is the default. This is agent we will have a default system message about detailed instructions for writing code. So we don't need to provide additional system message. I will add a description saying that this is an engineer that writes code based on the plan provided by planner. After the engineer writes code, we need some agent to execute code. So we probably need an executor. So this is a conversable agent with code execution configuration. Okay. So we will set the last n messages to be three. So this agent will look back in the comments in history and find, first message that contains code in the backward order, and execute the code in that message. Is that the working directory until the coding and is set user_docker to be false. Don't forget the task is about writing blog post. So we also need a writer agent that is in charge of writing. So we define this writer agent with the system message: "Please write blogs in markdown format with relevant titles and put content in the markdown code block." And will also tell it to take feedback from the Admin and refine the block. And we need to provide the description as well. Okay, so now we have created these agents. You can see that by creating each agent I need to think about what role this agent needs to play, and to solve this task, what are some of the roles I need to create these agents. I don't need to provide a detailed instructions about which agent should do what? First. I simply put them together in the group chat, here and creating a group chat with the agents I just created. There are five agents of them. I provide some initial message, an empty and initial message list and says max round to be ten. That's all I need. Before I make these agents work, I need to create a group chat manager as a special agent In AutoGen to manage this group chat. This group chat manager also needs a large language model configuration. So, I simply define these agents and put these in the group chat. And then, I can start the conversation by initiating the chat between user proxy and the manager. Because the first message I want it to be from the user proxy. And the message content will be the task we defined earlier. Let's try that. So, after I start the conversation. All these agents will automatically work together. And there's no need to specify a particular speak order from the developer. The first message will be sent from the admin, user proxy, to the chat manager about the task, and the chat manager will broadcast this message to every other agent. So every agent in the group chat will see this message. And then the chat manager will pick one agent to speak next. Using the large language model. And when deciding who to speak next, the chat manager will look at his current conversation history and the roles of each agent and decide which one is the best. So we see that the planner is picked as the first agent to speak. Okay, so planner is suggesting a few steps, including retrieving the stock data, analyze the stock data, research contextual events, draft a blog post. And in the last reiterate on step one. And suggest some actions. Again the chat manager now needs to pick the next speaker and picks the engineer. So the engineer will follow the suggestion by the planner of the first step and share the code to retrieve the stock data. Next, the executor is picked by the manager to execute the code and output the data. And now the planner is picked again by the manager. After the first step is finished. So it's suggesting the next steps about analyzing stock data, research, contacting events, etc... So, it actually suggested one Python code example to get started with the second step. So the engineer will complete that Python code. About this stock data analysis. And the executor is picked the manager to run the code and upload the result. You can see not only the stock prices output, but also the daily change. And when the first steps are finished, we see that the the writer is picked by the chat manager to start drafting the blog post, because the writer already has good enough information to begin writing. So it writes the blog post in markdown format. It has an introduction section. Analysis of stock price. Stock performance section, significant events and their impact and conclusion. Now the admin is picked by the chat manager. So this admin will ask for user's feedback. If I am not satisfied with this blog post, I can provide my input. Here, I'm going to skip my feedback and let this user proxy agent suggest some change on behalf of myself. Now, this user proxy agent is using large language model to come up with the reply. This reply should contain some suggestions about what needs to be improved in this blog post. So the admin comes up with some refinements including adding videos, detailed analysis, interactive elements, and so on. So after that, the writer is supposed to take that feedback and automatically suggest, a refined blog post. So we see that in during this conversation, all agents are trigger automatically by the group chat manager and following the predefined roles and descriptions. The roles and description need to be carefully designed to make sure they can follow the right order. Okay, now we see that the writer has made some revisions to the blog post. It also summarized the enhanced elements in the blog post. If we increase the amount of rounds in this group chat, there can be more conversations. This conversation stops here because we set the max round to be ten. So if we, review this conversation, we will find that the planner does play the role of suggesting an initial plan. And after some steps finished, it will review the progress and just follow the steps. But not all the steps are followed exactly. After the first two steps, I think the writer skipped the third step and started writing the blog post. This is downside of using language model to design and speak order always. But there a few ways you could, add more control to the conversation. For example, you. can set constraints about the speaker's order. I'll show you how to do that. First, let's repeat the same definition of agents. So these are the same agents I used and defined here again. And I will demonstrate, to add some constraints in the speaker order. So in this example, I create a group chat with additional constraints. this is a dictionary called "allowed or disallowed speaker transitions". For each agent you could specify which agent is allowed to speak after this particular agent. For example, we restrict the speaker after engineer to be either user proxy or executor. And we restrict the speaker after the executor to be either the proxy or engineer or planner. So after we impose this constraint, we're not supposed to see the writer to follow up executor agent immediately. So that gives the planner a chance to review the plan before the writer starts writing a blog post. You could either specify, allow or disallowed speaker transitions. In this case, we're setting only allowed transitions. Execute that. So after defining that, we're supposed to see a speaker order that conforms better with our desire. The first few steps are the same. But now, after the executor finished the second step, we're supposed to see the planner take over, view the previous steps and suggest the next steps. So this is fixing the problem I mentioned earlier. You see that although we added some constraints, the overall task completion is still non-linear. So this still keeps the flexibility of having some agent back and forth and chiming in when they need to. So this still has more flexibility than sequential chat. And this way of specifying on speaker transitions, can simulate the finance state machine transition in the group chat. So this is the best functionality to allow developers to add more control. You could also add some natural language instructions in the descriptions of the agents. so that you not only specify the constraint, but also has more details about when to translate to what which agent. And in addition, you could also define a precise transition order using programing language. I'll not cover that in this lesson, but you can find that information from AutoGen's website. To summarize, group chat provides a more dynamic way for multiple agents to solve a task together and without human developers to design very detailed plan for execution. You could also add some planner agents, for helping with making plans and task decomposition. In general, there can be multiple different ways for doing task decomposition and planning and where we want to show one example. That's all the lessons. We covered, the basic introduction to our AutoGen. There are many other advanced functionalities in AutoGen such as teaching agents will improve over time, having multimodality having vision capability to understand images. Using OpenAI assistant as a backend for agents and so on and so forth. We also have agent-based evaluation tools and benchmarking tools and other new interesting research. For example, how can users design agents for particular a task? Please find those advanced new features or ongoing research from our website and read the blog posts. We hope you enjoyed the lessons so far, and you explore much more interesting use cases if you are interested.