Build a ChatGPT Bot with State using Microsoft Bot Framework SDK C# & OpenAI GPT-4 API Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay hello everyone so this is the new feature that is available in teams where we can choose Avatar um let's try to build State Management chatbot using bot framework SDK this we have already built using the composer in one of our previous sessions now let's try to build that using the bot framework SDK I'll pick up the echobot template and let's go next gpt4 let's use gpd4 this time chat bot all right so now before starting with Let's uh simply run this application we'll be going step by step like initially we'll be just integrating gpt4 and build a stateless boss bot and then we'll build a state full bot okay so here it's just a simple Echo bot whatever we type it replies back with the same thing so now let's go to platform dot open AI get to the documentation sorry API reference chat and we'll be integrating with this one okay let's start we go to our bot class before that let me see uh what is the dotnet version this project is using okay it's dotnet6 that's fine now let's go to Echo bot class so we can name this as GPT bot okay and now this is the place let me increase the screen size [Music] 125 yep okay so this is the piece of line where it gets the message that is sent by the user in the channel and this is how it replies back by appending yeah basically here it appends the Echo and this is how it replies back to the channel so let's get that message first the uncortex activity dot text let's get rid of this statement and now let's call our method VAR response stay GPT response equals to a weight get GPT response and we will be passing the text as the parameter let's create a method out of this and instead of reply text we'll be just sending the GPT response before sending the GPT response first we need to check if it is null or having some value so if it is not null if it is not null we just send the response if it is null we send a standard message sorry I didn't understand that so how I get this message as the intellisense because I'm I'm using GitHub Copilot so it's a really good extension for visual studio where it helps you write code much faster so what it says cannot assign void to an implicitly type variable so you need to understand the error messages carefully so these are all the standard error message that you will find it says cannot assign y to implicitly type variable so this VAR is implicitly type variable and it requires certain object as the response not as a void so here it is currently as a void so we'll be just passing string yeah and we are also expecting the response as null because response can be null as well so we'll just pass a question mark it says the other the response is string or either can be null okay now since this is asynchronous we'll be also adding a sink okay and is the question mark there or here nope it's there only yeah for specifically targeting the data type we can change this word to strain and this question mark this tells that okay we can also get a null response all right so let's call an API so copilot will suggest me with the code let me write a comment call GPT 4 API and let's say whether it generates the code or not nope call and API with a post request and Json body no it's not working as of now let's manually do it so we'll be just using it was suggesting Something There It Is there it is so let's use this as the starting point of calling our API we'll be importing HTTP client will be also importing the encoding and also Newtons of Json f so this is a standard code for calling any API by passing Json body if you are not passing any Json body we can just get rid of this parameter here it's a postdressing and let's get to the documentation this is the API endpoint that we need to use and what is the syntax of this body we just send it here and let me add a dollar sign so that I can pass on the variables inside this one so I'll just copy paste the good part of Visual Studio it automatically pass or like add this what we call Escape characters if we have double quotes in the Json so these are all Escape characters because we are using Json syntax and Json does not add this if you just remove this it will just throw an error so if you are adding Json Properties or double code characters you need to escape that with this slash now get rid of this extra characters we do not want that okay instead of hello we will be just changing that to our variable that is text and yep that is all now instead of GPT 3.5 we are just changing that to gpt4 and this is this is the one that is reading the response after we get the response back from the API and it stores the response as a string into this property and how we can retrieve the values so it is using this completion so basically the response will be in here inside choices message content so here we need to write choices next property is message uh choices is an array so we need to take the first element of the array inside choice that is first element take the message object and inside message object take the content property here we need to just pass on our last property content okay so this should get us the response basically this particular content that we have received from gpt4 API and one more important thing that we are missing here is the headers so let's see how we can pass that headers okay perfect now let's copy paste this here and let's copy paste the token and how we need to pass on the token that is authorization is my header key name yes and b error plus and this is the place where I'll be passing my API token to pass on the API token I will add them to my app settings.json file let's create a new object open AI and let's pass on API key Also let's pass on the API endpoint yep then we can get get rid of all the hard-coded values that we have in our code let's copy paste this here and in order to get the values from the app settings.json let's call Private read only I configuration this eye configuration contains the values data part of the app settings.json and here we need to initialize that okay so now we can make use of this underscore configuration to retrieve the app settings property configuration and this is how you can call any property so since it's an object we take the object name in the API endpoint so you need to add colon in between if it's directly a property then you can just use the property name okay so now we need to add the token as well the API key so similar process configuration open AI API key yeah and this is a post request and we need to get the body as well like exactly like this and it has a copy pasted my Json content from Below okay and so this is the place what we can do we can combine this implementation inside this method so it will be easier to do so what response and let's copy paste this one request and that is all and so this one is throwing an error because that semicolon is added at the start and the double quotes needs to be wait a second let's see uh where we are missing the brackets so this bracket is this one and that should be the end of it yeah so what response and let's get rid of this statement and yes that is all and at this moment it just gets me the Json response in a string variable and I just need to return this before returning this I need to pass my Json response and then retrieve its value okay and then we can get rid of this completely and also this method let me just format the document this looks much better so gpt4 row user content text and yeah now another error message not all code red path returns a value because we are returning the value from the track H we are not returning any value from the catch block from the try block we are returning it but from the catch block we are not returning it so before returning let's add something on the console and let's return one okay okay so that is all is required here now let's see let's add the API key and let's test this out okay Let's test this if this works our bot is running let's restart the conversation this is a welcome message let's say hi hello how can I help you today so this is giving me response let's ask something else let's say so you might already know it will take time for the response if it is a large response okay there it is so perfect solution and it's also nicely formatted test science and let's add oh I think one middleware in order to add the typing indicator yeah let's see if this works so by the time the response we are receiving and it takes time it will show a typing indicator if the response is pretty quick it will not show then now let's ask something who is the first test man alive uh nope it's not working yeah there it is it is working it is sending that typing indicator as the activity and we do not want to show these activities hopefully this should not be visible in the production environment it is only found in the emulator all right so this seems to be fine now we need to convert this particular invitation and implementation into a stateful implementation like it remembers what you have said last time combines clubs them together and gives you the response so that you can have response like a conversation let's say who am I it will reply with that I do not know yeah please provide me more context so if I provide the more context initially it will reply me hello JD but if I ask again it will again Ask me same thing yeah so see here it is now not able to find who am I because each conversation is just one to one we are not storing any previous response of both user and the chat GPT and let's see how we can build that on this case can be little bit complex let's see the best and basically the best one and production friendly is to use the database to store the conversation um let's see let's see that let's use the database that will be much better and will not be using database we'll be using the storage account let's create a new Resource Group GPT 4 State full board let's add a storage account we also need a lot of details about the user in order to make this work because since we are storing in the storage account we need to add few properties related to the user such as their conversation ID or user ID along with their emails if it is available to make it work and for easy way okay let's use the emulator for now let's not go with the teams Channel Okay so let's do it I am going to create an interface before that let me add a folder services inside Services let me create an interface yeah and also implement this interface storage helper and we need to inherit from this I storage helper and now I can add all the like I can Implement all the methods that are part of my interface into this storage helper let's first add The Constructor inside Constructor we need to initialize our iconfiguration so that we can retrieve the properties from our app settings.json file okay so this is the first piece and next piece let's ask a copilot to write something for us um insert entity to azure table storage let's see and there we have first we need to create a table client and that is the wrong code it is not using the standard libraries um let's delete this one and let's make it very specific using azure tables storage SDK I think that should be fine uh let's see whether it generates ah it just generates some random documentation okay that's fine let's go to the documentation and see it quickly that's Azure Cosmos DB and let's see if it uses the same piece create a dot yeah this is the nuget package that we need to add let's add a let's get rid of this one okay the next piece is stored in the connection string that's fine let's do it in the app settings.json and here we need to the table service client let's copy this let's copy that method not public it should be private okay uh so for now let's make it using thread okay we are going to get the connection string from here there is a object connection strings where we can initialize all our connection string let's say storage account and create a table so after this no after this we are going to create a table with the name that we pass string table name table name and here we need to use configuration dot get connection string and what is the connection string name storage account you can also use the similar Syntax for getting the app settings value like square brackets and connection string object Name colon storage account since this get connection string method is already present so we are making use of that okay so what it will do it will get me the it will create a new table and it will also get in the table service client uh no it should get me the table client not service client because table client is what is used to do all the operation now I can return change the return type 2 table client yep so this is the first piece that we have implemented now let's go to the next one uh insert entity let's see and we need to create a model class keeping these default properties there so let's create a new folder model and uh let's name this as common entity oops let me only copy the property fields and this is inheriting from I table entity and inside I table entity we only have four properties that is row key partition key and e-tag and timestamp so these are the four standard Azure table storage properties now if I have many different tables that I want to create I can make use of this common entity and not initialize these properties again in other model classes for example let me add a new class and inherit from common entity so this will be GPT responses so the model class that you use will be the same name that will be used to create a table GPT response now I can inherit this from common entity and I did not initialize these four properties again here so if at all I create an object of GPT response I can also set properties that are available in common entity because it is a child of common entity okay so those four are set so in the row key that is unique to each row basically in an Azure table these two columns comprises of the primary key basically these two columns combines to make a primary key so it is also called as composite key composite key in terms of SQL you say that when two or more keys are combined together to create a unique key for a row that is called a composite key so these two are combined to create a unique row so what we can use um ideally in terms of Microsoft teams we use partition key as tenant ID and row key as the user object ID that is the user aad object ID but in this case since we are testing it on the emulator what we can do we can make this as partition key as user ID and row key as the conversation ID that will be much better um okay let's try and here we need to store all the messages so to store the message is for each conversation um let's design it first it generates on user ID conversation writing these two are main fields and we need to store user message bot message okay we can make use of single Json feed string user context so basically we'll be storing the messages uh in Json format Json string all right let's move back to storage helper and see the documentation for creating an entity entity means creating an object sorry entry in the table uh first let's see insert entity into table yeah this pretty simple method insert entity are saying it requires table name so when we pass on the table name it gets the table client from this particular method that we have already created and then it also gets the entity what we can also do we can initialize the entity here but since this is the generic method generic means you pass on any type of data and it will be able to add it so to make this work uh we will be doing like this absurd tablecline dot upset absurd means or insert means if the record is present it will throw an exception if record is not present then it will add it if record is present it will update the record if record is not present it will add a new entry so we use upsert and it will not throw any exception it will not throw that doesn't mean that doesn't means we do not have exceptions so we need to put that to try catch because we might have exception in creating the table client and through uh while upset entity and what is the error Dot message okay that should be fine all right now we need to take on this definition this method definition and put that to our storage helper let's see and there it is it is able to take on the definition let's import necessary packages and that is fine okay upset insert is the only thing that is required here and let's add delete entity as well ah get entity is also important and delete entity that is also important the first method works for both the cases that is insert an update the second method getting the entity the tag T must be a reference type in order to use it as a parameter T in the generic type basically this should be class and it will entity new yeah this was showing correct suggestion so we are telling this method as that t will be uh class of type I table entity okay and now what is the error the non-generate method cannot be used to the type argument what is the difference between this and this uh because there is no return type in decision this does not require generic this just requires the partition key or row key that is all this does not require this generic thing table name partition key rookie that is all that subscribe to delete an entity all that this is fine before dropping off let me put this Services here basically our storage helper service here in the dependency injection Services dot add Singleton hi storage helper duration now with adding of this dependency injection now I can pass on the interface here and call any method from there read only I storage helper okay now this seems to be some missing piece that is get entity assign and delete entity testing that needs to be added here K20 tier sync and delete entity okay and now I can call the method let's go back to our bot class GPT bot before sending that to GPT response storage helper Dot insert nttsing and this requires the table name you will get the table name from the configuration that is storage account um what is the table name that we want to give GPT response table that is my first property and the second a parameter sorry that's my first parameter and second one is the object of GPT response GPT response oops uh we are already using that let's say object kids I'm just making it prepared but it will require lot of implementation after this okay let us continue from where we have laptop that is we have created our storage table and we need to pass on the response object that is coming from Char GPT to our storage account so we'll be concatenating or will be appending all the Json objects into an array so let us get started with this one so for easy implementation what I am going to do I am going to take out this Json body and convert that to a dictionary so that it will be easier for me to pass on to my storage table so let's try to do that for that I am going to create a model class and this I am going to name this as chat context and then let's initialize few properties okay so this represent the model property in our Json body next is the messages it's an array so there will be just initializing it with a list so instead of message we'll be just making this as list of message and now I'm going to create a class message and this is a messages property inside message we have a role object we have a Content object and there we have a role object and a Content object and this seems to be fine so now what I can do I can create a no it's not a dictionary object but yeah I can create a chat context object pass on this data convert that to pre-serialize serialized that to a Json object and then we are pass on okay so now I can get rid of this and here I'm just sending the object object Json body okay this I can get rid of Json convert dot serialize object and Json body okay with this I can do it before doing this let me first test this out if it is working yeah so let me just comment this out and now let's create a Json body so that chat context um okay since GitHub copilot has suggested me that I put this in here so let's do that we already have these two properties I can just add it as model and it's GPT 4. okay this is fine and new message role role is user and content is text and this I can send it to what is the chat context all right okay so let's test this out first and then we can move on to the next part so let me say hi sorry I didn't understand that okay ah maybe my okay I think so some issue with the API call let's put a break point here and debug it all right so hi and welcome let's say hi to the bot the issue is response status code unauthorized that means my API key might be expired let's see platform dot open AI yes my API key is not present GPT 4 C sharp let me go back enter this value in my app settings restart the bot test it out okay so this seems to work fine what can you do okay this is working next piece is since this message object needs to be stored what I can do I can just store this message object basically at this messages list as a Json to my storage table so when do I have to store this as soon as we send the response I can show it that will be much better so as soon as I show the response so that I can confirm that response has been sent and I can store this property there so and along with the response object as well that also I need to send it okay let me do one thing let me also check my composer bot how we have done it there so that the same can be okay so we have done let me see the greetings card is new user true okay we are initializing a property is new as to true and we are checking if it is new then quotation is expired okay that is correct because if user is coming after some time then yes then turn dot activity okay here we are checking if it is null that means your session is expired and we are setting back to true and if it is new or user dot is new that means we are also checking if user has typed new in the chat so that we start a new conversation okay so turn dot activity dot text equals to new and we say we send hi to the chatbot okay I have seen in our composer bot so let's see how we can achieve that so I was looking at the response so this is the response that we need to append to our original object in a list right so what we can do instead of sending back the task string we are going to send the message object and here we need to get that message object so return Json convert D serialize object message in this case what will happen it will convert that the Json responds to a message object and then send it back okay now we can get rid of this one all right so when we get back the response so this will be a message and we are checking if it is null if it is not null g dot content so we are just sending back the content like this okay after sending the content we need to append this message object to a chat context chat context dot messages dot add it's not a new one because we already have a message object that we can just append it okay now initially we had our message object and after the response we have our again a message object both combined together apertures passing that to our storage okay and this particular code needs to be executed only when user is new or user has typed new okay okay so we are changing that text Dot and yes so that is the first thing that we need to perform is uh before that let's create a chat context all right so this will happen only for the new ones and what will happen for the old ones for old one we need to get it from our storage account so chat contacts entities storage helper get entity async and GPT context table is that the table name correct no we haven't connected that yet no not there storage account GPT context table user context that's my table name then what is this property partition key and row key this we haven't decided this yet but uh partition key and row key okay so let's decide it right now turn context Dot activity Dot conversation dot ID so I'm going to name my partition key as conversation ID no this should be here the row key as the conversation ID and partition key as the user ID all right and what is the error here uh the type for cannot be inferred from the usage okay the reason being we need to pass on a object uh let's say chat GPT response entity that is my class name okay so once I have that we are going to deserialize it but I was thinking we just keep the messages object in there so so basically it will be a list and the model [Music] let's make it as null it can be null so there we have the user context that user context we are saving to our chat context okay so chat context dot model this is correct then messages say it will automatically contain the messages that is not required right we are just adding a new message okay this code is p this code piece is correct all right then we're going to send our chat context there but since we are retrieving this we are not inserting that yet so let's copy this and first insert that piece in our storage table and that we will be doing over here here so storage account GPT context table GPT response entity partition key I have set it as ID Roki I have set it as conversation ID user context it should not be chat context it should be gpta response yeah it should be chat context dot messages yeah this is the one okay let's see for now whether this will work even this will fail we are going to check for the new users for new users it will always come up here so what I am going to do I am going to check if it is not null then only you perform this if it is null we are going to go to the normal route for initializing the conversation yeah all right so hoping this should work let's see okay initially only we have some error let's see that's good at least we have some error we are not using this chat context anywhere now we are using it okay let's put a breakpoint in future we'll just uh storing all the conversations as well I know what's the issue because we haven't uh added all our services to startup.cs class and nope we have added it okay I got it we do not have our storage helper the storage account connection string all right Let's test this out now okay so we are getting hello and welcome that's good let's say hi let's say hi first that's good that's good actually it should come at the new the else part okay let's say hi uh I need to restart my visual studio I still haven't figured out how to fix that especially while debugging whichever option I click on it doesn't work if you have any resolution you can always guide me how can I fix that issue okay it will come to X else part okay so the error is right here let's see what's issue um will it through an exception if the entity is not found let's see I doubt it should throw an exception but we can always check it uh yes so it will throw an exception in that case we need not uh throwback we just need to send null and just send it to another all right hoping this should fix that let's again test it now again I'll say hi okay we have still have another issue let's see okay so this condition should come after this date before this statement so we need to take this statement and put it here okay now let's test it again okay we are here at the inserted dating okay we are getting response and let's quickly check our DB there we have our user context and there we have our user context details and this should be role user context file role assistant hello okay this is fine now let's ask our normal question let me uncomment from like remove a breakpoint from there and also remove a breakpoint from here okay so let's see if this entry is there in the DB let me copy this whole object now it is replacing it it's not saving it it is replacing it we need to fix this one so when we have something in our database and while inserting it okay so this piece is wrong I think we this is correct Let's test it out at from the start um before that let me remove this entry let's say hi this seems to be correct next and that should insert a new entry Okay so my data the next context should be appending with this one let's try in that case let me put a break statement this time at all the places and especially fear okay what is my name it should return me the existing chat context entity and there we have if it is null go next okay this is chat context entity yes this is chat context entity in that case let me stop this remove the entry the reason I am removing it I'll be fixing that later but first we need to check it let's say hi and also cross verify if the indeed entry is there yes let me copy paste this put it here yes that's correct let's ask what is my name okay let's see that should not be null D serializing it that's an error cannot deserialize the current Json array into a type chat context because the type requires a Json object that is absolutely correct because we are we are deserializing the chat context but we are saving the messages okay so we converted this to our user context to messages and let's see if this works now before that we need to delete our entry over here let's start debugging okay now let's ask our question there we have chat context dot messages the first object is our initial message the second is the response from charge GPT now we are adding the third object that is our current question let's continue and that should reply back let's see in the chat screen that's okay now chat context dot messages the current chat context is of three contains three elements and this is the fourth element that we are adding that's again the response right and that should be updating our current DB let's see let me copy this and there we have so that's our initial next message and yes now let's continue our screen let's continue and again I will be asking perfect see ya so it is working it is able to remember my user context and Let me refresh get this one and see it on the notepad see now all our conversation is here now what happens if I type new if I type new then it will be replaced and let's see if it if it is going to replace that let's say new for new I need to send some data that is hi okay and let me restart the conversation so it will still remember me actually uh no it will not remember me because I have restarted the conversation with a new user ID if I have restarted the conversation with the same user ID then it should remember me yeah but if you are working in the Microsoft teams environment then it should remember me at all the times so let's start again let me get rid of all the breakpoints and also see a new entry will be generated there you see with a new conversation ID and the user ID now let's ask the same one there you see and now let me ask okay it is remembering now if I just type new I am assuming that it should only reset the current conversation and not the another one so if I just move here Let me refresh and I think this should be the entry okay let me see which is the entry uh timestamp 526 yeah this should be reset and also let me copy and paste the data yeah okay so let's ask new and here it is and also let me show you the entry that it got reset here you see now it has reset the conversation now if I ask it will not understand here you see so perfect this is working fine and we are able to achieve our requirement all right yeah thanks everyone
Info
Channel: Dewiride Technologies
Views: 2,301
Rating: undefined out of 5
Keywords: ChatGPT, bot framework, C#, OpenAI, GPT-4, conversational AI, tutorial, chatbot development, natural language processing, state management, Microsoft Bot Framework SDK, chatgpt, openai chat completion api, ai chatbot, chatbot tutorial, beginner tutorial, stateful bot, conversation bot, nlp, microsoft bot framework, openai, bot development, chatbot, bot, open ai, ai, ai bots, chatgpt tutorial, azure bot service, chatgpt api, chat, build chatbot, create chatbot, create ai bots
Id: 0joaIgHjbEk
Channel Id: undefined
Length: 77min 43sec (4663 seconds)
Published: Tue May 09 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.