Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -28,6 +28,7 @@ import type { ConnectionInfo } from '@mongodb-js/connection-info';
import { useTelemetry } from '@mongodb-js/compass-telemetry/provider';
import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider';
import { atlasAiServiceLocator } from '@mongodb-js/compass-generative-ai/provider';
import { buildConversationInstructionsPrompt } from './prompts';

export const ASSISTANT_DRAWER_ID = 'compass-assistant-drawer';

Expand Down Expand Up @@ -248,6 +249,9 @@ export const CompassAssistantProvider = registerCompassPlugin(
new Chat({
transport: new DocsProviderTransport({
baseUrl: atlasService.assistantApiEndpoint(),
instructions: buildConversationInstructionsPrompt({
target: atlasAiService.getAppNameForPrompt(),
}),
}),
onError: (err: Error) => {
logger.log.error(
Expand Down
15 changes: 14 additions & 1 deletion packages/compass-assistant/src/docs-provider-transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@ import { createOpenAI } from '@ai-sdk/openai';

export class DocsProviderTransport implements ChatTransport<UIMessage> {
private openai: ReturnType<typeof createOpenAI>;
private instructions: string;

constructor({ baseUrl }: { baseUrl: string }) {
constructor({
baseUrl,
instructions,
}: {
baseUrl: string;
instructions: string;
}) {
this.openai = createOpenAI({
baseURL: baseUrl,
apiKey: '',
});
this.instructions = instructions;
}

sendMessages({
Expand All @@ -25,6 +33,11 @@ export class DocsProviderTransport implements ChatTransport<UIMessage> {
model: this.openai.responses('mongodb-chat-latest'),
messages: convertToModelMessages(messages),
abortSignal: abortSignal,
providerOptions: {
openai: {
instructions: this.instructions,
},
},
});

return Promise.resolve(result.toUIMessageStream());
Expand Down
10 changes: 10 additions & 0 deletions packages/compass-assistant/src/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import type { ConnectionInfo } from '@mongodb-js/connection-info';
import { redactConnectionString } from 'mongodb-connection-string-url';

export const buildConversationInstructionsPrompt = ({
target,
}: {
target: string;
}) => {
// TODO: we'll want to greatly expand on this, but at minimum this is where we
// make the distinction between running inside Data Explorer vs Compass.
return `You are an assistant running in a side-panel inside ${target}.`;
};

export type EntryPointMessage = {
prompt: string;
displayText?: string;
Expand Down
13 changes: 12 additions & 1 deletion packages/compass-generative-ai/src/atlas-ai-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ describe('AtlasAiService', function () {
const endpointBasepathTests = [
{
apiURLPreset: 'admin-api',
expectedPromptName: 'MongoDB Compass',
expectedEndpoints: {
'mql-aggregation': `http://example.com/unauth/ai/api/v1/mql-aggregation?request_id=abc`,
'mql-query': `http://example.com/unauth/ai/api/v1/mql-query?request_id=abc`,
},
},
{
apiURLPreset: 'cloud',
expectedPromptName: 'Atlas Data Explorer',
expectedEndpoints: {
'mql-aggregation':
'/cloud/ai/v1/groups/testProject/mql-aggregation?request_id=abc',
Expand All @@ -102,7 +104,11 @@ describe('AtlasAiService', function () {
},
] as const;

for (const { apiURLPreset, expectedEndpoints } of endpointBasepathTests) {
for (const {
apiURLPreset,
expectedPromptName,
expectedEndpoints,
} of endpointBasepathTests) {
describe(`api URL Preset "${apiURLPreset}"`, function () {
let atlasAiService: AtlasAiService;

Expand All @@ -116,6 +122,11 @@ describe('AtlasAiService', function () {
});
});

it('returns the correct app name for prompts', function () {
const appName = atlasAiService.getAppNameForPrompt();
expect(appName).to.equal(expectedPromptName);
});

describe('getQueryFromUserInput and getAggregationFromUserInput', function () {
beforeEach(async function () {
// Enable the AI feature
Expand Down
12 changes: 12 additions & 0 deletions packages/compass-generative-ai/src/atlas-ai-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,16 @@ export class AtlasAiService {
throw new Error('Unexpected response: expected features to be an object');
}
}

getAppNameForPrompt() {
// This returns the name we will use to inform the chatbot of the
// application context. The more descriptive the better so we probably don't
// want it to match the marketing name. We also don't want it to behave
// different between dev/beta/staging or readonly vs isolated, so it doesn't
// map to the electron app name either.
if (this.apiURLPreset === 'cloud') {
return 'Atlas Data Explorer';
}
return 'MongoDB Compass';
}
}
Loading