Skip to content

Commit

Permalink
[sc-11352] Improve search statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
operramon committed Jan 9, 2025
1 parent 056c393 commit 7046c36
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 73 deletions.
43 changes: 42 additions & 1 deletion apps/dashboard/src/app/account/metrics.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { inject, Injectable } from '@angular/core';
import { AccountService, BillingService, FeaturesService, Prices, SDKService } from '@flaps/core';
import { catchError, combineLatest, forkJoin, map, Observable, of, shareReplay, switchMap } from 'rxjs';
import { catchError, combineLatest, forkJoin, map, Observable, of, shareReplay, switchMap, take } from 'rxjs';
import { format, getDaysInMonth, isFuture, subDays, subMonths } from 'date-fns';
import { AccountTypes, UsageMetric, UsagePoint, UsageType } from '@nuclia/core';

Expand Down Expand Up @@ -112,6 +112,24 @@ export class MetricsService {
);
}

getSearchCount() {
const now = new Date();
const thirtyDaysAgo = subDays(now, 30);
const twelveMonthsAgo = subMonths(now, 12);
return forkJoin([this.account$.pipe(take(1)), this.sdk.currentKb.pipe(take(1))]).pipe(
switchMap(([account, kb]) =>
forkJoin([
kb.activityMonitor.getSearchMetrics(twelveMonthsAgo.toISOString(), now.toISOString()),
kb.activityMonitor.getSearchMetrics(thirtyDaysAgo.toISOString(), now.toISOString()),
kb.activityMonitor.getSearchMetrics(account.creation_date, now.toISOString()),
]),
),
map(([year, month, sinceCreation]) => {
return { year: year[0], month: month[0], sinceCreation: sinceCreation[0] };
}),
);
}

getUsageCharts(kbId?: string, cumulative = false): Observable<Partial<{ [key in UsageType]: ChartData }>> {
return combineLatest([this.account$, this.period]).pipe(
switchMap(([account, period]) =>
Expand All @@ -131,6 +149,29 @@ export class MetricsService {
);
}

getSearchCharts(): Observable<{ search: ChartData; ask: ChartData }> {
return forkJoin([this.sdk.currentKb.pipe(take(1)), this.period.pipe(take(1))]).pipe(
switchMap(([kb, period]) =>
kb.activityMonitor.getSearchMetrics(period.start.toISOString(), period.end.toISOString(), 'day').pipe(
map((items) => {
return {
search: {
data: items.map((item) => [format(new Date(item.timestamp), 'd/MM'), item.search] as [string, number]),
domain: items.map((item) => format(new Date(item.timestamp), 'd/MM')),
yUnit: 'metrics.units.queries',
},
ask: {
data: items.map((item) => [format(new Date(item.timestamp), 'd/MM'), item.chat] as [string, number]),
domain: items.map((item) => format(new Date(item.timestamp), 'd/MM')),
yUnit: 'metrics.units.queries',
},
};
}),
),
),
);
}

getCumulativeUsageCharts(kbId?: string): Observable<Partial<{ [key in UsageType]: ChartData }>> {
return this.getUsageCharts(kbId, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
<div [style]="'height:' + chartHeight + 'px'"></div>
}
}
@case ('ask') {
@if (askChart; as chart) {
<app-line-chart
[yUnit]="chart.yUnit || '' | translate"
[data]="chart.data"
[xAxisTickOptions]="xAxisTickOptions"
[height]="chartHeight"></app-line-chart>
} @else {
<div [style]="'height:' + chartHeight + 'px'"></div>
}
}
@case ('processing') {
@if (processingChart; as chart) {
<app-line-chart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class UsageChartsComponent {
@Input() tokenChart?: ChartData | null;
@Input() processingChart?: ChartData | null;
@Input() searchChart?: ChartData | null;
@Input() askChart?: ChartData | null;
@Input() currentChart?: OptionModel | null;
@Input({ transform: numberAttribute }) chartHeight?: number;
@Input({ transform: booleanAttribute }) smallContainer = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
[currentChart]="currentChart"
[processingChart]="config.processingChart | async"
[searchChart]="config.searchChart | async"
[askChart]="config.askChart | async"
[tokenChart]="config.tokenChart | async"></app-kb-usage-charts>
</div>
</pa-modal-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { UsageChartsComponent } from './usage-charts.component';
export interface UsageModalConfig {
processingChart: Observable<ChartData>;
searchChart: Observable<ChartData>;
askChart: Observable<ChartData>;
tokenChart: Observable<ChartData>;
currentChart: OptionModel;
chartDropdownOptions: OptionModel[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,6 @@
<div class="title-with-icon">
<pa-icon name="chart"></pa-icon>
{{ 'dashboard-home.usage.title' | translate }}
<small class="body-s">
@if (isSubscribed | async) {
({{ 'kb.metrics.period.current-billing-period' | translate }})
} @else {
({{ 'kb.metrics.period.current-month' | translate }})
}
</small>
</div>
<pa-button
aspect="basic"
Expand All @@ -333,25 +326,36 @@
@if (searchQueriesCounts | async; as queriesCount) {
<pa-table-row last>
<pa-table-cell>
<div class="cell-with-icon">
<span class="body-s">
{{ 'metrics.search.title' | translate }}
<span class="body-s">{{ 'metrics.search.title' | translate }}</span>
</pa-table-cell>
@if (locale | async; as locale) {
<pa-table-cell>
<span class="title-xxs">
{{ queriesCount.month.search | number: '1.0-0' : locale }}
</span>
<pa-icon
[paPopover]="searchQueriesLegend"
size="small"
name="info"></pa-icon>
</div>
</pa-table-cell>
<pa-table-cell>
<span class="title-xxs">
{{ queriesCount.year.search | number: '1.0-0' : locale }}
</span>
</pa-table-cell>
}
</pa-table-row>
}
@if (searchQueriesCounts | async; as queriesCount) {
<pa-table-row last>
<pa-table-cell>
<span class="body-s">{{ 'metrics.ask.title' | translate }}</span>
</pa-table-cell>
@if (locale | async; as locale) {
<pa-table-cell>
<span class="title-xxs">
{{ queriesCount.month | number: '1.0-0' : locale }}
{{ queriesCount.month.chat | number: '1.0-0' : locale }}
</span>
</pa-table-cell>
<pa-table-cell>
<span class="title-xxs">
{{ queriesCount.year | number: '1.0-0' : locale }}
{{ queriesCount.year.chat | number: '1.0-0' : locale }}
</span>
</pa-table-cell>
}
Expand All @@ -377,17 +381,23 @@
</pa-table-row>
}
</pa-table>
<pa-popover #searchQueriesLegend>
{{ 'dashboard-home.usage.search-queries-explanation' | translate }}
</pa-popover>

<div>
<nsi-dropdown-button
fullWidth
aspect="basic"
[popupRef]="chartDropdown"
[open]="isChartDropdownOpen">
{{ currentChart.label | translate }}
<span class="title-with-icon">
{{ currentChart.label | translate }}
<span class="body-s period">
@if (isSubscribed | async) {
({{ 'kb.metrics.period.current-billing-period' | translate }})
} @else {
({{ 'kb.metrics.period.current-month' | translate }})
}
</span>
</span>
</nsi-dropdown-button>

<pa-dropdown
Expand All @@ -410,7 +420,8 @@
[currentChart]="currentChart"
[processingChart]="processingChart | async"
[tokenChart]="nucliaTokenChart | async"
[searchChart]="searchChart | async"></app-kb-usage-charts>
[searchChart]="searchChart | async"
[askChart]="askChart | async"></app-kb-usage-charts>
</nsi-home-container>
}

Expand All @@ -421,7 +432,7 @@
<div class="title-with-icon title-m">
<pa-icon name="heart"></pa-icon>
{{ 'dashboard-home.health-status.title' | translate }}
<small class="body-s">({{ 'kb.metrics.period.last-7d' | translate }})</small>
<small class="body-s period">({{ 'kb.metrics.period.last-7d' | translate }})</small>
</div>
<a
class="accent-link"
Expand All @@ -438,6 +449,6 @@
}
</div>

@if ((searchQueriesCounts | async)?.year; as yearCount) {
<app-knowledge-box-survey [totalSearch]="yearCount"></app-knowledge-box-survey>
@if ((searchQueriesCounts | async)?.sinceCreation; as sinceCreation) {
<app-knowledge-box-survey [totalSearch]="sinceCreation.search + sinceCreation.chat"></app-knowledge-box-survey>
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,13 @@
}
}

.cell-with-icon {
align-items: center;
display: flex;
gap: rhythm(0.5);

pa-icon {
cursor: pointer;
}
}
.title-with-icon {
align-items: center;
display: flex;
gap: rhythm(1);
overflow-wrap: anywhere;

.body-s {
color: $color-neutral-regular;
}
}

.cell-with-icon,
.title-with-icon {
pa-icon {
display: flex;
Expand Down Expand Up @@ -157,4 +143,8 @@
margin-bottom: rhythm(1);
}
}

.period {
color: $color-neutral-regular;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,34 @@ export class KnowledgeBoxHomeComponent implements OnInit, OnDestroy {
switchMap(() => this.currentKb),
switchMap((kb) => this.metrics.getUsageCharts(kb.id)),
takeUntil(this.unsubscribeAll),
shareReplay(),
shareReplay(1),
);
processingChart = this.allChartsData.pipe(map((charts) => charts[UsageType.SLOW_PROCESSING_TIME]));
searchChart = this.allChartsData.pipe(map((charts) => charts[UsageType.SEARCHES_PERFORMED]));
nucliaTokenChart = this.allChartsData.pipe(map((charts) => charts[UsageType.NUCLIA_TOKENS]));

searchQueriesCounts = this.isAccountManager.pipe(
searchChartsData = this.isAccountManager.pipe(
filter((isManager) => isManager),
switchMap(() => this.currentKb),
switchMap((kb) => this.metrics.getUsageCount(UsageType.SEARCHES_PERFORMED, kb.id)),
switchMap(() => this.metrics.getSearchCharts()),
takeUntil(this.unsubscribeAll),
shareReplay(),
shareReplay(1),
);
searchChart = this.searchChartsData.pipe(map((charts) => charts.search));
askChart = this.searchChartsData.pipe(map((charts) => charts.ask));

nucliaTokensCounts = this.isAccountManager.pipe(
filter((isManager) => isManager),
switchMap(() => this.currentKb),
switchMap((kb) => this.metrics.getUsageCount(UsageType.NUCLIA_TOKENS, kb.id)),
takeUntil(this.unsubscribeAll),
shareReplay(),
shareReplay(1),
);
searchQueriesCounts = this.isAccountManager.pipe(
filter((isManager) => isManager),
switchMap(() => this.currentKb),
switchMap(() => this.metrics.getSearchCount()),
takeUntil(this.unsubscribeAll),
shareReplay(1),
);
isSubscribed = this.metrics.isSubscribed;

Expand Down Expand Up @@ -117,6 +126,7 @@ export class KnowledgeBoxHomeComponent implements OnInit, OnDestroy {
currentChart: OptionModel = this.defaultChartOption;
chartDropdownOptions: OptionModel[] = [
this.defaultChartOption,
new OptionModel({ id: 'ask', label: 'metrics.ask.title', value: 'ask' }),
new OptionModel({ id: 'processing', label: 'metrics.processing.title', value: 'processing' }),
new OptionModel({ id: 'token', label: 'metrics.nuclia-tokens.title', value: 'token' }),
];
Expand Down Expand Up @@ -204,6 +214,7 @@ export class KnowledgeBoxHomeComponent implements OnInit, OnDestroy {
data: {
processingChart: this.processingChart,
searchChart: this.searchChart,
askChart: this.askChart,
tokenChart: this.nucliaTokenChart,
currentChart: this.currentChart,
chartDropdownOptions: this.chartDropdownOptions,
Expand Down
51 changes: 28 additions & 23 deletions libs/common/common.babel
Original file line number Diff line number Diff line change
Expand Up @@ -8064,29 +8064,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>search-queries-explanation</name>
<description/>
<comment/>
<translations>
<translation>
<language>ca-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>title</name>
<description/>
Expand Down Expand Up @@ -16620,6 +16597,34 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>ask</name>
<children>
<concept_node>
<name>title</name>
<description/>
<comment/>
<translations>
<translation>
<language>ca-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>legend</name>
<children>
Expand Down
2 changes: 1 addition & 1 deletion libs/common/src/assets/i18n/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@
"dashboard-home.upload-block.description-desktop": " o trieu una font per treballar amb Nuclia amb la vostra pròpia base de dades.",
"dashboard-home.upload-block.title": "Treballa amb les teves dades",
"dashboard-home.usage.fullscreen": "Mostra el gràfic a pantalla completa",
"dashboard-home.usage.search-queries-explanation": "El recompte de consultes de cerca es refereix a totes les cerques realitzades al Knowledge Box, incloses (però no limitades a) les respostes generatives.",
"dashboard-home.usage.title": "Ús",
"dataset.delete": "Suprimeix la mostra",
"dataset.delete_failed": "No s’ha pogut suprimir el conjunt de dades de mostra",
Expand Down Expand Up @@ -690,6 +689,7 @@
"language.sv": "Suec",
"language.tr": "Turc",
"metrics.answers.title": "Respostes generatives",
"metrics.ask.title": "Respostes generatives",
"metrics.legend.average": "Puntuació mitjana",
"metrics.legend.min-max-range": "Interval entre les puntuacions mínimes i màximes",
"metrics.nuclia-tokens.title": "Nuclia tokens",
Expand Down
Loading

0 comments on commit 7046c36

Please sign in to comment.