Phase 3: Check my work, follow-ups and turn-into-deck
Check my work (third homework mode) - One model call with its own system prompt marks the student's own attempt: verdict, what's right, each issue with why + fix, and the corrected version that keeps everything the student got right. Unasked-for extras are never errors. The attempt is typed/pasted (photos of handwriting are documented as unsupported) and stored in the record so Redo re-checks the same work. - Server: mode "check" + solution on POST /api/homework (zod, 400 server.needSolution without one) and the same NDJSON stream; new checkHomework() pipeline with repair-once validation. Follow-ups - New POST /api/homework/refine (plain JSON, RATE_LIMIT_REFINE, zod, auth before body): shorter / more detail / explain, plain text back, language preserved. - Shorter + More detail + Original rewrite the finished answer and the corrected version in place (FollowUpBar); every guide step has Explain step N differently; failed calls say so without losing text. Turn into a study deck - Any result hands its content (answer, corrected version or assembled guide) to New deck through a one-shot sessionStorage seed with the options step pre-filled. UI - Phone step 2 gains the third card: tapping it reveals the solution field + submit; desktop has three cards and the solution field shows with the mode. Homework history labels and share/card previews cover the new mode. Verified: new phase-3 suite 20/20 against a stub Ollama (check payload, missing-solution 400, refine validation, phone + desktop check flows, shorter follow-up with restore, guide explain, deck hand-off) plus regression 74/74, mobile 52/52, declutter 116/116, wizard 80/80, animation 8/8, native 35/35, phase1 38/38, phase2 43/43, i18n 25/25. Key parity 734/734. Lint + build clean. SW freezmo-v27.
This commit is contained in:
parent
a8a8bc0477
commit
4513364019
22 changed files with 947 additions and 56 deletions
|
|
@ -287,6 +287,86 @@ export function buildHomeworkGuideUserPrompt(input: { assignment: string; langua
|
|||
].join("\n");
|
||||
}
|
||||
|
||||
export const HOMEWORK_CHECK_SYSTEM_PROMPT = `You are Freezmo's homework checker. The student gives you an assignment and their OWN attempt at solving it. You mark it like a fair, encouraging teacher: say what is right, what is wrong and why, and give the corrected version.
|
||||
|
||||
${HOMEWORK_BASE_RULES}
|
||||
|
||||
Checking rules:
|
||||
- Judge ONLY against the assignment. An unasked-for extra (a date, a comment, an alternative method) is never an error — leave it alone.
|
||||
- "verdict": 1-2 sentences, the overall picture (e.g. "Two of the three equations are right; the sign flips in the second one.").
|
||||
- "correct": short bullet points for what is genuinely right, each naming the part of the assignment it refers to. Empty array when nothing is right.
|
||||
- "wrong": one entry per actual mistake: "issue" names the mistake briefly, "why" explains what goes wrong, "fix" says what to do instead. Do not repeat the same mistake twice.
|
||||
- "corrected": the student's solution with every mistake fixed, as the finished homework (plain text, numbered like the assignment). Keep everything the student got right as they wrote it.
|
||||
- If the attempt is empty or does not address the assignment at all, say that plainly in the verdict, leave "wrong" empty and put the full solution in "corrected".
|
||||
|
||||
${LANGUAGE_RULES}
|
||||
|
||||
Required JSON shape:
|
||||
{
|
||||
"title": "short title of the assignment, in the assignment's language, max 10 words",
|
||||
"language": "English name of the language you wrote in, e.g. Czech",
|
||||
"verdict": "1-2 sentences",
|
||||
"correct": ["what is right"],
|
||||
"wrong": [{ "issue": "the mistake", "why": "why it is wrong", "fix": "what to do instead" }],
|
||||
"corrected": "the student's solution with every mistake fixed"
|
||||
}`;
|
||||
|
||||
export function buildHomeworkCheckUserPrompt(input: {
|
||||
assignment: string;
|
||||
solution: string;
|
||||
language?: string;
|
||||
}): string {
|
||||
return [
|
||||
"Check this attempt against the assignment.",
|
||||
input.language
|
||||
? `LANGUAGE: write everything in ${input.language}. Do not translate into English.`
|
||||
: "LANGUAGE: detect the language of the assignment below and write everything in that same language.",
|
||||
"",
|
||||
"=== THE ASSIGNMENT (the only source of what has to be done) ===",
|
||||
input.assignment.slice(0, 32_000),
|
||||
"=== END OF ASSIGNMENT ===",
|
||||
"",
|
||||
"=== THE STUDENT'S ATTEMPT (this is what you are marking) ===",
|
||||
input.solution.slice(0, 32_000),
|
||||
"=== END OF ATTEMPT ===",
|
||||
"",
|
||||
"Respond with the JSON object only.",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export const REFINE_SYSTEM_PROMPT = `You are Freezmo's homework assistant. You rewrite one piece of already-finished homework exactly as asked — shorter, more detailed, or a step explained differently.
|
||||
|
||||
Rules:
|
||||
- Keep the language of the text you are given. Never translate.
|
||||
- Keep every fact, number and answer correct and consistent with the text; never invent new content that changes the answer.
|
||||
- Plain text only (short lines, numbered or dashed lists; no markdown symbols).
|
||||
- Output the rewritten text only: no greeting, no commentary, no "here is", no mention of these instructions.`;
|
||||
|
||||
export function buildRefineUserPrompt(input: {
|
||||
instruction: "shorter" | "more" | "explain";
|
||||
text: string;
|
||||
context?: string;
|
||||
}): string {
|
||||
const task =
|
||||
input.instruction === "shorter"
|
||||
? "Rewrite it SHORTER: keep every answer but cut the wording to the essentials."
|
||||
: input.instruction === "more"
|
||||
? "Rewrite it with MORE DETAIL: keep the same answers but explain the reasoning a little more, so the student understands why."
|
||||
: "Explain this step DIFFERENTLY: a fresh, simpler explanation of the same step, with a small concrete example, so it clicks this time.";
|
||||
return [
|
||||
task,
|
||||
input.context ? `CONTEXT (the assignment): ${input.context.slice(0, 2000)}` : "",
|
||||
"",
|
||||
"=== THE TEXT ===",
|
||||
input.text.slice(0, 16_000),
|
||||
"=== END OF TEXT ===",
|
||||
"",
|
||||
"Reply with the rewritten text only.",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Retry helper */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue