Skip to content

Refactor and Enhancements to Chat Components #73

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions actions/dashboard/ExamPreparationActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ export async function continueConversation (
You and the user can discuss the exam and the student's performance

Messages inside [] means that it's a UI element or a user event. For example:
- [showExamnForm] means that the user will see an exam form and fill it out
- [showExamnResult] means that the user will see the result of the exam he took
- [examnsSuggestions] means that the user will see suggestions for exams he can take
- [showExamForm] means that the user will see an exam form and fill it out
- [showExamResult] means that the user will see the result of the exam he took
- [examsSuggestions] means that the user will see suggestions for exams he can take

If the user requests a exam or quiz, call \`showExamnForm\` to show the exam form. after an exan is taken, call \`showExamnResult\` to show the result of the exam.
As a teacher, if the user ask for an exam but is vague, you can suggest exams to the user by calling \`examnsSuggestions\` or if the user is asking for suggestions.
If the user requests a exam or quiz, call \`showExamForm\` to show the exam form. after an exan is taken, call \`showExamResult\` to show the result of the exam.
As a teacher, if the user ask for an exam but is vague, you can suggest exams to the user by calling \`examsSuggestions\` or if the user is asking for suggestions.

Besides that, you can also chat with users about possible topics for exams, or any other topic you want to discuss with the user that goes along with the exam preparation as this is a exam preparation chat.
`,
Expand Down Expand Up @@ -118,7 +118,7 @@ export async function continueConversation (
)
},
tools: {
showExamnForm: {
showExamForm: {
description: 'Show the user an exam form to fill out for an exam preparationn, this form will be sent to the user and he will anwser it',
parameters: z.object({
singleSelectQuestion: z.array(z.object({
Expand Down Expand Up @@ -182,7 +182,7 @@ export async function continueConversation (
content: [
{
type: 'tool-call',
toolName: 'showExamnForm',
toolName: 'showExamForm',
toolCallId,
args: {
singleSelectQuestion,
Expand All @@ -199,7 +199,7 @@ export async function continueConversation (
content: [
{
type: 'tool-result',
toolName: 'showExamnForm',
toolName: 'showExamForm',
toolCallId,
result: {
singleSelectQuestion,
Expand Down Expand Up @@ -230,7 +230,7 @@ export async function continueConversation (
message: JSON.stringify([
{
type: 'tool-call',
toolName: 'showExamnForm',
toolName: 'showExamForm',
toolCallId,
result: {
singleSelectQuestion,
Expand All @@ -248,7 +248,7 @@ export async function continueConversation (
message: JSON.stringify([
{
type: 'tool-result',
toolName: 'showExamnForm',
toolName: 'showExamForm',
toolCallId,
result: {
singleSelectQuestion,
Expand Down Expand Up @@ -284,7 +284,7 @@ export async function continueConversation (
)
}
},
showExamnResult: {
showExamResult: {
description: 'Show the user the result of the exam he took',
parameters: z.object({
score: z.number().int().describe('The grade of the student in the exam with a scale from 0 to 20'),
Expand Down Expand Up @@ -313,7 +313,7 @@ export async function continueConversation (
content: [
{
type: 'tool-call',
toolName: 'showExamnResult',
toolName: 'showExamResult',
toolCallId,
args: {
score,
Expand All @@ -329,7 +329,7 @@ export async function continueConversation (
content: [
{
type: 'tool-result',
toolName: 'showExamnResult',
toolName: 'showExamResult',
toolCallId,
result: {
score,
Expand Down Expand Up @@ -361,7 +361,7 @@ export async function continueConversation (
message: JSON.stringify([
{
type: 'tool-call',
toolName: 'showExamnResult',
toolName: 'showExamResult',
toolCallId,
result: {
score,
Expand All @@ -378,7 +378,7 @@ export async function continueConversation (
message: JSON.stringify([
{
type: 'tool-result',
toolName: 'showExamnResult',
toolName: 'showExamResult',
toolCallId,
result: {
score,
Expand Down Expand Up @@ -408,14 +408,14 @@ export async function continueConversation (
)
}
},
examnsSuggestions: {
description: 'Show the user suggestions for exams he can take',
examsSuggestions: {
description: 'Show the user suggestions for exams forms he can take',
parameters: z.object({
suggestions: z.array(z.object({
title: z.string().describe('The title of the suggestion'),
description: z.string().describe('The description of the suggestion'),
content: z.string().describe('The content of the suggestion'),
difficulty: z.string().describe('The difficulty of the examn')
title: z.string().describe('The title of the suggestion for the exam'),
description: z.string().describe('The description of the suggestion for the exam'),
content: z.string().describe('The content of the suggestion for the exam'),
difficulty: z.string().describe('The difficulty of the exam')
}))
}),
generate: async function * ({
Expand All @@ -435,7 +435,7 @@ export async function continueConversation (
content: [
{
type: 'tool-call',
toolName: 'examnsSuggestions',
toolName: 'examsSuggestions',
toolCallId,
args: {
suggestions
Expand All @@ -449,7 +449,7 @@ export async function continueConversation (
content: [
{
type: 'tool-result',
toolName: 'examnsSuggestions',
toolName: 'examsSuggestions',
toolCallId,
result: {
suggestions
Expand All @@ -468,7 +468,7 @@ export async function continueConversation (
message: JSON.stringify([
{
type: 'tool-call',
toolName: 'examnsSuggestions',
toolName: 'examsSuggestions',
toolCallId,
result: {
suggestions
Expand All @@ -483,7 +483,7 @@ export async function continueConversation (
message: JSON.stringify([
{
type: 'tool-result',
toolName: 'examnsSuggestions',
toolName: 'examsSuggestions',
toolCallId,
result: {
suggestions
Expand Down Expand Up @@ -600,10 +600,10 @@ export const getUIStateFromAIState = (aiState: Chat) => {

message.role === 'tool' ? (
message.content.map(tool => {
// find if the next message is a showExamnResult
// find if the next message is a showExamResult
// @ts-expect-error
const isNextMessageAShowExamnResult = aiState?.messages[index + 1] ? aiState?.messages[index + 1].content[0]?.toolName === 'showExamnResult' : false
return tool.toolName === 'showExamnForm' ? (
const isNextMessageAShowExamnResult = aiState?.messages[index + 1] ? aiState?.messages[index + 1].content[0]?.toolName === 'showExamResult' : false
return tool.toolName === 'showExamForm' ? (
<Message
sender={'assistant'}
time={dayjs().format('dddd, MMMM D, YYYY h:mm A')}
Expand All @@ -621,7 +621,7 @@ export const getUIStateFromAIState = (aiState: Chat) => {
hideSubmit={isNextMessageAShowExamnResult}
/>
</Message>
) : tool.toolName === 'showExamnResult' ? (
) : tool.toolName === 'showExamResult' ? (
<Message
sender={'assistant'}
time={dayjs().format('dddd, MMMM D, YYYY h:mm A')}
Expand All @@ -636,7 +636,7 @@ export const getUIStateFromAIState = (aiState: Chat) => {
questionAndAnswerFeedback={tool.result.questionAndAnswerFeedback}
/>
</Message>
) : tool.toolName === 'examnsSuggestions' ? (
) : tool.toolName === 'examsSuggestions' ? (
<Message
sender={'assistant'}
time={dayjs().format('dddd, MMMM D, YYYY h:mm A')}
Expand Down
2 changes: 2 additions & 0 deletions app/api/lessons/chat/student/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function POST (req: Request) {
})
}
},
temperature: 0.5,
// model: ollama('llama3'),
messages: convertToCoreMessages(messages),
tools: {
Expand Down Expand Up @@ -76,6 +77,7 @@ export async function POST (req: Request) {
// Respond with the stream
return result.toAIStreamResponse()
} catch (error) {
console.log('Error:', error)
return new Response('Error', { status: 500 })
}
}
3 changes: 1 addition & 2 deletions app/dashboard/student/chat/[chatId]/free-chat/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ export default async function FreeChatPage ({
return (

<>
<div className='flex flex-col gap-4 overflow-y-auto h-[calc(100vh-4rem)]'>

<div className='flex flex-col gap-4 overflow-y-auto h-[calc(100vh)] md:h-[calc(100vh-4rem)]'>
<FreeChat
chatId={Number(params.chatId)}
initialMessages={
Expand Down
5 changes: 1 addition & 4 deletions app/dashboard/student/chat/[chatId]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ export default async function CoursesLayout ({
}

return (
<div className='flex flex-col gap-4 p-4'>
<h1 className="text-2xl font-semibold">
{chatData.data.title}
</h1>
<div className='flex flex-col gap-4 p-2 lg:p-4'>
{children}
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion components/dashboards/Common/CommentsSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default async function CommentsSections ({
.filter(comment => comment.parent_comment_id === null)
.map((comment) => {
const user = profiles.data.find((profile) => profile.id === comment.user_id)
const isReactionPresent = comment.comment_reactions.find(
const isReactionPresent = comment?.comment_reactions?.find(
(reaction) => reaction.user_id === currentUser.data.user.id
)

Expand Down
114 changes: 72 additions & 42 deletions components/dashboards/Common/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,12 @@ const ChatWindow = ({
isLoading: boolean
}) => {
return (
<div className="flex-1 overflow-y-auto p-4 ">
<div className="flex-1 overflow-y-auto p-1 md:p-2 lg:p-4">
{messages.map((msg, index) => {
if (msg.role === 'system') {
return null
}
if (index === 0) return null
return (
<Message
key={index}
Expand Down Expand Up @@ -151,57 +152,86 @@ const ChatWindow = ({
const ChatInput = ({
isLoading,
stop,
callbackFunction
callbackFunction,
isTemplatePresent
}: {
isLoading: boolean
stop?: () => void
callbackFunction: (MessageType: MessageType) => void
isTemplatePresent?: boolean
}) => {
const [message, setMessage] = useState<string>('')
const ref = useRef<MDXEditorMethods>(null)

return (
<form
onSubmit={(e) => {
e.preventDefault()
callbackFunction({
content: message,
role: 'user',
createdAt: new Date(),
id: generateId()
})
setMessage('')
ref.current?.setMarkdown('')
}}
className="py-4 flex gap-2 flex-col w-full"
>
<ForwardRefEditor
className={cn(
'flex-1 p-2 rounded border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent w-full rich-text markdown-body',
isLoading ? 'cursor-not-allowed' : 'cursor-text'
)}
placeholder="Chat with the AI assistant"
markdown={message}
onChange={(value) => setMessage(value)}
ref={ref}
/>
<input type="hidden" value={message} />
{isLoading ? (
<Button
type="button"
onClick={stop}
variant="outline"
className="rounded-r-lg"
>
Stop
</Button>
) : (
<Button type="submit" className="rounded-r-lg">
Send
</Button>
<>
{isTemplatePresent && (
<>
<Button
variant='outline'
disabled={isLoading}
onClick={() => {
('Template for generating exam form')
setMessage('Please create an exam form for the topic of **"Your Topic"**\n---\nThe exam form should contain the following sections:\n- Multiple choice questions\n- True or False questions\n- Fill in the blanks\n- Matching questions\nI want it to have a minimum of "X" questions.\nIt should have a level of difficulty of "X".\nThe exam form should be interactive and engaging.\n')
ref.current?.setMarkdown('Please create an exam form for the topic of **"Your Topic"**\n---\nThe exam form should contain the following sections:\n- Multiple choice questions\n- True or False questions\n- Fill in the blanks\n- Matching questions\nI want it to have a minimum of "X" questions.\nIt should have a level of difficulty of "X".\nThe exam form should be interactive and engaging.\n')
} }
>
Template for generating exam form for a "X" topic
</Button>
<Button
variant='outline'
disabled={isLoading}
onClick={() => {
setMessage('Please help me by giving suggestions of possible exams You could generate for the given topic "Your topic"')
ref.current?.setMarkdown('Please help me by giving suggestions of possible exams You could generate for the given topic "Your topic"')
} }
>
Template for asking a suggestions of an exam form for a "X" topic
</Button>
</>
)}
<DisclaimerForUser />
</form>
<form
onSubmit={(e) => {
e.preventDefault()
callbackFunction({
content: message,
role: 'user',
createdAt: new Date(),
id: generateId()
})
setMessage('')
ref.current?.setMarkdown('')
}}
className="py-4 flex gap-2 flex-col w-full"
>
<ForwardRefEditor
className={cn(
'flex-1 p-2 rounded border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent w-full rich-text markdown-body',
isLoading ? 'cursor-not-allowed' : 'cursor-text'
)}
placeholder="Chat with the AI assistant"
markdown={message}
onChange={(value) => setMessage(value)}
ref={ref}
/>
<input type="hidden" value={message} />
{isLoading ? (
<Button
type="button"
onClick={stop}
variant="outline"
className="rounded-r-lg"
>
Stop
</Button>
) : (
<Button type="submit" className="rounded-r-lg">
Send
</Button>
)}
<DisclaimerForUser />
</form>
</>
)
}

Expand Down
Loading
Loading