From 04f1c2b23b60a18c679959d7ccf81013537c8b8e Mon Sep 17 00:00:00 2001 From: Tobias Kotzian <74184208+SolizerCodes@users.noreply.github.com> Date: Tue, 18 Jul 2023 13:45:18 +0200 Subject: [PATCH] Iris: Get offered models from Pyris (#6886) --- .../domain/iris/settings/IrisSubSettings.java | 8 ++-- .../connectors/iris/IrisConnectorService.java | 20 +++++++- .../service/connectors/iris/IrisModel.java | 8 ---- .../iris/dto/IrisMessageResponseDTO.java | 3 +- .../connectors/iris/dto/IrisModelDTO.java | 4 ++ .../connectors/iris/dto/IrisRequestDTO.java | 3 +- .../connectors/iris/dto/IrisStatusDTO.java | 4 +- .../service/iris/IrisSettingsService.java | 6 +-- .../web/rest/iris/IrisModelsResource.java | 47 +++++++++++++++++++ .../changelog/20230717171717_changelog.xml | 8 ++++ .../resources/config/liquibase/master.xml | 1 + .../app/entities/iris/settings/iris-model.ts | 5 ++ .../iris/settings/iris-sub-settings.model.ts | 6 +-- .../iris-settings-update.component.html | 18 +++++-- .../iris-settings-update.component.ts | 11 ++++- .../iris-sub-settings-update.component.html | 15 +++++- .../iris-sub-settings-update.component.ts | 15 ++++++ .../settings/shared/iris-settings.service.ts | 8 ++++ src/main/webapp/i18n/de/iris.json | 1 + src/main/webapp/i18n/en/iris.json | 1 + .../connector/IrisRequestMockProvider.java | 3 +- .../iris/AbstractIrisIntegrationTest.java | 11 ++--- .../settings/IrisSettingsIntegrationTest.java | 9 ++-- .../iris-settings-update.component.spec.ts | 22 +++++++++ ...iris-sub-settings-update.component.spec.ts | 21 ++++++++- 25 files changed, 206 insertions(+), 52 deletions(-) delete mode 100644 src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisModel.java create mode 100644 src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisModelDTO.java create mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/iris/IrisModelsResource.java create mode 100644 src/main/resources/config/liquibase/changelog/20230717171717_changelog.xml create mode 100644 src/main/webapp/app/entities/iris/settings/iris-model.ts diff --git a/src/main/java/de/tum/in/www1/artemis/domain/iris/settings/IrisSubSettings.java b/src/main/java/de/tum/in/www1/artemis/domain/iris/settings/IrisSubSettings.java index ea87c35c3e65..1d603967c8e3 100644 --- a/src/main/java/de/tum/in/www1/artemis/domain/iris/settings/IrisSubSettings.java +++ b/src/main/java/de/tum/in/www1/artemis/domain/iris/settings/IrisSubSettings.java @@ -10,7 +10,6 @@ import de.tum.in.www1.artemis.domain.DomainObject; import de.tum.in.www1.artemis.domain.iris.IrisTemplate; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; /** * An IrisSubSettings object represents the settings for a specific feature of Iris. @@ -31,8 +30,7 @@ public class IrisSubSettings extends DomainObject { @Nullable @Column(name = "preferredModel") - @Enumerated(EnumType.STRING) - private IrisModel preferredModel; + private String preferredModel; public boolean isEnabled() { return enabled; @@ -52,11 +50,11 @@ public void setTemplate(@Nullable IrisTemplate template) { } @Nullable - public IrisModel getPreferredModel() { + public String getPreferredModel() { return preferredModel; } - public void setPreferredModel(@Nullable IrisModel preferredModel) { + public void setPreferredModel(@Nullable String preferredModel) { this.preferredModel = preferredModel; } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisConnectorService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisConnectorService.java index 98d75ca2eb82..595c2101d660 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisConnectorService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisConnectorService.java @@ -1,5 +1,7 @@ package de.tum.in.www1.artemis.service.connectors.iris; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -19,6 +21,7 @@ import de.tum.in.www1.artemis.domain.iris.IrisTemplate; import de.tum.in.www1.artemis.service.connectors.iris.dto.IrisErrorResponseDTO; import de.tum.in.www1.artemis.service.connectors.iris.dto.IrisMessageResponseDTO; +import de.tum.in.www1.artemis.service.connectors.iris.dto.IrisModelDTO; import de.tum.in.www1.artemis.service.connectors.iris.dto.IrisRequestDTO; import de.tum.in.www1.artemis.service.iris.exception.*; @@ -50,14 +53,27 @@ public IrisConnectorService(@Qualifier("irisRestTemplate") RestTemplate restTemp * not reachable) * @param parameters A map of parameters to be included in the template through handlebars (if they are specified * in the template) - * @return The message response to the request which includes the {@link de.tum.in.www1.artemis.domain.iris.IrisMessage} and the used {@link IrisModel} + * @return The message response to the request which includes the {@link de.tum.in.www1.artemis.domain.iris.IrisMessage} and the used IrisModel */ @Async - public CompletableFuture sendRequest(IrisTemplate template, IrisModel preferredModel, Map parameters) { + public CompletableFuture sendRequest(IrisTemplate template, String preferredModel, Map parameters) { var request = new IrisRequestDTO(template, preferredModel, parameters); return sendRequest(request); } + /** + * Requests all available models from Pyris + * + * @return A list of available Models as IrisModelDTO + */ + public List getOfferedModels() throws IrisConnectorException { + var response = restTemplate.getForEntity(irisUrl + "/api/v1/models", JsonNode.class); + if (!response.getStatusCode().is2xxSuccessful() || !response.hasBody()) { + throw new IrisConnectorException("Could not fetch offered models"); + } + return Arrays.asList((IrisModelDTO[]) parseResponse(response.getBody(), IrisModelDTO.class.arrayType())); + } + private CompletableFuture sendRequest(IrisRequestDTO request) { try { try { diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisModel.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisModel.java deleted file mode 100644 index 62059b8be3e3..000000000000 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/IrisModel.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.tum.in.www1.artemis.service.connectors.iris; - -/** - * Represents the possible LLM models available for Iris - */ -public enum IrisModel { - GPT35_TURBO, GPT35_TURBO_16K_0613, GPT35_TURBO_0613 -} diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisMessageResponseDTO.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisMessageResponseDTO.java index 1e4ae8f42d3e..cac9b0849bad 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisMessageResponseDTO.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisMessageResponseDTO.java @@ -1,7 +1,6 @@ package de.tum.in.www1.artemis.service.connectors.iris.dto; import de.tum.in.www1.artemis.domain.iris.IrisMessage; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; -public record IrisMessageResponseDTO(IrisModel usedModel, IrisMessage message) { +public record IrisMessageResponseDTO(String usedModel, IrisMessage message) { } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisModelDTO.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisModelDTO.java new file mode 100644 index 000000000000..53f686cce216 --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisModelDTO.java @@ -0,0 +1,4 @@ +package de.tum.in.www1.artemis.service.connectors.iris.dto; + +public record IrisModelDTO(String id, String name, String description) { +} diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisRequestDTO.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisRequestDTO.java index 1b3e46884454..b419ac151ce1 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisRequestDTO.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisRequestDTO.java @@ -3,7 +3,6 @@ import java.util.Map; import de.tum.in.www1.artemis.domain.iris.IrisTemplate; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; -public record IrisRequestDTO(IrisTemplate template, IrisModel preferredModel, Map parameters) { +public record IrisRequestDTO(IrisTemplate template, String preferredModel, Map parameters) { } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisStatusDTO.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisStatusDTO.java index 67ed3ea7409d..a90dcf732abc 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisStatusDTO.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/iris/dto/IrisStatusDTO.java @@ -2,9 +2,7 @@ import java.util.Map; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; - -public record IrisStatusDTO(Map modelStatuses) { +public record IrisStatusDTO(Map modelStatuses) { public enum ModelStatus { UP, DOWN, NOT_AVAILABLE diff --git a/src/main/java/de/tum/in/www1/artemis/service/iris/IrisSettingsService.java b/src/main/java/de/tum/in/www1/artemis/service/iris/IrisSettingsService.java index 6492e790f828..76a64e6d68be 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/iris/IrisSettingsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/iris/IrisSettingsService.java @@ -21,7 +21,6 @@ import de.tum.in.www1.artemis.repository.CourseRepository; import de.tum.in.www1.artemis.repository.ProgrammingExerciseRepository; import de.tum.in.www1.artemis.repository.iris.IrisSettingsRepository; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; import de.tum.in.www1.artemis.web.rest.errors.AccessForbiddenException; import de.tum.in.www1.artemis.web.rest.errors.BadRequestAlertException; @@ -229,16 +228,13 @@ private IrisSubSettings combineSubSettings(IrisSubSettings subSettings1, IrisSub combinedSettings.setEnabled(enabled); if (!reduced) { - IrisModel preferredModel; + String preferredModel = null; if (subSettings2 != null && subSettings2.getPreferredModel() != null) { preferredModel = subSettings2.getPreferredModel(); } else if (subSettings1 != null && subSettings1.getPreferredModel() != null) { preferredModel = subSettings1.getPreferredModel(); } - else { - preferredModel = IrisModel.GPT35_TURBO; - } combinedSettings.setPreferredModel(preferredModel); IrisTemplate template; diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/iris/IrisModelsResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/iris/IrisModelsResource.java new file mode 100644 index 000000000000..519070c023f4 --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/iris/IrisModelsResource.java @@ -0,0 +1,47 @@ +package de.tum.in.www1.artemis.web.rest.iris; + +import java.util.List; + +import org.springframework.context.annotation.Profile; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import de.tum.in.www1.artemis.security.annotations.EnforceAtLeastEditor; +import de.tum.in.www1.artemis.service.connectors.iris.IrisConnectorException; +import de.tum.in.www1.artemis.service.connectors.iris.IrisConnectorService; +import de.tum.in.www1.artemis.service.connectors.iris.dto.IrisModelDTO; +import de.tum.in.www1.artemis.web.rest.errors.InternalServerErrorException; + +/** + * REST controller for managing the models Pyris provides. + */ +@RestController +@Profile("iris") +@RequestMapping("api/") +public class IrisModelsResource { + + private final IrisConnectorService irisConnectorService; + + public IrisModelsResource(IrisConnectorService irisConnectorService) { + this.irisConnectorService = irisConnectorService; + } + + /** + * GET iris/models: Retrieve all available models offered by Pyris + * + * @return the {@link ResponseEntity} with status {@code 200 (Ok)} and with body a List of the models + */ + @GetMapping("iris/models") + @EnforceAtLeastEditor + public ResponseEntity> getAllModels() { + try { + var models = irisConnectorService.getOfferedModels(); + return ResponseEntity.ok(models); + } + catch (IrisConnectorException e) { + throw new InternalServerErrorException("Could not fetch available Iris models"); + } + } +} diff --git a/src/main/resources/config/liquibase/changelog/20230717171717_changelog.xml b/src/main/resources/config/liquibase/changelog/20230717171717_changelog.xml new file mode 100644 index 000000000000..7968f7ba6ab2 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20230717171717_changelog.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/main/resources/config/liquibase/master.xml b/src/main/resources/config/liquibase/master.xml index c1478afd08b5..5b950696b6a1 100644 --- a/src/main/resources/config/liquibase/master.xml +++ b/src/main/resources/config/liquibase/master.xml @@ -52,6 +52,7 @@ + diff --git a/src/main/webapp/app/entities/iris/settings/iris-model.ts b/src/main/webapp/app/entities/iris/settings/iris-model.ts new file mode 100644 index 000000000000..94a7f9202d92 --- /dev/null +++ b/src/main/webapp/app/entities/iris/settings/iris-model.ts @@ -0,0 +1,5 @@ +export class IrisModel { + id: string; + name: string; + description: string; +} diff --git a/src/main/webapp/app/entities/iris/settings/iris-sub-settings.model.ts b/src/main/webapp/app/entities/iris/settings/iris-sub-settings.model.ts index 199b1a4d087c..e436e7b3427b 100644 --- a/src/main/webapp/app/entities/iris/settings/iris-sub-settings.model.ts +++ b/src/main/webapp/app/entities/iris/settings/iris-sub-settings.model.ts @@ -1,13 +1,9 @@ import { BaseEntity } from 'app/shared/model/base-entity'; import { IrisTemplate } from 'app/entities/iris/settings/iris-template'; -export enum IrisModel { - GPT35 = 'GPT35', -} - export class IrisSubSettings implements BaseEntity { id?: number; enabled = false; template?: IrisTemplate; - preferredModel?: IrisModel; + preferredModel?: string; } diff --git a/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.html b/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.html index 539545e4c191..9db00ccb7781 100644 --- a/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.html +++ b/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.html @@ -1,21 +1,31 @@
- +

Chat Settings

- +

Hestia Settings

- +
- +
diff --git a/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.ts b/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.ts index e6323d1b3cf9..8ffd46696c9d 100644 --- a/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.ts +++ b/src/main/webapp/app/iris/settings/iris-settings-update/iris-settings-update.component.ts @@ -7,6 +7,7 @@ import { AlertService } from 'app/core/util/alert.service'; import { ButtonType } from 'app/shared/components/button.component'; import { faRotate, faSave } from '@fortawesome/free-solid-svg-icons'; import { IrisSubSettings } from 'app/entities/iris/settings/iris-sub-settings.model'; +import { IrisModel } from 'app/entities/iris/settings/iris-model'; export enum IrisSettingsType { GLOBAL = 'GLOBAL', @@ -27,6 +28,7 @@ export class IrisSettingsUpdateComponent implements OnInit { public programmingExerciseId?: number; public irisSettings?: IrisSettings; + public irisModels?: IrisModel[]; // Loading bools isLoading = false; @@ -47,10 +49,17 @@ export class IrisSettingsUpdateComponent implements OnInit { this.loadIrisSettings(); } + loadIrisModels(): void { + this.irisSettingsService.getIrisModels().subscribe((models) => { + this.irisModels = models; + this.isLoading = false; + }); + } + loadIrisSettings(): void { this.isLoading = true; this.loadIrisSettingsObservable().subscribe((settings) => { - this.isLoading = false; + this.loadIrisModels(); if (!settings) { this.alertService.error('artemisApp.iris.settings.error.noSettings'); } diff --git a/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.html b/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.html index 5e250dcac3b8..b3107084482f 100644 --- a/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.html +++ b/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.html @@ -2,7 +2,20 @@ -Preferred Model: {{ subSettings.preferredModel }} +Preferred Model: +
+ +
+ + +
+
diff --git a/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.ts b/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.ts index a59501b38bc8..b78a05e52eed 100644 --- a/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.ts +++ b/src/main/webapp/app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; import { IrisSubSettings } from 'app/entities/iris/settings/iris-sub-settings.model'; import { IrisTemplate } from 'app/entities/iris/settings/iris-template'; +import { IrisModel } from 'app/entities/iris/settings/iris-model'; @Component({ selector: 'jhi-iris-sub-settings-update', @@ -10,6 +11,12 @@ export class IrisSubSettingsUpdateComponent { @Input() subSettings: IrisSubSettings; + @Input() + models: IrisModel[]; + + @Input() + modelOptional = false; + @Input() templateOptional = false; @@ -25,4 +32,12 @@ export class IrisSubSettingsUpdateComponent { this.subSettings.template = this.previousTemplate ?? irisTemplate; } } + + getSelectedModelName(): string { + return this.models.find((model) => model.id === this.subSettings.preferredModel)?.name ?? this.subSettings.preferredModel ?? 'None'; + } + + setModel(model: IrisModel | undefined) { + this.subSettings.preferredModel = model?.id; + } } diff --git a/src/main/webapp/app/iris/settings/shared/iris-settings.service.ts b/src/main/webapp/app/iris/settings/shared/iris-settings.service.ts index 0d38a8520489..f85240cef829 100644 --- a/src/main/webapp/app/iris/settings/shared/iris-settings.service.ts +++ b/src/main/webapp/app/iris/settings/shared/iris-settings.service.ts @@ -3,6 +3,7 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { IrisSettings } from 'app/entities/iris/settings/iris-settings.model'; +import { IrisModel } from 'app/entities/iris/settings/iris-model'; type EntityResponseType = HttpResponse; @@ -89,4 +90,11 @@ export class IrisSettingsService { setProgrammingExerciseSettings(exerciseId: number, settings: IrisSettings): Observable { return this.http.put(`${this.resourceUrl}/programming-exercises/${exerciseId}/raw-iris-settings`, settings, { observe: 'response' }); } + + /** + * Get the global Iris settings + */ + getIrisModels(): Observable { + return this.http.get(`${this.resourceUrl}/iris/models`, { observe: 'response' }).pipe(map((res: HttpResponse) => res.body ?? [])); + } } diff --git a/src/main/webapp/i18n/de/iris.json b/src/main/webapp/i18n/de/iris.json index 2ed66dd6f41a..95e45c8259e6 100644 --- a/src/main/webapp/i18n/de/iris.json +++ b/src/main/webapp/i18n/de/iris.json @@ -26,6 +26,7 @@ "inheritHestiaSettings": "Vererbe Hestia Einstellungen", "enabled-disabled": "Aktiviert/Deaktiviert", "preferredModel": "Präferiertes Modell", + "inheritModel": "Vererbe Modell", "template": { "title": "Template", "inherit": "Inherit Template" diff --git a/src/main/webapp/i18n/en/iris.json b/src/main/webapp/i18n/en/iris.json index 282b6250bb95..64480dde3d5a 100644 --- a/src/main/webapp/i18n/en/iris.json +++ b/src/main/webapp/i18n/en/iris.json @@ -26,6 +26,7 @@ "inheritHestiaSettings": "Inherit Hestia Settings", "enabled-disabled": "Enabled/Disabled", "preferredModel": "Preferred Model", + "inheritModel": "Inherit Modell", "template": { "title": "Template", "inherit": "Inherit Template" diff --git a/src/test/java/de/tum/in/www1/artemis/connector/IrisRequestMockProvider.java b/src/test/java/de/tum/in/www1/artemis/connector/IrisRequestMockProvider.java index 96cc49dd8ed8..f9e6cfd7a642 100644 --- a/src/test/java/de/tum/in/www1/artemis/connector/IrisRequestMockProvider.java +++ b/src/test/java/de/tum/in/www1/artemis/connector/IrisRequestMockProvider.java @@ -26,7 +26,6 @@ import de.tum.in.www1.artemis.domain.iris.IrisMessage; import de.tum.in.www1.artemis.domain.iris.IrisMessageContent; import de.tum.in.www1.artemis.domain.iris.IrisMessageSender; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; import de.tum.in.www1.artemis.service.connectors.iris.dto.IrisMessageResponseDTO; @Component @@ -79,7 +78,7 @@ public void mockResponse(String responseMessage) throws JsonProcessingException irisMessage.setSender(IrisMessageSender.LLM); irisMessage.setSentAt(ZonedDateTime.now()); - var response = new IrisMessageResponseDTO(IrisModel.GPT35_TURBO, irisMessage); + var response = new IrisMessageResponseDTO(null, irisMessage); var json = mapper.writeValueAsString(response); mockServer.expect(ExpectedCount.once(), requestTo(apiURL.toString())).andExpect(method(HttpMethod.POST)).andRespond(withSuccess(json, MediaType.APPLICATION_JSON)); diff --git a/src/test/java/de/tum/in/www1/artemis/iris/AbstractIrisIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/iris/AbstractIrisIntegrationTest.java index c451415a303e..462c76961173 100644 --- a/src/test/java/de/tum/in/www1/artemis/iris/AbstractIrisIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/iris/AbstractIrisIntegrationTest.java @@ -24,7 +24,6 @@ import de.tum.in.www1.artemis.repository.CourseRepository; import de.tum.in.www1.artemis.repository.ProgrammingExerciseRepository; import de.tum.in.www1.artemis.repository.iris.IrisTemplateRepository; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; import de.tum.in.www1.artemis.service.iris.IrisSettingsService; import de.tum.in.www1.artemis.service.iris.IrisWebsocketService; import de.tum.in.www1.artemis.user.UserUtilService; @@ -70,9 +69,9 @@ void tearDown() throws Exception { protected void activateIrisGlobally() { var globalSettings = irisSettingsService.getGlobalSettings(); globalSettings.getIrisChatSettings().setEnabled(true); - globalSettings.getIrisChatSettings().setPreferredModel(IrisModel.GPT35_TURBO); + globalSettings.getIrisChatSettings().setPreferredModel(null); globalSettings.getIrisHestiaSettings().setEnabled(true); - globalSettings.getIrisHestiaSettings().setPreferredModel(IrisModel.GPT35_TURBO); + globalSettings.getIrisHestiaSettings().setPreferredModel(null); irisSettingsService.saveGlobalIrisSettings(globalSettings); } @@ -80,10 +79,10 @@ protected void activateIrisFor(Course course) { var courseWithSettings = irisSettingsService.addDefaultIrisSettingsTo(course); courseWithSettings.getIrisSettings().getIrisChatSettings().setEnabled(true); courseWithSettings.getIrisSettings().getIrisChatSettings().setTemplate(createDummyTemplate()); - courseWithSettings.getIrisSettings().getIrisChatSettings().setPreferredModel(IrisModel.GPT35_TURBO); + courseWithSettings.getIrisSettings().getIrisChatSettings().setPreferredModel(null); courseWithSettings.getIrisSettings().getIrisHestiaSettings().setEnabled(true); courseWithSettings.getIrisSettings().getIrisHestiaSettings().setTemplate(createDummyTemplate()); - courseWithSettings.getIrisSettings().getIrisHestiaSettings().setPreferredModel(IrisModel.GPT35_TURBO); + courseWithSettings.getIrisSettings().getIrisHestiaSettings().setPreferredModel(null); courseRepository.save(courseWithSettings); } @@ -91,7 +90,7 @@ protected void activateIrisFor(ProgrammingExercise exercise) { var exerciseWithSettings = irisSettingsService.addDefaultIrisSettingsTo(exercise); exerciseWithSettings.getIrisSettings().getIrisChatSettings().setEnabled(true); exerciseWithSettings.getIrisSettings().getIrisChatSettings().setTemplate(createDummyTemplate()); - exerciseWithSettings.getIrisSettings().getIrisChatSettings().setPreferredModel(IrisModel.GPT35_TURBO); + exerciseWithSettings.getIrisSettings().getIrisChatSettings().setPreferredModel(null); programmingExerciseRepository.save(exerciseWithSettings); } diff --git a/src/test/java/de/tum/in/www1/artemis/iris/settings/IrisSettingsIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/iris/settings/IrisSettingsIntegrationTest.java index b28c34de5708..39f292072d55 100644 --- a/src/test/java/de/tum/in/www1/artemis/iris/settings/IrisSettingsIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/iris/settings/IrisSettingsIntegrationTest.java @@ -15,7 +15,6 @@ import de.tum.in.www1.artemis.iris.AbstractIrisIntegrationTest; import de.tum.in.www1.artemis.repository.iris.IrisSettingsRepository; import de.tum.in.www1.artemis.repository.iris.IrisSubSettingsRepository; -import de.tum.in.www1.artemis.service.connectors.iris.IrisModel; class IrisSettingsIntegrationTest extends AbstractIrisIntegrationTest { @@ -135,11 +134,11 @@ void updateCourseSettings3() throws Exception { course.getIrisSettings().setIrisChatSettings(new IrisSubSettings()); course.getIrisSettings().getIrisChatSettings().setEnabled(true); course.getIrisSettings().getIrisChatSettings().setTemplate(createDummyTemplate()); - course.getIrisSettings().getIrisChatSettings().setPreferredModel(IrisModel.GPT35_TURBO); + course.getIrisSettings().getIrisChatSettings().setPreferredModel(null); course.getIrisSettings().setIrisHestiaSettings(new IrisSubSettings()); course.getIrisSettings().getIrisHestiaSettings().setEnabled(true); course.getIrisSettings().getIrisHestiaSettings().setTemplate(createDummyTemplate()); - course.getIrisSettings().getIrisHestiaSettings().setPreferredModel(IrisModel.GPT35_TURBO); + course.getIrisSettings().getIrisHestiaSettings().setPreferredModel(null); var updatedSettings = request.putWithResponseBody("/api/courses/" + course.getId() + "/raw-iris-settings", course.getIrisSettings(), IrisSettings.class, HttpStatus.OK); var loadedSettings1 = request.get("/api/courses/" + course.getId() + "/raw-iris-settings", HttpStatus.OK, IrisSettings.class); @@ -253,11 +252,11 @@ void updateProgrammingExerciseSettings3() throws Exception { programmingExercise.getIrisSettings().setIrisChatSettings(new IrisSubSettings()); programmingExercise.getIrisSettings().getIrisChatSettings().setEnabled(true); programmingExercise.getIrisSettings().getIrisChatSettings().setTemplate(createDummyTemplate()); - programmingExercise.getIrisSettings().getIrisChatSettings().setPreferredModel(IrisModel.GPT35_TURBO); + programmingExercise.getIrisSettings().getIrisChatSettings().setPreferredModel(null); programmingExercise.getIrisSettings().setIrisHestiaSettings(new IrisSubSettings()); programmingExercise.getIrisSettings().getIrisHestiaSettings().setEnabled(true); programmingExercise.getIrisSettings().getIrisHestiaSettings().setTemplate(createDummyTemplate()); - programmingExercise.getIrisSettings().getIrisHestiaSettings().setPreferredModel(IrisModel.GPT35_TURBO); + programmingExercise.getIrisSettings().getIrisHestiaSettings().setPreferredModel(null); var updatedSettings = request.putWithResponseBody("/api/programming-exercises/" + programmingExercise.getId() + "/raw-iris-settings", programmingExercise.getIrisSettings(), IrisSettings.class, HttpStatus.OK); diff --git a/src/test/javascript/spec/component/iris/settings/iris-settings-update.component.spec.ts b/src/test/javascript/spec/component/iris/settings/iris-settings-update.component.spec.ts index dfac6440eba5..0bed904d03eb 100644 --- a/src/test/javascript/spec/component/iris/settings/iris-settings-update.component.spec.ts +++ b/src/test/javascript/spec/component/iris/settings/iris-settings-update.component.spec.ts @@ -10,6 +10,7 @@ import { of } from 'rxjs'; import { IrisSubSettingsUpdateComponent } from 'app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component'; import { ButtonComponent } from 'app/shared/components/button.component'; import { HttpResponse } from '@angular/common/http'; +import { IrisModel } from 'app/entities/iris/settings/iris-model'; function baseSettings() { const mockTemplate = new IrisTemplate(); @@ -30,6 +31,21 @@ function baseSettings() { return irisSettings; } +function models() { + return [ + { + id: '1', + name: 'Model 1', + description: 'Model 1 Description', + }, + { + id: '2', + name: 'Model 2', + description: 'Model 2 Description', + }, + ] as IrisModel[]; +} + describe('IrisSettingsUpdateComponent Component', () => { let comp: IrisSettingsUpdateComponent; let fixture: ComponentFixture; @@ -56,9 +72,11 @@ describe('IrisSettingsUpdateComponent Component', () => { it('Loads global settings correctly', () => { const irisSettings = baseSettings(); const getSettingsSpy = jest.spyOn(irisSettingsService, 'getGlobalSettings').mockReturnValue(of(irisSettings)); + const getModelsSpy = jest.spyOn(irisSettingsService, 'getIrisModels').mockReturnValue(of(models())); comp.settingType = IrisSettingsType.GLOBAL; fixture.detectChanges(); expect(getSettingsSpy).toHaveBeenCalledOnce(); + expect(getModelsSpy).toHaveBeenCalledOnce(); expect(comp.irisSettings).toEqual(irisSettings); expect(fixture.debugElement.nativeElement.querySelector('#inheritHestia')).toBeFalsy(); }); @@ -66,10 +84,12 @@ describe('IrisSettingsUpdateComponent Component', () => { it('Loads course settings correctly', () => { const irisSettings = baseSettings(); const getSettingsSpy = jest.spyOn(irisSettingsService, 'getUncombinedCourseSettings').mockReturnValue(of(irisSettings)); + const getModelsSpy = jest.spyOn(irisSettingsService, 'getIrisModels').mockReturnValue(of(models())); comp.settingType = IrisSettingsType.COURSE; comp.courseId = 1; fixture.detectChanges(); expect(getSettingsSpy).toHaveBeenCalledWith(1); + expect(getModelsSpy).toHaveBeenCalledOnce(); expect(comp.irisSettings).toEqual(irisSettings); expect(fixture.debugElement.nativeElement.querySelector('#inheritHestia')).toBeFalsy(); }); @@ -77,10 +97,12 @@ describe('IrisSettingsUpdateComponent Component', () => { it('Loads programming exercise settings correctly', () => { const irisSettings = baseSettings(); const getSettingsSpy = jest.spyOn(irisSettingsService, 'getUncombinedProgrammingExerciseSettings').mockReturnValue(of(irisSettings)); + const getModelsSpy = jest.spyOn(irisSettingsService, 'getIrisModels').mockReturnValue(of(models())); comp.settingType = IrisSettingsType.PROGRAMMING_EXERCISE; comp.programmingExerciseId = 1; fixture.detectChanges(); expect(getSettingsSpy).toHaveBeenCalledWith(1); + expect(getModelsSpy).toHaveBeenCalledOnce(); expect(comp.irisSettings).toEqual(irisSettings); expect(fixture.debugElement.nativeElement.querySelector('#inheritHestia')).toBeTruthy(); }); diff --git a/src/test/javascript/spec/component/iris/settings/iris-sub-settings-update.component.spec.ts b/src/test/javascript/spec/component/iris/settings/iris-sub-settings-update.component.spec.ts index 9377b338bca0..bab069444247 100644 --- a/src/test/javascript/spec/component/iris/settings/iris-sub-settings-update.component.spec.ts +++ b/src/test/javascript/spec/component/iris/settings/iris-sub-settings-update.component.spec.ts @@ -4,6 +4,9 @@ import { FormsModule } from '@angular/forms'; import { IrisTemplate } from 'app/entities/iris/settings/iris-template'; import { IrisSubSettings } from 'app/entities/iris/settings/iris-sub-settings.model'; import { IrisSubSettingsUpdateComponent } from 'app/iris/settings/iris-settings-update/iris-sub-settings-update/iris-sub-settings-update.component'; +import { IrisModel } from 'app/entities/iris/settings/iris-model'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { MockDirective } from 'ng-mocks'; function baseSettings() { const mockTemplate = new IrisTemplate(); @@ -16,17 +19,33 @@ function baseSettings() { return irisSubSettings; } +function models() { + return [ + { + id: '1', + name: 'Model 1', + description: 'Model 1 Description', + }, + { + id: '2', + name: 'Model 2', + description: 'Model 2 Description', + }, + ] as IrisModel[]; +} + describe('IrisSubSettingsUpdateComponent Component', () => { let comp: IrisSubSettingsUpdateComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ - imports: [ArtemisTestModule, FormsModule], + imports: [ArtemisTestModule, FormsModule, MockDirective(NgbTooltip)], declarations: [IrisSubSettingsUpdateComponent], }).compileComponents(); fixture = TestBed.createComponent(IrisSubSettingsUpdateComponent); comp = fixture.componentInstance; + comp.models = models(); }); afterEach(() => {