From beab0afb4ff682109eef9f47dc22580f7a8248ce Mon Sep 17 00:00:00 2001 From: Alla Yakubova Date: Tue, 25 Mar 2025 18:40:26 -0400 Subject: [PATCH 1/6] allow tag list in generate eval cases --- .../eval/bin/generateEvalCasesYamlFromCSV.ts | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts b/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts index faa464244..472c03ec0 100644 --- a/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts +++ b/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts @@ -63,24 +63,34 @@ const pageStore = makeMongoDbPageStore({ databaseName: MONGODB_DATABASE_NAME, }); -function addWebDataSourceTag(evalCases: ConversationEvalCase[]) { - return evalCases.map((caseItem) => { - const tags = caseItem.tags || []; - if (!tags.includes("web")) { - tags.push("web"); +const allowedTags: { [key: string]: boolean } = { + allowed: true, + alsoAllowed: true, +} + +function validateTags(tagNames: string[], custom: boolean): void { + if (!custom) { + const invalidTags = tagNames.filter(tag => !allowedTags[tag]); + if (invalidTags.length) { + throw new Error(`Tags not allowed: ${invalidTags.join(', ')}. \n Use the "addCustomTags" transformation or use allowed tags: ${Object.keys(allowedTags)}\n`); } - return { - ...caseItem, - tags, - }; - }); + } +} + +function addTags({ evalCases, tagNames, custom = false }: { evalCases: ConversationEvalCase[]; tagNames: string[]; custom?: boolean; }): ConversationEvalCase[] { + validateTags(tagNames, custom); + return evalCases.map(caseItem => ({ + ...caseItem, + tags: [...(caseItem.tags || []), ...tagNames] + })); } const transformationMap: Record< string, - (cases: ConversationEvalCase[]) => ConversationEvalCase[] + (cases: ConversationEvalCase[], options?: string[]) => ConversationEvalCase[] > = { - web: addWebDataSourceTag, + addTags: (cases: ConversationEvalCase[], options?: string[]) => addTags({ evalCases: cases, tagNames: options || [] }), + addCustomTags: (cases: ConversationEvalCase[], options?: string[]) => addTags({ evalCases: cases, tagNames: options || [], custom: true }), // Add more transformation functions here as needed }; @@ -117,15 +127,17 @@ async function main({ csvFilePath, yamlFileName, transformationType, + transformationOptions, }: { csvFilePath: string; yamlFileName: string; transformationType?: keyof typeof transformationMap; + transformationOptions?: string[]; }): Promise { console.log(`Reading from: ${csvFilePath}`); const evalCases = await getConversationEvalCasesFromCSV( csvFilePath, - transformationType ? transformationMap[transformationType] : undefined + transformationType ? (cases) => transformationMap[transformationType](cases, transformationOptions) : undefined, ); const expectedUrls = Array.from( new Set(evalCases.flatMap((caseItem) => caseItem.expectedLinks ?? [])) @@ -153,7 +165,7 @@ async function main({ // Checks if the script is being run directly (not imported as a module) and handles command-line arguments. if (require.main === module) { const args = process.argv.slice(2); - const [csvFilePath, yamlFileName, transformationType] = args; + const [csvFilePath, yamlFileName, transformationType, ...transformationOptions] = args; const availableTransformationTypes = Object.keys(transformationMap); if ( args.length < 2 || @@ -161,7 +173,7 @@ if (require.main === module) { !availableTransformationTypes.includes(transformationType)) ) { console.error( - "Usage: node generateEvalCasesYamlFromCSV.js [transformationType]\n" + + "Usage: node generateEvalCasesYamlFromCSV.js [transformationType] [tranformationOptions]\n" + "Arguments:\n" + " csvFileName: Input CSV file name (required)\n" + " yamlFileName: Output YAML file name (required)\n" + @@ -177,6 +189,7 @@ if (require.main === module) { csvFilePath, yamlFileName, transformationType, + transformationOptions, }) .catch((error) => { console.error("Error:", error); From 3483b837ae4dc25280933efb9b398c78ef129221 Mon Sep 17 00:00:00 2001 From: Alla Yakubova Date: Wed, 26 Mar 2025 12:11:25 -0400 Subject: [PATCH 2/6] use MongoDbTag to determine allowed tags --- .../eval/bin/generateEvalCasesYamlFromCSV.ts | 53 +++++++++++++------ .../src/mongoDbMetadata/tags.ts | 33 ++++++++++-- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts b/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts index 472c03ec0..94af7d218 100644 --- a/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts +++ b/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts @@ -55,6 +55,7 @@ import { } from "mongodb-rag-core/eval"; import { MONGODB_CONNECTION_URI, MONGODB_DATABASE_NAME } from "../../config"; import { makeMongoDbPageStore } from "mongodb-rag-core"; +import { MongoDbTag } from "../../mongoDbMetadata"; const SRC_ROOT = path.resolve(__dirname, "../"); @@ -63,25 +64,37 @@ const pageStore = makeMongoDbPageStore({ databaseName: MONGODB_DATABASE_NAME, }); -const allowedTags: { [key: string]: boolean } = { - allowed: true, - alsoAllowed: true, -} - function validateTags(tagNames: string[], custom: boolean): void { if (!custom) { - const invalidTags = tagNames.filter(tag => !allowedTags[tag]); - if (invalidTags.length) { - throw new Error(`Tags not allowed: ${invalidTags.join(', ')}. \n Use the "addCustomTags" transformation or use allowed tags: ${Object.keys(allowedTags)}\n`); + // check if all tags are allowed using the enum MongoDbTag + const invalidTags = tagNames.filter((tag) => !(tag in MongoDbTag)); + if (invalidTags.length > 0) { + throw new Error( + `Invalid tags found: ${invalidTags.join( + ", " + )} \nUse the "addCustomTags" transformation instead or use allowed tags: \n - ${Object.keys( + MongoDbTag + ) + .sort() + .join("\n - ")}` + ); } } } -function addTags({ evalCases, tagNames, custom = false }: { evalCases: ConversationEvalCase[]; tagNames: string[]; custom?: boolean; }): ConversationEvalCase[] { +function addTags({ + evalCases, + tagNames, + custom = false, +}: { + evalCases: ConversationEvalCase[]; + tagNames: string[]; + custom?: boolean; +}): ConversationEvalCase[] { validateTags(tagNames, custom); - return evalCases.map(caseItem => ({ + return evalCases.map((caseItem) => ({ ...caseItem, - tags: [...(caseItem.tags || []), ...tagNames] + tags: [...(caseItem.tags || []), ...tagNames], })); } @@ -89,8 +102,10 @@ const transformationMap: Record< string, (cases: ConversationEvalCase[], options?: string[]) => ConversationEvalCase[] > = { - addTags: (cases: ConversationEvalCase[], options?: string[]) => addTags({ evalCases: cases, tagNames: options || [] }), - addCustomTags: (cases: ConversationEvalCase[], options?: string[]) => addTags({ evalCases: cases, tagNames: options || [], custom: true }), + addTags: (cases: ConversationEvalCase[], options?: string[]) => + addTags({ evalCases: cases, tagNames: options || [] }), + addCustomTags: (cases: ConversationEvalCase[], options?: string[]) => + addTags({ evalCases: cases, tagNames: options || [], custom: true }), // Add more transformation functions here as needed }; @@ -137,7 +152,10 @@ async function main({ console.log(`Reading from: ${csvFilePath}`); const evalCases = await getConversationEvalCasesFromCSV( csvFilePath, - transformationType ? (cases) => transformationMap[transformationType](cases, transformationOptions) : undefined, + transformationType + ? (cases) => + transformationMap[transformationType](cases, transformationOptions) + : undefined ); const expectedUrls = Array.from( new Set(evalCases.flatMap((caseItem) => caseItem.expectedLinks ?? [])) @@ -165,7 +183,12 @@ async function main({ // Checks if the script is being run directly (not imported as a module) and handles command-line arguments. if (require.main === module) { const args = process.argv.slice(2); - const [csvFilePath, yamlFileName, transformationType, ...transformationOptions] = args; + const [ + csvFilePath, + yamlFileName, + transformationType, + ...transformationOptions + ] = args; const availableTransformationTypes = Object.keys(transformationMap); if ( args.length < 2 || diff --git a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts b/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts index a42538888..9e97bb71c 100644 --- a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts +++ b/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts @@ -10,8 +10,31 @@ const mongoDbTopicIds = mongoDbTopics.map((topic) => topic.id); /** All possible MongoDB tags. Useful for tagging evaluations. */ -export type MongoDbTag = - | (typeof mongoDbProgrammingLanguageIds)[number] - | (typeof mongoDbProductIds)[number] - | (typeof mongoDbDriverIds)[number] - | (typeof mongoDbTopicIds)[number]; +export const MongoDbTag = { + // Add all programming language IDs + ...mongoDbProgrammingLanguageIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), + + // Add all product IDs + ...mongoDbProductIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), + + // Add all driver IDs + ...mongoDbDriverIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), + + // Add all topic IDs + ...mongoDbTopicIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), +} as const; + +// Define the type based on the const object +export type MongoDbTag = keyof typeof MongoDbTag; From eeb178130560747a1b8f425e1bfc1325d29f6e06 Mon Sep 17 00:00:00 2001 From: Alla Yakubova Date: Mon, 7 Apr 2025 14:38:10 -0400 Subject: [PATCH 3/6] move mongoDbMetadata to core --- .../src/eval/ConversationEval.ts | 2 +- .../eval/bin/generateEvalCasesYamlFromCSV.ts | 38 +++------- .../experiments/skillsQuestionsTest.eval.ts | 7 +- .../chatbot-server-mongodb-public/src/lib.ts | 2 +- .../src/mongoDbMetadata/tags.ts | 40 ---------- ...ractMongoDbMetadataFromUserMessage.eval.ts | 2 +- .../extractMongoDbMetadataFromUserMessage.ts | 2 +- .../processors/makeStepBackUserQuery.eval.ts | 2 +- .../src/processors/makeStepBackUserQuery.ts | 5 +- .../retrieveRelevantContent.eval.ts | 2 +- .../userMessageMongoDbGuardrail.eval.ts | 2 +- .../processors/userMessageMongoDbGuardrail.ts | 4 +- .../src/verifiedAnswers.eval.ts | 2 +- packages/mongodb-rag-core/src/index.ts | 1 + .../src/mongoDbMetadata/index.ts | 0 .../src/mongoDbMetadata/products.ts | 0 .../mongoDbMetadata/programmingLanguages.ts | 0 .../src/mongoDbMetadata/tags.ts | 76 +++++++++++++++++++ .../src/mongoDbMetadata/topics.ts | 0 19 files changed, 105 insertions(+), 82 deletions(-) delete mode 100644 packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts rename packages/{chatbot-server-mongodb-public => mongodb-rag-core}/src/mongoDbMetadata/index.ts (100%) rename packages/{chatbot-server-mongodb-public => mongodb-rag-core}/src/mongoDbMetadata/products.ts (100%) rename packages/{chatbot-server-mongodb-public => mongodb-rag-core}/src/mongoDbMetadata/programmingLanguages.ts (100%) create mode 100644 packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts rename packages/{chatbot-server-mongodb-public => mongodb-rag-core}/src/mongoDbMetadata/topics.ts (100%) diff --git a/packages/chatbot-server-mongodb-public/src/eval/ConversationEval.ts b/packages/chatbot-server-mongodb-public/src/eval/ConversationEval.ts index c02455256..251ffeee1 100644 --- a/packages/chatbot-server-mongodb-public/src/eval/ConversationEval.ts +++ b/packages/chatbot-server-mongodb-public/src/eval/ConversationEval.ts @@ -21,7 +21,7 @@ import { Factuality, } from "autoevals"; import { strict as assert } from "assert"; -import { MongoDbTag } from "../mongoDbMetadata"; +import { MongoDbTag } from "mongodb-rag-core"; import { fuzzyLinkMatch } from "./fuzzyLinkMatch"; import { binaryNdcgAtK } from "./scorers/binaryNdcgAtK"; import { ConversationEvalCase as ConversationEvalCaseSource } from "mongodb-rag-core/eval"; diff --git a/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts b/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts index 94af7d218..84599c242 100644 --- a/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts +++ b/packages/chatbot-server-mongodb-public/src/eval/bin/generateEvalCasesYamlFromCSV.ts @@ -10,13 +10,13 @@ Can be run through npm script or directly using node: ```bash - npm run generate-eval-cases -- [transformationType] + npm run generate-eval-cases -- [transformationType] [transformationOptions] ``` Or: ```bash - node generateEvalCasesYamlFromCSV.js [transformationType] + node generateEvalCasesYamlFromCSV.js [transformationType] [transformationOptions] ``` ### Arguments @@ -24,10 +24,12 @@ - `csvFilePath`: (Required) Absolute path to the input CSV file - `yamlFileName`: (Required) Name of the output YAML file (without .yml extension) - `transformationType`: (Optional) Type of transformation to apply to the cases + - `transformationOptions`: (Optional) Additional options for the transformation ### Available Transformations - - `web`: Adds a "web" tag to all evaluation cases + - `addTags`: Adds specified tags to all evaluation cases + - `addCustomTags`: Adds specified custom tags to all evaluation cases ### File Paths @@ -36,14 +38,14 @@ ### Example ```bash - npm run generate-eval-cases -- Users/first.lastname/Downloads/input-file.csv output-file-name web + npm run generate-eval-cases -- /path/to/input.csv output-name addTags tag1 tag2 ``` This will: - 1. Read from: /Users/first.lastname/Downloads/input-file.csv - 2. Apply the web transformation - 3. Write to: evalCases/output-file-name.yml - 4. Log missing resources to the console in a warning + 1. Read from: /path/to/input.csv + 2. Add tags "tag1" and "tag2" to all cases, after validating them against the MongoDbTags enum. + 3. Write to: evalCases/output-name.yml + 4. Log any missing resources to the console as warnings */ import fs from "fs"; @@ -55,7 +57,7 @@ import { } from "mongodb-rag-core/eval"; import { MONGODB_CONNECTION_URI, MONGODB_DATABASE_NAME } from "../../config"; import { makeMongoDbPageStore } from "mongodb-rag-core"; -import { MongoDbTag } from "../../mongoDbMetadata"; +import { validateTags } from "mongodb-rag-core"; const SRC_ROOT = path.resolve(__dirname, "../"); @@ -64,24 +66,6 @@ const pageStore = makeMongoDbPageStore({ databaseName: MONGODB_DATABASE_NAME, }); -function validateTags(tagNames: string[], custom: boolean): void { - if (!custom) { - // check if all tags are allowed using the enum MongoDbTag - const invalidTags = tagNames.filter((tag) => !(tag in MongoDbTag)); - if (invalidTags.length > 0) { - throw new Error( - `Invalid tags found: ${invalidTags.join( - ", " - )} \nUse the "addCustomTags" transformation instead or use allowed tags: \n - ${Object.keys( - MongoDbTag - ) - .sort() - .join("\n - ")}` - ); - } - } -} - function addTags({ evalCases, tagNames, diff --git a/packages/chatbot-server-mongodb-public/src/eval/experiments/skillsQuestionsTest.eval.ts b/packages/chatbot-server-mongodb-public/src/eval/experiments/skillsQuestionsTest.eval.ts index d8059e3a2..bc054325b 100644 --- a/packages/chatbot-server-mongodb-public/src/eval/experiments/skillsQuestionsTest.eval.ts +++ b/packages/chatbot-server-mongodb-public/src/eval/experiments/skillsQuestionsTest.eval.ts @@ -17,7 +17,10 @@ async function conversationEval() { // Get dotcom question set eval cases from YAML const basePath = path.resolve(__dirname, "..", "..", "..", "evalCases"); const conversationEvalCases = getConversationsEvalCasesFromYaml( - fs.readFileSync(path.resolve(basePath, "uni_skills_evaluation_questions.yml"), "utf8") + fs.readFileSync( + path.resolve(basePath, "uni_skills_evaluation_questions.yml"), + "utf8" + ) ); const generateConfig = { @@ -52,4 +55,4 @@ async function conversationEval() { generate: generateConfig, }); } -conversationEval(); \ No newline at end of file +conversationEval(); diff --git a/packages/chatbot-server-mongodb-public/src/lib.ts b/packages/chatbot-server-mongodb-public/src/lib.ts index 45c3766a6..08d7bc9a6 100644 --- a/packages/chatbot-server-mongodb-public/src/lib.ts +++ b/packages/chatbot-server-mongodb-public/src/lib.ts @@ -3,4 +3,4 @@ Export some modules from the implementation for use in things like evaluation. */ export { systemPrompt } from "./systemPrompt"; -export * as mongoDbMetadata from "./mongoDbMetadata"; +export * as mongoDbMetadata from "mongodb-rag-core"; diff --git a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts b/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts deleted file mode 100644 index 9e97bb71c..000000000 --- a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/tags.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { mongoDbProducts, mongodbDrivers } from "./products"; -import { mongoDbProgrammingLanguageIds } from "./programmingLanguages"; -import { mongoDbTopics } from "./topics"; - -// Helpers for constructing the `MongoDbTag` union type -const mongoDbProductIds = mongoDbProducts.map((product) => product.id); -const mongoDbDriverIds = mongodbDrivers.map((driver) => driver.id); -const mongoDbTopicIds = mongoDbTopics.map((topic) => topic.id); - -/** - All possible MongoDB tags. Useful for tagging evaluations. - */ -export const MongoDbTag = { - // Add all programming language IDs - ...mongoDbProgrammingLanguageIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), - - // Add all product IDs - ...mongoDbProductIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), - - // Add all driver IDs - ...mongoDbDriverIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), - - // Add all topic IDs - ...mongoDbTopicIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), -} as const; - -// Define the type based on the const object -export type MongoDbTag = keyof typeof MongoDbTag; diff --git a/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.eval.ts b/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.eval.ts index 4767c845f..9ba358d06 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.eval.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.eval.ts @@ -4,7 +4,7 @@ import { } from "./extractMongoDbMetadataFromUserMessage"; import { Eval } from "braintrust"; import { Scorer } from "autoevals"; -import { MongoDbTag } from "../mongoDbMetadata"; +import { MongoDbTag } from "mongodb-rag-core"; import { OPENAI_PREPROCESSOR_CHAT_COMPLETION_DEPLOYMENT, openAiClient, diff --git a/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.ts b/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.ts index b3e5e087f..e569c469d 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/extractMongoDbMetadataFromUserMessage.ts @@ -8,7 +8,7 @@ import { OpenAI } from "mongodb-rag-core/openai"; import { mongoDbProductNames, mongoDbProgrammingLanguageIds, -} from "../mongoDbMetadata"; +} from "mongodb-rag-core"; export const ExtractMongoDbMetadataFunctionSchema = z.object({ programmingLanguage: z diff --git a/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.eval.ts b/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.eval.ts index 83a770ff4..dc345acf8 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.eval.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.eval.ts @@ -6,7 +6,7 @@ import { } from "./makeStepBackUserQuery"; import { Message, updateFrontMatter } from "mongodb-chatbot-server"; import { ObjectId } from "mongodb-rag-core/mongodb"; -import { MongoDbTag } from "../mongoDbMetadata"; +import { MongoDbTag } from "mongodb-rag-core"; import { OPENAI_PREPROCESSOR_CHAT_COMPLETION_DEPLOYMENT, OPENAI_API_KEY, diff --git a/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.ts b/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.ts index 4ea2da9c2..eb3ec846d 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/makeStepBackUserQuery.ts @@ -110,8 +110,9 @@ const fewShotExamples: OpenAI.ChatCompletionMessageParam[] = [ mongoDbProduct: "MongoDB University", }) ), - makeAssistantFunctionCallMessage(name,{ - transformedUserQuery: "What is the skill badge program on MongoDB University?", + makeAssistantFunctionCallMessage(name, { + transformedUserQuery: + "What is the skill badge program on MongoDB University?", } satisfies StepBackUserQueryMongoDbFunction), ]; diff --git a/packages/chatbot-server-mongodb-public/src/processors/retrieveRelevantContent.eval.ts b/packages/chatbot-server-mongodb-public/src/processors/retrieveRelevantContent.eval.ts index cc06adaa0..b739968f7 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/retrieveRelevantContent.eval.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/retrieveRelevantContent.eval.ts @@ -20,7 +20,7 @@ import { binaryNdcgAtK } from "../eval/scorers/binaryNdcgAtK"; import { f1AtK } from "../eval/scorers/f1AtK"; import { precisionAtK } from "../eval/scorers/precisionAtK"; import { recallAtK } from "../eval/scorers/recallAtK"; -import { MongoDbTag } from "../mongoDbMetadata"; +import { MongoDbTag } from "mongodb-rag-core"; import { extractMongoDbMetadataFromUserMessage, ExtractMongoDbMetadataFunction, diff --git a/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.eval.ts b/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.eval.ts index 2e807d331..6d427f081 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.eval.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.eval.ts @@ -5,7 +5,7 @@ import { } from "./userMessageMongoDbGuardrail"; import { Eval } from "braintrust"; import { Scorer, LLMClassifierFromTemplate } from "autoevals"; -import { MongoDbTag } from "../mongoDbMetadata"; +import { MongoDbTag } from "mongodb-rag-core"; import { JUDGE_LLM, OPENAI_PREPROCESSOR_CHAT_COMPLETION_DEPLOYMENT, diff --git a/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.ts b/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.ts index a35d14206..d31b25cb4 100644 --- a/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.ts +++ b/packages/chatbot-server-mongodb-public/src/processors/userMessageMongoDbGuardrail.ts @@ -147,9 +147,7 @@ const fewShotExamples: OpenAI.ChatCompletionMessageParam[] = [ rejectMessage: false, } satisfies UserMessageMongoDbGuardrailFunction), // Example 16 - makeUserMessage( - "What is a skill?" - ), + makeUserMessage("What is a skill?"), makeAssistantFunctionCallMessage(name, { reasoning: "This query is asking about MongoDB University's skills program, which allows users to earn a skill badge for taking a short course and completing an assessment. Therefore, it is relevant to MongoDB.", diff --git a/packages/chatbot-server-mongodb-public/src/verifiedAnswers.eval.ts b/packages/chatbot-server-mongodb-public/src/verifiedAnswers.eval.ts index 0095fe535..0f2608280 100644 --- a/packages/chatbot-server-mongodb-public/src/verifiedAnswers.eval.ts +++ b/packages/chatbot-server-mongodb-public/src/verifiedAnswers.eval.ts @@ -1,5 +1,5 @@ import { Eval, EvalCase, EvalScorer } from "braintrust"; -import { MongoDbTag } from "./mongoDbMetadata"; +import { MongoDbTag } from "mongodb-rag-core"; import { findVerifiedAnswer, verifiedAnswerConfig, diff --git a/packages/mongodb-rag-core/src/index.ts b/packages/mongodb-rag-core/src/index.ts index 594e32ba8..151251bde 100644 --- a/packages/mongodb-rag-core/src/index.ts +++ b/packages/mongodb-rag-core/src/index.ts @@ -25,3 +25,4 @@ export * from "./References"; export * from "./VectorStore"; export * from "./arrayFilters"; export * from "./assertEnvVars"; +export * from "./mongoDbMetadata"; diff --git a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/index.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/index.ts similarity index 100% rename from packages/chatbot-server-mongodb-public/src/mongoDbMetadata/index.ts rename to packages/mongodb-rag-core/src/mongoDbMetadata/index.ts diff --git a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/products.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/products.ts similarity index 100% rename from packages/chatbot-server-mongodb-public/src/mongoDbMetadata/products.ts rename to packages/mongodb-rag-core/src/mongoDbMetadata/products.ts diff --git a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/programmingLanguages.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/programmingLanguages.ts similarity index 100% rename from packages/chatbot-server-mongodb-public/src/mongoDbMetadata/programmingLanguages.ts rename to packages/mongodb-rag-core/src/mongoDbMetadata/programmingLanguages.ts diff --git a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts new file mode 100644 index 000000000..9e236c98b --- /dev/null +++ b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts @@ -0,0 +1,76 @@ +import { mongoDbProducts, mongodbDrivers } from "./products"; +import { mongoDbProgrammingLanguageIds } from "./programmingLanguages"; +import { mongoDbTopics } from "./topics"; + +// Helpers for constructing the `MongoDbTag` union type +const mongoDbProductIds = mongoDbProducts.map((product) => product.id); +const mongoDbDriverIds = mongodbDrivers.map((driver) => driver.id); +const mongoDbTopicIds = mongoDbTopics.map((topic) => topic.id); + +/** + All possible MongoDB tags. Useful for tagging evaluations. + */ + export type MongoDbTag = + | (typeof mongoDbProgrammingLanguageIds)[number] + | (typeof mongoDbProductIds)[number] + | (typeof mongoDbDriverIds)[number] + | (typeof mongoDbTopicIds)[number]; + +/** + All possible MongoDB tags as enum. + */ +export const mongoDbTags = { + // Add all programming language IDs + ...mongoDbProgrammingLanguageIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), + + // Add all product IDs + ...mongoDbProductIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), + + // Add all driver IDs + ...mongoDbDriverIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), + + // Add all topic IDs + ...mongoDbTopicIds.reduce((acc, id) => { + acc[id] = id; + return acc; + }, {} as Record), +} as const; + +/** + * Validates an array of tag names against the MongoDbTags enum. + * + * @param tagNames - An array of strings representing tag names to validate + * @param custom - A boolean flag indicating whether custom tags are allowed + * @throws {Error} When non-custom tags are used that don't exist in MongoDbTags enum + * + * @remarks + * If custom is false, all tags must exist in the MongoDbTags enum. + * If any invalid tags are found, throws an error with the list of invalid tags + * and the allowed tags from MongoDbTags enum. + */ +export const validateTags = (tagNames: string[], custom: boolean): void => { + if (!custom) { + // check if all tags are allowed using the enum MongoDbTags + const invalidTags = tagNames.filter((tag) => !(tag in mongoDbTags)); + if (invalidTags.length > 0) { + throw new Error( + `Invalid tags found: ${invalidTags.join( + ", " + )} \nUse the "addCustomTags" transformation instead or use allowed tags: \n - ${Object.keys( + mongoDbTags + ) + .sort() + .join("\n - ")}` + ); + } + } +} \ No newline at end of file diff --git a/packages/chatbot-server-mongodb-public/src/mongoDbMetadata/topics.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/topics.ts similarity index 100% rename from packages/chatbot-server-mongodb-public/src/mongoDbMetadata/topics.ts rename to packages/mongodb-rag-core/src/mongoDbMetadata/topics.ts From 9988271544a69c19d861cb18efef2dc95f44b918 Mon Sep 17 00:00:00 2001 From: Alla Yakubova Date: Mon, 7 Apr 2025 14:49:36 -0400 Subject: [PATCH 4/6] lint --- .../src/mongoDbMetadata/products.ts | 6 +++-- .../src/mongoDbMetadata/tags.ts | 24 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/mongodb-rag-core/src/mongoDbMetadata/products.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/products.ts index 9d39f85d5..e3422b304 100644 --- a/packages/mongodb-rag-core/src/mongoDbMetadata/products.ts +++ b/packages/mongodb-rag-core/src/mongoDbMetadata/products.ts @@ -311,12 +311,14 @@ export const mongoDbProducts = [ { id: "mongodb_university", name: "MongoDB University", - description: "Online platform that offers certifications, courses, labs, and skills badges", + description: + "Online platform that offers certifications, courses, labs, and skills badges", }, { id: "skills", name: "MongoDB University Skills", - description: "An educational program that allows users to earn a skill badge after taking a short course and completing an assessment", + description: + "An educational program that allows users to earn a skill badge after taking a short course and completing an assessment", }, ] as const satisfies MongoDbProduct[]; diff --git a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts index 9e236c98b..d7dc1541a 100644 --- a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts +++ b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts @@ -10,7 +10,7 @@ const mongoDbTopicIds = mongoDbTopics.map((topic) => topic.id); /** All possible MongoDB tags. Useful for tagging evaluations. */ - export type MongoDbTag = +export type MongoDbTag = | (typeof mongoDbProgrammingLanguageIds)[number] | (typeof mongoDbProductIds)[number] | (typeof mongoDbDriverIds)[number] @@ -46,16 +46,16 @@ export const mongoDbTags = { } as const; /** - * Validates an array of tag names against the MongoDbTags enum. - * - * @param tagNames - An array of strings representing tag names to validate - * @param custom - A boolean flag indicating whether custom tags are allowed - * @throws {Error} When non-custom tags are used that don't exist in MongoDbTags enum - * - * @remarks - * If custom is false, all tags must exist in the MongoDbTags enum. - * If any invalid tags are found, throws an error with the list of invalid tags - * and the allowed tags from MongoDbTags enum. + Validates an array of tag names against the MongoDbTags enum. + + @param tagNames - An array of strings representing tag names to validate + @param custom - A boolean flag indicating whether custom tags are allowed + @throws {Error} When non-custom tags are used that don't exist in MongoDbTags enum + + @remarks + If custom is false, all tags must exist in the MongoDbTags enum. + If any invalid tags are found, throws an error with the list of invalid tags + and the allowed tags from MongoDbTags enum. */ export const validateTags = (tagNames: string[], custom: boolean): void => { if (!custom) { @@ -73,4 +73,4 @@ export const validateTags = (tagNames: string[], custom: boolean): void => { ); } } -} \ No newline at end of file +}; From 9e7eb5332ebb771a607644f277e68e5f4a5e7320 Mon Sep 17 00:00:00 2001 From: Alla Yakubova Date: Tue, 22 Apr 2025 12:07:54 -0400 Subject: [PATCH 5/6] clarify mongoDbTags obj and comment --- .../src/mongoDbMetadata/tags.ts | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts index d7dc1541a..bcbd9b6af 100644 --- a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts +++ b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts @@ -17,33 +17,20 @@ export type MongoDbTag = | (typeof mongoDbTopicIds)[number]; /** - All possible MongoDB tags as enum. + All possible MongoDB tags as runtime object to validate tags. */ export const mongoDbTags = { - // Add all programming language IDs - ...mongoDbProgrammingLanguageIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), - - // Add all product IDs - ...mongoDbProductIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), - - // Add all driver IDs - ...mongoDbDriverIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), - - // Add all topic IDs - ...mongoDbTopicIds.reduce((acc, id) => { - acc[id] = id; - return acc; - }, {} as Record), + ...Object.fromEntries( + ([] as MongoDbTag[]).concat( + mongoDbProgrammingLanguageIds, + mongoDbProductIds, + mongoDbDriverIds, + mongoDbTopicIds + ).map(id => [id, id]) + ) } as const; +export type MongoDbTags = keyof typeof mongoDbTags; + /** Validates an array of tag names against the MongoDbTags enum. From ba97cfd46a524a617eed8ea7e8d7e59f58b220c9 Mon Sep 17 00:00:00 2001 From: Alla Yakubova Date: Tue, 22 Apr 2025 12:41:32 -0400 Subject: [PATCH 6/6] simplify tags check --- .../src/mongoDbMetadata/tags.ts | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts index bcbd9b6af..dc6d42460 100644 --- a/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts +++ b/packages/mongodb-rag-core/src/mongoDbMetadata/tags.ts @@ -16,21 +16,13 @@ export type MongoDbTag = | (typeof mongoDbDriverIds)[number] | (typeof mongoDbTopicIds)[number]; -/** - All possible MongoDB tags as runtime object to validate tags. - */ -export const mongoDbTags = { - ...Object.fromEntries( - ([] as MongoDbTag[]).concat( - mongoDbProgrammingLanguageIds, - mongoDbProductIds, - mongoDbDriverIds, - mongoDbTopicIds - ).map(id => [id, id]) - ) -} as const; -export type MongoDbTags = keyof typeof mongoDbTags; - +// Combine all tag arrays into a single array +const allTags = [ + ...mongoDbProgrammingLanguageIds, + ...mongoDbProductIds, + ...mongoDbDriverIds, + ...mongoDbTopicIds, +]; /** Validates an array of tag names against the MongoDbTags enum. @@ -46,15 +38,12 @@ export type MongoDbTags = keyof typeof mongoDbTags; */ export const validateTags = (tagNames: string[], custom: boolean): void => { if (!custom) { - // check if all tags are allowed using the enum MongoDbTags - const invalidTags = tagNames.filter((tag) => !(tag in mongoDbTags)); + const invalidTags = tagNames.filter((tag) => !allTags.includes(tag as MongoDbTag)); if (invalidTags.length > 0) { throw new Error( `Invalid tags found: ${invalidTags.join( ", " - )} \nUse the "addCustomTags" transformation instead or use allowed tags: \n - ${Object.keys( - mongoDbTags - ) + )} \nUse the "addCustomTags" transformation instead or use allowed tags: \n - ${allTags .sort() .join("\n - ")}` );