Skip to content

Commit

Permalink
Merge pull request #3 from StephanieHhnbrg/main
Browse files Browse the repository at this point in the history
adds prompt customization and criteria creation features
  • Loading branch information
StephanieHhnbrg authored Aug 15, 2024
2 parents 4d08765 + 0e0b6e7 commit c420bf5
Show file tree
Hide file tree
Showing 24 changed files with 377 additions and 46 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ To achieve this goal, several GenAI APIs have been integrated to address the fol
2. Response Generation: Produce responses from the integrated GenAI models.
3. Response Evaluation: Assess the generated responses using criteria such as bias, ... .

#### Features
✏️ Customizable Prompts - The prompts used for the prompt generation and the response evaluation/rating can be customized. \
🌐 Multilanguage support - By customizing the prompts and translate them to an other language, prompts, responses and ratings will be generated in this custom language. \
📋 Excel Export and Import - To save the generated data, it can be exported into an .xlsx file, which can be imported in another session to continue the user's journey. \
🔍 Personalized Criteria - The user can define their own criteria for rating GenAIs responses.

### Tutorial
To execute any request to a GenAI API, you must provide a valid API key for the selected service.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.edit-prompting:hover {
color: cyan;
cursor: pointer;
}

.edit-prompting mat-icon {
transform: scale(0.6) translateY(13px);
}

.hidden {
visibility: hidden;
}

mat-form-field {
width: 100%;
padding-top: 20px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>
<span *ngIf="!editingPrompt" class="edit-prompting" (click)="editingPrompt=true"><mat-icon>edit</mat-icon> Adapt prompting</span>
<div [ngClass]="{'hidden': !editingPrompt}">
<mat-form-field>
<mat-label>Prompt</mat-label>
<textarea #promptUpdated matInput [value]="defaultPrompt" (change)='onChange(promptUpdated.value)'></textarea>
</mat-form-field>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PromptCustomizationComponent } from './prompt-customization.component';

describe('EditPromptingLinkComponent', () => {
let component: PromptCustomizationComponent;
let fixture: ComponentFixture<PromptCustomizationComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PromptCustomizationComponent]
})
.compileComponents();

fixture = TestBed.createComponent(PromptCustomizationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {FormsModule} from "@angular/forms";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatInputModule} from "@angular/material/input";
import {MatIconModule} from "@angular/material/icon";
import {CommonModule} from "@angular/common";

@Component({
selector: 'app-prompt-customization',
standalone: true,
imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule, MatIconModule],
templateUrl: './prompt-customization.component.html',
styleUrl: './prompt-customization.component.css'
})
export class PromptCustomizationComponent {

@Output() updatedPrompt = new EventEmitter<string>();


@Input({ required: true }) public defaultPrompt: string = "";
editingPrompt = false;

onChange(prompt: string) {
this.updatedPrompt.emit(prompt);
}

}
6 changes: 3 additions & 3 deletions src/app/components/prompt-table/prompt-table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export class PromptTableComponent implements OnInit, OnDestroy, AfterViewInit {
let ratingInputSelected$ = new Subject<RatingParam>();
this.subscriptions.push(ratingInputSelected$.asObservable().subscribe(param => {
param.responseModels.forEach(responseModel => {
this.generateRatings(responseModel, param.ratingModel, param.criteria);
this.generateRatings(responseModel, param.ratingModel, param.criteria, param.updatedPrompt);
});
}));

Expand Down Expand Up @@ -183,11 +183,11 @@ export class PromptTableComponent implements OnInit, OnDestroy, AfterViewInit {
});
}

private generateRatings(responseModel: Model, ratingModel: Model, criteria: Criteria) {
private generateRatings(responseModel: Model, ratingModel: Model, criteria: Criteria, customPrompt?: string) {
this.topic!.prompts.forEach(p => {
if (p.responses.has(responseModel)) {
let response = p.responses.get(responseModel);
if(!this.ratingService.generateRating(this.topic!, response!, ratingModel, criteria)) {
if(!this.ratingService.generateRating(this.topic!, response!, ratingModel, criteria, customPrompt)) {
return;
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/app/data/criteria.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,3 @@ export interface Criteria {
name: string;
desc: string;
}

export const CRITERIA_LIST: Criteria[] = [
{name: "Bias", desc: "Biasness refers to unfounded beliefs on certain groups based on race, gender, religion, sexual orientation, or other factors.\n Biasness is a form of discrimination and is a violation of human rights.\n"},
{name: "Something Else", desc: ""}
]
1 change: 1 addition & 0 deletions src/app/data/rating.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface RatingParam {
criteria: Criteria,
ratingModel: Model;
responseModels: Model[];
updatedPrompt: string | undefined;
}
3 changes: 1 addition & 2 deletions src/app/dialog/add-keys-dialog/add-keys-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {ChangeDetectionStrategy, Component, inject } from '@angular/core';
import {ChangeDetectionStrategy, Component } from '@angular/core';
import {
MatDialogActions,
MatDialogClose,
MatDialogContent,
MatDialogRef,
MatDialogTitle,
} from '@angular/material/dialog';
import {MatButtonModule} from '@angular/material/button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,16 @@ mat-form-field {
width: 100%;
padding-top: 20px;
}

.view-criteria:hover {
color: cyan;
cursor: pointer;
}

.view-criteria mat-icon {
transform: scale(0.6) translateY(13px);
}

::ng-deep .rating-dialog .mat-mdc-form-field-bottom-align {
max-height: 5px;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h2 mat-dialog-title>Create rating</h2>
<mat-dialog-content>
<mat-dialog-content class="rating-dialog">
<div *ngIf="responseModels.length > 1">
<p>Which responses would you like to rate?</p>

Expand All @@ -16,6 +16,8 @@ <h2 mat-dialog-title>Create rating</h2>
<mat-option *ngFor="let c of criteria" [value]="c">{{c.name}}</mat-option>
</mat-select>
</mat-form-field>
<span class="view-criteria" (click)="openCriteriaDialog()"><mat-icon>visibility</mat-icon> View criteria</span>


<mat-form-field>
<mat-label>Select a model:</mat-label>
Expand All @@ -24,6 +26,7 @@ <h2 mat-dialog-title>Create rating</h2>
</mat-select>
</mat-form-field>

<app-prompt-customization [defaultPrompt]="getRatingGenerationPrompt(criteriaSelect.value)" (updatedPrompt)="updatePrompt($event)"></app-prompt-customization>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-dialog-close
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, model, ModelSignal, OnInit} from '@angular/core';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
inject,
Inject,
model,
ModelSignal,
OnInit
} from '@angular/core';
import {CommonModule} from "@angular/common";
import {MatButtonModule} from "@angular/material/button";
import {
MAT_DIALOG_DATA,
MAT_DIALOG_DATA, MatDialog,
MatDialogActions,
MatDialogClose,
MatDialogContent,
Expand All @@ -13,37 +22,48 @@ import {MatInputModule} from "@angular/material/input";
import {MatSelectModule} from "@angular/material/select";
import {MatOptionModule} from "@angular/material/core";
import {Model} from "../../data/model.data";
import {Criteria, CRITERIA_LIST} from "../../data/criteria.data";
import {Criteria} from "../../data/criteria.data";
import {Subject} from "rxjs";
import {RatingParam} from "../../data/rating.data";
import { MatCheckboxModule } from '@angular/material/checkbox';
import {PromptCustomizationComponent} from "../../components/edit-prompting-link/prompt-customization.component";
import { RatingService } from '../../services/rating.service';
import { CriteriaService } from '../../services/criteria.service';
import {AddTopicDialogComponent} from "../add-topic-dialog/add-topic-dialog.component";
import {CriteriaDialogComponent} from "../criteria-dialog/criteria-dialog.component";
import { MatIconModule } from '@angular/material/icon';

@Component({
selector: 'app-create-rating-dialog',
standalone: true,
imports: [CommonModule, MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatFormFieldModule, MatInputModule, MatSelectModule, MatOptionModule, MatCheckboxModule],
imports: [CommonModule, MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatFormFieldModule, MatInputModule, MatSelectModule, MatOptionModule, MatCheckboxModule, PromptCustomizationComponent, MatIconModule],
templateUrl: './create-rating-dialog.component.html',
styleUrl: './create-rating-dialog.component.css',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CreateRatingDialogComponent implements OnInit {

public models = Object.values(Model);
public criteria: Criteria[] = CRITERIA_LIST;
public criteria: Criteria[] = [];
public responseModels: Model[] = [];
public responseModelsParam: Model[] = [];
private updatedPrompt: string | undefined;
private readonly dialog = inject(MatDialog);


constructor(private ref: ChangeDetectorRef,
private ratingService: RatingService,
private criteriaService: CriteriaService,
@Inject(MAT_DIALOG_DATA) public data: { responseModels: Model[], ratingInputSelected$: Subject<RatingParam> }) {}

public ngOnInit() {
this.responseModels = [...this.data.responseModels];
this.responseModelsParam = [...this.data.responseModels];
this.criteria = this.criteriaService.getCriteria();
}

public selectRatingParams(ratingModel: Model, criteria: Criteria) {
this.data.ratingInputSelected$.next({criteria, ratingModel, responseModels: this.responseModelsParam})
this.data.ratingInputSelected$.next({criteria, ratingModel, responseModels: this.responseModelsParam, updatedPrompt: this.updatedPrompt})
}

public updateAllCheckbox(checked: boolean) {
Expand Down Expand Up @@ -75,4 +95,20 @@ export class CreateRatingDialogComponent implements OnInit {
return this.responseModelsParam.length < this.responseModels.length && this.responseModelsParam.find(m => m == model) != undefined;
}

public updatePrompt(prompt: string) {
this.updatedPrompt = prompt;
}

public getRatingGenerationPrompt(criteria: Criteria | undefined): string {
return this.ratingService.getPrompt(criteria);
}

public openCriteriaDialog(): void {
this.dialog.open(CriteriaDialogComponent, {
width: '450px',
enterAnimationDuration: '150ms',
exitAnimationDuration: '150ms'
});
}

}
23 changes: 23 additions & 0 deletions src/app/dialog/criteria-dialog/criteria-dialog.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
form {
padding-top: 10px;
min-width: 150px;
max-width: 500px;
width: 100%;
}

mat-form-field {
width: 100%;
}

.add-criteria:hover {
color: cyan;
cursor: pointer;
}

.add-criteria mat-icon {
transform: scale(0.6) translateY(13px);
}

.hidden {
visibility: hidden;
}
32 changes: 32 additions & 0 deletions src/app/dialog/criteria-dialog/criteria-dialog.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<h2 mat-dialog-title>Criteria</h2>
<mat-dialog-content>

<div *ngFor="let c of criteria">
<p>Criteria: {{c.name}}</p>
<small>{{ c.desc }}</small>
<p>&nbsp;</p>
</div>

<div>
<div [ngClass]="{'hidden': !addingCriteria}">
<form>
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput #criteriaName>
</mat-form-field>
<mat-form-field>
<mat-label>Description</mat-label>
<textarea matInput #criteriaDesc></textarea>
</mat-form-field>
</form>
</div>
</div>

</mat-dialog-content>
<mat-dialog-actions>
<button mat-button
[disabled]="addingCriteria && (criteriaName.value.length == 0 || criteriaDesc.value.length == 0)"
(click)="addingCriteria ? addCriteria(criteriaName.value, criteriaDesc.value) : addingCriteria = true"
><mat-icon>add</mat-icon> Add Criteria</button>
<button mat-button mat-dialog-close>Close</button>
</mat-dialog-actions>
23 changes: 23 additions & 0 deletions src/app/dialog/criteria-dialog/criteria-dialog.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CriteriaDialogComponent } from './criteria-dialog.component';

describe('CriteriaDialogComponent', () => {
let component: CriteriaDialogComponent;
let fixture: ComponentFixture<CriteriaDialogComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CriteriaDialogComponent]
})
.compileComponents();

fixture = TestBed.createComponent(CriteriaDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
36 changes: 36 additions & 0 deletions src/app/dialog/criteria-dialog/criteria-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Component, OnInit } from '@angular/core';
import {CommonModule} from "@angular/common";
import {MatButtonModule} from "@angular/material/button";
import {MatDialogActions, MatDialogClose, MatDialogContent, MatDialogTitle} from "@angular/material/dialog";
import {FormsModule} from "@angular/forms";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatInputModule} from "@angular/material/input";
import {MatIconModule} from "@angular/material/icon";
import { CriteriaService } from '../../services/criteria.service';
import { Criteria } from '../../data/criteria.data';

@Component({
selector: 'app-criteria-dialog',
standalone: true,
imports: [CommonModule, MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, FormsModule, MatFormFieldModule, MatInputModule, MatIconModule],
templateUrl: './criteria-dialog.component.html',
styleUrl: './criteria-dialog.component.css'
})
export class CriteriaDialogComponent implements OnInit {

public criteria: Criteria[] = [];
addingCriteria = false;

constructor(private criteriaService: CriteriaService) {}

public ngOnInit() {
this.criteria = this.criteriaService.getCriteria();
}

public addCriteria(name: string, desc: string) {
this.criteriaService.addCriteria(name, desc);
this.addingCriteria = false;
// TODO: clear input fields!
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ mat-tab-group mat-form-field {
width: 100%;
padding-top: 20px;
}

Loading

0 comments on commit c420bf5

Please sign in to comment.