In this lesson, you will explore how to add coding capabilities to your agents and use the generated code to complete a financial analysis task. You will get to build two agent systems where agents collaborate to solve the task at hand while asking for human feedback. The first one will use the large language model to generate the code from scratch, and the second one will leverage user-provided to code. Let's start coding. How about, let's do some coding and financial analysis in this lesson? In previous lessons, we learned how to use AutoGen to create agents that are able to use tools leveraging the OpenAI tool use functionality. One limitation of that is many other models don't have the same feature. Or sometimes you want agents to be creative in writing free-style code, instead of only using some certain predefined functions. So in this lesson, we'll go over how to do freeform coding, including how to make agents that can generate code to complete a financial analysis task. And making a two-agent system where agents collaborate to solve the task and asking for human feedback. And we'll create two such systems, For the first one, we'll ask the language model agent to generate the code all by itself. And the second one will also consume a user-defined code. We are going to use GPT-4 turbo for this example. First, we need to create a code executer. Import from AutoGen. Coding an Executer called the local command line code Executer. There are several different types of code executing AutoGen, including Docker-based execution and Jupiter note-based execution. For this example, we will simply use the local command line code called executer. We are going to create executer. With some configuration. For example, we'll set the timeout element to 60s and we will set the working directory to be coding. So that creates the work direction here called coding. And all the code and intermediate results generated can be found in that folder. Now we're going to create agents where we will import conversable agent and another derived class called assistant agent from AutoGen. We will first create a agent that's able to execute code. So we use conversable agent named "code Executor agent." This agent doesn't use large language model, but it will use the code Executer to perform execution. It set the input mode to be "always". So it will always ask for human input confirmation before executing code. And if this agent doesn't find any code in the message it's received, it will reply "Please continue. If everything is done, reply terminate". Next, we'll create an agent that is able to write code. In this case, we create this assistant agent. The assistant agent is a special class of conversable agent with the default system message about, how to write code and how to deal with different conditions to solve a task. We name it "Code Writer agent". We gave it to the large language model configuration. And we said that the code execution condition to be "false". So this agent will only propose code not execute them. We set the human input model to be "never". So this agent will never ask for human input. If you are curious about the system message, defaults message is provided by the assistant agent. We could use this cell to print it out. So here are the instructions. It's so pretty long as this message and contains a comprehensive instruction about how to solve tasks using your coding and language skills. It will suggests a few cases where Python code or shell script should be suggested. For example, when the agent needs to collect information, it can use a code out of the information. For example, when browsing or searching the web, or downloading and reading a file. Second, when the agent needs to perform some tasks of this code, we ask the agent, to use the code to perform task and output the result and finish the task smartly. We also provide instructions about, suggesting plans and be clear which step uses code and which step uses a language skill. We have instructions about when using code, there are certain, format they need to follow. And we also let the agent know that the users would only execute the code. So, try to make the agent not such as incomplete code, which requires users to modify them. The code can be saved in the file if a particular tag is added inside the code block. We also let the agent know that the agent should check the execution result, and if the result indicates there's an error, fix the error and output the code again. And finally, we ask the agent to reply to terminate in the end when everything is done. And this is the default system message of the assistant agent. You could certainly customize this to make it a stronger coder. But we found this default message works pretty well in many coding tasks, including solving math problems. Now, let's move on. We have these two agents ready, so we can make them, work on some tasks. So, let's try to define a task about, financial analysis. We import the data time library, get it to this date, and define the task as create a plot showing stock gain year-to-date for Nvidia and Tesla. And we're on to the plot to be saved to a file. So that's the whole message. And, we can now start the conversation from the code executor agent. And the code executor agent will send the initial message to call the writer agent. So the code executor agent says "Today is 2024 May 2nd. Create a plot showing stock and year to date for Nvidia and Tesla. Make sure the code is in markdown code block and save the figure to a file. The code executer sends the initial message to the code writer. The code writer is provided with a large language model. We're using GPT-4 turbo, so now we're waiting for the GPT-4 turbo to generate a response from the code. The writer agent. Here is the reply. So the code the writer agent does suggest, how to solve this task using code. It suggests a few steps. Fetch the stock price data using yfinance, calculates stock gains, plot stock gains using matplotlib and save the plot of file. The code is suggested following that plan that contains all the steps. So now the user can verify the code. And if we have no issue with that, we can simply press enter to skip the feedback and use auto-reply. So now the code executor will execute the function, generate output. And send that output back to the code writer agent. So now set the code writer agent said script executed successfully and generated the plot. We can inspect whether the file is indeed generated. So now, since the code writer said terminate, I can type "exit" to stop the conversation and let's see the plot. We import the image function and show that in the notebook. So here's the plot file generated by the two agents. Okay. Looks good. And that is one way of making the agent write code in freestyle. We only need the default assistant agent from AutoGen and another code execution agent to perform this task. In case, you want more control about how to finish this task, You could provide some code you've already written and make the agent use them instead of writing the code completely by themselves. In the next, we will demonstrate how to do that. So let's say we already have a function about getting stock prices. We could define them here with our own definition. For example, we could import yfinance. And download the data and return the stock data. And we also want to add docstring about this function so that agent will have better idea about how to use this function. It looks good. And let's say we also want to provide a function about how to plot stock price. You could provide that function again with both docstring and function definition. Then let's assume we want the agents who only use these two user defined functions to perform the tasks. How do we let the agent know about that? Well, we can change the creation of the local command line code executer by adding this function parameter. So, we provide these tool functions in the list to the class action. Then the code executor will be able to execute these functions. Also, we need to let the code writer agent know about the existence of these two functions. The way we do that is, we will modify the system message of the coder writer agent, by penning some additional prompts not contend the knowledge of all these two functions. After we execute that, we see that the first part of the system message is the same as before. But after that, we added some knowledge about you have access to the following user-defined functions. They can access the from module called functions and then function names. For example, if there's a function called "foo", you could expand it by writing from functions import "foo" and now we added this concrete functions signature and docstrings into the system message. So this is done automatically when you call the executer dot format functions for prompt, will populate these instructions automatically based on the function definition. So users don't need to ask for work. They only need to write the Python functions in the normal way. And with this command we automatically register that system message to the original system message. Okay. Now we could, create the code registration again. This is the new system message. This time it will contain instructions about these two user-defined functions. And we'll create in their code execute their agent again. With updated code executer. Now, if we try the same task again. This time, we're getting the same instruction, except that we save the figure to a different file name. So, when we initiate the two agent chat again, we're using the updated code writer and code Executer with access to user-provided functions. So, this time we should expect the code the writer agent to leverage the user-defined functions. Let's check that. So, we got first to check the plan. The code writer said "We want to first identify the start date of the current year and then to utilize a function, get stock prices to download the data. So, this to get stock price is a function provided by the user. And after collecting data we use a function to the plot stock prices function to create a plot. This is also the other provided function. So we can see that in the plan the writer agent indeed, suggested using the two functions provided by the user, and then let's check the code generated. This time it will call this from functions in part these two functions. And and to write code based on these functions. So this creation of this functions module is also done automatically by AutoGen. We can see that in this case the code is much shorter because it's directly using the user priority functions for these two steps. And the code is also cleaner. So we'll press enter to escape the human input and is auto reply. This time the code executor will execute the code again. So, let's end the conversation and check the generated plot again. So, here we go. So, this time we use the provided stock price plot function to plot the price instead of the percentage of change of these two stocks. And also notice that we don't require any function call or to call functionality of the underlying model. So, even when you use a model that's not based on OpenAI or not doesn't support the function call feature, it's to be able to use the user-defined function as well. I want to mention, a few notes. So, first of all, when we check the Python code block, we see there's the line about the file name. So, when this line is there, the Python code suggests will be saved in the file with this file name under the specified coding directory. And but if it's not there, the code will be automatically removed after execution. Another note is, if we find the code is not meeting expectations, and we want to suggest some change to the code, we could provide that in code when the code executer prompts for human input, for example here. Only if we skip that, the code Executer will execute the code. If we compare the code execution and the tool execution, there are some differences. The code execution is a more flexible way to write any code the agent is capable of. It also has the flexibility of using user defined code. Just similar to the user defined the tool or function. But this code execution capability doesn't require the language model to have the tool call feature. There are pros and cons of these two different ways. For the tool call and function call: They are more restricted, but also more deterministic because, you know, only the provided functions will be executed and nothing else. For the code execution: it's not always the case. That also means, if you want the agent to be able to go beyond the provided functions, you can use code execution to do that. In general, the code execution capability, is very useful for many diverse tasks. To recap, we learned about the two ways of coding for AutoGen agents. One based on the default assistant agent and another based on additional user-provided functions. The coding capability is a very generic capability that can be used to perform many different tasks. You could explore more about different kind of codes executers or define your own code executer for different languages or different execution environments. We also learned that, human has a chance to provide feedback before the code execution, and different human input modes can be used for these agents. You could either, make them fully automatic or have human-in-the-loop. In the next lesson, we'll also learn about a more complex example using both coding agent, planning agent, execution agent, to compilation task using group chat, which is also a new conversation pattern. We're going to learn.