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
Original file line number Diff line number Diff line change
Expand Up @@ -183,24 +183,6 @@ describe('useAssistantActions', function () {
},
});

expect(Object.keys(result.current)).to.have.length.greaterThan(0);
expect(result.current.interpretExplainPlan).to.be.a('function');
expect(result.current.interpretConnectionError).to.be.a('function');
expect(result.current.tellMoreAboutInsight).to.be.undefined;
});

it('returns actions when both AI features and assistant flag AND enablePerformanceInsightsEntrypoints are enabled', function () {
const { result } = renderHook(() => useAssistantActions(), {
wrapper: createWrapper(createMockChat({ messages: [] })),
preferences: {
enableAIAssistant: true,
enablePerformanceInsightsEntrypoints: true,
enableGenAIFeatures: true,
enableGenAIFeaturesAtlasOrg: true,
cloudFeatureRolloutAccess: { GEN_AI_COMPASS: true },
},
});

expect(Object.keys(result.current)).to.have.length.greaterThan(0);
expect(result.current.interpretExplainPlan).to.be.a('function');
expect(result.current.interpretConnectionError).to.be.a('function');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,6 @@ export function useAssistantActions(): AssistantActionsType {
const actions = useContext(AssistantActionsContext);
const isAIFeatureEnabled = useIsAIFeatureEnabled();
const isAssistantFlagEnabled = usePreference('enableAIAssistant');
const isPerformanceInsightEntrypointsEnabled = usePreference(
'enablePerformanceInsightsEntrypoints'
);

if (!isAIFeatureEnabled || !isAssistantFlagEnabled) {
return {
Expand All @@ -150,9 +147,7 @@ export function useAssistantActions(): AssistantActionsType {
return {
interpretExplainPlan,
interpretConnectionError,
tellMoreAboutInsight: isPerformanceInsightEntrypointsEnabled
? tellMoreAboutInsight
: undefined,
tellMoreAboutInsight,
getIsAssistantEnabled: () => true,
};
}
Expand Down
213 changes: 210 additions & 3 deletions packages/compass-assistant/src/prompts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,17 @@ describe('prompts', function () {
},
activeCollectionMetadata: {
isTimeSeries: false,
isClustered: false,
isFLE: false,
isSearchIndexesSupported: false,
isDataLake: false,
isAtlas: false,
serverVersion: '7.0.0',
},
activeCollectionSubTab: 'Schema',
},
expected:
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Schema" tab for the "test.normal" namespace.',
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Schema" tab for the "test.normal" namespace. "test.normal" does not support Atlas Search indexes. Server version: 7.0.0',
},
// Timeseries Collection
{
Expand All @@ -204,11 +210,17 @@ describe('prompts', function () {
},
activeCollectionMetadata: {
isTimeSeries: true,
isClustered: false,
isFLE: false,
isSearchIndexesSupported: false,
isDataLake: false,
isAtlas: false,
serverVersion: '',
},
activeCollectionSubTab: 'Aggregations',
},
expected:
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Aggregations" tab for the "test.timeseries" namespace. "test.timeseries" is a time-series collection.',
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Aggregations" tab for the "test.timeseries" namespace. "test.timeseries" is a time-series collection, does not support Atlas Search indexes. Server version: ',
},
// View Collection
{
Expand All @@ -228,11 +240,191 @@ describe('prompts', function () {
activeCollectionMetadata: {
isTimeSeries: false,
sourceName: 'test.normal',
isClustered: false,
isFLE: false,
isSearchIndexesSupported: false,
isDataLake: false,
isAtlas: false,
serverVersion: '7.0.0',
},
activeCollectionSubTab: 'Documents',
},
expected:
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Documents" tab for the "test.view" namespace. "test.view" is a view on the "test.normal" collection.',
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Documents" tab for the "test.view" namespace. "test.view" is a view on the "test.normal" collection, does not support Atlas Search indexes. Server version: 7.0.0',
},
// Clustered Collection
{
context: {
activeWorkspace: {
id: 'collection-tab-1',
type: 'Collection',
connectionId: 'conn-1',
namespace: 'test.clustered',
subTab: 'Schema',
},
activeConnection: {
connectionOptions: {
connectionString: 'mongodb://localhost:27017',
},
},
activeCollectionMetadata: {
isTimeSeries: false,
isClustered: true,
isFLE: false,
isSearchIndexesSupported: false,
isDataLake: false,
isAtlas: false,
serverVersion: '7.0.0',
},
activeCollectionSubTab: 'Schema',
},
expected:
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Schema" tab for the "test.clustered" namespace. "test.clustered" is a clustered collection, does not support Atlas Search indexes. Server version: 7.0.0',
},
// FLE Collection
{
context: {
activeWorkspace: {
id: 'collection-tab-1',
type: 'Collection',
connectionId: 'conn-1',
namespace: 'test.encrypted',
subTab: 'Documents',
},
activeConnection: {
connectionOptions: {
connectionString: 'mongodb://localhost:27017',
},
},
activeCollectionMetadata: {
isTimeSeries: false,
isClustered: false,
isFLE: true,
isSearchIndexesSupported: false,
isDataLake: false,
isAtlas: false,
serverVersion: '7.0.0',
},
activeCollectionSubTab: 'Documents',
},
expected:
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Documents" tab for the "test.encrypted" namespace. "test.encrypted" has encrypted fields, does not support Atlas Search indexes. Server version: 7.0.0',
},
// Collection with Search Indexes Support
{
context: {
activeWorkspace: {
id: 'collection-tab-1',
type: 'Collection',
connectionId: 'conn-1',
namespace: 'test.searchable',
subTab: 'Indexes',
},
activeConnection: {
connectionOptions: {
connectionString: 'mongodb+srv://cluster.mongodb.net',
},
},
activeCollectionMetadata: {
isTimeSeries: false,
isClustered: false,
isFLE: false,
isSearchIndexesSupported: true,
isDataLake: false,
isAtlas: true,
serverVersion: '7.0.0',
},
activeCollectionSubTab: 'Indexes',
},
expected:
'The connection is named "cluster.mongodb.net". The redacted connection string is "mongodb+srv://cluster.mongodb.net/".\n\nThe user is on the "Indexes" tab for the "test.searchable" namespace. "test.searchable" supports Atlas Search indexes. The instance is Atlas. Server version: 7.0.0',
},
// Data Lake Collection
{
context: {
activeWorkspace: {
id: 'collection-tab-1',
type: 'Collection',
connectionId: 'conn-1',
namespace: 'test.datalake',
subTab: 'Documents',
},
activeConnection: {
connectionOptions: {
connectionString: 'mongodb+srv://datalake.mongodb.net',
},
},
activeCollectionMetadata: {
isTimeSeries: false,
isClustered: false,
isFLE: false,
isSearchIndexesSupported: false,
isDataLake: true,
isAtlas: true,
serverVersion: '6.0.0',
},
activeCollectionSubTab: 'Documents',
},
expected:
'The connection is named "datalake.mongodb.net". The redacted connection string is "mongodb+srv://datalake.mongodb.net/".\n\nThe user is on the "Documents" tab for the "test.datalake" namespace. "test.datalake" does not support Atlas Search indexes. The instance is Data Lake and Atlas. Server version: 6.0.0',
},
// Collection with multiple features
{
context: {
activeWorkspace: {
id: 'collection-tab-1',
type: 'Collection',
connectionId: 'conn-1',
namespace: 'test.multifeature',
subTab: 'Aggregations',
},
activeConnection: {
connectionOptions: {
connectionString: 'mongodb+srv://cluster.mongodb.net',
},
},
activeCollectionMetadata: {
isTimeSeries: true,
isClustered: true,
isFLE: true,
isSearchIndexesSupported: true,
isDataLake: false,
isAtlas: true,
serverVersion: '8.0.0',
},
activeCollectionSubTab: 'Aggregations',
},
expected:
'The connection is named "cluster.mongodb.net". The redacted connection string is "mongodb+srv://cluster.mongodb.net/".\n\nThe user is on the "Aggregations" tab for the "test.multifeature" namespace. "test.multifeature" is a time-series collection, is a clustered collection, has encrypted fields, supports Atlas Search indexes. The instance is Atlas. Server version: 8.0.0',
},
// Collection without server version
{
context: {
activeWorkspace: {
id: 'collection-tab-1',
type: 'Collection',
connectionId: 'conn-1',
namespace: 'test.noversion',
subTab: 'Documents',
},
activeConnection: {
connectionOptions: {
connectionString: 'mongodb://localhost:27017',
},
},
activeCollectionMetadata: {
isTimeSeries: false,
isClustered: false,
isFLE: false,
isSearchIndexesSupported: false,
isDataLake: false,
isAtlas: false,
serverVersion: '7.0.0',
},
activeCollectionSubTab: 'Documents',
},
expected:
'The connection is named "localhost:27017". The redacted connection string is "mongodb://localhost:27017/".\n\nThe user is on the "Documents" tab for the "test.noversion" namespace. "test.noversion" does not support Atlas Search indexes. Server version: 7.0.0',
},
];

Expand All @@ -246,6 +438,21 @@ describe('prompts', function () {
if (testCase.context.activeCollectionMetadata?.sourceName) {
summary.isView = true;
}
if (testCase.context.activeCollectionMetadata?.isClustered) {
summary.isClustered = true;
}
if (testCase.context.activeCollectionMetadata?.isFLE) {
summary.isFLE = true;
}
if (testCase.context.activeCollectionMetadata?.isSearchIndexesSupported) {
summary.isSearchIndexesSupported = true;
}
if (testCase.context.activeCollectionMetadata?.isDataLake) {
summary.isDataLake = true;
}
if (testCase.context.activeCollectionMetadata?.isAtlas) {
summary.isAtlas = true;
}
if (hasSubtab(testCase.context.activeWorkspace)) {
summary.subTab = testCase.context.activeWorkspace.subTab;
}
Expand Down
58 changes: 47 additions & 11 deletions packages/compass-assistant/src/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,8 @@ export const buildProactiveInsightsPrompt = (
switch (context.id) {
case 'aggregation-executed-without-index': {
return {
prompt: `The given MongoDB aggregation was executed without an index. Provide a concise human readable explanation that explains why it might degrade performance to not use an index.

Please suggest whether an existing index can be used to improve the performance of this query, or if a new index must be created, and describe how it can be accomplished in MongoDB Compass. Do not advise users to create indexes without weighing the pros and cons.

Respond with as much concision and clarity as possible.
prompt: `Provide a concise, human-readable explanation of why not using an index for this aggregation can degrade performance. Do not refer to the specifics of the explain plan output, but use it to contextualize your recommendations. Assess whether any existing indexes could optimize this operation, or if a new index could improve performance. Do not ever explicitly instruct to create an index. If a new index might help, mention important pros and cons of adding an index, not just benefits, and briefly describe how to create it in MongoDB Compass.
Consider the type of collection (e.g. view v. not). If tools are available, use the \`explain\` tool to get the explain plan output, use the \`list-indexes\` tool to get the list of indexes for this collection.

<input>
${context.stages.join('\n')}
Expand Down Expand Up @@ -244,8 +241,14 @@ export function buildContextPrompt({
activeConnection: Pick<ConnectionInfo, 'connectionOptions'> | null;
activeCollectionMetadata: Pick<
CollectionMetadata,
'isTimeSeries' | 'sourceName'
// TODO(COMPASS-10173): isClustered, isFLE, isSearchIndexesSupported, isDataLake, isAtlas, serverVersion
| 'isTimeSeries'
| 'sourceName'
| 'isClustered'
| 'isFLE'
| 'isSearchIndexesSupported'
| 'isDataLake'
| 'isAtlas'
| 'serverVersion'
> | null;
activeCollectionSubTab: CollectionSubtab | null;
}): AssistantMessage {
Expand All @@ -269,17 +272,50 @@ export function buildContextPrompt({
: '';
const lines = [`The user is on the "${tabName}" tab${namespacePart}.`];
if (isNamespaceTab && activeConnection && activeCollectionMetadata) {
const collectionDetails: string[] = [];
if (activeCollectionMetadata.isTimeSeries) {
lines.push(
`"${activeWorkspace.namespace}" is a time-series collection.`
);
collectionDetails.push('is a time-series collection');
}

if (activeCollectionMetadata.sourceName) {
collectionDetails.push(
`is a view on the "${activeCollectionMetadata.sourceName}" collection`
);
}

if (activeCollectionMetadata.isClustered) {
collectionDetails.push('is a clustered collection');
}

if (activeCollectionMetadata.isFLE) {
collectionDetails.push('has encrypted fields');
}

if (activeCollectionMetadata.isSearchIndexesSupported) {
collectionDetails.push('supports Atlas Search indexes');
} else {
collectionDetails.push('does not support Atlas Search indexes');
}

if (collectionDetails.length > 0) {
lines.push(
`"${activeWorkspace.namespace}" is a view on the "${activeCollectionMetadata.sourceName}" collection.`
`"${activeWorkspace.namespace}" ${collectionDetails.join(', ')}.`
);
}

// Instance metadata
const instanceDetails: string[] = [];
if (activeCollectionMetadata.isDataLake) {
instanceDetails.push('Data Lake');
}
if (activeCollectionMetadata.isAtlas) {
instanceDetails.push('Atlas');
}

if (instanceDetails.length > 0) {
lines.push(`The instance is ${instanceDetails.join(' and ')}.`);
}
lines.push(`Server version: ${activeCollectionMetadata.serverVersion}`);
}
parts.push(lines.join(' '));
} else {
Expand Down
Loading
Loading