@mastra/rag 2.7.3-alpha.1 → 2.8.0-alpha.3

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
@@ -9,6 +9,7 @@ import { createSimilarityPrompt } from "@mastra/core/relevance";
9
9
  import ZeroEntropy from "zeroentropy";
10
10
  import { createTool } from "@mastra/core/tools";
11
11
  import { embedV1, embedV2, embedV3, embedV4 } from "@mastra/core/vector";
12
+ import { getRequestUser } from "@mastra/core/utils";
12
13
  import { AgenticRetrieveStreamCommand, BedrockAgentRuntimeClient, RetrieveCommand } from "@aws-sdk/client-bedrock-agent-runtime";
13
14
  // \0rolldown/runtime.js
14
15
  var __create$1 = Object.create;
@@ -4847,6 +4848,7 @@ var RecursiveJsonTransformer = class RecursiveJsonTransformer {
4847
4848
  ensureAscii;
4848
4849
  convertLists;
4849
4850
  constructor({ maxSize = 2e3, ensureAscii = false, convertLists = true }) {
4851
+ if (!Number.isFinite(maxSize) || maxSize < 21) throw new RangeError("JSON maxSize must be at least 21");
4850
4852
  this.maxSize = maxSize;
4851
4853
  this.ensureAscii = ensureAscii;
4852
4854
  this.convertLists = convertLists;
@@ -5779,6 +5781,7 @@ const validationSchemas = {
5779
5781
  disallowedSpecial: setOrAllSchema
5780
5782
  }).strict(),
5781
5783
  json: baseChunkOptionsSchema.extend({
5784
+ maxSize: z.number().min(21).optional(),
5782
5785
  minSize: z.number().positive().optional(),
5783
5786
  ensureAscii: z.boolean().optional(),
5784
5787
  convertLists: z.boolean().optional()
@@ -6208,9 +6211,17 @@ async function executeRerank({ results, query, scorer, options }) {
6208
6211
  ...DEFAULT_WEIGHTS,
6209
6212
  ...options.weights
6210
6213
  };
6214
+ for (const [name, weight] of Object.entries(weights)) if (!Number.isFinite(weight) || weight < 0 || weight > 1) {
6215
+ const err = /* @__PURE__ */ new Error(`Weights must be finite numbers between 0 and 1. Got ${name}: ${weight}`);
6216
+ rerankSpan?.error({
6217
+ error: err,
6218
+ endSpan: true
6219
+ });
6220
+ throw err;
6221
+ }
6211
6222
  const sum = Object.values(weights).reduce((acc, w) => acc.plus(w.toString()), new Big(0));
6212
6223
  if (!sum.eq(1)) {
6213
- const err = /* @__PURE__ */ new Error(`Weights must add up to 1. Got ${sum} from ${weights}`);
6224
+ const err = /* @__PURE__ */ new Error(`Weights must add up to 1. Got ${sum} from ${JSON.stringify(weights)}`);
6214
6225
  rerankSpan?.error({
6215
6226
  error: err,
6216
6227
  endSpan: true
@@ -6296,12 +6307,17 @@ var GraphRAG = class GraphRAG {
6296
6307
  addNode(node) {
6297
6308
  if (!node.embedding) throw new Error("Node must have an embedding");
6298
6309
  if (node.embedding.length !== this.dimension) throw new Error(`Embedding dimension must be ${this.dimension}`);
6299
- this.nodes.set(node.id, node);
6310
+ for (const component of node.embedding) if (!Number.isFinite(component)) throw new Error("Embedding must contain only finite numbers");
6311
+ this.nodes.set(node.id, {
6312
+ ...node,
6313
+ embedding: [...node.embedding]
6314
+ });
6300
6315
  }
6301
6316
  addEdge(edge) {
6302
6317
  if (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) throw new Error("Both source and target nodes must exist");
6318
+ if (!Number.isFinite(edge.weight)) throw new Error("Edge weight must be a finite number");
6303
6319
  this.edges.push(edge);
6304
- this.edges.push({
6320
+ if (edge.source !== edge.target) this.edges.push({
6305
6321
  source: edge.target,
6306
6322
  target: edge.source,
6307
6323
  weight: edge.weight,
@@ -6309,7 +6325,10 @@ var GraphRAG = class GraphRAG {
6309
6325
  });
6310
6326
  }
6311
6327
  getNodes() {
6312
- return Array.from(this.nodes.values());
6328
+ return Array.from(this.nodes.values(), (node) => ({
6329
+ ...node,
6330
+ ...node.embedding ? { embedding: [...node.embedding] } : {}
6331
+ }));
6313
6332
  }
6314
6333
  getEdges() {
6315
6334
  return this.edges;
@@ -6342,20 +6361,25 @@ var GraphRAG = class GraphRAG {
6342
6361
  /**
6343
6362
  * Rebuild a GraphRAG instance from a snapshot produced by `serialize()`.
6344
6363
  *
6345
- * @throws if the snapshot version is unsupported, a node embedding does not
6346
- * match the snapshot dimension, or an edge references an unknown node.
6364
+ * @throws if the snapshot version is unsupported, a node ID is duplicated,
6365
+ * a node embedding does not match the snapshot dimension or contains nonfinite values,
6366
+ * or an edge references an unknown node.
6347
6367
  */
6348
6368
  static deserialize(snapshot) {
6349
6369
  if (snapshot?.version !== GRAPH_RAG_SNAPSHOT_VERSION) throw new Error(`Unsupported GraphRAG snapshot version: ${snapshot?.version}`);
6350
6370
  const graph = new GraphRAG(snapshot.dimension, snapshot.threshold);
6351
- for (const node of snapshot.nodes ?? []) graph.addNode({
6352
- ...node,
6353
- ...node.embedding ? { embedding: [...node.embedding] } : {},
6354
- ...node.metadata ? { metadata: structuredClone(node.metadata) } : {}
6355
- });
6371
+ for (const node of snapshot.nodes ?? []) {
6372
+ if (graph.nodes.has(node.id)) throw new Error(`Duplicate node id in snapshot: ${node.id}`);
6373
+ graph.addNode({
6374
+ ...node,
6375
+ ...node.embedding ? { embedding: [...node.embedding] } : {},
6376
+ ...node.metadata ? { metadata: structuredClone(node.metadata) } : {}
6377
+ });
6378
+ }
6356
6379
  for (const edge of snapshot.edges ?? []) {
6357
6380
  if (!graph.nodes.has(edge.source)) throw new Error(`Edge references unknown node: ${edge.source}`);
6358
6381
  if (!graph.nodes.has(edge.target)) throw new Error(`Edge references unknown node: ${edge.target}`);
6382
+ if (!Number.isFinite(edge.weight)) throw new Error("Edge weight must be a finite number");
6359
6383
  }
6360
6384
  graph.edges = (snapshot.edges ?? []).map((edge) => ({ ...edge }));
6361
6385
  return graph;
@@ -6397,22 +6421,21 @@ var GraphRAG = class GraphRAG {
6397
6421
  createGraph(chunks, embeddings) {
6398
6422
  if (!chunks?.length || !embeddings?.length) throw new Error("Chunks and embeddings arrays must not be empty");
6399
6423
  if (chunks.length !== embeddings.length) throw new Error("Chunks and embeddings must have the same length");
6424
+ const graph = new GraphRAG(this.dimension, this.threshold);
6400
6425
  chunks.forEach((chunk, index) => {
6401
- const node = {
6426
+ graph.addNode({
6402
6427
  id: index.toString(),
6403
6428
  content: chunk.text,
6404
6429
  embedding: embeddings[index]?.vector,
6405
6430
  metadata: { ...chunk.metadata }
6406
- };
6407
- this.addNode(node);
6408
- this.nodes.set(node.id, node);
6431
+ });
6409
6432
  });
6410
6433
  for (let i = 0; i < chunks.length; i++) {
6411
6434
  const firstEmbedding = embeddings[i]?.vector;
6412
6435
  for (let j = i + 1; j < chunks.length; j++) {
6413
6436
  const secondEmbedding = embeddings[j]?.vector;
6414
6437
  const similarity = this.cosineSimilarity(firstEmbedding, secondEmbedding);
6415
- if (similarity > this.threshold) this.addEdge({
6438
+ if (similarity > this.threshold) graph.addEdge({
6416
6439
  source: i.toString(),
6417
6440
  target: j.toString(),
6418
6441
  weight: similarity,
@@ -6420,6 +6443,8 @@ var GraphRAG = class GraphRAG {
6420
6443
  });
6421
6444
  }
6422
6445
  }
6446
+ this.nodes = graph.nodes;
6447
+ this.edges = graph.edges;
6423
6448
  }
6424
6449
  selectWeightedNeighbor(neighbors) {
6425
6450
  const totalWeight = neighbors.reduce((sum, n) => sum + n.weight, 0);
@@ -6463,9 +6488,10 @@ var GraphRAG = class GraphRAG {
6463
6488
  */
6464
6489
  query({ query, topK = 10, randomWalkSteps = 100, restartProb = .15, filter }) {
6465
6490
  if (!query || query.length !== this.dimension) throw new Error(`Query embedding must have dimension ${this.dimension}`);
6466
- if (topK < 1) throw new Error("TopK must be greater than 0");
6467
- if (randomWalkSteps < 1) throw new Error("Random walk steps must be greater than 0");
6468
- if (restartProb <= 0 || restartProb >= 1) throw new Error("Restart probability must be between 0 and 1");
6491
+ for (const component of query) if (!Number.isFinite(component)) throw new Error("Query embedding must contain only finite numbers");
6492
+ if (!Number.isInteger(topK) || topK < 1) throw new Error("TopK must be a positive integer");
6493
+ if (!Number.isInteger(randomWalkSteps) || randomWalkSteps < 1) throw new Error("Random walk steps must be a positive integer");
6494
+ if (!Number.isFinite(restartProb) || restartProb <= 0 || restartProb >= 1) throw new Error("Restart probability must be between 0 and 1");
6469
6495
  const filterEntries = Object.entries(filter ?? {});
6470
6496
  const matchesFilter = (node) => filterEntries.length === 0 ? true : filterEntries.every(([key, value]) => node.metadata?.[key] === value);
6471
6497
  const nodesToSearch = Array.from(this.nodes.values()).filter(matchesFilter);
@@ -6723,7 +6749,8 @@ async function resolveVectorStore(options, context, logger) {
6723
6749
  if (typeof vectorStoreOption === "function") {
6724
6750
  const resolved = await vectorStoreOption({
6725
6751
  requestContext,
6726
- mastra
6752
+ mastra,
6753
+ user: getRequestUser(requestContext)
6727
6754
  });
6728
6755
  if (!isValidMastraVector(resolved)) {
6729
6756
  const contextStr = buildContextString(context);
@@ -6827,8 +6854,6 @@ const createGraphRAGTool = (options) => {
6827
6854
  ...defaultGraphOptions,
6828
6855
  ...options.graphOptions || {}
6829
6856
  };
6830
- const graphRag = new GraphRAG(graphOptions.dimension, graphOptions.threshold);
6831
- let isInitialized = false;
6832
6857
  const inputSchema = options.enableFilter ? filterSchema : z.object(baseSchema).passthrough();
6833
6858
  return createTool({
6834
6859
  id: toolId,
@@ -6888,38 +6913,40 @@ const createGraphRAGTool = (options) => {
6888
6913
  observabilityContext
6889
6914
  });
6890
6915
  if (logger) logger.debug("vectorQuerySearch returned results", { count: results.length });
6891
- if (!isInitialized) {
6892
- const chunks = results.map((result) => ({
6893
- text: result?.metadata?.text,
6894
- metadata: result.metadata ?? {}
6895
- }));
6896
- const embeddings = results.map((result) => ({ vector: result.vector || [] }));
6897
- if (logger) logger.debug("Initializing graph", {
6898
- chunkCount: chunks.length,
6899
- embeddingCount: embeddings.length
6900
- });
6901
- const buildSpan = parentSpan?.createChildSpan({
6902
- type: SpanType.GRAPH_ACTION,
6903
- name: "graph build",
6904
- input: { nodeCount: chunks.length },
6905
- attributes: {
6906
- action: "build",
6907
- nodeCount: chunks.length,
6908
- threshold: graphOptions.threshold
6909
- }
6910
- });
6911
- try {
6912
- graphRag.createGraph(chunks, embeddings);
6913
- } catch (err) {
6914
- buildSpan?.error({
6915
- error: err,
6916
- endSpan: true
6917
- });
6918
- throw err;
6916
+ if (results.length === 0) return {
6917
+ relevantContext: [],
6918
+ sources: []
6919
+ };
6920
+ const graphRag = new GraphRAG(graphOptions.dimension, graphOptions.threshold);
6921
+ const chunks = results.map((result) => ({
6922
+ text: result?.metadata?.text,
6923
+ metadata: result.metadata ?? {}
6924
+ }));
6925
+ const embeddings = results.map((result) => ({ vector: result.vector || [] }));
6926
+ if (logger) logger.debug("Initializing graph", {
6927
+ chunkCount: chunks.length,
6928
+ embeddingCount: embeddings.length
6929
+ });
6930
+ const buildSpan = parentSpan?.createChildSpan({
6931
+ type: SpanType.GRAPH_ACTION,
6932
+ name: "graph build",
6933
+ input: { nodeCount: chunks.length },
6934
+ attributes: {
6935
+ action: "build",
6936
+ nodeCount: chunks.length,
6937
+ threshold: graphOptions.threshold
6919
6938
  }
6920
- buildSpan?.end();
6921
- isInitialized = true;
6922
- } else if (logger) logger.debug("Graph already initialized, skipping graph construction");
6939
+ });
6940
+ try {
6941
+ graphRag.createGraph(chunks, embeddings);
6942
+ } catch (err) {
6943
+ buildSpan?.error({
6944
+ error: err,
6945
+ endSpan: true
6946
+ });
6947
+ throw err;
6948
+ }
6949
+ buildSpan?.end();
6923
6950
  const traverseSpan = parentSpan?.createChildSpan({
6924
6951
  type: SpanType.GRAPH_ACTION,
6925
6952
  name: "graph traverse",