📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

ИИ-агенты — вот что действительно изменит разработку. Пишем ИИ-агент на Python, LangChain и GigaChat

Диджитализируй!48:36

Transcription

Hello, katana. I have prepared absolutely bombastic material for you today. I highly recommend watching until the end for those involved in development, for those who professionally write software. So, a spoiler right away. We won't be hyping about the fact that artificial intelligence can write code, that it will supposedly, you know, change the world of development, software engineering, that it will relieve businesses of the need to hire programmers, blah-blah-blah. This is not what we're talking about at all. Behind all this hype, the emperor has no clothes, because those people who will professionally develop software, including with the help of large language models, oh my god, they will still be called programmers. It's just that to the necessity of mastering the knowledge and the technological stack that programmers have now, the necessity of mastering one more tool will be added, and nothing more, dear friends. But, you know, uh, in the topic of artificial intelligence and large language models, there is something much more interesting, something much deeper, and much more important, something that will truly change development and provide new opportunities. And these are agents. What is this? So, to put it simply, an agent is a system based on a large language model that is capable of solving a task on its own, interacting with the external world, and making decisions independently. That is, there is a model that understands human language. It's a bit dumb, but it understands human language and has some basic knowledge about the world, about the fact that the Earth is round, and functions in Python are defined using the `def` keyword. We give this model specific tools to solve our task. That is, essentially, we give it the ability to call our specific code, which we will provide to this model. And the model, pay attention, decides for itself when to call our code and what parameters to pass to this code. What arguments to pass to our function? Once again, it's no longer us writing `if else` to determine which function to call, but the model itself makes the decision and calls the right function with the right parameters at the right moment. Imagine that this, in fact, is a huge paradigm shift. And this is something that is already working now. I will further show how it works and how to use it in practice. But let's try to comprehend what is actually happening, what this paradigm shift actually provides, and whether it is a paradigm shift at all. Yes, essentially, what are the programs that we have been writing until recently, for the last 80 years? According to various sources, the first program was written and executed on a computer either in 1943, 1943, or in 1944. Well, 80 years. The very first program that was written was written in the X century, by Lovelace, but there was nowhere to execute this program, so we take programs that were written and executed, yes, that's 80 years of programming. And essentially, for these 80 years, we have been writing programs that are not so different from each other. All these programs are built on three basic capabilities, right? Capability one is the ability to store and modify data. That is, we want to be able to write something into a memory cell, read something from it, and change what is stored there, right? Capability two is to make logical branching. That is, `if else`. If a condition is met, we call one piece of code. If a condition is not met, we call another piece of code. Logical branching. And capability three is the ability to repeat logic, for example, through loops, through `goto`, or any other possibilities. And that's it. This is enough. These three very simple capabilities are enough to write any algorithmizable task, right? That is, any programming language that provides these capabilities is a Turing-complete programming language and allows the implementation of any algorithmic task. There are no complex data types here, as you may notice, right? No complex data structures, no functions, no object-oriented programming, no, you know, nice syntactic sugar, right? But, using these three basic capabilities, everything that can be algorithmically solved can be implemented using these three basic capabilities. That is, you can write any little program, right? Of course, more high-level, more convenient programming languages have been created, on which you can write faster, right? On which it is easier to develop programs, on which many features are already implemented, all necessary libraries are connected, right? There is a large amount of syntactic sugar, but internally all this is implemented and all this is based on these three very basic capabilities: the ability to store and modify data in memory, the ability to perform logical branching, and the ability to repeat logic, for example, through loops or by other similar means through `goto` and so on, right? And what can the appearance of large language models change in this whole model? In fact, it can change a lot, dear friends, it can change a lot. In fact, we have a dummy who understands ordinary human language. I use the word "understands" in context here, of course, for a large language model. You just need to understand again what a large language model is. A large language model is an advanced text autocompletion mechanism. Advanced to the ninth degree. Okay, this is a rough analogy, but let's use it anyway, right? A large language model, LLM, is a tool that selects the most relevant next word, then selects the most relevant next word, then the next word, and so on. Yes, of course, taking semantics into account, yes, LLM tokens are not exactly words. Yes, of course, there are many caveats, but in general, it's roughly like that. It's just selecting the most relevant next text based on the previous text. So, with these caveats, let's say that an LLM understands ordinary human language in Russian or English. Yes, it's like a child who isn't very good at some complex activity, but they understand you when you say, "Please, my friend, give me a fork" or "Close the door" or ask how they are doing, they will understand you and will be able to correctly interpret your words and do what you ask. And with more complex things, you can ask them to call you, you understand? That is, if a child doesn't know how to do something, you can tell them: "Friend, when you need this, please call me, and I'll come and do it." Do you understand? And this "call me" can be a call to your code, any arbitrary code in any programming language, for example, in Python. And this code can do anything, right? The model will know about the existence of this code. You explain in the comments to this code, literally in the docstring comments, what this code does, what this code takes as input, what this code outputs. And the model understands this information because it understands ordinary human language, right? And then the model will itself request the necessary data. Again, it can request it from the user in the chat, it can request it from your other Python function, without any problems, right? And at the right moment, it will call your Python code, pass the necessary arguments to it, and solve the task that you are setting for this system. That is, you can literally write, for example, in Python or, in fact, as I repeat, in any other programming language, code that does something, what you need, exactly according to the algorithms that have existed for 80 years, with the same `ifs`, data storage, modification, and loops. And this function takes some arguments as input. They can be of complex types. It can be some nested data class. This function can return something, something complex as well, also some data classes with some data structure, and so on. And the model will understand all this, and it will know when it is necessary to call your code, with what arguments it is necessary to call your code, and will do it. Yes. And what does this mean then? It means that, if you think about it a little, it means that it's no longer you who branch the logic with `if else` in your wonderful programming language, but the model itself branches the logic within itself, the model itself makes decisions about what to do, right? Ask for missing data from you or from some other Python function, clarify something, go somewhere for data, gather the necessary data to call your code. and it will call your code when it is necessary. Yes. So, uh, I will now show how this works in practice. I am an entrepreneur and I often need to prepare accounting documents, invoices, acts, reports for various clients, and so on. I don't consider it right for myself to hire full-time assistants for such tasks yet. I'm not sure if I can keep an assistant busy for 40 hours a week, but someone has to do these tasks, and I'm doing them now. It's not rocket science, but it's quite tedious and boring. And I thought, what if I write an agent that will help me do this? How does it happen? So, someone sends me their details via email, and I need to issue, for example, an invoice or prepare an act of completion of some work based on these details. Yes, the details are sent in different formats. Sometimes it's a PDF document, sometimes it's a Word document, sometimes it's an Excel file, sometimes the details are just written in the text of the email. And all this in different formats. somewhere in a table, somewhere as text, somewhere comma-separated, generally in complete chaos. And I need to, accordingly, manually select different pieces of these details from there, cut them out of this document, and insert them into my template for an invoice, act, or any other document, and at the end, assemble a PDF, and send this PDF somewhere. I thought, why not create an agent for this task, so that it can independently extract details from this arbitrary document, pass them to my Python function, and my Python function generates a PDF. Here, of course, you can also make the language model itself generate the PDF. But, firstly, I want to control this process, so that only my template is used. And secondly, I want to control my details. I want my details to be correct. If I issue an invoice, for example, then I want to be sure that in the final document, which I will send somewhere, my details will be strictly correct, because, well, a model is still a model, right? And it's a probabilistic thing. It can mess up somewhere, right? If it makes a mistake in the counterparty's details, well, there won't be a big problem, right? But I want my details to be accurate, right? Therefore, I want my function to generate the PDF. My function will take the counterparty's details as input and will generate a beautiful, wonderful PDF with my correct details and the counterparty's details, which it received from the large language model. And as the model, I decided to use Sber's GigaChat. OpenAI models don't want to process requests from Russian APIs, even with paid accounts. And I don't want to solve this problem by messing with VPNs, proxies, and so on. Well, and of course, I was interested if the Russian model could handle this task. Those who are already reaching out: "I see everything, I see everything, damn it, you're going to write that this is an advertisement." Yes, of course, guys, it's an advertisement. But, damn it, what did you expect? I'm going to make a lot of money from this video. Yes, this is Sber's advertisement, undoubtedly. There's advertising here. So, what do we have here? Huawei, right? Here's Huawei advertising. So, here's Huawei advertising again. Pay attention, right? This is Huawei. So, here I have advertising, also Huawei, undoubtedly. So, what else do we have? Advertising, advertising for Woop, a brand of bracelets, advertising for Peneray. So, advertising for Logitech, right? Advertising for this Henderson. Henderson advertising. Well, I also talk about Python in almost every video. Guido van Rossum, undoubtedly, also pays me for this. So, envy, envy. Silently, dear friends. Here. Although, in reality, if you're interested in how this happens in practice, I spent several days developing this video and will earn exactly 0 rubles and 0 kopecks from it. I'm recording it now on Saturday, midnight, by the way, well, it's 23:59 now, right? Therefore, accusations of advertising are always, so to speak, very pleasant to me. So, guys, One love. One love. Yes, in reality, a big sincere thank you to those who buy training, educational programs from me. I have a course called "Hardcore Web Development." And those who come to study there, guys, this is all thanks to you. Thank you very much. Yes, the link is in the description of this video. You can also take a look, maybe it will interest you. Well, so, by the way, about GigaChat. It is the only purely Russian trained model at the moment. Well, at least, as far as I've Googled and studied, right? It used to be called RU GPT, and now it's called GigaChat. And it was trained on Sber's supercomputer Christofari, surprisingly, which is named after the first owner of a savings book in the 19th century, right? Yandex GPT version 5, it seems, uses N in some capacity, right? Tinkoff's model also seems to be on Quanta. There's some LLM from MTS, it seems to be their own, but I understood that it's not sold externally, it's used internally in some of their own tools. There's also VK, they made their own LLM last year, but I understood that they don't publish it either and use it internally for some tasks. I don't have much information about them. So, let's use GigaChat. Let's create an agent that will cheerfully and briskly solve the task of creating accounting documents according to my template by calling my code. So, we will use GigaChat with their advanced model, GigaChat 2 Max. This is the current, most powerful model from GigaChat at the moment, around mid-May. After registration, you get 50,000 tokens for free. Then you can buy a million tokens for 1,950 rubles. For the development and testing of the initial version, the first free 50,000 tokens were enough for me, but then I bought a package for further use. The source code is all on GitHub for what I got. The link is, of course, in the description. You can take a look right away. And I will show you more or less step-by-step how I did it. It's interesting. Create a directory, navigate into it. Do `uv init venv .` and `git init`. Initialization has occurred, including the Git repository. In the new version of `uv`, for some reason, you now need to pass `vcs git` to initialize the Git repository as well. Well, okay. Immediately add the necessary packages: `langchain`, `langchain-gigachat`, `langchain-graph`, and `python-dotenv`. To accept confidential data from environment variables. Open `main.py`. Add the necessary imports here. So, let's immediately activate the virtual environment so that my VS Code picks everything up. Excellent. So, here are the necessary imports that we will use in our development process. Load environment variables and create the GigaChat model. Take the most powerful model, GigaChat 2 Max. Nicely done. Also, let's create a `.env` file and paste the credentials for GigaChat into it, i.e., the API key. I named it `gigachat_credentials`, and paste your wonderful key here. On the right here is the act that we should get as a result, right? So, here the customer is inserted, which is taken from the counterparty's details, right? Here are all the counterparty's details, who signs this thing. And my details, they are hardcoded into the template of this document. And here there can be one or several lines with work performed. Accordingly, the total cost is summed up and finally written at the end of this document. Next, we need to create a function that takes the counterparty's details as input and outputs a PDF, saving it somewhere on disk. So, I will create the PDF using the `typst` tool. This is a modern replacement for LaTeX. I will talk about it in more detail in a separate video. It's a great tool. I really liked it for typesetting and layout. Yes, you can, of course, do all this with pure Python libraries, like `reportlab`, `fpdf`, and a huge number of other libraries for working with PDFs. But it's more convenient for me to use `typst` to solve the task now, so I will use `typst`. Therefore, here I create a `typst` directory. In the `typst` directory, I will have several documents. Well, let me show you what's inside this directory. The main thing is `act.typ`, right? This is the document template according to which the PDF will be created. This PDF consumes data from a JSON object. And the task of my Python function will be to assemble this JSON object. Something like this, well, essentially, just a JSON with the counterparty's data and their bank details. Yes. Well, one more library written in `typst` is used here, because `typst` even has a built-in scripting language, surprisingly. So, this is regarding `typst`. Next, for our wonderful function to work, let's create data classes, a data structure. Yes, we have bank details. Bank details include the bank name. Here you go. Yes, for Sberbank, there's the BIC, there's the settlement account, the correspondent account, there's the customer, that's our counterparty, right? They have a name, full legal name, OGRN, signatory, and bank. This is also a data class, nested, according to the corresponding bank structure. Yes. And there's a job. There can be several jobs, right? These are the projects that we include in the invoice or act. Well, in this case, we are preparing, preparing the creation of an act. Let's sketch out a skeleton of a function that will generate these PDFs for us in the future. I call it `generate_pdf_act`. Undoubtedly, the function name should be understandable, so that the model can also understand it, right? The function takes `customer` of type `Customer` as input, and the model will also understand this, undoubtedly, because it will call this function, and it should understand what needs to be passed to it as input, right? And it takes a list of `jobs` to form this table of work performed. It doesn't return anything. And pay attention, in the comment, I write everything here, right? Generates a PDF act with filled-in client data, their bank details, and also completed tasks. And what arguments of what types, what it returns. And here, for now, it's just a print statement, right? Later, we will implement the call to the necessary logic. Now, let's make it so that the model calls our function right now, and we can verify this through this wonderful print statement. To do this, I've put together this code: a class `LLMAgent`, a `main` function that communicates with the LLM agent. And here it starts. We'll look at how this code works a little later. But for now, let's just check its operation, dear friends. Yes, it also needs a `requisites_file` variable. This is a file where the wonderful requisites are located. Yes, I have uploaded this file here. Requisites for PAO MTS. Let me show you what this file looks like. I'll open this wonderful document. This is what the file looks like, right? This is a regular Word document with PAO MTS requisites. They bought my course. And, accordingly, I have this file with requisites. I'm currently preparing an act for them. Well, I was preparing an act when I was developing this system. Yes, excellent. So, let's call this thing. `python main.py`. `python main.py`. Here we go. Uh, `requisites_file`, of course, needs to be specified. The file with requisites is specified, and we call it. The LLM tells us: "Please specify what work needs to be included in the act. Write the name of the tasks and their cost." Well, let's write. CRM system development 200. Well, let's say 2.5 million. Like this. And our function was called. Pay attention. That is, this `print(generate_pdf_act)` is called from our wonderful function, which we wrote here. Here it is, please. Here, this print statement worked. That is, now the LLM called our function `generate_pdf_act`, which we wrote here. Here it is, please. Pay attention, it was called with these arguments, right? That is, a data class of the correct structure was passed, right? That is, it actually read the Word file that I showed you, and actually extracted all the correct details for Mobile TeleSystems, the address, all the bank details, and so on. And here are my details, which I entered here. CRM system development, price 2.5 million. It correctly selected everything from there. Let's exit here with Ctrl+C. The program even prints "goodbye." What a polite, good program, right? And let's look in more detail at the code that I put together. Well, the entry point to the program is `if __name__ == "__main__":`, right? The main function is `main`. Let's go into it. The model, by the way, doesn't need to be created at the top anymore. That's an old version. So, here the `system_prompt` is set, the system prompt. That is, this is the prompt with which our thing is launched, right? Your task is to generate an act. To do this, you need to take the counterparty's details from the attached file, and also request the work to be included in the act, the name of the tasks, their cost. There can be several tasks. Do not invent any data. Strictly request everything necessary from the user. Shorten the first and middle name of the signatory to one letter, for example, Ivanov AE. Enclose the company name in quotation marks, like "OOO Rog i Kopyta". That is, put an opening quotation mark before the company name and a closing quotation mark after the company name. The model is the same as the one we created before, right? GigaChat 2 Max. The model, in principle, can be any, right? That is, the `Langchain` tool is used here, and it can be OpenAI, and anything else. All of them have APIs and connectors to this `Langchain` tool. So, here our `LLMAgent` class is created. Let's dive into it and see what's happening here, right? It takes the model and `tools` as input. What are `tools`? `Tools` are the instruments that we give to the model to perform our tasks. In this case, we give one tool, `generate_pdf_act`, that is, the function that generates the PDF, but in this case, it just prints for now. We will implement the actual generation later, it's not difficult. It's already clear how it happens, right? So, this `LLMAgent` class saves the model internally, creates an agent using the built-in function in `LangGraph`, `create_react_agent`, passes the model, passes the tools, and passes a `checkpoint` so that all messages in this chat are saved. In this case, they are saved in memory. For production use, of course, you need to save the context, that is, the communication history in a specific chat, somewhere in PostgreSQL. Again, there are connectors for saving history in PostgreSQL. All this can be used without problems. And in the `config` that will be passed further in the chat, the identifier of this chat is passed, right? Because for the model to use previous communication in this chat, it needs access to this communication, and specifically to this communication, not some other, right? Therefore, each communication, each chat, right, that you create in the web interface for working with the model, which you have surely seen, these interfaces, right, in ChatGPT and so on, each chat has its own identifier. In this case, with each output, a UUID version 4 is generated. And within the scope of this session, that is, within the execution of this script, this identifier will be the same, because it is stored here in `self.config`. This `LLMAgent` has several methods, well, essentially only two methods, right? Method one: `upload_file`, that is, uploads a file from the local computer to the LLM model, in this case, to GigaChat. And `invoke` is a call to the API to get a response, that is, sending a message to the chat and getting a response, right? The `invoke` function creates a message, and optional attachments are passed to this message if they exist. The role is `user`, from whom the message is sent, right? And `content` is the content that we ask the model to send. It returns the message and as a string, right? A completely simple, elementary class, right? Accordingly, the system prompt is set in the main function, the model is created, the agent is initialized, the file is uploaded, right? Which I showed you earlier, right? This is a Word document, `requisites_file`. And then we call it, passing the system prompt with this file to this model. And the model responds to us, saying something like, "Please enter the requisites, right?" And then `while True`, we have communication with the chat. Moreover, this communication can be anything. That is, we can, in principle, create an act, and then ask something else, right? And, well, yes, this communication will take into account previous communications. That is, the first message about preparing the act, it can have some influence on future communication, but what I mean is that this is a regular LLM, GigaChat, and we can communicate, in general, on other topics as well. That's why the chat is implemented here as an infinite loop. Until we exit with Ctrl+C from the chat, everything will work, and we can continue communication with this wonderful chat. Also, the temperature is set somewhere here, right? It's set to a default temperature of 0.1. So, to make the model fantasize more, you need to set a higher temperature. To make the model

It provided more deterministic answers, you need to set smaller values, for example, 0.1. In this case, I don't want it to fantasize, yes, I want the answers to be as deterministic as possible, so I set the temperature to a small 01. So, well, that's it. Let's implement the generate act function now. Here is its implementation, which is not complicated at all, yes. We simply, you know, form a JSON. We write the JSON to filt.json. This JSON contains the counterparty's data, their bank details. And then we simply call types via subprocess for compilation, that is, for generating the PDF document. And that's it, we have a PDF document. Yes, let's, let's run this thing again, and see, see how it will work. Please specify what work needs to be included in the act. Specify the names of the tasks and their cost. Well, let's say ERP system development. And let's write it like this. 2 million rubles. Okay. And let me open the PDF file that was generated right here. It's in the Types directory. Note, ERP system development 2 million rubles. Total cost of work 2 million rubles. Everything works perfectly as we wanted. But, dear friends, this is an LLM, and in fact, we can use it in a more complex way. Yes, add another project for 1.5 million rubles. Telephony system enhancement. Let's see how the model handles this. On the right, we will have the updated PDF document, because it will be saved here as well. Note, telephony system enhancement 1.5 million rubles. It understood that 1.5 million is this much, right? And everything is calculated correctly here. 3.5 million. Everything works perfectly. Remove the first, first job from the act, yes? The first job is ERP system development. The second job is telephony system enhancement. Let's see how the model handles this. It handled it perfectly, yes? Telephony system enhancement. Change the cost of the work to, we currently have one and a half million, to one million. Let's write it like this. Change the cost of the work to one million. Will the model understand us or not? Note, it understood us. It was one and a half million, now it's one million. Yes, and this all, like, works. This is how simply everything works. Dear friends, imagine, imagine, say it's cool. Say it's cool. And these are precisely the capabilities that LLMs give us, yes? That is, the ability to understand ordinary human speech and, at the right moment, call our code that performs our necessary tasks with the correct parameters that the model took from the user or from our other Python function. Imagine, imagine, and this is what truly inspires me, this is truly a paradigm shift. This truly offers new possibilities, because we don't write if-else, but the model makes the decision when to call our code, with what parameters, and it does it. And it does it very beautifully. When I created this thing, I thought about the possibilities it offers, and I thought about the following: why not ask the agent to find the file with the details independently? Because now I give this file to it myself, yes, it's on my disk, I give the path to this file, and, accordingly, the model doesn't have a question about where to get the details. I directly ask, get the details from the file, yes, but the details are somewhere in my email. What if I ask the model to go to my email, to my email inbox, yes, and find the details there? Exactly like that. Find the details there for generating the act. I set myself this task and thought about how to do it. Yes, what is needed for this? For this, we need to write two additional functions. Function one. This is a Python function that will go to my email inbox, retrieve emails from my email inbox for a certain number of recent days, and return them as a list of data classes. This data class will contain, accordingly, the necessary data for each email, yes, this is the subject of the email, yes, this is the text of the email, and this is the attachments. All attachments must be downloaded to your local computer, where this Python code is running. And the path to this file must also be returned in this data class, yes? And we need to implement another tool, another Python function, that uploads the file from the local computer to the servers of the large language model, yes? That is, we need to complete, create two more tools. Now we have one tool that we pass to our AI agent. This tool generates a PDF act. So, we need to create two more tools. One tool goes to email, retrieves emails, and the second tool will upload some of the attachments to, essentially, the large language model servers. Let's do it. I'll show you how it works. What did I do here? I added the mail.py file here. This is a file that handles communication with email. So, what's happening here? Here we have aopostupport Yandex mail. These are not needed. I used these for debugging. All of this can be removed. So, we have the email data class. A list of these data classes will be returned from our function that retrieves, retrieves mail, yes? We have the subject, body, attachments, a list of local filenames, yes, and the date of the email. Here are a few utility functions for working with dates on the server, yes, a few exceptions, again, clearly named. Incorrect variables. Environment variables are used here to get, you know, the credentials for the email, yes? They are not passed as input to this function because this function must know this data internally. Or any here can simply be set, yes, by variables, or simply obtained within the function, yes. An empty array of emails is created. And we simply go, in short, to the email and for the specified number of days passed into the function, yes, here it's equal to 3, so for these 3 days or for these 4 days, 5 days, with what parameter we call this function, we retrieve, retrieve emails and simply return them, yes, we form an array of emails, in which, you know, we add an email, yes, subject, body, attachments, and date. And we return these emails. This is regarding, you know, this mail.py file. From this mail.py file, fetch recent emails. Yes, load the latest emails here. And, note, we were passing one tool to the agent, generate PDF act, and now we are passing two additional tools. Yes, the first tool is fetch recent emails, for getting the latest messages from email. And the second tool is upload, email attachment, file to LLM, in order to upload the file to, you know, the LLM. Moreover, the files that are uploaded to the LLM, I print them here to see which files will be uploaded to the LLM, because there are actually several attachments. There are actually several attachments. Dear friends, well, essentially, yes, let's print this thing too, so that you can be convinced of this. Well, here in mail.py, when we have a filename, I will print it, that we have such an attachment, just so we can see the number of attachments in the email, and compare it with the files that the model decides to upload. This is interesting. This is interesting how it will work. The prompt has also been changed here, of course. The old prompt is commented out. It can be used. So, the new system prompt, yes? Your task is to generate an act. To do this, you need to find the company's details, the counterparty's details in my email. They can be in the email text or in an attached file. Do not search for or request my details, they are in my code. For the act, you need to request the work, the names of the tasks, and their cost. There can be several jobs. Do not invent any data. Strictly request everything necessary from the user. The name, patronymic, of the signatory. Similarly, shorten to one letter. Enclose the company name in quotation marks. Well, essentially, as it was before. And, and, essentially, that's it. And, essentially, that's it. That is, we have simply added, added two tools, slightly changed the system prompt, and that's it. Let's see how this thing will work. I've closed the PDF for now. First, I need to get access to your email to extract the necessary counterparty company details. Specify the number, please specify for how many recent days you need to view the email, and also tell me what exactly the work is. Ah, 4 days. Ah, 4 days, and the work. Ah, for example, ERP system creation 3 million rubles. Whoops. Let's see. Ah, 4 days are set, yes? 17 emails found in the last 4 days. It understands that there are several attachments here, one, two, three, and it uploads them to itself, note, it uploads only the file with the details. This picture file it doesn't upload, meaning it understands that in this email, there are likely details, yes, and it uploads only this file with the details for analysis, yes, let's, let's open it and see what kind of PDF it is. Whoops, yes, ERP system creation 3 million rubles. Yes, everything is absolutely magnificent, dear friends. However, dear friends, I see that the details here are incorrect. The signatory Ivanov, the signatory is not Ivanov in the details file, and for some reason it shows Unicredit Bank, it's not Unicredit Bank. That is, we see the classic hallucination problem here. The classic hallucination problem. Therefore, we need to, you know, explain to the model that it should not invent details under any circumstances. It should strictly take details only from the file in the email. So, in short, right at the moment of recording, we caught a hallucination. The model had incorrect details, which the model simply made up, yes, the last name and patronymic of its signatory were incorrect, and so on. In short, I have now studied and realized that if many actions occur within one AI agent, that is, within one agent, searching for an email, uploading this email to the model's servers, analyzing the details from this email, from this uploaded file, yes, and generating a PDF act, then the model starts to hallucinate. I could not find a prompt that would solve this task within a single AI agent. Therefore, I simply broke the task into two AI agents that work sequentially. The task of the first AI agent is to find the file with the details in the email, and the task of the second agent is to generate the correct act with the details taken from the local file, and the second agent knows nothing about where this file came from. And in this configuration, it works wonderfully, dear friends. Ha, in short, how it works, yes? We have the first agent, its prompt is this. Your task is to find a file containing the company's details in one of the emails. Find the name of this file in the email and output it as the answer. In the answer, only the filename or the word "no" if not found. Accordingly, the model is exactly the same. We create the first agent. It has only one tool available. This is fetch recent emails, yes? That is, simply downloading the latest, latest emails. It doesn't even get the ability to download any file for analysis. It simply looks at the emails and searches for details based on them. We get the answer and save it immediately to filename, because we asked the model to respond either with the filename or the word "no" if not found. If, accordingly, the word "no" is returned, then we exit, nothing worked, we couldn't find the details in the email, yes. Otherwise, we create a new agent, yes, that is, the second agent, which, essentially, has only generate PDF act available, only the PDF act generation function. So, we then upload the file that we received from the first agent to this agent. Here is the filename, yes? And, essentially, that's it, we set a new prompt. This is exactly the same prompt that we had before. Your task is to generate an act. To do this, you need to take the counterparty's details from the attached file, yes? Accordingly, we attach the file to this prompt, which was previously uploaded. And thus, everything works. Dear friends, let's, let's run this thing and see, and see how it will work. anmain.p, 17 emails found in the last 3 days. Now it didn't even ask me for how many days to download emails. Well, okay. Composition of work, for example, ERP development. Well, some amount of rubles, many, many rubles. The act has been successfully created. ERP development 10 million rubles. Everything is precise, dear friends. Change the cost to 2 million. Moreover, the details are correct now, yes? Charaeva. This is the correct signatory, the correct bank, MTS Bank, and so on. Well, here it is 2 million rubles, the cost has changed here. So, two AI agents wonderfully solved this problem, although one AI agent did not solve it for some reason, yes? That is, we can create chains of AI agents. Each of the AI agents performs some simple task, but the overall thing can be quite complex. Dear friends, cool, cool. Well, just think about what we've done. We've created an AI agent that goes to email, finds details there, and creates an automatic act from these details. Imagine how we would solve this task with if-else, dear friends, how we would solve this task with if-else. And AI agents give us this opportunity. Imagine, imagine, that is, essentially, we describe the business logic in ordinary Russian language, and we write our code in the format of connectors, yes, there can be any logic. It can be complex logic, but in this task, it's simply connectors to the external world. That is, the AI agent must interact with the external world to bring some practical benefit, to solve some practical task, and not just be a chatbot, yes. And we, accordingly, write our Python code for connectors to the external world, and the business logic is described essentially in ordinary, ordinary Russian language. So, there used to be such systems, BPM systems, but they existed. There are Business Process Management systems, systems for managing business processes. And there is even such a notation, BPMN, Business Process Management Notation, probably, yes, where such diagrams are drawn, yes, and with the help of these things, we can automate business processes, yes, and a BPM system will call those very connectors to the external world within itself, yes, create a meeting, ping an employee, ask for approval of a document from a manager, and so on. Essentially, now with LLMs, we have the opportunity to discard all of this and simply describe the business logic in ordinary words. In ordinary words, simply in Russian or in English, as we prefer. And those very connectors to some external world will also be written in Python or in a programming language familiar to us. And this is the first thought. The second thought is that, note, we did not create any interface here. The interface is the chat, but because at the core of the chatbot is such a dummy that understands ordinary language, it can serve as an interface, yes? That is, once again, yes, add another job. CRM development, say, 3 million. And it will do it now. And it will do it now, that is, it will add another project. We had one project, ERP development. Now another project will be added here, CRM development. Note, 3 million. The total cost, it became 5 million, and we didn't write any interface for this. What if we had to write an interface for this now? Well, how else can this be used? Well, like, an interface is needed, yes? Accordingly, we would need a frontend. On the frontend, we would need some design. Okay, we could take some ready-made template, but we have to think about it. We have to look for a ready-made template too. Bootstrap, not Bootstrap, what's popular now, yes? We would need some JavaScript binding, how would we add these jobs, these items, yes? That is, there would need to be a button to add an item, click this button, and some form appears. In this form, we enter the item name and its cost. Items can be edited, yes, that is, after adding, this information needs to be edited. That is, on the frontend, there should be an edit button, yes? There should be a delete button. If we want to delete an item from here, then here we simply write text, delete some line, yes, and it will delete it. And on the frontend, all of this would need to be written. We would need to write frontend code for this, of course, in React, not in React, in anything. And we would need to write backend endpoints that would process this, that would accept creation, deletion, update, and so on. But here we don't need to do any of this. We simply get, essentially, a frontend in the form of a chat. And it simply works. Moreover, this thing, well, here it just generates acts, but we can also create an agent that generates acts and invoices. For example, one AI agent will generate acts, another will generate invoices, and a third will coordinate their work, for example, yes? And then we can ask the agent that coordinates the work to do both the act and the invoice at once. Yes? And again, we wouldn't need to do anything for this, because we already have an agent that does the act, we have an agent that does the invoice. And our coordinating agent will simply call one AI agent first, then call the second AI agent, and we will get the result. And on the frontend, we would again have to create some logic for this, create some frontend, some button, because we have a button to create an act, a separate button to create an invoice, and then we would need some third button to create an invoice and an act. But here, nothing like this needs to be done. Here, we simply do everything we need in Russian. At the same time, note, for example, for some reason, yes, we created an act, and they respond to us: "Damn, sorry, but the signatory is incorrect in our details, the signatory is not Charaeva Yuven, but - Pupsik Ivan Vasilievich, yes? Our interface might not have such logic, well, we didn't plan for it. Well, we didn't plan for it, yes, well, like, why? The data comes from somewhere, whatever the person entered, that's what will be there, yes? But here we don't even need to plan for this, we can simply replace it. Replace the signatory with Pupsik Ivan Vasilievich. Whoops. And this thing will now, apparently, replace it. Yes, indeed. Here Pupsik Ivan Vasilievich appeared. Well, say it's cool. Say it's cool. And this truly offers new possibilities. This truly offers new possibilities. Yes. It's not about the fact that artificial intelligence can write code. Once again, all of this is secondary, all of this is nonsense. But this is cool, this is cool, this is useful. And if you listen to Zuckerberg's speeches, listen to the head of Nvidia's speeches, they all say that in the coming years, we will see a total boom in AI agents. By the twenty-something year, it is expected that the number of AI agents developed and functioning will be greater than the number of people living on our planet. And I easily believe this. I easily believe this, because this is the thing that truly offers new possibilities, truly changes the paradigm in which we create software and in which we have been creating software for the last 80 years. Now it can be done with the help of AI agents and new possibilities can be obtained. M, cool. Yes. I want to show you one more thing, dear friends, that this thing works normally with different documents. Here I have a bunch of company details that I recently worked with, to whom I issued invoices. Here, Yandex, an employee is studying with me, Rosbitchestra, a Linux developer, Astra is studying with me, Promstandart, RTK IB, VK Digital Technologies, MTN Integration, MTS, the one I showed you. All these companies paid for employee training in my hardcore web development course. By the way, you can also ask your manager to pay for your company, pay for the course and come to me to study, if you suddenly want to. Ah, well, yes, let's check that all of this will work normally with these files, that this thing won't stumble anywhere and everything will be fine. For this, I have rolled back the edits for searching for details in email. And simply, yes, we take, we take the file that is in constants.file and work with it, with this wonderful file. Well, let's try RTB. This is also a docx file. Let me open it and show you what it looks like. Well, Rostelecom. Company Rostelecom Group RTK Information Security. Let's check if everything will work precisely with this file. Precisely. UV run. Because I didn't copy the DocX for some reason. Docx, yes. Okay, like this. Uvrunmain. Running. Well, let's. Student training 170,000. Employee training should be written. Well, it doesn't matter. Wonderful. ORTK and B Nester and NN UGRN. Everything was picked up perfectly. Run with this file. Well, let me just copy from here. The act has been successfully formed. Here, OPM standard Kochetkova for Sberbank. Everything also worked perfectly. Let's go further. Yadroaps. Let's check for employee training at Yadro. Yes, wonderful. Yadroaps marshin. Everything worked magnificently. Bitchekhastra. Let's check. Well, you see, here are different doc, docx, pdf, yes, everything works wonderfully. And the details are extracted correctly. Say it's cool. Say it's cool. Moreover, the format of these documents is, like, completely different. That is, the information is presented differently in all these files, but everything works wonderfully. For example, Bittech. Let's see how the details are here, here in such a table, yes, and the previous file we analyzed, here in such a table, yes, and a PDF with a bank, dot, yes, such a table, yes, then Promstandart, here is such a file, yes, in this form, but with all these formats, everything works wonderfully. Here, Rosbit Astra, please. Everything, everything, also beauty. Well, let's try Vkontakte as well. Will it work with Vkontakte? Everything is precise. Let's check. Whoops, whoops. Let's restart. What are Vkontakte's details? Let's, so, Bagudina Elena Evgenievna, signatory and INN. Let's copy this. Yes, Bagudina and the INN are correct. Well, everything works wonderfully exactly as we want. Cool. Here are such wonderful AI agents, changing our world in real time, practically here and now. And you can use this, it's available to you. You can really use it right now. Imagine? Think about where you can apply this. Think about what you can do with this. What pet project can you create with this? What can you add to your GitHub, what can you add to your resume, or maybe you'll start some business with this. There are a huge number of possibilities here. And think, think. Thank you for watching, and let's stay in touch. Until the next episodes. Bye-bye. Bye-bye.