diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 1076ce4..9776eb9 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,23 +21,11 @@ export async function POST(request: Request) { studySheet, chatRecallMetadata, randomRecallFact, - profile_context + systemContext } = json const studentMessage = messages[messages.length - 1] - const studentContext = - profile_context.length > 0 - ? `Here is how the student would like you to respond: - """${profile_context}"""` - : "" - 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.` - const defaultModel = openai("gpt-4o-mini") as LanguageModel const scoringModel = defaultModel const hintingModel = defaultModel @@ -53,7 +38,7 @@ export async function POST(request: Request) { return await handleTopicGeneration( defaultModel, messages, - studentContext + systemContext ) case "recall_tutorial_first_attempt": @@ -61,13 +46,11 @@ export async function POST(request: Request) { return await handleRecallAttempt( scoringModel, defaultModel, - messages, studyState, studySheet, chatId, studentMessage, - mentor_system_message, - finalFeedback + systemContext ) case "recall_tutorial_hinting": @@ -78,22 +61,23 @@ export async function POST(request: Request) { studyState, studySheet, chatRecallMetadata, - studentMessage + systemContext ) 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": + case "quick_quiz_user_answer": case "quick_quiz_finished": return await handleQuickQuizAnswer( defaultModel, @@ -101,7 +85,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 7d49f4b..f665f54 100644 --- a/components/chat/chat-hooks/use-chat-handler.tsx +++ b/components/chat/chat-hooks/use-chat-handler.tsx @@ -67,13 +67,23 @@ export const useChatHandler = () => { setChatStudyState(studyState) } + const systemContext = ` +User Info: +${profile?.profile_context || ""} + + +System Instructions for module ${selectedWorkspace?.name || ""}: +${selectedWorkspace?.instructions || ""} + +` + return { chatId: currentChat?.id, studyState, studySheet, chatRecallMetadata, randomRecallFact, - profile_context: profile?.profile_context || "" + systemContext } } 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/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 c6c3a6b..8779270 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 + systemContext: 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. + ${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.` + if (allRecalled) { newStudyState = studyState === "recall_tutorial_first_attempt" 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 47461d8..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({ @@ -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. + +${systemContext} +` }, ...messages ])