Build a Fullstack Next.js App, v4

Adding AI to Actions

Brian Holt
Databricks
Build a Fullstack Next.js App, v4

Lesson Description

The "Adding AI to Actions" Lesson is part of the full, Build a Fullstack Next.js App, v4 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates summarizing articles with AI, moving the code to the correct directory, updating the database schema with a migration, and integrating summaries into the front end, while addressing troubleshooting and future improvements.

Preview

Transcript from the "Adding AI to Actions" Lesson

[00:00:00]
>> Brian Holt: So let's go and we are going to go to our actions, our articles, and we're going to summarize the hell out of some articles. Import summarize article from—I would change that just to at. Uh, is it not? Oh, this AI, sorry, it was not meant to be in the app directory. It's meant to just be in like the root of the source directory. So what I did, I had AI in the app directory, and I moved it into just the plain source directory.

[00:00:50]
Yeah, so this should be the correct path. OK, and now we're going to go to our create article here. So we're going to have this and we're going to do const summary equals await summarize article, data.title or empty string, if it doesn't come in with it, data.content or empty string, which this would get rejected, which is fine that we already wrote the code for that.

[00:01:41]
And now we'll have this summary, which should be a string. Now, we want to insert this into the database, so we're going to put summary, but it's going to yell at us right away, it's like, hey, I don't have a summary, which is true, we didn't put that in our initial schema, so we are going to have to do a migration, which we'll do here in just a second.

[00:02:03]
Um, and we're going to put the exact same code here into our update as well. OK, update, update, update, update. Yeah, you'll notice that I have this underscore on here now. I was just fixing some linting errors off camera, and if you don't put an underscore here, it gets mad at you for this is used but never read, or this is created but never read.

[00:02:32]
You can silence Biome by putting an underscore there, which I thought was kind of nice. Really what they want you to do is just do this and just ignore it totally and not store it. Both of those are fine though. Uh, all right, and then here, we're going to do kind of the same thing, we're just going to say summary. Um, and so if there is a new summary, then put it in there, otherwise put in undefined.

[00:03:03]
Right, so that's really it now. It's going to again yell at us and say, hey, I don't have a summary, please go fix that for me. It's really going to be pretty simple, like, I was originally just going to like go back port summary to like exist at the beginning, um, but I thought it'd be useful for you to see like how a migration is done. So, we're going to go into our DB, we're going to go into our schema.

[00:03:27]
And we're going to come in here and just at the bottom, or really wherever, we're just going to say summary. And it's going to be a text. Summary, like, we're not doing anything more interesting than just setting another text column called summary. And then now, really all it is, is we're just going to say npm run uh DB generate. It's going to see that this is slightly different than it was before.

[00:03:57]
If you go look in our Drizzle directory, it really just generates one alter table statement. Add column summary. And then I'm just going to run npm run DB migrate. And now suddenly we have a summary. Uh, if you want to go validate that, we can go to Neon. Uh, log in. FAM Wiki Masters, if we look at our table. Uh, we're in user sync. We want to be in public.

[00:04:38]
Um, we can see here somewhere. Summary, just null, for all of these. Pretty simple, right? Drizzle makes managing these migrations really easy. You just kind of update your schema into whatever you want, it does the diff on it, it figures out what migration needs to generate, you run generate, you run migrate, and it's done. Um, we won't actually do this in the course of this class, but like what you would do with production then is like whenever it gets deployed, if it sees that it doesn't have migrations applied, just apply the migrations and go from there.

[00:05:09]
And so, when I was at Reddit, we used a lot of Django, and Django has its own ORM built into Django, um. It's much better now. I've looked recently, but back then, those migrations failed all the time. To be incredibly fair, we wrote that migrations, so, uh, if you want to look at the culprit, I should probably find a mirror, um, but it just failed all the time, and I've actually never, I've maintained some decently sized Drizzle product, I've never had it fail, like it works really well.

[00:05:46]
Um yeah, and one more thing just to prove my point, if you go look at the, uh, Drizzle schema here. We should see two rows in this database, right? So that now it has both of these migration supplied. Which is cool too, right? Yeah, really at some point, something that we eventually ended up doing at Reddit, which probably applies to Drizzle. When you have like 70 migrations that you're running, at some point you should just go squash them down to another like, let's just get started from one migration.

[00:06:18]
And we just never did that. Every time our database was going out, it was running 70 migrations. Which takes a while, as you might imagine, and fails in spectacular ways at times that you don't want to. OK, so, let's go into uh data, articles. Uh, which is going to be in our lib, lib data articles. Um, in our get articles we're going to put in here summary, and that's going to be articles.summary.

[00:07:06]
That's going to come into the response, and we just return the response. Yeah, as unknown, uh, I don't remember why I did that. In any case, now this should go to the front end, I think the front end it should be already all wired up to have this, let's go see what happens. So npm run dev here. Uh, open our page Wiki masters. So, uh, and we actually, this is on the wiki article viewer.

[00:07:51]
So we might need to look at the article viewer here. And do I have summary being used here? No, I think it's just using content. So you might need an article content here. I think it's just displaying the content, am I right? Card content rendered markdown content. And I don't want the article view. I want the home page. Yeah, because that's where we want to show it.

[00:08:29]
So it's not there, it's in, uh, app page. Wiki card, oh, it's going to be in the wiki card. Uh, which is going to be in the UI, it's going to be in the wiki card. Card description is summary, alright, and so summary comes from this and where's the summary made? That's got to be on the page that we're just looking at, right? Oh yeah, OK, so I was right.

[00:09:01]
So you're going to come to, um, this is app, so source app page.tsx. Right now this has just content being substringed to 200, which is definitely not how you want to do that because that would just cut off in the middle of the word. Right, we actually just want this to be summary, so instead of content here, we're going to pull in summary like that.

[00:09:37]
Uh, and why are you mad about this? Does not exist on article list. Um, so that needs to be modified in, um, where that comes from, which is from the data, yeah, from data articles. We don't have content on here, which we need to put something very similar to this, and this will be summary. And I think that should work. Let's just npm run lint, make sure, uh.

[00:10:18]
Yeah, so what did we? Oh, that's from email. Nobody cares about email. Jeez, uh, can I just fix these? Sure can. Don't even care what was wrong. After spending a bunch of time with Biome, this was the first time I spent a lot of time with Biome, it is a much noisier, uh, and like, the tooling is much less mature than ESLint. Like in retrospect, I kind of wish I had taught ESLint for this class, because ESLint, I figured out over the, what, 8 years I've been teaching with ESLint.

[00:10:52]
It's very easy to kind of mold to what you want it to be. Biome is a much stricter tool. Which is not to say like I think they're heading in a really good direction. It's just, it was hard to teach with that. More than anything, the tooling is less mature than. Uh, yeah, I guess this is here on page. Um, we're going to put summary or just empty string like that.

[00:11:26]
Like if there's no summary there, just to put nothing there, or like you could put like summary not done yet. So we still have a problem here. I think if we go back to our page after we npm run dev again. Yeah, none of these summaries are done yet, right, because we haven't edited or created these articles recently, they have nothing in there. In theory, let's just go edit one of these, edit article.

[00:12:16]
Um, let's give it like a more useful title, uh. Websites and forests. And we'll save article. OK, let's go check our thing here. Um, did we get an AI summary here? Update article called. Did we not log anything from our AI summarize? I don't think we did. No, there's no article here, so if we refresh the page, so this all worked. Now if we go find, uh, websites.

[00:12:55]
Is it just it just like straight up delete it? Oh, maybe it's because it's cached. I don't remember. Yeah, websites and forest. And then you can see, it's funny that the summary is somewhat longer than the actual thing itself. But that came from uh OpenAI. Which is probably hard to see. Let's make it just temporarily much bigger. Kind of cool, right?

[00:13:23]
It's cool that it was that easy to integrate AI into whatever we were doing. OK, so. Now we do kind of have somewhat of a problem that we have a bunch of articles that don't have summaries. I think you can imagine a future where like, maybe some summaries fail here and there, like we kind of want to make that something that's failable because it's not the biggest deal if summary doesn't get done now and it gets done later.

[00:13:48]
So how do we do that? How do we have it so that like, we could go back and fix these kind of errors? There's a bunch of ways to do it. Um, my initial instinct is like let's just have a job that does it, right? Like some sort of like cron that does it. The nice thing with Vercel and Next.js is like they kind of, it's built into the framework. There's a way to do crons with the framework itself.

[00:00:00]
It's, I would qualify it as like minorly hacky, not the most hacky, could be more hacky, still somewhat hacky. You write an API route and then you tell Vercel via configuration to call that, uh, API route as a job. So minorly hacky does work pretty well though. I've used it quite a bit.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now