2023-04-12 09:08:06 -04:00
|
|
|
import * as dotenv from "dotenv";
|
|
|
|
import { Configuration, OpenAIApi } from "openai";
|
2023-04-12 09:36:43 -04:00
|
|
|
import PlotGenerator from "@xeserv/plottoriffic";
|
2023-04-12 16:02:41 -04:00
|
|
|
import { generateName } from "@kotofurumiya/th-namegen";
|
|
|
|
import * as fs from "node:fs/promises";
|
2023-04-12 09:08:06 -04:00
|
|
|
|
|
|
|
dotenv.config();
|
|
|
|
|
2023-04-12 16:02:41 -04:00
|
|
|
const dirName = `var/${generateName()}`;
|
|
|
|
await fs.mkdir(dirName, { recursive: true });
|
|
|
|
console.log(`dirName: ${dirName}`);
|
|
|
|
|
|
|
|
const pg = new PlotGenerator({ flipGenders: false });
|
2023-04-12 09:36:43 -04:00
|
|
|
const plot = pg.generate();
|
|
|
|
|
2023-04-12 16:02:41 -04:00
|
|
|
await fs.writeFile(`${dirName}/plotto.json`, JSON.stringify(plot));
|
|
|
|
|
2023-04-12 09:08:06 -04:00
|
|
|
const configuration = new Configuration({
|
|
|
|
apiKey: process.env.OPENAI_API_KEY,
|
|
|
|
});
|
|
|
|
const openai = new OpenAIApi(configuration);
|
|
|
|
|
2023-04-12 16:02:41 -04:00
|
|
|
const promptBase = `Write me the following about the following plot summary for a novel:
|
|
|
|
|
2023-04-12 17:37:46 -04:00
|
|
|
- A two to five word title for the novel starting with "Title: " and followed by two newlines. For example: "Fresh Beginnings" or "Jared's Adventure through Crime".
|
|
|
|
- A detailed plot summary for the story starting with "Plot Summary: " and followed by two newlines. The plot summary should be on the same line as the prefix.
|
2023-04-12 16:02:41 -04:00
|
|
|
- The string "Chapter Summaries" followed by two newlines.
|
2023-04-12 17:37:46 -04:00
|
|
|
- A markdown list of detailed chapter summaries in at least 3 sentences and titles for each of the 10 chapters that a novel based on the plot summary would have. Surround each chapter title in quotes and put a dash after the name like this:
|
|
|
|
|
|
|
|
- Chapter name - Chapter summary goes here. More words in the summary go here.
|
|
|
|
- Second chapter name - Second chapter summary goes here.`;
|
2023-04-12 16:02:41 -04:00
|
|
|
|
|
|
|
const summary = await openai.createChatCompletion({
|
2023-04-12 09:08:06 -04:00
|
|
|
model: "gpt-3.5-turbo",
|
2023-04-12 09:36:43 -04:00
|
|
|
messages: [
|
|
|
|
{
|
|
|
|
role: "user",
|
2023-04-12 16:02:41 -04:00
|
|
|
content: promptBase + "\n\n" + plot.plot,
|
2023-04-12 09:36:43 -04:00
|
|
|
},
|
|
|
|
],
|
2023-04-12 09:08:06 -04:00
|
|
|
});
|
2023-04-12 16:02:41 -04:00
|
|
|
|
|
|
|
if (!!summary.data.usage) {
|
|
|
|
const usage = summary.data.usage;
|
|
|
|
console.log(
|
|
|
|
`${usage.total_tokens} tokens (${usage.prompt_tokens} prompt, ${usage?.completion_tokens} completion)`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-04-12 17:37:46 -04:00
|
|
|
const summaryText = summary.data.choices[0].message?.content;
|
|
|
|
|
|
|
|
console.log(summaryText);
|
|
|
|
await fs.writeFile(`${dirName}/summary.txt`, summaryText as string);
|
|
|
|
|
|
|
|
const titleRegex = /^Title: (.+)$/gm;
|
|
|
|
const plotSummaryRegex = /^Plot Summary: (.+)$/gm;
|
|
|
|
const chapterSummaryRegex = /^- (.+) - (.+)$/gm;
|
|
|
|
|
|
|
|
let title = summaryText?.split("\n", 2)[0].split(titleRegex)[1] as string;
|
|
|
|
|
|
|
|
if (title[0] === '"') {
|
|
|
|
title = title.slice(1, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const chapterList = summaryText
|
|
|
|
?.split("\n\n")
|
|
|
|
.slice(-1)[0]
|
|
|
|
.split("\n")
|
|
|
|
.map((line) => {
|
|
|
|
return line.split(chapterSummaryRegex);
|
|
|
|
})
|
|
|
|
.map((ch) => {
|
|
|
|
ch.shift();
|
|
|
|
ch.pop();
|
|
|
|
return { title: ch[0].slice(1, -1), summary: ch[1] };
|
|
|
|
});
|
|
|
|
|
|
|
|
const plotSummary = summaryText?.split("\n\n", 3)[1].split(plotSummaryRegex)[1];
|
|
|
|
|
|
|
|
plot.cast.forEach(async (ch) => {});
|
|
|
|
|
|
|
|
const bookInfo = {
|
|
|
|
title,
|
|
|
|
chapterList,
|
|
|
|
plotSummary,
|
|
|
|
};
|
|
|
|
|
|
|
|
console.log(bookInfo);
|
|
|
|
await fs.writeFile(`${dirName}/summary.json`, JSON.stringify(bookInfo));
|