@mastra/evals 0.14.3-alpha.0 → 1.0.0-beta.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.
Files changed (189) hide show
  1. package/CHANGELOG.md +36 -9
  2. package/README.md +19 -159
  3. package/dist/{chunk-KHEXN75Q.js → chunk-CCLM7KPF.js} +45 -21
  4. package/dist/chunk-CCLM7KPF.js.map +1 -0
  5. package/dist/{chunk-QKR2PMLZ.cjs → chunk-TPQLLHZW.cjs} +46 -21
  6. package/dist/chunk-TPQLLHZW.cjs.map +1 -0
  7. package/dist/scorers/code/completeness/index.d.ts +1 -1
  8. package/dist/scorers/code/completeness/index.d.ts.map +1 -1
  9. package/dist/scorers/code/content-similarity/index.d.ts +1 -1
  10. package/dist/scorers/code/content-similarity/index.d.ts.map +1 -1
  11. package/dist/scorers/code/keyword-coverage/index.d.ts +1 -1
  12. package/dist/scorers/code/keyword-coverage/index.d.ts.map +1 -1
  13. package/dist/scorers/code/textual-difference/index.d.ts +1 -1
  14. package/dist/scorers/code/textual-difference/index.d.ts.map +1 -1
  15. package/dist/scorers/code/tone/index.d.ts +1 -1
  16. package/dist/scorers/code/tone/index.d.ts.map +1 -1
  17. package/dist/scorers/code/tool-call-accuracy/index.d.ts +1 -1
  18. package/dist/scorers/code/tool-call-accuracy/index.d.ts.map +1 -1
  19. package/dist/scorers/llm/answer-relevancy/index.d.ts +1 -1
  20. package/dist/scorers/llm/answer-relevancy/index.d.ts.map +1 -1
  21. package/dist/scorers/llm/answer-similarity/index.d.ts +2 -2
  22. package/dist/scorers/llm/answer-similarity/index.d.ts.map +1 -1
  23. package/dist/scorers/llm/bias/index.d.ts +2 -2
  24. package/dist/scorers/llm/bias/index.d.ts.map +1 -1
  25. package/dist/scorers/llm/context-precision/index.d.ts +3 -3
  26. package/dist/scorers/llm/context-precision/index.d.ts.map +1 -1
  27. package/dist/scorers/llm/context-relevance/index.d.ts +3 -3
  28. package/dist/scorers/llm/context-relevance/index.d.ts.map +1 -1
  29. package/dist/scorers/llm/faithfulness/index.d.ts +2 -2
  30. package/dist/scorers/llm/faithfulness/index.d.ts.map +1 -1
  31. package/dist/scorers/llm/hallucination/index.d.ts +2 -2
  32. package/dist/scorers/llm/hallucination/index.d.ts.map +1 -1
  33. package/dist/scorers/llm/noise-sensitivity/index.d.ts +1 -1
  34. package/dist/scorers/llm/noise-sensitivity/index.d.ts.map +1 -1
  35. package/dist/scorers/llm/prompt-alignment/index.d.ts +2 -2
  36. package/dist/scorers/llm/prompt-alignment/index.d.ts.map +1 -1
  37. package/dist/scorers/llm/tool-call-accuracy/index.d.ts +2 -2
  38. package/dist/scorers/llm/tool-call-accuracy/index.d.ts.map +1 -1
  39. package/dist/scorers/llm/toxicity/index.d.ts +2 -2
  40. package/dist/scorers/llm/toxicity/index.d.ts.map +1 -1
  41. package/dist/scorers/{llm → prebuilt}/index.cjs +479 -62
  42. package/dist/scorers/prebuilt/index.cjs.map +1 -0
  43. package/dist/scorers/prebuilt/index.d.ts +3 -0
  44. package/dist/scorers/prebuilt/index.d.ts.map +1 -0
  45. package/dist/scorers/{llm → prebuilt}/index.js +419 -15
  46. package/dist/scorers/prebuilt/index.js.map +1 -0
  47. package/dist/scorers/utils.cjs +21 -17
  48. package/dist/scorers/utils.d.ts +21 -11
  49. package/dist/scorers/utils.d.ts.map +1 -1
  50. package/dist/scorers/utils.js +1 -1
  51. package/package.json +12 -58
  52. package/dist/attachListeners.d.ts +0 -4
  53. package/dist/attachListeners.d.ts.map +0 -1
  54. package/dist/chunk-7QAUEU4L.cjs +0 -10
  55. package/dist/chunk-7QAUEU4L.cjs.map +0 -1
  56. package/dist/chunk-EMMSS5I5.cjs +0 -37
  57. package/dist/chunk-EMMSS5I5.cjs.map +0 -1
  58. package/dist/chunk-G3PMV62Z.js +0 -33
  59. package/dist/chunk-G3PMV62Z.js.map +0 -1
  60. package/dist/chunk-IUSAD2BW.cjs +0 -19
  61. package/dist/chunk-IUSAD2BW.cjs.map +0 -1
  62. package/dist/chunk-KHEXN75Q.js.map +0 -1
  63. package/dist/chunk-QKR2PMLZ.cjs.map +0 -1
  64. package/dist/chunk-QTWX6TKR.js +0 -8
  65. package/dist/chunk-QTWX6TKR.js.map +0 -1
  66. package/dist/chunk-YGTIO3J5.js +0 -17
  67. package/dist/chunk-YGTIO3J5.js.map +0 -1
  68. package/dist/dist-LDTK3TIP.cjs +0 -16759
  69. package/dist/dist-LDTK3TIP.cjs.map +0 -1
  70. package/dist/dist-OWYZEOJK.js +0 -16737
  71. package/dist/dist-OWYZEOJK.js.map +0 -1
  72. package/dist/evaluation.d.ts +0 -8
  73. package/dist/evaluation.d.ts.map +0 -1
  74. package/dist/index.cjs +0 -93
  75. package/dist/index.cjs.map +0 -1
  76. package/dist/index.d.ts +0 -3
  77. package/dist/index.d.ts.map +0 -1
  78. package/dist/index.js +0 -89
  79. package/dist/index.js.map +0 -1
  80. package/dist/magic-string.es-7ORA5OGR.js +0 -1305
  81. package/dist/magic-string.es-7ORA5OGR.js.map +0 -1
  82. package/dist/magic-string.es-NZ2XWFKN.cjs +0 -1311
  83. package/dist/magic-string.es-NZ2XWFKN.cjs.map +0 -1
  84. package/dist/metrics/index.d.ts +0 -4
  85. package/dist/metrics/index.d.ts.map +0 -1
  86. package/dist/metrics/judge/index.cjs +0 -12
  87. package/dist/metrics/judge/index.cjs.map +0 -1
  88. package/dist/metrics/judge/index.d.ts +0 -7
  89. package/dist/metrics/judge/index.d.ts.map +0 -1
  90. package/dist/metrics/judge/index.js +0 -3
  91. package/dist/metrics/judge/index.js.map +0 -1
  92. package/dist/metrics/llm/answer-relevancy/index.d.ts +0 -16
  93. package/dist/metrics/llm/answer-relevancy/index.d.ts.map +0 -1
  94. package/dist/metrics/llm/answer-relevancy/metricJudge.d.ts +0 -20
  95. package/dist/metrics/llm/answer-relevancy/metricJudge.d.ts.map +0 -1
  96. package/dist/metrics/llm/answer-relevancy/prompts.d.ts +0 -19
  97. package/dist/metrics/llm/answer-relevancy/prompts.d.ts.map +0 -1
  98. package/dist/metrics/llm/bias/index.d.ts +0 -14
  99. package/dist/metrics/llm/bias/index.d.ts.map +0 -1
  100. package/dist/metrics/llm/bias/metricJudge.d.ts +0 -14
  101. package/dist/metrics/llm/bias/metricJudge.d.ts.map +0 -1
  102. package/dist/metrics/llm/bias/prompts.d.ts +0 -14
  103. package/dist/metrics/llm/bias/prompts.d.ts.map +0 -1
  104. package/dist/metrics/llm/context-position/index.d.ts +0 -16
  105. package/dist/metrics/llm/context-position/index.d.ts.map +0 -1
  106. package/dist/metrics/llm/context-position/metricJudge.d.ts +0 -20
  107. package/dist/metrics/llm/context-position/metricJudge.d.ts.map +0 -1
  108. package/dist/metrics/llm/context-position/prompts.d.ts +0 -17
  109. package/dist/metrics/llm/context-position/prompts.d.ts.map +0 -1
  110. package/dist/metrics/llm/context-precision/index.d.ts +0 -16
  111. package/dist/metrics/llm/context-precision/index.d.ts.map +0 -1
  112. package/dist/metrics/llm/context-precision/metricJudge.d.ts +0 -20
  113. package/dist/metrics/llm/context-precision/metricJudge.d.ts.map +0 -1
  114. package/dist/metrics/llm/context-precision/prompts.d.ts +0 -17
  115. package/dist/metrics/llm/context-precision/prompts.d.ts.map +0 -1
  116. package/dist/metrics/llm/context-relevancy/index.d.ts +0 -16
  117. package/dist/metrics/llm/context-relevancy/index.d.ts.map +0 -1
  118. package/dist/metrics/llm/context-relevancy/metricJudge.d.ts +0 -16
  119. package/dist/metrics/llm/context-relevancy/metricJudge.d.ts.map +0 -1
  120. package/dist/metrics/llm/context-relevancy/prompts.d.ts +0 -13
  121. package/dist/metrics/llm/context-relevancy/prompts.d.ts.map +0 -1
  122. package/dist/metrics/llm/contextual-recall/index.d.ts +0 -16
  123. package/dist/metrics/llm/contextual-recall/index.d.ts.map +0 -1
  124. package/dist/metrics/llm/contextual-recall/metricJudge.d.ts +0 -16
  125. package/dist/metrics/llm/contextual-recall/metricJudge.d.ts.map +0 -1
  126. package/dist/metrics/llm/contextual-recall/prompts.d.ts +0 -13
  127. package/dist/metrics/llm/contextual-recall/prompts.d.ts.map +0 -1
  128. package/dist/metrics/llm/faithfulness/index.d.ts +0 -16
  129. package/dist/metrics/llm/faithfulness/index.d.ts.map +0 -1
  130. package/dist/metrics/llm/faithfulness/metricJudge.d.ts +0 -22
  131. package/dist/metrics/llm/faithfulness/metricJudge.d.ts.map +0 -1
  132. package/dist/metrics/llm/faithfulness/prompts.d.ts +0 -20
  133. package/dist/metrics/llm/faithfulness/prompts.d.ts.map +0 -1
  134. package/dist/metrics/llm/hallucination/index.d.ts +0 -16
  135. package/dist/metrics/llm/hallucination/index.d.ts.map +0 -1
  136. package/dist/metrics/llm/hallucination/metricJudge.d.ts +0 -22
  137. package/dist/metrics/llm/hallucination/metricJudge.d.ts.map +0 -1
  138. package/dist/metrics/llm/hallucination/prompts.d.ts +0 -17
  139. package/dist/metrics/llm/hallucination/prompts.d.ts.map +0 -1
  140. package/dist/metrics/llm/index.cjs +0 -2481
  141. package/dist/metrics/llm/index.cjs.map +0 -1
  142. package/dist/metrics/llm/index.d.ts +0 -12
  143. package/dist/metrics/llm/index.d.ts.map +0 -1
  144. package/dist/metrics/llm/index.js +0 -2469
  145. package/dist/metrics/llm/index.js.map +0 -1
  146. package/dist/metrics/llm/prompt-alignment/index.d.ts +0 -33
  147. package/dist/metrics/llm/prompt-alignment/index.d.ts.map +0 -1
  148. package/dist/metrics/llm/prompt-alignment/metricJudge.d.ts +0 -20
  149. package/dist/metrics/llm/prompt-alignment/metricJudge.d.ts.map +0 -1
  150. package/dist/metrics/llm/prompt-alignment/prompts.d.ts +0 -17
  151. package/dist/metrics/llm/prompt-alignment/prompts.d.ts.map +0 -1
  152. package/dist/metrics/llm/summarization/index.d.ts +0 -19
  153. package/dist/metrics/llm/summarization/index.d.ts.map +0 -1
  154. package/dist/metrics/llm/summarization/metricJudge.d.ts +0 -34
  155. package/dist/metrics/llm/summarization/metricJudge.d.ts.map +0 -1
  156. package/dist/metrics/llm/summarization/prompts.d.ts +0 -30
  157. package/dist/metrics/llm/summarization/prompts.d.ts.map +0 -1
  158. package/dist/metrics/llm/toxicity/index.d.ts +0 -14
  159. package/dist/metrics/llm/toxicity/index.d.ts.map +0 -1
  160. package/dist/metrics/llm/toxicity/metricJudge.d.ts +0 -14
  161. package/dist/metrics/llm/toxicity/metricJudge.d.ts.map +0 -1
  162. package/dist/metrics/llm/toxicity/prompts.d.ts +0 -10
  163. package/dist/metrics/llm/toxicity/prompts.d.ts.map +0 -1
  164. package/dist/metrics/llm/types.d.ts +0 -7
  165. package/dist/metrics/llm/types.d.ts.map +0 -1
  166. package/dist/metrics/llm/utils.d.ts +0 -14
  167. package/dist/metrics/llm/utils.d.ts.map +0 -1
  168. package/dist/metrics/nlp/completeness/index.d.ts +0 -21
  169. package/dist/metrics/nlp/completeness/index.d.ts.map +0 -1
  170. package/dist/metrics/nlp/content-similarity/index.d.ts +0 -18
  171. package/dist/metrics/nlp/content-similarity/index.d.ts.map +0 -1
  172. package/dist/metrics/nlp/index.cjs +0 -203
  173. package/dist/metrics/nlp/index.cjs.map +0 -1
  174. package/dist/metrics/nlp/index.d.ts +0 -6
  175. package/dist/metrics/nlp/index.d.ts.map +0 -1
  176. package/dist/metrics/nlp/index.js +0 -190
  177. package/dist/metrics/nlp/index.js.map +0 -1
  178. package/dist/metrics/nlp/keyword-coverage/index.d.ts +0 -13
  179. package/dist/metrics/nlp/keyword-coverage/index.d.ts.map +0 -1
  180. package/dist/metrics/nlp/textual-difference/index.d.ts +0 -15
  181. package/dist/metrics/nlp/textual-difference/index.d.ts.map +0 -1
  182. package/dist/metrics/nlp/tone/index.d.ts +0 -18
  183. package/dist/metrics/nlp/tone/index.d.ts.map +0 -1
  184. package/dist/scorers/code/index.cjs +0 -329
  185. package/dist/scorers/code/index.cjs.map +0 -1
  186. package/dist/scorers/code/index.js +0 -315
  187. package/dist/scorers/code/index.js.map +0 -1
  188. package/dist/scorers/llm/index.cjs.map +0 -1
  189. package/dist/scorers/llm/index.js.map +0 -1
@@ -1,7 +0,0 @@
1
- import type { MetricResult } from '@mastra/core/eval';
2
- export interface MetricResultWithReason extends MetricResult {
3
- info: {
4
- reason: string;
5
- };
6
- }
7
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/metrics/llm/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH"}
@@ -1,14 +0,0 @@
1
- export declare const roundToTwoDecimals: (num: number) => number;
2
- export declare function isCloserTo(value: number, target1: number, target2: number): boolean;
3
- export type TestCase = {
4
- input: string;
5
- output: string;
6
- expectedResult: {
7
- score: number;
8
- reason?: string;
9
- };
10
- };
11
- export type TestCaseWithContext = TestCase & {
12
- context: string[];
13
- };
14
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/metrics/llm/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,WAE7C,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC"}
@@ -1,21 +0,0 @@
1
- import { Metric } from '@mastra/core/eval';
2
- import type { MetricResult } from '@mastra/core/eval';
3
- interface CompletenessMetricResult extends MetricResult {
4
- info: {
5
- inputElements: string[];
6
- outputElements: string[];
7
- missingElements: string[];
8
- elementCounts: {
9
- input: number;
10
- output: number;
11
- };
12
- };
13
- }
14
- export declare class CompletenessMetric extends Metric {
15
- measure(input: string, output: string): Promise<CompletenessMetricResult>;
16
- private extractElements;
17
- private normalizeString;
18
- private calculateCoverage;
19
- }
20
- export {};
21
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/metrics/nlp/completeness/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,UAAU,wBAAyB,SAAQ,YAAY;IACrD,IAAI,EAAE;QACJ,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,aAAa,EAAE;YACb,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH;AAED,qBAAa,kBAAmB,SAAQ,MAAM;IACtC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAiC/E,OAAO,CAAC,eAAe;IAiCvB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,iBAAiB;CA6B1B"}
@@ -1,18 +0,0 @@
1
- import { Metric } from '@mastra/core/eval';
2
- import type { MetricResult } from '@mastra/core/eval';
3
- interface ContentSimilarityResult extends MetricResult {
4
- info: {
5
- similarity: number;
6
- };
7
- }
8
- interface ContentSimilarityOptions {
9
- ignoreCase?: boolean;
10
- ignoreWhitespace?: boolean;
11
- }
12
- export declare class ContentSimilarityMetric extends Metric {
13
- private options;
14
- constructor(options?: ContentSimilarityOptions);
15
- measure(input: string, output: string): Promise<ContentSimilarityResult>;
16
- }
17
- export {};
18
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/metrics/nlp/content-similarity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,UAAU,uBAAwB,SAAQ,YAAY;IACpD,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,UAAU,wBAAwB;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,uBAAwB,SAAQ,MAAM;IACjD,OAAO,CAAC,OAAO,CAA2B;gBAE9B,OAAO,GAAE,wBAA6B;IAS5C,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAqB/E"}
@@ -1,203 +0,0 @@
1
- 'use strict';
2
-
3
- var _eval = require('@mastra/core/eval');
4
- var nlp = require('compromise');
5
- var stringSimilarity = require('string-similarity');
6
- var difflib = require('difflib');
7
- var keyword_extractor = require('keyword-extractor');
8
- var Sentiment = require('sentiment');
9
-
10
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
-
12
- var nlp__default = /*#__PURE__*/_interopDefault(nlp);
13
- var stringSimilarity__default = /*#__PURE__*/_interopDefault(stringSimilarity);
14
- var keyword_extractor__default = /*#__PURE__*/_interopDefault(keyword_extractor);
15
- var Sentiment__default = /*#__PURE__*/_interopDefault(Sentiment);
16
-
17
- var CompletenessMetric = class extends _eval.Metric {
18
- async measure(input, output) {
19
- if (input === null || input === void 0 || output === null || output === void 0) {
20
- throw new Error("Inputs cannot be null or undefined");
21
- }
22
- input = input.trim();
23
- output = output.trim();
24
- const inputDoc = nlp__default.default(input);
25
- const outputDoc = nlp__default.default(output);
26
- const inputElements = this.extractElements(inputDoc);
27
- const outputElements = this.extractElements(outputDoc);
28
- const coverage = this.calculateCoverage(inputElements, outputElements);
29
- return {
30
- score: coverage,
31
- info: {
32
- inputElements,
33
- outputElements,
34
- missingElements: inputElements.filter((e) => !outputElements.includes(e)),
35
- elementCounts: {
36
- input: inputElements.length,
37
- output: outputElements.length
38
- }
39
- }
40
- };
41
- }
42
- extractElements(doc) {
43
- const nouns = doc.nouns().out("array") || [];
44
- const verbs = doc.verbs().toInfinitive().out("array") || [];
45
- const topics = doc.topics().out("array") || [];
46
- const terms = doc.terms().out("array") || [];
47
- const cleanAndSplitTerm = (term) => {
48
- const normalized = this.normalizeString(term);
49
- return normalized.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[^a-z0-9]+/g, " ").trim().split(/\s+/).filter((word) => word.length > 0);
50
- };
51
- const processedTerms = [
52
- ...nouns.flatMap(cleanAndSplitTerm),
53
- ...verbs.flatMap(cleanAndSplitTerm),
54
- ...topics.flatMap(cleanAndSplitTerm),
55
- ...terms.flatMap(cleanAndSplitTerm)
56
- ];
57
- return [...new Set(processedTerms)];
58
- }
59
- normalizeString(str) {
60
- return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
61
- }
62
- calculateCoverage(original, simplified) {
63
- if (original.length === 0) {
64
- return simplified.length === 0 ? 1 : 0;
65
- }
66
- const covered = original.filter(
67
- (element) => simplified.some((s) => {
68
- const elem = this.normalizeString(element);
69
- const simp = this.normalizeString(s);
70
- if (elem.length <= 3) {
71
- return elem === simp;
72
- }
73
- const longer = elem.length > simp.length ? elem : simp;
74
- const shorter = elem.length > simp.length ? simp : elem;
75
- if (longer.includes(shorter)) {
76
- return shorter.length / longer.length > 0.6;
77
- }
78
- return false;
79
- })
80
- );
81
- return covered.length / original.length;
82
- }
83
- };
84
- var ContentSimilarityMetric = class extends _eval.Metric {
85
- options;
86
- constructor(options = {}) {
87
- super();
88
- this.options = {
89
- ignoreCase: true,
90
- ignoreWhitespace: true,
91
- ...options
92
- };
93
- }
94
- async measure(input, output) {
95
- let processedInput = input;
96
- let processedOutput = output;
97
- if (this.options.ignoreCase) {
98
- processedInput = processedInput.toLowerCase();
99
- processedOutput = processedOutput.toLowerCase();
100
- }
101
- if (this.options.ignoreWhitespace) {
102
- processedInput = processedInput.replace(/\s+/g, " ").trim();
103
- processedOutput = processedOutput.replace(/\s+/g, " ").trim();
104
- }
105
- const similarity = stringSimilarity__default.default.compareTwoStrings(processedInput, processedOutput);
106
- return {
107
- score: similarity,
108
- info: { similarity }
109
- };
110
- }
111
- };
112
- var TextualDifferenceMetric = class extends _eval.Metric {
113
- async measure(input, output) {
114
- const matcher = new difflib.SequenceMatcher(null, input, output);
115
- const ratio = matcher.ratio();
116
- const ops = matcher.getOpcodes();
117
- const changes = ops.filter(([op]) => op !== "equal").length;
118
- const maxLength = Math.max(input.length, output.length);
119
- const lengthDiff = maxLength > 0 ? Math.abs(input.length - output.length) / maxLength : 0;
120
- const confidence = 1 - lengthDiff;
121
- return {
122
- score: ratio,
123
- info: {
124
- confidence,
125
- ratio,
126
- changes,
127
- lengthDiff
128
- }
129
- };
130
- }
131
- };
132
- var KeywordCoverageMetric = class extends _eval.Metric {
133
- async measure(input, output) {
134
- if (!input && !output) {
135
- return {
136
- score: 1,
137
- info: {
138
- totalKeywords: 0,
139
- matchedKeywords: 0
140
- }
141
- };
142
- }
143
- const extractKeywords = (text) => {
144
- return keyword_extractor__default.default.extract(text, {
145
- language: "english",
146
- remove_digits: true,
147
- return_changed_case: true,
148
- remove_duplicates: true
149
- });
150
- };
151
- const referenceKeywords = new Set(extractKeywords(input));
152
- const responseKeywords = new Set(extractKeywords(output));
153
- const matchedKeywords = [...referenceKeywords].filter((k) => responseKeywords.has(k));
154
- const totalKeywords = referenceKeywords.size;
155
- const coverage = totalKeywords > 0 ? matchedKeywords.length / totalKeywords : 0;
156
- return {
157
- score: coverage,
158
- info: {
159
- totalKeywords: referenceKeywords.size,
160
- matchedKeywords: matchedKeywords.length
161
- }
162
- };
163
- }
164
- };
165
- var ToneConsistencyMetric = class extends _eval.Metric {
166
- sentiment = new Sentiment__default.default();
167
- async measure(input, output) {
168
- const responseSentiment = this.sentiment.analyze(input);
169
- if (output) {
170
- const referenceSentiment = this.sentiment.analyze(output);
171
- const sentimentDiff = Math.abs(responseSentiment.comparative - referenceSentiment.comparative);
172
- const normalizedScore = Math.max(0, 1 - sentimentDiff);
173
- return {
174
- score: normalizedScore,
175
- info: {
176
- responseSentiment: responseSentiment.comparative,
177
- referenceSentiment: referenceSentiment.comparative,
178
- difference: sentimentDiff
179
- }
180
- };
181
- }
182
- const sentences = input.match(/[^.!?]+[.!?]+/g) || [input];
183
- const sentiments = sentences.map((s) => this.sentiment.analyze(s).comparative);
184
- const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;
185
- const variance = sentiments.reduce((sum, s) => sum + Math.pow(s - avgSentiment, 2), 0) / sentiments.length;
186
- const stability = Math.max(0, 1 - variance);
187
- return {
188
- score: stability,
189
- info: {
190
- avgSentiment,
191
- sentimentVariance: variance
192
- }
193
- };
194
- }
195
- };
196
-
197
- exports.CompletenessMetric = CompletenessMetric;
198
- exports.ContentSimilarityMetric = ContentSimilarityMetric;
199
- exports.KeywordCoverageMetric = KeywordCoverageMetric;
200
- exports.TextualDifferenceMetric = TextualDifferenceMetric;
201
- exports.ToneConsistencyMetric = ToneConsistencyMetric;
202
- //# sourceMappingURL=index.cjs.map
203
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/metrics/nlp/completeness/index.ts","../../../src/metrics/nlp/content-similarity/index.ts","../../../src/metrics/nlp/textual-difference/index.ts","../../../src/metrics/nlp/keyword-coverage/index.ts","../../../src/metrics/nlp/tone/index.ts"],"names":["Metric","nlp","stringSimilarity","SequenceMatcher","keyword_extractor","Sentiment"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport nlp from 'compromise';\n\ninterface CompletenessMetricResult extends MetricResult {\n info: {\n inputElements: string[];\n outputElements: string[];\n missingElements: string[];\n elementCounts: {\n input: number;\n output: number;\n };\n };\n}\n\nexport class CompletenessMetric extends Metric {\n async measure(input: string, output: string): Promise<CompletenessMetricResult> {\n // Handle null/undefined inputs\n if (input === null || input === undefined || output === null || output === undefined) {\n throw new Error('Inputs cannot be null or undefined');\n }\n\n // Trim both inputs\n input = input.trim();\n output = output.trim();\n\n const inputDoc = nlp(input);\n const outputDoc = nlp(output);\n\n // Extract and log elements\n const inputElements = this.extractElements(inputDoc);\n const outputElements = this.extractElements(outputDoc);\n // Maybe we need a more sophisticated matching approach\n const coverage = this.calculateCoverage(inputElements, outputElements);\n\n return {\n score: coverage,\n info: {\n inputElements,\n outputElements,\n missingElements: inputElements.filter(e => !outputElements.includes(e)),\n elementCounts: {\n input: inputElements.length,\n output: outputElements.length,\n },\n },\n };\n }\n\n private extractElements(doc: any): string[] {\n // Get more specific elements and ensure they're arrays\n const nouns = doc.nouns().out('array') || [];\n const verbs = doc.verbs().toInfinitive().out('array') || [];\n const topics = doc.topics().out('array') || [];\n const terms = doc.terms().out('array') || [];\n\n // Helper function to clean and split terms\n const cleanAndSplitTerm = (term: string): string[] => {\n // First normalize the string\n const normalized = this.normalizeString(term);\n\n // Split on word boundaries and filter out empty strings\n return normalized\n .replace(/([a-z])([A-Z])/g, '$1 $2') // Split camelCase\n .replace(/[^a-z0-9]+/g, ' ') // Replace non-alphanumeric with spaces\n .trim()\n .split(/\\s+/)\n .filter(word => word.length > 0);\n };\n\n // Process all elements\n const processedTerms = [\n ...nouns.flatMap(cleanAndSplitTerm),\n ...verbs.flatMap(cleanAndSplitTerm),\n ...topics.flatMap(cleanAndSplitTerm),\n ...terms.flatMap(cleanAndSplitTerm),\n ];\n\n // Remove duplicates\n return [...new Set(processedTerms)];\n }\n\n private normalizeString(str: string): string {\n // Remove diacritics and convert to lowercase\n return str\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase();\n }\n\n private calculateCoverage(original: string[], simplified: string[]): number {\n if (original.length === 0) {\n return simplified.length === 0 ? 1 : 0;\n }\n\n // Exact matching for short words (3 chars or less), substring matching for longer words\n const covered = original.filter(element =>\n simplified.some(s => {\n const elem = this.normalizeString(element);\n const simp = this.normalizeString(s);\n\n // For short words (3 chars or less), require exact match\n if (elem.length <= 3) {\n return elem === simp;\n }\n\n // For longer words, require substantial overlap (more than 60% of the longer word)\n const longer = elem.length > simp.length ? elem : simp;\n const shorter = elem.length > simp.length ? simp : elem;\n\n if (longer.includes(shorter)) {\n return shorter.length / longer.length > 0.6;\n }\n\n return false;\n }),\n );\n return covered.length / original.length;\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport stringSimilarity from 'string-similarity';\n\ninterface ContentSimilarityResult extends MetricResult {\n info: {\n similarity: number;\n };\n}\n\ninterface ContentSimilarityOptions {\n ignoreCase?: boolean;\n ignoreWhitespace?: boolean;\n}\n\nexport class ContentSimilarityMetric extends Metric {\n private options: ContentSimilarityOptions;\n\n constructor(options: ContentSimilarityOptions = {}) {\n super();\n this.options = {\n ignoreCase: true,\n ignoreWhitespace: true,\n ...options,\n };\n }\n\n async measure(input: string, output: string): Promise<ContentSimilarityResult> {\n let processedInput = input;\n let processedOutput = output;\n\n if (this.options.ignoreCase) {\n processedInput = processedInput.toLowerCase();\n processedOutput = processedOutput.toLowerCase();\n }\n\n if (this.options.ignoreWhitespace) {\n processedInput = processedInput.replace(/\\s+/g, ' ').trim();\n processedOutput = processedOutput.replace(/\\s+/g, ' ').trim();\n }\n\n const similarity = stringSimilarity.compareTwoStrings(processedInput, processedOutput);\n\n return {\n score: similarity,\n info: { similarity },\n };\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport { SequenceMatcher } from 'difflib';\n\ninterface TextualDifferenceResult extends MetricResult {\n info: {\n ratio: number;\n changes: number;\n lengthDiff: number;\n confidence: number;\n };\n}\n\nexport class TextualDifferenceMetric extends Metric {\n async measure(input: string, output: string): Promise<TextualDifferenceResult> {\n const matcher = new SequenceMatcher(null, input, output);\n const ratio = matcher.ratio();\n\n // Get detailed operations\n const ops = matcher.getOpcodes();\n const changes = ops.filter(([op]) => op !== 'equal').length;\n\n // Calculate confidence based on text length difference\n const maxLength = Math.max(input.length, output.length);\n const lengthDiff = maxLength > 0 ? Math.abs(input.length - output.length) / maxLength : 0;\n const confidence = 1 - lengthDiff;\n\n return {\n score: ratio,\n info: {\n confidence,\n ratio,\n changes,\n lengthDiff,\n },\n };\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport keyword_extractor from 'keyword-extractor';\n\ninterface KeywordCoverageResult extends MetricResult {\n info: {\n totalKeywords: number;\n matchedKeywords: number;\n };\n}\n\nexport class KeywordCoverageMetric extends Metric {\n async measure(input: string, output: string): Promise<KeywordCoverageResult> {\n // Handle empty strings case\n if (!input && !output) {\n return {\n score: 1,\n info: {\n totalKeywords: 0,\n matchedKeywords: 0,\n },\n };\n }\n\n const extractKeywords = (text: string) => {\n return keyword_extractor.extract(text, {\n language: 'english',\n remove_digits: true,\n return_changed_case: true,\n remove_duplicates: true,\n });\n };\n\n const referenceKeywords = new Set(extractKeywords(input));\n const responseKeywords = new Set(extractKeywords(output));\n\n const matchedKeywords = [...referenceKeywords].filter(k => responseKeywords.has(k));\n const totalKeywords = referenceKeywords.size;\n const coverage = totalKeywords > 0 ? matchedKeywords.length / totalKeywords : 0;\n\n return {\n score: coverage,\n info: {\n totalKeywords: referenceKeywords.size,\n matchedKeywords: matchedKeywords.length,\n },\n };\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport Sentiment from 'sentiment';\n\ninterface ToneConsitencyResult extends MetricResult {\n info:\n | {\n responseSentiment: number;\n referenceSentiment: number;\n difference: number;\n }\n | {\n avgSentiment: number;\n sentimentVariance: number;\n };\n}\n\nexport class ToneConsistencyMetric extends Metric {\n private sentiment = new Sentiment();\n\n async measure(input: string, output: string): Promise<ToneConsitencyResult> {\n const responseSentiment = this.sentiment.analyze(input);\n\n if (output) {\n // Compare sentiment with reference\n const referenceSentiment = this.sentiment.analyze(output);\n const sentimentDiff = Math.abs(responseSentiment.comparative - referenceSentiment.comparative);\n const normalizedScore = Math.max(0, 1 - sentimentDiff);\n\n return {\n score: normalizedScore,\n info: {\n responseSentiment: responseSentiment.comparative,\n referenceSentiment: referenceSentiment.comparative,\n difference: sentimentDiff,\n },\n };\n }\n\n // Evaluate sentiment stability across response\n const sentences = input.match(/[^.!?]+[.!?]+/g) || [input];\n const sentiments = sentences.map(s => this.sentiment.analyze(s).comparative);\n const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;\n const variance = sentiments.reduce((sum, s) => sum + Math.pow(s - avgSentiment, 2), 0) / sentiments.length;\n const stability = Math.max(0, 1 - variance);\n\n return {\n score: stability,\n info: {\n avgSentiment,\n sentimentVariance: variance,\n },\n };\n }\n}\n"]}
@@ -1,6 +0,0 @@
1
- export { CompletenessMetric } from './completeness/index.js';
2
- export { ContentSimilarityMetric } from './content-similarity/index.js';
3
- export { TextualDifferenceMetric } from './textual-difference/index.js';
4
- export { KeywordCoverageMetric } from './keyword-coverage/index.js';
5
- export { ToneConsistencyMetric } from './tone/index.js';
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/metrics/nlp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC"}
@@ -1,190 +0,0 @@
1
- import { Metric } from '@mastra/core/eval';
2
- import nlp from 'compromise';
3
- import stringSimilarity from 'string-similarity';
4
- import { SequenceMatcher } from 'difflib';
5
- import keyword_extractor from 'keyword-extractor';
6
- import Sentiment from 'sentiment';
7
-
8
- var CompletenessMetric = class extends Metric {
9
- async measure(input, output) {
10
- if (input === null || input === void 0 || output === null || output === void 0) {
11
- throw new Error("Inputs cannot be null or undefined");
12
- }
13
- input = input.trim();
14
- output = output.trim();
15
- const inputDoc = nlp(input);
16
- const outputDoc = nlp(output);
17
- const inputElements = this.extractElements(inputDoc);
18
- const outputElements = this.extractElements(outputDoc);
19
- const coverage = this.calculateCoverage(inputElements, outputElements);
20
- return {
21
- score: coverage,
22
- info: {
23
- inputElements,
24
- outputElements,
25
- missingElements: inputElements.filter((e) => !outputElements.includes(e)),
26
- elementCounts: {
27
- input: inputElements.length,
28
- output: outputElements.length
29
- }
30
- }
31
- };
32
- }
33
- extractElements(doc) {
34
- const nouns = doc.nouns().out("array") || [];
35
- const verbs = doc.verbs().toInfinitive().out("array") || [];
36
- const topics = doc.topics().out("array") || [];
37
- const terms = doc.terms().out("array") || [];
38
- const cleanAndSplitTerm = (term) => {
39
- const normalized = this.normalizeString(term);
40
- return normalized.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[^a-z0-9]+/g, " ").trim().split(/\s+/).filter((word) => word.length > 0);
41
- };
42
- const processedTerms = [
43
- ...nouns.flatMap(cleanAndSplitTerm),
44
- ...verbs.flatMap(cleanAndSplitTerm),
45
- ...topics.flatMap(cleanAndSplitTerm),
46
- ...terms.flatMap(cleanAndSplitTerm)
47
- ];
48
- return [...new Set(processedTerms)];
49
- }
50
- normalizeString(str) {
51
- return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
52
- }
53
- calculateCoverage(original, simplified) {
54
- if (original.length === 0) {
55
- return simplified.length === 0 ? 1 : 0;
56
- }
57
- const covered = original.filter(
58
- (element) => simplified.some((s) => {
59
- const elem = this.normalizeString(element);
60
- const simp = this.normalizeString(s);
61
- if (elem.length <= 3) {
62
- return elem === simp;
63
- }
64
- const longer = elem.length > simp.length ? elem : simp;
65
- const shorter = elem.length > simp.length ? simp : elem;
66
- if (longer.includes(shorter)) {
67
- return shorter.length / longer.length > 0.6;
68
- }
69
- return false;
70
- })
71
- );
72
- return covered.length / original.length;
73
- }
74
- };
75
- var ContentSimilarityMetric = class extends Metric {
76
- options;
77
- constructor(options = {}) {
78
- super();
79
- this.options = {
80
- ignoreCase: true,
81
- ignoreWhitespace: true,
82
- ...options
83
- };
84
- }
85
- async measure(input, output) {
86
- let processedInput = input;
87
- let processedOutput = output;
88
- if (this.options.ignoreCase) {
89
- processedInput = processedInput.toLowerCase();
90
- processedOutput = processedOutput.toLowerCase();
91
- }
92
- if (this.options.ignoreWhitespace) {
93
- processedInput = processedInput.replace(/\s+/g, " ").trim();
94
- processedOutput = processedOutput.replace(/\s+/g, " ").trim();
95
- }
96
- const similarity = stringSimilarity.compareTwoStrings(processedInput, processedOutput);
97
- return {
98
- score: similarity,
99
- info: { similarity }
100
- };
101
- }
102
- };
103
- var TextualDifferenceMetric = class extends Metric {
104
- async measure(input, output) {
105
- const matcher = new SequenceMatcher(null, input, output);
106
- const ratio = matcher.ratio();
107
- const ops = matcher.getOpcodes();
108
- const changes = ops.filter(([op]) => op !== "equal").length;
109
- const maxLength = Math.max(input.length, output.length);
110
- const lengthDiff = maxLength > 0 ? Math.abs(input.length - output.length) / maxLength : 0;
111
- const confidence = 1 - lengthDiff;
112
- return {
113
- score: ratio,
114
- info: {
115
- confidence,
116
- ratio,
117
- changes,
118
- lengthDiff
119
- }
120
- };
121
- }
122
- };
123
- var KeywordCoverageMetric = class extends Metric {
124
- async measure(input, output) {
125
- if (!input && !output) {
126
- return {
127
- score: 1,
128
- info: {
129
- totalKeywords: 0,
130
- matchedKeywords: 0
131
- }
132
- };
133
- }
134
- const extractKeywords = (text) => {
135
- return keyword_extractor.extract(text, {
136
- language: "english",
137
- remove_digits: true,
138
- return_changed_case: true,
139
- remove_duplicates: true
140
- });
141
- };
142
- const referenceKeywords = new Set(extractKeywords(input));
143
- const responseKeywords = new Set(extractKeywords(output));
144
- const matchedKeywords = [...referenceKeywords].filter((k) => responseKeywords.has(k));
145
- const totalKeywords = referenceKeywords.size;
146
- const coverage = totalKeywords > 0 ? matchedKeywords.length / totalKeywords : 0;
147
- return {
148
- score: coverage,
149
- info: {
150
- totalKeywords: referenceKeywords.size,
151
- matchedKeywords: matchedKeywords.length
152
- }
153
- };
154
- }
155
- };
156
- var ToneConsistencyMetric = class extends Metric {
157
- sentiment = new Sentiment();
158
- async measure(input, output) {
159
- const responseSentiment = this.sentiment.analyze(input);
160
- if (output) {
161
- const referenceSentiment = this.sentiment.analyze(output);
162
- const sentimentDiff = Math.abs(responseSentiment.comparative - referenceSentiment.comparative);
163
- const normalizedScore = Math.max(0, 1 - sentimentDiff);
164
- return {
165
- score: normalizedScore,
166
- info: {
167
- responseSentiment: responseSentiment.comparative,
168
- referenceSentiment: referenceSentiment.comparative,
169
- difference: sentimentDiff
170
- }
171
- };
172
- }
173
- const sentences = input.match(/[^.!?]+[.!?]+/g) || [input];
174
- const sentiments = sentences.map((s) => this.sentiment.analyze(s).comparative);
175
- const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;
176
- const variance = sentiments.reduce((sum, s) => sum + Math.pow(s - avgSentiment, 2), 0) / sentiments.length;
177
- const stability = Math.max(0, 1 - variance);
178
- return {
179
- score: stability,
180
- info: {
181
- avgSentiment,
182
- sentimentVariance: variance
183
- }
184
- };
185
- }
186
- };
187
-
188
- export { CompletenessMetric, ContentSimilarityMetric, KeywordCoverageMetric, TextualDifferenceMetric, ToneConsistencyMetric };
189
- //# sourceMappingURL=index.js.map
190
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/metrics/nlp/completeness/index.ts","../../../src/metrics/nlp/content-similarity/index.ts","../../../src/metrics/nlp/textual-difference/index.ts","../../../src/metrics/nlp/keyword-coverage/index.ts","../../../src/metrics/nlp/tone/index.ts"],"names":["Metric"],"mappings":"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","file":"index.js","sourcesContent":["import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport nlp from 'compromise';\n\ninterface CompletenessMetricResult extends MetricResult {\n info: {\n inputElements: string[];\n outputElements: string[];\n missingElements: string[];\n elementCounts: {\n input: number;\n output: number;\n };\n };\n}\n\nexport class CompletenessMetric extends Metric {\n async measure(input: string, output: string): Promise<CompletenessMetricResult> {\n // Handle null/undefined inputs\n if (input === null || input === undefined || output === null || output === undefined) {\n throw new Error('Inputs cannot be null or undefined');\n }\n\n // Trim both inputs\n input = input.trim();\n output = output.trim();\n\n const inputDoc = nlp(input);\n const outputDoc = nlp(output);\n\n // Extract and log elements\n const inputElements = this.extractElements(inputDoc);\n const outputElements = this.extractElements(outputDoc);\n // Maybe we need a more sophisticated matching approach\n const coverage = this.calculateCoverage(inputElements, outputElements);\n\n return {\n score: coverage,\n info: {\n inputElements,\n outputElements,\n missingElements: inputElements.filter(e => !outputElements.includes(e)),\n elementCounts: {\n input: inputElements.length,\n output: outputElements.length,\n },\n },\n };\n }\n\n private extractElements(doc: any): string[] {\n // Get more specific elements and ensure they're arrays\n const nouns = doc.nouns().out('array') || [];\n const verbs = doc.verbs().toInfinitive().out('array') || [];\n const topics = doc.topics().out('array') || [];\n const terms = doc.terms().out('array') || [];\n\n // Helper function to clean and split terms\n const cleanAndSplitTerm = (term: string): string[] => {\n // First normalize the string\n const normalized = this.normalizeString(term);\n\n // Split on word boundaries and filter out empty strings\n return normalized\n .replace(/([a-z])([A-Z])/g, '$1 $2') // Split camelCase\n .replace(/[^a-z0-9]+/g, ' ') // Replace non-alphanumeric with spaces\n .trim()\n .split(/\\s+/)\n .filter(word => word.length > 0);\n };\n\n // Process all elements\n const processedTerms = [\n ...nouns.flatMap(cleanAndSplitTerm),\n ...verbs.flatMap(cleanAndSplitTerm),\n ...topics.flatMap(cleanAndSplitTerm),\n ...terms.flatMap(cleanAndSplitTerm),\n ];\n\n // Remove duplicates\n return [...new Set(processedTerms)];\n }\n\n private normalizeString(str: string): string {\n // Remove diacritics and convert to lowercase\n return str\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase();\n }\n\n private calculateCoverage(original: string[], simplified: string[]): number {\n if (original.length === 0) {\n return simplified.length === 0 ? 1 : 0;\n }\n\n // Exact matching for short words (3 chars or less), substring matching for longer words\n const covered = original.filter(element =>\n simplified.some(s => {\n const elem = this.normalizeString(element);\n const simp = this.normalizeString(s);\n\n // For short words (3 chars or less), require exact match\n if (elem.length <= 3) {\n return elem === simp;\n }\n\n // For longer words, require substantial overlap (more than 60% of the longer word)\n const longer = elem.length > simp.length ? elem : simp;\n const shorter = elem.length > simp.length ? simp : elem;\n\n if (longer.includes(shorter)) {\n return shorter.length / longer.length > 0.6;\n }\n\n return false;\n }),\n );\n return covered.length / original.length;\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport stringSimilarity from 'string-similarity';\n\ninterface ContentSimilarityResult extends MetricResult {\n info: {\n similarity: number;\n };\n}\n\ninterface ContentSimilarityOptions {\n ignoreCase?: boolean;\n ignoreWhitespace?: boolean;\n}\n\nexport class ContentSimilarityMetric extends Metric {\n private options: ContentSimilarityOptions;\n\n constructor(options: ContentSimilarityOptions = {}) {\n super();\n this.options = {\n ignoreCase: true,\n ignoreWhitespace: true,\n ...options,\n };\n }\n\n async measure(input: string, output: string): Promise<ContentSimilarityResult> {\n let processedInput = input;\n let processedOutput = output;\n\n if (this.options.ignoreCase) {\n processedInput = processedInput.toLowerCase();\n processedOutput = processedOutput.toLowerCase();\n }\n\n if (this.options.ignoreWhitespace) {\n processedInput = processedInput.replace(/\\s+/g, ' ').trim();\n processedOutput = processedOutput.replace(/\\s+/g, ' ').trim();\n }\n\n const similarity = stringSimilarity.compareTwoStrings(processedInput, processedOutput);\n\n return {\n score: similarity,\n info: { similarity },\n };\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport { SequenceMatcher } from 'difflib';\n\ninterface TextualDifferenceResult extends MetricResult {\n info: {\n ratio: number;\n changes: number;\n lengthDiff: number;\n confidence: number;\n };\n}\n\nexport class TextualDifferenceMetric extends Metric {\n async measure(input: string, output: string): Promise<TextualDifferenceResult> {\n const matcher = new SequenceMatcher(null, input, output);\n const ratio = matcher.ratio();\n\n // Get detailed operations\n const ops = matcher.getOpcodes();\n const changes = ops.filter(([op]) => op !== 'equal').length;\n\n // Calculate confidence based on text length difference\n const maxLength = Math.max(input.length, output.length);\n const lengthDiff = maxLength > 0 ? Math.abs(input.length - output.length) / maxLength : 0;\n const confidence = 1 - lengthDiff;\n\n return {\n score: ratio,\n info: {\n confidence,\n ratio,\n changes,\n lengthDiff,\n },\n };\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport keyword_extractor from 'keyword-extractor';\n\ninterface KeywordCoverageResult extends MetricResult {\n info: {\n totalKeywords: number;\n matchedKeywords: number;\n };\n}\n\nexport class KeywordCoverageMetric extends Metric {\n async measure(input: string, output: string): Promise<KeywordCoverageResult> {\n // Handle empty strings case\n if (!input && !output) {\n return {\n score: 1,\n info: {\n totalKeywords: 0,\n matchedKeywords: 0,\n },\n };\n }\n\n const extractKeywords = (text: string) => {\n return keyword_extractor.extract(text, {\n language: 'english',\n remove_digits: true,\n return_changed_case: true,\n remove_duplicates: true,\n });\n };\n\n const referenceKeywords = new Set(extractKeywords(input));\n const responseKeywords = new Set(extractKeywords(output));\n\n const matchedKeywords = [...referenceKeywords].filter(k => responseKeywords.has(k));\n const totalKeywords = referenceKeywords.size;\n const coverage = totalKeywords > 0 ? matchedKeywords.length / totalKeywords : 0;\n\n return {\n score: coverage,\n info: {\n totalKeywords: referenceKeywords.size,\n matchedKeywords: matchedKeywords.length,\n },\n };\n }\n}\n","import { Metric } from '@mastra/core/eval';\nimport type { MetricResult } from '@mastra/core/eval';\nimport Sentiment from 'sentiment';\n\ninterface ToneConsitencyResult extends MetricResult {\n info:\n | {\n responseSentiment: number;\n referenceSentiment: number;\n difference: number;\n }\n | {\n avgSentiment: number;\n sentimentVariance: number;\n };\n}\n\nexport class ToneConsistencyMetric extends Metric {\n private sentiment = new Sentiment();\n\n async measure(input: string, output: string): Promise<ToneConsitencyResult> {\n const responseSentiment = this.sentiment.analyze(input);\n\n if (output) {\n // Compare sentiment with reference\n const referenceSentiment = this.sentiment.analyze(output);\n const sentimentDiff = Math.abs(responseSentiment.comparative - referenceSentiment.comparative);\n const normalizedScore = Math.max(0, 1 - sentimentDiff);\n\n return {\n score: normalizedScore,\n info: {\n responseSentiment: responseSentiment.comparative,\n referenceSentiment: referenceSentiment.comparative,\n difference: sentimentDiff,\n },\n };\n }\n\n // Evaluate sentiment stability across response\n const sentences = input.match(/[^.!?]+[.!?]+/g) || [input];\n const sentiments = sentences.map(s => this.sentiment.analyze(s).comparative);\n const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;\n const variance = sentiments.reduce((sum, s) => sum + Math.pow(s - avgSentiment, 2), 0) / sentiments.length;\n const stability = Math.max(0, 1 - variance);\n\n return {\n score: stability,\n info: {\n avgSentiment,\n sentimentVariance: variance,\n },\n };\n }\n}\n"]}
@@ -1,13 +0,0 @@
1
- import { Metric } from '@mastra/core/eval';
2
- import type { MetricResult } from '@mastra/core/eval';
3
- interface KeywordCoverageResult extends MetricResult {
4
- info: {
5
- totalKeywords: number;
6
- matchedKeywords: number;
7
- };
8
- }
9
- export declare class KeywordCoverageMetric extends Metric {
10
- measure(input: string, output: string): Promise<KeywordCoverageResult>;
11
- }
12
- export {};
13
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/metrics/nlp/keyword-coverage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,UAAU,qBAAsB,SAAQ,YAAY;IAClD,IAAI,EAAE;QACJ,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAED,qBAAa,qBAAsB,SAAQ,MAAM;IACzC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAoC7E"}
@@ -1,15 +0,0 @@
1
- import { Metric } from '@mastra/core/eval';
2
- import type { MetricResult } from '@mastra/core/eval';
3
- interface TextualDifferenceResult extends MetricResult {
4
- info: {
5
- ratio: number;
6
- changes: number;
7
- lengthDiff: number;
8
- confidence: number;
9
- };
10
- }
11
- export declare class TextualDifferenceMetric extends Metric {
12
- measure(input: string, output: string): Promise<TextualDifferenceResult>;
13
- }
14
- export {};
15
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/metrics/nlp/textual-difference/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,UAAU,uBAAwB,SAAQ,YAAY;IACpD,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,qBAAa,uBAAwB,SAAQ,MAAM;IAC3C,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAuB/E"}
@@ -1,18 +0,0 @@
1
- import { Metric } from '@mastra/core/eval';
2
- import type { MetricResult } from '@mastra/core/eval';
3
- interface ToneConsitencyResult extends MetricResult {
4
- info: {
5
- responseSentiment: number;
6
- referenceSentiment: number;
7
- difference: number;
8
- } | {
9
- avgSentiment: number;
10
- sentimentVariance: number;
11
- };
12
- }
13
- export declare class ToneConsistencyMetric extends Metric {
14
- private sentiment;
15
- measure(input: string, output: string): Promise<ToneConsitencyResult>;
16
- }
17
- export {};
18
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/metrics/nlp/tone/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,UAAU,oBAAqB,SAAQ,YAAY;IACjD,IAAI,EACA;QACE,iBAAiB,EAAE,MAAM,CAAC;QAC1B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;KACpB,GACD;QACE,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;CACP;AAED,qBAAa,qBAAsB,SAAQ,MAAM;IAC/C,OAAO,CAAC,SAAS,CAAmB;IAE9B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAkC5E"}