Skip to content

Commit 8e937d4

Browse files
feat(assistant): changed default model to 4o && vision support (images)
1 parent ce390cf commit 8e937d4

30 files changed

+373
-52
lines changed

apps/api/src/app/chat/chat.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const assistantParams: AssistantCreateParams = {
66
name: '@boldare/openai-assistant',
77
instructions: `You are a chatbot assistant. Use the general knowledge to answer questions. Speak briefly and clearly.`,
88
tools: [{ type: 'code_interpreter' }, { type: 'file_search' }],
9-
model: 'gpt-4-turbo',
9+
model: 'gpt-4o',
1010
temperature: 0.05,
1111
};
1212

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
@if (isAudioEnabled && message) {
2-
<span class="chat-audio" [ngClass]="'chat-audio--' + message.role">
3-
@if(!isStarted) {
4-
<mat-icon (click)="speech()">play_circle</mat-icon>
5-
} @else {
6-
<mat-icon (click)="pause()">pause_circle</mat-icon>
7-
}
8-
</span>
1+
@if (getMessageText) {
2+
<span class="chat-audio" [ngClass]="'chat-audio--' + message.role">
3+
@if (!isStarted) {
4+
<mat-icon (click)="speech()">play_circle</mat-icon>
5+
} @else {
6+
<mat-icon (click)="pause()">pause_circle</mat-icon>
7+
}
8+
</span>
99
}

apps/spa/src/app/components/chat/chat-audio/chat-audio.component.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { Component, Input, OnInit } from '@angular/core';
2+
import { MatIconModule } from '@angular/material/icon';
3+
import { delay } from 'rxjs';
4+
import { ChatAudioResponse, PostSpeechDto } from '@boldare/openai-assistant';
5+
import { NgClass } from '@angular/common';
6+
import { getMessageText } from '../../controls/message-content/message-content.helpers';
27
import { ChatClientService } from '../../../modules/+chat/shared/chat-client.service';
38
import {
49
ChatMessage,
510
SpeechVoice,
611
} from '../../../modules/+chat/shared/chat.model';
712
import { environment } from '../../../../environments/environment';
8-
import { MatIconModule } from '@angular/material/icon';
9-
import { delay } from 'rxjs';
10-
import { ChatAudioResponse, PostSpeechDto } from '@boldare/openai-assistant';
11-
import { NgClass } from '@angular/common';
1213

1314
@Component({
1415
selector: 'ai-chat-audio',
@@ -19,10 +20,17 @@ import { NgClass } from '@angular/common';
1920
})
2021
export class ChatAudioComponent implements OnInit {
2122
@Input() message!: ChatMessage;
22-
isAudioEnabled = environment.isAudioEnabled;
2323
isStarted = false;
2424
audio = new Audio();
2525

26+
get getMessageText(): string {
27+
if (!environment.isAudioEnabled || !this.message) {
28+
return '';
29+
}
30+
31+
return getMessageText(this.message);
32+
}
33+
2634
constructor(private readonly chatService: ChatClientService) {}
2735

2836
ngOnInit(): void {
@@ -42,6 +50,10 @@ export class ChatAudioComponent implements OnInit {
4250
}
4351

4452
speech(): void {
53+
if (!this.getMessageText) {
54+
return;
55+
}
56+
4557
this.isStarted = true;
4658

4759
if (this.audio.src) {
@@ -50,7 +62,7 @@ export class ChatAudioComponent implements OnInit {
5062
}
5163

5264
const payload: PostSpeechDto = {
53-
content: this.message.content,
65+
content: getMessageText(this.message),
5466
voice: SpeechVoice.Onyx,
5567
};
5668

apps/spa/src/app/components/chat/chat-footer/chat-footer.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
[matTooltip]="!isDisabled ? 'Add files' : ''"
1212
[isDisabled]="isDisabled" />
1313
}
14+
@if (isImageContentEnabled) {
15+
<ai-message-content
16+
[matTooltip]="!isDisabled ? 'Add images' : ''"
17+
[isDisabled]="isDisabled" />
18+
}
1419
</ai-controls>
1520

1621
<ai-input

apps/spa/src/app/components/chat/chat-footer/chat-footer.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
RecorderComponent,
88
} from '../../controls';
99
import { MatTooltip } from '@angular/material/tooltip';
10+
import { MessageContentComponent } from '../../controls/message-content/message-content.component';
1011

1112
@Component({
1213
selector: 'ai-chat-footer',
@@ -20,6 +21,7 @@ import { MatTooltip } from '@angular/material/tooltip';
2021
RecorderComponent,
2122
FilesComponent,
2223
MatTooltip,
24+
MessageContentComponent,
2325
],
2426
})
2527
export class ChatFooterComponent {
@@ -28,4 +30,5 @@ export class ChatFooterComponent {
2830
@Input() isDisabled = false;
2931
@Input() isTranscriptionEnabled = false;
3032
@Input() isAttachmentEnabled = false;
33+
@Input() isImageContentEnabled = false;
3134
}
Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
@if (message) { @if (message.role === 'assistant') {
2-
<ai-chat-avatar></ai-chat-avatar>
3-
}
1+
@if (message) {
2+
@if (message.role === 'assistant') {
3+
<ai-chat-avatar></ai-chat-avatar>
4+
}
45

5-
<div class="chat-message">
6-
<span markdown [data]="message.content"></span>
6+
<div class="chat-message">
7+
@if (messageText) {
8+
<span markdown [data]="messageText"></span>
9+
}
710

8-
@if (message.role !== chatRole.System) {
9-
<ai-chat-audio [message]="message"></ai-chat-audio>
10-
}
11-
</div>
11+
@if (message.role !== chatRole.System) {
12+
<ai-chat-audio [message]="message"></ai-chat-audio>
13+
}
14+
15+
@if (messageImage.length) {
16+
<div class="chat-message__file">
17+
@for (image of messageImage; track messageImage) {
18+
<div>File ID: {{ image.image_file.file_id }}</div>
19+
}
20+
</div>
21+
}
22+
</div>
1223
}

apps/spa/src/app/components/chat/chat-message/chat-message.component.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,10 @@
4646
max-width: 80%;
4747
z-index: 1;
4848
}
49+
50+
.chat-message__file {
51+
border-top: 1px dashed rgba(0, 0, 0, 0.4);
52+
margin-top: $size-2;
53+
padding-top: $size-2;
54+
font-size: 11px;
55+
}

apps/spa/src/app/components/chat/chat-message/chat-message.component.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import { MarkdownComponent } from 'ngx-markdown';
77
import { ChatAudioComponent } from '../chat-audio/chat-audio.component';
88
import { NgClass } from '@angular/common';
99
import { ChatAvatarComponent } from '../chat-avatar/chat-avatar.component';
10+
import {
11+
getMessageImage,
12+
getMessageText,
13+
} from '../../controls/message-content/message-content.helpers';
14+
import { ImageFileContentBlock } from 'openai/resources/beta/threads';
1015

1116
@Component({
1217
selector: 'ai-chat-message',
@@ -25,6 +30,14 @@ export class ChatMessageComponent {
2530
@Input() class = '';
2631
chatRole = ChatRole;
2732

33+
get messageText(): string {
34+
return getMessageText(this.message);
35+
}
36+
37+
get messageImage(): ImageFileContentBlock[] {
38+
return getMessageImage(this.message);
39+
}
40+
2841
@HostBinding('class') get getClasses(): string {
2942
return `${this.class} is-${this.message?.role || 'none'}`;
3043
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<div class="messages">
22
@for (message of initialMessages.concat(messages); track message) {
33
<span #item>
4-
<ai-chat-message [message]="message"></ai-chat-message>
5-
</span>
4+
<ai-chat-message [message]="message"></ai-chat-message>
5+
</span>
66
} @empty {
7-
<ai-chat-tips [tips]="tips" (tipSelected$)="tipSelected$.emit($event)" />
7+
<ai-chat-tips [tips]="tips" (tipSelected$)="tipSelected$.emit($event)" />
88
}
99
<ai-chat-typing [isTyping]="isTyping"></ai-chat-typing>
1010
</div>

apps/spa/src/app/components/controls/files/files.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, Input, ViewChild } from '@angular/core';
1+
import { Component, ElementRef, Input, ViewChild } from '@angular/core';
22
import { MatIcon } from '@angular/material/icon';
33
import { AiFilesDirective } from './files.directive';
44
import { toSignal } from '@angular/core/rxjs-interop';
@@ -19,7 +19,7 @@ import { ControlIconComponent } from '../control-icon/control-icon.component';
1919
styleUrl: './files.component.scss',
2020
})
2121
export class FilesComponent {
22-
@ViewChild('input') input!: HTMLInputElement;
22+
@ViewChild('input') input!: ElementRef<HTMLInputElement>;
2323
@Input() isDisabled = false;
2424
files = toSignal(this.fileService.files$, { initialValue: [] });
2525

@@ -37,7 +37,8 @@ export class FilesComponent {
3737
clear(event: Event): void {
3838
event.preventDefault();
3939
event.stopPropagation();
40-
this.input.files = null;
40+
this.input.nativeElement.files = null;
41+
this.input.nativeElement.value = '';
4142
this.fileService.clear();
4243
}
4344
}

0 commit comments

Comments
 (0)