@cogitator-ai/evals 0.9.0 → 0.10.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 (74) hide show
  1. package/README.md +195 -47
  2. package/dist/datasets/csv-loader.d.ts +5 -0
  3. package/dist/datasets/csv-loader.d.ts.map +1 -1
  4. package/dist/datasets/csv-loader.js +18 -0
  5. package/dist/datasets/csv-loader.js.map +1 -1
  6. package/dist/eval-builder.d.ts +3 -0
  7. package/dist/eval-builder.d.ts.map +1 -1
  8. package/dist/eval-builder.js +7 -0
  9. package/dist/eval-builder.js.map +1 -1
  10. package/dist/eval-comparison.d.ts +5 -0
  11. package/dist/eval-comparison.d.ts.map +1 -1
  12. package/dist/eval-comparison.js +20 -4
  13. package/dist/eval-comparison.js.map +1 -1
  14. package/dist/eval-suite.d.ts +48 -5
  15. package/dist/eval-suite.d.ts.map +1 -1
  16. package/dist/eval-suite.js +219 -57
  17. package/dist/eval-suite.js.map +1 -1
  18. package/dist/index.d.ts +13 -8
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +5 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/matchers.d.ts +68 -0
  23. package/dist/matchers.d.ts.map +1 -0
  24. package/dist/matchers.js +112 -0
  25. package/dist/matchers.js.map +1 -0
  26. package/dist/metrics/custom.d.ts +19 -7
  27. package/dist/metrics/custom.d.ts.map +1 -1
  28. package/dist/metrics/custom.js +5 -0
  29. package/dist/metrics/custom.js.map +1 -1
  30. package/dist/metrics/index.d.ts +8 -4
  31. package/dist/metrics/index.d.ts.map +1 -1
  32. package/dist/metrics/index.js +4 -2
  33. package/dist/metrics/index.js.map +1 -1
  34. package/dist/metrics/llm-judge.d.ts +20 -1
  35. package/dist/metrics/llm-judge.d.ts.map +1 -1
  36. package/dist/metrics/llm-judge.js +64 -10
  37. package/dist/metrics/llm-judge.js.map +1 -1
  38. package/dist/metrics/matching.d.ts +28 -0
  39. package/dist/metrics/matching.d.ts.map +1 -0
  40. package/dist/metrics/matching.js +124 -0
  41. package/dist/metrics/matching.js.map +1 -0
  42. package/dist/metrics/retrieval.d.ts +21 -0
  43. package/dist/metrics/retrieval.d.ts.map +1 -0
  44. package/dist/metrics/retrieval.js +108 -0
  45. package/dist/metrics/retrieval.js.map +1 -0
  46. package/dist/metrics/statistical.d.ts +28 -0
  47. package/dist/metrics/statistical.d.ts.map +1 -1
  48. package/dist/metrics/statistical.js +61 -0
  49. package/dist/metrics/statistical.js.map +1 -1
  50. package/dist/metrics/tool-calls.d.ts +43 -0
  51. package/dist/metrics/tool-calls.d.ts.map +1 -0
  52. package/dist/metrics/tool-calls.js +106 -0
  53. package/dist/metrics/tool-calls.js.map +1 -0
  54. package/dist/metrics/types.d.ts +47 -5
  55. package/dist/metrics/types.d.ts.map +1 -1
  56. package/dist/metrics/types.js.map +1 -1
  57. package/dist/reporters/console.d.ts.map +1 -1
  58. package/dist/reporters/console.js +6 -2
  59. package/dist/reporters/console.js.map +1 -1
  60. package/dist/reporters/format.d.ts +6 -0
  61. package/dist/reporters/format.d.ts.map +1 -1
  62. package/dist/reporters/format.js +4 -0
  63. package/dist/reporters/format.js.map +1 -1
  64. package/dist/reporters/github.d.ts.map +1 -1
  65. package/dist/reporters/github.js +3 -2
  66. package/dist/reporters/github.js.map +1 -1
  67. package/dist/reporters/index.d.ts +34 -21
  68. package/dist/reporters/index.d.ts.map +1 -1
  69. package/dist/reporters/index.js.map +1 -1
  70. package/dist/schema.d.ts +14 -0
  71. package/dist/schema.d.ts.map +1 -1
  72. package/dist/schema.js +13 -0
  73. package/dist/schema.js.map +1 -1
  74. package/package.json +8 -3
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export declare const VERSION: string;
2
2
  export { EvalSuite, isLLMMetric } from './eval-suite.js';
3
- export type { EvalTarget, EvalTargetContext, EvalProgress, EvalRunOptions, EvalSuiteOptions, EvalSuiteResult, EvalSuiteStats, } from './eval-suite.js';
3
+ export type { EvalTarget, EvalTargetContext, EvalTurn, RetrievalToolResult, EvalProgress, EvalRunOptions, EvalSuiteOptions, EvalSuiteResult, EvalSuiteStats, } from './eval-suite.js';
4
4
  export { EvalComparison } from './eval-comparison.js';
5
5
  export type { EvalComparisonOptions, EvalComparisonRunOptions, MetricComparison, ComparisonResult, } from './eval-comparison.js';
6
6
  export { EvalBuilder } from './eval-builder.js';
@@ -8,25 +8,30 @@ export { Dataset } from './datasets/index.js';
8
8
  export { loadJsonl } from './datasets/index.js';
9
9
  export { loadCsv } from './datasets/index.js';
10
10
  export { exactMatch, contains, containsAll, containsAny, similarity, regex, jsonSchema, } from './metrics/deterministic.js';
11
- export { faithfulness, relevance, coherence, helpfulness, llmMetric, bindJudgeContext, } from './metrics/llm-judge.js';
12
- export type { LLMMetricFn, JudgeContext } from './metrics/llm-judge.js';
13
- export { latency, cost, tokenUsage } from './metrics/statistical.js';
11
+ export { faithfulness, relevance, coherence, helpfulness, llmMetric, contextRelevance, bindJudgeContext, } from './metrics/llm-judge.js';
12
+ export type { LLMMetricFn, JudgeContext, JudgeMessage } from './metrics/llm-judge.js';
13
+ export { latency, cost, tokenUsage, passAtK, passAtKEstimate, isPassAtKMetric, } from './metrics/statistical.js';
14
+ export type { PassAtKOptions, PassAtKMetricFn } from './metrics/statistical.js';
15
+ export { toolCalls, trajectory, toolCallMatches, trajectoryScore } from './metrics/tool-calls.js';
16
+ export type { ToolCallsOptions, TrajectoryOptions, ToolArgumentsMatch, ToolCallsScore, TrajectoryOrder, } from './metrics/tool-calls.js';
17
+ export { retrievalRecall, retrievalPrecision, retrievalMRR, ragSearchPassages, } from './metrics/retrieval.js';
18
+ export { passageMatches } from './metrics/matching.js';
14
19
  export { metric } from './metrics/custom.js';
15
- export type { MetricFn, MetricScore, MetricUsage, MetricOptions, EvalCaseResult, StatisticalMetricFn, StatisticalScore, } from './metrics/types.js';
16
- export type { CustomMetricConfig } from './metrics/custom.js';
20
+ export type { MetricFn, MetricScore, MetricUsage, MetricOptions, EvalCaseResult, ScoredCaseResult, EvalToolCall, EvalToolResult, EvalTurnResult, Passage, StatisticalMetricFn, StatisticalScore, } from './metrics/types.js';
21
+ export type { CustomMetricConfig, CustomMetricData } from './metrics/custom.js';
17
22
  export { threshold } from './assertions/index.js';
18
23
  export { noRegression } from './assertions/index.js';
19
24
  export { assertion } from './assertions/index.js';
20
25
  export { maxErrorRate } from './assertions/index.js';
21
26
  export type { AssertionFn, AssertionResult, AggregatedMetric, EvalStats } from './assertions/index.js';
22
27
  export { report } from './reporters/index.js';
23
- export type { ReporterType, ReporterOptions } from './reporters/index.js';
28
+ export type { ReporterType, ReporterOptions, ReportedCase } from './reporters/index.js';
24
29
  export { pairedTTest } from './stats/t-test.js';
25
30
  export type { TTestResult } from './stats/t-test.js';
26
31
  export { mcnemarsTest } from './stats/mcnemar.js';
27
32
  export type { McNemarResult } from './stats/mcnemar.js';
28
33
  export { mean, median, stdDev, percentile, aggregate } from './stats/percentiles.js';
29
- export type { EvalCase, EvalSuiteConfig, JudgeConfig, JudgeConfigInput, JudgeCache, JudgeCogitator, EvalComparisonConfig, } from './schema.js';
34
+ export type { EvalCase, ExpectedToolCall, EvalSuiteConfig, JudgeConfig, JudgeConfigInput, JudgeCache, JudgeCogitator, EvalComparisonConfig, } from './schema.js';
30
35
  export { createRunEvalTool, evalTools } from './tools.js';
31
36
  export type { EvalTool } from './tools.js';
32
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,EAAE,MAA4B,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9F,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAElF,YAAY,EACV,QAAQ,EACR,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACvD,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,8 +8,11 @@ export { Dataset } from './datasets/index.js';
8
8
  export { loadJsonl } from './datasets/index.js';
9
9
  export { loadCsv } from './datasets/index.js';
10
10
  export { exactMatch, contains, containsAll, containsAny, similarity, regex, jsonSchema, } from './metrics/deterministic.js';
11
- export { faithfulness, relevance, coherence, helpfulness, llmMetric, bindJudgeContext, } from './metrics/llm-judge.js';
12
- export { latency, cost, tokenUsage } from './metrics/statistical.js';
11
+ export { faithfulness, relevance, coherence, helpfulness, llmMetric, contextRelevance, bindJudgeContext, } from './metrics/llm-judge.js';
12
+ export { latency, cost, tokenUsage, passAtK, passAtKEstimate, isPassAtKMetric, } from './metrics/statistical.js';
13
+ export { toolCalls, trajectory, toolCallMatches, trajectoryScore } from './metrics/tool-calls.js';
14
+ export { retrievalRecall, retrievalPrecision, retrievalMRR, ragSearchPassages, } from './metrics/retrieval.js';
15
+ export { passageMatches } from './metrics/matching.js';
13
16
  export { metric } from './metrics/custom.js';
14
17
  export { threshold } from './assertions/index.js';
15
18
  export { noRegression } from './assertions/index.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAwB,CAAC;AAE7F,MAAM,CAAC,MAAM,OAAO,GAAW,WAAW,CAAC,OAAO,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAUtD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAY1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAYlF,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAwB,CAAC;AAE7F,MAAM,CAAC,MAAM,OAAO,GAAW,WAAW,CAAC,OAAO,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAYtD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,OAAO,EACP,IAAI,EACJ,UAAU,EACV,OAAO,EACP,eAAe,EACf,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQ/F,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAiB1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAalF,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { TrajectoryOrder } from './metrics/tool-calls.js';
2
+ /** The matchers `evalMatchers` adds to Vitest's `expect`, typed for Vitest 5 */
3
+ export interface EvalMatchers<R = unknown> {
4
+ /**
5
+ * The case result called the tool `name`, over any of its turns, with arguments holding `args`
6
+ * when given (other arguments may be there too)
7
+ */
8
+ toHaveCalledTool(name: string, args?: Record<string, unknown>): R;
9
+ /**
10
+ * The case result called the tools in `names`. `order: 'exact'` (default): those calls and
11
+ * no others, in this order. `'in-order'`: in this order, other calls may come between.
12
+ * `'any-order'`: each of them, in any order, other calls allowed
13
+ */
14
+ toFollowTrajectory(names: readonly string[], options?: {
15
+ order?: TrajectoryOrder;
16
+ }): R;
17
+ /**
18
+ * The case result retrieved a passage with this id or this text, or whose text contains this
19
+ * one or is contained in it when the contained text has at least three words
20
+ */
21
+ toHaveRetrieved(idOrText: string): R;
22
+ /**
23
+ * A case result scored at least `min` on the metric, or a suite result's mean of the metric
24
+ * is at least `min`
25
+ */
26
+ toScoreAtLeast(metricName: string, min: number): R;
27
+ }
28
+ declare module 'vitest' {
29
+ interface Assertion<R extends void | Promise<void> = void, T = unknown> extends EvalMatchers<R> {
30
+ }
31
+ interface AsymmetricMatchersContaining extends EvalMatchers {
32
+ }
33
+ }
34
+ /** The part of Vitest's matcher context the eval matchers use */
35
+ interface MatcherContext {
36
+ isNot: boolean;
37
+ }
38
+ interface MatcherResult {
39
+ pass: boolean;
40
+ message: () => string;
41
+ actual?: unknown;
42
+ expected?: unknown;
43
+ }
44
+ /**
45
+ * Vitest matchers for eval results. Register them once, in a test file or a setup file:
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { expect } from 'vitest';
50
+ * import { evalMatchers } from '@cogitator-ai/evals/matchers';
51
+ *
52
+ * expect.extend(evalMatchers);
53
+ *
54
+ * const { results } = await suite.run();
55
+ * expect(results[0]).toHaveCalledTool('get_weather', { city: 'Paris' });
56
+ * expect(results[0]).toFollowTrajectory(['search', 'answer'], { order: 'in-order' });
57
+ * ```
58
+ */
59
+ export declare const evalMatchers: {
60
+ toHaveCalledTool(this: MatcherContext, received: unknown, name: string, args?: Record<string, unknown>): MatcherResult;
61
+ toFollowTrajectory(this: MatcherContext, received: unknown, names: readonly string[], options?: {
62
+ order?: TrajectoryOrder;
63
+ }): MatcherResult;
64
+ toHaveRetrieved(this: MatcherContext, received: unknown, idOrText: string): MatcherResult;
65
+ toScoreAtLeast(this: MatcherContext, received: unknown, metricName: string, min: number): MatcherResult;
66
+ };
67
+ export {};
68
+ //# sourceMappingURL=matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAS5D,gFAAgF;AAChF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAClE;;;;OAIG;IACH,kBAAkB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,eAAe,CAAA;KAAE,GAAG,CAAC,CAAC;IACvF;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC;IACrC;;;OAGG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC;CACpD;AAED,OAAO,QAAQ,QAAQ,CAAC;IAEtB,UAAU,SAAS,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,OAAO,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;KAAG;IAElG,UAAU,4BAA6B,SAAQ,YAAY;KAAG;CAC/D;AAED,iEAAiE;AACjE,UAAU,cAAc;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA4BD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY;2BAEf,cAAc,YACV,OAAO,QACX,MAAM,SACL,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,aAAa;6BAgBR,cAAc,YACV,OAAO,SACV,SAAS,MAAM,EAAE,YACf;QAAE,KAAK,CAAC,EAAE,eAAe,CAAA;KAAE,GACnC,aAAa;0BAmBM,cAAc,YAAY,OAAO,YAAY,MAAM,GAAG,aAAa;yBAejF,cAAc,YACV,OAAO,cACL,MAAM,OACb,MAAM,GACV,aAAa;CAUjB,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { trajectoryScore } from './metrics/tool-calls.js';
2
+ import { isSubset, longestCommonSubsequence, multisetOverlap, passageMatches, } from './metrics/matching.js';
3
+ function isRecord(value) {
4
+ return typeof value === 'object' && value !== null;
5
+ }
6
+ function caseResultOf(received, matcher) {
7
+ if (isRecord(received) && isRecord(received.case) && typeof received.output === 'string') {
8
+ return received;
9
+ }
10
+ throw new TypeError(`${matcher} expects a case result, one of suite.run()'s results`);
11
+ }
12
+ function callText(name, args) {
13
+ return args === undefined ? name : `${name}(${JSON.stringify(args)})`;
14
+ }
15
+ function callsText(result) {
16
+ const calls = result.toolCalls ?? [];
17
+ return calls.length === 0
18
+ ? 'no tool calls'
19
+ : calls.map((c) => callText(c.name, c.arguments)).join(', ');
20
+ }
21
+ function negation(context) {
22
+ return context.isNot ? 'not ' : '';
23
+ }
24
+ /**
25
+ * Vitest matchers for eval results. Register them once, in a test file or a setup file:
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { expect } from 'vitest';
30
+ * import { evalMatchers } from '@cogitator-ai/evals/matchers';
31
+ *
32
+ * expect.extend(evalMatchers);
33
+ *
34
+ * const { results } = await suite.run();
35
+ * expect(results[0]).toHaveCalledTool('get_weather', { city: 'Paris' });
36
+ * expect(results[0]).toFollowTrajectory(['search', 'answer'], { order: 'in-order' });
37
+ * ```
38
+ */
39
+ export const evalMatchers = {
40
+ toHaveCalledTool(received, name, args) {
41
+ const result = caseResultOf(received, 'toHaveCalledTool');
42
+ const calls = result.toolCalls ?? [];
43
+ const pass = calls.some((call) => call.name === name && (args === undefined || isSubset(args, call.arguments)));
44
+ return {
45
+ pass,
46
+ message: () => `expected the case ${negation(this)}to call ${callText(name, args)}, it made ${callsText(result)}`,
47
+ actual: calls.map((c) => ({ name: c.name, arguments: c.arguments })),
48
+ expected: { name, ...(args !== undefined && { arguments: args }) },
49
+ };
50
+ },
51
+ toFollowTrajectory(received, names, options = {}) {
52
+ const result = caseResultOf(received, 'toFollowTrajectory');
53
+ const order = options.order ?? 'exact';
54
+ const actual = (result.toolCalls ?? []).map((c) => c.name);
55
+ const pass = order === 'exact'
56
+ ? trajectoryScore(names, actual, 'exact') === 1
57
+ : order === 'in-order'
58
+ ? longestCommonSubsequence(names, actual) === names.length
59
+ : multisetOverlap(names, actual) === names.length;
60
+ return {
61
+ pass,
62
+ message: () => `expected the tool calls ${negation(this)}to follow [${names.join(', ')}] (${order}), they were [${actual.join(', ')}]`,
63
+ actual,
64
+ expected: [...names],
65
+ };
66
+ },
67
+ toHaveRetrieved(received, idOrText) {
68
+ const result = caseResultOf(received, 'toHaveRetrieved');
69
+ const retrieved = result.retrieved ?? [];
70
+ const pass = retrieved.some((p) => passageMatches(p, idOrText));
71
+ const shown = retrieved.map((p) => p.id ?? JSON.stringify(p.content.slice(0, 60)));
72
+ return {
73
+ pass,
74
+ message: () => `expected the case ${negation(this)}to retrieve ${JSON.stringify(idOrText)}, it retrieved ${retrieved.length === 0 ? 'nothing' : `${retrieved.length} passage(s): ${shown.join(', ')}`}`,
75
+ };
76
+ },
77
+ toScoreAtLeast(received, metricName, min) {
78
+ const { score, of } = metricScoreOf(received, metricName);
79
+ const pass = score >= min;
80
+ return {
81
+ pass,
82
+ message: () => `expected ${of} ${negation(this)}to be at least ${min}, it is ${score}`,
83
+ actual: score,
84
+ expected: min,
85
+ };
86
+ },
87
+ };
88
+ /** The score a matcher compares: a case result's score of the metric, or a suite's mean of it */
89
+ function metricScoreOf(received, metricName) {
90
+ if (isRecord(received) && isRecord(received.aggregated)) {
91
+ const aggregated = received.aggregated;
92
+ const metric = aggregated[metricName];
93
+ if (!metric) {
94
+ throw new Error(`toScoreAtLeast: the suite has no metric '${metricName}', it has ${namesText(Object.keys(aggregated))}`);
95
+ }
96
+ return { score: metric.mean, of: `the mean of ${metricName}` };
97
+ }
98
+ const result = caseResultOf(received, 'toScoreAtLeast');
99
+ const scores = result.scores ?? [];
100
+ const found = scores.find((s) => s.name === metricName);
101
+ if (!found) {
102
+ throw new Error(`toScoreAtLeast: the case has no score for '${metricName}', it has ${namesText(scores.map((s) => s.name))}`);
103
+ }
104
+ return {
105
+ score: found.score,
106
+ of: `the ${metricName} score of the case${found.details ? ` (${found.details})` : ''}`,
107
+ };
108
+ }
109
+ function namesText(names) {
110
+ return names.length === 0 ? 'none' : names.map((n) => `'${n}'`).join(', ');
111
+ }
112
+ //# sourceMappingURL=matchers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.js","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,7 @@
1
- import type { MetricFn } from './types.js';
1
+ import type { MetricFn, EvalCaseResult, EvalToolCall, EvalToolResult, EvalTurnResult, Passage } from './types.js';
2
2
  export interface CustomMetricConfig {
3
3
  name: string;
4
- evaluate: (data: {
5
- input: string;
6
- output: string;
7
- expected?: string;
8
- context?: Record<string, unknown>;
9
- }) => Promise<{
4
+ evaluate: (data: CustomMetricData) => Promise<{
10
5
  score: number;
11
6
  details?: string;
12
7
  }> | {
@@ -14,6 +9,23 @@ export interface CustomMetricConfig {
14
9
  details?: string;
15
10
  };
16
11
  }
12
+ /** What a custom metric's `evaluate` gets about a case */
13
+ export interface CustomMetricData {
14
+ input: string;
15
+ output: string;
16
+ expected?: string;
17
+ context?: Record<string, unknown>;
18
+ /** The tool calls of the run, over every turn */
19
+ toolCalls?: readonly EvalToolCall[];
20
+ /** What the tool calls returned, over every turn */
21
+ toolResults?: readonly EvalToolResult[];
22
+ /** The passages the run retrieved */
23
+ retrieved?: readonly Passage[];
24
+ /** Each turn of a multi-turn case */
25
+ turns?: readonly EvalTurnResult[];
26
+ /** The whole case result, the case itself included */
27
+ result: EvalCaseResult;
28
+ }
17
29
  /**
18
30
  * A metric from an `evaluate` function. Its score is clamped to 0 - 1. When `evaluate` throws or
19
31
  * returns a score that is not a finite number (such as NaN from a division by zero), the metric
@@ -1 +1 @@
1
- {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/metrics/custom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAC;AAGxD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1F;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,QAAQ,CAsC3D"}
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/metrics/custom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,cAAc,EACd,cAAc,EACd,OAAO,EACR,MAAM,SAAS,CAAC;AAGjB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CACR,IAAI,EAAE,gBAAgB,KACnB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzF;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,iDAAiD;IACjD,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACpC,oDAAoD;IACpD,WAAW,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACxC,qCAAqC;IACrC,SAAS,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC/B,qCAAqC;IACrC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,sDAAsD;IACtD,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,QAAQ,CA2C3D"}
@@ -12,6 +12,11 @@ export function metric(config) {
12
12
  output: result.output,
13
13
  expected: result.case.expected,
14
14
  context: result.case.context,
15
+ toolCalls: result.toolCalls,
16
+ toolResults: result.toolResults,
17
+ retrieved: result.retrieved,
18
+ turns: result.turns,
19
+ result,
15
20
  });
16
21
  const invalid = nonFiniteScoreError(score);
17
22
  if (invalid) {
@@ -1 +1 @@
1
- {"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/metrics/custom.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAY9C;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,MAA0B;IAC/C,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,MAAsB,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;gBAC/C,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK;gBACxB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ;gBAC9B,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;aAC7B,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;oBACL,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,mBAAmB,OAAO,EAAE;oBACrC,KAAK,EAAE,OAAO;iBACf,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBACtC,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC;aAC1C,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,mBAAmB,OAAO,EAAE;gBACrC,KAAK,EAAE,OAAO;aACf,CAAC;QACJ,CAAC;IACH,CAAC,CAAa,CAAC;IAEf,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;IAC5B,OAAO,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/metrics/custom.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AA2B9C;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,MAA0B;IAC/C,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,MAAsB,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;gBAC/C,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK;gBACxB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ;gBAC9B,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;gBAC5B,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,MAAM;aACP,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;oBACL,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,mBAAmB,OAAO,EAAE;oBACrC,KAAK,EAAE,OAAO;iBACf,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBACtC,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC;aAC1C,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,mBAAmB,OAAO,EAAE;gBACrC,KAAK,EAAE,OAAO;aACf,CAAC;QACJ,CAAC;IACH,CAAC,CAAa,CAAC;IAEf,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;IAC5B,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -1,8 +1,12 @@
1
- export type { MetricScore, MetricUsage, MetricOptions, EvalCaseResult, MetricFn, StatisticalMetricFn, StatisticalScore, } from './types.js';
1
+ export type { MetricScore, MetricUsage, MetricOptions, EvalCaseResult, MetricFn, StatisticalMetricFn, StatisticalScore, ScoredCaseResult, EvalToolCall, EvalToolResult, EvalTurnResult, Passage, } from './types.js';
2
2
  export { exactMatch, contains, containsAll, containsAny, similarity, regex, jsonSchema, } from './deterministic.js';
3
3
  export { metric } from './custom.js';
4
- export type { CustomMetricConfig } from './custom.js';
5
- export { latency, cost, tokenUsage } from './statistical.js';
6
- export { faithfulness, relevance, coherence, helpfulness, llmMetric, bindJudgeContext, } from './llm-judge.js';
4
+ export type { CustomMetricConfig, CustomMetricData } from './custom.js';
5
+ export { latency, cost, tokenUsage, passAtK, passAtKEstimate, isPassAtKMetric, } from './statistical.js';
6
+ export type { PassAtKOptions, PassAtKMetricFn } from './statistical.js';
7
+ export { toolCalls, trajectory, toolCallMatches, trajectoryScore } from './tool-calls.js';
8
+ export type { ToolCallsOptions, TrajectoryOptions, ToolArgumentsMatch, ToolCallsScore, TrajectoryOrder, } from './tool-calls.js';
9
+ export { retrievalRecall, retrievalPrecision, retrievalMRR, ragSearchPassages } from './retrieval.js';
10
+ export { faithfulness, relevance, coherence, helpfulness, contextRelevance, llmMetric, bindJudgeContext, } from './llm-judge.js';
7
11
  export type { JudgeContext, LLMMetricFn } from './llm-judge.js';
8
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,EACd,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,EACd,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,EACL,OAAO,EACP,IAAI,EACJ,UAAU,EACV,OAAO,EACP,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvF,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -1,5 +1,7 @@
1
1
  export { exactMatch, contains, containsAll, containsAny, similarity, regex, jsonSchema, } from './deterministic.js';
2
2
  export { metric } from './custom.js';
3
- export { latency, cost, tokenUsage } from './statistical.js';
4
- export { faithfulness, relevance, coherence, helpfulness, llmMetric, bindJudgeContext, } from './llm-judge.js';
3
+ export { latency, cost, tokenUsage, passAtK, passAtKEstimate, isPassAtKMetric, } from './statistical.js';
4
+ export { toolCalls, trajectory, toolCallMatches, trajectoryScore } from './tool-calls.js';
5
+ export { retrievalRecall, retrievalPrecision, retrievalMRR, ragSearchPassages } from './retrieval.js';
6
+ export { faithfulness, relevance, coherence, helpfulness, contextRelevance, llmMetric, bindJudgeContext, } from './llm-judge.js';
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,KAAK,EACL,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EACL,OAAO,EACP,IAAI,EACJ,UAAU,EACV,OAAO,EACP,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQvF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { JudgeCogitator, JudgeConfig } from '../schema.js';
2
- import type { MetricFn, MetricOptions, MetricUsage } from './types.js';
2
+ import type { MetricFn, EvalCaseResult, MetricOptions, MetricUsage } from './types.js';
3
3
  export interface JudgeContext {
4
4
  cogitator: {
5
5
  run: (opts: {
@@ -11,10 +11,18 @@ export interface JudgeContext {
11
11
  };
12
12
  judgeConfig: JudgeConfig;
13
13
  }
14
+ /** What the judge is asked about a case, or why the case is not judged and scores 0 */
15
+ export type JudgeMessage = {
16
+ message: string;
17
+ } | {
18
+ skip: string;
19
+ };
14
20
  export interface LLMMetricFn extends MetricFn {
15
21
  readonly requiresJudge: true;
16
22
  readonly __judgeSystemPrompt: string;
17
23
  readonly __judgeName: string;
24
+ /** Builds what the judge reads about a case. Default: input, context, expected and response */
25
+ readonly __judgeMessage?: (result: EvalCaseResult) => JudgeMessage;
18
26
  }
19
27
  /**
20
28
  * A judge context that runs the judge as a Cogitator agent on `judgeConfig.model`,
@@ -22,7 +30,18 @@ export interface LLMMetricFn extends MetricFn {
22
30
  */
23
31
  export declare function judgeContextFor(cogitator: JudgeCogitator, judgeConfig: JudgeConfig): JudgeContext;
24
32
  export declare function bindJudgeContext(metric: LLMMetricFn, context: JudgeContext): MetricFn;
33
+ /**
34
+ * How faithful the response is to the input and the evidence: the passages the run retrieved
35
+ * when the case has any, its `context` otherwise.
36
+ */
25
37
  export declare function faithfulness(opts?: MetricOptions): LLMMetricFn;
38
+ /**
39
+ * Whether the passages the run retrieved are relevant to the input, judged on the input (the
40
+ * conversation for a multi-turn case) and the passages alone (the case's `context` when nothing
41
+ * was retrieved). A case with neither scores 0
42
+ * without a judge call.
43
+ */
44
+ export declare function contextRelevance(opts?: MetricOptions): LLMMetricFn;
26
45
  export declare function relevance(opts?: MetricOptions): LLMMetricFn;
27
46
  export declare function coherence(opts?: MetricOptions): LLMMetricFn;
28
47
  export declare function helpfulness(opts?: MetricOptions): LLMMetricFn;
@@ -1 +1 @@
1
- {"version":3,"file":"llm-judge.d.ts","sourceRoot":"","sources":["../../src/metrics/llm-judge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAA+B,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjG,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE;QACT,GAAG,EAAE,CAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,WAAW,CAAA;SAAE,CAAC,CAAC;KACpF,CAAC;IACF,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC;IAC7B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAsFD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,GAAG,YAAY,CAyDjG;AA0GD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,QAAQ,CA6CrF;AAED,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK9D;AAED,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK3D;AAED,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK3D;AAED,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK7D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAK7E"}
1
+ {"version":3,"file":"llm-judge.d.ts","sourceRoot":"","sources":["../../src/metrics/llm-judge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EAEd,aAAa,EACb,WAAW,EAEZ,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE;QACT,GAAG,EAAE,CAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,WAAW,CAAA;SAAE,CAAC,CAAC;KACpF,CAAC;IACF,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,uFAAuF;AACvF,MAAM,MAAM,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC;IAC7B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+FAA+F;IAC/F,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,YAAY,CAAC;CACpE;AAsFD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,GAAG,YAAY,CAyDjG;AAgJD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,QAAQ,CA8CrF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAM9D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAUlE;AAED,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK3D;AAED,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK3D;AAED,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,WAAW,CAK7D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAK7E"}
@@ -195,7 +195,7 @@ function limiter(limit) {
195
195
  }
196
196
  };
197
197
  }
198
- function createJudgeMetric(name, systemPrompt) {
198
+ function createJudgeMetric(name, systemPrompt, message) {
199
199
  const fn = (async (_result) => {
200
200
  return { name, score: 0, details: 'unbound judge metric — call bindJudgeContext first' };
201
201
  });
@@ -203,6 +203,8 @@ function createJudgeMetric(name, systemPrompt) {
203
203
  Object.defineProperty(fn, 'requiresJudge', { value: true, writable: false });
204
204
  Object.defineProperty(fn, '__judgeSystemPrompt', { value: systemPrompt, writable: false });
205
205
  Object.defineProperty(fn, '__judgeName', { value: name, writable: false });
206
+ if (message)
207
+ Object.defineProperty(fn, '__judgeMessage', { value: message, writable: false });
206
208
  return fn;
207
209
  }
208
210
  function contextText(context) {
@@ -210,23 +212,57 @@ function contextText(context) {
210
212
  .map(([key, value]) => `${key}: ${typeof value === 'string' ? value : JSON.stringify(value, null, 2)}`)
211
213
  .join('\n');
212
214
  }
215
+ function passagesText(passages) {
216
+ return passages
217
+ .map((p, i) => `[${i + 1}]${p.source ? ` (${p.source})` : ''} ${p.content}`)
218
+ .join('\n');
219
+ }
213
220
  /**
214
- * What the judge reads: the input, the case's context when it has one (source documents, a
215
- * dossier, retrieved passages), the expected answer and the response.
221
+ * The evidence of a case: its retrieved passages when it has any and `preferRetrieved` is set,
222
+ * else its context, else nothing
216
223
  */
217
- function buildUserMessage(result) {
218
- const expected = result.case.expected || 'N/A';
224
+ function evidenceBlock(result, preferRetrieved) {
225
+ if (preferRetrieved && result.retrieved && result.retrieved.length > 0) {
226
+ return `Retrieved passages:\n${passagesText(result.retrieved)}`;
227
+ }
219
228
  const context = result.case.context;
220
- const contextBlock = context && Object.keys(context).length > 0 ? `\nContext:\n${contextText(context)}` : '';
221
- return `Input: ${result.case.input}${contextBlock}\nExpected: ${expected}\nResponse: ${result.output}`;
229
+ return context && Object.keys(context).length > 0
230
+ ? `Context:\n${contextText(context)}`
231
+ : undefined;
232
+ }
233
+ /**
234
+ * What the response answers. A single-turn case: its input. A multi-turn case: the conversation
235
+ * before the last user message, each turn's input and answer, then that last message marked as
236
+ * the one the response replies to.
237
+ */
238
+ function inputBlock(result) {
239
+ const inputs = [result.case.input, ...(result.case.turns ?? [])];
240
+ if (inputs.length === 1)
241
+ return `Input: ${result.case.input}`;
242
+ const earlier = inputs
243
+ .slice(0, -1)
244
+ .map((input, i) => `User: ${input}\nAssistant: ${result.turns?.[i]?.output ?? ''}`);
245
+ return `Conversation so far:\n${earlier.join('\n')}\nInput (the last user message, which the response answers): ${inputs[inputs.length - 1]}`;
246
+ }
247
+ /**
248
+ * What the judge reads: the input (the conversation for a multi-turn case), the case's evidence when it has some (its context, or the
249
+ * retrieved passages for metrics that prefer them), the expected answer and the response.
250
+ */
251
+ function buildUserMessage(result, preferRetrieved = false) {
252
+ const expected = result.case.expected || 'N/A';
253
+ const evidence = evidenceBlock(result, preferRetrieved);
254
+ const evidenceText = evidence === undefined ? '' : `\n${evidence}`;
255
+ return `${inputBlock(result)}${evidenceText}\nExpected: ${expected}\nResponse: ${result.output}`;
222
256
  }
223
257
  export function bindJudgeContext(metric, context) {
224
258
  const name = metric.__judgeName;
225
259
  const systemPrompt = metric.__judgeSystemPrompt;
226
260
  const bound = (async (result) => {
227
261
  try {
228
- const userMessage = buildUserMessage(result);
229
- const prompt = `${systemPrompt}\n\n${userMessage}`;
262
+ const message = metric.__judgeMessage?.(result) ?? { message: buildUserMessage(result) };
263
+ if ('skip' in message)
264
+ return { name, score: 0, details: message.skip };
265
+ const prompt = `${systemPrompt}\n\n${message.message}`;
230
266
  const runResult = await context.cogitator.run({ input: prompt });
231
267
  const usage = usageOf(runResult.usage);
232
268
  const parsed = parseJudgeOutput(runResult.output);
@@ -260,8 +296,26 @@ export function bindJudgeContext(metric, context) {
260
296
  Object.defineProperty(bound, 'metricName', { value: name, writable: false });
261
297
  return bound;
262
298
  }
299
+ /**
300
+ * How faithful the response is to the input and the evidence: the passages the run retrieved
301
+ * when the case has any, its `context` otherwise.
302
+ */
263
303
  export function faithfulness(opts) {
264
- return createJudgeMetric(opts?.name ?? 'faithfulness', 'You are evaluating the faithfulness of an AI assistant\'s response.\n\nGiven the input, the context when there is one, and the response, rate how faithful the response is to the facts and information in the input and the context. Claims that neither supports count against it.\n\nScore from 0.0 (completely unfaithful) to 1.0 (perfectly faithful).\n\nRespond with JSON: {"score": <number>, "reasoning": "<explanation>"}');
304
+ return createJudgeMetric(opts?.name ?? 'faithfulness', 'You are evaluating the faithfulness of an AI assistant\'s response.\n\nGiven the input, the context or retrieved passages when there are some, and the response, rate how faithful the response is to the facts and information in the input and the context. Claims that neither supports count against it.\n\nScore from 0.0 (completely unfaithful) to 1.0 (perfectly faithful).\n\nRespond with JSON: {"score": <number>, "reasoning": "<explanation>"}', (result) => ({ message: buildUserMessage(result, true) }));
305
+ }
306
+ /**
307
+ * Whether the passages the run retrieved are relevant to the input, judged on the input (the
308
+ * conversation for a multi-turn case) and the passages alone (the case's `context` when nothing
309
+ * was retrieved). A case with neither scores 0
310
+ * without a judge call.
311
+ */
312
+ export function contextRelevance(opts) {
313
+ return createJudgeMetric(opts?.name ?? 'contextRelevance', 'You are evaluating the context an AI assistant retrieved to answer a request.\n\nGiven the input and the retrieved passages (or context), rate how relevant they are to the input: whether they hold the information needed to answer it, with little that is off topic.\n\nScore from 0.0 (completely irrelevant) to 1.0 (perfectly relevant).\n\nRespond with JSON: {"score": <number>, "reasoning": "<explanation>"}', (result) => {
314
+ const evidence = evidenceBlock(result, true);
315
+ if (evidence === undefined)
316
+ return { skip: 'no retrieved passages or context to judge' };
317
+ return { message: `${inputBlock(result)}\n${evidence}` };
318
+ });
265
319
  }
266
320
  export function relevance(opts) {
267
321
  return createJudgeMetric(opts?.name ?? 'relevance', 'You are evaluating the relevance of an AI assistant\'s response.\n\nGiven the input and the response, rate how relevant the response is to the question asked.\n\nScore from 0.0 (completely irrelevant) to 1.0 (perfectly relevant).\n\nRespond with JSON: {"score": <number>, "reasoning": "<explanation>"}');