Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/main' into dataSour…
Browse files Browse the repository at this point in the history
…ceFix

# Conflicts:
#	public/components/incontext_insight/generate_popover_body.tsx
  • Loading branch information
qianheng-aws committed Sep 20, 2024
2 parents 672bef2 + db5155b commit 97a3c0f
Show file tree
Hide file tree
Showing 15 changed files with 515 additions and 226 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Use smaller and compressed variants of buttons and form components ([#250](https://github.com/opensearch-project/dashboards-assistant/pull/250))
- Support insight with RAG in alert analysis assistant and refine the UX ([#266](https://github.com/opensearch-project/dashboards-assistant/pull/266))
- Add assistant enabled capabilities to control rendering component([#267](https://github.com/opensearch-project/dashboards-assistant/pull/267))
- Add data to summary API([#295](https://github.com/opensearch-project/dashboards-assistant/pull/295))
- Add data to summary API([#295](https://github.com/opensearch-project/dashboards-assistant/pull/295))
- Refactor popover to add message action bar and add metrics to thumb-up and thumb-down([#304](https://github.com/opensearch-project/dashboards-assistant/pull/304))
3 changes: 2 additions & 1 deletion opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
],
"optionalPlugins": [
"dataSource",
"dataSourceManagement"
"dataSourceManagement",
"usageCollection"
],
"requiredBundles": [],
"configPath": [
Expand Down
25 changes: 20 additions & 5 deletions public/components/incontext_insight/generate_popover_body.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
*/

import React from 'react';
import { render, cleanup, fireEvent, waitFor } from '@testing-library/react';
import { render, cleanup, fireEvent, waitFor, screen } from '@testing-library/react';
import { getConfigSchema, getNotifications } from '../../services';
import { GeneratePopoverBody } from './generate_popover_body';
import { HttpSetup } from '../../../../../src/core/public';
import { SUMMARY_ASSISTANT_API } from '../../../common/constants/llm';
import { usageCollectionPluginMock } from '../../../../../src/plugins/usage_collection/public/mocks';

jest.mock('../../services');

Expand All @@ -26,7 +27,7 @@ beforeEach(() => {
});

afterEach(cleanup);

const mockUsageCollection = usageCollectionPluginMock.createSetupContract();
const mockPost = jest.fn();
const mockHttpSetup: HttpSetup = ({
post: mockPost,
Expand Down Expand Up @@ -68,6 +69,7 @@ describe('GeneratePopoverBody', () => {
incontextInsight={incontextInsightMock}
httpSetup={mockHttpSetup}
closePopover={closePopoverMock}
usageCollection={mockUsageCollection}
/>
);

Expand All @@ -86,9 +88,15 @@ describe('GeneratePopoverBody', () => {
expect(queryByLabelText('loading_content')).toBeNull();
expect(mockPost).toHaveBeenCalledWith(SUMMARY_ASSISTANT_API.SUMMARIZE, expect.any(Object));
expect(mockToasts.addDanger).not.toHaveBeenCalled();
// generated metric is sent
expect(mockUsageCollection.reportUiStats).toHaveBeenCalledWith(
'alertSummary',
'count',
expect.stringMatching(/^generated/)
);

// insight tip icon is visible
const insightTipIcon = getByLabelText('Insight');
const insightTipIcon = screen.getAllByLabelText('How was this generated?')[0];
expect(insightTipIcon).toBeInTheDocument();

// 2. Click insight tip icon to view insight
Expand Down Expand Up @@ -142,6 +150,7 @@ describe('GeneratePopoverBody', () => {
incontextInsight={incontextInsightMock}
httpSetup={mockHttpSetup}
closePopover={closePopoverMock}
usageCollection={mockUsageCollection}
/>
);

Expand All @@ -159,9 +168,15 @@ describe('GeneratePopoverBody', () => {
expect(queryByLabelText('loading_content')).toBeNull();
expect(mockPost).toHaveBeenCalledWith(SUMMARY_ASSISTANT_API.SUMMARIZE, expect.any(Object));
expect(mockToasts.addDanger).not.toHaveBeenCalled();
// generated metric is sent
expect(mockUsageCollection.reportUiStats).toHaveBeenCalledWith(
'alertSummary',
'count',
expect.stringMatching(/^generated/)
);

// insight tip icon is not visible
expect(queryByLabelText('Insight')).toBeNull();
expect(screen.queryAllByLabelText('How was this generated?')).toHaveLength(0);
// Only call http post 1 time.
expect(mockPost).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -223,6 +238,6 @@ describe('GeneratePopoverBody', () => {
// Show summary content although insight generation failed
expect(getByText('Generated summary content')).toBeInTheDocument();
// insight tip icon is not visible for this alert
expect(queryByLabelText('Insight')).toBeNull();
expect(screen.queryAllByLabelText('How was this generated?')).toHaveLength(0);
});
});
52 changes: 35 additions & 17 deletions public/components/incontext_insight/generate_popover_body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiIconTip,
EuiLoadingContent,
EuiMarkdownFormat,
EuiPanel,
Expand All @@ -20,21 +19,28 @@ import {
EuiTitle,
} from '@elastic/eui';
import { useEffectOnce } from 'react-use';
import { METRIC_TYPE } from '@osd/analytics';
import { MessageActions } from '../../tabs/chat/messages/message_action';
import { ContextObj, IncontextInsight as IncontextInsightInput } from '../../types';
import { getNotifications } from '../../services';
import { HttpSetup } from '../../../../../src/core/public';
import { SUMMARY_ASSISTANT_API } from '../../../common/constants/llm';
import shiny_sparkle from '../../assets/shiny_sparkle.svg';
import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public';
import { reportMetric } from '../../utils/report_metric';

export const GeneratePopoverBody: React.FC<{
incontextInsight: IncontextInsightInput;
httpSetup?: HttpSetup;
usageCollection?: UsageCollectionSetup;
closePopover: () => void;
}> = ({ incontextInsight, httpSetup, closePopover }) => {
}> = ({ incontextInsight, httpSetup, usageCollection, closePopover }) => {
const [summary, setSummary] = useState('');
const [insight, setInsight] = useState('');
const [insightAvailable, setInsightAvailable] = useState(false);
const [showInsight, setShowInsight] = useState(false);
const metricAppName = 'alertSummary';

const toasts = getNotifications().toasts;

useEffectOnce(() => {
Expand Down Expand Up @@ -102,6 +108,7 @@ export const GeneratePopoverBody: React.FC<{
`Please provide your insight on this ${summaryType}.`
);
}
reportMetric(usageCollection, metricAppName, 'generated', METRIC_TYPE.COUNT);
})
.catch((error) => {
toasts.addDanger(
Expand Down Expand Up @@ -208,23 +215,34 @@ export const GeneratePopoverBody: React.FC<{
const renderInnerFooter = () => {
return (
<EuiPopoverFooter className="incontextInsightGeneratePopoverFooter" paddingSize="none">
<EuiFlexGroup gutterSize="none" direction={'rowReverse'}>
{insightAvailable && (
<EuiFlexItem
grow={false}
onClick={() => {
{
<div style={{ display: showInsight ? 'none' : 'block' }}>
<MessageActions
contentToCopy={summary}
showFeedback
showTraceIcon={insightAvailable}
onViewTrace={() => {
setShowInsight(true);
}}
>
<EuiIconTip
aria-label="Insight"
type="iInCircle"
content="Insight with RAG"
color={showInsight ? 'blue' : 'black'}
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
usageCollection={usageCollection}
isOnTrace={showInsight}
metricAppName={metricAppName}
/>
</div>
}
{
<div style={{ display: showInsight && insightAvailable ? 'block' : 'none' }}>
<MessageActions
contentToCopy={insight}
showFeedback
showTraceIcon={insightAvailable}
onViewTrace={() => {}}
usageCollection={usageCollection}
isOnTrace={showInsight}
metricAppName={metricAppName}
/>
</div>
}
</EuiPopoverFooter>
);
};
Expand Down
9 changes: 8 additions & 1 deletion public/components/incontext_insight/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,20 @@ import chatIcon from '../../assets/chat.svg';
import sparkle from '../../assets/sparkle.svg';
import { HttpSetup } from '../../../../../src/core/public';
import { GeneratePopoverBody } from './generate_popover_body';
import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public/plugin';

export interface IncontextInsightProps {
children?: React.ReactNode;
httpSetup?: HttpSetup;
usageCollection?: UsageCollectionSetup;
}

// TODO: add saved objects / config to store seed suggestions
export const IncontextInsight = ({ children, httpSetup }: IncontextInsightProps) => {
export const IncontextInsight = ({
children,
httpSetup,
usageCollection,
}: IncontextInsightProps) => {
const anchor = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(false);

Expand Down Expand Up @@ -279,6 +285,7 @@ export const IncontextInsight = ({ children, httpSetup }: IncontextInsightProps)
<GeneratePopoverBody
incontextInsight={input}
httpSetup={httpSetup}
usageCollection={usageCollection}
closePopover={closePopover}
/>
);
Expand Down
Loading

0 comments on commit 97a3c0f

Please sign in to comment.