Skip to content

Commit 8770bec

Browse files
authored
EAI-1027 Add more scrubbed message data for analytics (#749)
* Add clean origin names to customData * Add thumbsup/down & commented data to scrubbed user message * EAI-1006 Track origin code in Braintrust
1 parent 82da6ac commit 8770bec

File tree

6 files changed

+116
-6
lines changed

6 files changed

+116
-6
lines changed

packages/chatbot-server-mongodb-public/src/tracing/extractTracingData.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { ObjectId } from "mongodb-rag-core/mongodb";
88
import { llmDoesNotKnowMessage } from "../systemPrompt";
99
import { strict as assert } from "assert";
10+
import { OriginCode } from "mongodb-chatbot-server";
1011

1112
export function extractTracingData(
1213
messages: Message[],
@@ -41,12 +42,18 @@ export function extractTracingData(
4142
const mongoDbProduct = previousUserMessage?.customData?.mongoDbProduct as
4243
| string
4344
| undefined;
45+
const requestOriginCode = previousUserMessage?.customData?.originCode as
46+
| OriginCode
47+
| undefined;
4448
if (programmingLanguage) {
4549
tags.push(tagify(programmingLanguage));
4650
}
4751
if (mongoDbProduct) {
4852
tags.push(tagify(mongoDbProduct));
4953
}
54+
if (requestOriginCode) {
55+
tags.push(tagify(requestOriginCode));
56+
}
5057

5158
const numRetrievedChunks = previousUserMessage?.contextContent?.length ?? 0;
5259
if (numRetrievedChunks === 0) {

packages/chatbot-server-mongodb-public/src/tracing/routesUpdateTraceHandlers.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
import { logRequest } from "../utils";
1818
import { Logger } from "mongodb-rag-core/braintrust";
1919
import { ScrubbedMessageStore } from "./scrubbedMessages/ScrubbedMessageStore";
20+
import { ScrubbedMessage } from "./scrubbedMessages/ScrubbedMessage";
2021
import { LanguageModel } from "mongodb-rag-core/aiSdk";
2122
import { makeScrubbedMessagesFromTracingData } from "./scrubbedMessages/makeScrubbedMessagesFromTracingData";
2223
import { redactPii } from "./scrubbedMessages/redactPii";
@@ -87,7 +88,7 @@ export function makeAddMessageToConversationUpdateTrace({
8788
} catch (error) {
8889
logRequest({
8990
reqId,
90-
message: `Error scrubbing messages ${error}`,
91+
message: `Error scrubbing messages while adding message ${error}`,
9192
type: "error",
9293
});
9394
}
@@ -249,10 +250,18 @@ export function makeRateMessageUpdateTrace({
249250
responseRating: rating,
250251
},
251252
});
253+
254+
assert(userMessage?.id, "Missing user message for rating");
255+
await scrubbedMessageStore.updateScrubbedMessage({
256+
id: userMessage.id,
257+
message: {
258+
"response.responseRating": rating,
259+
} as Partial<Omit<ScrubbedMessage, "_id">>,
260+
});
252261
} catch (error) {
253262
logRequest({
254263
reqId: traceId,
255-
message: `Error scrubbing messages ${error}`,
264+
message: `Error scrubbing messages during rating ${error}`,
256265
type: "error",
257266
});
258267
}
@@ -357,24 +366,33 @@ export function makeCommentMessageUpdateTrace({
357366
try {
358367
const { redactedText: userComment, piiFound } = redactPii(comment ?? "");
359368
assert(assistantMessage?.id, "Missing assistant message for comment");
360-
const fieldsToUpdate: Record<string, unknown> = {
369+
const assistantMessageFieldsToUpdate: Record<string, unknown> = {
361370
userComment,
362371
userCommented: true,
363372
userCommentPii: piiFound,
364373
};
365374
// Update PII only if true.
366375
// This way it doesn't override it previously having been set.
367376
if (piiFound?.length) {
368-
fieldsToUpdate.pii = true;
377+
assistantMessageFieldsToUpdate.pii = true;
369378
}
370379
await scrubbedMessageStore.updateScrubbedMessage({
371380
id: assistantMessage.id,
372-
message: fieldsToUpdate,
381+
message: assistantMessageFieldsToUpdate,
382+
});
383+
384+
assert(userMessage?.id, "Missing user message for comment");
385+
await scrubbedMessageStore.updateScrubbedMessage({
386+
id: userMessage.id,
387+
message: {
388+
"response.userCommented": true,
389+
"response.userComment": userComment
390+
} as Partial<Omit<ScrubbedMessage, "_id">>,
373391
});
374392
} catch (error) {
375393
logRequest({
376394
reqId: traceId,
377-
message: `Error scrubbing messages ${error}`,
395+
message: `Error scrubbing messages during comment ${error}`,
378396
type: "error",
379397
});
380398
}

packages/chatbot-server-mongodb-public/src/tracing/scrubbedMessages/ScrubbedMessage.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ObjectId } from "mongodb";
22
import { DbMessage, SomeMessage } from "mongodb-rag-core";
33
import { Pii } from "./redactPii";
4+
import { OriginCode } from "mongodb-chatbot-server";
45

56
export type ScrubbedMessage<
67
Analysis extends Record<string, unknown> | undefined = undefined
@@ -73,4 +74,27 @@ export type ScrubbedMessage<
7374
Any PII redacted from the original user comment.
7475
*/
7576
userCommentPii?: Pii[];
77+
78+
/**
79+
For 'user' role messages, track information about the subsequent assistant
80+
response to the user message.
81+
*/
82+
response?: {
83+
isVerifiedAnswer?: boolean;
84+
userCommented?: boolean;
85+
userComment?: string;
86+
responseRating?: boolean;
87+
[key: string]: unknown;
88+
};
89+
90+
/**
91+
For 'assistant' role messages, track information about the user request preceding
92+
this assistant response.
93+
*/
94+
request?: {
95+
userTopics?: string[] | null;
96+
origin?: string;
97+
originCode?: OriginCode;
98+
[key: string]: unknown;
99+
};
76100
};

packages/chatbot-server-mongodb-public/src/tracing/scrubbedMessages/makeScrubbedMessagesFromTracingData.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { analyzeMessage, MessageAnalysis } from "./analyzeMessage";
44
import { redactPii } from "./redactPii";
55
import { ScrubbedMessage } from "./ScrubbedMessage";
66
import { LanguageModel } from "mongodb-rag-core/aiSdk";
7+
import { OriginCode } from "mongodb-chatbot-server";
78

89
export async function makeScrubbedMessagesFromTracingData({
910
tracingData,
@@ -49,6 +50,9 @@ export async function makeScrubbedMessagesFromTracingData({
4950
customData: userMessage.customData,
5051
pii: userMessagePii?.length ? true : undefined,
5152
metadata: userMessage.metadata,
53+
response: {
54+
isVerifiedAnswer: tracingData?.isVerifiedAnswer ? true : false,
55+
},
5256
embedding: userMessage.embedding,
5357
embeddingModelName,
5458
messagePii: userMessagePii.length ? userMessagePii : undefined,
@@ -57,18 +61,28 @@ export async function makeScrubbedMessagesFromTracingData({
5761
} satisfies ScrubbedMessage<MessageAnalysis>;
5862

5963
// Assistant message scrubbing
64+
const assistantAnalysis = analysis && !tracingData.isVerifiedAnswer
65+
? await analyzeMessage(assistantMessage.content, analysis.model)
66+
: undefined;
6067
const {
6168
redactedText: redactedAssistantContent,
6269
piiFound: assistantMessagePii,
6370
} = redactPii(assistantMessage.content);
71+
6472
const scrubbedAssistantMessage = {
6573
_id: assistantMessage.id,
6674
conversationId: tracingData.conversationId,
6775
index: tracingData.assistantMessageIndex,
76+
analysis: assistantAnalysis,
6877
role: assistantMessage.role,
6978
content: redactedAssistantContent,
7079
createdAt: assistantMessage.createdAt,
7180
customData: assistantMessage.customData,
81+
request: {
82+
userTopics: userAnalysis?.topics,
83+
origin: userMessage?.customData?.origin as string,
84+
originCode: userMessage?.customData?.originCode as OriginCode,
85+
},
7286
pii: assistantMessagePii?.length ? true : undefined,
7387
metadata: assistantMessage.metadata,
7488
messagePii: assistantMessagePii.length ? assistantMessagePii : undefined,

packages/mongodb-chatbot-server/src/routes/conversations/addMessageToConversation.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ describe("POST /conversations/:conversationId/messages", () => {
119119
expect(userMessageWithCustomData?.customData).toStrictEqual({
120120
ip: ipAddress,
121121
origin,
122+
originCode: "OTHER",
122123
userAgent: "test-user-agent",
123124
});
124125
});

packages/mongodb-chatbot-server/src/routes/conversations/conversationsRouter.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,50 @@ const addOriginToCustomData: AddCustomDataFunc = async (_, res) =>
236236
}
237237
: undefined;
238238

239+
export const originCodes = [
240+
"LEARN",
241+
"DEVELOPER",
242+
"DOCS",
243+
"DOTCOM",
244+
"GEMINI_CODE_ASSIST",
245+
"VSCODE",
246+
"OTHER",
247+
] as const;
248+
249+
export type OriginCode = (typeof originCodes)[number];
250+
251+
interface OriginRule {
252+
regex: RegExp;
253+
code: OriginCode;
254+
}
255+
256+
const ORIGIN_RULES: OriginRule[] = [
257+
{ regex: /learn\.mongodb\.com/, code: "LEARN" },
258+
{ regex: /mongodb\.com\/developer/, code: "DEVELOPER" },
259+
{ regex: /mongodb\.com\/docs/, code: "DOCS" },
260+
{ regex: /mongodb\.com\//, code: "DOTCOM" },
261+
{ regex: /google-gemini-code-assist/, code: "GEMINI_CODE_ASSIST" },
262+
{ regex: /vscode-mongodb-copilot/, code: "VSCODE" },
263+
];
264+
265+
function getOriginCode(origin: string): OriginCode {
266+
for (const rule of ORIGIN_RULES) {
267+
if (rule.regex.test(origin)) {
268+
return rule.code;
269+
}
270+
}
271+
return "OTHER";
272+
}
273+
274+
const addOriginCodeToCustomData: AddCustomDataFunc = async (_, res) => {
275+
const origin = res.locals.customData.origin;
276+
return typeof origin === "string" && origin.length > 0
277+
? {
278+
originCode: getOriginCode(origin),
279+
}
280+
: undefined;
281+
}
282+
239283
const addUserAgentToCustomData: AddCustomDataFunc = async (req) =>
240284
req.headers["user-agent"]
241285
? {
@@ -252,6 +296,7 @@ export const defaultCreateConversationCustomData: AddDefinedCustomDataFunc =
252296
return {
253297
...(await addIpToCustomData(req, res)),
254298
...(await addOriginToCustomData(req, res)),
299+
...(await addOriginCodeToCustomData(req, res)),
255300
...(await addUserAgentToCustomData(req, res)),
256301
};
257302
};
@@ -261,6 +306,7 @@ export const defaultAddMessageToConversationCustomData: AddDefinedCustomDataFunc
261306
return {
262307
...(await addIpToCustomData(req, res)),
263308
...(await addOriginToCustomData(req, res)),
309+
...(await addOriginCodeToCustomData(req, res)),
264310
...(await addUserAgentToCustomData(req, res)),
265311
};
266312
};

0 commit comments

Comments
 (0)