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

[AI Assistant] Add scopes to AI assistant #192611

Merged
merged 12 commits into from
Sep 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ export const LogRateAnalysisPage: FC<LogRateAnalysisPageProps> = ({
<observabilityAIAssistant.ObservabilityAIAssistantContextualInsight
title={logRateAnalysisTitle}
messages={messages}
scope="observability"
/>
</EuiFlexItem>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ export function ErrorSampleContextualInsight({
instructions: `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:
Expand All @@ -68,6 +68,7 @@ export function ErrorSampleContextualInsight({
title={i18n.translate('xpack.apm.errorGroupContextualInsight.explainErrorTitle', {
defaultMessage: "What's this error?",
})}
scope="observability"
/>
</EuiFlexItem>
<EuiSpacer size="s" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export function registerGetApmDatasetInfoFunction({
`,
},
};
}
},
['observability']
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ export function registerGetApmDownstreamDependenciesFunction({
registerFunction(
{
name: 'get_apm_downstream_dependencies',
description: `Get the downstream dependencies (services or uninstrumented backends) for a
service. This allows you to map the downstream dependency name to a service, by
returning both span.destination.service.resource and service.name. Use this to
description: `Get the downstream dependencies (services or uninstrumented backends) for a
service. This allows you to map the downstream dependency name to a service, by
returning both span.destination.service.resource and service.name. Use this to
drilldown further if needed.`,
descriptionForUser: i18n.translate(
'xpack.apm.observabilityAiAssistant.functions.registerGetApmDownstreamDependencies.descriptionForUser',
{
defaultMessage: `Get the downstream dependencies (services or uninstrumented backends) for a
service. This allows you to map the dowstream dependency name to a service, by
returning both span.destination.service.resource and service.name. Use this to
defaultMessage: `Get the downstream dependencies (services or uninstrumented backends) for a
service. This allows you to map the dowstream dependency name to a service, by
returning both span.destination.service.resource and service.name. Use this to
drilldown further if needed.`,
}
),
Expand Down Expand Up @@ -67,6 +67,7 @@ export function registerGetApmDownstreamDependenciesFunction({
randomSampler,
}),
};
}
},
['observability']
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export function registerGetApmServicesListFunction({
arguments: args,
}),
};
}
},
['observability']
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ export function registerGetApmTimeseriesFunction({
content: timeseries.map((series): Omit<ApmTimeseries, 'data'> => omit(series, 'data')),
data: timeseries,
};
}
},
['observability']
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ export const LogRateAnalysis: FC<AlertDetailsLogRateAnalysisSectionProps> = ({ r
<observabilityAIAssistant.ObservabilityAIAssistantContextualInsight
title={logRateAnalysisTitle}
messages={messages}
scope="observability"
/>
</EuiFlexItem>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const ContextualInsightProcessRow = ({ command }: { command: string }) =>
with the arguments to the process you should then explain its arguments and how they influence the behaviour
of the process. If I do not provide any arguments then explain the behaviour of the process when no arguments are
provided.

Here is an example with arguments.
Process: metricbeat -c /etc/metricbeat.yml -d autodiscover,kafka -e -system.hostfs=/hostfs
Explanation: Metricbeat is part of the Elastic Stack. It is a lightweight shipper that you can install on your
Expand Down Expand Up @@ -94,6 +94,7 @@ export const ContextualInsightProcessRow = ({ command }: { command: string }) =>
<observabilityAIAssistant.ObservabilityAIAssistantContextualInsight
title={explainProcessMessageTitle}
messages={explainProcessMessages}
scope="observability"
/>
</EuiFlexItem>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const LogAIAssistant = ({
title={explainLogMessageTitle}
messages={explainLogMessageMessages}
dataTestSubj="obsAiAssistantInsightButtonExplainLogMessage"
scope="observability"
/>
</EuiFlexItem>
) : null}
Expand All @@ -78,6 +79,7 @@ export const LogAIAssistant = ({
title={similarLogMessagesTitle}
messages={similarLogMessageMessages}
dataTestSubj="obsAiAssistantInsightButtonSimilarLogMessage"
scope="observability"
/>
</EuiFlexItem>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ export function LogRateAnalysis({
<ObservabilityAIAssistantContextualInsight
title={logRateAnalysisTitle}
messages={messages}
scope="observability"
/>
</EuiFlexItem>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export function AlertDetailContextualInsights({ alert }: { alert: AlertData | nu
{ defaultMessage: 'Help me understand this alert' }
)}
messages={getAlertContextMessages}
scope="observability"
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { JSONSchema7TypeName } from 'json-schema';
import type { Observable } from 'rxjs';
import { ChatCompletionChunkEvent, MessageAddEvent } from '../conversation_complete';
import { FunctionVisibility } from './function_visibility';
import { AssistantScope } from '../types';
export { FunctionVisibility };

type JSONSchemaOrPrimitive = CompatibleJSONSchema | string | number | boolean;
Expand Down Expand Up @@ -41,6 +42,7 @@ export interface FunctionDefinition<TParameters extends CompatibleJSONSchema = a
visibility?: FunctionVisibility;
descriptionForUser?: string;
parameters?: TParameters;
scopes?: AssistantScope[];
}

export type FunctionRegistry = Map<string, FunctionDefinition>;
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,5 @@ export interface ObservabilityAIAssistantScreenContext {
actions?: Array<ScreenContextActionDefinition<any>>;
starterPrompts?: StarterPrompt[];
}

export type AssistantScope = 'observability' | 'search' | 'all';
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { cloneDeep, isArray, isEmpty, last, once } from 'lodash';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import useObservable from 'react-use/lib/useObservable';
import { ILicense } from '@kbn/licensing-plugin/public';
import { MessageRole, type Message } from '../../../common/types';
import { MessageRole, type Message, AssistantScope } from '../../../common/types';
import { ObservabilityAIAssistantChatServiceContext } from '../../context/observability_ai_assistant_chat_service_context';
import { useAbortableAsync } from '../../hooks/use_abortable_async';
import { ChatState, useChat } from '../../hooks/use_chat';
Expand Down Expand Up @@ -49,10 +49,12 @@ function ChatContent({
title: defaultTitle,
initialMessages,
connectorId,
scope,
}: {
title: string;
initialMessages: Message[];
connectorId: string;
scope: AssistantScope;
}) {
const service = useObservabilityAIAssistant();
const chatService = useObservabilityAIAssistantChatService();
Expand All @@ -68,6 +70,7 @@ function ChatContent({
initialMessages,
persist: false,
disableFunctions: true,
scope,
});

const lastAssistantResponse = getLastMessageOfType(
Expand Down Expand Up @@ -199,6 +202,7 @@ export interface InsightProps {
messages: Message[] | (() => Promise<Message[] | undefined>);
title: string;
dataTestSubj?: string;
scope: AssistantScope;
}

enum FETCH_STATUS {
Expand All @@ -212,6 +216,7 @@ export function Insight({
messages: initialMessagesOrCallback,
title,
dataTestSubj,
scope,
}: InsightProps) {
const [messages, setMessages] = useState<{ messages: Message[]; status: FETCH_STATUS }>({
messages: [],
Expand Down Expand Up @@ -354,6 +359,7 @@ export function Insight({
title={title}
initialMessages={messages.messages}
connectorId={connectors.selectedConnector}
scope={scope}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ describe('useChat', () => {
service: {
getScreenContexts: () => [],
} as unknown as ObservabilityAIAssistantService,
scope: 'observability',
} as UseChatProps,
});
});
Expand Down Expand Up @@ -109,6 +110,7 @@ describe('useChat', () => {
service: {
getScreenContexts: () => [],
} as unknown as ObservabilityAIAssistantService,
scope: 'observability',
} as UseChatProps,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { merge } from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { AbortError } from '@kbn/kibana-utils-plugin/common';
import type { NotificationsStart } from '@kbn/core/public';
import { AssistantScope } from '../../common/types';
import {
MessageRole,
type Message,
Expand Down Expand Up @@ -55,6 +56,7 @@ interface UseChatPropsWithoutContext {
disableFunctions?: boolean;
onConversationUpdate?: (event: ConversationCreateEvent | ConversationUpdateEvent) => void;
onChatComplete?: (messages: Message[]) => void;
scope: AssistantScope;
}

export type UseChatProps = Omit<UseChatPropsWithoutContext, 'notifications'>;
Expand All @@ -70,6 +72,7 @@ function useChatWithoutContext({
onChatComplete,
persist,
disableFunctions,
scope,
}: UseChatPropsWithoutContext): UseChatResult {
const [chatState, setChatState] = useState(ChatState.Ready);
const systemMessage = useMemo(() => {
Expand Down Expand Up @@ -161,6 +164,7 @@ function useChatWithoutContext({
disableFunctions: disableFunctions ?? false,
signal: abortControllerRef.current.signal,
conversationId,
scope,
});

function getPendingMessages() {
Expand Down Expand Up @@ -259,6 +263,7 @@ function useChatWithoutContext({
disableFunctions,
service,
systemMessage,
scope,
]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const mockService: ObservabilityAIAssistantService = {
predefinedConversation$: new Observable(),
},
navigate: async () => of(),
scope: 'all',
};

function createSetupContract(): ObservabilityAIAssistantPublicSetup {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class ObservabilityAIAssistantPlugin
coreStart.application.capabilities.observabilityAIAssistant[
aiAssistantCapabilities.show
] === true,
scope: 'observability',
}));

const withProviders = <P extends {}, R = {}>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ describe('complete', () => {
disableFunctions: false,
signal: new AbortController().signal,
...params,
scope: 'all',
},
requestCallback
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function complete(
disableFunctions,
signal,
instructions,
scope,
}: {
client: Pick<ObservabilityAIAssistantChatService, 'chat' | 'complete'>;
getScreenContexts: () => ObservabilityAIAssistantScreenContext[];
Expand All @@ -65,6 +66,7 @@ export function complete(
screenContexts,
conversationId,
instructions,
scope,
},
},
}).pipe(shareReplay());
Expand Down Expand Up @@ -131,6 +133,7 @@ export function complete(
persist,
disableFunctions,
instructions,
scope,
},
requestCallback
).subscribe(subscriber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ describe('createChatService', () => {
apiClient: clientSpy,
registrations: [],
signal: new AbortController().signal,
scope: 'observability',
});
});

Expand All @@ -79,7 +80,12 @@ describe('createChatService', () => {

describe('chat', () => {
function chat({ signal }: { signal: AbortSignal } = { signal: new AbortController().signal }) {
return service.chat('my_test', { signal, messages: [], connectorId: '' });
return service.chat('my_test', {
signal,
messages: [],
connectorId: '',
scope: 'observability',
});
}

it('correctly parses a stream of JSON lines', async () => {
Expand Down
Loading