Error I can't get
Any clue why I'm getting this error. It says it's coming from open api sdk, and I assume it's related to needing 'use node', but the strange thing everything was working fine without needing use node until I refactored the logic into an internalAction and scheduled it from a mutation
3 Replies
export const startRoughDraftMutation = mutation({
args: {
script: v.string(),
title: v.string(),
},
async handler(ctx, args) {
const userId = await auth.getUserId(ctx);
if (userId === null) {
throw new Error("User is not logged in");
}
const textSegments = await getSegments(args.script);
await consumeCreditsHelper(
ctx,
userId,
textSegments.length * CREDIT_COSTS.IMAGE_GENERATION,
);
const storyId = await ctx.db.insert("story", {
script: args.script,
userId: userId,
title: args.title,
});
await Promise.all(
textSegments.map(async (textSegment, idx) => {
const segmentId = await ctx.db.insert("segments", {
storyId,
text: textSegment,
order: idx,
});
await ctx.scheduler.runAfter(
0,
internal.segments.generateSegmentImageReplicateInternal,
{
segment: {
text: textSegment,
_id: segmentId,
},
},
);
}),
);
},
});
export const startRoughDraftMutation = mutation({
args: {
script: v.string(),
title: v.string(),
},
async handler(ctx, args) {
const userId = await auth.getUserId(ctx);
if (userId === null) {
throw new Error("User is not logged in");
}
const textSegments = await getSegments(args.script);
await consumeCreditsHelper(
ctx,
userId,
textSegments.length * CREDIT_COSTS.IMAGE_GENERATION,
);
const storyId = await ctx.db.insert("story", {
script: args.script,
userId: userId,
title: args.title,
});
await Promise.all(
textSegments.map(async (textSegment, idx) => {
const segmentId = await ctx.db.insert("segments", {
storyId,
text: textSegment,
order: idx,
});
await ctx.scheduler.runAfter(
0,
internal.segments.generateSegmentImageReplicateInternal,
{
segment: {
text: textSegment,
_id: segmentId,
},
},
);
}),
);
},
});
export const generateSegmentImageReplicateInternal = internalAction({
args: {
segment: v.object({
text: v.string(),
_id: v.id("segments"),
}),
},
async handler(ctx, args) {
const prompt = await openai.chat.completions
.create({
messages: [
{
role: "system",
content: `
You will be provided a segment from a story and you need to generate a descriptive set of keywords to be used in an stable diffusion image generation model. Please keep the most important details, obhects, and scenes near the front of your description. This should be for a scary story, so use words that help paint a scary or gloomy image.
`,
},
{
role: "user",
content: args.segment.text,
},
],
model: "gpt-4o-mini",
response_format: zodResponseFormat(
z.object({
prompt: z.string(),
}),
"prompt",
),
})
.then((completion) => {
const content = completion.choices[0].message.content as string;
return JSON.parse(content).prompt;
});
await ctx.scheduler.runAfter(
0,
internal.segments.regenerateSegmentImageUsingPrompt,
{
segmentId: args.segment._id,
prompt: `${prompt}, high quality`,
},
);
},
});
export const generateSegmentImageReplicateInternal = internalAction({
args: {
segment: v.object({
text: v.string(),
_id: v.id("segments"),
}),
},
async handler(ctx, args) {
const prompt = await openai.chat.completions
.create({
messages: [
{
role: "system",
content: `
You will be provided a segment from a story and you need to generate a descriptive set of keywords to be used in an stable diffusion image generation model. Please keep the most important details, obhects, and scenes near the front of your description. This should be for a scary story, so use words that help paint a scary or gloomy image.
`,
},
{
role: "user",
content: args.segment.text,
},
],
model: "gpt-4o-mini",
response_format: zodResponseFormat(
z.object({
prompt: z.string(),
}),
"prompt",
),
})
.then((completion) => {
const content = completion.choices[0].message.content as string;
return JSON.parse(content).prompt;
});
await ctx.scheduler.runAfter(
0,
internal.segments.regenerateSegmentImageUsingPrompt,
{
segmentId: args.segment._id,
prompt: `${prompt}, high quality`,
},
);
},
});
huh. The error message indicates that the mutation is calling openai directly. Is it possible that
getSegments
or consumeCreditsHelper
calls openai? The stacktrace says that the call is happening on line 71 of story.ts. What's on that line?export async function consumeCreditsHelper(
ctx: MutationCtx,
userId: Id<"users">,
amountToUse: number,
) {
const credits = await ctx.db
.query("credits")
.withIndex("userId_index", (q) => q.eq("userId", userId))
.first();
if (!credits) {
throw new ConvexError("No credits found");
}
if (credits.remaining < amountToUse) {
throw new ConvexError("Insufficient credits");
}
await ctx.db.patch(credits._id, {
remaining: credits.remaining - amountToUse,
});
}
export async function consumeCreditsHelper(
ctx: MutationCtx,
userId: Id<"users">,
amountToUse: number,
) {
const credits = await ctx.db
.query("credits")
.withIndex("userId_index", (q) => q.eq("userId", userId))
.first();
if (!credits) {
throw new ConvexError("No credits found");
}
if (credits.remaining < amountToUse) {
throw new ConvexError("Insufficient credits");
}
await ctx.db.patch(credits._id, {
remaining: credits.remaining - amountToUse,
});
}