MME-6 Re-introduce ai infer for recipes upload.
This commit is contained in:
parent
ef49f55598
commit
907c8c34ad
@ -16,6 +16,7 @@ import { from, map, switchMap, tap } from 'rxjs';
|
|||||||
import { Review } from './steps/review/review';
|
import { Review } from './steps/review/review';
|
||||||
import { RecipeEditFormSubmitEvent } from '../../shared/components/recipe-edit-form/RecipeEditFormSubmitEvent';
|
import { RecipeEditFormSubmitEvent } from '../../shared/components/recipe-edit-form/RecipeEditFormSubmitEvent';
|
||||||
import { QueryClient } from '@tanstack/angular-query-experimental';
|
import { QueryClient } from '@tanstack/angular-query-experimental';
|
||||||
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recipe-upload-page',
|
selector: 'app-recipe-upload-page',
|
||||||
@ -37,6 +38,7 @@ export class RecipeUploadPage implements OnInit {
|
|||||||
private readonly activatedRoute = inject(ActivatedRoute);
|
private readonly activatedRoute = inject(ActivatedRoute);
|
||||||
private readonly recipeDraftService = inject(RecipeDraftService);
|
private readonly recipeDraftService = inject(RecipeDraftService);
|
||||||
private readonly queryClient = inject(QueryClient);
|
private readonly queryClient = inject(QueryClient);
|
||||||
|
private readonly toastrService = inject(ToastrService);
|
||||||
|
|
||||||
private isValidStep(step: number): boolean {
|
private isValidStep(step: number): boolean {
|
||||||
if (this.model().draft?.lastInference || this.model().draft?.state === 'INFER') {
|
if (this.model().draft?.lastInference || this.model().draft?.state === 'INFER') {
|
||||||
@ -83,7 +85,7 @@ export class RecipeUploadPage implements OnInit {
|
|||||||
switchStep: boolean | RecipeUploadStep = false,
|
switchStep: boolean | RecipeUploadStep = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.model.set(model);
|
this.model.set(model);
|
||||||
this.includeInfer.set(!!model.draft?.lastInference);
|
this.includeInfer.set(!!model.draft?.lastInference || model.inProgressStep === RecipeUploadStep.INFER);
|
||||||
if (switchStep === true) {
|
if (switchStep === true) {
|
||||||
await this.changeDisplayStep(model.inProgressStep);
|
await this.changeDisplayStep(model.inProgressStep);
|
||||||
} else if (typeof switchStep === 'number') {
|
} else if (typeof switchStep === 'number') {
|
||||||
@ -126,16 +128,30 @@ export class RecipeUploadPage implements OnInit {
|
|||||||
const model = await this.recipeDraftService.createManualDraft();
|
const model = await this.recipeDraftService.createManualDraft();
|
||||||
await this.switchModel(model, true);
|
await this.switchModel(model, true);
|
||||||
} else {
|
} else {
|
||||||
this.model.update((model) => ({
|
await this.switchModel(
|
||||||
...model,
|
{
|
||||||
|
...this.model(),
|
||||||
inputSourceFile: this.sourceFile(),
|
inputSourceFile: this.sourceFile(),
|
||||||
inProgressStep: RecipeUploadStep.INFER,
|
inProgressStep: RecipeUploadStep.INFER,
|
||||||
}));
|
},
|
||||||
await this.changeDisplayStep(RecipeUploadStep.INFER);
|
true,
|
||||||
this.includeInfer.set(true);
|
);
|
||||||
this.recipeDraftService.doInference(this.model()).subscribe((updatedModel) => {
|
this.recipeDraftService
|
||||||
this.model.set(updatedModel);
|
.startInference(this.model())
|
||||||
this.changeDisplayStep(RecipeUploadStep.ENTER_DATA);
|
.pipe(
|
||||||
|
tap((updated) => {
|
||||||
|
this.switchModel(updated, true);
|
||||||
|
}),
|
||||||
|
switchMap((model) => this.recipeDraftService.pollUntilInferenceComplete(model)),
|
||||||
|
)
|
||||||
|
.subscribe({
|
||||||
|
next: (inferredModel) => {
|
||||||
|
this.switchModel(inferredModel, true);
|
||||||
|
},
|
||||||
|
error: (e) => {
|
||||||
|
console.error(e);
|
||||||
|
this.toastrService.error('Error while extracting recipe data');
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { inject, Injectable } from '@angular/core';
|
import { inject, Injectable } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { delay, firstValueFrom, map, Observable, of } from 'rxjs';
|
import { first, firstValueFrom, interval, map, Observable, switchMap, takeWhile } from 'rxjs';
|
||||||
import { RecipeUploadClientModel } from '../client-models/RecipeUploadClientModel';
|
import { RecipeUploadClientModel } from '../client-models/RecipeUploadClientModel';
|
||||||
import { RecipeUploadStep } from '../client-models/RecipeUploadStep';
|
import { RecipeUploadStep } from '../client-models/RecipeUploadStep';
|
||||||
import { RecipeDraftViewModel } from '../models/RecipeDraftView.model';
|
import { RecipeDraftViewModel } from '../models/RecipeDraftView.model';
|
||||||
@ -122,14 +122,42 @@ export class RecipeDraftService {
|
|||||||
return firstValueFrom(this.http.delete<void>(this.endpointService.getUrl('recipeDrafts', [id])));
|
return firstValueFrom(this.http.delete<void>(this.endpointService.getUrl('recipeDrafts', [id])));
|
||||||
}
|
}
|
||||||
|
|
||||||
public doInference(model: RecipeUploadClientModel): Observable<RecipeUploadClientModel> {
|
public startInference(model: RecipeUploadClientModel): Observable<RecipeUploadClientModel> {
|
||||||
return of({
|
const formData = new FormData();
|
||||||
|
formData.set('sourceFile', model.inputSourceFile!);
|
||||||
|
formData.set('sourceFileName', model.inputSourceFile!.name);
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post<WithStringDates<RecipeDraftViewModel>>(this.endpointService.getUrl('recipeDrafts', ['ai']), formData)
|
||||||
|
.pipe(
|
||||||
|
map((rawDraft) => this.hydrateView(rawDraft)),
|
||||||
|
map((draft) => ({
|
||||||
|
...model,
|
||||||
|
inProgressStep: RecipeUploadStep.INFER,
|
||||||
|
draft,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public pollUntilInferenceComplete(
|
||||||
|
model: RecipeUploadClientModel,
|
||||||
|
pollInterval: number = 5000,
|
||||||
|
maxPollCount: number = 12,
|
||||||
|
): Observable<RecipeUploadClientModel> {
|
||||||
|
return interval(pollInterval).pipe(
|
||||||
|
takeWhile((pollCount) => pollCount < maxPollCount),
|
||||||
|
switchMap(() =>
|
||||||
|
this.http.get<WithStringDates<RecipeDraftViewModel>>(
|
||||||
|
this.endpointService.getUrl('recipeDrafts', [model.draft!.id]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
map((rawDraft) => this.hydrateView(rawDraft)),
|
||||||
|
first((draft) => draft.state === 'ENTER_DATA'),
|
||||||
|
map((draft) => ({
|
||||||
|
...model,
|
||||||
inProgressStep: RecipeUploadStep.ENTER_DATA,
|
inProgressStep: RecipeUploadStep.ENTER_DATA,
|
||||||
id: 16,
|
draft,
|
||||||
inferredTitle: 'Some recipe',
|
})),
|
||||||
inferredSlug: 'some-recipe',
|
);
|
||||||
inferredText: 'Some text.',
|
|
||||||
inferredIngredients: [],
|
|
||||||
}).pipe(delay(5_000));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user