From 45c82230c5003601a399f737a9cd45a93924eb75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Fri, 5 Jul 2024 13:43:57 +0200 Subject: [PATCH] [Obs AI Assistant] Make resource names static (#187489) This changes the resource names from being stateful to being static. This makes it easier to import them since they don't have to be passed around, and "go-to-definition" actually takes you to the implementation point instead of the types. (cherry picked from commit 1040bae64087e2d8fb6a4ef77b93b731b74b8d27) --- .../server/service/client/index.test.ts | 2 - .../server/service/client/index.ts | 9 +-- .../server/service/index.ts | 80 ++++++++----------- .../service/knowledge_base_service/index.ts | 22 ++--- .../server/service/types.ts | 22 ----- 5 files changed, 51 insertions(+), 84 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts index 46d72d303f7e3..cbe033ed0e4b9 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts @@ -14,7 +14,6 @@ import { Subject } from 'rxjs'; import { EventEmitter, PassThrough, type Readable } from 'stream'; import { finished } from 'stream/promises'; import { ObservabilityAIAssistantClient } from '.'; -import { createResourceNamesMap } from '..'; import { MessageRole, type Message } from '../../../common'; import { ObservabilityAIAssistantConnectorType } from '../../../common/connectors'; import { @@ -186,7 +185,6 @@ describe('Observability AI Assistant client', () => { knowledgeBaseService: knowledgeBaseServiceMock, logger: loggerMock, namespace: 'default', - resources: createResourceNamesMap(), user: { name: 'johndoe', }, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts index 139955742ef6e..7341bf766b764 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts @@ -30,6 +30,7 @@ import { } from 'rxjs'; import { Readable } from 'stream'; import { v4 } from 'uuid'; +import { resourceNames } from '..'; import { ObservabilityAIAssistantConnectorType } from '../../../common/connectors'; import { ChatCompletionChunkEvent, @@ -60,7 +61,6 @@ import { KnowledgeBaseService, RecalledEntry, } from '../knowledge_base_service'; -import type { ObservabilityAIAssistantResourceNames } from '../types'; import { getAccessQuery } from '../util/get_access_query'; import { getSystemMessageFromInstructions } from '../util/get_system_message_from_instructions'; import { replaceSystemMessage } from '../util/replace_system_message'; @@ -93,7 +93,6 @@ export class ObservabilityAIAssistantClient { asInternalUser: ElasticsearchClient; asCurrentUser: ElasticsearchClient; }; - resources: ObservabilityAIAssistantResourceNames; logger: Logger; user?: { id?: string; @@ -107,7 +106,7 @@ export class ObservabilityAIAssistantClient { conversationId: string ): Promise | undefined> => { const response = await this.dependencies.esClient.asInternalUser.search({ - index: this.dependencies.resources.aliases.conversations, + index: resourceNames.aliases.conversations, query: { bool: { filter: [ @@ -594,7 +593,7 @@ export class ObservabilityAIAssistantClient { find = async (options?: { query?: string }): Promise<{ conversations: Conversation[] }> => { const response = await this.dependencies.esClient.asInternalUser.search({ - index: this.dependencies.resources.aliases.conversations, + index: resourceNames.aliases.conversations, allow_no_indices: true, query: { bool: { @@ -686,7 +685,7 @@ export class ObservabilityAIAssistantClient { ); await this.dependencies.esClient.asInternalUser.index({ - index: this.dependencies.resources.aliases.conversations, + index: resourceNames.aliases.conversations, document: createdConversation, refresh: true, }); diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/index.ts index 34f3667d1cb7b..eddcb8112f540 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/index.ts @@ -22,40 +22,34 @@ import { ObservabilityAIAssistantClient } from './client'; import { conversationComponentTemplate } from './conversation_component_template'; import { kbComponentTemplate } from './kb_component_template'; import { KnowledgeBaseEntryOperationType, KnowledgeBaseService } from './knowledge_base_service'; -import type { - RegistrationCallback, - ObservabilityAIAssistantResourceNames, - RespondFunctionResources, -} from './types'; +import type { RegistrationCallback, RespondFunctionResources } from './types'; import { splitKbText } from './util/split_kb_text'; function getResourceName(resource: string) { return `.kibana-observability-ai-assistant-${resource}`; } -export function createResourceNamesMap() { - return { - componentTemplate: { - conversations: getResourceName('component-template-conversations'), - kb: getResourceName('component-template-kb'), - }, - aliases: { - conversations: getResourceName('conversations'), - kb: getResourceName('kb'), - }, - indexPatterns: { - conversations: getResourceName('conversations*'), - kb: getResourceName('kb*'), - }, - indexTemplate: { - conversations: getResourceName('index-template-conversations'), - kb: getResourceName('index-template-kb'), - }, - pipelines: { - kb: getResourceName('kb-ingest-pipeline'), - }, - }; -} +export const resourceNames = { + componentTemplate: { + conversations: getResourceName('component-template-conversations'), + kb: getResourceName('component-template-kb'), + }, + aliases: { + conversations: getResourceName('conversations'), + kb: getResourceName('kb'), + }, + indexPatterns: { + conversations: getResourceName('conversations*'), + kb: getResourceName('kb*'), + }, + indexTemplate: { + conversations: getResourceName('index-template-conversations'), + kb: getResourceName('index-template-kb'), + }, + pipelines: { + kb: getResourceName('kb-ingest-pipeline'), + }, +}; export const INDEX_QUEUED_DOCUMENTS_TASK_ID = 'observabilityAIAssistant:indexQueuedDocumentsTask'; @@ -76,8 +70,6 @@ export class ObservabilityAIAssistantService { private readonly getModelId: () => Promise; private kbService?: KnowledgeBaseService; - private readonly resourceNames: ObservabilityAIAssistantResourceNames = createResourceNamesMap(); - private readonly registrations: RegistrationCallback[] = []; constructor({ @@ -143,15 +135,15 @@ export class ObservabilityAIAssistantService { const esClient = coreStart.elasticsearch.client; await esClient.asInternalUser.cluster.putComponentTemplate({ create: false, - name: this.resourceNames.componentTemplate.conversations, + name: resourceNames.componentTemplate.conversations, template: conversationComponentTemplate, }); await esClient.asInternalUser.indices.putIndexTemplate({ - name: this.resourceNames.indexTemplate.conversations, - composed_of: [this.resourceNames.componentTemplate.conversations], + name: resourceNames.indexTemplate.conversations, + composed_of: [resourceNames.componentTemplate.conversations], create: false, - index_patterns: [this.resourceNames.indexPatterns.conversations], + index_patterns: [resourceNames.indexPatterns.conversations], template: { settings: { number_of_shards: 1, @@ -166,7 +158,7 @@ export class ObservabilityAIAssistantService { }, }); - const conversationAliasName = this.resourceNames.aliases.conversations; + const conversationAliasName = resourceNames.aliases.conversations; await createConcreteWriteIndex({ esClient: esClient.asInternalUser, @@ -177,19 +169,19 @@ export class ObservabilityAIAssistantService { pattern: `${conversationAliasName}*`, basePattern: `${conversationAliasName}*`, name: `${conversationAliasName}-000001`, - template: this.resourceNames.indexTemplate.conversations, + template: resourceNames.indexTemplate.conversations, }, dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts: false }), }); await esClient.asInternalUser.cluster.putComponentTemplate({ create: false, - name: this.resourceNames.componentTemplate.kb, + name: resourceNames.componentTemplate.kb, template: kbComponentTemplate, }); await esClient.asInternalUser.ingest.putPipeline({ - id: this.resourceNames.pipelines.kb, + id: resourceNames.pipelines.kb, processors: [ { inference: { @@ -210,10 +202,10 @@ export class ObservabilityAIAssistantService { }); await esClient.asInternalUser.indices.putIndexTemplate({ - name: this.resourceNames.indexTemplate.kb, - composed_of: [this.resourceNames.componentTemplate.kb], + name: resourceNames.indexTemplate.kb, + composed_of: [resourceNames.componentTemplate.kb], create: false, - index_patterns: [this.resourceNames.indexPatterns.kb], + index_patterns: [resourceNames.indexPatterns.kb], template: { settings: { number_of_shards: 1, @@ -223,7 +215,7 @@ export class ObservabilityAIAssistantService { }, }); - const kbAliasName = this.resourceNames.aliases.kb; + const kbAliasName = resourceNames.aliases.kb; await createConcreteWriteIndex({ esClient: esClient.asInternalUser, @@ -234,7 +226,7 @@ export class ObservabilityAIAssistantService { pattern: `${kbAliasName}*`, basePattern: `${kbAliasName}*`, name: `${kbAliasName}-000001`, - template: this.resourceNames.indexTemplate.kb, + template: resourceNames.indexTemplate.kb, }, dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts: false }), }); @@ -242,7 +234,6 @@ export class ObservabilityAIAssistantService { this.kbService = new KnowledgeBaseService({ logger: this.logger.get('kb'), esClient, - resources: this.resourceNames, taskManagerStart: pluginsStart.taskManager, getModelId: this.getModelId, }); @@ -289,7 +280,6 @@ export class ObservabilityAIAssistantService { asInternalUser: coreStart.elasticsearch.client.asInternalUser, asCurrentUser: coreStart.elasticsearch.client.asScoped(request).asCurrentUser, }, - resources: this.resourceNames, logger: this.logger, user: user ? { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts index 45330f9da2f2b..28343f054f037 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts @@ -14,16 +14,18 @@ import pRetry from 'p-retry'; import { map, orderBy } from 'lodash'; import { encode } from 'gpt-tokenizer'; import { MlTrainedModelDeploymentNodesStats } from '@elastic/elasticsearch/lib/api/types'; -import { INDEX_QUEUED_DOCUMENTS_TASK_ID, INDEX_QUEUED_DOCUMENTS_TASK_TYPE } from '..'; +import { + INDEX_QUEUED_DOCUMENTS_TASK_ID, + INDEX_QUEUED_DOCUMENTS_TASK_TYPE, + resourceNames, +} from '..'; import { KnowledgeBaseEntry, KnowledgeBaseEntryRole, UserInstruction } from '../../../common/types'; -import type { ObservabilityAIAssistantResourceNames } from '../types'; import { getAccessQuery } from '../util/get_access_query'; import { getCategoryQuery } from '../util/get_category_query'; import { recallFromConnectors } from './recall_from_connectors'; interface Dependencies { esClient: { asInternalUser: ElasticsearchClient }; - resources: ObservabilityAIAssistantResourceNames; logger: Logger; taskManagerStart: TaskManagerStartContract; getModelId: () => Promise; @@ -194,7 +196,7 @@ export class KnowledgeBaseService { private async processOperation(operation: KnowledgeBaseEntryOperation) { if (operation.type === KnowledgeBaseEntryOperationType.Delete) { await this.dependencies.esClient.asInternalUser.deleteByQuery({ - index: this.dependencies.resources.aliases.kb, + index: resourceNames.aliases.kb, query: { bool: { filter: [ @@ -333,7 +335,7 @@ export class KnowledgeBaseService { const response = await this.dependencies.esClient.asInternalUser.search< Pick >({ - index: [this.dependencies.resources.aliases.kb], + index: [resourceNames.aliases.kb], query: esQuery, size: 20, _source: { @@ -431,7 +433,7 @@ export class KnowledgeBaseService { ): Promise => { try { const response = await this.dependencies.esClient.asInternalUser.search({ - index: this.dependencies.resources.aliases.kb, + index: resourceNames.aliases.kb, query: { bool: { must: [ @@ -475,7 +477,7 @@ export class KnowledgeBaseService { }): Promise<{ entries: KnowledgeBaseEntry[] }> => { try { const response = await this.dependencies.esClient.asInternalUser.search({ - index: this.dependencies.resources.aliases.kb, + index: resourceNames.aliases.kb, ...(query ? { query: { @@ -537,7 +539,7 @@ export class KnowledgeBaseService { }): Promise => { try { await this.dependencies.esClient.asInternalUser.index({ - index: this.dependencies.resources.aliases.kb, + index: resourceNames.aliases.kb, id, document: { '@timestamp': new Date().toISOString(), @@ -545,7 +547,7 @@ export class KnowledgeBaseService { user, namespace, }, - pipeline: this.dependencies.resources.pipelines.kb, + pipeline: resourceNames.pipelines.kb, refresh: 'wait_for', }); } catch (error) { @@ -579,7 +581,7 @@ export class KnowledgeBaseService { deleteEntry = async ({ id }: { id: string }): Promise => { try { await this.dependencies.esClient.asInternalUser.delete({ - index: this.dependencies.resources.aliases.kb, + index: resourceNames.aliases.kb, id, refresh: 'wait_for', }); diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/types.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/types.ts index 1d8d909447a38..6e6256c3b8b90 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/types.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/types.ts @@ -91,25 +91,3 @@ export type RegistrationCallback = ({}: { client: ObservabilityAIAssistantClient; functions: ChatFunctionClient; }) => Promise; - -export interface ObservabilityAIAssistantResourceNames { - componentTemplate: { - conversations: string; - kb: string; - }; - indexTemplate: { - conversations: string; - kb: string; - }; - aliases: { - conversations: string; - kb: string; - }; - indexPatterns: { - conversations: string; - kb: string; - }; - pipelines: { - kb: string; - }; -}