Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f71a8e4
[Obs AI Assistant] Add KB user instructions
Jul 4, 2024
f54af02
Improve description
Jul 4, 2024
7c65ee9
Address feedback
Jul 5, 2024
4c32316
Revert change to `requestInstructions`
Jul 5, 2024
f18dc24
Merge branch 'main' of github.com:elastic/kibana into kb-user-instruc…
Jul 5, 2024
371fb5e
Merge branch 'main' of github.com:elastic/kibana into kb-user-instruc…
Jul 8, 2024
421386f
Add UI for editing system prompt
Jul 9, 2024
dec0374
Merge branch 'main' into kb-user-instructions
Aug 5, 2024
063575b
Address feedback
Aug 5, 2024
14ec494
Merge branch 'main' of github.com:elastic/kibana into kb-user-instruc…
Aug 7, 2024
b43022b
Add comments
Aug 7, 2024
55255d9
i18n fix
Aug 7, 2024
3fe25f2
Improve naming
Aug 7, 2024
e69c9fb
Rename to adhoc instruction and fix tests
Aug 8, 2024
8a8e87d
Change terminology from “system prompt” to "AI User Profile"
Aug 8, 2024
4e78002
Remove unneeded header
Aug 8, 2024
6c4e406
Fix failing test
Aug 8, 2024
07d7c65
Remove `type`
Aug 9, 2024
9b2b3e1
Add route for retrieving user instructions
Aug 12, 2024
8e1fbcb
Remove unused type
Aug 12, 2024
4a49ee7
Add api tests
Aug 12, 2024
9392a44
Merge branch 'main' of github.com:elastic/kibana into kb-user-instruc…
Aug 13, 2024
88433ef
i18n
Aug 13, 2024
c6892fe
Improve api test
Aug 13, 2024
c05f37c
Fix order
Aug 13, 2024
ab8e19c
Add test for updating instruction
Aug 13, 2024
334d0e7
Test improvements
Aug 13, 2024
299167a
Merge branch 'main' of github.com:elastic/kibana into kb-user-instruc…
Aug 13, 2024
816e6eb
Merge branch 'main' of github.com:elastic/kibana into kb-user-instruc…
Aug 14, 2024
c2953b3
Add test that validates user instruction is added to system prompt
Aug 14, 2024
e433ab7
Add test to verify other users does not see instruction in their conv…
Aug 14, 2024
3639edf
Fik jest test (token count fixes)
Aug 14, 2024
e238ba0
Undo change to tsconfig.base.json
Aug 14, 2024
61bf0f4
Use shared `isFunctionTitleRequest`
Aug 14, 2024
4f960da
Remove unused import
Aug 15, 2024
4f0982c
Fix tsc issues
Aug 15, 2024
55a4fd5
Fix functional test
Aug 15, 2024
d41849c
Fix functional test
Aug 15, 2024
20f56fd
Fix jest
Aug 15, 2024
464b0b8
Remove context intercept
Aug 17, 2024
d76f1ce
Merge branch 'main' into kb-user-instructions
Aug 17, 2024
72f3338
Fix tests by clearing conversations
Aug 18, 2024
3004e2d
Merge branch 'main' into kb-user-instructions
Aug 19, 2024
ed6ee2c
Merge branch 'main' into kb-user-instructions
Aug 19, 2024
ee78461
Merge branch 'main' into kb-user-instructions
Aug 19, 2024
39627f1
Cleanup helper functions
Aug 19, 2024
465b77b
Change to debug
Aug 19, 2024
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 @@ -51,3 +51,5 @@ export { DEFAULT_LANGUAGE_OPTION, LANGUAGE_OPTIONS } from './ui_settings/languag
export { isSupportedConnectorType } from './connectors';

export { ShortIdTable } from './utils/short_id_table';

export { KnowledgeBaseType } from './types';
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export interface KnowledgeBaseEntry {
doc_id: string;
confidence: 'low' | 'medium' | 'high';
is_correction: boolean;
type?: 'user_instruction' | 'contextual';
public: boolean;
labels?: Record<string, string>;
role: KnowledgeBaseEntryRole;
Expand All @@ -92,13 +93,18 @@ export interface KnowledgeBaseEntry {
};
}

export interface UserInstruction {
export interface Instruction {
doc_id: string;
text: string;
system?: boolean;
user_instruction?: boolean;
}

export type UserInstructionOrPlainText = string | UserInstruction;
export type InstructionOrPlainText = string | Instruction;

export enum KnowledgeBaseType {
UserInstruction = 'user_instruction',
Contextual = 'contextual',
}

export interface ObservabilityAIAssistantScreenContextRequest {
screenDescription?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ export type {
ShortIdTable,
} from '../common';

export { KnowledgeBaseType } from '../common';

export type { TelemetryEventTypeWithPayload } from './analytics';
export { ObservabilityAIAssistantTelemetryEventType } from './analytics/telemetry_event_type';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {
Message,
ObservabilityAIAssistantScreenContext,
PendingMessage,
UserInstructionOrPlainText,
InstructionOrPlainText,
} from '../common/types';
import type { TelemetryEventTypeWithPayload } from './analytics';
import type { ObservabilityAIAssistantAPIClient } from './api';
Expand Down Expand Up @@ -68,7 +68,7 @@ export interface ObservabilityAIAssistantChatService {
};
signal: AbortSignal;
responseLanguage?: string;
instructions?: UserInstructionOrPlainText[];
instructions?: InstructionOrPlainText[];
}) => Observable<StreamingChatResponseEventWithoutError>;
getFunctions: (options?: { contexts?: string[]; filter?: string }) => FunctionDefinition[];
hasFunction: (name: string) => boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { KnowledgeBaseType } from '../../common/types';
import type { FunctionRegistrationParameters } from '.';
import { KnowledgeBaseEntryRole } from '../../common';

Expand Down Expand Up @@ -41,6 +42,11 @@ export function registerSummarizationFunction({
type: 'boolean',
description: 'Whether this is a correction for a previous learning.',
},
// type: {
// type: 'string',
// description: `The type can be: "user_instruction" or "contextual". A "user_instruction" entry will be included in the system message if it fits within the token budget and it will be marked as a user instruction. A "contextual" entry will be included as part of the context function response (and not the system message) if it semantically matches the user's prompt.`,
// enum: [KnowledgeBaseType.UserInstruction, KnowledgeBaseType.Contextual],
// },
Comment thread
sorenlouv marked this conversation as resolved.
Outdated
confidence: {
type: 'string',
description: 'How confident you are about this being a correct and useful learning',
Expand All @@ -56,6 +62,7 @@ export function registerSummarizationFunction({
'id' as const,
'text' as const,
'is_correction' as const,
// 'type' as const,
'confidence' as const,
'public' as const,
],
Expand All @@ -66,13 +73,14 @@ export function registerSummarizationFunction({
signal
) => {
return client
.createKnowledgeBaseEntry({
.addKnowledgeBaseEntry({
entry: {
doc_id: id,
role: KnowledgeBaseEntryRole.AssistantSummarization,
id,
text,
is_correction: isCorrection,
type: KnowledgeBaseType.Contextual,
confidence,
public: isPublic,
labels: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const chatCompleteBaseRt = t.type({
text: t.string,
}),
t.partial({
system: t.boolean,
user_instruction: t.boolean,
}),
]),
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ const getFunctionsRoute = createObservabilityAIAssistantServerRoute({

const client = await service.getClient({ request });

const [functionClient, userInstructions] = await Promise.all([
const [functionClient, kbUserInstructions] = await Promise.all([
service.getFunctionClient({
signal: controller.signal,
resources,
client,
screenContexts: [],
}),
// error is caught in client
client.fetchUserInstructions(),
client.getKnowledgeBaseUserInstructions(),
]);

const functionDefinitions = functionClient.getFunctions().map((fn) => fn.definition);
Expand All @@ -52,7 +52,7 @@ const getFunctionsRoute = createObservabilityAIAssistantServerRoute({
functionDefinitions: functionClient.getFunctions().map((fn) => fn.definition),
systemMessage: getSystemMessageFromInstructions({
registeredInstructions: functionClient.getInstructions(),
userInstructions,
kbUserInstructions,
requestInstructions: [],
availableFunctionNames,
}),
Expand Down Expand Up @@ -111,6 +111,7 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({
text: nonEmptyStringRt,
confidence: t.union([t.literal('low'), t.literal('medium'), t.literal('high')]),
is_correction: toBooleanRt,
type: t.union([t.literal('user_instruction'), t.literal('contextual')]),
public: toBooleanRt,
labels: t.record(t.string, t.string),
}),
Expand All @@ -129,17 +130,19 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({
confidence,
id,
is_correction: isCorrection,
type,
text,
public: isPublic,
labels,
} = resources.params.body;

return client.createKnowledgeBaseEntry({
return client.addKnowledgeBaseEntry({
entry: {
confidence,
id,
doc_id: id,
is_correction: isCorrection,
type,
text,
public: isPublic,
labels,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ const saveKnowledgeBaseEntry = createObservabilityAIAssistantServerRoute({
t.partial({
confidence: t.union([t.literal('low'), t.literal('medium'), t.literal('high')]),
is_correction: toBooleanRt,
type: t.union([t.literal('user_instruction'), t.literal('contextual')]),
public: toBooleanRt,
labels: t.record(t.string, t.string),
role: t.union([
Expand All @@ -126,17 +127,19 @@ const saveKnowledgeBaseEntry = createObservabilityAIAssistantServerRoute({
public: isPublic,
confidence,
is_correction: isCorrection,
type,
labels,
role,
} = resources.params.body;

return client.createKnowledgeBaseEntry({
return client.addKnowledgeBaseEntry({
entry: {
id,
text,
doc_id: id,
confidence: confidence ?? 'high',
is_correction: isCorrection ?? false,
type: type ?? 'contextual',
public: isPublic ?? true,
labels: labels ?? {},
role: (role as KnowledgeBaseEntryRole) ?? KnowledgeBaseEntryRole.UserEntry,
Expand Down Expand Up @@ -192,6 +195,7 @@ const importKnowledgeBaseEntries = createObservabilityAIAssistantServerRoute({
doc_id: entry.id,
confidence: 'high' as KnowledgeBaseEntry['confidence'],
is_correction: false,
type: 'contextual' as const,
public: true,
labels: {},
role: KnowledgeBaseEntryRole.UserEntry,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ describe('Observability AI Assistant client', () => {

const knowledgeBaseServiceMock: DeeplyMockedKeys<KnowledgeBaseService> = {
recall: jest.fn(),
getUserInstructions: jest.fn(),
getUserInstructions: jest.fn(), // TODO: change
Comment thread
sorenlouv marked this conversation as resolved.
Outdated
} as any;

let loggerMock: DeeplyMockedKeys<Logger> = {} as any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
} from '../../../common/conversation_complete';
import { CompatibleJSONSchema } from '../../../common/functions/types';
import {
UserInstructionOrPlainText,
InstructionOrPlainText,
type Conversation,
type ConversationCreateRequest,
type ConversationUpdateRequest,
Expand Down Expand Up @@ -159,7 +159,21 @@ export class ObservabilityAIAssistantClient {
});
};

complete = (params: {
complete = ({
functionClient,
connectorId,
simulateFunctionCalling,
instructions: requestInstructions = [],
messages: initialMessages,
signal,
responseLanguage = 'English',
persist,
kibanaPublicUrl,
isPublic,
title: predefinedTitle,
conversationId: predefinedConversationId,
disableFunctions = false,
}: {
messages: Message[];
connectorId: string;
signal: AbortSignal;
Expand All @@ -170,7 +184,7 @@ export class ObservabilityAIAssistantClient {
title?: string;
isPublic?: boolean;
kibanaPublicUrl?: string;
instructions?: UserInstructionOrPlainText[];
instructions?: InstructionOrPlainText[];
simulateFunctionCalling?: boolean;
disableFunctions?:
| boolean
Expand All @@ -181,22 +195,6 @@ export class ObservabilityAIAssistantClient {
return new LangTracer(context.active()).startActiveSpan(
'complete',
({ tracer: completeTracer }) => {
const {
functionClient,
connectorId,
simulateFunctionCalling,
instructions: requestInstructions = [],
messages: initialMessages,
signal,
responseLanguage = 'English',
persist,
kibanaPublicUrl,
isPublic,
title: predefinedTitle,
conversationId: predefinedConversationId,
disableFunctions = false,
} = params;

if (responseLanguage) {
requestInstructions.push(
`You MUST respond in the users preferred language which is: ${responseLanguage}.`
Expand All @@ -215,17 +213,19 @@ export class ObservabilityAIAssistantClient {
);
}

const userInstructions$ = from(this.fetchUserInstructions()).pipe(shareReplay());
const kbUserInstructions$ = from(this.getKnowledgeBaseUserInstructions()).pipe(
shareReplay()
);

// from the initial messages, override any system message with
// the one that is based on the instructions (registered, request, kb)
const messagesWithUpdatedSystemMessage$ = userInstructions$.pipe(
map((userInstructions) => {
const messagesWithUpdatedSystemMessage$ = kbUserInstructions$.pipe(
map((kbUserInstructions) => {
// this is what we eventually store in the conversation
const messagesWithUpdatedSystemMessage = replaceSystemMessage(
getSystemMessageFromInstructions({
registeredInstructions: functionClient.getInstructions(),
userInstructions,
kbUserInstructions,
requestInstructions,
availableFunctionNames: functionClient
.getFunctions()
Expand Down Expand Up @@ -272,9 +272,9 @@ export class ObservabilityAIAssistantClient {
// messages and the knowledge base instructions
const nextEvents$ = combineLatest([
messagesWithUpdatedSystemMessage$,
userInstructions$,
kbUserInstructions$,
]).pipe(
switchMap(([messagesWithUpdatedSystemMessage, userInstructions]) => {
switchMap(([messagesWithUpdatedSystemMessage, kbUserInstructions]) => {
// if needed, inject a context function request here
const contextRequest = functionClient.hasFunction(CONTEXT_FUNCTION_NAME)
? getContextFunctionRequestIfNeeded(messagesWithUpdatedSystemMessage)
Expand Down Expand Up @@ -302,7 +302,7 @@ export class ObservabilityAIAssistantClient {
// start out with the max number of function calls
functionCallsLeft: MAX_FUNCTION_CALLS,
functionClient,
userInstructions,
kbUserInstructions,
requestInstructions,
signal,
logger: this.dependencies.logger,
Expand Down Expand Up @@ -731,7 +731,7 @@ export class ObservabilityAIAssistantClient {
return this.dependencies.knowledgeBaseService.setup();
};

createKnowledgeBaseEntry = async ({
addKnowledgeBaseEntry = async ({
entry,
}: {
entry: Omit<KnowledgeBaseEntry, '@timestamp'>;
Expand Down Expand Up @@ -772,7 +772,7 @@ export class ObservabilityAIAssistantClient {
return this.dependencies.knowledgeBaseService.deleteEntry({ id });
};

fetchUserInstructions = async () => {
getKnowledgeBaseUserInstructions = async () => {
return this.dependencies.knowledgeBaseService.getUserInstructions(
this.dependencies.namespace,
this.dependencies.user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
MessageOrChatEvent,
} from '../../../../common/conversation_complete';
import { FunctionVisibility } from '../../../../common/functions/types';
import { UserInstruction } from '../../../../common/types';
import { Instruction } from '../../../../common/types';
import { createFunctionResponseMessage } from '../../../../common/utils/create_function_response_message';
import { emitWithConcatenatedMessage } from '../../../../common/utils/emit_with_concatenated_message';
import { withoutTokenCountEvents } from '../../../../common/utils/without_token_count_events';
Expand Down Expand Up @@ -172,7 +172,7 @@ export function continueConversation({
signal,
functionCallsLeft,
requestInstructions,
userInstructions,
kbUserInstructions,
logger,
disableFunctions,
tracer,
Expand All @@ -182,8 +182,8 @@ export function continueConversation({
chat: ChatFunctionWithoutConnector;
signal: AbortSignal;
functionCallsLeft: number;
requestInstructions: Array<string | UserInstruction>;
userInstructions: UserInstruction[];
requestInstructions: Array<string | Instruction>;
kbUserInstructions: Instruction[];
logger: Logger;
disableFunctions:
| boolean
Expand All @@ -205,7 +205,7 @@ export function continueConversation({
const messagesWithUpdatedSystemMessage = replaceSystemMessage(
getSystemMessageFromInstructions({
registeredInstructions: functionClient.getInstructions(),
userInstructions,
kbUserInstructions,
requestInstructions,
availableFunctionNames: definitions.map((def) => def.name),
}),
Expand Down Expand Up @@ -324,7 +324,7 @@ export function continueConversation({
functionCallsLeft: nextFunctionCallsLeft,
functionClient,
signal,
userInstructions,
kbUserInstructions,
requestInstructions,
logger,
disableFunctions,
Expand Down
Loading