@mastra/evals 0.14.4 → 1.0.0-beta.1

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 (195) hide show
  1. package/CHANGELOG.md +34 -25
  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 +15 -59
  52. package/dist/attachListeners.d.ts +0 -4
  53. package/dist/attachListeners.d.ts.map +0 -1
  54. package/dist/chunk-44PMY5ES.js +0 -78
  55. package/dist/chunk-44PMY5ES.js.map +0 -1
  56. package/dist/chunk-7QAUEU4L.cjs +0 -10
  57. package/dist/chunk-7QAUEU4L.cjs.map +0 -1
  58. package/dist/chunk-EMMSS5I5.cjs +0 -37
  59. package/dist/chunk-EMMSS5I5.cjs.map +0 -1
  60. package/dist/chunk-G3PMV62Z.js +0 -33
  61. package/dist/chunk-G3PMV62Z.js.map +0 -1
  62. package/dist/chunk-IUSAD2BW.cjs +0 -19
  63. package/dist/chunk-IUSAD2BW.cjs.map +0 -1
  64. package/dist/chunk-KHEXN75Q.js.map +0 -1
  65. package/dist/chunk-PWGOG6ML.cjs +0 -81
  66. package/dist/chunk-PWGOG6ML.cjs.map +0 -1
  67. package/dist/chunk-QKR2PMLZ.cjs.map +0 -1
  68. package/dist/chunk-QTWX6TKR.js +0 -8
  69. package/dist/chunk-QTWX6TKR.js.map +0 -1
  70. package/dist/chunk-YGTIO3J5.js +0 -17
  71. package/dist/chunk-YGTIO3J5.js.map +0 -1
  72. package/dist/dist-LDTK3TIP.cjs +0 -16759
  73. package/dist/dist-LDTK3TIP.cjs.map +0 -1
  74. package/dist/dist-OWYZEOJK.js +0 -16737
  75. package/dist/dist-OWYZEOJK.js.map +0 -1
  76. package/dist/evaluation.d.ts +0 -8
  77. package/dist/evaluation.d.ts.map +0 -1
  78. package/dist/index.cjs +0 -93
  79. package/dist/index.cjs.map +0 -1
  80. package/dist/index.d.ts +0 -3
  81. package/dist/index.d.ts.map +0 -1
  82. package/dist/index.js +0 -89
  83. package/dist/index.js.map +0 -1
  84. package/dist/magic-string.es-7ORA5OGR.js +0 -1305
  85. package/dist/magic-string.es-7ORA5OGR.js.map +0 -1
  86. package/dist/magic-string.es-NZ2XWFKN.cjs +0 -1311
  87. package/dist/magic-string.es-NZ2XWFKN.cjs.map +0 -1
  88. package/dist/metrics/index.d.ts +0 -4
  89. package/dist/metrics/index.d.ts.map +0 -1
  90. package/dist/metrics/judge/index.cjs +0 -12
  91. package/dist/metrics/judge/index.cjs.map +0 -1
  92. package/dist/metrics/judge/index.d.ts +0 -7
  93. package/dist/metrics/judge/index.d.ts.map +0 -1
  94. package/dist/metrics/judge/index.js +0 -3
  95. package/dist/metrics/judge/index.js.map +0 -1
  96. package/dist/metrics/llm/answer-relevancy/index.d.ts +0 -16
  97. package/dist/metrics/llm/answer-relevancy/index.d.ts.map +0 -1
  98. package/dist/metrics/llm/answer-relevancy/metricJudge.d.ts +0 -20
  99. package/dist/metrics/llm/answer-relevancy/metricJudge.d.ts.map +0 -1
  100. package/dist/metrics/llm/answer-relevancy/prompts.d.ts +0 -19
  101. package/dist/metrics/llm/answer-relevancy/prompts.d.ts.map +0 -1
  102. package/dist/metrics/llm/bias/index.d.ts +0 -14
  103. package/dist/metrics/llm/bias/index.d.ts.map +0 -1
  104. package/dist/metrics/llm/bias/metricJudge.d.ts +0 -14
  105. package/dist/metrics/llm/bias/metricJudge.d.ts.map +0 -1
  106. package/dist/metrics/llm/bias/prompts.d.ts +0 -14
  107. package/dist/metrics/llm/bias/prompts.d.ts.map +0 -1
  108. package/dist/metrics/llm/context-position/index.d.ts +0 -16
  109. package/dist/metrics/llm/context-position/index.d.ts.map +0 -1
  110. package/dist/metrics/llm/context-position/metricJudge.d.ts +0 -20
  111. package/dist/metrics/llm/context-position/metricJudge.d.ts.map +0 -1
  112. package/dist/metrics/llm/context-position/prompts.d.ts +0 -17
  113. package/dist/metrics/llm/context-position/prompts.d.ts.map +0 -1
  114. package/dist/metrics/llm/context-precision/index.d.ts +0 -16
  115. package/dist/metrics/llm/context-precision/index.d.ts.map +0 -1
  116. package/dist/metrics/llm/context-precision/metricJudge.d.ts +0 -20
  117. package/dist/metrics/llm/context-precision/metricJudge.d.ts.map +0 -1
  118. package/dist/metrics/llm/context-precision/prompts.d.ts +0 -17
  119. package/dist/metrics/llm/context-precision/prompts.d.ts.map +0 -1
  120. package/dist/metrics/llm/context-relevancy/index.d.ts +0 -16
  121. package/dist/metrics/llm/context-relevancy/index.d.ts.map +0 -1
  122. package/dist/metrics/llm/context-relevancy/metricJudge.d.ts +0 -16
  123. package/dist/metrics/llm/context-relevancy/metricJudge.d.ts.map +0 -1
  124. package/dist/metrics/llm/context-relevancy/prompts.d.ts +0 -13
  125. package/dist/metrics/llm/context-relevancy/prompts.d.ts.map +0 -1
  126. package/dist/metrics/llm/contextual-recall/index.d.ts +0 -16
  127. package/dist/metrics/llm/contextual-recall/index.d.ts.map +0 -1
  128. package/dist/metrics/llm/contextual-recall/metricJudge.d.ts +0 -16
  129. package/dist/metrics/llm/contextual-recall/metricJudge.d.ts.map +0 -1
  130. package/dist/metrics/llm/contextual-recall/prompts.d.ts +0 -13
  131. package/dist/metrics/llm/contextual-recall/prompts.d.ts.map +0 -1
  132. package/dist/metrics/llm/faithfulness/index.d.ts +0 -16
  133. package/dist/metrics/llm/faithfulness/index.d.ts.map +0 -1
  134. package/dist/metrics/llm/faithfulness/metricJudge.d.ts +0 -22
  135. package/dist/metrics/llm/faithfulness/metricJudge.d.ts.map +0 -1
  136. package/dist/metrics/llm/faithfulness/prompts.d.ts +0 -20
  137. package/dist/metrics/llm/faithfulness/prompts.d.ts.map +0 -1
  138. package/dist/metrics/llm/hallucination/index.d.ts +0 -16
  139. package/dist/metrics/llm/hallucination/index.d.ts.map +0 -1
  140. package/dist/metrics/llm/hallucination/metricJudge.d.ts +0 -22
  141. package/dist/metrics/llm/hallucination/metricJudge.d.ts.map +0 -1
  142. package/dist/metrics/llm/hallucination/prompts.d.ts +0 -17
  143. package/dist/metrics/llm/hallucination/prompts.d.ts.map +0 -1
  144. package/dist/metrics/llm/index.cjs +0 -2481
  145. package/dist/metrics/llm/index.cjs.map +0 -1
  146. package/dist/metrics/llm/index.d.ts +0 -12
  147. package/dist/metrics/llm/index.d.ts.map +0 -1
  148. package/dist/metrics/llm/index.js +0 -2469
  149. package/dist/metrics/llm/index.js.map +0 -1
  150. package/dist/metrics/llm/prompt-alignment/index.d.ts +0 -33
  151. package/dist/metrics/llm/prompt-alignment/index.d.ts.map +0 -1
  152. package/dist/metrics/llm/prompt-alignment/metricJudge.d.ts +0 -20
  153. package/dist/metrics/llm/prompt-alignment/metricJudge.d.ts.map +0 -1
  154. package/dist/metrics/llm/prompt-alignment/prompts.d.ts +0 -17
  155. package/dist/metrics/llm/prompt-alignment/prompts.d.ts.map +0 -1
  156. package/dist/metrics/llm/summarization/index.d.ts +0 -19
  157. package/dist/metrics/llm/summarization/index.d.ts.map +0 -1
  158. package/dist/metrics/llm/summarization/metricJudge.d.ts +0 -34
  159. package/dist/metrics/llm/summarization/metricJudge.d.ts.map +0 -1
  160. package/dist/metrics/llm/summarization/prompts.d.ts +0 -30
  161. package/dist/metrics/llm/summarization/prompts.d.ts.map +0 -1
  162. package/dist/metrics/llm/toxicity/index.d.ts +0 -14
  163. package/dist/metrics/llm/toxicity/index.d.ts.map +0 -1
  164. package/dist/metrics/llm/toxicity/metricJudge.d.ts +0 -14
  165. package/dist/metrics/llm/toxicity/metricJudge.d.ts.map +0 -1
  166. package/dist/metrics/llm/toxicity/prompts.d.ts +0 -10
  167. package/dist/metrics/llm/toxicity/prompts.d.ts.map +0 -1
  168. package/dist/metrics/llm/types.d.ts +0 -7
  169. package/dist/metrics/llm/types.d.ts.map +0 -1
  170. package/dist/metrics/llm/utils.d.ts +0 -14
  171. package/dist/metrics/llm/utils.d.ts.map +0 -1
  172. package/dist/metrics/nlp/completeness/index.d.ts +0 -21
  173. package/dist/metrics/nlp/completeness/index.d.ts.map +0 -1
  174. package/dist/metrics/nlp/content-similarity/index.d.ts +0 -18
  175. package/dist/metrics/nlp/content-similarity/index.d.ts.map +0 -1
  176. package/dist/metrics/nlp/index.cjs +0 -201
  177. package/dist/metrics/nlp/index.cjs.map +0 -1
  178. package/dist/metrics/nlp/index.d.ts +0 -6
  179. package/dist/metrics/nlp/index.d.ts.map +0 -1
  180. package/dist/metrics/nlp/index.js +0 -188
  181. package/dist/metrics/nlp/index.js.map +0 -1
  182. package/dist/metrics/nlp/keyword-coverage/index.d.ts +0 -13
  183. package/dist/metrics/nlp/keyword-coverage/index.d.ts.map +0 -1
  184. package/dist/metrics/nlp/textual-difference/index.d.ts +0 -15
  185. package/dist/metrics/nlp/textual-difference/index.d.ts.map +0 -1
  186. package/dist/metrics/nlp/tone/index.d.ts +0 -18
  187. package/dist/metrics/nlp/tone/index.d.ts.map +0 -1
  188. package/dist/ratio.d.ts +0 -13
  189. package/dist/ratio.d.ts.map +0 -1
  190. package/dist/scorers/code/index.cjs +0 -327
  191. package/dist/scorers/code/index.cjs.map +0 -1
  192. package/dist/scorers/code/index.js +0 -313
  193. package/dist/scorers/code/index.js.map +0 -1
  194. package/dist/scorers/llm/index.cjs.map +0 -1
  195. 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,201 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkPWGOG6ML_cjs = require('../../chunk-PWGOG6ML.cjs');
4
- var _eval = require('@mastra/core/eval');
5
- var nlp = require('compromise');
6
- var stringSimilarity = require('string-similarity');
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 ratio = chunkPWGOG6ML_cjs.calculateRatio(input, output);
115
- const changes = chunkPWGOG6ML_cjs.countChanges(input, output);
116
- const maxLength = Math.max(input.length, output.length);
117
- const lengthDiff = maxLength > 0 ? Math.abs(input.length - output.length) / maxLength : 0;
118
- const confidence = 1 - lengthDiff;
119
- return {
120
- score: ratio,
121
- info: {
122
- confidence,
123
- ratio,
124
- changes,
125
- lengthDiff
126
- }
127
- };
128
- }
129
- };
130
- var KeywordCoverageMetric = class extends _eval.Metric {
131
- async measure(input, output) {
132
- if (!input && !output) {
133
- return {
134
- score: 1,
135
- info: {
136
- totalKeywords: 0,
137
- matchedKeywords: 0
138
- }
139
- };
140
- }
141
- const extractKeywords = (text) => {
142
- return keyword_extractor__default.default.extract(text, {
143
- language: "english",
144
- remove_digits: true,
145
- return_changed_case: true,
146
- remove_duplicates: true
147
- });
148
- };
149
- const referenceKeywords = new Set(extractKeywords(input));
150
- const responseKeywords = new Set(extractKeywords(output));
151
- const matchedKeywords = [...referenceKeywords].filter((k) => responseKeywords.has(k));
152
- const totalKeywords = referenceKeywords.size;
153
- const coverage = totalKeywords > 0 ? matchedKeywords.length / totalKeywords : 0;
154
- return {
155
- score: coverage,
156
- info: {
157
- totalKeywords: referenceKeywords.size,
158
- matchedKeywords: matchedKeywords.length
159
- }
160
- };
161
- }
162
- };
163
- var ToneConsistencyMetric = class extends _eval.Metric {
164
- sentiment = new Sentiment__default.default();
165
- async measure(input, output) {
166
- const responseSentiment = this.sentiment.analyze(input);
167
- if (output) {
168
- const referenceSentiment = this.sentiment.analyze(output);
169
- const sentimentDiff = Math.abs(responseSentiment.comparative - referenceSentiment.comparative);
170
- const normalizedScore = Math.max(0, 1 - sentimentDiff);
171
- return {
172
- score: normalizedScore,
173
- info: {
174
- responseSentiment: responseSentiment.comparative,
175
- referenceSentiment: referenceSentiment.comparative,
176
- difference: sentimentDiff
177
- }
178
- };
179
- }
180
- const sentences = input.match(/[^.!?]+[.!?]+/g) || [input];
181
- const sentiments = sentences.map((s) => this.sentiment.analyze(s).comparative);
182
- const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;
183
- const variance = sentiments.reduce((sum, s) => sum + Math.pow(s - avgSentiment, 2), 0) / sentiments.length;
184
- const stability = Math.max(0, 1 - variance);
185
- return {
186
- score: stability,
187
- info: {
188
- avgSentiment,
189
- sentimentVariance: variance
190
- }
191
- };
192
- }
193
- };
194
-
195
- exports.CompletenessMetric = CompletenessMetric;
196
- exports.ContentSimilarityMetric = ContentSimilarityMetric;
197
- exports.KeywordCoverageMetric = KeywordCoverageMetric;
198
- exports.TextualDifferenceMetric = TextualDifferenceMetric;
199
- exports.ToneConsistencyMetric = ToneConsistencyMetric;
200
- //# sourceMappingURL=index.cjs.map
201
- //# 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","calculateRatio","countChanges","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 { calculateRatio, countChanges } from '../../../ratio';\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 // Calculate similarity ratio using LCS approach (similar to SequenceMatcher.ratio())\n const ratio = calculateRatio(input, output);\n\n // Count changes by comparing words\n const changes = countChanges(input, output);\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,188 +0,0 @@
1
- import { calculateRatio, countChanges } from '../../chunk-44PMY5ES.js';
2
- import { Metric } from '@mastra/core/eval';
3
- import nlp from 'compromise';
4
- import stringSimilarity from 'string-similarity';
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 ratio = calculateRatio(input, output);
106
- const changes = countChanges(input, output);
107
- const maxLength = Math.max(input.length, output.length);
108
- const lengthDiff = maxLength > 0 ? Math.abs(input.length - output.length) / maxLength : 0;
109
- const confidence = 1 - lengthDiff;
110
- return {
111
- score: ratio,
112
- info: {
113
- confidence,
114
- ratio,
115
- changes,
116
- lengthDiff
117
- }
118
- };
119
- }
120
- };
121
- var KeywordCoverageMetric = class extends Metric {
122
- async measure(input, output) {
123
- if (!input && !output) {
124
- return {
125
- score: 1,
126
- info: {
127
- totalKeywords: 0,
128
- matchedKeywords: 0
129
- }
130
- };
131
- }
132
- const extractKeywords = (text) => {
133
- return keyword_extractor.extract(text, {
134
- language: "english",
135
- remove_digits: true,
136
- return_changed_case: true,
137
- remove_duplicates: true
138
- });
139
- };
140
- const referenceKeywords = new Set(extractKeywords(input));
141
- const responseKeywords = new Set(extractKeywords(output));
142
- const matchedKeywords = [...referenceKeywords].filter((k) => responseKeywords.has(k));
143
- const totalKeywords = referenceKeywords.size;
144
- const coverage = totalKeywords > 0 ? matchedKeywords.length / totalKeywords : 0;
145
- return {
146
- score: coverage,
147
- info: {
148
- totalKeywords: referenceKeywords.size,
149
- matchedKeywords: matchedKeywords.length
150
- }
151
- };
152
- }
153
- };
154
- var ToneConsistencyMetric = class extends Metric {
155
- sentiment = new Sentiment();
156
- async measure(input, output) {
157
- const responseSentiment = this.sentiment.analyze(input);
158
- if (output) {
159
- const referenceSentiment = this.sentiment.analyze(output);
160
- const sentimentDiff = Math.abs(responseSentiment.comparative - referenceSentiment.comparative);
161
- const normalizedScore = Math.max(0, 1 - sentimentDiff);
162
- return {
163
- score: normalizedScore,
164
- info: {
165
- responseSentiment: responseSentiment.comparative,
166
- referenceSentiment: referenceSentiment.comparative,
167
- difference: sentimentDiff
168
- }
169
- };
170
- }
171
- const sentences = input.match(/[^.!?]+[.!?]+/g) || [input];
172
- const sentiments = sentences.map((s) => this.sentiment.analyze(s).comparative);
173
- const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;
174
- const variance = sentiments.reduce((sum, s) => sum + Math.pow(s - avgSentiment, 2), 0) / sentiments.length;
175
- const stability = Math.max(0, 1 - variance);
176
- return {
177
- score: stability,
178
- info: {
179
- avgSentiment,
180
- sentimentVariance: variance
181
- }
182
- };
183
- }
184
- };
185
-
186
- export { CompletenessMetric, ContentSimilarityMetric, KeywordCoverageMetric, TextualDifferenceMetric, ToneConsistencyMetric };
187
- //# sourceMappingURL=index.js.map
188
- //# 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 { calculateRatio, countChanges } from '../../../ratio';\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 // Calculate similarity ratio using LCS approach (similar to SequenceMatcher.ratio())\n const ratio = calculateRatio(input, output);\n\n // Count changes by comparing words\n const changes = countChanges(input, output);\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;CAsB/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"}
package/dist/ratio.d.ts DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * Calculates similarity ratio similar to SequenceMatcher.ratio()
3
- * Uses longest common subsequence (LCS) approach
4
- * Ratio = 2.0 * matches / total
5
- */
6
- export declare function calculateRatio(input: string, output: string): number;
7
- /**
8
- * Counts the number of differences between two strings
9
- * Uses opcodes-like approach: counts insertions, deletions, and replacements
10
- * For whitespace differences, preserves the original strings before word splitting
11
- */
12
- export declare function countChanges(input: string, output: string): number;
13
- //# sourceMappingURL=ratio.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ratio.d.ts","sourceRoot":"","sources":["../src/ratio.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAapE;AA+BD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAqClE"}