Study/src/services/settingsService.ts
Elijah 611a585757
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m4s
Initial addition of the Arcade study feature. Add connections as the first working game.
2026-07-13 17:35:18 -07:00

87 lines
4 KiB
TypeScript

import { prisma } from "@/lib/db";
import { ARCADE_SERVER_REGISTRY } from "@/lib/arcade/registry";
export type LlmInstructionType = "flashcards" | "quizzes" | "connections";
const DEFAULT_LLM_INSTRUCTIONS_FLASHCARDS = `You are generating study materials in a strict JSON format for import into a
personal study app. The overall output must be raw JSON with no wrapping
markdown code fence and no commentary before or after. Markdown formatting
INSIDE string values (lists, **bold**, tables) is fine, see the formatting
rule below.
For flashcards, use this shape:
{ "type": "flashcards", "deckName": "...", "description": "...", "cards": [{"front": "...", "back": "..."}] }
Rules:
- CRITICAL: Output MUST be valid JSON. EVERY string value must start and end with double quotes. Do NOT output unquoted strings. Example: "back": "your text here".
- Use Markdown formatting (bullet lists, **bold**, tables) inside "back"
text wherever it improves clarity. You MUST escape any newlines in the string as \\n. Do not use raw newlines.
- Base everything strictly on the material below. Do not add outside facts.
Material:
[paste your notes or lecture content here]`;
const DEFAULT_LLM_INSTRUCTIONS_QUIZZES = `You are generating study materials in a strict JSON format for import into a
personal study app. The overall output must be raw JSON with no wrapping
markdown code fence and no commentary before or after. Markdown formatting
INSIDE string values (lists, **bold**, tables) is fine, see the formatting
rule below.
For quizzes, use this shape:
{ "type": "quiz", "quizName": "...", "description": "...", "questions": [
{"type": "multiple_choice" | "sata", "prompt": "...", "category": "...",
"options": [{"text": "...", "correct": true|false}], "rationale": "..."}
]}
Rules:
- CRITICAL: Output MUST be perfectly valid JSON. EVERY string value (including rationale and prompt) MUST start and end with double quotes. Do NOT output unquoted strings. Example: "rationale": "your text here"
- "multiple_choice" questions must have exactly one option with correct: true.
- "sata" questions must have two or more options with correct: true.
- Every question needs a rationale explaining why the correct option(s) are
correct, and briefly why the others are not.
- Every question must include a "category" field: a short topic tag you
choose based on the content (e.g. "thyroid", "limbic system"). Reuse the
exact same label across questions on the same topic rather than inventing
a new variant each time, and keep the total number of distinct categories
small relative to the number of questions.
- Use Markdown formatting (bullet lists, **bold**, tables) inside
"rationale" text wherever it improves clarity. You MUST escape any newlines in the string as \\n. Do not use raw newlines.
- Base everything strictly on the material below. Do not add outside facts.
Material:
[paste your notes or lecture content here]`;
function instructionConfig(type: LlmInstructionType) {
if (type === "flashcards") return { key: "llmInstructionsFlashcards", value: DEFAULT_LLM_INSTRUCTIONS_FLASHCARDS };
if (type === "quizzes") return { key: "llmInstructionsQuizzes", value: DEFAULT_LLM_INSTRUCTIONS_QUIZZES };
return { key: "llmInstructionsConnections", value: ARCADE_SERVER_REGISTRY.connections.defaultInstructions };
}
export async function getLlmInstructions(type: LlmInstructionType): Promise<string> {
const { key, value: def } = instructionConfig(type);
const setting = await prisma.setting.findUnique({
where: { key },
});
return setting?.value ?? def;
}
export async function updateLlmInstructions(type: LlmInstructionType, value: string) {
const { key } = instructionConfig(type);
return prisma.setting.upsert({
where: { key },
update: { value },
create: { key, value },
});
}
export async function resetLlmInstructions(type: LlmInstructionType) {
const { key, value: def } = instructionConfig(type);
return prisma.setting.upsert({
where: { key },
update: { value: def },
create: { key, value: def },
});
}