Skip to content

Commit

Permalink
feat: copilot input & insight copilot
Browse files Browse the repository at this point in the history
  • Loading branch information
meta-d committed Jan 25, 2024
1 parent bdf50e3 commit e099953
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@
</form>
</div>

<ngm-copilot-input class="w-60"></ngm-copilot-input>
<ngm-copilot-input class="w-60" [suggests]="suggestedPrompts()" (ask)="onAsk($event)"></ngm-copilot-input>
</div>

<div *ngIf="showModel() && entityType()" class="h-60 w-full md:w-1/2 lg:1/3 mx-auto overflow-auto">
Expand Down Expand Up @@ -245,9 +245,9 @@
</mat-option>
</mat-autocomplete>

<pac-copilot-enable *ngIf="copilotNotEnabled$ | async" class="z-[101]">
</pac-copilot-enable>

@if (!copilotEnabled) {
<pac-copilot-enable class="z-[101]"/>
}

<ngm-story-explorer *ngIf="showExplorer()" class="absolute top-0 left-0 w-full h-full z-20"
cdkDropListGroup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ export class InsightComponent {
return this.insightService.error
}

public readonly copilotNotEnabled$ = this.insightService.copilotNotEnabled$
// public readonly copilotNotEnabled$ = this.insightService.copilotNotEnabled$
get copilotEnabled() {
return this.insightService.copilotEnabled
}
readonly models$ = this.insightService.models$
readonly hasCube$ = this.insightService.hasCube$
readonly cubes$ = this.insightService.cubes$
Expand Down Expand Up @@ -195,6 +198,10 @@ export class InsightComponent {
}
}

onAsk(event) {
this.askCopilot(event.prompt)
}

selected(event: MatAutocompleteSelectedEvent) {
this.promptInput.nativeElement.value = event.option.viewValue
this.promptControl.setValue(event.option.viewValue)
Expand Down
11 changes: 7 additions & 4 deletions apps/cloud/src/app/features/home/insight/insight.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { computed, inject, Injectable, signal } from '@angular/core'
import { toObservable, toSignal } from '@angular/core/rxjs-interop'
import { CopilotChatMessageRoleEnum, getFunctionCall } from '@metad/copilot'
import { CopilotChatMessageRoleEnum, CopilotService, getFunctionCall } from '@metad/copilot'
import { NgmDSCoreService } from '@metad/ocap-angular/core'
import { WasmAgentService } from '@metad/ocap-angular/wasm-agent'
import {
Expand All @@ -24,14 +24,14 @@ import { getSemanticModelKey } from '@metad/story/core'
import { calcEntityTypePrompt, nonNullable } from '@metad/core'
import zodToJsonSchema from 'zod-to-json-schema'
import { ChartSchema, SuggestsSchema } from './types'
import { CopilotAPIService, registerModel } from '../../../@core'
import { nanoid } from 'nanoid'
import { registerModel } from '../../../@core'


@Injectable()
export class InsightService {
private modelsService = inject(ModelsService)
private copilotService = inject(CopilotAPIService)
private copilotService = inject(CopilotService)
private dsCoreService = inject(NgmDSCoreService)
private wasmAgent = inject(WasmAgentService)
private readonly translateService = inject(TranslateService)
Expand Down Expand Up @@ -133,7 +133,10 @@ export class InsightService {
]

entityPromptLimit = 10
public readonly copilotNotEnabled$ = this.copilotService.notEnabled$
get copilotEnabled() {
return this.copilotService.enabled
}
// public readonly copilotNotEnabled$ = this.copilotService.notEnabled$
readonly models$ = this.modelsService.getMy()
readonly hasCube$ = this.model$.pipe(map((model) => !!model?.schema?.cubes?.length))
readonly cubes$ = this.model$.pipe(
Expand Down
56 changes: 30 additions & 26 deletions packages/angular/copilot/input/input.component.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
<div class="relative flex-1 w-full rounded-lg p-[2px] from-rose-400 via-fuchsia-500 to-indigo-500"
[class.bg-gradient-to-r]="true"
[class.ngm-background-animate]="answering()"
[class.bg-gradient-to-r]="true"
[class.ngm-background-animate]="answering()"
>
<form class="flex rounded-md px-2 py-1 overflow-hidden bg-white dark:bg-bluegray-700" [formGroup]="formGroup"
(ngSubmit)="onSubmit()"
>
<div class="px-2 left-0 flex items-center">
<div *ngIf="suggesting()" class="pac-insight__suggesting emoji-loader text-base" [matTooltip]=" 'PAC.KEY_WORDS.SuggestingPrompts' | translate: { Default: 'Suggesting prompts' } "></div>
<span *ngIf="!suggesting()" class="font-notoColorEmoji">🤖</span>
</div>
<input #promptInput type="text" id="simple-search" class="border-none outline-none text-gray-900 text-sm block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder=" {{'PAC.KEY_WORDS.Ask' | translate: { Default: 'Ask' } }}..." required
matInput
[matAutocomplete]="auto"
formControlName="prompt"
>
<form class="flex rounded-md px-2 py-1 overflow-hidden bg-white dark:bg-bluegray-700">
<mat-chip-grid #chipGrid>
<div class="px-2 left-0 flex items-center">
<div *ngIf="suggesting()" class="pac-insight__suggesting emoji-loader text-base" [matTooltip]=" 'PAC.KEY_WORDS.SuggestingPrompts' | translate: { Default: 'Suggesting prompts' } "></div>
<span *ngIf="!suggesting()" class="font-notoColorEmoji">🤖</span>
</div>
</mat-chip-grid>
<input #promptInput type="text" id="simple-search" class="border-none outline-none text-gray-900 text-sm block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder=" {{'PAC.KEY_WORDS.Ask' | translate: { Default: 'Ask' } }}..." required
matInput [matAutocomplete]="auto"
[formControl]="promptControl"
>
<div *ngIf="error" class="whitespace-nowrap text-ellipsis overflow-hidden text-red-400"
[matTooltip]="error"
>
{{error}}
</div>
</form>
@if(error) {
<div class="whitespace-nowrap text-ellipsis overflow-hidden text-red-400"
[matTooltip]="error"
>
{{error}}
</div>
}
</form>
</div>

<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)" class="pac-insight__autocomplete ngm-autocomplete-panel ngm-density__cosy">
<mat-option *ngFor="let prompt of suggestedPrompts()" [value]="prompt"
(click)="$event.stopPropagation();$event.preventDefault();">
<span>
{{prompt}}
</span>
<mat-autocomplete #auto="matAutocomplete" class="pac-insight__autocomplete ngm-autocomplete-panel ngm-density__cosy"
hideSingleSelectionIndicator
(optionSelected)="selected($event)" >
@for (prompt of filteredSuggests(); track prompt) {
<mat-option [value]="prompt" (click)="$event.stopPropagation();$event.preventDefault();">
<span [ngmHighlight]="search()" [content]="prompt"></span>
</mat-option>
}
</mat-autocomplete>
34 changes: 30 additions & 4 deletions packages/angular/copilot/input/input.component.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
import { NgFor, NgIf } from '@angular/common'
import { Component, signal } from '@angular/core'
import { FormControl, ReactiveFormsModule } from '@angular/forms'
import { Component, EventEmitter, Input, Output, computed, signal } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'
import { MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'
import { MatChipInputEvent, MatChipsModule } from '@angular/material/chips'
import { MatTooltipModule } from '@angular/material/tooltip'
import { NgmHighlightDirective } from '@metad/ocap-angular/common'
import { TranslateModule } from '@ngx-translate/core'

@Component({
standalone: true,
selector: 'ngm-copilot-input',
templateUrl: './input.component.html',
styleUrl: './input.component.scss',
imports: [NgIf, NgFor, TranslateModule, ReactiveFormsModule, MatTooltipModule, MatChipsModule, MatAutocompleteModule]
imports: [NgIf, NgFor, TranslateModule, ReactiveFormsModule, MatTooltipModule, MatChipsModule, MatAutocompleteModule, NgmHighlightDirective]
})
export class NgmCopilotInputComponent {
@Input() get suggests() {
return this.#suggests()
}
set suggests(value) {
this.#suggests.set(value)
}
readonly #suggests = signal<string[]>([])

@Output() ask = new EventEmitter<{command?: string; prompt: string}>()

answering = signal(false)
suggesting = signal(false)
error = ''
promptControl = new FormControl('')
formGroup = new FormGroup({ prompt: this.promptControl })

suggestedPrompts = signal([])
readonly search = toSignal(this.promptControl.valueChanges, { initialValue: null })

readonly filteredSuggests = computed(() => {
if (this.#suggests()) {
const search = this.search()?.toLowerCase()
return search ? this.#suggests().filter((item) => item.toLowerCase().includes(search)) : this.#suggests().slice()
}
return []
})

/**
* Add an ask prompt
Expand All @@ -43,4 +64,9 @@ export class NgmCopilotInputComponent {
// this.promptInput.nativeElement.value = event.option.viewValue
this.promptControl.setValue(event.option.viewValue)
}

onSubmit() {
this.promptControl.setValue(null)
this.ask.emit({ prompt: this.promptControl.value })
}
}

0 comments on commit e099953

Please sign in to comment.