@mastra/rag 2.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { SpanType, createObservabilityContext } from '@mastra/core/observability';
1
2
  import { Agent, isSupportedLanguageModel } from '@mastra/core/agent';
2
3
  import { randomUUID, createHash } from 'crypto';
3
4
  import { z } from 'zod';
@@ -6911,15 +6912,47 @@ var MDocument = class _MDocument {
6911
6912
  const textSplit = rt.transformDocuments(this.chunks);
6912
6913
  this.chunks = textSplit;
6913
6914
  }
6914
- async chunk(params) {
6915
+ async chunk(params, options) {
6915
6916
  const { strategy: passedStrategy, extract, ...chunkOptions } = params || {};
6916
6917
  const strategy = passedStrategy || this.defaultStrategy();
6917
- validateChunkParams(strategy, chunkOptions);
6918
- await this.chunkBy(strategy, chunkOptions);
6919
- if (extract) {
6920
- await this.extractMetadata(extract);
6918
+ const parentSpan = options?.observabilityContext?.tracingContext?.currentSpan;
6919
+ const chunkSpan = parentSpan?.createChildSpan({
6920
+ type: SpanType.RAG_ACTION,
6921
+ name: `rag chunk: ${strategy}`,
6922
+ input: { strategy },
6923
+ attributes: {
6924
+ action: "chunk",
6925
+ strategy,
6926
+ chunkSize: chunkOptions?.size,
6927
+ chunkOverlap: chunkOptions?.overlap
6928
+ }
6929
+ });
6930
+ try {
6931
+ validateChunkParams(strategy, chunkOptions);
6932
+ await this.chunkBy(strategy, chunkOptions);
6933
+ if (extract) {
6934
+ const extractSpan = chunkSpan?.createChildSpan({
6935
+ type: SpanType.RAG_ACTION,
6936
+ name: "rag extract metadata",
6937
+ attributes: {
6938
+ action: "extract_metadata",
6939
+ extractor: Object.keys(extract).join(",")
6940
+ }
6941
+ });
6942
+ try {
6943
+ await this.extractMetadata(extract);
6944
+ } catch (err) {
6945
+ extractSpan?.error({ error: err, endSpan: true });
6946
+ throw err;
6947
+ }
6948
+ extractSpan?.end();
6949
+ }
6950
+ chunkSpan?.end({ output: { chunkCount: this.chunks.length } });
6951
+ return this.chunks;
6952
+ } catch (err) {
6953
+ chunkSpan?.error({ error: err, endSpan: true });
6954
+ throw err;
6921
6955
  }
6922
- return this.chunks;
6923
6956
  }
6924
6957
  getDocs() {
6925
6958
  return this.chunks;
@@ -7041,14 +7074,27 @@ async function executeRerank({
7041
7074
  scorer,
7042
7075
  options
7043
7076
  }) {
7044
- const { queryEmbedding, topK = 3 } = options;
7077
+ const { queryEmbedding, topK = 3, observabilityContext } = options;
7078
+ const rerankSpan = observabilityContext?.tracingContext?.currentSpan?.createChildSpan({
7079
+ type: SpanType.RAG_ACTION,
7080
+ name: `rag rerank`,
7081
+ input: { query, candidateCount: results.length },
7082
+ attributes: {
7083
+ action: "rerank",
7084
+ candidateCount: results.length,
7085
+ topN: topK,
7086
+ scorer: scorer?.constructor?.name
7087
+ }
7088
+ });
7045
7089
  const weights = {
7046
7090
  ...DEFAULT_WEIGHTS,
7047
7091
  ...options.weights
7048
7092
  };
7049
7093
  const sum = Object.values(weights).reduce((acc, w) => acc.plus(w.toString()), new Big(0));
7050
7094
  if (!sum.eq(1)) {
7051
- throw new Error(`Weights must add up to 1. Got ${sum} from ${weights}`);
7095
+ const err = new Error(`Weights must add up to 1. Got ${sum} from ${weights}`);
7096
+ rerankSpan?.error({ error: err, endSpan: true });
7097
+ throw err;
7052
7098
  }
7053
7099
  const resultLength = results.length;
7054
7100
  const queryAnalysis = queryEmbedding ? analyzeQueryEmbedding(queryEmbedding) : null;
@@ -7081,7 +7127,9 @@ async function executeRerank({
7081
7127
  };
7082
7128
  })
7083
7129
  );
7084
- return scoredResults.sort((a, b) => b.score - a.score).slice(0, topK);
7130
+ const final = scoredResults.sort((a, b) => b.score - a.score).slice(0, topK);
7131
+ rerankSpan?.end({ output: { returned: final.length } });
7132
+ return final;
7085
7133
  }
7086
7134
  async function rerankWithScorer({
7087
7135
  results,
@@ -7371,33 +7419,67 @@ var vectorQuerySearch = async ({
7371
7419
  includeVectors = false,
7372
7420
  maxRetries = 2,
7373
7421
  databaseConfig = {},
7374
- providerOptions
7422
+ providerOptions,
7423
+ observabilityContext
7375
7424
  }) => {
7425
+ const parentSpan = observabilityContext?.tracingContext?.currentSpan;
7426
+ const embedSpan = parentSpan?.createChildSpan({
7427
+ type: SpanType.RAG_EMBEDDING,
7428
+ name: `rag embed: query`,
7429
+ input: queryText,
7430
+ attributes: {
7431
+ mode: "query",
7432
+ model: model?.modelId,
7433
+ provider: model?.provider,
7434
+ inputCount: 1
7435
+ }
7436
+ });
7376
7437
  let embeddingResult;
7377
- if (model.specificationVersion === "v3") {
7378
- embeddingResult = await embedV3({
7379
- model,
7380
- value: queryText,
7381
- maxRetries,
7382
- // Type assertion needed: providerOptions type is a union, but embedV3 expects specific version
7383
- ...providerOptions && { providerOptions }
7384
- });
7385
- } else if (model.specificationVersion === "v2") {
7386
- embeddingResult = await embedV2({
7387
- model,
7388
- value: queryText,
7389
- maxRetries,
7390
- // Type assertion needed: providerOptions type is a union, but embedV2 expects specific version
7391
- ...providerOptions && { providerOptions }
7392
- });
7393
- } else {
7394
- embeddingResult = await embedV1({
7395
- value: queryText,
7396
- model,
7397
- maxRetries
7398
- });
7438
+ try {
7439
+ if (model.specificationVersion === "v3") {
7440
+ embeddingResult = await embedV3({
7441
+ model,
7442
+ value: queryText,
7443
+ maxRetries,
7444
+ // Type assertion needed: providerOptions type is a union, but embedV3 expects specific version
7445
+ ...providerOptions && {
7446
+ providerOptions
7447
+ }
7448
+ });
7449
+ } else if (model.specificationVersion === "v2") {
7450
+ embeddingResult = await embedV2({
7451
+ model,
7452
+ value: queryText,
7453
+ maxRetries,
7454
+ // Type assertion needed: providerOptions type is a union, but embedV2 expects specific version
7455
+ ...providerOptions && {
7456
+ providerOptions
7457
+ }
7458
+ });
7459
+ } else {
7460
+ embeddingResult = await embedV1({
7461
+ value: queryText,
7462
+ model,
7463
+ maxRetries
7464
+ });
7465
+ }
7466
+ } catch (err) {
7467
+ embedSpan?.error({ error: err, endSpan: true });
7468
+ throw err;
7399
7469
  }
7400
7470
  const embedding = embeddingResult.embedding;
7471
+ const embedUsage = embeddingResult?.usage;
7472
+ embedSpan?.end({
7473
+ attributes: {
7474
+ dimensions: embedding?.length,
7475
+ ...embedUsage && {
7476
+ usage: {
7477
+ inputTokens: embedUsage.tokens ?? embedUsage.promptTokens ?? embedUsage.inputTokens
7478
+ }
7479
+ }
7480
+ },
7481
+ output: { dimensions: embedding?.length }
7482
+ });
7401
7483
  const queryParams = {
7402
7484
  indexName,
7403
7485
  queryVector: embedding,
@@ -7405,7 +7487,29 @@ var vectorQuerySearch = async ({
7405
7487
  filter: queryFilter,
7406
7488
  includeVector: includeVectors
7407
7489
  };
7408
- const results = await vectorStore.query({ ...queryParams, ...databaseSpecificParams(databaseConfig) });
7490
+ const querySpan = parentSpan?.createChildSpan({
7491
+ type: SpanType.RAG_VECTOR_OPERATION,
7492
+ name: `rag vector: query`,
7493
+ // Pass filter as-is; the observability layer's deepClean handles
7494
+ // size limits and sanitization centrally.
7495
+ input: { topK, filter: queryFilter },
7496
+ attributes: {
7497
+ operation: "query",
7498
+ indexName,
7499
+ topK,
7500
+ dimensions: embedding?.length
7501
+ }
7502
+ });
7503
+ let results;
7504
+ try {
7505
+ results = await vectorStore.query({ ...queryParams, ...databaseSpecificParams(databaseConfig) });
7506
+ } catch (err) {
7507
+ querySpan?.error({ error: err, endSpan: true });
7508
+ throw err;
7509
+ }
7510
+ querySpan?.end({
7511
+ output: { returned: results?.length ?? 0 }
7512
+ });
7409
7513
  return { results, queryEmbedding: embedding };
7410
7514
  };
7411
7515
  var databaseSpecificParams = (databaseConfig) => {
@@ -7669,7 +7773,9 @@ var createGraphRAGTool = (options) => {
7669
7773
  outputSchema,
7670
7774
  description: toolDescription,
7671
7775
  execute: async (inputData, context) => {
7672
- const { requestContext, mastra } = context || {};
7776
+ const { requestContext, mastra, tracingContext } = context || {};
7777
+ const observabilityContext = createObservabilityContext(tracingContext);
7778
+ const parentSpan = observabilityContext.tracingContext?.currentSpan;
7673
7779
  const indexName = requestContext?.get("indexName") ?? options.indexName;
7674
7780
  const vectorStoreName = "vectorStore" in options ? storeName : requestContext?.get("vectorStoreName") ?? storeName;
7675
7781
  if (!indexName) throw new Error(`indexName is required, got: ${indexName}`);
@@ -7707,7 +7813,8 @@ var createGraphRAGTool = (options) => {
7707
7813
  queryFilter: Object.keys(queryFilter || {}).length > 0 ? queryFilter : void 0,
7708
7814
  topK: topKValue,
7709
7815
  includeVectors: true,
7710
- providerOptions
7816
+ providerOptions,
7817
+ observabilityContext
7711
7818
  });
7712
7819
  if (logger) {
7713
7820
  logger.debug("vectorQuerySearch returned results", { count: results.length });
@@ -7723,17 +7830,50 @@ var createGraphRAGTool = (options) => {
7723
7830
  if (logger) {
7724
7831
  logger.debug("Initializing graph", { chunkCount: chunks.length, embeddingCount: embeddings.length });
7725
7832
  }
7726
- graphRag.createGraph(chunks, embeddings);
7833
+ const buildSpan = parentSpan?.createChildSpan({
7834
+ type: SpanType.GRAPH_ACTION,
7835
+ name: "graph build",
7836
+ input: { nodeCount: chunks.length },
7837
+ attributes: {
7838
+ action: "build",
7839
+ nodeCount: chunks.length,
7840
+ threshold: graphOptions.threshold
7841
+ }
7842
+ });
7843
+ try {
7844
+ graphRag.createGraph(chunks, embeddings);
7845
+ } catch (err) {
7846
+ buildSpan?.error({ error: err, endSpan: true });
7847
+ throw err;
7848
+ }
7849
+ buildSpan?.end();
7727
7850
  isInitialized = true;
7728
7851
  } else if (logger) {
7729
7852
  logger.debug("Graph already initialized, skipping graph construction");
7730
7853
  }
7731
- const rerankedResults = graphRag.query({
7732
- query: queryEmbedding,
7733
- topK: topKValue,
7734
- randomWalkSteps,
7735
- restartProb
7854
+ const traverseSpan = parentSpan?.createChildSpan({
7855
+ type: SpanType.GRAPH_ACTION,
7856
+ name: "graph traverse",
7857
+ input: { topK: topKValue, randomWalkSteps, restartProb },
7858
+ attributes: {
7859
+ action: "traverse",
7860
+ startNodes: 1,
7861
+ maxDepth: randomWalkSteps
7862
+ }
7736
7863
  });
7864
+ let rerankedResults;
7865
+ try {
7866
+ rerankedResults = graphRag.query({
7867
+ query: queryEmbedding,
7868
+ topK: topKValue,
7869
+ randomWalkSteps,
7870
+ restartProb
7871
+ });
7872
+ } catch (err) {
7873
+ traverseSpan?.error({ error: err, endSpan: true });
7874
+ throw err;
7875
+ }
7876
+ traverseSpan?.end({ output: { returned: rerankedResults.length } });
7737
7877
  if (logger) {
7738
7878
  logger.debug("GraphRAG query returned results", { count: rerankedResults.length });
7739
7879
  }
@@ -7772,7 +7912,8 @@ var createVectorQueryTool = (options) => {
7772
7912
  inputSchema,
7773
7913
  outputSchema,
7774
7914
  execute: async (inputData, context) => {
7775
- const { requestContext, mastra } = context || {};
7915
+ const { requestContext, mastra, tracingContext } = context || {};
7916
+ const observabilityContext = createObservabilityContext(tracingContext);
7776
7917
  const indexName = requestContext?.get("indexName") ?? options.indexName;
7777
7918
  const vectorStoreName = "vectorStore" in options ? storeName : requestContext?.get("vectorStoreName") ?? storeName;
7778
7919
  const includeVectors = requestContext?.get("includeVectors") ?? options.includeVectors ?? false;
@@ -7813,7 +7954,8 @@ var createVectorQueryTool = (options) => {
7813
7954
  topK: topKValue,
7814
7955
  includeVectors,
7815
7956
  databaseConfig,
7816
- providerOptions
7957
+ providerOptions,
7958
+ observabilityContext
7817
7959
  });
7818
7960
  if (logger) {
7819
7961
  logger.debug("vectorQuerySearch returned results", { count: results.length });
@@ -7830,13 +7972,15 @@ var createVectorQueryTool = (options) => {
7830
7972
  scorer: reranker.model,
7831
7973
  options: {
7832
7974
  ...reranker.options,
7833
- topK: reranker.options?.topK || topKValue
7975
+ topK: reranker.options?.topK || topKValue,
7976
+ observabilityContext
7834
7977
  }
7835
7978
  });
7836
7979
  } else {
7837
7980
  rerankedResults = await rerank(results, queryText, reranker.model, {
7838
7981
  ...reranker.options,
7839
- topK: reranker.options?.topK || topKValue
7982
+ topK: reranker.options?.topK || topKValue,
7983
+ observabilityContext
7840
7984
  });
7841
7985
  }
7842
7986
  if (logger) {