Skip to content

Commit

Permalink
Merge branch 'main' into analyzer-preview-dataview
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippeOberti authored Sep 1, 2023
2 parents e060017 + d238114 commit a0ceb98
Show file tree
Hide file tree
Showing 17 changed files with 751 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export const LogRateAnalysis: FC<AlertDetailsLogRateAnalysisSectionProps> = ({ r
Do not mention indidivual p-values from the analysis results. Do not guess, just say what you are sure of. Do not repeat the given instructions in your output.`;

const now = new Date().toString();
const now = new Date().toISOString();

return [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ export function AskAssistantButton({
)}
>
<EuiButtonIcon
aria-label={i18n.translate(
'xpack.observabilityAiAssistant.askAssistantButton.popoverTitle',
{
defaultMessage: 'Elastic Assistant',
}
)}
iconType="sparkles"
display={fill ? 'fill' : 'base'}
size={size}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/*
* 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, { useState } from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiButton,
EuiButtonIcon,
EuiContextMenu,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiLink,
EuiLoadingSpinner,
EuiPanel,
EuiPopover,
EuiSpacer,
EuiSwitch,
EuiText,
} from '@elastic/eui';
import { ConnectorSelectorBase } from '../connector_selector/connector_selector_base';
import type { UseGenAIConnectorsResult } from '../../hooks/use_genai_connectors';
import type { UseKnowledgeBaseResult } from '../../hooks/use_knowledge_base';
import type { StartedFrom } from '../../utils/get_timeline_items_from_conversation';

export function ChatActionsMenu({
connectors,
connectorsManagementHref,
conversationId,
knowledgeBase,
modelsManagementHref,
startedFrom,
onCopyConversationClick,
}: {
connectors: UseGenAIConnectorsResult;
connectorsManagementHref: string;
conversationId?: string;
knowledgeBase: UseKnowledgeBaseResult;
modelsManagementHref: string;
startedFrom?: StartedFrom;
onCopyConversationClick: () => void;
}) {
const [isOpen, setIsOpen] = useState(false);

const toggleActionsMenu = () => {
setIsOpen(!isOpen);
};

return (
<EuiPopover
isOpen={isOpen}
button={
<EuiButtonIcon iconType="boxesVertical" onClick={toggleActionsMenu} aria-label="Menu" />
}
panelPaddingSize="none"
closePopover={toggleActionsMenu}
>
<EuiContextMenu
initialPanelId={0}
panels={[
{
id: 0,
title: i18n.translate('xpack.observabilityAiAssistant.chatHeader.actions.title', {
defaultMessage: 'Actions',
}),
items: [
{
name: (
<>
{i18n.translate('xpack.observabilityAiAssistant.chatHeader.actions.connector', {
defaultMessage: 'Connector',
})}{' '}
<strong>
{
connectors.connectors?.find(({ id }) => id === connectors.selectedConnector)
?.name
}
</strong>
</>
),
panel: 1,
},
{
name: (
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem grow>
{i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.knowledgeBase',
{
defaultMessage: 'Knowledge base',
}
)}
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ paddingRight: 4 }}>
{knowledgeBase.status.loading || knowledgeBase.isInstalling ? (
<EuiLoadingSpinner size="s" />
) : knowledgeBase.status.value?.ready ? (
<EuiIcon type="checkInCircleFilled" />
) : (
<EuiIcon type="dotInCircle" />
)}
</EuiFlexItem>
</EuiFlexGroup>
),
panel: 2,
},
{
name: i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.copyConversation',
{
defaultMessage: 'Copy conversation',
}
),
disabled: !conversationId,
onClick: () => {
toggleActionsMenu();
onCopyConversationClick();
},
},
],
},
{
id: 1,
width: 256,
title: i18n.translate('xpack.observabilityAiAssistant.chatHeader.actions.connector', {
defaultMessage: 'Connector',
}),
content: (
<EuiPanel>
<ConnectorSelectorBase {...connectors} />
<EuiSpacer size="m" />
<EuiButton
href={connectorsManagementHref}
iconSide="right"
iconType="arrowRight"
size="s"
>
{i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.connectorManagement.button',
{
defaultMessage: 'Manage connectors',
}
)}
</EuiButton>
</EuiPanel>
),
},
{
id: 2,
width: 256,
title: i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.knowledgeBase.title',
{
defaultMessage: 'Knowledge base',
}
),
content: (
<EuiPanel>
<EuiText size="s">
<p>
{i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.knowledgeBase.description.paragraph',
{
defaultMessage:
'Using a knowledge base is optional but improves the experience of using the Assistant significantly.',
}
)}{' '}
<EuiLink
external
target="_blank"
href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html"
>
{i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.knowledgeBase.elser.learnMore',
{
defaultMessage: 'Learn more',
}
)}
</EuiLink>
</p>
</EuiText>

<EuiSpacer size="l" />
{knowledgeBase.isInstalling || knowledgeBase.status.loading ? (
<EuiLoadingSpinner size="m" />
) : (
<>
<EuiSwitch
label={
knowledgeBase.isInstalling
? i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.knowledgeBase.switchLabel.installing',
{
defaultMessage: 'Setting up knowledge base',
}
)
: i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.knowledgeBase.switchLabel.enable',
{
defaultMessage: 'Knowledge base installed',
}
)
}
checked={Boolean(knowledgeBase.status.value?.ready)}
disabled={
Boolean(knowledgeBase.status.value?.ready) || knowledgeBase.isInstalling
}
onChange={(e) => {
if (e.target.checked) {
knowledgeBase.install();
}
}}
/>

<EuiSpacer size="m" />

<EuiButton href={modelsManagementHref} fullWidth size="s">
{i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.connectorManagement',
{
defaultMessage: 'Go to Machine Learning',
}
)}
</EuiButton>
</>
)}
</EuiPanel>
),
},
]}
/>
</EuiPopover>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,14 @@ import type { UseKnowledgeBaseResult } from '../../hooks/use_knowledge_base';
import { useTimeline } from '../../hooks/use_timeline';
import { useLicense } from '../../hooks/use_license';
import { useObservabilityAIAssistantChatService } from '../../hooks/use_observability_ai_assistant_chat_service';
import { MissingCredentialsCallout } from '../missing_credentials_callout';
import { ExperimentalFeatureBanner } from './experimental_feature_banner';
import { InitialSetupPanel } from './initial_setup_panel';
import { IncorrectLicensePanel } from './incorrect_license_panel';
import { ChatHeader } from './chat_header';
import { ChatPromptEditor } from './chat_prompt_editor';
import { ChatTimeline } from './chat_timeline';
import { StartedFrom } from '../../utils/get_timeline_items_from_conversation';

const containerClassName = css`
max-height: 100%;
max-width: ${1200 - 250}px; // page template max width - conversation list width.
`;

const timelineClassName = css`
overflow-y: auto;
`;
Expand All @@ -57,6 +52,7 @@ export function ChatBody({
connectors,
knowledgeBase,
connectorsManagementHref,
modelsManagementHref,
conversationId,
currentUser,
startedFrom,
Expand All @@ -70,6 +66,7 @@ export function ChatBody({
connectors: UseGenAIConnectorsResult;
knowledgeBase: UseKnowledgeBaseResult;
connectorsManagementHref: string;
modelsManagementHref: string;
conversationId?: string;
currentUser?: Pick<AuthenticatedUser, 'full_name' | 'username'>;
startedFrom?: StartedFrom;
Expand All @@ -83,10 +80,10 @@ export function ChatBody({
const chatService = useObservabilityAIAssistantChatService();

const timeline = useTimeline({
messages,
chatService,
connectors,
currentUser,
chatService,
messages,
startedFrom,
onChatUpdate,
onChatComplete,
Expand All @@ -100,6 +97,13 @@ export function ChatBody({
connectors.loading || knowledgeBase.status.loading || last(timeline.items)?.loading
);

const containerClassName = css`
max-height: 100%;
max-width: ${startedFrom === 'conversationView'
? 1200 - 250 + 'px' // page template max width - conversation list width.
: '100%'};
`;

useEffect(() => {
const parent = timelineContainerRef.current?.parentElement;
if (!parent) {
Expand Down Expand Up @@ -143,6 +147,12 @@ export function ChatBody({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [timelineContainerRef.current]);

const handleCopyConversation = () => {
const content = JSON.stringify({ title, messages });

navigator.clipboard?.writeText(content || '');
};

if (!hasCorrectLicense && !conversationId) {
footer = (
<>
Expand All @@ -166,12 +176,14 @@ export function ChatBody({
<EuiLoadingSpinner />
</EuiFlexItem>
);
} else if (connectors.connectors?.length === 0) {
} else if (connectors.connectors?.length === 0 && !conversationId) {
footer = (
<>
<EuiSpacer size="l" />
<MissingCredentialsCallout connectorsManagementHref={connectorsManagementHref} />
</>
<InitialSetupPanel
connectors={connectors}
connectorsManagementHref={connectorsManagementHref}
knowledgeBase={knowledgeBase}
startedFrom={startedFrom}
/>
);
} else {
footer = (
Expand All @@ -181,6 +193,7 @@ export function ChatBody({
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="m">
<ChatTimeline
items={timeline.items}
knowledgeBase={knowledgeBase}
onEdit={timeline.onEdit}
onFeedback={timeline.onFeedback}
onRegenerate={timeline.onRegenerate}
Expand Down Expand Up @@ -208,16 +221,24 @@ export function ChatBody({

return (
<EuiFlexGroup direction="column" gutterSize="none" className={containerClassName}>
<EuiFlexItem grow={false}>
<ExperimentalFeatureBanner />
</EuiFlexItem>
{connectors.selectedConnector ? (
<EuiFlexItem grow={false}>
<ExperimentalFeatureBanner />
</EuiFlexItem>
) : null}

<EuiFlexItem grow={false}>
<ChatHeader
connectors={connectors}
conversationId={conversationId}
connectorsManagementHref={connectorsManagementHref}
modelsManagementHref={modelsManagementHref}
knowledgeBase={knowledgeBase}
licenseInvalid={!hasCorrectLicense && !conversationId}
loading={loading}
startedFrom={startedFrom}
title={title}
onCopyConversation={handleCopyConversation}
onSaveTitle={onSaveTitle}
/>
</EuiFlexItem>
Expand Down
Loading

0 comments on commit a0ceb98

Please sign in to comment.