Skip to content

Commit

Permalink
Merge pull request #64 from replicate/reduce-prediction-load
Browse files Browse the repository at this point in the history
Rely on app database rather than replicate for prediction polling
  • Loading branch information
cbh123 authored Dec 4, 2023
2 parents 199b111 + b234742 commit d4b1b5a
Show file tree
Hide file tree
Showing 13 changed files with 38 additions and 24 deletions.
6 changes: 4 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ OPENAI_API_KEY=

# setup a supabase account and create a new project https://supabase.com/docs/guides/getting-started/quickstarts/nextjs
# this is only required if you want your outputs to persist, or if you're using controlnet (input image uploads need to be saved to a DB)
SUPABASE_SERVICE_ROLE=
SUPABASE_URL=
SUPABASE_JWT=
SUPABASE_KEY=

# host for your supabase "images" bucket used to store and serve predicitions
# e.g. xyz.supabase.co
NEXT_PUBLIC_SUPABASE_IMAGES_HOST=

# install https://ngrok.com/, run it, and set the host here
NGROK_HOST=
2 changes: 1 addition & 1 deletion components/controlnet-prediction.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function ControlnetPrediction({ prediction }) {
}

async function getOutput(prediction) {
const bucket = `https://ennwjiitmiqwdrgxkevm.supabase.co/storage/v1/object/public/images/public`;
const bucket = `${process.env.NEXT_PUBLIC_SUPABASE_IMAGES_URL}/storage/v1/object/public/images/public`;
const predictionUrl = `${bucket}/${prediction.id}.png`;
const predictionAnnotationUrl = `${bucket}/annotated-${prediction.id}.png`;

Expand Down
2 changes: 1 addition & 1 deletion components/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default function Popup({ open, setOpen }) {
width={250}
height={250}
className="mx-auto"
src="https://ennwjiitmiqwdrgxkevm.supabase.co/storage/v1/object/public/images/public/2370caef-bc8c-423e-88bb-0ca4a71e19c8.png"
src={`${process.env.NEXT_PUBLIC_SUPABASE_IMAGES_URL}/storage/v1/object/public/images/public/2370caef-bc8c-423e-88bb-0ca4a71e19c8.png`}
alt=""
unoptimized={true}
/>
Expand Down
2 changes: 1 addition & 1 deletion components/prediction.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function Prediction({ prediction }) {
if (prediction.output) {
return prediction.output;
} else {
return `https://ennwjiitmiqwdrgxkevm.supabase.co/storage/v1/object/public/images/public/${prediction.id}.png`;
return `${process.env.NEXT_PUBLIC_SUPABASE_IMAGES_URL}/storage/v1/object/public/images/public/${prediction.id}.png`;
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ if (process.env.SUPABASE_URL) {
db = createClient(supabaseUrl, supabaseKey);
}

module.exports = db;
export default db;
4 changes: 2 additions & 2 deletions lib/upsertPrediction.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ export default async function upsertPrediction(prediction) {

const { data, error } = await db
.from("predictions")
.upsert([predictionObject], { onConflict: "id" });
.upsert(predictionObject, { onConflict: "id" });

if (error) {
console.log("error upserting prediction ", error);
console.log("error upserting prediction ", predictionObject, error);
}

console.log(`prediction ${JSON.stringify(predictionObject.id)} upserted`);
Expand Down
2 changes: 1 addition & 1 deletion pages/api/og.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default async function handler(req) {
try {
const { searchParams } = req.nextUrl;
const bucketUrl =
"https://ennwjiitmiqwdrgxkevm.supabase.co/storage/v1/object/public/images/public/";
`${process.env.NEXT_PUBLIC_SUPABASE_IMAGES_URL}/storage/v1/object/public/images/public/`;
let predictionIds = searchParams.get("ids").split(",");
let outputUrls = predictionIds.map((id) => `${bucketUrl}${id}.png`);
const prompt = searchParams.get("prompt");
Expand Down
24 changes: 17 additions & 7 deletions pages/api/predictions/[id].js
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import Replicate from "replicate";
import db from "../../../lib/db";

const replicate = new Replicate({
auth: process.env.REPLICATE_API_TOKEN,
});

export default async function handler(req, res) {
if (req.method === "GET") {
const prediction = await replicate.predictions.get(req.query.id);
res.end(JSON.stringify(prediction));
const {data, error} = await db.from("predictions").select().eq('id', req.query.id)

if (error) {
console.log("error retrieving prediction ", error, req.body);
return res.status(500).json({ error: error.message });
}

// If the prediction is not found, we are still waiting on the webhook
// so we just return success with an unknown status and id.
// TODO: We could store the initial prediction in the db on creation
// time but then we'd potentially be storing failed and partial
// predictions.
if (data.length === 0) {
return res.status(200).json({ id: req.query.id, status: "unknown" });
}

res.end(JSON.stringify(data[0]));
} else if (req.method === "PUT") {
const { data, error } = await db
.from("predictions")
Expand Down
2 changes: 1 addition & 1 deletion pages/api/predictions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async function handler(req, res) {

if (!WEBHOOK_HOST) {
throw new Error(
"WEBHOOK HOST is not set. If you're on local, make sure you set it to an ngrok url. If this doesn't exist, replicate predictions won't save to DB."
"WEBHOOK_HOST is not set. If you're on local, make sure you set NGROK_HOST. If this doesn't exist, replicate predictions won't save to DB."
);
}

Expand Down
8 changes: 4 additions & 4 deletions pages/api/submissions/[id].js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ export default async function handler(req, res) {
.eq("submission_id", req.query.id)
.order("created_at", { ascending: true });

data.forEach((prediction) => {
delete prediction.output;
});

if (error) {
console.log("error getting predictions for submission id ", error);
return res.status(500).json({ error: error.message });
}

data.forEach((prediction) => {
delete prediction.output;
});

res.end(JSON.stringify(data));
}
2 changes: 1 addition & 1 deletion pages/controlnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const supabase = createClient(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImVubndqaWl0bWlxd2RyZ3hrZXZtIiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODM5Mjc3OTgsImV4cCI6MTk5OTUwMzc5OH0.zCHzwchIjcmKNmccb9D4OLVwrWrpLHMmf4a8W7UedFs"
);

const supabaseUrl = "https://ennwjiitmiqwdrgxkevm.supabase.co";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_IMAGES_HOST;

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const fileTypes = ["JPG", "PNG"];
Expand Down
4 changes: 3 additions & 1 deletion pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,9 @@ export async function getServerSideProps({ req }) {
const response = await fetch(`${baseUrl}/api/submissions/${submissionId}`, {
method: "GET",
});
submissionPredictions = await response.json();
if (response.ok) {
submissionPredictions = await response.json();
}
}

return { props: { baseUrl, submissionPredictions } };
Expand Down
2 changes: 1 addition & 1 deletion pages/memories.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function History() {
const [anonId, setAnonId] = useState(null);

function getPredictionOutput(prediction) {
return `https://ennwjiitmiqwdrgxkevm.supabase.co/storage/v1/object/public/images/public/${prediction.id}.png`;
return `${process.env.NEXT_PUBLIC_SUPABASE_IMAGES_URL}/storage/v1/object/public/images/public/${prediction.id}.png`;
}

const clearHistory = () => {
Expand Down

1 comment on commit d4b1b5a

@vercel
Copy link

@vercel vercel bot commented on d4b1b5a Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.