Skip to content
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
1 change: 1 addition & 0 deletions packages/deeplinks/security/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

export enum SecurityPageName {
administration = 'administration',
aiInsights = 'ai_insights',
alerts = 'alerts',
assets = 'assets',
blocklist = 'blocklist',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export type AssistantFeatures = { [K in keyof typeof defaultAssistantFeatures]:
* Default features available to the elastic assistant
*/
export const defaultAssistantFeatures = Object.freeze({
assistantAlertsInsights: false,
assistantModelEvaluation: false,
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { Replacements } from '../../schemas';
import { AnonymizationFieldResponse } from '../../schemas/anonymization_fields/bulk_crud_anonymization_fields_route.gen';
import { isAllowed } from '../helpers';
import type { AnonymizedData, GetAnonymizedValues } from '../types';
Expand All @@ -16,12 +17,12 @@ export const getAnonymizedData = ({
rawData,
}: {
anonymizationFields?: AnonymizationFieldResponse[];
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
getAnonymizedValue: ({
currentReplacements,
rawValue,
}: {
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
rawValue: string;
}) => string;
getAnonymizedValues: GetAnonymizedValues;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@

import { invert } from 'lodash/fp';
import { v4 } from 'uuid';
import { Replacements } from '../../schemas';

export const getAnonymizedValue = ({
currentReplacements,
rawValue,
}: {
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
rawValue: string;
}): string => {
if (currentReplacements != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const transformRawData = ({
currentReplacements,
rawValue,
}: {
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
rawValue: string;
}) => string;
onNewReplacements?: (replacements: Replacements) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@
* 2.0.
*/

import { Replacements } from '../schemas';
import { AnonymizationFieldResponse } from '../schemas/anonymization_fields/bulk_crud_anonymization_fields_route.gen';

export interface AnonymizedValues {
/** The original values were transformed to these anonymized values */
anonymizedValues: string[];

/** A map from replacement value to original value */
replacements: Record<string, string>;
replacements: Replacements;
}

export interface AnonymizedData {
/** The original data was transformed to this anonymized data */
anonymizedData: Record<string, string[]>;

/** A map from replacement value to original value */
replacements: Record<string, string>;
replacements: Replacements;
}

export type GetAnonymizedValues = ({
Expand All @@ -31,13 +32,13 @@ export type GetAnonymizedValues = ({
rawData,
}: {
anonymizationFields?: AnonymizationFieldResponse[];
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
field: string;
getAnonymizedValue: ({
currentReplacements,
rawValue,
}: {
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
rawValue: string;
}) => string;
rawData: Record<string, unknown[]>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ import { getMessageContentAndRole } from './helpers';

const LLM_TYPE = 'ActionsClientLlm';

const DEFAULT_OPEN_AI_TEMPERATURE = 0.2;
const DEFAULT_TEMPERATURE = 0;

interface ActionsClientLlmParams {
actions: ActionsPluginStart;
connectorId: string;
llmType?: string;
logger: Logger;
request: KibanaRequest;
model?: string;
temperature?: number;
traceId?: string;
}

Expand All @@ -37,6 +41,7 @@ export class ActionsClientLlm extends LLM {
protected llmType: string;

model?: string;
temperature?: number;

constructor({
actions,
Expand All @@ -46,6 +51,7 @@ export class ActionsClientLlm extends LLM {
logger,
model,
request,
temperature,
}: ActionsClientLlmParams) {
super({});

Expand All @@ -56,6 +62,7 @@ export class ActionsClientLlm extends LLM {
this.#logger = logger;
this.#request = request;
this.model = model;
this.temperature = temperature;
}

_llmType() {
Expand Down Expand Up @@ -87,8 +94,8 @@ export class ActionsClientLlm extends LLM {
model: this.model,
messages: [assistantMessage], // the assistant message
...(this.llmType === 'openai'
? { n: 1, stop: null, temperature: 0.2 }
: { temperature: 0, stopSequences: [] }),
? { n: 1, stop: null, temperature: this.temperature ?? DEFAULT_OPEN_AI_TEMPERATURE }
: { temperature: this.temperature ?? DEFAULT_TEMPERATURE, stopSequences: [] }),
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
* 2.0.
*/

import { Replacements } from '../../schemas';

/** This mock returns the reverse of `value` */
export const mockGetAnonymizedValue = ({
currentReplacements,
rawValue,
}: {
currentReplacements: Record<string, string> | undefined;
currentReplacements: Replacements | undefined;
rawValue: string;
}): string => rawValue.split('').reverse().join('');
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ import { z } from 'zod';

export type GetCapabilitiesResponse = z.infer<typeof GetCapabilitiesResponse>;
export const GetCapabilitiesResponse = z.object({
assistantAlertsInsights: z.boolean(),
assistantModelEvaluation: z.boolean(),
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ paths:
schema:
type: object
properties:
assistantAlertsInsights:
type: boolean
assistantModelEvaluation:
type: boolean
required:
- assistantAlertsInsights
- assistantModelEvaluation
'400':
description: Generic Error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export const API_VERSIONS = {
export const PUBLIC_API_ACCESS = 'public';
export const INTERNAL_API_ACCESS = 'internal';

// Alerts Insights Schemas
export * from './insights/alerts/post_alerts_insights_route.gen';

// Evaluation Schemas
export * from './evaluation/post_evaluate_route.gen';
export * from './evaluation/get_evaluate_route.gen';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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 { z } from 'zod';

/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Alerts insights API endpoint
* version: 1
*/

import { AnonymizationFieldResponse } from '../../anonymization_fields/bulk_crud_anonymization_fields_route.gen';
import { Replacements, TraceData } from '../../conversations/common_attributes.gen';

/**
* An insight generated from one or more alerts
*/
export type AlertsInsight = z.infer<typeof AlertsInsight>;
export const AlertsInsight = z.object({
/**
* The alert IDs that the insight is based on
*/
alertIds: z.array(z.string()),
/**
* A detailed insight with bulleted markdown that always uses special syntax for field names and values from the source data.
*/
detailsMarkdown: z.string(),
/**
* A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same syntax
*/
entitySummaryMarkdown: z.string(),
/**
* An array of MITRE ATT&CK tactic for the insight
*/
mitreAttackTactics: z.array(z.string()).optional(),
/**
* A markdown summary of insight, using the same syntax
*/
summaryMarkdown: z.string(),
/**
* A title for the insight, in plain text
*/
title: z.string(),
});

export type AlertsInsightsPostRequestBody = z.infer<typeof AlertsInsightsPostRequestBody>;
export const AlertsInsightsPostRequestBody = z.object({
alertsIndexPattern: z.string(),
anonymizationFields: z.array(AnonymizationFieldResponse),
connectorId: z.string(),
actionTypeId: z.string(),
model: z.string().optional(),
replacements: Replacements.optional(),
size: z.number(),
subAction: z.enum(['invokeAI', 'invokeStream']),
});
export type AlertsInsightsPostRequestBodyInput = z.input<typeof AlertsInsightsPostRequestBody>;

export type AlertsInsightsPostResponse = z.infer<typeof AlertsInsightsPostResponse>;
export const AlertsInsightsPostResponse = z.object({
connector_id: z.string().optional(),
insights: z.array(AlertsInsight).optional(),
replacements: Replacements.optional(),
status: z.string().optional(),
trace_data: TraceData.optional(),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
openapi: 3.0.0
info:
title: Alerts insights API endpoint
version: '1'
components:
x-codegen-enabled: true
schemas:
AlertsInsight:
type: object
description: An insight generated from one or more alerts
required:
- 'alertIds'
- 'detailsMarkdown'
- 'entitySummaryMarkdown'
- 'summaryMarkdown'
- 'title'
properties:
alertIds:
description: The alert IDs that the insight is based on
items:
type: string
type: array
detailsMarkdown:
description: A detailed insight with bulleted markdown that always uses special syntax for field names and values from the source data.
type: string
entitySummaryMarkdown:
description: A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same syntax
type: string
mitreAttackTactics:
description: An array of MITRE ATT&CK tactic for the insight
items:
type: string
type: array
summaryMarkdown:
description: A markdown summary of insight, using the same syntax
type: string
title:
description: A title for the insight, in plain text
type: string


paths:
/internal/elastic_assistant/insights/alerts:
post:
operationId: AlertsInsightsPost
x-codegen-enabled: true
description: Generate insights from alerts
summary: Generate insights from alerts via the Elastic Assistant
tags:
- insights
- alerts
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- actionTypeId
- alertsIndexPattern
- anonymizationFields
- connectorId
- size
- subAction
properties:
alertsIndexPattern:
type: string
anonymizationFields:
items:
$ref: '../../anonymization_fields/bulk_crud_anonymization_fields_route.schema.yaml#/components/schemas/AnonymizationFieldResponse'
type: array
connectorId:
type: string
actionTypeId:
type: string
model:
type: string
replacements:
$ref: '../../conversations/common_attributes.schema.yaml#/components/schemas/Replacements'
size:
type: number
subAction:
type: string
enum:
- invokeAI
- invokeStream
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
connector_id:
type: string
insights:
type: array
items:
$ref: '#/components/schemas/AlertsInsight'
replacements:
$ref: '../../conversations/common_attributes.schema.yaml#/components/schemas/Replacements'
status:
type: string
trace_data:
$ref: '../../conversations/common_attributes.schema.yaml#/components/schemas/TraceData'
'400':
description: Bad request
content:
application/json:
schema:
type: object
properties:
statusCode:
type: number
error:
type: string
message:
type: string

Loading