Skip to content

Commit 865cd42

Browse files
authored
Merge pull request #30 from intel/update-branch-18156297050
feat: enable content generation without source for slide (#351)
2 parents 5916c33 + cf7cd4e commit 865cd42

File tree

7 files changed

+155
-24
lines changed

7 files changed

+155
-24
lines changed

frontend/src/app/api/slide/content-generator.ts

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { createOllama } from 'ollama-ai-provider'
55
import { type CoreMessage, generateText } from 'ai'
66
import type { ClientSource } from '@/lib/types/client-source'
7+
import type { CourseInfo } from '@/lib/types/course-info-types'
78
import type {
89
LectureContent,
910
AssessmentQuestion,
@@ -42,6 +43,7 @@ export async function generateCourseContent(
4243
sessionLength: number,
4344
difficultyLevel: string,
4445
topicName: string,
46+
courseInfo?: CourseInfo,
4547
): Promise<LectureContent> {
4648
try {
4749
// Check for required environment variables
@@ -55,8 +57,11 @@ export async function generateCourseContent(
5557

5658
// Prepare source content
5759
console.log('Preparing source content...')
58-
const { content: assistantContent, metadata: sourceMetadata } =
59-
await prepareSourceContent(selectedSources)
60+
const { content: assistantContent, metadata: sourceMetadata } = await prepareSourceContent(
61+
selectedSources,
62+
topicName,
63+
courseInfo,
64+
)
6065

6166
// Ensure assistant content fits within context window
6267
const assistantMessage: CoreMessage = {
@@ -112,7 +117,9 @@ export async function generateCourseContent(
112117

113118
const metadataUserMessage: CoreMessage = {
114119
role: 'user',
115-
content: `Generate the title, learning outcomes, and at least 5-10 key terms for a ${difficultyLevel} level ${contentType} on "${topicName}" based STRICTLY on the provided source materials above.`,
120+
content: sourceMetadata.usingCourseContext
121+
? `Generate the title, learning outcomes, and at least 5-10 key terms for a ${difficultyLevel} level ${contentType} on "${topicName}" based on standard academic knowledge and best practices for this subject area.`
122+
: `Generate the title, learning outcomes, and at least 5-10 key terms for a ${difficultyLevel} level ${contentType} on "${topicName}" based STRICTLY on the provided source materials above.`,
116123
}
117124

118125
const metadataMessages = [metadataSystemMessage, assistantMessage, metadataUserMessage]
@@ -137,10 +144,17 @@ export async function generateCourseContent(
137144
const introSystemPrompt = `You are an expert educational content developer. Continue creating a ${difficultyLevel} level ${contentType} on "${topicName}" designed for a ${sessionLength}-minute session.
138145
139146
IMPORTANT INSTRUCTIONS:
140-
1. You MUST base your content ENTIRELY on the source materials provided.
147+
${
148+
sourceMetadata.usingCourseContext
149+
? `1. Since no specific source materials were provided, base your content on standard academic knowledge for the topic.
150+
2. Draw from established educational practices and common curriculum content for this subject area.
151+
3. Create content appropriate for the specified difficulty level and session length.
152+
4. Ensure the introduction provides context and importance of the topic based on general knowledge.`
153+
: `1. You MUST base your content ENTIRELY on the source materials provided.
141154
2. Extract key concepts, terminology, examples, and explanations directly from the source materials.
142155
3. Do not introduce concepts or information that is not present in the source materials.
143-
4. Create an engaging introduction that provides context and importance of the topic.
156+
4. Create an engaging introduction that provides context and importance of the topic.`
157+
}
144158
145159
RESPONSE FORMAT:
146160
Your response MUST be a valid JSON object with EXACTLY these fields:
@@ -157,7 +171,9 @@ CRITICAL: Your response MUST be valid JSON only. Do not include any text, markdo
157171

158172
const introUserMessage: CoreMessage = {
159173
role: 'user',
160-
content: `Generate an engaging introduction for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
174+
content: sourceMetadata.usingCourseContext
175+
? `Generate an engaging introduction for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based on standard academic knowledge and best practices for this subject area.`
176+
: `Generate an engaging introduction for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
161177
}
162178

163179
const introMessages = [introSystemMessage, assistantMessage, introUserMessage]
@@ -179,9 +195,15 @@ CRITICAL: Your response MUST be valid JSON only. Do not include any text, markdo
179195
const specialSlidesSystemPrompt = `You are an expert educational content developer. Continue creating a ${difficultyLevel} level ${contentType} on "${topicName}" designed for a ${sessionLength}-minute session.
180196
181197
IMPORTANT INSTRUCTIONS:
182-
1. You MUST base your content ENTIRELY on the source materials provided.
198+
${
199+
sourceMetadata.usingCourseContext
200+
? `1. Since no specific source materials were provided, base your content on standard academic knowledge for the topic.
201+
2. Draw from established educational practices and common curriculum content for this subject area.
202+
3. Create content appropriate for the specified difficulty level and session length.`
203+
: `1. You MUST base your content ENTIRELY on the source materials provided.
183204
2. Extract key concepts, terminology, examples, and explanations directly from the source materials.
184-
3. Do not introduce concepts or information that is not present in the source materials.
205+
3. Do not introduce concepts or information that is not present in the source materials.`
206+
}
185207
4. Create ONLY the following special slides:
186208
- Introduction slide (first slide that introduces the topic)
187209
- Agenda/Overview slide (outlines what will be covered)
@@ -228,7 +250,9 @@ CRITICAL: Your response MUST be valid JSON only. Do not include any text, markdo
228250

229251
const specialSlidesUserMessage: CoreMessage = {
230252
role: 'user',
231-
content: `Generate the introduction, agenda, assessment, and conclusion slides for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
253+
content: sourceMetadata.usingCourseContext
254+
? `Generate the introduction, agenda, assessment, and conclusion slides for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based on standard academic knowledge and best practices for this subject area.`
255+
: `Generate the introduction, agenda, assessment, and conclusion slides for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
232256
}
233257

234258
const specialSlidesMessages = [
@@ -291,9 +315,15 @@ CRITICAL: Your response MUST be valid JSON only. Do not include any text, markdo
291315
const contentSlidesSystemPrompt = `You are generating content slides ${startSlideNum} through ${endSlideNum} of a total of ${totalContentSlidesNeeded} content slides. Ensure all slides are unique.
292316
293317
IMPORTANT INSTRUCTIONS:
294-
1. You MUST base your content ENTIRELY on the source materials provided.
318+
${
319+
sourceMetadata.usingCourseContext
320+
? `1. Since no specific source materials were provided, base your content on standard academic knowledge for the topic.
321+
2. Draw from established educational practices and common curriculum content for this subject area.
322+
3. Create content appropriate for the specified difficulty level and session length.`
323+
: `1. You MUST base your content ENTIRELY on the source materials provided.
295324
2. Extract key concepts, terminology, examples, and explanations directly from the source materials.
296-
3. Do not introduce concepts or information that is not present in the source materials.
325+
3. Do not introduce concepts or information that is not present in the source materials.`
326+
}
297327
4. Create detailed teaching slides with substantial content on each slide.
298328
5. Focus ONLY on core teaching content slides.
299329
6. Each slide should have comprehensive speaker notes with additional details and examples.
@@ -324,7 +354,11 @@ CRITICAL: Your response MUST be valid JSON only. Do not include any text, markdo
324354

325355
const contentSlidesUserMessage: CoreMessage = {
326356
role: 'user',
327-
content: `Generate content slides ${startSlideNum} through ${endSlideNum} for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.
357+
content: sourceMetadata.usingCourseContext
358+
? `Generate content slides ${startSlideNum} through ${endSlideNum} for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based on standard academic knowledge and best practices for this subject area.
359+
360+
DO NOT create introduction, agenda, assessment, or conclusion slides. Focus ONLY on core teaching content slides.`
361+
: `Generate content slides ${startSlideNum} through ${endSlideNum} for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.
328362
329363
DO NOT create introduction, agenda, assessment, or conclusion slides. Focus ONLY on core teaching content slides.`,
330364
}
@@ -381,7 +415,9 @@ DO NOT create introduction, agenda, assessment, or conclusion slides. Focus ONLY
381415

382416
const activitiesUserMessage: CoreMessage = {
383417
role: 'user',
384-
content: `Generate the activities for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
418+
content: sourceMetadata.usingCourseContext
419+
? `Generate the activities for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based on standard academic knowledge and best practices for this subject area.`
420+
: `Generate the activities for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
385421
}
386422

387423
const activitiesMessages = [activitiesSystemMessage, assistantMessage, activitiesUserMessage]
@@ -417,7 +453,9 @@ DO NOT create introduction, agenda, assessment, or conclusion slides. Focus ONLY
417453

418454
const assessmentUserMessage: CoreMessage = {
419455
role: 'user',
420-
content: `Generate assessment ideas (without example questions) for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
456+
content: sourceMetadata.usingCourseContext
457+
? `Generate assessment ideas (without example questions) for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based on standard academic knowledge and best practices for this subject area.`
458+
: `Generate assessment ideas (without example questions) for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
421459
}
422460

423461
const assessmentMessages = [assessmentSystemMessage, assistantMessage, assessmentUserMessage]
@@ -479,7 +517,9 @@ DO NOT create introduction, agenda, assessment, or conclusion slides. Focus ONLY
479517

480518
const readingsUserMessage: CoreMessage = {
481519
role: 'user',
482-
content: `Generate further reading suggestions for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
520+
content: sourceMetadata.usingCourseContext
521+
? `Generate further reading suggestions for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based on standard academic knowledge and best practices for this subject area.`
522+
: `Generate further reading suggestions for a ${difficultyLevel} level ${contentType} on "${topicName}" with title "${metadataResponse.title}" based STRICTLY on the provided source materials above.`,
483523
}
484524

485525
const readingsMessages = [readingsSystemMessage, assistantMessage, readingsUserMessage]

frontend/src/app/api/slide/route.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export async function POST(req: Request) {
139139
sessionLength,
140140
difficultyLevel,
141141
topicName,
142+
courseInfo,
142143
} = requestData
143144

144145
console.log('Data from request:', {
@@ -149,6 +150,7 @@ export async function POST(req: Request) {
149150
sessionLength,
150151
difficultyLevel,
151152
topicName,
153+
courseInfo,
152154
})
153155

154156
// Generate course content
@@ -160,6 +162,7 @@ export async function POST(req: Request) {
160162
sessionLength,
161163
difficultyLevel,
162164
topicName,
165+
courseInfo,
163166
)
164167

165168
return NextResponse.json(generatedContent)

frontend/src/app/api/slide/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Type definitions for course content generation
55

66
import { ClientSource } from '@/lib/types/client-source'
7+
import type { CourseInfo } from '@/lib/types/course-info-types'
78

89
export interface LectureSlide {
910
title: string
@@ -120,6 +121,7 @@ export interface CourseContentRequest {
120121
sessionLength: number
121122
difficultyLevel: string
122123
topicName: string
124+
courseInfo?: CourseInfo
123125
action?: string
124126
content?: LectureContent
125127
}

frontend/src/app/api/slide/utils.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import type { ContextChunk } from '@/lib/types/context-chunk'
55
import type { ClientSource } from '@/lib/types/client-source'
6+
import type { CourseInfo } from '@/lib/types/course-info-types'
67
import { getStoredChunks } from '@/lib/chunk/get-stored-chunks'
78
import type { AssessmentQuestion } from './types'
89
import { fallbackDiscussionIdeas } from './fallback-content'
@@ -95,14 +96,66 @@ export function extractAndParseJSON(text: string) {
9596
}
9697

9798
// Prepare source content for the AI model
98-
export async function prepareSourceContent(selectedSources: ClientSource[]) {
99+
export async function prepareSourceContent(
100+
selectedSources: ClientSource[],
101+
topicName?: string,
102+
courseInfo?: CourseInfo,
103+
) {
99104
try {
105+
// Check if we have any selected sources
106+
const selectedSourcesFiltered = selectedSources?.filter((source) => source.selected) || []
107+
// If no sources are selected, create course-based content
108+
if (selectedSourcesFiltered.length === 0) {
109+
console.log('No sources selected, using course context for content generation')
110+
const courseContent = `COURSE CONTEXT:\n\n`
111+
let structuredContent = courseContent
112+
if (courseInfo) {
113+
structuredContent += `Course: ${courseInfo.courseCode || ''} ${courseInfo.courseName || 'Academic Course'}\n`
114+
structuredContent += `Semester: ${courseInfo.semester || 'Current Semester'}\n`
115+
structuredContent += `Academic Year: ${courseInfo.academicYear || 'Current Academic Year'}\n\n`
116+
}
117+
structuredContent += `Topic: ${topicName || 'Course Topic'}\n\n`
118+
structuredContent += `GENERAL KNOWLEDGE CONTEXT:\n`
119+
structuredContent += `Since no specific source materials were provided, this content should be generated based on:\n`
120+
structuredContent += `1. Standard academic knowledge for the topic "${topicName}"\n`
121+
structuredContent += `2. Common educational practices and pedagogical approaches\n`
122+
structuredContent += `3. Typical curriculum content for this subject area\n`
123+
structuredContent += `4. Best practices in educational content development\n\n`
124+
const sourceMetadata = {
125+
sourceCount: 0,
126+
chunkCount: 0,
127+
tokenEstimate: countTokens(structuredContent),
128+
sourceNames: [],
129+
usingCourseContext: true,
130+
}
131+
return { content: structuredContent, metadata: sourceMetadata }
132+
}
133+
100134
// Use the getStoredChunks function to retrieve chunks from Payload CMS
101-
const retrievedChunks = await getStoredChunks(selectedSources)
135+
const retrievedChunks = await getStoredChunks(selectedSourcesFiltered)
102136
console.log('Retrieved chunks:', retrievedChunks.length)
103137

104138
if (retrievedChunks.length === 0) {
105-
throw new Error('No content found in the selected sources.')
139+
// If we have selected sources but no chunks found, fallback to course context
140+
console.log('No content found in selected sources, falling back to course context')
141+
const courseContent = `COURSE CONTEXT (Source Fallback):\n\n`
142+
let structuredContent = courseContent
143+
if (courseInfo) {
144+
structuredContent += `Course: ${courseInfo.courseCode || ''} ${courseInfo.courseName || 'Academic Course'}\n`
145+
structuredContent += `Semester: ${courseInfo.semester || 'Current Semester'}\n`
146+
structuredContent += `Academic Year: ${courseInfo.academicYear || 'Current Academic Year'}\n\n`
147+
}
148+
structuredContent += `Topic: ${topicName || 'Course Topic'}\n\n`
149+
structuredContent += `GENERAL KNOWLEDGE CONTEXT:\n`
150+
structuredContent += `Content should be generated based on standard academic knowledge for "${topicName}"\n\n`
151+
const sourceMetadata = {
152+
sourceCount: 0,
153+
chunkCount: 0,
154+
tokenEstimate: countTokens(structuredContent),
155+
sourceNames: [],
156+
usingCourseContext: true,
157+
}
158+
return { content: structuredContent, metadata: sourceMetadata }
106159
}
107160

108161
// Process chunks to create a more structured context
@@ -184,6 +237,7 @@ export async function prepareSourceContent(selectedSources: ClientSource[]) {
184237
chunkCount: retrievedChunks.length,
185238
tokenEstimate: countTokens(structuredContent),
186239
sourceNames: Array.from(sourceGroups.keys()),
240+
usingCourseContext: false,
187241
}
188242

189243
return { content: structuredContent, metadata: sourceMetadata }
@@ -196,6 +250,7 @@ export async function prepareSourceContent(selectedSources: ClientSource[]) {
196250
chunkCount: 0,
197251
tokenEstimate: 0,
198252
sourceNames: [],
253+
usingCourseContext: false,
199254
},
200255
}
201256
}

frontend/src/components/slide/ConfigView.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,12 @@ export function ConfigView({
103103
{selectedSources.filter((source) => source.selected).length === 0 && (
104104
<div className="text-sm text-muted-foreground">
105105
<p>
106-
No sources selected. Please select at least one source document from the
107-
sidebar.
106+
No sources selected. Content will be generated using course context and
107+
general knowledge.
108108
</p>
109109
<p className="mt-1 font-medium text-amber-500">
110-
The generated content will be based ONLY on your selected sources.
110+
You can optionally select source documents to focus content on specific
111+
materials.
111112
</p>
112113
</div>
113114
)}

0 commit comments

Comments
 (0)