mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
PR changes includes migration for anonymization defaults from the local
storage to use the ES data stream instead.
1. Extended `AIAssistantService` with the default setup method
`createDefaultAnonymizationFields` for anonymization fields, which will
be executed once for each space data stream. With that approach we will
have anonymization settings centralized for all the applications which
will use security GenAI functionality.
2. Anonymization fields is not personalizable and all the changes will
be applied to all users in the current space. Only users with the
defined privileges will be able to change anonymization setting.
3. Removed anonymization defaults from the AssistantContext provider.
Now fetch anonymization fields using API
`"/api/elastic_assistant/anonymization_fields/_find"`.
4. Anonymization settings component:
- replaced usage of `defaultAllow: string[];`, `defaultAllowReplacement:
string[];`,
`setUpdatedDefaultAllow:React.Dispatch<React.SetStateAction<string[]>>;`,
`setUpdatedDefaultAllowReplacement:
React.Dispatch<React.SetStateAction<string[]>>;` with
anonymizationFields fetched from the APIs;
- for the anonymize/allow UI operations use bulk actions update
operation;
- all the changes will be send to the server side using bulk API
`"/api/elastic_assistant/anonymization_fields/_bulk_action" ` after Save
settings button clicked or reset to the previous state when clicked
Cancel.
5. Data anonymization editor:
- This component will remain to apply the anonymization changes only in
the message scope. That means that any type of changes will be persisted
in the `.kibana-elastic-ai-assistant-anonymization-fields` and impact
only on the fields replacements in the selectedPromptContext.
6. Changed `.kibana-elastic-ai-assistant-anonymization-fields` data
stream schema to fits the UX:
```
"@timestamp": "2024-04-05T04:10:24.764Z",
"created_at": "2024-04-05T04:10:24.764Z",
"created_by": "",
"field": "_id",
"anonymized": false,
"allowed": true,
"namespace": "default",
"updated_at": "2024-04-05T17:15:00.903Z"
```
Components involved:
<img width="1091" alt="Screenshot 2024-04-05 at 11 35 05 AM" src="807ee596
-101f-413c-97d6-8f62c723397e">
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Steph Milovic <stephanie.milovic@elastic.co>
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
/*
|
|
* 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 { KibanaRequest } from '@kbn/core-http-server';
|
|
import type { Message } from '@kbn/elastic-assistant-common';
|
|
import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
|
|
import { ExecuteConnectorRequestBody } from '@kbn/elastic-assistant-common/impl/schemas/actions_connector/post_actions_connector_execute_route.gen';
|
|
|
|
export const getLangChainMessage = (
|
|
assistantMessage: Pick<Message, 'content' | 'role'>
|
|
): BaseMessage => {
|
|
switch (assistantMessage.role) {
|
|
case 'system':
|
|
return new SystemMessage(assistantMessage.content ?? '');
|
|
case 'user':
|
|
return new HumanMessage(assistantMessage.content ?? '');
|
|
case 'assistant':
|
|
return new AIMessage(assistantMessage.content ?? '');
|
|
default:
|
|
return new HumanMessage(assistantMessage.content ?? '');
|
|
}
|
|
};
|
|
|
|
export const getLangChainMessages = (
|
|
assistantMessages: Array<Pick<Message, 'content' | 'role'>>
|
|
): BaseMessage[] => assistantMessages.map(getLangChainMessage);
|
|
|
|
export const requestHasRequiredAnonymizationParams = (
|
|
request: KibanaRequest<unknown, unknown, ExecuteConnectorRequestBody>
|
|
): boolean => {
|
|
const { replacements } = request?.body ?? {};
|
|
|
|
const replacementsIsValid =
|
|
typeof replacements === 'object' &&
|
|
Object.keys(replacements).every(
|
|
(key) => typeof key === 'string' && typeof replacements[key] === 'string'
|
|
);
|
|
|
|
return replacementsIsValid;
|
|
};
|