Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Trained models: Replace download button by extending deploy action #205699

Open
wants to merge 35 commits into
base: main
Choose a base branch
from

Conversation

rbrtj
Copy link
Contributor

@rbrtj rbrtj commented Jan 7, 2025

Summary

  • Removes the download model button by extending the deploy action.
  • The model download begins automatically after clicking Start Deployment.
  • It is possible to queue one deployment while the model is still downloading.
  • Navigating away from the Trained Models page will not interrupt the downloading or deployment process.
  • State column renamed to Model State
  • Responsiveness fix: icons overlap
Screen.Recording.2025-01-14.at.10.23.55.mov

try {
await this.ensureModelIsDownloaded(modelId);

this.addActiveOperation({ modelId, type: 'deploying' });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how do you queue several deployments of the same model?
in the cloud environment, the depoyment process can take minutes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a mistake. Previously user could start only one deployment at a time, made changes to follow the same pattern in:
b9d6c5f

@darnautov
Copy link
Contributor

We should make the Actions column look a bit neater with primary actions. Either increasing the column width or use icons

image

@darnautov
Copy link
Contributor

After the model downloading I see the "Read to deploy" state, while it should move to "Deploying" right after the downloading

image

@darnautov
Copy link
Contributor

At the moment you allow 2 start deployment actions, but not more. Any particular reason for that?

Also, it is possible to queue deployments with the same ID.

same_deployment_id_issue.mov

@darnautov
Copy link
Contributor

When the user deletes a model after starting a download, we should cancel all queued deployment requests:

start_after_delte.mov

);

// Navigation blocker when there are active operations
useUnsavedChangesPrompt({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should allow the user to navigate to another Kibana page, but prompt on closing the Kibana browser tab.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 5acf8dd

this.modelState$.complete();
this.downloadStatus$.complete();
this.stopPolling$.complete();
this.pollingSubscription?.unsubscribe();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems like you already unsubscribe in this.stopPolling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 9856fe7

)
.subscribe({
next: (downloadStatus) => {
const currentItems = this.modelState$.getValue().items;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use withLatestFrom operator instead of static getValue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 9856fe7

this.abortedDownloads.add(modelId);
}

public getModelDownloadState$(modelId: string): Observable<ModelDownloadState | undefined> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find the usage of this method anywhere

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also keep in mind, it returns a new Observable instance on each call. It will not work with useObservable hook as expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a leftover, removed in 173321f

return this.downloadStatus$.getValue()[modelId];
}

private async ensureModelIsDownloaded(modelId: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixing concepts makes it difficult to follow the logic. I would suggest sticking to one, either observables or promises. If you prefer the reactive approach, you should create a queue of model deployments. And this queue should wait for model download completion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor to follow the more reactive pattern done in: 173321f

if (!refresh) return;

// Register callback for expanded rows updates
const removeCallback = trainedModelsService.onFetch((modelItems) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the motivation for registring a callback? Did you consider using an effect that tracks model items?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in: 173321f

},
} = useMlKibana();

const trainedModelsService = useTrainedModelsService();
const isInitialized = trainedModelsService.isInitialized();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a static value and the React component will never get this update. We should either get rid of is altogether or make it part of state (or observable)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in: 27f8d9f

useEffect(() => {
return () => {
if (trainedModelsService) {
trainedModelsService.destroy();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reckon we should only destroy on leave if there are no deployments queued

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5acf8dd

@rbrtj
Copy link
Contributor Author

rbrtj commented Jan 9, 2025

At the moment you allow 2 start deployment actions, but not more. Any particular reason for that?

Also, it is possible to queue deployments with the same ID.

same_deployment_id_issue.mov

Previously only one deployment could be started at a time, fixed in:
b9d6c5f

}

export const useUnsavedChangesPrompt = ({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: This is just a proposal, so it is possible to use useUnsavedChangesPrompt without blocking SPA navigation. If you don't like the implementation, we can separate the relevant part of the hook into our package

@rbrtj rbrtj self-assigned this Jan 14, 2025
@rbrtj rbrtj added release_note:enhancement :ml v9.0.0 Feature:3rd Party Models ML 3rd party models Team:ML Team label for ML (also use :ml) backport:version Backport to applied version labels v8.18.0 labels Jan 14, 2025
@elasticmachine
Copy link
Contributor

Pinging @elastic/ml-ui (:ml)

);
},
onClick: async (item) => {
if (isModelDownloadItem(item) && item.state === MODEL_STATE.NOT_DOWNLOADED) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it a deliberate decision to start downloading the model as soon as the deployment modal is opened? I wonder if we should wait to begin the download until the user clicks the 'Start' button in the deployment modal, otherwise there is no way to cancel the download.

Copy link
Contributor Author

@rbrtj rbrtj Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior is described in: #195593 (comment)
It is possible to cancel the download by hitting 'Delete Model':

Screen.Recording.2025-01-15.at.14.47.59.mov

// Navigation blocker when there are active operations
useUnsavedChangesPrompt({
hasUnsavedChanges: activeOperations.length > 0,
blockSpaNavigation: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, can you add toast notification in to inform the user that a model has finished deploying if they have navigated away from the page?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in: 832418b
I will consult on the toast text after the PR is approved.

Screen.Recording.2025-01-15.at.15.51.51.mov

@peteharverson
Copy link
Contributor

@rbrtj @darnautov do we want to keep the current behavior in the 'Add trained models' flyout, where it just does the download part?

Screenshot 2025-01-15 at 11 54 36

Copy link
Member

@sabarasaba sabarasaba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the new prop for the unsaved changes prop hook, thanks @rbrtj!

@peteharverson
Copy link
Contributor

The UX when you try to deploy a model which is downloaded but not available in the current space could be improved, but this also applies to main so I have raised a separate issue for this - #206834.

Screenshot 2025-01-15 at 17 41 44

text: i18n.translate(
'xpack.ml.trainedModels.modelsList.startSuccessDescription',
{
defaultMessage: 'Deployment for "{modelId}" has been started successfully.',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove been from this message. Or do you know the deployment ID at this point, in which case something like

Deployment .elser_model_2_ingest has started successfully.

Copy link
Contributor

@szabosteve szabosteve Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either

Suggested change
defaultMessage: 'Deployment for "{modelId}" has been started successfully.',
defaultMessage: 'Deployment for "{modelId}" has started successfully.',

or

Suggested change
defaultMessage: 'Deployment for "{modelId}" has been started successfully.',
defaultMessage: '"DeploymentID" has started successfully.',

The second one would be better if possible, so we wouldn't need to distinguish between model and deployment (Deployment for modelID) in the message as it makes the toast harder to skim.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with option 2 in 62b3a61

image

Additionally, the error message has been updated to include the deploymentId instead of the modelId

image

@rbrtj rbrtj requested a review from darnautov January 20, 2025 09:03
@joana-cps
Copy link

Review: Start Deployment Modal

Screenshot 2025-01-20 at 12 06 51

Can we change the text "Downloading" to one of these options?
It's unclear what are we exactly downloading. I know that on the table we have "model state" but here it's unclear.

  1. Use model name (might be too long)
  2. Use "Downloading model"
Screenshot 2025-01-20 at 12 04 16

Minor UI fixes:

  • Download bar size
Screenshot 2025-01-20 at 12 11 07
  • Add divider after download progress bar for visual separation.
Screenshot 2025-01-20 at 12 10 11

@joana-cps
Copy link

joana-cps commented Jan 20, 2025

✅ Design Review
Besides the previous comment, LGTM. Behavious are correct and UI responsiveness was fixed and looks pretty neat 👌

@darnautov
Copy link
Contributor

If you start model download and duplicate the browser's tab, the Start deployment actions is not disabled. We should keep the state in sync across browsers tabs.

image

@rbrtj
Copy link
Contributor Author

rbrtj commented Jan 21, 2025

@joana-cps

  1. Updated the downloading label inside the modal and adjusted the text color in 0a6ff9f
image
  1. Adjusted the download bar size and added a divider in a199de2

  2. Inside the modal, we now display only the ready for deployment or downloading states. Other states, such as deployed, are hidden
    Done in (e651ce4)

@elasticmachine
Copy link
Contributor

elasticmachine commented Jan 21, 2025

💔 Build Failed

Failed CI Steps

History

cc @rbrtj

Copy link
Contributor

@szabosteve szabosteve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI text LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:version Backport to applied version labels Feature:3rd Party Models ML 3rd party models :ml release_note:enhancement Team:ML Team label for ML (also use :ml) v8.18.0 v9.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants