@mastra/rag 2.4.0-alpha.0 → 2.4.1-alpha.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
@@ -4531,8 +4531,8 @@ var TextTransformer = class {
4531
4531
  addStartIndex = false,
4532
4532
  stripWhitespace = true
4533
4533
  }) {
4534
- if (overlap > maxSize) {
4535
- throw new Error(`Got a larger chunk overlap (${overlap}) than chunk size (${maxSize}), should be smaller.`);
4534
+ if (overlap >= maxSize) {
4535
+ throw new Error(`Chunk overlap (${overlap}) must be smaller than chunk size (${maxSize}).`);
4536
4536
  }
4537
4537
  this.maxSize = maxSize;
4538
4538
  this.overlap = overlap;
@@ -4701,17 +4701,31 @@ var CharacterTransformer = class extends TextTransformer {
4701
4701
  }
4702
4702
  __splitChunk(text) {
4703
4703
  const chunks = [];
4704
- let currentPosition = 0;
4705
- while (currentPosition < text.length) {
4706
- let chunkEnd = currentPosition;
4707
- while (chunkEnd < text.length && this.lengthFunction(text.slice(currentPosition, chunkEnd + 1)) <= this.maxSize) {
4708
- chunkEnd++;
4709
- }
4710
- const currentChunk = text.slice(currentPosition, chunkEnd);
4711
- const chunkLength = this.lengthFunction(currentChunk);
4704
+ const codePointBoundaries = [0];
4705
+ for (const codePoint of text) {
4706
+ codePointBoundaries.push(codePointBoundaries[codePointBoundaries.length - 1] + codePoint.length);
4707
+ }
4708
+ const finalBoundaryIndex = codePointBoundaries.length - 1;
4709
+ let currentBoundaryIndex = 0;
4710
+ while (currentBoundaryIndex < finalBoundaryIndex) {
4711
+ let chunkEndBoundaryIndex = currentBoundaryIndex;
4712
+ while (chunkEndBoundaryIndex < finalBoundaryIndex && this.lengthFunction(
4713
+ text.slice(codePointBoundaries[currentBoundaryIndex], codePointBoundaries[chunkEndBoundaryIndex + 1])
4714
+ ) <= this.maxSize) {
4715
+ chunkEndBoundaryIndex++;
4716
+ }
4717
+ if (chunkEndBoundaryIndex === currentBoundaryIndex) {
4718
+ chunkEndBoundaryIndex++;
4719
+ }
4720
+ const chunkEnd = codePointBoundaries[chunkEndBoundaryIndex];
4721
+ const currentChunk = text.slice(codePointBoundaries[currentBoundaryIndex], chunkEnd);
4712
4722
  chunks.push(currentChunk);
4713
- if (chunkEnd >= text.length) break;
4714
- currentPosition += Math.max(1, chunkLength - this.overlap);
4723
+ if (chunkEndBoundaryIndex >= finalBoundaryIndex) break;
4724
+ let nextBoundaryIndex = chunkEndBoundaryIndex;
4725
+ while (this.overlap > 0 && nextBoundaryIndex > currentBoundaryIndex && this.lengthFunction(text.slice(codePointBoundaries[nextBoundaryIndex - 1], chunkEnd)) <= this.overlap) {
4726
+ nextBoundaryIndex--;
4727
+ }
4728
+ currentBoundaryIndex = Math.max(currentBoundaryIndex + 1, nextBoundaryIndex);
4715
4729
  }
4716
4730
  return chunks;
4717
4731
  }
@@ -6970,10 +6984,13 @@ var CohereRelevanceScorer = class {
6970
6984
  model;
6971
6985
  apiKey;
6972
6986
  constructor(model, apiKey) {
6973
- this.apiKey = apiKey;
6987
+ this.apiKey = apiKey ?? process.env.COHERE_API_KEY;
6974
6988
  this.model = model;
6975
6989
  }
6976
6990
  async getRelevanceScore(query, text) {
6991
+ if (!this.apiKey) {
6992
+ throw new Error("Cohere API key is required. Pass an apiKey or set COHERE_API_KEY.");
6993
+ }
6977
6994
  const response = await fetch(`https://api.cohere.com/v2/rerank`, {
6978
6995
  method: "POST",
6979
6996
  headers: {
@@ -6992,12 +7009,20 @@ var CohereRelevanceScorer = class {
6992
7009
  }
6993
7010
  const data = await response.json();
6994
7011
  const relevanceScore = data.results[0]?.relevance_score;
6995
- if (!relevanceScore) {
7012
+ if (typeof relevanceScore !== "number" || !Number.isFinite(relevanceScore)) {
6996
7013
  throw new Error("No relevance score found on Cohere response");
6997
7014
  }
6998
7015
  return relevanceScore;
6999
7016
  }
7000
7017
  };
7018
+ function parseRelevanceScore(responseText) {
7019
+ const trimmed = responseText.trim();
7020
+ const score = Number(trimmed);
7021
+ if (!trimmed || !Number.isFinite(score) || score < 0 || score > 1) {
7022
+ throw new Error(`Invalid relevance score returned by model: ${responseText}`);
7023
+ }
7024
+ return score;
7025
+ }
7001
7026
  var MastraAgentRelevanceScorer = class {
7002
7027
  agent;
7003
7028
  constructor(name14, model) {
@@ -7026,7 +7051,7 @@ Always return just the number, no explanation.`,
7026
7051
  } else {
7027
7052
  response = await this.agent.generateLegacy(prompt);
7028
7053
  }
7029
- return parseFloat(response.text);
7054
+ return parseRelevanceScore(response.text);
7030
7055
  }
7031
7056
  };
7032
7057
  var ZeroEntropyRelevanceScorer = class {
@@ -7098,35 +7123,41 @@ async function executeRerank({
7098
7123
  }
7099
7124
  const resultLength = results.length;
7100
7125
  const queryAnalysis = queryEmbedding ? analyzeQueryEmbedding(queryEmbedding) : null;
7101
- const scoredResults = await Promise.all(
7102
- results.map(async (result, index) => {
7103
- let semanticScore = 0;
7104
- if (result?.metadata?.text) {
7105
- semanticScore = await scorer.getRelevanceScore(query, result?.metadata?.text);
7106
- }
7107
- const vectorScore = result.score;
7108
- const positionScore = calculatePositionScore(index, resultLength);
7109
- let finalScore = weights.semantic * semanticScore + weights.vector * vectorScore + weights.position * positionScore;
7110
- if (queryAnalysis) {
7111
- finalScore = adjustScores(finalScore, queryAnalysis);
7112
- }
7113
- return {
7114
- result,
7115
- score: finalScore,
7116
- details: {
7117
- semantic: semanticScore,
7118
- vector: vectorScore,
7119
- position: positionScore,
7120
- ...queryAnalysis && {
7121
- queryAnalysis: {
7122
- magnitude: queryAnalysis.magnitude,
7123
- dominantFeatures: queryAnalysis.dominantFeatures
7126
+ let scoredResults;
7127
+ try {
7128
+ scoredResults = await Promise.all(
7129
+ results.map(async (result, index) => {
7130
+ let semanticScore = 0;
7131
+ if (result?.metadata?.text) {
7132
+ semanticScore = await scorer.getRelevanceScore(query, result?.metadata?.text);
7133
+ }
7134
+ const vectorScore = result.score;
7135
+ const positionScore = calculatePositionScore(index, resultLength);
7136
+ let finalScore = weights.semantic * semanticScore + weights.vector * vectorScore + weights.position * positionScore;
7137
+ if (queryAnalysis) {
7138
+ finalScore = adjustScores(finalScore, queryAnalysis);
7139
+ }
7140
+ return {
7141
+ result,
7142
+ score: finalScore,
7143
+ details: {
7144
+ semantic: semanticScore,
7145
+ vector: vectorScore,
7146
+ position: positionScore,
7147
+ ...queryAnalysis && {
7148
+ queryAnalysis: {
7149
+ magnitude: queryAnalysis.magnitude,
7150
+ dominantFeatures: queryAnalysis.dominantFeatures
7151
+ }
7124
7152
  }
7125
7153
  }
7126
- }
7127
- };
7128
- })
7129
- );
7154
+ };
7155
+ })
7156
+ );
7157
+ } catch (err) {
7158
+ rerankSpan?.error({ error: err, endSpan: true });
7159
+ throw err;
7160
+ }
7130
7161
  const final = scoredResults.sort((a, b) => b.score - a.score).slice(0, topK);
7131
7162
  rerankSpan?.end({ output: { returned: final.length } });
7132
7163
  return final;
@@ -7700,9 +7731,10 @@ function parseFilterValue(filter, logger) {
7700
7731
  if (!filter) {
7701
7732
  return {};
7702
7733
  }
7734
+ let parsedFilter = filter;
7703
7735
  if (typeof filter === "string") {
7704
7736
  try {
7705
- return JSON.parse(filter);
7737
+ parsedFilter = JSON.parse(filter);
7706
7738
  } catch (error) {
7707
7739
  if (logger) {
7708
7740
  logger.error("Invalid filter", { filter, error });
@@ -7710,15 +7742,14 @@ function parseFilterValue(filter, logger) {
7710
7742
  throw new Error(`Invalid filter format: ${error instanceof Error ? error.message : String(error)}`);
7711
7743
  }
7712
7744
  }
7713
- if (typeof filter !== "object" || filter === null || Array.isArray(filter)) {
7745
+ if (typeof parsedFilter !== "object" || parsedFilter === null || Array.isArray(parsedFilter)) {
7746
+ const receivedType = Array.isArray(parsedFilter) ? "array" : typeof parsedFilter;
7714
7747
  if (logger) {
7715
7748
  logger.error("Invalid filter", { filter, error: "Filter must be a plain object" });
7716
7749
  }
7717
- throw new Error(
7718
- `Invalid filter format: expected a plain object, got ${Array.isArray(filter) ? "array" : typeof filter}`
7719
- );
7750
+ throw new Error(`Invalid filter format: expected a plain object, got ${receivedType}`);
7720
7751
  }
7721
- return filter;
7752
+ return parsedFilter;
7722
7753
  }
7723
7754
 
7724
7755
  // src/utils/convert-sources.ts