@mastra/rag 2.7.3-alpha.0 → 2.7.3-alpha.2

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
@@ -6208,9 +6208,25 @@ async function executeRerank({ results, query, scorer, options }) {
6208
6208
  ...DEFAULT_WEIGHTS,
6209
6209
  ...options.weights
6210
6210
  };
6211
+ for (const [name, weight] of Object.entries(weights)) if (!Number.isFinite(weight) || weight < 0 || weight > 1) {
6212
+ const err = /* @__PURE__ */ new Error(`Weights must be finite numbers between 0 and 1. Got ${name}: ${weight}`);
6213
+ rerankSpan?.error({
6214
+ error: err,
6215
+ endSpan: true
6216
+ });
6217
+ throw err;
6218
+ }
6211
6219
  const sum = Object.values(weights).reduce((acc, w) => acc.plus(w.toString()), new Big(0));
6212
6220
  if (!sum.eq(1)) {
6213
- const err = /* @__PURE__ */ new Error(`Weights must add up to 1. Got ${sum} from ${weights}`);
6221
+ const err = /* @__PURE__ */ new Error(`Weights must add up to 1. Got ${sum} from ${JSON.stringify(weights)}`);
6222
+ rerankSpan?.error({
6223
+ error: err,
6224
+ endSpan: true
6225
+ });
6226
+ throw err;
6227
+ }
6228
+ if (!Number.isInteger(topK) || topK < 0) {
6229
+ const err = /* @__PURE__ */ new Error(`topK must be a nonnegative integer. Got ${topK}`);
6214
6230
  rerankSpan?.error({
6215
6231
  error: err,
6216
6232
  endSpan: true
@@ -6288,12 +6304,17 @@ var GraphRAG = class GraphRAG {
6288
6304
  addNode(node) {
6289
6305
  if (!node.embedding) throw new Error("Node must have an embedding");
6290
6306
  if (node.embedding.length !== this.dimension) throw new Error(`Embedding dimension must be ${this.dimension}`);
6291
- this.nodes.set(node.id, node);
6307
+ for (const component of node.embedding) if (!Number.isFinite(component)) throw new Error("Embedding must contain only finite numbers");
6308
+ this.nodes.set(node.id, {
6309
+ ...node,
6310
+ embedding: [...node.embedding]
6311
+ });
6292
6312
  }
6293
6313
  addEdge(edge) {
6294
6314
  if (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) throw new Error("Both source and target nodes must exist");
6315
+ if (!Number.isFinite(edge.weight)) throw new Error("Edge weight must be a finite number");
6295
6316
  this.edges.push(edge);
6296
- this.edges.push({
6317
+ if (edge.source !== edge.target) this.edges.push({
6297
6318
  source: edge.target,
6298
6319
  target: edge.source,
6299
6320
  weight: edge.weight,
@@ -6301,7 +6322,10 @@ var GraphRAG = class GraphRAG {
6301
6322
  });
6302
6323
  }
6303
6324
  getNodes() {
6304
- return Array.from(this.nodes.values());
6325
+ return Array.from(this.nodes.values(), (node) => ({
6326
+ ...node,
6327
+ ...node.embedding ? { embedding: [...node.embedding] } : {}
6328
+ }));
6305
6329
  }
6306
6330
  getEdges() {
6307
6331
  return this.edges;
@@ -6334,20 +6358,25 @@ var GraphRAG = class GraphRAG {
6334
6358
  /**
6335
6359
  * Rebuild a GraphRAG instance from a snapshot produced by `serialize()`.
6336
6360
  *
6337
- * @throws if the snapshot version is unsupported, a node embedding does not
6338
- * match the snapshot dimension, or an edge references an unknown node.
6361
+ * @throws if the snapshot version is unsupported, a node ID is duplicated,
6362
+ * a node embedding does not match the snapshot dimension or contains nonfinite values,
6363
+ * or an edge references an unknown node.
6339
6364
  */
6340
6365
  static deserialize(snapshot) {
6341
6366
  if (snapshot?.version !== GRAPH_RAG_SNAPSHOT_VERSION) throw new Error(`Unsupported GraphRAG snapshot version: ${snapshot?.version}`);
6342
6367
  const graph = new GraphRAG(snapshot.dimension, snapshot.threshold);
6343
- for (const node of snapshot.nodes ?? []) graph.addNode({
6344
- ...node,
6345
- ...node.embedding ? { embedding: [...node.embedding] } : {},
6346
- ...node.metadata ? { metadata: structuredClone(node.metadata) } : {}
6347
- });
6368
+ for (const node of snapshot.nodes ?? []) {
6369
+ if (graph.nodes.has(node.id)) throw new Error(`Duplicate node id in snapshot: ${node.id}`);
6370
+ graph.addNode({
6371
+ ...node,
6372
+ ...node.embedding ? { embedding: [...node.embedding] } : {},
6373
+ ...node.metadata ? { metadata: structuredClone(node.metadata) } : {}
6374
+ });
6375
+ }
6348
6376
  for (const edge of snapshot.edges ?? []) {
6349
6377
  if (!graph.nodes.has(edge.source)) throw new Error(`Edge references unknown node: ${edge.source}`);
6350
6378
  if (!graph.nodes.has(edge.target)) throw new Error(`Edge references unknown node: ${edge.target}`);
6379
+ if (!Number.isFinite(edge.weight)) throw new Error("Edge weight must be a finite number");
6351
6380
  }
6352
6381
  graph.edges = (snapshot.edges ?? []).map((edge) => ({ ...edge }));
6353
6382
  return graph;
@@ -6389,22 +6418,21 @@ var GraphRAG = class GraphRAG {
6389
6418
  createGraph(chunks, embeddings) {
6390
6419
  if (!chunks?.length || !embeddings?.length) throw new Error("Chunks and embeddings arrays must not be empty");
6391
6420
  if (chunks.length !== embeddings.length) throw new Error("Chunks and embeddings must have the same length");
6421
+ const graph = new GraphRAG(this.dimension, this.threshold);
6392
6422
  chunks.forEach((chunk, index) => {
6393
- const node = {
6423
+ graph.addNode({
6394
6424
  id: index.toString(),
6395
6425
  content: chunk.text,
6396
6426
  embedding: embeddings[index]?.vector,
6397
6427
  metadata: { ...chunk.metadata }
6398
- };
6399
- this.addNode(node);
6400
- this.nodes.set(node.id, node);
6428
+ });
6401
6429
  });
6402
6430
  for (let i = 0; i < chunks.length; i++) {
6403
6431
  const firstEmbedding = embeddings[i]?.vector;
6404
6432
  for (let j = i + 1; j < chunks.length; j++) {
6405
6433
  const secondEmbedding = embeddings[j]?.vector;
6406
6434
  const similarity = this.cosineSimilarity(firstEmbedding, secondEmbedding);
6407
- if (similarity > this.threshold) this.addEdge({
6435
+ if (similarity > this.threshold) graph.addEdge({
6408
6436
  source: i.toString(),
6409
6437
  target: j.toString(),
6410
6438
  weight: similarity,
@@ -6412,6 +6440,8 @@ var GraphRAG = class GraphRAG {
6412
6440
  });
6413
6441
  }
6414
6442
  }
6443
+ this.nodes = graph.nodes;
6444
+ this.edges = graph.edges;
6415
6445
  }
6416
6446
  selectWeightedNeighbor(neighbors) {
6417
6447
  const totalWeight = neighbors.reduce((sum, n) => sum + n.weight, 0);
@@ -6455,9 +6485,10 @@ var GraphRAG = class GraphRAG {
6455
6485
  */
6456
6486
  query({ query, topK = 10, randomWalkSteps = 100, restartProb = .15, filter }) {
6457
6487
  if (!query || query.length !== this.dimension) throw new Error(`Query embedding must have dimension ${this.dimension}`);
6458
- if (topK < 1) throw new Error("TopK must be greater than 0");
6459
- if (randomWalkSteps < 1) throw new Error("Random walk steps must be greater than 0");
6460
- if (restartProb <= 0 || restartProb >= 1) throw new Error("Restart probability must be between 0 and 1");
6488
+ for (const component of query) if (!Number.isFinite(component)) throw new Error("Query embedding must contain only finite numbers");
6489
+ if (!Number.isInteger(topK) || topK < 1) throw new Error("TopK must be a positive integer");
6490
+ if (!Number.isInteger(randomWalkSteps) || randomWalkSteps < 1) throw new Error("Random walk steps must be a positive integer");
6491
+ if (!Number.isFinite(restartProb) || restartProb <= 0 || restartProb >= 1) throw new Error("Restart probability must be between 0 and 1");
6461
6492
  const filterEntries = Object.entries(filter ?? {});
6462
6493
  const matchesFilter = (node) => filterEntries.length === 0 ? true : filterEntries.every(([key, value]) => node.metadata?.[key] === value);
6463
6494
  const nodesToSearch = Array.from(this.nodes.values()).filter(matchesFilter);
@@ -6750,15 +6781,8 @@ async function resolveVectorStore(options, context, logger) {
6750
6781
  if (mastra) return mastra.getVector(vectorStoreName);
6751
6782
  }
6752
6783
  function coerceTopK(topK, defaultValue = 10) {
6753
- if (typeof topK === "number") {
6754
- if (Number.isFinite(topK) && topK > 0) return topK;
6755
- return defaultValue;
6756
- }
6757
- if (typeof topK === "string") {
6758
- const parsed = Number(topK);
6759
- if (Number.isFinite(parsed) && parsed > 0) return parsed;
6760
- return defaultValue;
6761
- }
6784
+ const parsed = typeof topK === "string" ? Number(topK) : topK;
6785
+ if (typeof parsed === "number" && Number.isFinite(parsed) && Math.floor(parsed) >= 1) return Math.floor(parsed);
6762
6786
  return defaultValue;
6763
6787
  }
6764
6788
  function parseFilterValue(filter, logger) {