From 3cb27a5d21eb44a214ce6e7ec39c5e567987fc3f Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Wed, 26 Jul 2023 01:16:31 +0200 Subject: [PATCH] Chat Flyout --- .../components/chat/chat_flyout.stories.tsx | 25 +++++ .../public/components/chat/chat_flyout.tsx | 61 ++++++++++++ .../public/components/chat/chat_item.tsx | 9 +- .../components/chat/chat_item_controls.tsx | 1 + .../chat/chat_prompt_editor.stories.tsx | 25 +++++ .../components/chat/chat_prompt_editor.tsx | 95 +++++++++++++++++++ .../use_chat_conversation.ts | 67 +++++++++++++ .../__storybook_mocks__/use_functions.ts | 60 ++++++++++++ .../public/hooks/use_chat_conversation.ts | 19 ++++ .../public/hooks/use_functions.ts | 22 +++++ 10 files changed, 381 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.stories.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.stories.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_chat_conversation.ts create mode 100644 x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_functions.ts create mode 100644 x-pack/plugins/observability_ai_assistant/public/hooks/use_chat_conversation.ts create mode 100644 x-pack/plugins/observability_ai_assistant/public/hooks/use_functions.ts diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.stories.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.stories.tsx new file mode 100644 index 0000000000000..230c3058bcb31 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.stories.tsx @@ -0,0 +1,25 @@ +/* + * 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 { ComponentStory } from '@storybook/react'; +import { ChatFlyout as Component, ChatFlyoutProps } from './chat_flyout'; + +export default { + component: Component, + title: 'app/Molecules/ChatFlyout', + argTypes: {}, +}; + +const Template: ComponentStory = (props: ChatFlyoutProps) => { + return ; +}; + +const defaultProps = {}; + +export const ChatFlyout = Template.bind({}); +ChatFlyout.args = defaultProps; diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.tsx new file mode 100644 index 0000000000000..63991375a9dbd --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_flyout.tsx @@ -0,0 +1,61 @@ +/* + * 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 { + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiTitle, +} from '@elastic/eui'; +import { euiThemeVars } from '@kbn/ui-theme'; +import { useChatConversation } from '../../hooks/use_chat_conversation'; +import { ChatTimeline } from './chat_timeline'; +import { ChatPromptEditor } from './chat_prompt_editor'; +import { AssistantAvatar } from '../assistant_avatar'; + +export interface ChatFlyoutProps { + conversationId?: string; +} + +export function ChatFlyout({ conversationId }: ChatFlyoutProps) { + const { title, messages } = useChatConversation({ conversationId }); + + const [isOpen, setIsOpen] = useState(true); + + const handleSubmit = (prompt: string) => {}; + + return isOpen ? ( + setIsOpen(false)} size="m"> + + + + + + + +

{title}

+
+
+
+
+ + + + + + + + +
+ ) : null; +} diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_item.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_item.tsx index ab096114141b1..f990138533f62 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_item.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_item.tsx @@ -148,9 +148,12 @@ export function ChatItem({ anchorPosition="downLeft" button={ + {canReceiveFeedback ? : null} diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.stories.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.stories.tsx new file mode 100644 index 0000000000000..7506d259d76f0 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.stories.tsx @@ -0,0 +1,25 @@ +/* + * 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 { ComponentStory } from '@storybook/react'; +import { ChatPromptEditor as Component, ChatPromptEditorProps } from './chat_prompt_editor'; + +export default { + component: Component, + title: 'app/Molecules/ChatPromptEditor', + argTypes: {}, +}; + +const Template: ComponentStory = (props: ChatPromptEditorProps) => { + return ; +}; + +const defaultProps = {}; + +export const ChatPromptEditor = Template.bind({}); +ChatPromptEditor.args = defaultProps; diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx new file mode 100644 index 0000000000000..6fdb74e90c139 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx @@ -0,0 +1,95 @@ +/* + * 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 { + EuiButtonIcon, + EuiContextMenuItem, + EuiContextMenuPanel, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useFunctions, Func } from '../../hooks/use_functions'; + +export interface ChatPromptEditorProps { + onSubmitPrompt: (prompt: string) => void; +} + +export function ChatPromptEditor({ onSubmitPrompt }: ChatPromptEditorProps) { + const functions = useFunctions(); + + const [prompt, setPrompt] = useState(''); + const [isFunctionListOpen, setIsFunctionListOpen] = useState(false); + + const handleChange = (event: React.ChangeEvent) => { + setPrompt(event.currentTarget.value); + }; + + const handleSubmit = () => { + onSubmitPrompt(prompt); + }; + + const handleClickFunctionList = () => { + setIsFunctionListOpen(!isFunctionListOpen); + }; + + const handleSelectFunction = (func: Func) => { + setIsFunctionListOpen(false); + }; + + return ( + + + + } + closePopover={handleClickFunctionList} + panelPaddingSize="s" + isOpen={isFunctionListOpen} + > + ( + handleSelectFunction(func)}> + {func.function_name} + + ))} + /> + + + + + + + + + + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_chat_conversation.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_chat_conversation.ts new file mode 100644 index 0000000000000..67416974e20e1 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_chat_conversation.ts @@ -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 { Message } from '../../../common'; +import { + buildAssistantInnerMessage, + buildElasticInnerMessage, + buildMessage, + buildSystemInnerMessage, + buildUserInnerMessage, +} from '../../utils/builders'; + +interface UseChatConversationProps { + conversationId?: string; +} + +export function useChatConversation({ conversationId }: UseChatConversationProps): { + title: string; + messages: Message[]; +} { + const currentDate = new Date(); + + return { + title: 'Event name', + messages: [ + buildMessage({ + '@timestamp': String(new Date(currentDate.getTime())), + message: buildSystemInnerMessage(), + }), + buildMessage({ + '@timestamp': String(new Date(currentDate.getTime() + 1000)), + message: buildUserInnerMessage(), + }), + buildMessage({ + '@timestamp': String(new Date(currentDate.getTime() + 2000)), + message: buildAssistantInnerMessage({ + content: `In computer programming and mathematics, a function is a fundamental concept that represents a relationship between input values and output values. It takes one or more input values (also known as arguments or parameters) and processes them to produce a result, which is the output of the function. The input values are passed to the function, and the function performs a specific set of operations or calculations on those inputs to produce the desired output. + A function is often defined with a name, which serves as an identifier to call and use the function in the code. It can be thought of as a reusable block of code that can be executed whenever needed, and it helps in organizing code and making it more modular and maintainable.`, + }), + }), + buildMessage({ + '@timestamp': String(new Date(currentDate.getTime() + 3000)), + message: buildUserInnerMessage({ content: 'How does it work?' }), + }), + buildMessage({ + '@timestamp': String(new Date(currentDate.getTime() + 4000)), + message: buildElasticInnerMessage({ + content: `The way functions work depends on whether we are talking about mathematical functions or programming functions. Let's explore both: + + Mathematical Functions: + In mathematics, a function maps input values to corresponding output values based on a specific rule or expression. The general process of how a mathematical function works can be summarized as follows: + Step 1: Input - You provide an input value to the function, denoted as 'x' in the notation f(x). This value represents the independent variable. + + Step 2: Processing - The function takes the input value and applies a specific rule or algorithm to it. This rule is defined by the function itself and varies depending on the function's expression. + + Step 3: Output - After processing the input, the function produces an output value, denoted as 'f(x)' or 'y'. This output represents the dependent variable and is the result of applying the function's rule to the input. + + Step 4: Uniqueness - A well-defined mathematical function ensures that each input value corresponds to exactly one output value. In other words, the function should yield the same output for the same input whenever it is called.`, + }), + }), + ], + }; +} diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_functions.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_functions.ts new file mode 100644 index 0000000000000..06e13df331ea6 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/__storybook_mocks__/use_functions.ts @@ -0,0 +1,60 @@ +/* + * 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. + */ + +interface FuncParameters { + name: string; + type: 'string' | 'int' | 'boolean' | 'object'; + description: string; +} + +export interface Func { + id: string; + function_name: string; + parameters: FuncParameters[]; +} + +export function useFunctions(): Func[] { + return [ + { + id: '1', + function_name: 'get_service_summary', + parameters: [ + { + name: 'service', + type: 'string', + description: 'The service', + }, + ], + }, + { + id: '2', + function_name: 'get_apm_chart', + parameters: [], + }, + { + id: '3', + function_name: 'get_dependencies', + parameters: [ + { + name: 'service', + type: 'string', + description: 'The service', + }, + ], + }, + { + id: '4', + function_name: 'get_correlation_values', + parameters: [], + }, + { + id: '4', + function_name: 'get_error', + parameters: [], + }, + ]; +} diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat_conversation.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat_conversation.ts new file mode 100644 index 0000000000000..6dcc20cdf62dc --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat_conversation.ts @@ -0,0 +1,19 @@ +/* + * 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 { Message } from '../../common'; + +interface UseChatConversationProps { + conversationId?: string; +} + +export function useChatConversation({ conversationId }: UseChatConversationProps): { + title: string; + messages: Message[]; +} { + return { title: '', messages: [] }; +} diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_functions.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_functions.ts new file mode 100644 index 0000000000000..fbb47c31d6a08 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_functions.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +interface FuncParameters { + name: string; + type: 'string' | 'int' | 'boolean' | 'object'; + description: string; +} + +export interface Func { + id: string; + function_name: string; + parameters: FuncParameters[]; +} + +export function useFunctions(): Func[] { + return []; +}