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

[Observability AI Assistant] Create chat #17

Merged
merged 5 commits into from
Jul 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,27 @@ export function ErrorSampleContextualInsight({
role: MessageRole.User,
content: `I'm an SRE. I am looking at an exception and trying to understand what it means.

Your task is to describe what the error means and what it could be caused by.
The error occurred on a service called ${serviceName}, which is a ${runtimeName} service written in ${languageName}. The
runtime version is ${runtimeVersion}.
The request it occurred for is called ${transactionName}.
${
logStacktrace
? `The log stacktrace:
${logStacktrace}`
: ''
}
${
exceptionStacktrace
? `The exception stacktrace:
${exceptionStacktrace}`
: ''
}
`,
Your task is to describe what the error means and what it could be caused by.

The error occurred on a service called ${serviceName}, which is a ${runtimeName} service written in ${languageName}. The
runtime version is ${runtimeVersion}.

The request it occurred for is called ${transactionName}.

${
logStacktrace
? `The log stacktrace:
${logStacktrace}`
: ''
}

${
exceptionStacktrace
? `The exception stacktrace:
${exceptionStacktrace}`
: ''
}
`,
},
},
];
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/observability_ai_assistant/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export enum MessageRole {
Assistant = 'assistant',
User = 'user',
Function = 'function',
Event = 'event',
Elastic = 'elastic',
}

Expand All @@ -21,6 +20,7 @@ export interface Message {
message: {
content?: string;
name?: string;
event?: string;
role: MessageRole;
function_call?: {
name: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function Application({
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider
services={{
...coreStart,
plugins: {
start: pluginsStart,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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 { ComponentStory } from '@storybook/react';
import React from 'react';
import { ChatBody as Component } from './chat_body';

export default {
component: Component,
title: 'app/Organisms/ChatBody',
};

type ChatBodyProps = React.ComponentProps<typeof Component>;

const Template: ComponentStory<typeof Component> = (props: ChatBodyProps) => {
return (
<div style={{ minHeight: 800, display: 'flex' }}>
<Component {...props} />
</div>
);
};

const defaultProps: ChatBodyProps = {
initialConversation: {
'@timestamp': new Date().toISOString(),
conversation: {
title: 'My conversation',
},
labels: {},
numeric_labels: {},
messages: [],
},
connectors: {
connectors: [
{
id: 'foo',
referencedByCount: 1,
actionTypeId: 'foo',
name: 'GPT-v8-ultra',
isPreconfigured: true,
isDeprecated: false,
isSystemAction: false,
},
],
loading: false,
error: undefined,
selectedConnector: 'foo',
selectConnector: () => {},
},
currentUser: {
username: 'elastic',
},
chat: {
loading: false,
abort: () => {},
generate: async () => {
return {} as any;
},
},
};

export const ChatBody = Template.bind({});
ChatBody.args = defaultProps;
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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 { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiPanel } from '@elastic/eui';
import { css } from '@emotion/css';
import type { AuthenticatedUser } from '@kbn/security-plugin/common';
import React from 'react';
import { type ConversationCreateRequest } from '../../../common/types';
import type { UseChatResult } from '../../hooks/use_chat';
import type { UseGenAIConnectorsResult } from '../../hooks/use_genai_connectors';
import { useTimeline } from '../../hooks/use_timeline';
import { ChatHeader } from './chat_header';
import { ChatPromptEditor } from './chat_prompt_editor';
import { ChatTimeline } from './chat_timeline';

const containerClassName = css`
max-height: 100%;
`;

const timelineClassName = css`
overflow-y: auto;
`;

export function ChatBody({
initialConversation,
connectors,
currentUser,
chat,
}: {
initialConversation?: ConversationCreateRequest;
connectors: UseGenAIConnectorsResult;
currentUser?: Pick<AuthenticatedUser, 'full_name' | 'username'>;
chat: UseChatResult;
}) {
const timeline = useTimeline({
initialConversation,
connectors,
currentUser,
chat,
});

return (
<EuiFlexGroup direction="column" gutterSize="none" className={containerClassName}>
<EuiFlexItem grow={false}>
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="l">
<ChatHeader title="foo" connectors={connectors} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiHorizontalRule margin="none" />
</EuiFlexItem>
<EuiFlexItem grow className={timelineClassName}>
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="l">
<ChatTimeline
items={timeline.items}
onEdit={timeline.onEdit}
onFeedback={timeline.onFeedback}
onRegenerate={timeline.onRegenerate}
onStopGenerating={timeline.onStopGenerating}
/>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiHorizontalRule margin="none" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="l">
<ChatPromptEditor
loading={chat.loading}
disabled={!connectors.selectedConnector}
onSubmit={timeline.onSubmit}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,37 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { EuiFlyout, EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader } from '@elastic/eui';
import { euiThemeVars } from '@kbn/ui-theme';
import React, { useState } from 'react';
import { ConversationCreateRequest } from '../../../common/types';
import { UseGenAIConnectorsResult } from '../../hooks/use_genai_connectors';
import { ChatHeader } from './chat_header';
import { ChatPromptEditor } from './chat_prompt_editor';
import { ChatTimeline } from './chat_timeline';

export interface ChatFlyoutProps {
conversation: ConversationCreateRequest;
connectors: UseGenAIConnectorsResult;
}

export function ChatFlyout({ conversation, connectors }: ChatFlyoutProps) {
const {
conversation: { title },
messages,
} = conversation;

const [isOpen, setIsOpen] = useState(true);

const handleSubmit = (prompt: string) => {};
import { EuiFlyout } from '@elastic/eui';
import React from 'react';
import type { ConversationCreateRequest } from '../../../common/types';
import { useChat } from '../../hooks/use_chat';
import { useCurrentUser } from '../../hooks/use_current_user';
import { useGenAIConnectors } from '../../hooks/use_genai_connectors';
import { ChatBody } from './chat_body';

export function ChatFlyout({
initialConversation,
isOpen,
onClose,
}: {
initialConversation: ConversationCreateRequest;
isOpen: boolean;
onClose: () => void;
}) {
const chat = useChat();

const connectors = useGenAIConnectors();

const currentUser = useCurrentUser();

return isOpen ? (
<EuiFlyout onClose={() => setIsOpen(false)} size="m">
<EuiFlyoutHeader hasBorder>
<ChatHeader title={title} connectors={connectors} />
</EuiFlyoutHeader>

<EuiFlyoutBody>
<ChatTimeline messages={messages} />
</EuiFlyoutBody>

<EuiFlyoutFooter
css={{ borderTop: `solid 1px ${euiThemeVars.euiBorderColor}`, background: '#fff' }}
>
<ChatPromptEditor onSubmitPrompt={handleSubmit} />
</EuiFlyoutFooter>
<EuiFlyout onClose={onClose}>
<ChatBody
chat={chat}
connectors={connectors}
initialConversation={initialConversation}
currentUser={currentUser}
/>
</EuiFlyout>
) : null;
}
Loading
Loading