From 3edda3af3516703a4bb8bbd280aa715691dc6c2b Mon Sep 17 00:00:00 2001 From: = Date: Fri, 4 Oct 2024 14:32:08 +0100 Subject: [PATCH 1/3] quiz fixed and other refactors --- app/api/chat/route.ts | 29 +++++++++---------- .../chat/chat-hooks/use-chat-handler.tsx | 3 +- components/utility/global-state.tsx | 21 ++++++++++++++ components/workspace/workspace-settings.tsx | 2 +- lib/server/hinting-handler.ts | 11 +------ lib/server/recall-attempt-handler.ts | 26 +++++++++-------- lib/server/topic-generation-handler.ts | 25 ++++++++++------ 7 files changed, 68 insertions(+), 49 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 1076ce4..a040aa0 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,7 +1,4 @@ -import { StudyState } from "@/lib/studyStates" -import { updateTopicOnRecall } from "@/lib/server/server-chat-helpers" import { LanguageModel } from "ai" -import { formatDistanceToNow } from "date-fns/esm" import { openai } from "./registry" import { handleTopicGeneration } from "@/lib/server/topic-generation-handler" import { handleRecallAttempt } from "@/lib/server/recall-attempt-handler" @@ -24,22 +21,24 @@ export async function POST(request: Request) { studySheet, chatRecallMetadata, randomRecallFact, - profile_context + profile_context, + workspaceInstructions } = json const studentMessage = messages[messages.length - 1] - const studentContext = + const systemContext = [ profile_context.length > 0 ? `Here is how the student would like you to respond: """${profile_context}"""` + : "", + workspaceInstructions.length > 0 + ? `Here are the workspace instructions: + """${workspaceInstructions}"""` : "" - const mentor_system_message = `You are helpful, friendly study mentor. - ${studentContext} - IMPORTANT: When generating Corrections do not provide answers (additions) to ommited or forgotten facts. - When generating Hints for Forgotten facts, provide hints and clues without giving away answers.` - - const finalFeedback = `Finally, ask the student if they wish to revisit the topic's source material to enhance understanding or clarify any uncertainties.` + ] + .filter(Boolean) + .join("\n\n") const defaultModel = openai("gpt-4o-mini") as LanguageModel const scoringModel = defaultModel @@ -61,13 +60,11 @@ export async function POST(request: Request) { return await handleRecallAttempt( scoringModel, defaultModel, - messages, studyState, studySheet, chatId, studentMessage, - mentor_system_message, - finalFeedback + studentContext ) case "recall_tutorial_hinting": @@ -77,8 +74,7 @@ export async function POST(request: Request) { messages, studyState, studySheet, - chatRecallMetadata, - studentMessage + chatRecallMetadata ) case "recall_finished": @@ -94,6 +90,7 @@ export async function POST(request: Request) { ) case "quick_quiz_answer": + case "quick_quiz_user_answer": case "quick_quiz_finished": return await handleQuickQuizAnswer( defaultModel, diff --git a/components/chat/chat-hooks/use-chat-handler.tsx b/components/chat/chat-hooks/use-chat-handler.tsx index 7d49f4b..6308606 100644 --- a/components/chat/chat-hooks/use-chat-handler.tsx +++ b/components/chat/chat-hooks/use-chat-handler.tsx @@ -73,7 +73,8 @@ export const useChatHandler = () => { studySheet, chatRecallMetadata, randomRecallFact, - profile_context: profile?.profile_context || "" + profile_context: profile?.profile_context || "", + workspaceInstructions: selectedWorkspace?.instructions || "" } } diff --git a/components/utility/global-state.tsx b/components/utility/global-state.tsx index aafb845..f53d4bd 100644 --- a/components/utility/global-state.tsx +++ b/components/utility/global-state.tsx @@ -13,6 +13,8 @@ import { WorkspaceImage } from "@/types" import { useChat } from "ai/react" import { useRouter } from "next/navigation" import { FC, useEffect, useState } from "react" +import { getChatById } from "@/db/chats" +import { toast } from "sonner" interface GlobalStateProps { children: React.ReactNode @@ -60,6 +62,22 @@ export const GlobalState: FC = ({ children }) => { dueDateFromNow: dueDateFromNow! }) } + + const isQuickQuiz: boolean = chatStudyState.startsWith("quick_quiz") + + if (!isQuickQuiz) { + const updatedChat = await getChatById(selectedChat!.id) + + if (updatedChat) { + setChats(prevChats => { + const updatedChats = prevChats.map(prevChat => + prevChat.id === updatedChat.id ? updatedChat : prevChat + ) + + return updatedChats + }) + } + } } const { @@ -76,6 +94,9 @@ export const GlobalState: FC = ({ children }) => { keepLastMessageOnError: true, onResponse: response => { handleResponse(response) + }, + onError: error => { + toast.error(error.message) } }) diff --git a/components/workspace/workspace-settings.tsx b/components/workspace/workspace-settings.tsx index b9b209a..41decb7 100644 --- a/components/workspace/workspace-settings.tsx +++ b/components/workspace/workspace-settings.tsx @@ -206,7 +206,7 @@ export const WorkspaceSettings: FC = ({}) => {
${studySheet}. - Reinforce correct information with additional context or interesting facts. - Example: "You got the first part right; indeed, Venus has a day that is longer than its year due to its incredibly slow rotation." - Address Incorrect Answers: diff --git a/lib/server/recall-attempt-handler.ts b/lib/server/recall-attempt-handler.ts index c6c3a6b..9e7baac 100644 --- a/lib/server/recall-attempt-handler.ts +++ b/lib/server/recall-attempt-handler.ts @@ -11,26 +11,17 @@ import { formatDistanceToNow } from "date-fns/esm" export async function handleRecallAttempt( scoringModel: LanguageModel, defaultModel: LanguageModel, - messages: any[], studyState: StudyState, studySheet: string, chatId: string, studentMessage: any, - mentor_system_message: string, - finalFeedback: string + studentContext: string ) { let date_from_now = "" let recallScore = 0 let forgottenOrIncorrectFacts: string[] = [] - let content = ` - -${studySheet} - - -${studentMessage.content} - - ` + const finalFeedback = `Finally, ask the student if they wish to revisit the topic's source material to enhance understanding or clarify any uncertainties.` const { text } = await generateText({ model: scoringModel, @@ -42,7 +33,13 @@ ${studentMessage.content} }, { role: "user", - content + content: ` + +${studySheet} + + +${studentMessage.content} +` } ]) }) @@ -74,6 +71,11 @@ ${studentMessage.content} let chatStreamResponse let newStudyState: StudyState + const mentor_system_message = `You are helpful, friendly study mentor. + ${studentContext} + IMPORTANT: When generating Corrections do not provide answers (additions) to ommited or forgotten facts. + When generating Hints for Forgotten facts, provide hints and clues without giving away answers.` + if (allRecalled) { newStudyState = studyState === "recall_tutorial_first_attempt" diff --git a/lib/server/topic-generation-handler.ts b/lib/server/topic-generation-handler.ts index 47461d8..153df4a 100644 --- a/lib/server/topic-generation-handler.ts +++ b/lib/server/topic-generation-handler.ts @@ -13,16 +13,23 @@ export async function handleTopicGeneration( messages: convertToCoreMessages([ { role: "system", - content: `Objective: Create a detailed study sheet for a specified topic. The study sheet should be concise, informative, and well-organized to facilitate quick learning and retention. Important: generate the study sheet text only. Do not generate additional text like summary, notes or additional text not in study sheet text. - Instructions: - Introduction to the Topic: - Provide a brief overview of the topic, including its significance and general context. - Key Components or Concepts: - List the key facts or components related to the topic. Each fact should be succinct and supported by one or two important details to aid understanding. + content: `Objective: Create a detailed study sheet for a specified topic. +The study sheet should be concise, informative, and well-organized to facilitate quick learning and retention. +Important: if the user has provided source material, use it to generate the study sheet. Do not ignore the source material or expand on it. +Important: generate the study sheet text only. Do not generate additional text like summary, notes or additional text not in study sheet text. - Formatting Instructions: - Ensure the study sheet is clear and easy to read. Use bullet points for lists, bold headings for sections, and provide ample spacing for clarity. - Do not generate additional text like summary, notes or additional text not in study sheet text.${studentContext}` +Instructions: + Introduction to the Topic: + Provide a brief overview of the topic, including its significance and general context. + Key Components or Concepts: + List the key facts or components related to the topic. Each fact should be succinct and supported by one or two important details to aid understanding. + +Formatting Instructions: + Ensure the study sheet is clear and easy to read. Use bullet points for lists, bold headings for sections, and provide ample spacing for clarity. + Do not generate additional text like summary, notes or additional text not in study sheet text. + +${studentContext} +` }, ...messages ]) From d6055154c7341e62c55a1998ebd20a6c07d1c3d0 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 4 Oct 2024 14:40:12 +0100 Subject: [PATCH 2/3] new systemContext --- app/api/chat/route.ts | 26 +++++-------------- .../chat/chat-hooks/use-chat-handler.tsx | 16 ++++++++++-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index a040aa0..5f62bd1 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -21,25 +21,11 @@ export async function POST(request: Request) { studySheet, chatRecallMetadata, randomRecallFact, - profile_context, - workspaceInstructions + systemContext } = json const studentMessage = messages[messages.length - 1] - const systemContext = [ - profile_context.length > 0 - ? `Here is how the student would like you to respond: - """${profile_context}"""` - : "", - workspaceInstructions.length > 0 - ? `Here are the workspace instructions: - """${workspaceInstructions}"""` - : "" - ] - .filter(Boolean) - .join("\n\n") - const defaultModel = openai("gpt-4o-mini") as LanguageModel const scoringModel = defaultModel const hintingModel = defaultModel @@ -52,7 +38,7 @@ export async function POST(request: Request) { return await handleTopicGeneration( defaultModel, messages, - studentContext + systemContext ) case "recall_tutorial_first_attempt": @@ -64,7 +50,7 @@ export async function POST(request: Request) { studySheet, chatId, studentMessage, - studentContext + systemContext ) case "recall_tutorial_hinting": @@ -79,14 +65,14 @@ export async function POST(request: Request) { case "recall_finished": case "reviewing": - return await handleReview(defaultModel, messages, studentContext) + return await handleReview(defaultModel, messages, systemContext) case "quick_quiz_question": return await handleQuickQuizQuestion( defaultModel, studySheet, randomRecallFact, - studentContext + systemContext ) case "quick_quiz_answer": @@ -98,7 +84,7 @@ export async function POST(request: Request) { studyState, studySheet, studentMessage, - studentContext + systemContext ) default: diff --git a/components/chat/chat-hooks/use-chat-handler.tsx b/components/chat/chat-hooks/use-chat-handler.tsx index 6308606..5bdfb2e 100644 --- a/components/chat/chat-hooks/use-chat-handler.tsx +++ b/components/chat/chat-hooks/use-chat-handler.tsx @@ -67,14 +67,26 @@ export const useChatHandler = () => { setChatStudyState(studyState) } + const systemContext = ` + +${profile?.profile_context || ""} + + +${selectedWorkspace?.name || ""} + + +${selectedWorkspace?.instructions || ""} + + +`.trim() + return { chatId: currentChat?.id, studyState, studySheet, chatRecallMetadata, randomRecallFact, - profile_context: profile?.profile_context || "", - workspaceInstructions: selectedWorkspace?.instructions || "" + systemContext } } From b4054dd3425b9a5736d74601834864c3e19af882 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 4 Oct 2024 15:11:21 +0100 Subject: [PATCH 3/3] context working --- app/api/chat/route.ts | 3 ++- .../chat/chat-hooks/use-chat-handler.tsx | 9 +++------ lib/server/hinting-handler.ts | 14 ++++++++------ lib/server/quick-quiz-answer-handler.ts | 12 ++++++++---- lib/server/quick-quiz-question-handler.ts | 18 ++++++++++-------- lib/server/recall-attempt-handler.ts | 4 ++-- lib/server/server-chat-helpers.ts | 6 +++--- lib/server/topic-generation-handler.ts | 4 ++-- 8 files changed, 38 insertions(+), 32 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 5f62bd1..9776eb9 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -60,7 +60,8 @@ export async function POST(request: Request) { messages, studyState, studySheet, - chatRecallMetadata + chatRecallMetadata, + systemContext ) case "recall_finished": diff --git a/components/chat/chat-hooks/use-chat-handler.tsx b/components/chat/chat-hooks/use-chat-handler.tsx index 5bdfb2e..f665f54 100644 --- a/components/chat/chat-hooks/use-chat-handler.tsx +++ b/components/chat/chat-hooks/use-chat-handler.tsx @@ -68,17 +68,14 @@ export const useChatHandler = () => { } const systemContext = ` - +User Info: ${profile?.profile_context || ""} - -${selectedWorkspace?.name || ""} - +System Instructions for module ${selectedWorkspace?.name || ""}: ${selectedWorkspace?.instructions || ""} - -`.trim() +` return { chatId: currentChat?.id, diff --git a/lib/server/hinting-handler.ts b/lib/server/hinting-handler.ts index 0572080..803b799 100644 --- a/lib/server/hinting-handler.ts +++ b/lib/server/hinting-handler.ts @@ -6,7 +6,8 @@ export async function handleHinting( messages: any[], studyState: StudyState, studySheet: string, - chatRecallMetadata: any + chatRecallMetadata: any, + systemContext: string ) { const chatStreamResponse = await streamText({ model: hintingModel, @@ -14,13 +15,14 @@ export async function handleHinting( messages: convertToCoreMessages([ { role: "system", - content: `When constructing feedback for a student's attempt at answering hints on a recall test, follow these guidelines: + content: `${systemContext} +When constructing feedback for a student's attempt at answering hints on a recall test, follow these guidelines: - Positive Reinforcement: +Positive Reinforcement: - Begin with an encouraging statement that acknowledges the student's effort. - Use positive language and emojis to create a friendly tone. - Example: "Great effort! 🌟" +Begin with an encouraging statement that acknowledges the student's effort. +Use positive language and emojis to create a friendly tone. +Example: "Great effort! 🌟" Highlight Correct Answers: diff --git a/lib/server/quick-quiz-answer-handler.ts b/lib/server/quick-quiz-answer-handler.ts index 0b349c1..8748223 100644 --- a/lib/server/quick-quiz-answer-handler.ts +++ b/lib/server/quick-quiz-answer-handler.ts @@ -7,7 +7,7 @@ export async function handleQuickQuizAnswer( studyState: StudyState, studySheet: string, studentMessage: any, - studentContext: string + systemContext: string ) { const noMoreQuizQuestions = studyState === "quick_quiz_finished" const previousQuizQuestion = messages[messages.length - 2].content @@ -15,15 +15,19 @@ export async function handleQuickQuizAnswer( ? "Finally advise the student there are no more quiz questions available. Come back again another time." : "" - const quickQuizSystemMessage = `You are helpful, friendly quiz master. Generate short answer quiz questions based on a provided fact. Never give the answer to the question when generating the question text. Do not state which step of the instructions you are on.${studentContext}` - const chatStreamResponse = await streamText({ model: defaultModel, temperature: 0.3, messages: convertToCoreMessages([ { role: "system", - content: `${quickQuizSystemMessage}. Always provide the answer when giving feedback to the student. If the student answers "I don't know.", just give the answer.` + content: `You are helpful, friendly quiz master. +Generate short answer quiz questions based on a provided fact. +Never give the answer to the question when generating the question text. +Do not state which step of the instructions you are on. +Always provide the answer when giving feedback to the student. +If the student answers "I don't know.", just give the answer. +${systemContext}` }, { role: "user", diff --git a/lib/server/quick-quiz-question-handler.ts b/lib/server/quick-quiz-question-handler.ts index fae9c6c..10b65f8 100644 --- a/lib/server/quick-quiz-question-handler.ts +++ b/lib/server/quick-quiz-question-handler.ts @@ -5,25 +5,27 @@ export async function handleQuickQuizQuestion( defaultModel: LanguageModel, studySheet: string, randomRecallFact: string, - studentContext: string + systemContext: string ) { - const quickQuizSystemMessage = `You are helpful, friendly quiz master. Generate short answer quiz questions based on a provided fact. Never give the answer to the question when generating the question text. Do not state which step of the instructions you are on.${studentContext}` - const chatStreamResponse = await streamText({ model: defaultModel, temperature: 0.3, messages: convertToCoreMessages([ { role: "system", - content: quickQuizSystemMessage + content: `You are helpful, friendly quiz master. +Generate short answer quiz questions based on a provided fact. +Never give the answer to the question when generating the question text. +Do not state which step of the instructions you are on. +${systemContext}` }, { role: "user", content: `Given this topic study sheet as context: - """${studySheet}""" - Generate a short answer quiz question based on the following fact the student previously got incorrect: - """${randomRecallFact}""" - Important: Do not provide the answer when generating the question or mention the fact used to generate quiz question.` +${studySheet} +Generate a short answer quiz question based on the following fact the student previously got incorrect: +${randomRecallFact} +Important: Do not provide the answer when generating the question or mention the fact used to generate quiz question.` } ]) }) diff --git a/lib/server/recall-attempt-handler.ts b/lib/server/recall-attempt-handler.ts index 9e7baac..8779270 100644 --- a/lib/server/recall-attempt-handler.ts +++ b/lib/server/recall-attempt-handler.ts @@ -15,7 +15,7 @@ export async function handleRecallAttempt( studySheet: string, chatId: string, studentMessage: any, - studentContext: string + systemContext: string ) { let date_from_now = "" let recallScore = 0 @@ -72,7 +72,7 @@ ${studentMessage.content} let newStudyState: StudyState const mentor_system_message = `You are helpful, friendly study mentor. - ${studentContext} + ${systemContext} IMPORTANT: When generating Corrections do not provide answers (additions) to ommited or forgotten facts. When generating Hints for Forgotten facts, provide hints and clues without giving away answers.` diff --git a/lib/server/server-chat-helpers.ts b/lib/server/server-chat-helpers.ts index e0a5015..e105c01 100644 --- a/lib/server/server-chat-helpers.ts +++ b/lib/server/server-chat-helpers.ts @@ -135,11 +135,11 @@ export async function updateTopicOnRecall( // map test_result to a rating let rating: Rating - if (test_result < 50) { + if (test_result < 40) { rating = Rating.Again - } else if (test_result < 75) { + } else if (test_result < 65) { rating = Rating.Hard - } else if (test_result < 90) { + } else if (test_result < 85) { rating = Rating.Good } else { rating = Rating.Easy diff --git a/lib/server/topic-generation-handler.ts b/lib/server/topic-generation-handler.ts index 153df4a..69e9f84 100644 --- a/lib/server/topic-generation-handler.ts +++ b/lib/server/topic-generation-handler.ts @@ -4,7 +4,7 @@ import { StudyState } from "@/lib/studyStates" export async function handleTopicGeneration( defaultModel: LanguageModel, messages: any[], - studentContext: string + systemContext: string ) { try { const chatStreamResponse = await streamText({ @@ -28,7 +28,7 @@ Formatting Instructions: Ensure the study sheet is clear and easy to read. Use bullet points for lists, bold headings for sections, and provide ample spacing for clarity. Do not generate additional text like summary, notes or additional text not in study sheet text. -${studentContext} +${systemContext} ` }, ...messages