Have you been wanting to get started using machine learning to generate images from the models available on Replicate? Well, in this tutorial, we'll explore Replicate's wide range of hosted models and Upstash's Redis. Not only will we explore these models, but we'll walk through the process of setting one up, and touch on how you can easily update the implementation to use other models too.
In this tutorial, we'll cover the usage of Microsoft's Bringing Old Photos Back to Life model, which essentially takes an old photo, runs it through the model, and outputs an edited, and hopefully improved version of your photo.
What's the architecture?
If you have some React experience, you should be able to determine how the app architecture works simply by reading through the codebase, but to make it that little bit easier, or if you simply prefer to see an overview, there is one provided below.
What do I need to start?
To start with, you'll of course need a Next.js project. This can be done by following the Next.js setup guide here, or if you have one already setup, then that's okay too. In this tutorial, we're also using Tailwind CSS, but you can of course use any form of styling setup that you prefer.
Now that we have a basic Next.js project setup, we can still Upstash's Redis library by running the command:
Next up, we'll want to populate our .env.local file with the following keys, of which the Redis token can be found in your Upstash console, the Replicate API token here under your account, and your site URL would be wherever you deploy it, so in this case it would be the Vercel deployment endpoint.
Setting up the frontend form
To begin with, we'll need a form that handles the form, polling and displaying of completed images.
Restore Image Form Creation
File: pages/index.tsx
By default, this component displays a form allowing the user to enter the image URL of the image that they'd like to restore, and a couple of options to go alongside it such as whether the image is high resolution, or if the image has scratches that need to be removed. Once the user fills in this information, and submits the form, it sends a POST request to /api/create along with the form data.
Once this request has been sent to the API and a response has been received with the prediction information that has been returned, the component enters into a polling state that checks sends a GET request to /api/poll once per second in order to check if the prediction has completed yet. Once a polling request returns a successful response, indicating that Replicate has sent a request to our callback endpoint, we'll now have access to the prediction output.
Whilst the polling is ongoing, the form displays a button with the option to cancel the prediction. Once pressed, this sends a POST request to /api/cancel with the cancel_url from the prediction data that we received upon initial creation.
The polling implementation utilises a custom hook to be located in hooks/useInterval.ts which allows us to easily and seamlessly work with React's component lifestyle, and provide a more convenient way to handle intervals with callbacks within any given React component. You can read more about this hook here and here should you want to learn more about it and in greater detail.
API Setup
The API setup, made up of a few files, is what allows us to create and cancel predictions, poll to check when predictions are complete, as well as specify the callback that Replicate will use for when the prediction is complete on their end.
Image Prediction Creation
File: pages/api/create.ts
For our create API endpoint, we first do a simple check to ensure that the incoming request method is a POST request, and if not we'll return a simple 400 response. We then proceed to send a POST request to Replicate with our Replicate API token. The request body consists of the parameters for the given model version which indicates what model we are sending the request to (this is found under the "API" tab on the model you'd like to use). We also pass through the parameters associated with the model with the data from the form on the frontend.
Once the request has been sent, we use the returned prediction id to store it in Redis, and return the prediction data to the frontend to be used in polling the Redis item until it consists of a completed prediction.
Callback
File: pages/api/callback.ts
The callback endpoint is what Replicate will send a POST request to in order to let us know that the processing of a given prediction has finished. When we receive this request, we retrieve the prediction data from the request body, and update the given Redis item with the completed prediction data.
Polling
File: pages/api/poll.ts
For our polling setup, we extract the id from the request and then try to retrieve the data stored in Redis under that identifier, and if no data is found, we return a 404 response, but if there is data, we return said data as part of a 200 response.
Cancel
File: pages/api/cancel.tsx
The API endpoint for cancelling predictions which have been started is rather straightforward. We simply extract the cancel_url which is passed through from the frontend which in itself comes from the prediction that was stored when a creation request was submitted, and we simply send a POST request to that endpoint, alongside our Replicate API token.
Libs
For our libs, we'll create a Redis client which is used in tracking
File: lib/redis.ts
This object will be used within the application to store and retrieve data whilst being polled, so that we know when the webhook completion from Replicate has happened.
Conclusion
Replicate have a variety of models available that can be used via an API. With Vercel and Upstash, it's easier than ever to utilise machine learning models and deploy usable web applciations.
If you'd like to view the complete repository, you can access it here.
Further Development
This is just a simple example of utilising a rather simple model with Replicate. By simply switching up the form parameters and the version in the API, you can easily change to another model as so long as you have your Replicate API token linked, you'll be able to consume any of the available models.
You can explore all of Replicate's available models here, and once you find one you'd like to experiment with, you can click on the "API" tab in order to view the usage of it. Here you'll also find buttons for Python, cURL, Cog and Docker, which allow you to test out the model, but it's also useful for knowing which parameters are required, and how they are sent.