Rayy
Rayy11mo ago

Is there a way to run mutations in bulk?

I am trying to create embeddings from chunk and then store those embedding in the convex vector store. But rather than calling one mutation for each embedding response, is there a way I can add them in bulk? I am trying to minimize addEmbedding calls.
export const generateEmbeddings = internalAction({
args: {...},
handler: async (ctx, args) => {
//Batching chunks

const responses = await Promise.all(
batches.map((batch) => fetchEmbedding(batch))
);

responses.forEach(async (response) => {
for (let i = 0; i < response.data.length; i++) {
const chunk =
typeof args.chunks[0] !== "string"
? (args.chunks[i] as Chunk)
: undefined;
await ctx.runMutation(internal.chatbook.addEmbedding, {
chatId: args.chatId,
content: chunk?.content ?? (args.chunks[i] as string),
source: chunk?.source ?? "",
embedding: response.data[i].embedding,
title: args.title,
type: args.type,
});
}
});
},
});

export const addEmbedding = internalMutation({
args: {
chatId: v.id("chatbook"),
content: v.string(),
source: v.optional(v.string()),
embedding: v.array(v.number()),
title: v.string(),
type: v.union(v.literal("code"), v.literal("doc"), v.literal("video")),
},
handler: async (ctx, args) => {
const chatEmbeddingId = await ctx.db.insert("chatEmbeddings", {
embedding: args.embedding,
content: args.content,
chatId: args.chatId,
source: args.source,
});
const existingChatDocument = await ctx.db.get(args.chatId);
const embeddingIds = existingChatDocument?.embeddingId || [];

embeddingIds.push(chatEmbeddingId);

await ctx.db.patch(args.chatId, {
embeddingId: embeddingIds,
title: args.title,
type: args.type,
});
},
});
export const generateEmbeddings = internalAction({
args: {...},
handler: async (ctx, args) => {
//Batching chunks

const responses = await Promise.all(
batches.map((batch) => fetchEmbedding(batch))
);

responses.forEach(async (response) => {
for (let i = 0; i < response.data.length; i++) {
const chunk =
typeof args.chunks[0] !== "string"
? (args.chunks[i] as Chunk)
: undefined;
await ctx.runMutation(internal.chatbook.addEmbedding, {
chatId: args.chatId,
content: chunk?.content ?? (args.chunks[i] as string),
source: chunk?.source ?? "",
embedding: response.data[i].embedding,
title: args.title,
type: args.type,
});
}
});
},
});

export const addEmbedding = internalMutation({
args: {
chatId: v.id("chatbook"),
content: v.string(),
source: v.optional(v.string()),
embedding: v.array(v.number()),
title: v.string(),
type: v.union(v.literal("code"), v.literal("doc"), v.literal("video")),
},
handler: async (ctx, args) => {
const chatEmbeddingId = await ctx.db.insert("chatEmbeddings", {
embedding: args.embedding,
content: args.content,
chatId: args.chatId,
source: args.source,
});
const existingChatDocument = await ctx.db.get(args.chatId);
const embeddingIds = existingChatDocument?.embeddingId || [];

embeddingIds.push(chatEmbeddingId);

await ctx.db.patch(args.chatId, {
embeddingId: embeddingIds,
title: args.title,
type: args.type,
});
},
});
2 Replies
ian
ian11mo ago
Just pass the array in and pass an array back- it’s all just code. Nothing requires you to only take one parameter. Maybe call it addEmbeddingBatch But don’t pass all at once- you should pass them in chunks, maybe start with 100 and see?
Rayy
RayyOP11mo ago
Ah yes, ofc. That was such a simple thing. Thank you so much. 🙂

Did you find this page helpful?