All language subtitles for OpenAI API Integration _ Drifting Ruby (Transcribed on 23-Mar-2023 23-35-07)

af Afrikaans
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bn Bengali
bs Bosnian
bg Bulgarian
ca Catalan
ceb Cebuano
ny Chichewa
zh-CN Chinese (Simplified) Download
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
tl Filipino
fi Finnish
fr French
fy Frisian
gl Galician
ka Georgian
de German
el Greek
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
km Khmer
ko Korean
ku Kurdish (Kurmanji)
ky Kyrgyz
lo Lao
la Latin
lv Latvian
lt Lithuanian
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mn Mongolian
my Myanmar (Burmese)
ne Nepali
no Norwegian
ps Pashto
fa Persian
pl Polish
pt Portuguese
pa Punjabi
ro Romanian
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
st Sesotho
sn Shona
sd Sindhi
si Sinhala
sk Slovak
sl Slovenian
so Somali
es Spanish
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
te Telugu
th Thai
tr Turkish
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu
or Odia (Oriya)
rw Kinyarwanda
tk Turkmen
tt Tatar
ug Uyghur
Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated: 1 00:00:00,000 --> 00:00:15,960 In this episode, we're going to have a look at a blog post system that can accept comments. 2 00:00:15,960 --> 00:00:21,000 And the interesting thing about these comments is that if we enter in one, we can then 3 00:00:21,000 --> 00:00:24,640 create the comment, and then you'll see that we have a button. 4 00:00:24,640 --> 00:00:29,440 In the focus of this episode, it's going to be creating this button that could be hindered, 5 00:00:29,440 --> 00:00:34,160 and also an API wrapper for the OpenAI API. 6 00:00:34,160 --> 00:00:39,120 So when we click the button, it'll make a request, and then that request will be an 7 00:00:39,120 --> 00:00:40,880 AI response. 8 00:00:40,880 --> 00:00:46,320 And so there's a lot of different use cases that we can do with this with OpenAI, and they 9 00:00:46,320 --> 00:00:48,120 have a pretty extensive AI. 10 00:00:48,120 --> 00:00:52,880 So if you just want some kind of text generation, or if you want to have some kind of code 11 00:00:52,880 --> 00:00:59,040 generation, which, GitHub's, Copilot actually uses, Codex under the hood, and there's 12 00:00:59,040 --> 00:01:01,040 many more examples. 13 00:01:01,040 --> 00:01:06,520 And so in this episode, we're going to be using the OpenAI and the Deventy model in order 14 00:01:06,520 --> 00:01:09,360 to have this AI bot response. 15 00:01:09,360 --> 00:01:13,120 And because we are using the API, it is a paid solution. 16 00:01:13,120 --> 00:01:17,560 But if you sign up for a free account, you can get about $18 worth of credit that can 17 00:01:17,560 --> 00:01:20,039 be used within the first three months. 18 00:01:20,039 --> 00:01:25,039 And so the cost associated with this is going to vary depending on the amount of traffic 19 00:01:25,040 --> 00:01:30,560 to your website, as well as how much the actual AI is going to be used. 20 00:01:30,560 --> 00:01:36,120 But as we'll see, we do have some mitigating factors that we can do to limit the usage. 21 00:01:36,120 --> 00:01:41,480 And then we're also going to be creating an API wrapper around OpenAI, because it's one 22 00:01:41,480 --> 00:01:46,640 of those things where we are creating an API request for one external API. 23 00:01:46,640 --> 00:01:50,360 But in our application, there's good chances that there's going to be many more APIs that 24 00:01:50,360 --> 00:01:55,640 we're going to be interacting with, and without bringing in any external libraries, I would 25 00:01:55,640 --> 00:02:00,440 like to just create a simple wrapper that we're then going to be able to reuse within 26 00:02:00,440 --> 00:02:02,160 our application. 27 00:02:02,160 --> 00:02:07,120 And so we are going to start out this application with the blog post already created. 28 00:02:07,120 --> 00:02:09,560 And we're not doing anything fancy with that. 29 00:02:09,560 --> 00:02:12,000 We have a very basic device set up. 30 00:02:12,000 --> 00:02:15,920 A user has many posts and a user has many comments. 31 00:02:15,920 --> 00:02:21,119 And as you would expect, a post has many comments and that belongs to the user. 32 00:02:21,119 --> 00:02:26,359 The post has a rich text content, so we're using the action text. 33 00:02:26,359 --> 00:02:31,320 And for the comments, that belongs to the user and it also belongs to the post. 34 00:02:31,320 --> 00:02:33,920 And we also have the rich text content. 35 00:02:33,920 --> 00:02:37,440 So again, we're using action text for the comments. 36 00:02:37,440 --> 00:02:41,839 We have our controller for the post and the controller for the comments, neither of which 37 00:02:41,839 --> 00:02:44,440 we're really going to have to touch in this episode. 38 00:02:44,440 --> 00:02:48,480 For this episode, I was very intentional to keep it as simple as possible. 39 00:02:48,480 --> 00:02:54,520 So I'm not introducing any kind of hot wire with the turbo frame tags or stimulus controllers 40 00:02:54,520 --> 00:02:55,520 for this. 41 00:02:55,520 --> 00:03:01,640 I wanted to just keep it pretty bare bones, so we can focus on building the AI integration. 42 00:03:01,640 --> 00:03:06,520 And so the first thing that you need to do is go to openAI.com and sign up for a free account. 43 00:03:06,520 --> 00:03:09,440 We then generate some kind of API key. 44 00:03:09,440 --> 00:03:12,040 And you'll just want to copy this and keep it secret. 45 00:03:12,040 --> 00:03:17,799 And so first, let's go into our routes file and we'll make a route for the open AI to comment. 46 00:03:17,799 --> 00:03:21,880 So we'll just create a block under the resources for the comments. 47 00:03:21,880 --> 00:03:27,560 And the reason for that is because when we make the call to open AI, it is going to generate 48 00:03:27,560 --> 00:03:31,680 a response based on the prompt we give it and the prompt that we're going to give it is 49 00:03:31,680 --> 00:03:32,920 the comment. 50 00:03:32,920 --> 00:03:37,440 So then we could also have a resources for the comments. 51 00:03:37,440 --> 00:03:39,799 And we would only need the create action. 52 00:03:39,800 --> 00:03:43,240 But I don't like doing this because this is very confusing. 53 00:03:43,240 --> 00:03:48,240 If I were to just look at this, I would think that this is so that people can make a comment 54 00:03:48,240 --> 00:03:52,680 on a comment and it has nothing to do with the open AI. 55 00:03:52,680 --> 00:03:57,480 So instead, what I would rather do is to just wrap this comment that we just created 56 00:03:57,480 --> 00:03:59,040 in a name space. 57 00:03:59,040 --> 00:04:01,360 And we'll just call this the open AI. 58 00:04:01,360 --> 00:04:04,240 We'll create our block and they will close it out. 59 00:04:04,240 --> 00:04:07,920 And before we move on from that, let's go ahead and run the Rails routes. 60 00:04:07,920 --> 00:04:13,320 Dash G. So we can see what the routes are and we'll grab the open AI. 61 00:04:13,320 --> 00:04:15,359 And so we can see our prefix. 62 00:04:15,359 --> 00:04:18,440 This is going to have the URI for the posts. 63 00:04:18,440 --> 00:04:22,200 So we'll pass in the post ID, the comments, the common ID. 64 00:04:22,200 --> 00:04:27,200 And then it'll just go to the fourth slash open AI, fourth slash comments. 65 00:04:27,200 --> 00:04:33,960 And then we have the open AI name space, a comments controller with the create action. 66 00:04:33,960 --> 00:04:36,159 And so I'm happy enough with this. 67 00:04:36,160 --> 00:04:42,000 We then generate our controller and we'll just call it the open AI, fourth slash comments. 68 00:04:42,000 --> 00:04:47,720 And as we would expect, that would create the folder open AI and the comments controller. 69 00:04:47,720 --> 00:04:51,000 And within here, we can make our create action. 70 00:04:51,000 --> 00:04:56,240 Similar to what we are doing in other areas of the application, we have a before action 71 00:04:56,240 --> 00:04:58,080 for the authenticate user. 72 00:04:58,080 --> 00:05:02,680 And that simply a device helper that we want to make sure that on the open AI that we do 73 00:05:02,680 --> 00:05:07,960 have a user authenticated before we make that API call to open AI. 74 00:05:07,960 --> 00:05:13,000 And so I'm going to lead this alone for now because what we are displaying out the comments, 75 00:05:13,000 --> 00:05:15,680 we can trace that back if we look at our posts. 76 00:05:15,680 --> 00:05:20,240 When we are showing a post, you'll see that we are rendering out the post comments. 77 00:05:20,240 --> 00:05:24,040 And so we need to look at the comments folder in the comment partial. 78 00:05:24,040 --> 00:05:30,360 And then here we have where we are displaying the user, said on the date, and then the content. 79 00:05:30,360 --> 00:05:32,040 So let's go ahead and create our link. 80 00:05:32,040 --> 00:05:36,800 I'm not going to do a link too because we do have a post request that we are making for 81 00:05:36,800 --> 00:05:38,400 that create action. 82 00:05:38,400 --> 00:05:41,000 So instead, I'll do a button too. 83 00:05:41,000 --> 00:05:42,400 We can then give it some text. 84 00:05:42,400 --> 00:05:45,800 We'll just call it the ask AI to respond. 85 00:05:45,800 --> 00:05:51,960 And then this needs to go to the post comment, open AI comments path. 86 00:05:51,960 --> 00:05:58,040 We do need to pass in both our posts and the comment for this particular endpoint. 87 00:05:58,040 --> 00:06:02,320 I'm also going to have a class because I am using bootstrap on this project. 88 00:06:02,320 --> 00:06:06,920 I'll just make a button small and then a button outline primary. 89 00:06:06,920 --> 00:06:12,040 And just so you know, this post and the comment, we do have access to both of these 90 00:06:12,040 --> 00:06:19,320 because when we are displaying out in the post show page, we're rendering out the post comments. 91 00:06:19,320 --> 00:06:23,280 So this will automatically create that local variable comment. 92 00:06:23,280 --> 00:06:28,679 But then we are passing in the local variable post sending it to the instance variable. 93 00:06:28,679 --> 00:06:32,719 Because when I'm working in partials, I don't like use it instance variables within 94 00:06:32,719 --> 00:06:33,719 here. 95 00:06:33,719 --> 00:06:37,960 For a few reasons, it may not be clear what that object should actually be. 96 00:06:37,960 --> 00:06:43,200 And if that instance variable was even required by using local variables instead of the instance 97 00:06:43,200 --> 00:06:48,520 variables, then we would actually receive an error that the variable wasn't defined. 98 00:06:48,520 --> 00:06:53,159 Otherwise we would get a nil and then we could get into situations where we get a 99 00:06:53,159 --> 00:06:58,359 undefined method created at four nil class and we don't want to deal with those kind 100 00:06:58,359 --> 00:06:59,359 of issues. 101 00:06:59,359 --> 00:07:03,640 And so surprisingly, this is really all we have to do on our front end. 102 00:07:03,640 --> 00:07:07,280 We created the endpoint and we created our button. 103 00:07:07,280 --> 00:07:09,880 Everything else is going to be done on the back end. 104 00:07:09,880 --> 00:07:14,960 And we'll start with then the controllers, open AI and the comments controller. 105 00:07:14,960 --> 00:07:19,120 Because there's a lot of different ways that we can architect this, but essentially what 106 00:07:19,120 --> 00:07:22,599 I want to do is that we're going to create a new comment. 107 00:07:22,599 --> 00:07:27,560 And that comment is going to be from our current user, which we do have access to, especially 108 00:07:27,560 --> 00:07:31,919 because we are requiring that user to be authenticated and then we'll have a comment 109 00:07:31,919 --> 00:07:32,919 start new. 110 00:07:32,919 --> 00:07:38,000 We can set that new comment and we can set the post is equal to the post, which that 111 00:07:38,000 --> 00:07:39,840 post we don't have access to. 112 00:07:39,840 --> 00:07:44,880 So we're going to create a private method for our post. We'll send an instance variable post 113 00:07:44,880 --> 00:07:49,840 double pipe equals just so we are memoizing it because we are going to refer to the post 114 00:07:49,840 --> 00:07:54,640 potentially a few different times and then we can have a post stop find and then we need 115 00:07:54,640 --> 00:08:00,400 to pass in the prams and then the post underscore ID and that post underscore ID. 116 00:08:00,400 --> 00:08:05,840 If you remember, if we look at our routes, we have our post and then that post ID and then 117 00:08:05,840 --> 00:08:10,719 for the comments, we have the comment ID and we're also going to need that comment because 118 00:08:10,719 --> 00:08:13,560 we need to get the content of that comment. 119 00:08:13,560 --> 00:08:17,520 And so we're not going to be using the comment multiple times, so there's no need to 120 00:08:17,520 --> 00:08:21,239 memoize it, but we are going to call on our post. 121 00:08:21,239 --> 00:08:25,359 Notice that I'm just using the local variable and not the instance variable that we 122 00:08:25,359 --> 00:08:29,400 said because we don't know if that instance variable has been set yet. 123 00:08:29,400 --> 00:08:31,280 We name call the comments. 124 00:08:31,280 --> 00:08:36,880 Find and we can find the comment based on the prams comment underscore ID. 125 00:08:36,880 --> 00:08:41,679 So now that we have created a new comment, we haven't saved the yet and we've also 126 00:08:41,679 --> 00:08:44,280 associated the comment to a post. 127 00:08:44,280 --> 00:08:49,640 We then set some kind of content so we have our new comment dot content and we want to 128 00:08:49,640 --> 00:08:55,040 set this equal to and we'll propend some text on here, we'll just call the AI said and 129 00:08:55,040 --> 00:08:58,280 then we can call some kind of external service. 130 00:08:58,280 --> 00:09:03,319 So we wouldn't want to put all of that logic or call an open AI within our controller. 131 00:09:03,319 --> 00:09:06,319 So I'm going to create a different kind of class. 132 00:09:06,319 --> 00:09:09,400 We'll just call this the open AI commenter. 133 00:09:09,400 --> 00:09:14,680 We'll have a class method called call and then we're just going to pass in the comment 134 00:09:14,680 --> 00:09:20,439 dot content, but the problem with this is that we just need the plain text of the content. 135 00:09:20,439 --> 00:09:27,480 And because this content is action text, we can call to underscore plain underscore text. 136 00:09:27,480 --> 00:09:33,720 We then check if the new comment that save, we can then just redirect to the post with 137 00:09:33,720 --> 00:09:38,720 the notice AI has responded and that's all we're going to do in here for now. 138 00:09:38,720 --> 00:09:44,120 If you do have your system set up for hot wire where you're broadcasting the changes 139 00:09:44,120 --> 00:09:48,840 that you would need to redirect to the post, you could just call the new comment dot save 140 00:09:48,840 --> 00:09:50,840 then maybe a head okay. 141 00:09:50,840 --> 00:09:56,200 So that way it's not expecting any kind of return value or input, but then turbo would 142 00:09:56,200 --> 00:10:00,280 then broadcast the response stream to the browsers. 143 00:10:00,280 --> 00:10:05,720 And I would definitely prefer doing that over just calling our class here because then we could 144 00:10:05,720 --> 00:10:08,120 just call this from a background job. 145 00:10:08,120 --> 00:10:13,960 So that way the end user isn't having to wait for open AI to generate a response. 146 00:10:13,960 --> 00:10:18,280 But again, those kind of implementations are very simple and we've already covered them 147 00:10:18,280 --> 00:10:23,480 in the past another episodes because we have done the turbo stream broadcasts and we've 148 00:10:23,480 --> 00:10:25,560 done plenty on background jobs. 149 00:10:25,560 --> 00:10:30,839 You would simply just move this into a background job passing in the comment and the broadcast 150 00:10:30,839 --> 00:10:34,119 within the comments model would handle the rest. 151 00:10:34,119 --> 00:10:38,680 So I'm going to undo these changes for now because we're not going to set that part up. 152 00:10:38,680 --> 00:10:41,319 We're just going to redirect back to the post. 153 00:10:41,319 --> 00:10:47,160 So we do need to create this open AI commenter and I'm just going to create a new file in the 154 00:10:47,160 --> 00:10:48,119 models. 155 00:10:48,119 --> 00:10:51,479 We'll call it the open AI commenter dot RB. 156 00:10:51,480 --> 00:10:58,120 It'll be a class of open AI commenter will have a class method named the call method. 157 00:10:58,120 --> 00:11:02,040 And we're going to be taking the comments content plain text. 158 00:11:02,040 --> 00:11:03,880 So I'm just going to call it the prompt. 159 00:11:03,880 --> 00:11:09,640 We'll create a new instance of this class passing in the prompt and then we'll have a call method. 160 00:11:09,640 --> 00:11:12,440 We can initialize a class taking in our prompt. 161 00:11:12,440 --> 00:11:17,640 Well, then set our instance variable prompt is equal to the prompt and then we'll have the call 162 00:11:17,640 --> 00:11:20,760 method where we'll do all the business logic. 163 00:11:20,760 --> 00:11:23,560 And so we do have a few different things going on here. 164 00:11:23,560 --> 00:11:29,319 I'm first going to set a constant and that constant I'm just going to put the URL for the open 165 00:11:29,319 --> 00:11:32,360 AI's completion API. 166 00:11:32,360 --> 00:11:38,520 And while I could do all of the necessary bit of code to make the API call from here, I actually 167 00:11:38,520 --> 00:11:39,640 don't want to do that. 168 00:11:39,640 --> 00:11:46,439 I want this open AI commenter to be specifically on the formation of the request and getting the 169 00:11:46,440 --> 00:11:47,560 response. 170 00:11:47,560 --> 00:11:53,800 I want to create an API wrapper that's then going to make whatever kind of API requests we want 171 00:11:53,800 --> 00:11:58,520 to make, whether it's a get request or a post or a putter patch. 172 00:11:58,520 --> 00:12:02,520 And so this API let's just call it an API client. 173 00:12:02,520 --> 00:12:08,920 And this API client, we're going to initialize it and we're going to take in a few different variables. 174 00:12:08,920 --> 00:12:11,080 We're going to take in our URL. 175 00:12:11,080 --> 00:12:16,120 We also are going to create some kind of headers and then we're also going to have 176 00:12:16,120 --> 00:12:18,840 some kind of body that we're going to pass in. 177 00:12:18,840 --> 00:12:27,080 We then have an action where do we want to do a get request, a put request, a delete, or in our case, 178 00:12:27,080 --> 00:12:29,880 we want to make a post request to this endpoint. 179 00:12:29,880 --> 00:12:31,960 We can set this to a local variable. 180 00:12:31,960 --> 00:12:38,360 And for open AI specifically, it's going to give us a response back, which we'll look at. 181 00:12:38,360 --> 00:12:41,080 And we can actually do that with a Rails.logger. 182 00:12:41,080 --> 00:12:45,800 And unlike using emojis in my logs, just so I can see it more clearly. 183 00:12:45,800 --> 00:12:50,839 And we'll just spit out that JSON because I've already done this in preparations. 184 00:12:50,839 --> 00:12:54,439 I know that this is going to return some kind of choices. 185 00:12:54,439 --> 00:12:58,520 And then we can get the first item and then the text response. 186 00:12:58,520 --> 00:13:04,280 If the choices is nil, because it will some kind of issue, maybe we've hit some kind of limits, 187 00:13:04,280 --> 00:13:09,640 or some other kind of issue, we can do a rescue or some other kind of handler. 188 00:13:09,640 --> 00:13:14,040 Because remember, when we are calling this open AI commoner from our controller, 189 00:13:14,040 --> 00:13:17,240 it is expecting some kind of text response. 190 00:13:17,240 --> 00:13:20,439 So this is going to be visible to the end user. 191 00:13:20,439 --> 00:13:23,560 So we can capture whatever kind of errors we want here. 192 00:13:23,560 --> 00:13:27,240 And the nice part about this kind of thing, we can just respond with, 193 00:13:27,240 --> 00:13:31,079 I'm sorry, but I cannot give a response based on the information provided, 194 00:13:31,079 --> 00:13:33,480 or some other kind of meaningful error. 195 00:13:33,480 --> 00:13:37,640 But if we go back and look at the comments controller for the open AI, 196 00:13:37,640 --> 00:13:42,360 remember, we are creating this comment as that particular user. 197 00:13:42,360 --> 00:13:46,760 So if the user has the ability to delete their own comments, 198 00:13:46,760 --> 00:13:51,880 then they're going to be able to also delete the comment that was created by the AI. 199 00:13:51,880 --> 00:13:56,680 So for that reason, I would actually be okay with having some kind of text like this, 200 00:13:56,680 --> 00:14:02,360 because if the user who created or asked the bot to make a response, 201 00:14:02,360 --> 00:14:06,440 doesn't like the response or it wasn't what they were looking for, 202 00:14:06,440 --> 00:14:09,000 then they could delete it and move on. 203 00:14:09,000 --> 00:14:13,640 But before we create this API client, we do need to go ahead and create 204 00:14:13,640 --> 00:14:18,600 this headers and the body, because these both are going to be private methods 205 00:14:18,600 --> 00:14:20,040 within this model. 206 00:14:20,040 --> 00:14:22,440 So we have our headers and the body method. 207 00:14:22,440 --> 00:14:25,400 And for the headers, we do need to set the content, 208 00:14:25,400 --> 00:14:29,000 dash type, and this is going to be the application, 209 00:14:29,000 --> 00:14:30,600 or slash JSON. 210 00:14:30,600 --> 00:14:33,800 And then we also need to pass in our authorization. 211 00:14:33,800 --> 00:14:38,680 The authorization is going to be bear with the space, 212 00:14:38,680 --> 00:14:41,560 and then we need to interplay it in our API token 213 00:14:41,560 --> 00:14:43,800 that we are getting from OpenAI. 214 00:14:43,800 --> 00:14:47,560 And we can just make this an environment variable or something like that. 215 00:14:47,560 --> 00:14:49,959 However, this is just a semantics thing. 216 00:14:49,959 --> 00:14:53,079 I really don't like interplating in text like this. 217 00:14:53,079 --> 00:14:56,920 I would rather do it as an array, or we have our bearer, 218 00:14:56,920 --> 00:14:58,920 and then we also have our token, 219 00:14:58,920 --> 00:15:02,199 and then I'm just going to join it with a space. 220 00:15:02,199 --> 00:15:04,599 And so for me, I think that reads better, 221 00:15:04,599 --> 00:15:07,240 and it's easier to just work around in my opinion, 222 00:15:07,240 --> 00:15:10,200 but you can interplay it in if you want to. 223 00:15:10,200 --> 00:15:13,240 And for the body, we're also just going to make a JSON. 224 00:15:13,240 --> 00:15:15,640 We need to pass in some kind of model, 225 00:15:15,640 --> 00:15:18,280 and their documentation is actually very good. 226 00:15:18,280 --> 00:15:18,840 I like it. 227 00:15:18,840 --> 00:15:21,720 It explains all the different models that you can use. 228 00:15:21,720 --> 00:15:24,600 And in our case, I want to use the DaVinci model, 229 00:15:24,600 --> 00:15:28,840 and its code is text-divinci-003. 230 00:15:28,840 --> 00:15:32,440 We take in our prompt, and that prompt is going to be our instance 231 00:15:32,440 --> 00:15:33,640 variable prompt. 232 00:15:33,640 --> 00:15:35,480 And then the max tokens, 233 00:15:35,480 --> 00:15:38,600 this is basically going to be an integer value, 234 00:15:38,600 --> 00:15:42,120 and that's going to be the number of words in our response 235 00:15:42,120 --> 00:15:44,200 that we're getting from OpenAI. 236 00:15:44,200 --> 00:15:46,280 So if you set this to be too large, 237 00:15:46,280 --> 00:15:49,000 it's going to get expensive very fast. 238 00:15:49,000 --> 00:15:52,120 So I would set it to some kind of reasonable amount. 239 00:15:52,120 --> 00:15:54,920 100 is probably going to be a bit too low, 240 00:15:54,920 --> 00:15:59,000 but you can experiment with what's going to be the expected response. 241 00:15:59,000 --> 00:16:01,880 And then we also are going to pass in a temperature. 242 00:16:01,880 --> 00:16:05,480 And I think it's worth going into the docs for OpenAI, 243 00:16:05,480 --> 00:16:09,240 just so we can see what the completions API is expecting, 244 00:16:09,240 --> 00:16:11,560 because there's a lot more options here. 245 00:16:11,560 --> 00:16:13,320 There's our max tokens, 246 00:16:13,320 --> 00:16:17,000 which you can see it defaults to 16 if we did not include it, 247 00:16:17,000 --> 00:16:18,439 but then the temperature. 248 00:16:18,439 --> 00:16:21,400 It's going to take a number between 0 and 2. 249 00:16:21,400 --> 00:16:25,080 A higher value will make the output more random, 250 00:16:25,080 --> 00:16:29,240 while a lower value will make it more focus and deterministic. 251 00:16:29,240 --> 00:16:31,880 And there's other ones that you can use as well to tweak, 252 00:16:31,880 --> 00:16:33,880 basically how it's going to work. 253 00:16:33,880 --> 00:16:37,640 One that you may want to look at or use is the presence penalty, 254 00:16:37,640 --> 00:16:39,560 and the frequency penalty, 255 00:16:39,560 --> 00:16:43,800 but ultimately it'll be up to you on how you wanted to tweak the settings 256 00:16:43,800 --> 00:16:46,600 to get the desired responses. 257 00:16:46,600 --> 00:16:49,240 And so that's basically all we have to do 258 00:16:49,240 --> 00:16:52,040 to get the AI to generate the response. 259 00:16:52,040 --> 00:16:54,920 Next we have to create that client API, 260 00:16:54,920 --> 00:16:57,800 but that simply just making a post request 261 00:16:57,800 --> 00:17:03,079 to open AI's endpoint with the headers and the body. 262 00:17:03,079 --> 00:17:04,760 So I'm going to create another file 263 00:17:04,760 --> 00:17:08,680 on our models called the API client.rb. 264 00:17:08,680 --> 00:17:10,919 It'll be a class API client, 265 00:17:10,919 --> 00:17:13,960 and this is actually going to be more code than the open AI 266 00:17:13,960 --> 00:17:16,839 cometer, because we are going to take in 267 00:17:16,839 --> 00:17:18,839 a few different things into account. 268 00:17:18,839 --> 00:17:20,839 Well, first initializes, 269 00:17:20,839 --> 00:17:24,040 remember we had our URL, the headers, 270 00:17:24,040 --> 00:17:26,520 and the headers if we don't pass in anything, 271 00:17:26,520 --> 00:17:29,320 just so we don't get any kind of no class errors. 272 00:17:29,320 --> 00:17:31,480 I'm going to set it to an empty hash, 273 00:17:31,480 --> 00:17:34,200 and we're also going to do the same thing for the body. 274 00:17:34,200 --> 00:17:36,360 We'll set our instance variable URL, 275 00:17:36,360 --> 00:17:39,560 is equal to the URL for our URL. 276 00:17:39,560 --> 00:17:42,360 We have our headers is equal to the headers, 277 00:17:42,360 --> 00:17:45,320 and we'll have our body is equal to the body, 278 00:17:45,320 --> 00:17:48,200 but I'm also going to pass to JSON on here, 279 00:17:48,200 --> 00:17:50,040 just so it's properly formatted. 280 00:17:50,040 --> 00:17:53,080 And so we're going to handle a few different types of requests. 281 00:17:53,080 --> 00:17:55,000 We're going to have a get request, 282 00:17:55,000 --> 00:17:57,480 we're going to have a post, a put, 283 00:17:57,480 --> 00:17:59,480 and let's also handle the delete. 284 00:17:59,480 --> 00:18:01,000 So in each one of these cases, 285 00:18:01,000 --> 00:18:03,320 they're going to be instance methods, 286 00:18:03,320 --> 00:18:06,760 and whenever you call the get post, putter delete, 287 00:18:06,760 --> 00:18:09,880 we're just going to make a request passing in, 288 00:18:09,880 --> 00:18:12,440 the appropriate get post, putter delete. 289 00:18:12,440 --> 00:18:15,000 And when I have a single line method like this, 290 00:18:15,000 --> 00:18:17,320 we're as a very simple definition, 291 00:18:17,320 --> 00:18:20,760 I like using the semicolon to just make a one line, 292 00:18:20,760 --> 00:18:23,960 instead of having it multiple lines like this, 293 00:18:23,960 --> 00:18:26,920 because I think that's just going to make it vertically longer, 294 00:18:26,920 --> 00:18:28,120 and it's not necessary. 295 00:18:28,120 --> 00:18:31,400 You can see just kind of add a glance what this is doing, 296 00:18:31,400 --> 00:18:32,760 and what to expect. 297 00:18:32,760 --> 00:18:34,680 We then have our private method, 298 00:18:34,680 --> 00:18:36,920 and we'll first have the request. 299 00:18:36,920 --> 00:18:40,280 We're going to take in our method for that request, 300 00:18:40,280 --> 00:18:42,520 and then we need to build that request. 301 00:18:42,520 --> 00:18:45,000 So I'm going to make a build request, 302 00:18:45,000 --> 00:18:46,840 taking in the method again, 303 00:18:46,840 --> 00:18:50,520 and that's just where we're going to do a case statement on the method. 304 00:18:50,520 --> 00:18:53,320 Because depending on what we're going to use, 305 00:18:53,320 --> 00:18:56,120 it is going to vary on how this is going to look. 306 00:18:56,120 --> 00:18:59,000 So we can have when it's a get request, 307 00:18:59,000 --> 00:19:00,919 when it is a post, 308 00:19:00,919 --> 00:19:02,280 when it's a putt, 309 00:19:02,280 --> 00:19:04,760 and also when it is a delete. 310 00:19:04,760 --> 00:19:06,600 If it is a get request, 311 00:19:06,600 --> 00:19:11,320 then we can respond with the net HTTP get, 312 00:19:11,320 --> 00:19:14,200 and then we can create a new instance of that, 313 00:19:14,200 --> 00:19:17,639 passing in our URL and the headers. 314 00:19:17,639 --> 00:19:19,480 If it's a post request, 315 00:19:19,480 --> 00:19:21,720 we actually want to make this a post. 316 00:19:21,720 --> 00:19:24,280 It's still going to take in the URL and headers, 317 00:19:24,280 --> 00:19:27,320 but we also need to set the body for this, 318 00:19:27,320 --> 00:19:30,600 and so we can call the request.body, 319 00:19:30,600 --> 00:19:32,520 and set that equal to our body. 320 00:19:32,520 --> 00:19:33,800 If it's a putt, 321 00:19:33,800 --> 00:19:36,840 then we need to do the same thing as the post, 322 00:19:36,840 --> 00:19:40,440 except we'll just change this class to a putt, 323 00:19:40,440 --> 00:19:41,880 and if it's a delete, 324 00:19:41,880 --> 00:19:44,600 that's going to be very similar to where it get requests, 325 00:19:44,600 --> 00:19:46,680 but we'll call the delete instead. 326 00:19:46,680 --> 00:19:50,520 And so we could just return the request here, 327 00:19:50,520 --> 00:19:52,360 and that's all we should have to do, 328 00:19:52,360 --> 00:19:54,520 but I think this looks a little bit funny 329 00:19:54,520 --> 00:19:57,800 having the request down here like this multiple times. 330 00:19:57,800 --> 00:20:00,520 So instead, it's a little bit strange, 331 00:20:00,520 --> 00:20:03,639 but I think I would just rather set the request 332 00:20:03,639 --> 00:20:05,240 on each one of these, 333 00:20:05,240 --> 00:20:06,600 and that should work, 334 00:20:06,600 --> 00:20:07,960 or if we wanted to, 335 00:20:07,960 --> 00:20:10,920 we could just set the request up here like this, 336 00:20:10,920 --> 00:20:12,200 on the case, 337 00:20:12,200 --> 00:20:14,840 but then we're going to have to remove this body 338 00:20:14,840 --> 00:20:17,320 on both the putt and the post, 339 00:20:17,320 --> 00:20:20,440 and then we can do a check if we can then check if it's 340 00:20:20,440 --> 00:20:22,440 a putt, or a post, 341 00:20:22,440 --> 00:20:26,440 we'll make it array and just check to see if it includes that method. 342 00:20:26,440 --> 00:20:29,000 Then we return the request. 343 00:20:29,000 --> 00:20:31,320 And so you can do this however you want, 344 00:20:31,320 --> 00:20:33,240 it's really just a matter of styling, 345 00:20:33,240 --> 00:20:36,120 as long as the application is consistent, 346 00:20:36,120 --> 00:20:38,760 with whatever kind of styling you're using here, 347 00:20:38,760 --> 00:20:42,440 then it would be fine by me with whatever direction you went. 348 00:20:42,440 --> 00:20:44,920 So we're going to run the build request, 349 00:20:44,920 --> 00:20:49,160 and we'll set our request as equal to that build request passing in the method. 350 00:20:49,160 --> 00:20:53,320 We can then take our HTTP is equal to the net, 351 00:20:53,320 --> 00:20:59,400 and then HTTP will create a new instance passing in our URL.host, 352 00:20:59,400 --> 00:21:02,200 and also passing in the URL.port. 353 00:21:02,200 --> 00:21:04,040 We can then set the use, 354 00:21:04,040 --> 00:21:08,760 underscore SSL is equal to the URL.scheme, 355 00:21:08,760 --> 00:21:13,800 and we just want to do a check if that is equal to HTTPS. 356 00:21:13,800 --> 00:21:17,320 We can then set some kind of response is equal to 357 00:21:17,320 --> 00:21:22,200 the HTTPS.request passing in our request. 358 00:21:22,200 --> 00:21:24,679 And then we need to handle that response. 359 00:21:24,679 --> 00:21:27,960 So this is going to be another private method that we create, 360 00:21:27,960 --> 00:21:29,960 passing in the response. 361 00:21:29,960 --> 00:21:34,280 And there is a possibility that the request that we make 362 00:21:34,280 --> 00:21:40,040 to the open AI or some other API endpoint is going to timeout. 363 00:21:40,040 --> 00:21:43,480 So what I like to do is to have some kind of rescue 364 00:21:43,480 --> 00:21:46,760 and in our case with net HTTP, 365 00:21:46,760 --> 00:21:48,760 we can rescue from the timeout. 366 00:21:48,760 --> 00:21:50,520 We can then raise the error. 367 00:21:50,520 --> 00:21:54,360 I'm going to create a standard error called API error, 368 00:21:54,360 --> 00:21:58,040 and then we'll just call this the operation time down. 369 00:21:58,040 --> 00:22:00,440 So we do need to create that API error, 370 00:22:00,440 --> 00:22:03,160 and that's just going to be a class API error 371 00:22:03,160 --> 00:22:05,320 inheriting from the standard error, 372 00:22:05,320 --> 00:22:07,879 and we don't need to have anything in there. 373 00:22:07,879 --> 00:22:10,200 So then we need to handle our response. 374 00:22:10,200 --> 00:22:12,600 Again, we'll make that a private method, 375 00:22:12,600 --> 00:22:16,360 and let's just return the JSON dot parse 376 00:22:16,360 --> 00:22:22,040 response.body if it was a net HTTP success. 377 00:22:22,040 --> 00:22:25,560 If it wasn't a success, then we're not going to return, 378 00:22:25,560 --> 00:22:27,399 and then we could do something else here. 379 00:22:27,399 --> 00:22:29,639 We could say some kind of error message, 380 00:22:29,639 --> 00:22:34,439 and we can set this to go to the API request failed with code, 381 00:22:34,439 --> 00:22:37,959 and then we can't interplay it in response.code, 382 00:22:37,959 --> 00:22:42,280 and then we could also interplay it in the response.message. 383 00:22:42,280 --> 00:22:46,760 We can raise the API error with that error message, 384 00:22:46,760 --> 00:22:49,320 but then we also want to handle in case 385 00:22:49,320 --> 00:22:52,360 if we are not getting the proper response. 386 00:22:52,360 --> 00:22:54,840 So for not getting a good response, 387 00:22:54,840 --> 00:22:57,080 meaning that the JSON parsing will fail, 388 00:22:57,080 --> 00:23:00,520 we could also rescue from the JSON parser, 389 00:23:00,520 --> 00:23:03,720 and then we can raise to the API error 390 00:23:03,720 --> 00:23:07,080 that we were unable to parse the JSON response. 391 00:23:07,080 --> 00:23:09,480 And so while this was a bit more, 392 00:23:09,480 --> 00:23:11,879 then the actual API commenter, 393 00:23:11,880 --> 00:23:14,440 I think we are doing two very different things, 394 00:23:14,440 --> 00:23:17,560 and the reason why I like breaking it up like this 395 00:23:17,560 --> 00:23:22,760 is because we have so much going on around that HTTP within here. 396 00:23:22,760 --> 00:23:27,240 Sure, we could use something like HTTP party or another gym. 397 00:23:27,240 --> 00:23:29,960 However, I really don't think that's necessary, 398 00:23:29,960 --> 00:23:34,280 especially once we create some kind of API client like this. 399 00:23:34,280 --> 00:23:38,920 I am going to require the net HTTP at the top here. 400 00:23:38,920 --> 00:23:42,360 Just in case if we're not requiring that else we're in our application, 401 00:23:42,360 --> 00:23:47,480 we don't want to get an error raised that the net HTTP doesn't exist. 402 00:23:47,480 --> 00:23:49,800 It is part of the standard Ruby library, 403 00:23:49,800 --> 00:23:53,160 so there is no external gym that we have to require. 404 00:23:53,160 --> 00:23:56,360 And so once you say you're open a i access token, 405 00:23:56,360 --> 00:23:57,560 don't forget to do that. 406 00:23:57,560 --> 00:23:59,320 We can come in and test this out. 407 00:23:59,320 --> 00:24:01,640 We do what is drifting Ruby. 408 00:24:01,640 --> 00:24:03,160 We'll create our comment, 409 00:24:03,160 --> 00:24:05,720 and then we can ask a i to respond. 410 00:24:05,720 --> 00:24:09,320 It'll take a moment because it is making a API request 411 00:24:09,320 --> 00:24:11,160 and doing some AI generation, 412 00:24:11,160 --> 00:24:13,000 but then we get our response. 413 00:24:13,000 --> 00:24:16,680 And then we could also just make some other kind of comment, 414 00:24:16,680 --> 00:24:18,280 S the AI to respond, 415 00:24:18,280 --> 00:24:20,680 it will respond to that particular comment, 416 00:24:20,680 --> 00:24:23,080 and then we got the response. 417 00:24:23,080 --> 00:24:24,600 And if we look at our logs, 418 00:24:24,600 --> 00:24:28,520 we can see the response that we got back from open a i. 419 00:24:28,520 --> 00:24:31,880 And just so you know how the open a i does handle its billing, 420 00:24:31,880 --> 00:24:33,480 with the prompt tokens, 421 00:24:33,480 --> 00:24:35,880 that was eight, and the completion token, 422 00:24:35,880 --> 00:24:38,680 so the number of words it said in response, 423 00:24:38,680 --> 00:24:41,720 was 20 for a total tokens of 28, 424 00:24:41,720 --> 00:24:46,280 so you would actually be metered build on that 28 tokens. 425 00:24:46,280 --> 00:24:49,000 And so if you're going to implement something like this, 426 00:24:49,000 --> 00:24:51,720 if that is something that you would want to pass a charge 427 00:24:51,720 --> 00:24:53,480 onto the end user, 428 00:24:53,480 --> 00:24:57,560 whether just for the completion tokens or whatever the situation, 429 00:24:57,560 --> 00:25:02,600 you do have access to the usage from that particular user, 430 00:25:02,600 --> 00:25:05,639 but you do want to be careful because it is a metered billing, 431 00:25:05,639 --> 00:25:08,120 and it could get out of hand pretty quick. 432 00:25:08,120 --> 00:25:10,360 And if I were to refactor this, 433 00:25:10,360 --> 00:25:12,199 if we had a particular need, 434 00:25:12,199 --> 00:25:14,760 let's say for the API client, 435 00:25:14,760 --> 00:25:18,840 we also had a situation where you wanted to make a get request, 436 00:25:18,840 --> 00:25:23,159 you then wanted to make a post request or a put or a delete, 437 00:25:23,159 --> 00:25:27,240 multiple times within one single request from the end user, 438 00:25:27,240 --> 00:25:31,879 we are rebuilding a lot of the net HTTP internals here, 439 00:25:31,880 --> 00:25:34,200 for each one of the things that we're doing. 440 00:25:34,200 --> 00:25:39,000 So one option that you could do is instead of passing in that full URL, 441 00:25:39,000 --> 00:25:41,560 we could just pass in the base URL, 442 00:25:41,560 --> 00:25:45,320 and then on the get request, the post put in delete, 443 00:25:45,320 --> 00:25:47,880 we could just take in the URL I. 444 00:25:47,880 --> 00:25:50,920 We would need to update our request to handle that a bit, 445 00:25:50,920 --> 00:25:55,720 but once we initialize the API client and the class that's consuming it, 446 00:25:55,720 --> 00:25:59,960 we can then basically just have one instance of the net HTTP, 447 00:25:59,960 --> 00:26:02,600 and then make the appropriate requests. 448 00:26:02,600 --> 00:26:05,720 But in my case, that really hasn't come up very often, 449 00:26:05,720 --> 00:26:09,480 because the APIs are often interface with our fairly simple, 450 00:26:09,480 --> 00:26:14,360 you just make a request already providing in some kind of credentials. 451 00:26:14,360 --> 00:26:18,520 If you were doing something where you first had to make an authentication request, 452 00:26:18,520 --> 00:26:20,280 and some other kind of handshake, 453 00:26:20,280 --> 00:26:23,960 then I could see that kind of refactor may make sense, 454 00:26:23,960 --> 00:26:27,800 just so we're not having to do an SSL handshake multiple times, 455 00:26:27,800 --> 00:26:31,159 but that net HTTP instance could be reused. 456 00:26:31,160 --> 00:27:00,840 Well, that's all for this episode. Thanks for watching. 41107

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.