Skip to content

Commit

Permalink
[AI Assistant] Add assistant to Serverless Search (#196832)
Browse files Browse the repository at this point in the history
## Summary

This adds the AI assistant to Serverless Elasticsearch. It also disables
the knowledge base, and disables a few config values we don't want users
to be able to set in that context.

---------

Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Elena Shostak <[email protected]>
  • Loading branch information
3 people authored Oct 25, 2024
1 parent 27a98aa commit 3bc5e2d
Show file tree
Hide file tree
Showing 50 changed files with 639 additions and 349 deletions.
13 changes: 12 additions & 1 deletion config/serverless.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ xpack.observability.enabled: false
xpack.securitySolution.enabled: false
xpack.serverless.observability.enabled: false
enterpriseSearch.enabled: false
xpack.observabilityAIAssistant.enabled: false
xpack.osquery.enabled: false

# Enable fleet on search projects for agentless features
Expand Down Expand Up @@ -120,4 +119,16 @@ xpack.searchInferenceEndpoints.ui.enabled: false
xpack.search.notebooks.catalog.url: https://elastic-enterprise-search.s3.us-east-2.amazonaws.com/serverless/catalog.json

# Semantic text UI

xpack.index_management.dev.enableSemanticText: true

# AI Assistant config
xpack.observabilityAIAssistant.enabled: true
xpack.searchAssistant.enabled: true
xpack.searchAssistant.ui.enabled: true
xpack.observabilityAIAssistant.scope: "search"
xpack.observabilityAIAssistant.enableKnowledgeBase: false
aiAssistantManagementSelection.preferredAIAssistantType: "observability"
xpack.observabilityAiAssistantManagement.logSourcesEnabled: false
xpack.observabilityAiAssistantManagement.spacesEnabled: false
xpack.observabilityAiAssistantManagement.visibilityEnabled: false
1 change: 1 addition & 0 deletions config/serverless.oblt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ xpack.apm.featureFlags.storageExplorerAvailable: false

## Set the AI Assistant type
aiAssistantManagementSelection.preferredAIAssistantType: "observability"
xpack.observabilityAIAssistant.scope: "observability"

# Specify in telemetry the project type
telemetry.labels.serverless: observability
Expand Down
3 changes: 3 additions & 0 deletions test/plugin_functional/test_suites/core_plugins/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.observability_onboarding.ui.enabled (boolean?)',
'xpack.observabilityLogsExplorer.navigation.showAppLink (boolean?|never)',
'xpack.observabilityAIAssistant.scope (observability?|search?)',
'xpack.observabilityAiAssistantManagement.logSourcesEnabled (boolean?)',
'xpack.observabilityAiAssistantManagement.spacesEnabled (boolean?)',
'xpack.observabilityAiAssistantManagement.visibilityEnabled (boolean?)',
'share.new_version.enabled (boolean?)',
'aiAssistantManagementSelection.preferredAIAssistantType (default?|never?|observability?)',
/**
Expand Down
24 changes: 15 additions & 9 deletions x-pack/packages/kbn-ai-assistant/src/chat/chat_actions_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { ConnectorSelectorBase } from '@kbn/observability-ai-assistant-plugin/public';
import type { UseGenAIConnectorsResult } from '../hooks/use_genai_connectors';
import { useKibana } from '../hooks/use_kibana';
import { useKnowledgeBase } from '../hooks';

export function ChatActionsMenu({
connectors,
Expand All @@ -31,6 +32,7 @@ export function ChatActionsMenu({
onCopyConversationClick: () => void;
}) {
const { application, http } = useKibana().services;
const knowledgeBase = useKnowledgeBase();
const [isOpen, setIsOpen] = useState(false);

const handleNavigateToConnectors = () => {
Expand Down Expand Up @@ -91,15 +93,19 @@ export function ChatActionsMenu({
defaultMessage: 'Actions',
}),
items: [
{
name: i18n.translate('xpack.aiAssistant.chatHeader.actions.knowledgeBase', {
defaultMessage: 'Manage knowledge base',
}),
onClick: () => {
toggleActionsMenu();
handleNavigateToSettingsKnowledgeBase();
},
},
...(knowledgeBase?.status.value?.enabled
? [
{
name: i18n.translate('xpack.aiAssistant.chatHeader.actions.knowledgeBase', {
defaultMessage: 'Manage knowledge base',
}),
onClick: () => {
toggleActionsMenu();
handleNavigateToSettingsKnowledgeBase();
},
},
]
: []),
{
name: i18n.translate('xpack.aiAssistant.chatHeader.actions.settings', {
defaultMessage: 'AI Assistant Settings',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const defaultProps: ComponentStoryObj<typeof Component> = {
loading: false,
value: {
ready: true,
enabled: true,
},
refresh: () => {},
},
Expand Down
2 changes: 1 addition & 1 deletion x-pack/packages/kbn-ai-assistant/src/chat/chat_body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export function ChatBody({
showLinkToConversationsApp: boolean;
onConversationUpdate: (conversation: { conversation: Conversation['conversation'] }) => void;
onToggleFlyoutPositionMode?: (flyoutPositionMode: FlyoutPositionMode) => void;
navigateToConversation: (conversationId?: string) => void;
navigateToConversation?: (conversationId?: string) => void;
}) {
const license = useLicense();
const hasCorrectLicense = license?.hasAtLeast('enterprise');
Expand Down
14 changes: 9 additions & 5 deletions x-pack/packages/kbn-ai-assistant/src/chat/chat_flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function ChatFlyout({
initialFlyoutPositionMode?: FlyoutPositionMode;
isOpen: boolean;
onClose: () => void;
navigateToConversation(conversationId?: string): void;
navigateToConversation?: (conversationId?: string) => void;
}) {
const { euiTheme } = useEuiTheme();
const breakpoint = useCurrentEuiBreakpoint();
Expand Down Expand Up @@ -272,10 +272,14 @@ export function ChatFlyout({
conversationList.conversations.refresh();
}}
onToggleFlyoutPositionMode={handleToggleFlyoutPositionMode}
navigateToConversation={(newConversationId?: string) => {
if (onClose) onClose();
navigateToConversation(newConversationId);
}}
navigateToConversation={
navigateToConversation
? (newConversationId?: string) => {
if (onClose) onClose();
navigateToConversation(newConversationId);
}
: undefined
}
/>
</EuiFlexItem>

Expand Down
49 changes: 25 additions & 24 deletions x-pack/packages/kbn-ai-assistant/src/chat/chat_header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function ChatHeader({
onCopyConversation: () => void;
onSaveTitle: (title: string) => void;
onToggleFlyoutPositionMode?: (newFlyoutPositionMode: FlyoutPositionMode) => void;
navigateToConversation: (nextConversationId?: string) => void;
navigateToConversation?: (nextConversationId?: string) => void;
}) {
const theme = useEuiTheme();
const breakpoint = useCurrentEuiBreakpoint();
Expand Down Expand Up @@ -164,31 +164,32 @@ export function ChatHeader({
}
/>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiPopover
anchorPosition="downLeft"
button={
<EuiToolTip
content={i18n.translate(
'xpack.aiAssistant.chatHeader.euiToolTip.navigateToConversationsLabel',
{ defaultMessage: 'Navigate to conversations' }
)}
display="block"
>
<EuiButtonIcon
aria-label={i18n.translate(
'xpack.aiAssistant.chatHeader.euiButtonIcon.navigateToConversationsLabel',
{navigateToConversation ? (
<EuiFlexItem grow={false}>
<EuiPopover
anchorPosition="downLeft"
button={
<EuiToolTip
content={i18n.translate(
'xpack.aiAssistant.chatHeader.euiToolTip.navigateToConversationsLabel',
{ defaultMessage: 'Navigate to conversations' }
)}
data-test-subj="observabilityAiAssistantChatHeaderButton"
iconType="discuss"
onClick={() => navigateToConversation(conversationId)}
/>
</EuiToolTip>
}
/>
</EuiFlexItem>
display="block"
>
<EuiButtonIcon
aria-label={i18n.translate(
'xpack.aiAssistant.chatHeader.euiButtonIcon.navigateToConversationsLabel',
{ defaultMessage: 'Navigate to conversations' }
)}
data-test-subj="observabilityAiAssistantChatHeaderButton"
iconType="discuss"
onClick={() => navigateToConversation(conversationId)}
/>
</EuiToolTip>
}
/>
</EuiFlexItem>
) : null}
</>
) : null}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const defaultProps: ComponentProps<typeof Component> = {
loading: false,
value: {
ready: true,
enabled: true,
},
refresh: () => {},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const defaultProps: ComponentStoryObj<typeof Component> = {
loading: false,
value: {
ready: false,
enabled: true,
},
refresh: () => {},
},
Expand All @@ -43,12 +44,15 @@ export const Loading: ComponentStoryObj<typeof Component> = merge({}, defaultPro
});

export const NotInstalled: ComponentStoryObj<typeof Component> = merge({}, defaultProps, {
args: { knowledgeBase: { status: { loading: false, value: { ready: false } } } },
args: { knowledgeBase: { status: { loading: false, value: { ready: false, enabled: true } } } },
});

export const Installing: ComponentStoryObj<typeof Component> = merge({}, defaultProps, {
args: {
knowledgeBase: { status: { loading: false, value: { ready: false } }, isInstalling: true },
knowledgeBase: {
status: { loading: false, value: { ready: false, enabled: true } },
isInstalling: true,
},
},
});

Expand All @@ -57,7 +61,7 @@ export const InstallError: ComponentStoryObj<typeof Component> = merge({}, defau
knowledgeBase: {
status: {
loading: false,
value: { ready: false },
value: { ready: false, enabled: true },
},
isInstalling: false,
installError: new Error(),
Expand All @@ -66,5 +70,5 @@ export const InstallError: ComponentStoryObj<typeof Component> = merge({}, defau
});

export const Installed: ComponentStoryObj<typeof Component> = merge({}, defaultProps, {
args: { knowledgeBase: { status: { loading: false, value: { ready: true } } } },
args: { knowledgeBase: { status: { loading: false, value: { ready: true, enabled: true } } } },
});
5 changes: 3 additions & 2 deletions x-pack/packages/kbn-ai-assistant/src/chat/welcome_message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ export function WelcomeMessage({
connectors={connectors}
onSetupConnectorClick={handleConnectorClick}
/>

<WelcomeMessageKnowledgeBase connectors={connectors} knowledgeBase={knowledgeBase} />
{knowledgeBase.status.value?.enabled ? (
<WelcomeMessageKnowledgeBase connectors={connectors} knowledgeBase={knowledgeBase} />
) : null}
</EuiFlexItem>

<EuiFlexItem grow={false}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const SECOND_SLOT_CONTAINER_WIDTH = 400;

interface ConversationViewProps {
conversationId?: string;
navigateToConversation: (nextConversationId?: string) => void;
navigateToConversation?: (nextConversationId?: string) => void;
getConversationHref?: (conversationId: string) => string;
newConversationHref?: string;
scopes?: AssistantScope[];
Expand Down Expand Up @@ -81,7 +81,9 @@ export const ConversationView: React.FC<ConversationViewProps> = ({
const handleConversationUpdate = (conversation: { conversation: { id: string } }) => {
if (!conversationId) {
updateConversationIdInPlace(conversation.conversation.id);
navigateToConversation(conversation.conversation.id);
if (navigateToConversation) {
navigateToConversation(conversation.conversation.id);
}
}
handleRefreshConversations();
};
Expand Down Expand Up @@ -143,7 +145,7 @@ export const ConversationView: React.FC<ConversationViewProps> = ({
isLoading={conversationList.isLoading}
onConversationDeleteClick={(deletedConversationId) => {
conversationList.deleteConversation(deletedConversationId).then(() => {
if (deletedConversationId === conversationId) {
if (deletedConversationId === conversationId && navigateToConversation) {
navigateToConversation(undefined);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function useKnowledgeBase(): UseKnowledgeBaseResult {
error: undefined,
value: {
ready: true,
enabled: true,
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useAIAssistantAppService } from './use_ai_assistant_app_service';
export interface UseKnowledgeBaseResult {
status: AbortableAsyncState<{
ready: boolean;
enabled: boolean;
error?: any;
deployment_state?: MlDeploymentState;
allocation_state?: MlDeploymentAllocationState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const config = schema.object({
enabled: schema.boolean({ defaultValue: true }),
modelId: schema.maybe(schema.string()),
scope: schema.maybe(schema.oneOf([schema.literal('observability'), schema.literal('search')])),
enableKnowledgeBase: schema.boolean({ defaultValue: true }),
});

export type ObservabilityAIAssistantConfig = TypeOf<typeof config>;
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,14 @@ export class ObservabilityAIAssistantPlugin
core,
taskManager: plugins.taskManager,
getModelId,
enableKnowledgeBase: this.config.enableKnowledgeBase,
}));

service.register(registerFunctions);

addLensDocsToKb({ service, logger: this.logger.get('kb').get('lens') });
if (this.config.enableKnowledgeBase) {
addLensDocsToKb({ service, logger: this.logger.get('kb').get('lens') });
}

registerServerRoutes({
core,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const getKnowledgeBaseStatus = createObservabilityAIAssistantServerRoute({
handler: async (
resources
): Promise<{
enabled: boolean;
ready: boolean;
error?: any;
deployment_state?: MlDeploymentState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,14 +707,16 @@ export class ObservabilityAIAssistantClient {
queries: Array<{ text: string; boost?: number }>;
categories?: string[];
}): Promise<{ entries: RecalledEntry[] }> => {
return this.dependencies.knowledgeBaseService.recall({
namespace: this.dependencies.namespace,
user: this.dependencies.user,
queries,
categories,
esClient: this.dependencies.esClient,
uiSettingsClient: this.dependencies.uiSettingsClient,
});
return (
this.dependencies.knowledgeBaseService?.recall({
namespace: this.dependencies.namespace,
user: this.dependencies.user,
queries,
categories,
esClient: this.dependencies.esClient,
uiSettingsClient: this.dependencies.uiSettingsClient,
}) || { entries: [] }
);
};

getKnowledgeBaseStatus = () => {
Expand Down
Loading

0 comments on commit 3bc5e2d

Please sign in to comment.