From 0c44efcf693be0f03a9fcdc8eb3f1829b343335a Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Mon, 6 Apr 2026 09:31:36 -0700 Subject: [PATCH 1/2] Use systemPrompt in the component content instead of the default, if exists. --- src/assets/wise5/common/ComponentContent.ts | 3 +++ .../ai-summary/ai-summary.component.ts | 12 +++++++++--- .../discussion-ai-summary.component.ts | 2 +- .../open-response-ai-summary.component.ts | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/assets/wise5/common/ComponentContent.ts b/src/assets/wise5/common/ComponentContent.ts index 6273bb3663e..ea9795e1a05 100644 --- a/src/assets/wise5/common/ComponentContent.ts +++ b/src/assets/wise5/common/ComponentContent.ts @@ -4,6 +4,9 @@ import { DynamicPrompt } from '../directives/dynamic-prompt/DynamicPrompt'; export interface ComponentContent { id: string; + ai?: { + teacherSummarySystemPrompt?: string; + }; anonymizeResponses?: boolean; connectedComponents?: any[]; constraints?: any[]; diff --git a/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts index 12916ebcf82..b074f68de7a 100644 --- a/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts @@ -10,6 +10,7 @@ import { DatePipe } from '@angular/common'; import { TeacherProjectService } from '../../../services/teacherProjectService'; import { ChatService } from '../../../../../app/services/chat/chat.service'; import { OpenAiChatService } from '../../../../../app/services/chat/openAiChat.service'; +import { ComponentContent } from '../../../common/ComponentContent'; /** * Abstract base class for components that use an LLM to summarize student responses. @@ -25,6 +26,7 @@ export abstract class AiSummaryComponent { @Input() periodId: number; private chatService: ChatService = inject(OpenAiChatService); + private component: ComponentContent; protected dataService: TeacherDataService = inject(TeacherDataService); protected datePipe: DatePipe = inject(DatePipe); private localStorageService: LocalStorageService = inject(LocalStorageService); @@ -38,6 +40,7 @@ export abstract class AiSummaryComponent { protected summaryDate: Date; ngOnInit(): void { + this.component = this.projectService.getComponent(this.nodeId, this.componentId); this.latestComponentStates = this.getLatestComponentStates(); this.hasStudentResponses = this.latestComponentStates.length > 0; if (this.hasStudentResponses) { @@ -64,9 +67,8 @@ export abstract class AiSummaryComponent { protected async generateSummary(): Promise { this.generatingSummary = true; - const prompt = this.projectService.getComponent(this.nodeId, this.componentId).prompt; this.summary = await this.chatService.sendMessage([ - new ChatMessage('system', this.getSystemPrompt(prompt), this.nodeId), + new ChatMessage('system', this.getSystemPrompt(this.component.prompt), this.nodeId), new ChatMessage('user', this.getStudentResponses(), this.nodeId) ]); this.localStorageService.setItem(this.getSummaryKey(), this.summary); @@ -79,7 +81,11 @@ export abstract class AiSummaryComponent { protected abstract getStudentResponses(): string; - protected abstract getSystemPrompt(prompt: string): string; + protected getSystemPrompt(prompt: string): string { + return this.component.ai?.teacherSummarySystemPrompt ?? this.getDefaultSystemPrompt(prompt); + } + + protected abstract getDefaultSystemPrompt(prompt: string): string; private getSummaryKey(): string { return `component-summary-${this.periodId}-${this.nodeId}-${this.componentId}`; diff --git a/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts index c3727aef2f2..5f2585700a5 100644 --- a/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts @@ -23,7 +23,7 @@ interface Thread { templateUrl: '../ai-summary/ai-summary.component.html' }) export class DiscussionAiSummaryComponent extends AiSummaryComponent { - protected getSystemPrompt(prompt: string): string { + protected getDefaultSystemPrompt(prompt: string): string { return `You are a teacher who is summarizing students' discussion threads, which include posts and replies to the following question: "${prompt}". Each thread is in the format: PostReply 1Reply 2. In the same language as the question, provide a summary of the threads in 100 words or less.`; diff --git a/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts index 6953cf4b80e..af9958eb234 100644 --- a/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts @@ -17,7 +17,7 @@ import { AiSummaryComponent } from '../ai-summary/ai-summary.component'; templateUrl: '../ai-summary/ai-summary.component.html' }) export class OpenResponseAiSummaryComponent extends AiSummaryComponent { - protected getSystemPrompt(prompt: string): string { + protected getDefaultSystemPrompt(prompt: string): string { return `You are a teacher who is summarizing student responses to the following question: "${prompt}". Each student response is in the format: Response. In the same language as the question, provide a summary of the responses in 100 words or less.`; From 599394cdd6c346727cbc8e09092547a3078e02c8 Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Mon, 6 Apr 2026 11:31:15 -0700 Subject: [PATCH 2/2] Allow authors to override default summary system prompt for OR and Discussion componens in the advanced authoring view's AI tab. Also introduced $QUESTION$ and $RESPONSE_FORMAT$ variables --- .../edit-advanced-component.component.ts | 19 ++- .../edit-component-advanced-shared.module.ts | 3 + .../edit-component-advanced.component.spec.ts | 4 + ...nt-summarizer-system-prompt.component.html | 0 ...nent-summarizer-system-prompt.component.ts | 21 +++ .../edit-ai-chat-advanced.component.spec.ts | 11 +- ...dit-concept-map-advanced.component.spec.ts | 1 + .../discussion/discussionService.ts | 9 ++ .../edit-discussion-advanced.component.html | 8 + .../edit-graph-advanced.component.spec.ts | 1 + ...edit-open-response-advanced.component.html | 4 + ...t-open-response-advanced.component.spec.ts | 1 + .../openResponse/openResponseService.ts | 9 ++ ...-chat-advanced-component.component.spec.ts | 9 +- .../edit-table-advanced.component.spec.ts | 1 + .../ai-summary/ai-summary.component.ts | 10 +- .../discussion-ai-summary.component.ts | 15 +- ...open-response-ai-summary.component.spec.ts | 9 +- .../open-response-ai-summary.component.ts | 15 +- src/messages.xlf | 147 ++++++++++-------- 20 files changed, 212 insertions(+), 85 deletions(-) create mode 100644 src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.html create mode 100644 src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.ts diff --git a/src/app/authoring-tool/edit-advanced-component/edit-advanced-component.component.ts b/src/app/authoring-tool/edit-advanced-component/edit-advanced-component.component.ts index 94a3858b113..738fbca9356 100644 --- a/src/app/authoring-tool/edit-advanced-component/edit-advanced-component.component.ts +++ b/src/app/authoring-tool/edit-advanced-component/edit-advanced-component.component.ts @@ -1,18 +1,22 @@ -import { Directive, Input } from '@angular/core'; +import { Directive, inject, Input } from '@angular/core'; import { ComponentContent } from '../../../assets/wise5/common/ComponentContent'; import { Component } from '../../../assets/wise5/common/Component'; import { NotebookService } from '../../../assets/wise5/services/notebookService'; import { TeacherProjectService } from '../../../assets/wise5/services/teacherProjectService'; import { TeacherNodeService } from '../../../assets/wise5/services/teacherNodeService'; import { moveObjectDown, moveObjectUp } from '../../../assets/wise5/common/array/array'; +import { ComponentServiceLookupService } from '../../../assets/wise5/services/componentServiceLookupService'; @Directive() export abstract class EditAdvancedComponentComponent { + protected aiEnabled: boolean; component: Component; componentContent: ComponentContent; @Input() componentId: string; @Input() nodeId: string; + private componentServiceLookupService = inject(ComponentServiceLookupService); + constructor( protected nodeService: TeacherNodeService, protected notebookService: NotebookService, @@ -22,6 +26,19 @@ export abstract class EditAdvancedComponentComponent { ngOnInit(): void { this.componentContent = this.teacherProjectService.getComponent(this.nodeId, this.componentId); this.component = new Component(this.componentContent, this.nodeId); + this.aiEnabled = this.teacherProjectService.getProject().ai?.enabled; + if (this.aiEnabled && ['Discussion', 'OpenResponse'].includes(this.component.content.type)) { + if (this.component.content.ai == null) { + const componentService = this.componentServiceLookupService.getService( + this.component.content.type + ); + this.component.content.ai = { + teacherSummarySystemPrompt: componentService.getDefaultTeacherSummarySystemPrompt( + this.component.content.prompt + ) + }; + } + } this.teacherProjectService.uiChanged(); } diff --git a/src/app/authoring-tool/edit-component-advanced/edit-component-advanced-shared.module.ts b/src/app/authoring-tool/edit-component-advanced/edit-component-advanced-shared.module.ts index d0e6ffee11e..7782418c9f2 100644 --- a/src/app/authoring-tool/edit-component-advanced/edit-component-advanced-shared.module.ts +++ b/src/app/authoring-tool/edit-component-advanced/edit-component-advanced-shared.module.ts @@ -16,6 +16,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox'; import { FormsModule } from '@angular/forms'; import { EditComponentAddToNotebookButtonComponent } from '../edit-component-add-to-notebook-button/edit-component-add-to-notebook-button.component'; import { EditConnectedComponentsComponent } from '../edit-connected-components/edit-connected-components.component'; +import { EditComponentSummarizerSystemPromptComponent } from '../edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component'; @NgModule({ imports: [ @@ -29,6 +30,7 @@ import { EditConnectedComponentsComponent } from '../edit-connected-components/e EditComponentExcludeFromTotalScoreComponent, EditComponentWidthComponent, EditComponentRubricComponent, + EditComponentSummarizerSystemPromptComponent, EditComponentTagsComponent, EditComponentConstraintsComponent, EditComponentJsonComponent, @@ -48,6 +50,7 @@ import { EditConnectedComponentsComponent } from '../edit-connected-components/e EditComponentExcludeFromTotalScoreComponent, EditComponentWidthComponent, EditComponentRubricComponent, + EditComponentSummarizerSystemPromptComponent, EditComponentTagsComponent, EditComponentConstraintsComponent, EditComponentJsonComponent, diff --git a/src/app/authoring-tool/edit-component-advanced/edit-component-advanced.component.spec.ts b/src/app/authoring-tool/edit-component-advanced/edit-component-advanced.component.spec.ts index 88fbe826309..7533e5b0f4f 100644 --- a/src/app/authoring-tool/edit-component-advanced/edit-component-advanced.component.spec.ts +++ b/src/app/authoring-tool/edit-component-advanced/edit-component-advanced.component.spec.ts @@ -8,6 +8,7 @@ import { NotificationService } from '../../../assets/wise5/services/notification import { TeacherNodeService } from '../../../assets/wise5/services/teacherNodeService'; import { TeacherProjectService } from '../../../assets/wise5/services/teacherProjectService'; import { EditComponentAdvancedComponent } from './edit-component-advanced.component'; +import { ComponentServiceLookupService } from '../../../assets/wise5/services/componentServiceLookupService'; let component: EditComponentAdvancedComponent; let fixture: ComponentFixture; @@ -31,6 +32,7 @@ describe('EditComponentAdvancedComponent', () => { } }, MockProviders( + ComponentServiceLookupService, TeacherNodeService, NotebookService, NotificationService, @@ -44,6 +46,8 @@ describe('EditComponentAdvancedComponent', () => { spyOn(TestBed.inject(TeacherProjectService), 'getComponent').and.returnValue({ type: 'ShowMyWork' } as ComponentContent); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); + fixture.detectChanges(); }); diff --git a/src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.html b/src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.ts b/src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.ts new file mode 100644 index 00000000000..43c02268678 --- /dev/null +++ b/src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; +import { EditComponentFieldComponent } from '../edit-component-field.component'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { FormsModule } from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { CdkTextareaAutosize } from '@angular/cdk/text-field'; + +@Component({ + imports: [CdkTextareaAutosize, FormsModule, MatFormFieldModule, MatInputModule], + selector: 'edit-component-summarizer-system-prompt', + template: ` + Teacher Summary System Prompt + + ` +}) +export class EditComponentSummarizerSystemPromptComponent extends EditComponentFieldComponent {} diff --git a/src/assets/wise5/components/aiChat/edit-ai-chat-advanced/edit-ai-chat-advanced.component.spec.ts b/src/assets/wise5/components/aiChat/edit-ai-chat-advanced/edit-ai-chat-advanced.component.spec.ts index aa84662ac04..3fb55dd1c6c 100644 --- a/src/assets/wise5/components/aiChat/edit-ai-chat-advanced/edit-ai-chat-advanced.component.spec.ts +++ b/src/assets/wise5/components/aiChat/edit-ai-chat-advanced/edit-ai-chat-advanced.component.spec.ts @@ -7,6 +7,7 @@ import { NotebookService } from '../../../services/notebookService'; import { EditConnectedComponentsComponent } from '../../../../../app/authoring-tool/edit-connected-components/edit-connected-components.component'; import { EditComponentJsonComponent } from '../../../../../app/authoring-tool/edit-component-json/edit-component-json.component'; import { EditComponentWidthComponent } from '../../../../../app/authoring-tool/edit-component-width/edit-component-width.component'; +import { ComponentServiceLookupService } from '../../../services/componentServiceLookupService'; describe('EditAiChatAdvancedComponent', () => { let component: EditAiChatAdvancedComponent; @@ -22,7 +23,14 @@ describe('EditAiChatAdvancedComponent', () => { EditConnectedComponentsComponent ) ], - providers: [MockProviders(NotebookService, TeacherNodeService, TeacherProjectService)] + providers: [ + MockProviders( + ComponentServiceLookupService, + NotebookService, + TeacherNodeService, + TeacherProjectService + ) + ] }); fixture = TestBed.createComponent(EditAiChatAdvancedComponent); component = fixture.componentInstance; @@ -31,6 +39,7 @@ describe('EditAiChatAdvancedComponent', () => { id: 'component1', type: 'aiChat' }); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); fixture.detectChanges(); }); diff --git a/src/assets/wise5/components/conceptMap/edit-concept-map-advanced/edit-concept-map-advanced.component.spec.ts b/src/assets/wise5/components/conceptMap/edit-concept-map-advanced/edit-concept-map-advanced.component.spec.ts index 9b0a0c940c4..adc1646b8cd 100644 --- a/src/assets/wise5/components/conceptMap/edit-concept-map-advanced/edit-concept-map-advanced.component.spec.ts +++ b/src/assets/wise5/components/conceptMap/edit-concept-map-advanced/edit-concept-map-advanced.component.spec.ts @@ -26,6 +26,7 @@ describe('EditConceptMapAdvancedComponent', () => { spyOn(TestBed.inject(TeacherProjectService), 'getComponent').and.returnValue({ rules: [] } as ConceptMapContent); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); spyOn(TestBed.inject(NotebookService), 'isNotebookEnabled').and.returnValue(true); fixture = TestBed.createComponent(EditConceptMapAdvancedComponent); component = fixture.componentInstance; diff --git a/src/assets/wise5/components/discussion/discussionService.ts b/src/assets/wise5/components/discussion/discussionService.ts index a4691ac14d0..2a7ed4abfae 100644 --- a/src/assets/wise5/components/discussion/discussionService.ts +++ b/src/assets/wise5/components/discussion/discussionService.ts @@ -27,6 +27,9 @@ export class DiscussionService extends ComponentService { component.isStudentAttachmentEnabled = true; component.gateClassmateResponses = true; component.anonymizeResponses = false; + component.ai = { + teacherSummarySystemPrompt: this.getDefaultTeacherSummarySystemPrompt() + }; return component; } @@ -335,4 +338,10 @@ export class DiscussionService extends ComponentService { col2: evenResponses.reverse() }; } + + getDefaultTeacherSummarySystemPrompt(): string { + return `You are a teacher who is summarizing students' discussion threads, which include posts and replies to the following question: "$QUESTION$". + Each thread is in the format: $RESPONSE_FORMAT$. + In the same language as the question, provide a summary of the threads in 100 words or less.`; + } } diff --git a/src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html b/src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html index f7763164d97..62ce331bd9a 100644 --- a/src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html +++ b/src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html @@ -9,6 +9,14 @@ + @if (aiEnabled) { + + + auto_awesome AI + + + + } visibility Visibility diff --git a/src/assets/wise5/components/graph/edit-graph-advanced/edit-graph-advanced.component.spec.ts b/src/assets/wise5/components/graph/edit-graph-advanced/edit-graph-advanced.component.spec.ts index 194ad8826b9..824fe1d9320 100644 --- a/src/assets/wise5/components/graph/edit-graph-advanced/edit-graph-advanced.component.spec.ts +++ b/src/assets/wise5/components/graph/edit-graph-advanced/edit-graph-advanced.component.spec.ts @@ -30,6 +30,7 @@ describe('EditGraphAdvancedComponent', () => { xAxis: {}, yAxis: {} } as GraphContent); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); spyOn(projectService, 'getLocale').and.returnValue(new ProjectLocale({ default: 'en-US' })); spyOn(projectService, 'isDefaultLocale').and.returnValue(true); spyOn(TestBed.inject(NotebookService), 'isNotebookEnabled').and.returnValue(true); diff --git a/src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html b/src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html index 2b95896e911..0b248ccb238 100644 --- a/src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html +++ b/src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html @@ -42,6 +42,10 @@ auto_awesome AI + @if (aiEnabled) { + + + }
{ beforeEach(() => { const projectService = TestBed.inject(TeacherProjectService); spyOn(projectService, 'getComponent').and.returnValue({} as ComponentContent); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); spyOn(TestBed.inject(NotebookService), 'isNotebookEnabled').and.returnValue(true); spyOn(projectService, 'getFlattenedProjectAsNodeIds').and.returnValue([ 'node1', diff --git a/src/assets/wise5/components/openResponse/openResponseService.ts b/src/assets/wise5/components/openResponse/openResponseService.ts index f44f0a37ca9..7c576e391c6 100644 --- a/src/assets/wise5/components/openResponse/openResponseService.ts +++ b/src/assets/wise5/components/openResponse/openResponseService.ts @@ -19,6 +19,9 @@ export class OpenResponseService extends ComponentService { component.type = 'OpenResponse'; component.starterSentence = null; component.isStudentAttachmentEnabled = false; + component.ai = { + teacherSummarySystemPrompt: this.getDefaultTeacherSummarySystemPrompt() + }; return component; } @@ -127,4 +130,10 @@ export class OpenResponseService extends ComponentService { } return false; } + + getDefaultTeacherSummarySystemPrompt(): string { + return `You are a teacher who is summarizing student responses to the following question: "$QUESTION$". + Each student response is in the format: $RESPONSE_FORMAT$. + In the same language as the question, provide a summary of the responses in 100 words or less.`; + } } diff --git a/src/assets/wise5/components/peerChat/edit-peer-chat-advanced-component/edit-peer-chat-advanced-component.component.spec.ts b/src/assets/wise5/components/peerChat/edit-peer-chat-advanced-component/edit-peer-chat-advanced-component.component.spec.ts index bf3016c1d53..5094c9969ac 100644 --- a/src/assets/wise5/components/peerChat/edit-peer-chat-advanced-component/edit-peer-chat-advanced-component.component.spec.ts +++ b/src/assets/wise5/components/peerChat/edit-peer-chat-advanced-component/edit-peer-chat-advanced-component.component.spec.ts @@ -7,6 +7,7 @@ import { TeacherProjectService } from '../../../services/teacherProjectService'; import { PeerChatContent } from '../PeerChatContent'; import { EditPeerChatAdvancedComponentComponent } from './edit-peer-chat-advanced-component.component'; import { EditComponentJsonComponent } from '../../../../../app/authoring-tool/edit-component-json/edit-component-json.component'; +import { ComponentServiceLookupService } from '../../../services/componentServiceLookupService'; describe('EditPeerChatAdvancedComponentComponent', () => { let component: EditPeerChatAdvancedComponentComponent; @@ -16,7 +17,12 @@ describe('EditPeerChatAdvancedComponentComponent', () => { await TestBed.configureTestingModule({ imports: [EditPeerChatAdvancedComponentComponent, MockComponent(EditComponentJsonComponent)], providers: [ - MockProviders(TeacherNodeService, TeacherProjectService, NotebookService), + MockProviders( + ComponentServiceLookupService, + TeacherNodeService, + TeacherProjectService, + NotebookService + ), provideHttpClient(withInterceptorsFromDi()) ] }).compileComponents(); @@ -26,6 +32,7 @@ describe('EditPeerChatAdvancedComponentComponent', () => { spyOn(TestBed.inject(TeacherProjectService), 'getComponent').and.returnValue( {} as PeerChatContent ); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); fixture = TestBed.createComponent(EditPeerChatAdvancedComponentComponent); component = fixture.componentInstance; fixture.detectChanges(); diff --git a/src/assets/wise5/components/table/edit-table-advanced/edit-table-advanced.component.spec.ts b/src/assets/wise5/components/table/edit-table-advanced/edit-table-advanced.component.spec.ts index 4f653192c81..a45e0627cc0 100644 --- a/src/assets/wise5/components/table/edit-table-advanced/edit-table-advanced.component.spec.ts +++ b/src/assets/wise5/components/table/edit-table-advanced/edit-table-advanced.component.spec.ts @@ -30,6 +30,7 @@ describe('EditTableAdvancedComponent', () => { beforeEach(() => { spyOn(TestBed.inject(TeacherProjectService), 'getComponent').and.returnValue(createComponent()); + spyOn(TestBed.inject(TeacherProjectService), 'getProject').and.returnValue({}); spyOn(TestBed.inject(NotebookService), 'isNotebookEnabled').and.returnValue(true); spyOn(TestBed.inject(TeacherProjectService), 'getFlattenedProjectAsNodeIds').and.returnValue([ 'node1', diff --git a/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts index b074f68de7a..666cd099779 100644 --- a/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts @@ -82,10 +82,16 @@ export abstract class AiSummaryComponent { protected abstract getStudentResponses(): string; protected getSystemPrompt(prompt: string): string { - return this.component.ai?.teacherSummarySystemPrompt ?? this.getDefaultSystemPrompt(prompt); + const systemPrompt = + this.component.ai?.teacherSummarySystemPrompt ?? this.getDefaultSystemPrompt(); + return systemPrompt + .replace('$QUESTION$', prompt) + .replace('$RESPONSE_FORMAT$', this.getResponseFormat()); } - protected abstract getDefaultSystemPrompt(prompt: string): string; + protected abstract getResponseFormat(): string; + + protected abstract getDefaultSystemPrompt(): string; private getSummaryKey(): string { return `component-summary-${this.periodId}-${this.nodeId}-${this.componentId}`; diff --git a/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts index 5f2585700a5..14ce5adb2f7 100644 --- a/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts @@ -1,11 +1,12 @@ import { DatePipe } from '@angular/common'; -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { MatButton } from '@angular/material/button'; import { MatIcon } from '@angular/material/icon'; import { MatProgressSpinner } from '@angular/material/progress-spinner'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MarkdownComponent } from 'ngx-markdown'; import { AiSummaryComponent } from '../ai-summary/ai-summary.component'; +import { DiscussionService } from '../../../components/discussion/discussionService'; interface Thread { id: number; @@ -23,10 +24,14 @@ interface Thread { templateUrl: '../ai-summary/ai-summary.component.html' }) export class DiscussionAiSummaryComponent extends AiSummaryComponent { - protected getDefaultSystemPrompt(prompt: string): string { - return `You are a teacher who is summarizing students' discussion threads, which include posts and replies to the following question: "${prompt}". - Each thread is in the format: PostReply 1Reply 2. - In the same language as the question, provide a summary of the threads in 100 words or less.`; + private discussionService = inject(DiscussionService); + + protected getDefaultSystemPrompt(): string { + return this.discussionService.getDefaultTeacherSummarySystemPrompt(); + } + + protected getResponseFormat(): string { + return 'PostReply 1Reply 2'; } protected getStudentResponses(): string { diff --git a/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.spec.ts b/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.spec.ts index 7bbffdebf0d..d905d404af8 100644 --- a/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.spec.ts +++ b/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.spec.ts @@ -15,6 +15,7 @@ import { MarkdownComponent, MarkdownService } from 'ngx-markdown'; import { TeacherProjectService } from '../../../services/teacherProjectService'; import { ChatService } from '../../../../../app/services/chat/chat.service'; import { OpenAiChatService } from '../../../../../app/services/chat/openAiChat.service'; +import { OpenResponseService } from '../../../components/openResponse/openResponseService'; describe('OpenResponseAiSummaryComponent', () => { let component: OpenResponseAiSummaryComponent; @@ -38,6 +39,7 @@ describe('OpenResponseAiSummaryComponent', () => { LocalStorageService, MarkdownService, OpenAiChatService, + OpenResponseService, TeacherProjectService, SummaryService, TeacherDataService @@ -53,7 +55,10 @@ describe('OpenResponseAiSummaryComponent', () => { spyOn(projectService, 'getComponent').and.returnValue({ id: 'component1', type: 'OpenResponse', - prompt: 'What is your opinion on climate change?' + prompt: 'What is your opinion on climate change?', + ai: { + teacherSummarySystemPrompt: 'You are a teacher summarizing student responses.' + } } as any); fixture = TestBed.createComponent(OpenResponseAiSummaryComponent); @@ -172,7 +177,7 @@ describe('OpenResponseAiSummaryComponent', () => { await component['generateSummary'](); const messages = sendMessageSpy.calls.mostRecent().args[0]; expect(messages[0].role).toBe('system'); - expect(messages[0].content).toContain('What is your opinion on climate change?'); + expect(messages[0].content).toContain('You are a teacher summarizing student responses.'); }); it('should call chatService with student responses', async () => { diff --git a/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts index af9958eb234..4758e457c57 100644 --- a/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/open-response-ai-summary/open-response-ai-summary.component.ts @@ -1,11 +1,12 @@ import { DatePipe } from '@angular/common'; -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { MatButton } from '@angular/material/button'; import { MatIcon } from '@angular/material/icon'; import { MatProgressSpinner } from '@angular/material/progress-spinner'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MarkdownComponent } from 'ngx-markdown'; import { AiSummaryComponent } from '../ai-summary/ai-summary.component'; +import { OpenResponseService } from '../../../components/openResponse/openResponseService'; /** * Uses an LLM to summarize students' responses to open response questions. @@ -17,10 +18,14 @@ import { AiSummaryComponent } from '../ai-summary/ai-summary.component'; templateUrl: '../ai-summary/ai-summary.component.html' }) export class OpenResponseAiSummaryComponent extends AiSummaryComponent { - protected getDefaultSystemPrompt(prompt: string): string { - return `You are a teacher who is summarizing student responses to the following question: "${prompt}". - Each student response is in the format: Response. - In the same language as the question, provide a summary of the responses in 100 words or less.`; + private openResponseService = inject(OpenResponseService); + + protected getDefaultSystemPrompt(): string { + return this.openResponseService.getDefaultTeacherSummarySystemPrompt(); + } + + protected getResponseFormat(): string { + return 'Response'; } protected getStudentResponses(): string { diff --git a/src/messages.xlf b/src/messages.xlf index 07b0ba79ab1..cb98e5a7460 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -925,7 +925,7 @@ src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html - 42,44 + 50,52 src/assets/wise5/components/draw/edit-draw-advanced/edit-draw-advanced.component.html @@ -957,7 +957,7 @@ src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 608,610 + 612,614 src/assets/wise5/components/outsideURL/edit-outside-url-advanced/edit-outside-url-advanced.component.ts @@ -1102,7 +1102,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html - 33,35 + 41,43 src/assets/wise5/components/draw/edit-draw-advanced/edit-draw-advanced.component.html @@ -1134,7 +1134,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 599,601 + 603,605 src/assets/wise5/components/outsideURL/edit-outside-url-advanced/edit-outside-url-advanced.component.ts @@ -1186,6 +1186,13 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.15,18 + + Teacher Summary System Prompt + + src/app/authoring-tool/edit-component-summarizer-system-prompt/edit-component-summarizer-system-prompt.component.ts + 12,16 + + Tags @@ -1214,7 +1221,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html - 38,39 + 46,47 src/assets/wise5/components/draw/edit-draw-advanced/edit-draw-advanced.component.html @@ -1242,7 +1249,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 604,605 + 608,609 src/assets/wise5/components/outsideURL/edit-outside-url-advanced/edit-outside-url-advanced.component.ts @@ -1919,11 +1926,11 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 65,66 + 69,70 src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 524,525 + 528,529 src/assets/wise5/vle/node/node.component.html @@ -1985,7 +1992,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 505,506 + 509,510 src/assets/wise5/components/summary/summary-authoring/summary-authoring.component.html @@ -2000,7 +2007,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 515,518 + 519,522 src/assets/wise5/components/showGroupWork/show-group-work-authoring/show-group-work-authoring.component.html @@ -2039,7 +2046,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 493,494 + 497,498 src/assets/wise5/components/summary/summary-authoring/summary-authoring.component.html @@ -2073,11 +2080,11 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 66,67 + 70,71 src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 525,527 + 529,531 src/assets/wise5/vle/node/node.component.html @@ -2960,7 +2967,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 132,135 + 136,139 @@ -16653,7 +16660,7 @@ Are you sure you want to proceed? src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html - 14,16 + 22,24 src/assets/wise5/components/draw/edit-draw-advanced/edit-draw-advanced.component.html @@ -16685,7 +16692,7 @@ Are you sure you want to proceed? src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 580,582 + 584,586 src/assets/wise5/components/outsideURL/edit-outside-url-advanced/edit-outside-url-advanced.component.ts @@ -16736,7 +16743,7 @@ Are you sure you want to proceed? src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html - 20,23 + 28,31 src/assets/wise5/components/draw/edit-draw-advanced/edit-draw-advanced.component.html @@ -16764,7 +16771,7 @@ Are you sure you want to proceed? src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 586,589 + 590,593 src/assets/wise5/components/table/edit-table-advanced/edit-table-advanced.component.html @@ -18294,7 +18301,7 @@ Are you ready to receive feedback on this answer? src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 318,319 + 322,323 @@ -19405,6 +19412,17 @@ Category Name: 232 + + AI + + src/assets/wise5/components/discussion/edit-discussion-advanced/edit-discussion-advanced.component.html + 15,17 + + + src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html + 43,46 + + Students draw on a canvas using a variety of tools. @@ -21273,7 +21291,7 @@ Warning: This will delete all existing choices and buckets in this activity. src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 89,92 + 93,96 @@ -21430,212 +21448,205 @@ Warning: This will delete all existing choices in this activity. 21,26 - - AI - - src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 43,47 - - Enable AI Model src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 53,56 + 57,60 Score On src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 60,62 + 64,66 Change src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 67,70 + 71,74 Show Score src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 79,83 + 83,87 Enable Feedback Rules src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 99,101 + 103,105 Scoring Rule src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 111,114 + 115,118 Add Scoring Rule src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 116,119 + 120,123 Feedback Text src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 144,146 + 148,150 Move Scoring Rule Up src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 155,157 + 159,161 Move Scoring Rule Down src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 166,168 + 170,172 Delete Scoring Rule src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 176,178 + 180,182 Enable Multiple Attempt Feedback src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 196,199 + 200,203 Multiple Attempt Scoring Rules src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 201,204 + 205,208 Add Multiple Attempt Scoring Rule src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 206,209 + 210,213 Previous Score src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 222,225 + 226,229 src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 331,334 + 335,338 Current Score src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 231,234 + 235,238 src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 341,344 + 345,348 Feedback to Student src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 242,244 + 246,248 src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 429,431 + 433,435 Move Multiple Attempt Scoring Rule Up src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 258,260 + 262,264 Move Multiple Attempt Scoring Rule Down src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 274,276 + 278,280 Delet Multiple Attempt Scoring src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 284,286 + 288,290 Enable Notifications src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 304,307 + 308,311 Notifications src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 309,312 + 313,316 Move Notification Up src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 362,364 + 366,368 Move Notification Down src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 378,380 + 382,384 Delete Notification src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 388,390 + 392,394 Enable Ambient Display Dismiss Mode src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 403,405 + 407,409 Dismiss Code src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 407,410 + 411,414 src/assets/wise5/vle/dismiss-ambient-notification-dialog/dismiss-ambient-notification-dialog.component.html @@ -21646,63 +21657,63 @@ Warning: This will delete all existing choices in this activity. Notify Student src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 423,425 + 427,429 Notify Teacher src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 443,445 + 447,449 Feedback to Teacher src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 449,451 + 453,455 Use Custom Completion Criteria src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 468,470 + 472,474 Custom Completion Criteria src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 472,475 + 476,479 Add Completion Criteria src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 477,480 + 481,484 Move Completion Criteria Up src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 537,539 + 541,543 Move Completion Criteria Down src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 550,552 + 554,556 Delete Completion Criteria src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 560,562 + 564,566 @@ -23104,14 +23115,14 @@ If this problem continues, let your teacher know and move on to the next activit Summary generated from responses src/assets/wise5/directives/teacher-summary-display/ai-summary/ai-summary.component.ts - 93 + 105 Summary generated from posts and comments src/assets/wise5/directives/teacher-summary-display/discussion-ai-summary/discussion-ai-summary.component.ts - 55 + 60