|
import readline from "readline"; |
|
import minimist from "minimist"; |
|
|
|
|
|
import { MONGODB_URL } from "$env/static/private"; |
|
|
|
import { faker } from "@faker-js/faker"; |
|
import { ObjectId } from "mongodb"; |
|
|
|
import { collections } from "../src/lib/server/database.ts"; |
|
import { models } from "../src/lib/server/models.ts"; |
|
import type { User } from "../src/lib/types/User"; |
|
import type { Assistant } from "../src/lib/types/Assistant"; |
|
import type { Conversation } from "../src/lib/types/Conversation"; |
|
import type { Settings } from "../src/lib/types/Settings"; |
|
import { defaultEmbeddingModel } from "../src/lib/server/embeddingModels.ts"; |
|
import { Message } from "../src/lib/types/Message.ts"; |
|
|
|
import { addChildren } from "../src/lib/utils/tree/addChildren.ts"; |
|
|
|
const rl = readline.createInterface({ |
|
input: process.stdin, |
|
output: process.stdout, |
|
}); |
|
|
|
rl.on("close", function () { |
|
process.exit(0); |
|
}); |
|
|
|
const possibleFlags = ["reset", "all", "users", "settings", "assistants", "conversations"]; |
|
const argv = minimist(process.argv.slice(2)); |
|
const flags = argv["_"].filter((flag) => possibleFlags.includes(flag)); |
|
|
|
async function generateMessages(preprompt?: string): Promise<Message[]> { |
|
const isLinear = faker.datatype.boolean(0.5); |
|
const isInterrupted = faker.datatype.boolean(0.05); |
|
|
|
const messages: Message[] = []; |
|
|
|
messages.push({ |
|
id: crypto.randomUUID(), |
|
from: "system", |
|
content: preprompt ?? "", |
|
createdAt: faker.date.recent({ days: 30 }), |
|
updatedAt: faker.date.recent({ days: 30 }), |
|
}); |
|
|
|
let isUser = true; |
|
let lastId = messages[0].id; |
|
if (isLinear) { |
|
const convLength = faker.number.int({ min: 1, max: 25 }) * 2; |
|
|
|
for (let i = 0; i < convLength; i++) { |
|
lastId = addChildren( |
|
{ |
|
messages, |
|
rootMessageId: messages[0].id, |
|
}, |
|
{ |
|
from: isUser ? "user" : "assistant", |
|
content: faker.lorem.sentence({ |
|
min: 10, |
|
max: isUser ? 50 : 200, |
|
}), |
|
createdAt: faker.date.recent({ days: 30 }), |
|
updatedAt: faker.date.recent({ days: 30 }), |
|
interrupted: i === convLength - 1 && isInterrupted, |
|
}, |
|
lastId |
|
); |
|
isUser = !isUser; |
|
} |
|
} else { |
|
const convLength = faker.number.int({ min: 2, max: 200 }); |
|
|
|
for (let i = 0; i < convLength; i++) { |
|
addChildren( |
|
{ |
|
messages, |
|
rootMessageId: messages[0].id, |
|
}, |
|
{ |
|
from: isUser ? "user" : "assistant", |
|
content: faker.lorem.sentence({ |
|
min: 10, |
|
max: isUser ? 50 : 200, |
|
}), |
|
createdAt: faker.date.recent({ days: 30 }), |
|
updatedAt: faker.date.recent({ days: 30 }), |
|
interrupted: i === convLength - 1 && isInterrupted, |
|
}, |
|
faker.helpers.arrayElement([ |
|
messages[0].id, |
|
...messages.filter((m) => m.from === (isUser ? "assistant" : "user")).map((m) => m.id), |
|
]) |
|
); |
|
|
|
isUser = !isUser; |
|
} |
|
} |
|
return messages; |
|
} |
|
|
|
async function seed() { |
|
console.log("Seeding..."); |
|
const modelIds = models.map((model) => model.id); |
|
|
|
if (flags.includes("reset")) { |
|
console.log("Starting reset of DB"); |
|
await collections.users.deleteMany({}); |
|
await collections.settings.deleteMany({}); |
|
await collections.assistants.deleteMany({}); |
|
await collections.conversations.deleteMany({}); |
|
console.log("Reset done"); |
|
} |
|
|
|
if (flags.includes("users") || flags.includes("all")) { |
|
console.log("Creating 100 new users"); |
|
const newUsers: User[] = Array.from({ length: 100 }, () => ({ |
|
_id: new ObjectId(), |
|
createdAt: faker.date.recent({ days: 30 }), |
|
updatedAt: faker.date.recent({ days: 30 }), |
|
username: faker.internet.userName(), |
|
name: faker.person.fullName(), |
|
hfUserId: faker.string.alphanumeric(24), |
|
avatarUrl: faker.image.avatar(), |
|
})); |
|
|
|
await collections.users.insertMany(newUsers); |
|
console.log("Done creating users."); |
|
} |
|
|
|
const users = await collections.users.find().toArray(); |
|
if (flags.includes("settings") || flags.includes("all")) { |
|
console.log("Updating settings for all users"); |
|
users.forEach(async (user) => { |
|
const settings: Settings = { |
|
userId: user._id, |
|
shareConversationsWithModelAuthors: faker.datatype.boolean(0.25), |
|
hideEmojiOnSidebar: faker.datatype.boolean(0.25), |
|
ethicsModalAcceptedAt: faker.date.recent({ days: 30 }), |
|
activeModel: faker.helpers.arrayElement(modelIds), |
|
createdAt: faker.date.recent({ days: 30 }), |
|
updatedAt: faker.date.recent({ days: 30 }), |
|
customPrompts: {}, |
|
assistants: [], |
|
}; |
|
await collections.settings.updateOne( |
|
{ userId: user._id }, |
|
{ $set: { ...settings } }, |
|
{ upsert: true } |
|
); |
|
}); |
|
console.log("Done updating settings."); |
|
} |
|
|
|
if (flags.includes("assistants") || flags.includes("all")) { |
|
console.log("Creating assistants for all users"); |
|
await Promise.all( |
|
users.map(async (user) => { |
|
const assistants = faker.helpers.multiple<Assistant>( |
|
() => ({ |
|
_id: new ObjectId(), |
|
name: faker.animal.insect(), |
|
createdById: user._id, |
|
createdByName: user.username, |
|
createdAt: faker.date.recent({ days: 30 }), |
|
updatedAt: faker.date.recent({ days: 30 }), |
|
userCount: faker.number.int({ min: 1, max: 100000 }), |
|
featured: faker.datatype.boolean(0.25), |
|
modelId: faker.helpers.arrayElement(modelIds), |
|
description: faker.lorem.sentence(), |
|
preprompt: faker.hacker.phrase(), |
|
exampleInputs: faker.helpers.multiple(() => faker.lorem.sentence(), { |
|
count: faker.number.int({ min: 0, max: 4 }), |
|
}), |
|
}), |
|
{ count: faker.number.int({ min: 3, max: 10 }) } |
|
); |
|
await collections.assistants.insertMany(assistants); |
|
await collections.settings.updateOne( |
|
{ userId: user._id }, |
|
{ $set: { assistants: assistants.map((a) => a._id.toString()) } }, |
|
{ upsert: true } |
|
); |
|
}) |
|
); |
|
console.log("Done creating assistants."); |
|
} |
|
|
|
if (flags.includes("conversations") || flags.includes("all")) { |
|
console.log("Creating conversations for all users"); |
|
await Promise.all( |
|
users.map(async (user) => { |
|
const conversations = faker.helpers.multiple( |
|
async () => { |
|
const settings = await collections.settings.findOne<Settings>({ userId: user._id }); |
|
|
|
const assistantId = |
|
settings?.assistants && settings.assistants.length > 0 && faker.datatype.boolean(0.1) |
|
? faker.helpers.arrayElement<ObjectId>(settings.assistants) |
|
: undefined; |
|
|
|
const preprompt = |
|
(assistantId |
|
? await collections.assistants |
|
.findOne({ _id: assistantId }) |
|
.then((assistant: Assistant) => assistant?.preprompt ?? "") |
|
: faker.helpers.maybe(() => faker.hacker.phrase(), { probability: 0.5 })) ?? ""; |
|
|
|
const messages = await generateMessages(preprompt); |
|
|
|
const conv = { |
|
_id: new ObjectId(), |
|
userId: user._id, |
|
assistantId, |
|
preprompt, |
|
createdAt: faker.date.recent({ days: 145 }), |
|
updatedAt: faker.date.recent({ days: 145 }), |
|
model: faker.helpers.arrayElement(modelIds), |
|
title: faker.internet.emoji() + " " + faker.hacker.phrase(), |
|
embeddingModel: defaultEmbeddingModel.id, |
|
messages, |
|
rootMessageId: messages[0].id, |
|
} satisfies Conversation; |
|
|
|
return conv; |
|
}, |
|
{ count: faker.number.int({ min: 10, max: 200 }) } |
|
); |
|
|
|
await collections.conversations.insertMany(await Promise.all(conversations)); |
|
}) |
|
); |
|
console.log("Done creating conversations."); |
|
} |
|
} |
|
|
|
|
|
(async () => { |
|
try { |
|
rl.question( |
|
"You're about to run a seeding script on the following MONGODB_URL: \x1b[31m" + |
|
MONGODB_URL + |
|
"\x1b[0m\n\n With the following flags: \x1b[31m" + |
|
flags.join("\x1b[0m , \x1b[31m") + |
|
"\x1b[0m\n \n\n Are you sure you want to continue? (yes/no): ", |
|
async (confirm) => { |
|
if (confirm !== "yes") { |
|
console.log("Not 'yes', exiting."); |
|
rl.close(); |
|
process.exit(0); |
|
} |
|
console.log("Starting seeding..."); |
|
await seed(); |
|
console.log("Seeding done."); |
|
rl.close(); |
|
} |
|
); |
|
} catch (e) { |
|
console.error(e); |
|
process.exit(1); |
|
} |
|
})(); |
|
|