From 0d1d7fee6a509931caf4b6646402c9a58dfc8fcd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Feb 2025 15:32:03 +0000 Subject: [PATCH] Simplify RAG presets; add bulk API details (#610) * Add new ml response tab Signed-off-by: Tyler Ohlsen * Add bulk API content Signed-off-by: Tyler Ohlsen --------- Signed-off-by: Tyler Ohlsen (cherry picked from commit ee7ec893fc434280c46edd638f3f25685de63622) Signed-off-by: github-actions[bot] --- common/constants.ts | 2 + .../results/ml_response.tsx | 60 +++++++++++++++++++ public/general_components/results/results.tsx | 16 +++++ .../ingest_inputs/bulk_popover_content.tsx | 49 +++++++++++++++ .../ingest_inputs/source_data.tsx | 53 ++++++++++++++-- .../new_workflow/quick_configure_modal.tsx | 5 +- public/pages/workflows/new_workflow/utils.ts | 3 - 7 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 public/general_components/results/ml_response.tsx create mode 100644 public/pages/workflow_detail/workflow_inputs/ingest_inputs/bulk_popover_content.tsx diff --git a/common/constants.ts b/common/constants.ts index d4719221..f506f620 100644 --- a/common/constants.ts +++ b/common/constants.ts @@ -250,6 +250,8 @@ export const BULK_API_DOCS_LINK = 'https://opensearch.org/docs/latest/api-reference/document-apis/bulk/'; export const SEARCH_PIPELINE_DOCS_LINK = 'https://opensearch.org/docs/latest/search-plugins/search-pipelines/using-search-pipeline/'; +export const ML_RESPONSE_PROCESSOR_EXAMPLE_DOCS_LINK = + 'https://opensearch.org/docs/latest/search-plugins/search-pipelines/ml-inference-search-response/#example-externally-hosted-text-embedding-model'; /** * Text chunking algorithm constants diff --git a/public/general_components/results/ml_response.tsx b/public/general_components/results/ml_response.tsx new file mode 100644 index 00000000..036e3834 --- /dev/null +++ b/public/general_components/results/ml_response.tsx @@ -0,0 +1,60 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { isEmpty } from 'lodash'; +import { + EuiCode, + EuiCodeEditor, + EuiEmptyPrompt, + EuiLink, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { + customStringify, + ML_RESPONSE_PROCESSOR_EXAMPLE_DOCS_LINK, +} from '../../../common'; + +interface MLResponseProps { + mlResponse: {}; +} + +/** + * Small component to render the ML response within a raw search response. + */ +export function MLResponse(props: MLResponseProps) { + return ( + <> + + + Showing results stored in ext.ml_inference from the + search response.{' '} + + See an example + + + + {isEmpty(props.mlResponse) ? ( + No response found} titleSize="s" /> + ) : ( + + )} + + ); +} diff --git a/public/general_components/results/results.tsx b/public/general_components/results/results.tsx index a85e320c..3eac32ba 100644 --- a/public/general_components/results/results.tsx +++ b/public/general_components/results/results.tsx @@ -4,6 +4,7 @@ */ import React, { useState } from 'react'; +import { get } from 'lodash'; import { EuiPanel, EuiFlexGroup, @@ -13,6 +14,7 @@ import { import { SearchResponse } from '../../../common'; import { ResultsTable } from './results_table'; import { ResultsJSON } from './results_json'; +import { MLResponse } from './ml_response'; interface ResultsProps { response: SearchResponse; @@ -21,6 +23,7 @@ interface ResultsProps { enum VIEW { HITS_TABLE = 'hits_table', RAW_JSON = 'raw_json', + ML_RESPONSE = 'ml_response', } /** @@ -55,6 +58,10 @@ export function Results(props: ResultsProps) { id: VIEW.RAW_JSON, label: 'Raw JSON', }, + { + id: VIEW.ML_RESPONSE, + label: 'ML response', + }, ]} idSelected={selectedView} onChange={(id) => setSelectedView(id as VIEW)} @@ -69,9 +76,18 @@ export function Results(props: ResultsProps) { {selectedView === VIEW.RAW_JSON && ( )} + {selectedView === VIEW.ML_RESPONSE && ( + + )} ); } + +function getMLResponseFromSearchResponse(searchResponse: SearchResponse): {} { + return get(searchResponse, 'ext.ml_inference', {}); +} diff --git a/public/pages/workflow_detail/workflow_inputs/ingest_inputs/bulk_popover_content.tsx b/public/pages/workflow_detail/workflow_inputs/ingest_inputs/bulk_popover_content.tsx new file mode 100644 index 00000000..5396e7f4 --- /dev/null +++ b/public/pages/workflow_detail/workflow_inputs/ingest_inputs/bulk_popover_content.tsx @@ -0,0 +1,49 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { + EuiText, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiCodeBlock, + EuiPopoverTitle, +} from '@elastic/eui'; +import { BULK_API_DOCS_LINK } from '../../../../../common'; + +interface BulkPopoverContentProps { + indexName: string; +} + +/** + * A basic component containing details about the bulk API and link to documentation. + * Provides a partially-complete example, dynamically populated based on an index name. + */ +export function BulkPopoverContent(props: BulkPopoverContentProps) { + return ( + + Ingest additional data + + + + You can ingest additional bulk data into the same index using the + Bulk API.{' '} + + Learn more + + + + + + {`POST ${props.indexName}/_bulk +{ "index": { "_index": "${props.indexName}", "_id": //YOUR DOC ID// } } +{ //INSERT YOUR DOCUMENTS// }`} + + + + + ); +} diff --git a/public/pages/workflow_detail/workflow_inputs/ingest_inputs/source_data.tsx b/public/pages/workflow_detail/workflow_inputs/ingest_inputs/source_data.tsx index 98b881db..25c7ede8 100644 --- a/public/pages/workflow_detail/workflow_inputs/ingest_inputs/source_data.tsx +++ b/public/pages/workflow_detail/workflow_inputs/ingest_inputs/source_data.tsx @@ -14,6 +14,7 @@ import { EuiCodeBlock, EuiSmallButtonEmpty, EuiEmptyPrompt, + EuiPopover, } from '@elastic/eui'; import { MapEntry, @@ -25,6 +26,7 @@ import { toFormattedDate, } from '../../../../../common'; import { SourceDataModal } from './source_data_modal'; +import { BulkPopoverContent } from './bulk_popover_content'; interface SourceDataProps { workflow: Workflow | undefined; @@ -54,6 +56,9 @@ export function SourceData(props: SourceDataProps) { // edit modal state const [isEditModalOpen, setIsEditModalOpen] = useState(false); + // bulk API popover state + const [bulkPopoverOpen, setBulkPopoverOpen] = useState(false); + // hook to listen when the docs form value changes. useEffect(() => { if (values?.ingest?.docs) { @@ -133,11 +138,49 @@ export function SourceData(props: SourceDataProps) { {props.lastIngested !== undefined && ( - - - {`Last ingested: ${toFormattedDate(props.lastIngested)}`} - - + <> + + + {`Last ingested: ${toFormattedDate(props.lastIngested)}`} + + + + + + + Ingest additional data with the bulk API. + + + + setBulkPopoverOpen(false)} + button={ + { + setBulkPopoverOpen(!bulkPopoverOpen); + }} + > + Learn more + + } + > + + + + + + )} {docsPopulated ? ( <> diff --git a/public/pages/workflows/new_workflow/quick_configure_modal.tsx b/public/pages/workflows/new_workflow/quick_configure_modal.tsx index 6f307327..854be4ac 100644 --- a/public/pages/workflows/new_workflow/quick_configure_modal.tsx +++ b/public/pages/workflows/new_workflow/quick_configure_modal.tsx @@ -741,7 +741,8 @@ function updateRAGSearchResponseProcessors( llmInterface: ModelInterface | undefined ): WorkflowConfig { config.search.enrichResponse.processors.forEach((processor, idx) => { - // prefill ML inference + // prefill ML inference. By default, store the inference results + // under the `ext.ml_inference` response body. if (processor.type === PROCESSOR_TYPE.ML) { config.search.enrichResponse.processors[idx].fields.forEach((field) => { if (field.id === 'model' && fields.llmId) { @@ -784,7 +785,7 @@ function updateRAGSearchResponseProcessors( ...outputMap[0], value: { transformType: TRANSFORM_TYPE.FIELD, - value: fields.llmResponseField, + value: `ext.ml_inference.${fields.llmResponseField}`, }, }; } else { diff --git a/public/pages/workflows/new_workflow/utils.ts b/public/pages/workflows/new_workflow/utils.ts index 35e7b043..57d983a7 100644 --- a/public/pages/workflows/new_workflow/utils.ts +++ b/public/pages/workflows/new_workflow/utils.ts @@ -4,7 +4,6 @@ */ import { - CollapseProcessor, MLIngestProcessor, MLSearchRequestProcessor, MLSearchResponseProcessor, @@ -253,7 +252,6 @@ export function fetchRAGMetadata(version: string): UIState { baseState.config.search.request.value = customStringify(FETCH_ALL_QUERY); baseState.config.search.enrichResponse.processors = [ new MLSearchResponseProcessor().toObj(), - new CollapseProcessor().toObj(), ]; return baseState; } @@ -278,7 +276,6 @@ export function fetchVectorSearchWithRAGMetadata(version: string): UIState { ]; baseState.config.search.enrichResponse.processors = [ new MLSearchResponseProcessor().toObj(), - new CollapseProcessor().toObj(), ]; return baseState; }