Skip to content

Commit

Permalink
[8.x] [Obs AI Assistant] fix knowledge base installation state (#206130
Browse files Browse the repository at this point in the history
…) (#206777)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Obs AI Assistant] fix knowledge base installation state
(#206130)](#206130)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Sandra
G","email":"neptunian@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-01-15T14:38:07Z","message":"[Obs
AI Assistant] fix knowledge base installation state
(#206130)\n\nResolves
https://github.com/elastic/kibana/issues/205970\r\n\r\nUpdates logic to
account for knowledge base `/setup` no longer polling\r\nfor model
readiness before returning.\r\n\r\n- Currently we only poll `/status` if
user manually installs the\r\nknowledge base. In cases where we auto
installed, such as after\r\nsuccessfully setting up a connector, we
depended on `/setup` to poll\r\ninternally. Since the latter was
removed, we need to always poll\r\n`/status`, otherwise user could
potentially be in the state where\r\n`setup` has finished (considered
installed) but `status` still reports\r\nnot ready and we show the
install message again (see screenshots
in\r\nhttps://github.com//issues/205970)\r\n- Currently if
an install is in progress and user closes the flyout, the\r\nprogress
state is lost. These changes should continue to reflect
the\r\ninstallation progress in the UI.\r\n- Renames variables and adds
comments for easier readability\r\n- adds unit test to component that
handles the install UI
state,\r\n`WelcomeMessageKnowledgeBase`\r\n\r\n---------\r\n\r\nCo-authored-by:
Søren Louv-Jansen
<sorenlouv@gmail.com>","sha":"06526fe928ac98580e6fe02768b3c403184694f1","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","v9.0.0","ci:cloud-deploy","Team:Obs
AI
Assistant","ci:project-deploy-elasticsearch","ci:project-deploy-observability","backport:version","v8.18.0","v8.17.1"],"title":"[Obs
AI Assistant] fix knowledge base installation
state","number":206130,"url":"https://github.com/elastic/kibana/pull/206130","mergeCommit":{"message":"[Obs
AI Assistant] fix knowledge base installation state
(#206130)\n\nResolves
https://github.com/elastic/kibana/issues/205970\r\n\r\nUpdates logic to
account for knowledge base `/setup` no longer polling\r\nfor model
readiness before returning.\r\n\r\n- Currently we only poll `/status` if
user manually installs the\r\nknowledge base. In cases where we auto
installed, such as after\r\nsuccessfully setting up a connector, we
depended on `/setup` to poll\r\ninternally. Since the latter was
removed, we need to always poll\r\n`/status`, otherwise user could
potentially be in the state where\r\n`setup` has finished (considered
installed) but `status` still reports\r\nnot ready and we show the
install message again (see screenshots
in\r\nhttps://github.com//issues/205970)\r\n- Currently if
an install is in progress and user closes the flyout, the\r\nprogress
state is lost. These changes should continue to reflect
the\r\ninstallation progress in the UI.\r\n- Renames variables and adds
comments for easier readability\r\n- adds unit test to component that
handles the install UI
state,\r\n`WelcomeMessageKnowledgeBase`\r\n\r\n---------\r\n\r\nCo-authored-by:
Søren Louv-Jansen
<sorenlouv@gmail.com>","sha":"06526fe928ac98580e6fe02768b3c403184694f1"}},"sourceBranch":"main","suggestedTargetBranches":["8.x","8.17"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/206130","number":206130,"mergeCommit":{"message":"[Obs
AI Assistant] fix knowledge base installation state
(#206130)\n\nResolves
https://github.com/elastic/kibana/issues/205970\r\n\r\nUpdates logic to
account for knowledge base `/setup` no longer polling\r\nfor model
readiness before returning.\r\n\r\n- Currently we only poll `/status` if
user manually installs the\r\nknowledge base. In cases where we auto
installed, such as after\r\nsuccessfully setting up a connector, we
depended on `/setup` to poll\r\ninternally. Since the latter was
removed, we need to always poll\r\n`/status`, otherwise user could
potentially be in the state where\r\n`setup` has finished (considered
installed) but `status` still reports\r\nnot ready and we show the
install message again (see screenshots
in\r\nhttps://github.com//issues/205970)\r\n- Currently if
an install is in progress and user closes the flyout, the\r\nprogress
state is lost. These changes should continue to reflect
the\r\ninstallation progress in the UI.\r\n- Renames variables and adds
comments for easier readability\r\n- adds unit test to component that
handles the install UI
state,\r\n`WelcomeMessageKnowledgeBase`\r\n\r\n---------\r\n\r\nCo-authored-by:
Søren Louv-Jansen
<sorenlouv@gmail.com>","sha":"06526fe928ac98580e6fe02768b3c403184694f1"}},{"branch":"8.x","label":"v8.18.0","branchLabelMappingKey":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.17","label":"v8.17.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Sandra G <neptunian@users.noreply.github.com>
  • Loading branch information
kibanamachine and neptunian authored Jan 15, 2025
1 parent b8ce376 commit dd738e8
Show file tree
Hide file tree
Showing 8 changed files with 373 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export function WelcomeMessage({
connectors={connectors}
onSetupConnectorClick={handleConnectorClick}
/>
{knowledgeBase.status.value?.enabled ? (
{knowledgeBase.status.value?.enabled && connectors.connectors?.length ? (
<WelcomeMessageKnowledgeBase connectors={connectors} knowledgeBase={knowledgeBase} />
) : null}
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { act, render, screen } from '@testing-library/react';

import { WelcomeMessageKnowledgeBase } from './welcome_message_knowledge_base';
import type { UseGenAIConnectorsResult } from '../hooks/use_genai_connectors';
import type { UseKnowledgeBaseResult } from '../hooks/use_knowledge_base';

describe('WelcomeMessageKnowledgeBase', () => {
afterEach(() => {
jest.clearAllMocks();
});
type StatusType = NonNullable<UseKnowledgeBaseResult['status']['value']>;
type EndpointType = StatusType['endpoint'];
const endpoint: EndpointType = {
inference_id: 'obs_ai_assistant_kb_inference',
task_type: 'sparse_embedding',
service: 'elasticsearch',
service_settings: {
num_threads: 1,
model_id: '.elser_model_2',
adaptive_allocations: {
enabled: true,
min_number_of_allocations: 1,
},
},
};
const initKnowledgeBase: UseKnowledgeBaseResult = {
isInstalling: false,
install: jest.fn(),
installError: undefined,
status: {
value: {
ready: false,
enabled: true,
errorMessage: 'error',
},
loading: false,
refresh: jest.fn(),
},
};
const defaultConnectors: UseGenAIConnectorsResult = {
connectors: [
{
id: 'default-connector-id',
actionTypeId: 'action-type-id',
name: 'Default Connector',
isPreconfigured: false,
isDeprecated: false,
isSystemAction: false,
referencedByCount: 0,
},
],
selectedConnector: undefined,
loading: false,
error: undefined,
selectConnector: jest.fn(),
reloadConnectors: jest.fn(),
};
function renderComponent({
knowledgeBase,
connectors,
}: {
knowledgeBase: Partial<UseKnowledgeBaseResult>;
connectors: Partial<UseGenAIConnectorsResult>;
}) {
const mergedKnowledgeBase: UseKnowledgeBaseResult = {
...initKnowledgeBase,
...knowledgeBase,
status: {
...initKnowledgeBase.status,
...knowledgeBase.status,
},
};

return render(
<WelcomeMessageKnowledgeBase
knowledgeBase={mergedKnowledgeBase}
connectors={defaultConnectors}
/>
);
}

it('renders "Setting up Knowledge base" message while inference endpoint is installing', () => {
renderComponent({
knowledgeBase: {
isInstalling: true,
},
connectors: defaultConnectors,
});

expect(
screen.getByText('We are setting up your knowledge base', { exact: false })
).toBeInTheDocument();

expect(screen.getByText('Setting up Knowledge base', { exact: false })).toBeInTheDocument();
});
it('renders "Setting up Knowledge base" message while model is being deployed without deployment or allocation state yet being reported', () => {
renderComponent({
knowledgeBase: {
isInstalling: false,
status: {
value: {
endpoint,
ready: false,
enabled: true,
model_stats: { allocation_count: 0 },
},
loading: false,
refresh: jest.fn(),
},
},
connectors: defaultConnectors,
});
expect(
screen.getByText('We are setting up your knowledge base', { exact: false })
).toBeInTheDocument();
});
it('renders "Setting up Knowledge base" message while model is being deployed and starting', () => {
renderComponent({
knowledgeBase: {
isInstalling: false,
status: {
value: {
endpoint,
ready: false,
enabled: true,
model_stats: {
deployment_state: 'starting',
allocation_state: 'starting',
},
},
loading: false,
refresh: jest.fn(),
},
},
connectors: defaultConnectors,
});

expect(
screen.getByText('We are setting up your knowledge base', { exact: false })
).toBeInTheDocument();
});
it('displays success message after installation and hides it after timeout', async () => {
jest.useFakeTimers();

// Step 1: Initially not installed
const { rerender } = renderComponent({
knowledgeBase: {
isInstalling: true,
},
connectors: defaultConnectors,
});

// Step 2: Now it's ready
await act(async () => {
rerender(
<WelcomeMessageKnowledgeBase
knowledgeBase={{
...initKnowledgeBase,
status: {
...initKnowledgeBase.status,
value: {
ready: true,
enabled: true,
model_stats: { deployment_state: 'started', allocation_state: 'started' },
},
},
}}
connectors={defaultConnectors}
/>
);
});

// the success message should appear
expect(screen.queryByText(/Knowledge base successfully installed/i)).toBeInTheDocument();

// fast-forward until the success message would disappear
await act(async () => {
jest.runOnlyPendingTimers();
});

// now it should be gone
expect(screen.queryByText('Knowledge base successfully installed')).toBeNull();
});

it('renders no install messages when model has been installed and ready', () => {
// component should render nothing in this state (null)
renderComponent({
knowledgeBase: {
isInstalling: false,
status: {
...initKnowledgeBase.status,
value: {
ready: true,
enabled: true,
model_stats: { deployment_state: 'started', allocation_state: 'started' },
},
},
},
connectors: defaultConnectors,
});
expect(screen.queryByText(/We are setting up your knowledge base/i)).not.toBeInTheDocument();
expect(screen.queryByText(/Your Knowledge base hasn't been set up./i)).not.toBeInTheDocument();
});

it('renders knowledge base install and model state inspect when not installing and the inference endpoint installation has an error', () => {
renderComponent({
knowledgeBase: {
isInstalling: false,
installError: new Error('inference endpoint failed to install'),
},
connectors: defaultConnectors,
});
expect(
screen.getByText("Your Knowledge base hasn't been set up", { exact: false })
).toBeInTheDocument();
expect(screen.getByText('Install Knowledge base', { exact: false })).toBeInTheDocument();
expect(screen.getByText('Inspect issues', { exact: false })).toBeInTheDocument();
});

it('renders knowledge base install and model state inspect when not installing and no errors', () => {
// this can happen when you have a preconfigured connector,
// we don't automatically install in this case and just show the same UI as if there was an issue/error
renderComponent({
knowledgeBase: {
isInstalling: false,
},
connectors: defaultConnectors,
});
expect(
screen.getByText("Your Knowledge base hasn't been set up", { exact: false })
).toBeInTheDocument();
expect(screen.getByText('Install Knowledge base', { exact: false })).toBeInTheDocument();
expect(screen.getByText('Inspect issues', { exact: false })).toBeInTheDocument();
});

it('renders knowledge base install and model state inspect when not installing and model is not ready', () => {
// this state can occur if the model is having a deployment problem
renderComponent({
knowledgeBase: {
isInstalling: false,
status: {
...initKnowledgeBase.status,
value: {
ready: false,
enabled: true,
model_stats: { deployment_state: 'failed', allocation_state: 'started' },
},
},
},
connectors: defaultConnectors,
});
expect(
screen.getByText("Your Knowledge base hasn't been set up", { exact: false })
).toBeInTheDocument();
expect(screen.getByText('Install Knowledge base', { exact: false })).toBeInTheDocument();
expect(screen.getByText('Inspect issues', { exact: false })).toBeInTheDocument();
});
});
Loading

0 comments on commit dd738e8

Please sign in to comment.