๐Ÿ“ฆ GitSquared / wikiweaver

๐Ÿ“„ weave.ts ยท 102 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102import { DEFAULT_MODEL } from '@/ai';
import type { Universe } from '@/db/schema/universe';
import { generateObject, generateText } from 'ai';
import z from 'zod';
import { searchArticles } from './search';

export async function weaveUniverseName({
	prompt,
}: { prompt: string }): Promise<string> {
	const {
		object: { universeName },
	} = await generateObject({
		model: DEFAULT_MODEL,
		schema: z.object({
			universeName: z.string().min(4).max(50),
		}),
		prompt: `Generate a name for a universe based on the following prompt: "${prompt}". The name should not be more than 50 characters long, and should be unique, memorable, and fitting for a fictional universe. Avoid using common words or phrases.`,
	});

	return universeName;
}

export async function weaveFirstArticleTitle({
	universe,
}: {
	universe: Universe;
}): Promise<string> {
	const {
		object: { title },
	} = await generateObject({
		model: DEFAULT_MODEL,
		schema: z.object({
			title: z.string().min(4).max(50),
		}),
		prompt: `Generate a title for an article of a wiki within the universe "${universe.name}" based on its themes and lore. Here is a brief description of this universe: "${universe.prompt}". Invent any concept, event, place, object, character or so on that could warrant an encyclopedia article within that universe, and return the article's title. The title should be concise and fitting of a fictional encyclopedia, and in-lore. It should not be more than 50 characters long.`,
	});

	return title;
}

export async function weaveWikiArticle({
	universe,
	title,
}: {
	universe: Universe;
	title: string;
}): Promise<{
	text: string;
}> {
	const references = await searchArticles(universe.id, title).then((results) =>
		// max 10
		results.slice(0, 10),
	);

	const prompt = `You're writing an encyclopedia from a fictional universe. This universe is called "${universe.name}", and here is some information about it:
	
	"${universe.prompt}"

	Now, write a detailed article about "${title}" as if it were a real historical event, place, object, cultural phenomenon or concept in that world.

- Maintain a formal, Wikipedia-like tone.
- Feel free to fabricate locations, names, timelines, and organizations.
- Within the article content, wrap these invented names using double brackets like [[Name]]. These will be automatically turned into links.
- Invent at least 5 such references, but no more than 30.
- Keep the article in-universe and consistent with its lore.
- Do not mention the fictional universe's name or description directly.
- Use markdown formatting for headings, lists, and emphasis.
- Print the title of the article without any alteration.
- Write an article of at least 500 words.
- Keep internal logic and continuity consistent.
- Avoid real-world facts unless twisted into the fiction.

${
	references.length > 0
		? `Here's what's already been written about "${title}" in this universe:

${references
	.map(
		(result) => `In an article titled "${result.article.title}":
		${result.paragraphs.map((p) => `- ${p.text}`).join('\n')}`,
	)
	.join('\n\n')}

Make sure to keep your new article coherent and consistent with this existing information.
`
		: ''
}

Begin the article now:`;

	console.debug(prompt);

	const { text } = await generateText({
		model: DEFAULT_MODEL,
		prompt,
	});

	return {
		text,
	};
}