Skip to content

Commit

Permalink
[Obs AI Assistant] Implement contextual actions (#178405)
Browse files Browse the repository at this point in the history
Implements contextual actions. With this change, consumers of the
Observability AI Assistant can add contextual actions to screen context,
which are functions that are executed on the client. Its results are
then pushed back to the API and the LLM to continue the conversation.
This allows consumers to do things like:

- have the LLM navigate the app
- push component/browser state to the LLM
- provide functions that make the most sense in a specific UI context

Additionally, this also opens up the possibility for consumers of the
complete API to implement their own functions.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
dgieselaar and kibanamachine authored Mar 16, 2024
1 parent 2bd3e3f commit acc5beb
Show file tree
Hide file tree
Showing 38 changed files with 1,367 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@ export type FunctionResponse =
}
| Observable<ChatCompletionChunkEvent | MessageAddEvent>;

export interface FunctionDefinition<
TParameters extends CompatibleJSONSchema = CompatibleJSONSchema
> {
export interface FunctionDefinition<TParameters extends CompatibleJSONSchema = any> {
name: string;
description: string;
visibility?: FunctionVisibility;
descriptionForUser?: string;
parameters: TParameters;
parameters?: TParameters;
contexts: string[];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { ObservabilityAIAssistantChatService } from '../public';
import type { CompatibleJSONSchema, FunctionResponse } from './functions/types';

export enum MessageRole {
System = 'system',
Expand Down Expand Up @@ -77,11 +79,37 @@ export interface KnowledgeBaseEntry {
role: KnowledgeBaseEntryRole;
}

export interface ObservabilityAIAssistantScreenContextRequest {
screenDescription?: string;
data?: Array<{
name: string;
description: string;
value: any;
}>;
actions?: Array<{ name: string; description: string; parameters?: CompatibleJSONSchema }>;
}

export type ScreenContextActionRespondFunction<TArguments extends unknown> = ({}: {
args: TArguments;
signal: AbortSignal;
connectorId: string;
client: Pick<ObservabilityAIAssistantChatService, 'chat' | 'complete'>;
messages: Message[];
}) => Promise<FunctionResponse>;

export interface ScreenContextActionDefinition<TArguments = undefined> {
name: string;
description: string;
parameters?: CompatibleJSONSchema;
respond: ScreenContextActionRespondFunction<TArguments>;
}

export interface ObservabilityAIAssistantScreenContext {
screenDescription?: string;
data?: Array<{
name: string;
description: string;
value: any;
}>;
actions?: ScreenContextActionDefinition[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@
*/

import { v4 } from 'uuid';
import { MessageRole } from '../../../common';
import {
MessageAddEvent,
StreamingChatResponseEventType,
} from '../../../common/conversation_complete';
import { MessageRole } from '..';
import { MessageAddEvent, StreamingChatResponseEventType } from '../conversation_complete';

export function createFunctionRequestMessage({
name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 { createFunctionResponseMessage } from './create_function_response_message';

export function createFunctionResponseError({
name,
error,
message,
}: {
name: string;
error: Error;
message?: string;
}) {
return createFunctionResponseMessage({
name,
content: {
error: {
...error,
name: error.name,
message: error.message,
cause: error.cause,
stack: error.stack,
},
message: message || error.message,
},
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@
*/

import { v4 } from 'uuid';
import { MessageRole } from '../../../common';
import {
type MessageAddEvent,
StreamingChatResponseEventType,
} from '../../../common/conversation_complete';
import { MessageRole } from '..';
import { type MessageAddEvent, StreamingChatResponseEventType } from '../conversation_complete';

export function createFunctionResponseMessage({
name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ function useChatWithoutContext({
setChatState(ChatState.Loading);

const next$ = chatService.complete({
screenContexts: service.getScreenContexts(),
getScreenContexts: () => service.getScreenContexts(),
connectorId,
messages: getWithSystemMessage(nextMessages, systemMessage),
persist,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export { useAbortableAsync, type AbortableAsyncState } from './hooks/use_abortab

export { createStorybookChatService, createStorybookService } from './storybook_mock';

export { createScreenContextAction } from './utils/create_screen_context_action';

export { ChatState } from './hooks/use_chat';

export { FeedbackButtons, type Feedback } from './components/buttons/feedback_buttons';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import { i18n } from '@kbn/i18n';
import { noop } from 'lodash';
import React from 'react';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import type { StreamingChatResponseEventWithoutError } from '../common/conversation_complete';
import { ScreenContextActionDefinition } from '../common/types';
import type { ObservabilityAIAssistantAPIClient } from './api';
import type {
ObservabilityAIAssistantChatService,
Expand Down Expand Up @@ -49,6 +50,7 @@ export const mockService: ObservabilityAIAssistantService = {
openNewConversation: noop,
predefinedConversation$: new Observable(),
},
navigate: async () => of(),
};

function createSetupContract(): ObservabilityAIAssistantPublicSetup {
Expand All @@ -75,6 +77,7 @@ function createStartContract(): ObservabilityAIAssistantPublicStart {
getPreferredLanguage: () => 'English',
}),
getContextualInsightMessages: () => [],
createScreenContextAction: () => ({} as ScreenContextActionDefinition<any>),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
} from './types';
import { useUserPreferredLanguage } from './hooks/use_user_preferred_language';
import { getContextualInsightMessages } from './utils/get_contextual_insight_messages';
import { createScreenContextAction } from './utils/create_screen_context_action';

export class ObservabilityAIAssistantPlugin
implements
Expand Down Expand Up @@ -107,6 +108,7 @@ export class ObservabilityAIAssistantPlugin
)
: null,
getContextualInsightMessages,
createScreenContextAction,
};
}
}
Loading

0 comments on commit acc5beb

Please sign in to comment.