در حال بارگذاری ...

Deciding If You Care0:18

But I get it, it's 2026. And especially if you're younger, you might be thinking, what are you doing, bro? This is boomer mentality. It just doesn't matter. I don't care. Now, whenever you're working with ai, it is crucial that you ask yourself one key question, and that question is this, do I care or do I not care? And I'm not even being snarky, by the way. Sometimes your answer to

And I'm not even being snarky, by the way. Sometimes your answer to that question might be, you know what? I really don't care. And this is a vibe coded project, it's personal software, it just doesn't matter. And in those cases, you can lean on the AI a bit more heavily, but in other situations, maybe for your core project or the thing that makes you money and pays the bills, in those cases, you do care, right? And if that's the case from personal experience in 2026, as

and pays the bills, in those cases, you do care, right? And if that's the case from personal experience in 2026, as of this recording, don't just let AI have its way with your code base. I promise you, if you're a developer and you take the time to review every changed file, here's what's gonna happen. You're gonna take a look and you're gonna think to yourself, Hmm, what? Why did, wait, why are we caching it?

Hmm, what? Why did, wait, why are we caching it? I didn't say anything about caching. Respond to Why are we doing flesh? Why can't we use yield here? You're just gonna find endless things that AI did that either doesn't match your style, which is important, or it just isn't an efficient way to do that. So now imagine for every single file where it just kind of misses the Mark A. Little bit, compounds.

So now imagine for every single file where it just kind of misses the Mark A. Little bit, compounds that over the next year for every single feature and commit you make, because now of course, you're working at light speed, right? Well, now imagine your code base deteriorating, deteriorating at light speed. We can't allow that. So here's what I would recommend. Come along here. We have a controller called VideoAIController,

Reviewing VideoAIController2:14

Come along here. We have a controller called VideoAIController, and it's in charge of generating an AI response and then returning that as a stream. And it was entirely generated to use it two times by ai and it works. And then at the same time, I just don't like it at all. But first, before we decode this and improve it, I just wanna show you effectively what it does.

and improve it, I just wanna show you effectively what it does. So if we visit any video page and scroll down, you'll find an ask AI tab. And here we can ask AI about the video. We even feed it the transcript. So I could say, what is Eloquent? And now if we give this a run, I want you to notice that it's going to stream the response and notice how this is a much better experience versus the

that it's going to stream the response and notice how this is a much better experience versus the alternative, which is just seeing a loading spinner for 5, 6, 7 seconds until uh, it completes, right? So this is what that controller allows for. Alright? So let's take a look real quick. We have a generate method. Immediately as I'm reviewing this, uh, I love to stick to the seven resourceful actions. I'm kind of a stickler for that. Next, we validate the request. Okay?

Evaluating Caching Strategy3:19

I'm kind of a stickler for that. Next, we validate the request. Okay? So we have an incoming question. What is Eloquent? All right, that's fine. And then we grab the question and we trim it. All right? We load the transcript because that will be included along with the prompt. All right? And then it looks like we're caching here, but what are we caching? We're caching the question.

but what are we caching? We're caching the question. So that means if multiple people ask the same question, we don't defer to AI multiple times, we just return the cash response. But immediately, as developers, we might be thinking, well, wait a minute. Will that ever happen? Will anyone ask the identical question down to every character as somebody else? No. And then further, if we scroll down,

This is just a simple explanation with no code.

Instead we just return the cash response. But you know, what, is that really gonna happen? And is there any situation where multiple people are gonna ask the exact same question? Probably not. And yet we still have it built in. All right, well, I don't really like that, but it would just live there. Um, if I didn't review this file, let's keep going though. So we figure out if we have something in the cache, and if so, we just return our response stream.

So we figure out if we have something in the cache, and if so, we just return our response stream. Now, if you're not familiar with streams, this is what supports incremental, uh, responses. And it looks like it's echoing, and then it's using PHP's ob_flush and flush. But can't we just use yield? In that case, maybe AI doesn't know or didn't think about that. All right? Next, if we don't have a cash response,

doesn't know or didn't think about that. All right? Next, if we don't have a cash response, we do another response stream. All right? We send through the cash key. Here is my little, uh, service to delegate to our AI. Uh, now we are using a dedicated prompt. And it's doing this because I do have it in my guidelines. I don't like to have massive strings unless they're very basic, but I don't like to have massive strings for my prompts.

unless they're very basic, but I don't like to have massive strings for my prompts. Instead, I have dedicated classes that are my prompts. And here you can see again, this was generated by AI and we might wanna tweak it a little bit. Okay? Anyways, we're gonna skip over that for this video. Next, we get the response, and then we, we have this sendStreamed method and we loop over it. And once again, we echo it out,

and we loop over it. And once again, we echo it out, which supports the client receiving feedback on the fly, right? That's, that's what a stream allows for. And then finally, we c the completed response again. So maybe on the next page load, in the weird situation where somebody asks the exact same question, again, we don't have to defer to ai, okay? So then we have another one that's, um, unrelated. Okay?

we don't have to defer to ai, okay? So then we have another one that's, um, unrelated. Okay? So this is such a great example of how it works, right? And if this were vibe coated and you didn't care, maybe it's fine. But I care. And in this situation, I just don't like this. I don't want this to compound into worse and worse and worse and more deteriorated, deteriorated code, uh, over the next year.

Refactoring With AI6:32

and more deteriorated, deteriorated code, uh, over the next year. So we're gonna nip this in the bud right now and clean it up and we're gonna use AI. We're gonna make AI clean up its own mess. Let's get going. Alright, so let's bring up the terminal. I'm gonna boot up Claude. And the first thing I wanted to do is consume this file. So don't do anything until you know what you're working with.

So don't do anything until you know what you're working with. I'll say consume VideoAIController, and then I'll do voice to speech. I have some questions and we need to perform some refactors. Also, note that you made this entire file, all right? It's reviewed it. What are your questions? Okay, so the very first thing I wanna do is retire the caching functionality.

Okay, so the very first thing I wanna do is retire the caching functionality. I don't think we will benefit from the caching here. It's only for five minutes at a time. And the key is based upon the exact sequence of characters for the question. Uh, it's very unlikely that people will ask the same question. So let's retire that feature entirely. Update the file. Alright, that's done.

So let's retire that feature entirely. Update the file. Alright, that's done. So let's have a look and yeah, no reference to caching already. This looks much better. I like this. Alright, what next? Well, do I want to tackle this or the name? Let's go with the action name. So yeah, generally this is just a, a preference, but I'm kind of a stickler for my Laravel controllers. Uh, adhering to the seven resourceful actions.

but I'm kind of a stickler for my Laravel controllers. Uh, adhering to the seven resourceful actions. Maybe that's old school, but I still like it. So in this case, generate violates that. Uh, I don't want that you have it in your guidelines that Laravel controllers should adhere to CRUD by design as a principle, but in this case, we have a generate method. I'd like to fix that. So, uh, why don't you help me brainstorm a new controller, uh, that we could create and at which point the generate method

why don't you help me brainstorm a new controller, uh, that we could create and at which point the generate method could change to store. Yeah, so here's what I like about voice to speech is I think out loud and I make mistakes. Uh, I stumble on my words, but it's okay. It's close enough. It's much better than a, a four word, uh, direction that may isn't as clear to the ai. All right, so let's have a look. The current structure. Yes, yes. Uh, it's recommending a video AI

All right, so let's have a look. The current structure. Yes, yes. Uh, it's recommending a video AI response controller and a store action upon that. And I think that actually makes pretty good sense. So I'll say yes, I like that. Extract generate to, uh, video AI response controller at store. Okay? So now it's going to create a new layer fill controller. Uh, it's gonna take this generate method.

to create a new layer fill Controller. Uh, it's gonna take this generate method and it's gonna migrate it over and then, excuse me. Then it's going to of course update the, um, the endpoint in my routes file. Also, notice we have hooks in place so it knows, well, you made some changes. Let's make sure you run your test suite. Make sure you run pint on the changed files. And by the way, when you run pint,

Make sure you run pint on the changed files. And by the way, when you run pint, there is a --dirty option, uh, you can include, and that will only run pint on your git dirty files. All right, all done. So it created a new controller. Now we have, um, we're back to the resourceful action names. That's great. It cleaned up the existing VideoAIController, uh, and it updated the routes and the component. Great. So let's, uh, close this out. We can take a look. Here is VideoAIController,

Great. So let's, uh, close this out. We can take a look. Here is VideoAIController, and now it just has that unrelated store action, which is related to persisting, um, uh, a question that somebody asked. And that's an admin thing. So ignore that. So now I can switch over to VideoAIResponseController. And now once again, notice we're back to that store action. Perfect. Okay, so that's good. We've removed the caching, we've adhered to our guidelines.

Explaining Streamed Responses10:09

Perfect. Okay, so that's good. We've removed the caching, we've adhered to our guidelines so we have more consistency. That's great. Next, this section right here. Now, if you didn't understand how streams work, um, you probably say, okay, this is fine. I don't really know what's going on. I don't, you learned about ob_flush in year one, but maybe since then you've forgotten about it. You don't really know what's going on here, but it works.

but maybe since then you've forgotten about it. You don't really know what's going on here, but it works. So you leave it as it is, and maybe that's okay. But I would recommend always use AI to improve yourself. Don't simply just accept what it writes. Learn. So let's imagine in this case, streamed responses is just not something you picked up along the way. Awesome. Let's learn. Let's go to up. Hey, can you teach me the difference

Awesome. Let's learn. Let's go to up. Hey, can you teach me the difference between returning a standard response versus a streamed response? All right, so it's going into teacher mode. All right, let's scan this and improve ourselves. A standard response waits until everything is ready, right? That makes sense. Once you have the full response, we load the page. That's what you're used to. Uh,

full response, we load the page. That's what you're used to. Uh, however, a streamed response since the data incrementally, and that's what creates the illusion of, of something typing. Uh, that's the streamed response coming in as you read it. So we have a stream and then we loop over the results and we're gonna talk more about

and then we loop over the results and we're gonna talk more about sun strains in just a minute. And then it will echo the content, and then it runs ob_flush to make sure that we, that we, we flush out the, um, the output buffer so the connection stays open and each echo pushes a piece of data to the client in real time. That's what streaming refers to. Cool. So with a standard response,

That's what streaming refers to. Cool. So with a standard response, the user would stare at a spinner for several seconds. We talked about that at the beginning of the video with streaming. They see the text appear word by word as the model produces it. So finally, yeah, just if you have forgotten what this does, uh, ob_flush is necessary because php and the web server each maintain their own output buffers.

uh, ob_flush is necessary because php and the web server each maintain their own output buffers. You need to flush both to ensure the chunk actually reaches the client rather than sitting in a buffer. Okay? So this works and it's fine, but I know a little bit about this and I don't feel like we need this. Can't we just switch to using yield in this case? Loop over the output, yield the chunk, and you're good to go.

Loop over the output, yield the chunk, and you're good to go. That should achieve the exact same thing. So let's see. Looking over this, I feel like we could use the yield keyword instead of echo and flush. What do you think? Maybe I'm wrong, but I don't think I am. All right. So that's a reasonable instinct. yield would make this read more cleanly as a generator, but it won't work here. I'm pretty sure it will though.

but it won't work here. I'm pretty sure it will though. Uh, php's response stream expects a callback that directly writes to the output buffer via echo. It does consume a generator. If you yield values, nothing actually sends them to the client. Definitely challenge me if I'm wrong, but I think you are incorrect in this case. Can you dig more deeply into that response stream method?

but I think you are incorrect in this case. Can you dig more deeply into that response stream method? I'm fairly certain that I can use yield in this case. Alright, so notice immediately it launches a subagent. And the reason why he does this is it allows it to perform a bunch of research without polluting the current context window. Remember, your context is only so big when using Claude. So instead it sort of throws it into the background almost like a queue, do some research and then come

So instead it sort of throws it into the background almost like a queue, do some research and then come and give me the result and I will provide it to the user. So in this case, let's see, you're right, I was wrong. Laravel three method explicitly checks if the callback is a generator. In fact, if we were to take a look, show me an implementation. Yep. So if, uh, the function is a generator, then it can handle that.

Simplifying With yield13:57

Yep. So if, uh, the function is a generator, then it can handle that. Cool. So when it detects one, it wraps it automatically iterating, iterate, iterating the yielded values, echoing each chunk and handling the ob_flush calls for you, right? So we were doing a bunch of work that was simply unnecessary. So the controller can be simplified. Yeah, so this is even better.

So the controller can be simplified. Yeah, so this is even better. 'cause here's what I was expecting it to do. I was expecting it to do, excuse me, I was expecting it to do something like this. Yeah. So I thought it was gonna do something like this where it yields the chunk, uh, and that would work. But in this case, AI was actually a little bit smarter. Let's go to two up. In this case, AI dug into our sendStreams method that simply defers

Let's go to two up. In this case, AI dug into our sendStreams method that simply defers to the OpenAI wrapper, and it gets not the response, but the streamed response, at which point it loops over the stream, it grabs the content and it yields the content. So it's yielding within this method, and then the rest of it is just, um, compiling it so it can build up the full response, not each stream, but the collective response.

so it can build up the full response, not each stream, but the collective response. And that gets stored here. Okay? So think about it because we're yielding within this method. Well, if I switch back, instead we could replace this entire thing. You may not even know this. You can say yield from, and then you reference your method. So now the method will loop and perform the yield, and we can yield from that method call.

So now the method will loop and perform the yield, and we can yield from that method call. So now this is what we get. All right? So this is looking good. Uh, next AI chat, it's fine. If you want, maybe change that to message and you could say, all right, we're gonna build up our message and send it to AI and get a streamed response. Cool. Uh, what else? Video load transcript. This is just eager loading. A hasOne relationship.

Cool. Uh, what else? Video load transcript. This is just eager loading. A hasOne relationship. Um, it's not overly necessary. Uh, because well, if you didn't include it, it's still going to perform a query to grab the transcript when it builds up the prompt. So you, you might include this, if you have a constraint where you say, look, disable eager loading entirely, um, or, uh, uh, disable it on the fly. I need to be explicit about what I eager load.

or, uh, uh, disable it on the fly. I need to be explicit about what I eager load. Otherwise, if you don't have that enabled, this is, you know, it, it's not providing much value other than being explicit that the video depends on the transcript. Alright, next up, uh, the question. Yeah, I mean, that's fine. We already know the question is going to be a string, so I feel like we can grab or we can get rid of that entirely.

so I feel like we can grab or we can get rid of that entirely. Okay, so now let's review this, wrap it up, and then I wanna wrap up one final thing with you. So hang tight. So if we have a look here, it's so much easier to reason about we validate the request, we grab a question, we fire it off to ai, and we return this streamed response so much easier. And I don't care what anyone says this matters, but I get it, it's 2026.

And I don't care what anyone says this matters, but I get it, it's 2026. And especially if you're younger, you might be thinking, what are you doing, bro? This is boomer mentality. It just doesn't matter. I don't care. I'm on the team that says right now it does matter for the things I care about. And I will consent that there's some things I just don't care about. But for the things that make me money, it is my duty

that there's some things I just don't care about. But for the things that make me money, it is my duty and responsibility to care about these things so as to ensure they don't deteriorate over time. All right? It's important. Can't help it. And I hope you agree, but tell me what you think.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟