peerbench 0.0.6 → 0.0.7

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.
@@ -1,6 +1,12 @@
1
1
  declare abstract class AbstractScorer {
2
- abstract readonly kind: string;
2
+ readonly kind: string;
3
+ constructor();
3
4
  abstract score(params: any): Promise<BaseScorerResult | null>;
5
+ static withKind<TKind extends string, TThis extends abstract new (...args: any[]) => AbstractScorer>(this: TThis, kind: TKind): (new () => InstanceType<TThis> & {
6
+ readonly kind: TKind;
7
+ }) & {
8
+ readonly kind: TKind;
9
+ };
4
10
  }
5
11
  type BaseScorerResult = {
6
12
  value: number;
@@ -1,8 +1,8 @@
1
1
  import { BaseScoreV1, BaseTestCaseV1, BaseResponseV1 } from '../schemas/index.js';
2
- import { a as InferExtension } from '../index-BAioQhp2.js';
2
+ import { a as InferExtension } from '../index-Cn20kPrz.js';
3
3
  import z__default from 'zod';
4
- import '../provider-BDjGp2y-.js';
5
- import '../abstract-Dec9Sc5O.js';
4
+ import '../provider-DnEBdl1n.js';
5
+ import '../abstract-BdgLjkNC.js';
6
6
 
7
7
  declare abstract class AbstractAggregator {
8
8
  abstract push(params: {
@@ -1,10 +1,10 @@
1
- import { I as IdGenerator } from '../index-BAioQhp2.js';
1
+ import { I as IdGenerator } from '../index-Cn20kPrz.js';
2
2
  import z__default, { z } from 'zod';
3
- import { A as AbstractLLMProvider } from '../llm-BND163ns.js';
4
- import { a as MCQScorer, L as LLMAsAJudgeScorer } from '../llm-judge-BS_oNYUK.js';
3
+ import { A as AbstractLLMProvider } from '../llm-8ecJmwKJ.js';
4
+ import { a as MCQScorer, L as LLMAsAJudgeScorer } from '../llm-judge-BuF80-5-.js';
5
5
  import { J as JSONFileStorage } from '../json-file-Bgv9TLcX.js';
6
- import '../provider-BDjGp2y-.js';
7
- import '../abstract-Dec9Sc5O.js';
6
+ import '../provider-DnEBdl1n.js';
7
+ import '../abstract-BdgLjkNC.js';
8
8
  import 'openai/resources/shared';
9
9
  import 'openai/resources/chat/completions';
10
10
  import '../rate-limiter-CSmVIRsM.js';
@@ -54,7 +54,7 @@ declare const MCQTestCaseSchemaV1: z.ZodObject<Omit<{
54
54
  kind: "llm/mcq.tc";
55
55
  schemaVersion: 1;
56
56
  metadata?: Record<string, unknown> | undefined;
57
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
57
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
58
58
  id: string;
59
59
  question: string;
60
60
  options: Record<string, string>;
@@ -141,7 +141,7 @@ declare const MCQResponseSchemaV1: z.ZodObject<Omit<{
141
141
  outputTokensUsed?: number | undefined;
142
142
  inputCost?: string | undefined;
143
143
  outputCost?: string | undefined;
144
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
144
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
145
145
  startedAt: number;
146
146
  completedAt: number;
147
147
  id: string;
@@ -248,7 +248,7 @@ declare const MCQScoreSchemaV1: z.ZodObject<Omit<{
248
248
  scorerAIOutputTokensUsed?: number | undefined;
249
249
  scorerAIInputCost?: string | undefined;
250
250
  scorerAIOutputCost?: string | undefined;
251
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
251
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
252
252
  id: string;
253
253
  value: number;
254
254
  responseId: string;
@@ -335,7 +335,7 @@ declare const MultiTurnTestCaseSchemaV1: z.ZodObject<Omit<{
335
335
  metadata?: Record<string, unknown> | undefined;
336
336
  maxTurns?: number | undefined;
337
337
  expectedOutcome?: string | undefined;
338
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
338
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
339
339
  id: string;
340
340
  messages: {
341
341
  role: string;
@@ -467,7 +467,7 @@ declare const MultiTurnResponseSchemaV1: z.ZodObject<Omit<{
467
467
  outputTokensUsed?: number | undefined;
468
468
  inputCost?: string | undefined;
469
469
  outputCost?: string | undefined;
470
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
470
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
471
471
  startedAt: number;
472
472
  completedAt: number;
473
473
  id: string;
@@ -596,7 +596,7 @@ declare const MultiTurnScoreSchemaV1: z.ZodObject<Omit<{
596
596
  scorerAIOutputTokensUsed?: number | undefined;
597
597
  scorerAIInputCost?: string | undefined;
598
598
  scorerAIOutputCost?: string | undefined;
599
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
599
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
600
600
  id: string;
601
601
  value: number;
602
602
  responseId: string;
@@ -666,7 +666,7 @@ declare const QATestCaseSchemaV1: z.ZodObject<Omit<{
666
666
  kind: "llm/qa.tc";
667
667
  schemaVersion: 1;
668
668
  metadata?: Record<string, unknown> | undefined;
669
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
669
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
670
670
  id: string;
671
671
  question: string;
672
672
  goodAnswers: string[];
@@ -753,7 +753,7 @@ declare const QAResponseSchemaV1: z.ZodObject<Omit<{
753
753
  outputTokensUsed?: number | undefined;
754
754
  inputCost?: string | undefined;
755
755
  outputCost?: string | undefined;
756
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
756
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
757
757
  startedAt: number;
758
758
  completedAt: number;
759
759
  id: string;
@@ -856,7 +856,7 @@ declare const QAScoreSchemaV1: z.ZodObject<Omit<{
856
856
  scorerAIOutputTokensUsed?: number | undefined;
857
857
  scorerAIInputCost?: string | undefined;
858
858
  scorerAIOutputCost?: string | undefined;
859
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
859
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
860
860
  id: string;
861
861
  value: number;
862
862
  responseId: string;
@@ -1046,7 +1046,7 @@ declare const peerbenchRunner: ((params: {
1046
1046
  kind: `${string}/simple.sys-prompt`;
1047
1047
  schemaVersion: 1;
1048
1048
  metadata?: Record<string, unknown> | undefined;
1049
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1049
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1050
1050
  id: string;
1051
1051
  version: number;
1052
1052
  content: string;
@@ -1096,7 +1096,7 @@ declare const peerbenchRunner: ((params: {
1096
1096
  kind: `${string}/simple.sys-prompt`;
1097
1097
  schemaVersion: 1;
1098
1098
  metadata?: Record<string, unknown> | undefined;
1099
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1099
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1100
1100
  id: string;
1101
1101
  version: number;
1102
1102
  content: string;
@@ -1152,7 +1152,7 @@ declare const peerbenchRunner: ((params: {
1152
1152
  kind: "llm/mcq.tc";
1153
1153
  schemaVersion: 1;
1154
1154
  metadata?: Record<string, unknown> | undefined;
1155
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1155
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1156
1156
  id: string;
1157
1157
  question: string;
1158
1158
  options: Record<string, string>;
@@ -1238,7 +1238,7 @@ declare const peerbenchRunner: ((params: {
1238
1238
  outputTokensUsed?: number | undefined;
1239
1239
  inputCost?: string | undefined;
1240
1240
  outputCost?: string | undefined;
1241
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1241
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1242
1242
  startedAt: number;
1243
1243
  completedAt: number;
1244
1244
  id: string;
@@ -1344,7 +1344,7 @@ declare const peerbenchRunner: ((params: {
1344
1344
  scorerAIOutputTokensUsed?: number | undefined;
1345
1345
  scorerAIInputCost?: string | undefined;
1346
1346
  scorerAIOutputCost?: string | undefined;
1347
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1347
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1348
1348
  id: string;
1349
1349
  value: number;
1350
1350
  responseId: string;
@@ -1409,7 +1409,7 @@ declare const peerbenchRunner: ((params: {
1409
1409
  kind: "llm/qa.tc";
1410
1410
  schemaVersion: 1;
1411
1411
  metadata?: Record<string, unknown> | undefined;
1412
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1412
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1413
1413
  id: string;
1414
1414
  question: string;
1415
1415
  goodAnswers: string[];
@@ -1495,7 +1495,7 @@ declare const peerbenchRunner: ((params: {
1495
1495
  outputTokensUsed?: number | undefined;
1496
1496
  inputCost?: string | undefined;
1497
1497
  outputCost?: string | undefined;
1498
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1498
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1499
1499
  startedAt: number;
1500
1500
  completedAt: number;
1501
1501
  id: string;
@@ -1597,7 +1597,7 @@ declare const peerbenchRunner: ((params: {
1597
1597
  scorerAIOutputTokensUsed?: number | undefined;
1598
1598
  scorerAIInputCost?: string | undefined;
1599
1599
  scorerAIOutputCost?: string | undefined;
1600
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1600
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
1601
1601
  id: string;
1602
1602
  value: number;
1603
1603
  responseId: string;
@@ -1,12 +1,25 @@
1
1
  import {
2
2
  SimpleSystemPromptSchemaV1
3
- } from "../chunk-Q6GSOHOP.js";
3
+ } from "../chunk-ZXTQJFGL.js";
4
4
  import {
5
5
  defineRunner
6
6
  } from "../chunk-RTEAK4II.js";
7
+ import {
8
+ LLMAsAJudgeScorer,
9
+ MCQScorer
10
+ } from "../chunk-3JHDJEY3.js";
7
11
  import {
8
12
  AbstractLLMProvider
9
- } from "../chunk-3JF7SHLC.js";
13
+ } from "../chunk-SMLNDQFX.js";
14
+ import {
15
+ PEERBENCH_NAMESPACE
16
+ } from "../chunk-UHHHSYVE.js";
17
+ import {
18
+ JSONFileStorage
19
+ } from "../chunk-JFLUJLGT.js";
20
+ import {
21
+ idGeneratorUUIDv7
22
+ } from "../chunk-4UBK6452.js";
10
23
  import {
11
24
  BaseResponseSchemaV1,
12
25
  BaseScoreSchemaV1,
@@ -19,19 +32,6 @@ import "../chunk-OQE6TQXZ.js";
19
32
  import {
20
33
  ScoringMethod
21
34
  } from "../chunk-HMQYGCKI.js";
22
- import {
23
- LLMAsAJudgeScorer,
24
- MCQScorer
25
- } from "../chunk-DNGT4SJC.js";
26
- import {
27
- PEERBENCH_NAMESPACE
28
- } from "../chunk-UHHHSYVE.js";
29
- import {
30
- JSONFileStorage
31
- } from "../chunk-JFLUJLGT.js";
32
- import {
33
- idGeneratorUUIDv7
34
- } from "../chunk-4UBK6452.js";
35
35
  import {
36
36
  ExtensionLLMAsAJudgeScoreFieldsV1,
37
37
  ExtensionLLMResponseFieldsV1
@@ -7,11 +7,22 @@ import {
7
7
 
8
8
  // src/scorers/abstract.ts
9
9
  var AbstractScorer = class {
10
+ kind;
11
+ constructor() {
12
+ this.kind = this.constructor.kind;
13
+ if (!this.kind) throw new Error(`${this.constructor.name} must define "static readonly kind" as a constant property.`);
14
+ }
15
+ static withKind(kind) {
16
+ const base = this;
17
+ const derived = class extends base {
18
+ static kind = kind;
19
+ };
20
+ return derived;
21
+ }
10
22
  };
11
23
 
12
24
  // src/scorers/regex.ts
13
- var RegexScorer = class extends AbstractScorer {
14
- kind = `${PEERBENCH_NAMESPACE}/regex`;
25
+ var RegexScorer = class extends AbstractScorer.withKind(`${PEERBENCH_NAMESPACE}/regex`) {
15
26
  async score(params) {
16
27
  const allGroupNames = /* @__PURE__ */ new Set();
17
28
  for (const pattern of params.patterns) {
@@ -119,8 +130,7 @@ var RegexScorer = class extends AbstractScorer {
119
130
  };
120
131
 
121
132
  // src/scorers/mcq.ts
122
- var MCQScorer = class extends AbstractScorer {
123
- kind = `${PEERBENCH_NAMESPACE}/mcq`;
133
+ var MCQScorer = class extends AbstractScorer.withKind(`${PEERBENCH_NAMESPACE}/mcq`) {
124
134
  regexScorer = new RegexScorer();
125
135
  async score(params) {
126
136
  const { response, choices, correctAnswers } = params;
@@ -251,8 +261,7 @@ function escapeRegex(str) {
251
261
 
252
262
  // src/scorers/llm-judge.ts
253
263
  import z from "zod";
254
- var LLMAsAJudgeScorer = class extends AbstractScorer {
255
- kind = `${PEERBENCH_NAMESPACE}/llm-as-a-judge`;
264
+ var LLMAsAJudgeScorer = class extends AbstractScorer.withKind(`${PEERBENCH_NAMESPACE}/llm-as-a-judge`) {
256
265
  provider;
257
266
  constructor(config) {
258
267
  super();
@@ -362,4 +371,4 @@ export {
362
371
  MCQScorer,
363
372
  LLMAsAJudgeScorer
364
373
  };
365
- //# sourceMappingURL=chunk-DNGT4SJC.js.map
374
+ //# sourceMappingURL=chunk-3JHDJEY3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/scorers/abstract.ts","../src/scorers/regex.ts","../src/scorers/mcq.ts","../src/scorers/llm-judge.ts"],"sourcesContent":["export abstract class AbstractScorer {\n readonly kind: string;\n\n constructor() {\n this.kind = (this.constructor as any).kind;\n if (!this.kind) throw new Error(`${this.constructor.name} must define \"static readonly kind\" as a constant property.`);\n }\n\n abstract score(params: any): Promise<BaseScorerResult | null>;\n\n static withKind<\n TKind extends string,\n TThis extends abstract new (...args: any[]) => AbstractScorer\n >(this: TThis, kind: TKind) {\n const base = this as unknown as new (...args: any[]) => any;\n const derived = class extends base {\n static readonly kind: TKind = kind;\n declare readonly kind: TKind;\n };\n\n return derived as unknown as (new () => InstanceType<TThis> & { readonly kind: TKind }) & {\n readonly kind: TKind;\n };\n }\n}\n\nexport type BaseScorerResult = {\n value: number;\n explanation?: string;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n};\n","import { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport { AbstractScorer, BaseScorerResult } from \"./abstract\";\n\nexport type RegexPattern = {\n /**\n * The regex pattern to match against the response\n */\n regex: RegExp;\n\n /**\n * The index of the capture group to extract (1-based, like match[1])\n * If not provided, defaults to 1 (first capture group)\n */\n captureGroupIndex?: number;\n\n /**\n * Optional function to transform the extracted value before validation\n */\n transform?: (value: string) => string | undefined;\n};\n\nexport type RegexScorerParams = {\n /**\n * The input text to score\n */\n input: string;\n\n /**\n * Array of regex patterns to try (in order, first match wins)\n */\n patterns: RegexPattern[];\n\n /**\n * Expected value(s) to match against. Can be a record of expected values for named groups, or a validation function\n */\n expectedValue:\n | Record<string, string>\n | ((groupName: string, match: string) => boolean);\n\n /**\n * Optional: Which match to use when multiple matches are found\n * Defaults to \"last\" (uses the last match found)\n */\n matchPreference?: \"first\" | \"last\";\n\n /**\n * Optional: If true, allows partial scoring based on how many groups match\n * For example, if 2 groups are expected and only 1 matches, score would be 0.5\n * Defaults to false (all-or-nothing scoring)\n */\n allowPartialScoring?: boolean;\n};\n\n/**\n * Generic Regex scorer. It scores the given input against a set of regex patterns.\n */\nexport class RegexScorer extends AbstractScorer.withKind(`${PEERBENCH_NAMESPACE}/regex`) {\n override async score(params: RegexScorerParams) {\n // Collect all named group names from all patterns\n const allGroupNames = new Set<string>();\n for (const pattern of params.patterns) {\n const regexSource = pattern.regex.source;\n const namedGroupRegex = /\\(\\?<(\\w+)>/g;\n\n while (true) {\n const match = namedGroupRegex.exec(regexSource);\n if (match === null) {\n break;\n }\n\n if (match[1]) {\n allGroupNames.add(match[1]);\n }\n }\n }\n\n // Initialize result object with all group names set to null (aka not found yet)\n const extractedValues: Record<string, string | null> = {};\n for (const groupName of allGroupNames) {\n extractedValues[groupName] = null;\n }\n\n // Try regex patterns in order, stop at first successful match\n const matchPreference = params.matchPreference ?? \"last\";\n for (const pattern of params.patterns) {\n const matches = Array.from(params.input.matchAll(pattern.regex));\n const match = matchPreference === \"first\" ? matches[0] : matches.at(-1);\n\n if (match && match.groups) {\n // Extract all named groups from this match\n let hasExtractedValue = false;\n for (const [groupName, groupValue] of Object.entries(match.groups)) {\n if (groupValue !== undefined) {\n let value = groupValue;\n\n // Apply transformation if provided\n if (pattern.transform) {\n const transformed = pattern.transform(value);\n if (transformed === undefined) {\n continue;\n }\n value = transformed;\n }\n\n extractedValues[groupName] = value;\n hasExtractedValue = true;\n }\n }\n // If we extracted at least one value, stop processing further patterns\n if (hasExtractedValue) {\n break;\n }\n } else if (match) {\n // Fallback to captureGroupIndex if no named groups\n // For unnamed groups, we can't add to extractedValues by name\n // They are only used for scoring if no named groups are found\n const captureGroupIndex = pattern.captureGroupIndex ?? 1;\n const extractedValue = match[captureGroupIndex];\n\n if (extractedValue !== undefined) {\n // Apply transformation if provided\n if (pattern.transform) {\n const transformed = pattern.transform(extractedValue);\n if (transformed === undefined) {\n continue;\n }\n // For unnamed groups, we can't store in extractedValues\n // but we can use it for scoring if no named groups were found\n }\n // If we have an extracted value (even if unnamed), stop processing\n // Note: This is a fallback case, so we break here too\n break;\n }\n }\n }\n\n // Calculate score based on matched value\n const allowPartial = params.allowPartialScoring ?? false;\n let score = 0;\n\n if (typeof params.expectedValue === \"function\") {\n // To get proper type inference, cast it using \"as\"\n const validator = params.expectedValue as typeof params.expectedValue;\n const extractedEntries = Object.entries(extractedValues).filter(\n ([, value]) => value !== null\n );\n\n // If no values were extracted, score is 0\n if (extractedEntries.length === 0) {\n score = 0;\n } else {\n if (allowPartial) {\n // Count how many extracted values pass validation\n const passingCount = extractedEntries.filter(\n ([groupName, extractedValue]) =>\n validator(groupName, extractedValue as string)\n ).length;\n score = passingCount / extractedEntries.length;\n } else {\n // All extracted values must pass validation\n const allMatch = extractedEntries.every(\n ([groupName, extractedValue]) =>\n validator(groupName, extractedValue as string)\n );\n score = allMatch ? 1 : 0;\n }\n }\n } else {\n const expectedEntries = Object.entries(params.expectedValue);\n const totalExpected = expectedEntries.length;\n\n if (allowPartial) {\n // Count how many expected values match their extracted values\n const matchingCount = expectedEntries.filter(([key, expectedValue]) => {\n const extractedValue = extractedValues[key];\n return extractedValue !== null && extractedValue === expectedValue;\n }).length;\n score = totalExpected > 0 ? matchingCount / totalExpected : 0;\n } else {\n // All expected values must match\n const allMatch = expectedEntries.every(([key, expectedValue]) => {\n const extractedValue = extractedValues[key];\n return extractedValue !== null && extractedValue === expectedValue;\n });\n score = allMatch ? 1 : 0;\n }\n }\n\n return {\n value: score,\n extractedAnswers: Object.fromEntries(\n Object.entries(extractedValues).filter(\n (entry): entry is [string, string] => entry[1] !== null\n )\n ),\n } satisfies BaseScorerResult;\n }\n}\n","import { parseResponseAsJSON } from \"@/utils\";\nimport { AbstractScorer, BaseScorerResult } from \"./abstract\";\nimport { RegexScorer, RegexPattern, RegexScorerParams } from \"./regex\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\n\nexport type MCQScorerParams = {\n response: string;\n choices: Record<string, string>;\n correctAnswers: string[];\n};\n\nexport class MCQScorer extends AbstractScorer.withKind(`${PEERBENCH_NAMESPACE}/mcq`) {\n private regexScorer = new RegexScorer();\n\n async score(params: MCQScorerParams): Promise<\n BaseScorerResult & {\n extractedAnswers: string[];\n }\n > {\n const { response, choices, correctAnswers } = params;\n const normalizedCorrectAnswers = correctAnswers.map((ca) =>\n ca.toUpperCase()\n );\n\n // Direct answer comparison\n const normalizedResponse = response.trim().toUpperCase();\n if (normalizedCorrectAnswers.includes(normalizedResponse)) {\n return {\n value: 1,\n extractedAnswers: [normalizedResponse],\n };\n }\n\n // Try to parse the response as JSON (original behavior: returns early if parsed)\n const json = parseResponseAsJSON<{ answer: string }>(response);\n if (json !== undefined && typeof json === \"object\") {\n const extractedAnswer =\n json.answer !== undefined ? getFirstLetter(json.answer) : undefined;\n\n if (extractedAnswer !== undefined) {\n const normalizedExtracted = extractedAnswer.trim().toUpperCase();\n if (normalizedCorrectAnswers.includes(normalizedExtracted)) {\n return {\n value: 1,\n extractedAnswers: [extractedAnswer],\n };\n }\n\n // Response parsed as JSON but does not represent the correct answer\n return {\n value: 0,\n extractedAnswers:\n json.answer === undefined\n ? []\n : [extractedAnswer ?? String(json.answer)],\n };\n }\n }\n\n // Build patterns for all correctAnswers\n const patterns: RegexPattern[] = [];\n for (const answer of Object.values(params.choices)) {\n const answerPatterns = this.buildPatternsForAnswer(answer);\n patterns.push(...answerPatterns);\n }\n\n // Create validation function that handles choices matching\n // New RegexScorer API expects (groupName: string, match: string) => boolean\n const validateAnswer = (groupName: string, extracted: string): boolean => {\n const normalizedExtracted = extracted.trim().toUpperCase();\n\n // Check if extracted value is in correctAnswers\n if (normalizedCorrectAnswers.includes(normalizedExtracted)) {\n return true;\n }\n\n // Check if extracted text matches any choice value, and that choice key is correct\n // Note: When transform uppercases the value, we need to compare case-insensitively\n const answerOption = Object.entries(choices).find(\n ([, value]) =>\n value.trim().toUpperCase() === extracted.trim().toUpperCase()\n );\n\n if (\n answerOption &&\n normalizedCorrectAnswers.includes(answerOption[0].toUpperCase())\n ) {\n return true;\n }\n\n return false;\n };\n\n // Build regex scorer params\n const regexParams: RegexScorerParams = {\n input: response,\n patterns,\n expectedValue: validateAnswer,\n matchPreference: \"last\",\n };\n\n // Call regex scorer\n const result = await this.regexScorer.score(regexParams);\n\n return {\n value: result.value,\n extractedAnswers: Object.entries(result.extractedAnswers).map(\n ([, value]) => value\n ),\n };\n }\n\n private buildPatternsForAnswer(answerText: string): RegexPattern[] {\n const escapedAnswer = escapeRegex(answerText);\n\n return [\n {\n // \"<!NO ANSWER!>\" - This pattern matches but has no capture group, so it won't extract anything\n regex: /<!NO ANSWER!>/g,\n },\n // Specific patterns for the full answer text (checked first)\n {\n // \"Answer is $\\boxed{answer text}$\"\n regex: new RegExp(\n `[Aa]nswer is \\\\$\\\\\\\\boxed\\\\{(?<answer>${escapedAnswer})\\\\}\\\\$`,\n \"g\"\n ),\n transform: (value: string) => value.toUpperCase(),\n },\n {\n // \"Answer is answer text\"\n regex: new RegExp(`[Aa]nswer is\\\\s+(?<answer>${escapedAnswer})`, \"g\"),\n transform: (value: string) => value.toUpperCase(),\n },\n {\n // \"Answer is **answer text**\"\n regex: new RegExp(\n `[Aa]nswer is\\\\s+\\\\**(?<answer>${escapedAnswer})\\\\**`,\n \"g\"\n ),\n transform: (value: string) => value.toUpperCase(),\n },\n // Generic patterns (checked after specific patterns)\n {\n // \"Answer is $\\boxed{A}$.\"\n regex: /[Aa]nswer is \\$\\\\boxed\\{(?<answer>[A-Z])\\}\\$\\.?/g,\n },\n {\n // \"Answer is A\" - match single letter only when it's a complete standalone answer.\n // Pattern matches: \"Answer is\" + whitespace + single letter + end or punctuation\n regex: /[Aa]nswer is\\s+(?<answer>[A-Z])(?=\\s*$|[.,;:!?])/g,\n },\n {\n // \"Answer is **A**\"\n regex: /[Aa]nswer is\\s+\\**(?<answer>[A-Z])\\**/g,\n },\n {\n // \"A: answer text\"\n regex: /(?<answer>[A-Z]):.+/g,\n },\n {\n // \"A) answer text\"\n regex: /(?<answer>[A-Z])\\)\\s*.+/g,\n },\n {\n // \"A)\"\n regex: /(?<answer>[A-Z])\\)/g,\n },\n ];\n }\n}\n\nfunction getFirstLetter(text: string): string | undefined {\n const match = text.match(/[A-Za-z]/);\n return match ? match[0].toUpperCase() : undefined;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { AbstractLLMProvider } from \"@/providers/abstract/llm\";\nimport { parseResponseAsJSON } from \"@/utils\";\nimport { RateLimiter } from \"@/utils/rate-limiter\";\nimport { AbstractScorer, BaseScorerResult } from \"./abstract\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport z from \"zod\";\n\nexport class LLMAsAJudgeScorer extends AbstractScorer.withKind(`${PEERBENCH_NAMESPACE}/llm-as-a-judge`) {\n private provider: AbstractLLMProvider;\n\n constructor(config: {\n provider: AbstractLLMProvider;\n rateLimiter?: RateLimiter;\n }) {\n super();\n this.provider = config.provider;\n }\n\n override async score<T extends z.ZodRawShape>(\n params: LLMAsAJudgeScoreParams & { fieldsToExtract: T }\n ): Promise<ScorerResultWithExtractedFields<T> | null>;\n override async score(\n params: LLMAsAJudgeScoreParams & { fieldsToExtract?: never }\n ): Promise<ScorerResultWithoutExtractedFields | null>;\n override async score<T extends z.ZodRawShape>(\n params: LLMAsAJudgeScoreParams & { fieldsToExtract?: T }\n ): Promise<\n | ScorerResultWithoutExtractedFields\n | ScorerResultWithExtractedFields<T>\n | null\n > {\n const criteria = normalizeWeights(params.criteria);\n const systemPrompt = [];\n const responseSchema = z.object({\n results: z\n .array(\n z.object({\n id: z.string().describe(\"The id of the criterion\"),\n score: z.number().describe(\"The score of the criterion\"),\n explanation: z\n .string()\n .describe(\"The explanation of the criterion\"),\n })\n )\n .describe(\"The results of the evaluation per criterion\"),\n\n explanation: z\n .string()\n .describe(\n `The overall explanation for the score (less than ${params.maxExplanationLength ?? 200} characters)`\n ),\n\n ...(params.fieldsToExtract ?? {}),\n });\n\n if (params.systemPrompt) {\n systemPrompt.push(params.systemPrompt);\n } else {\n systemPrompt.push(\"You are a strict, fair evaluation judge.\");\n systemPrompt.push(\"Only use information from the rubric\");\n }\n\n systemPrompt.push(\n \"For each criterion return an integer score within the provided scale and a very brief justification (less than 2 sentences).\"\n );\n systemPrompt.push(\n [\n `Rubric: ${params.rubric}`,\n `Criteria:`,\n ...criteria.map(\n (criterion) =>\n `- ${criterion.id}: ${criterion.description} (weight: ${criterion.weight}, scale: ${criterion.scale?.min ?? 0}..${criterion.scale?.max ?? 5})`\n ),\n ].join(\"\\n\")\n );\n\n const responseJSONSchema = responseSchema.toJSONSchema();\n systemPrompt.push(\n `Reply back with the following JSON schema (strict):\\n${JSON.stringify(responseJSONSchema, null, 2)}\\n`\n );\n\n const userPrompt = [`Answer: ${params.response}`];\n const providerResponse = await this.provider.forward({\n messages: [\n {\n role: \"system\",\n content: systemPrompt.join(\"\\n\"),\n },\n {\n role: \"user\",\n content: userPrompt.join(\"\\n\"),\n },\n ],\n model: params.model,\n responseFormat: {\n type: \"json_schema\",\n json_schema: {\n name: \"judgeResult\",\n schema: responseJSONSchema,\n },\n },\n });\n\n const parsed = responseSchema.parse(\n parseResponseAsJSON(providerResponse.data)\n );\n\n const { explanation, results, ...extractedFields } = parsed;\n\n return {\n explanation,\n results,\n value: computeOverallScore(results, criteria),\n extractedFields: extractedFields as z.infer<z.ZodObject<T>>,\n\n provider: this.provider.kind,\n inputTokensUsed: providerResponse.inputTokensUsed,\n outputTokensUsed: providerResponse.outputTokensUsed,\n inputCost: providerResponse.inputCost,\n outputCost: providerResponse.outputCost,\n };\n }\n}\n\nexport type LLMAsAJudgeCriterion = {\n id: string;\n description: string;\n weight: number;\n scale?: {\n min: number;\n max: number;\n };\n};\n\nexport type LLMAsAJudgeScoreParams = {\n model: string;\n response: string;\n rubric: string;\n criteria: LLMAsAJudgeCriterion[];\n\n systemPrompt?: string;\n maxExplanationLength?: number;\n};\n\ntype ScorerResultWithoutExtractedFields = BaseScorerResult & {\n results: {\n id: string;\n score: number;\n explanation: string;\n }[];\n\n provider: string;\n inputTokensUsed?: number;\n outputTokensUsed?: number;\n inputCost?: string;\n outputCost?: string;\n};\n\ntype ScorerResultWithExtractedFields<T extends z.ZodRawShape> =\n ScorerResultWithoutExtractedFields & {\n extractedFields: z.infer<z.ZodObject<T>>;\n };\n\nfunction normalizeWeights(\n criteria: LLMAsAJudgeCriterion[]\n): LLMAsAJudgeCriterion[] {\n const sum = criteria.reduce((a, c) => a + (c.weight ?? 1), 0) || 1;\n return criteria.map((c) => ({ ...c, weight: (c.weight ?? 1) / sum }));\n}\n\nfunction computeOverallScore(\n results: ScorerResultWithoutExtractedFields[\"results\"],\n criteria: LLMAsAJudgeCriterion[]\n): number {\n let total = 0;\n for (const pc of results) {\n const criterion = criteria.find((c) => c.id === pc.id);\n const min = criterion?.scale?.min ?? 0;\n const max = criterion?.scale?.max ?? 5;\n const weight = criterion?.weight ?? 0;\n\n const score = Number(pc.score);\n if (!Number.isFinite(score)) continue;\n\n const clamped = Math.max(min, Math.min(max, score));\n const normalized01 = max === min ? 0 : (clamped - min) / (max - min);\n total += normalized01 * weight;\n }\n return Math.max(0, Math.min(1, total));\n}\n"],"mappings":"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","names":[]}
@@ -7,6 +7,18 @@ import {
7
7
 
8
8
  // src/providers/abstract/provider.ts
9
9
  var AbstractProvider = class {
10
+ kind;
11
+ constructor() {
12
+ this.kind = this.constructor.kind;
13
+ if (!this.kind) throw new Error(`${this.constructor.name} must define "static readonly kind" as a constant property.`);
14
+ }
15
+ static withKind(kind) {
16
+ const base = this;
17
+ const derived = class extends base {
18
+ static kind = kind;
19
+ };
20
+ return derived;
21
+ }
10
22
  };
11
23
 
12
24
  // src/providers/abstract/llm.ts
@@ -15,8 +27,7 @@ var AbstractLLMProvider = class extends AbstractProvider {
15
27
 
16
28
  // src/providers/mastra.ts
17
29
  import { MastraClient } from "@mastra/client-js";
18
- var MastraProvider = class extends AbstractLLMProvider {
19
- kind = "mastra";
30
+ var MastraProvider = class extends AbstractLLMProvider.withKind(`${PEERBENCH_NAMESPACE}/llm/mastra`) {
20
31
  endpoint;
21
32
  authToken;
22
33
  client;
@@ -65,8 +76,7 @@ var MastraProvider = class extends AbstractLLMProvider {
65
76
 
66
77
  // src/providers/openai.ts
67
78
  import OpenAI, { APIError } from "openai";
68
- var OpenAIProvider = class extends AbstractLLMProvider {
69
- kind = `${PEERBENCH_NAMESPACE}/llm/openai`;
79
+ var OpenAIProvider = class extends AbstractLLMProvider.withKind(`${PEERBENCH_NAMESPACE}/llm/openai`) {
70
80
  client;
71
81
  rateLimiter;
72
82
  maxRetries;
@@ -152,8 +162,7 @@ import Decimal from "decimal.js";
152
162
  import axios from "axios";
153
163
  var baseURL = "https://openrouter.ai/api/v1";
154
164
  var MODELS_CACHE_TTL = 1e3 * 60 * 60 * 24;
155
- var OpenRouterProvider = class extends AbstractLLMProvider {
156
- kind = `${PEERBENCH_NAMESPACE}/llm/openrouter.ai`;
165
+ var OpenRouterProvider = class extends AbstractLLMProvider.withKind(`${PEERBENCH_NAMESPACE}/llm/openrouter.ai`) {
157
166
  models = void 0;
158
167
  modelsCachePromise = Promise.resolve(void 0);
159
168
  modelsUpdatedAt = 0;
@@ -232,4 +241,4 @@ export {
232
241
  OpenAIProvider,
233
242
  OpenRouterProvider
234
243
  };
235
- //# sourceMappingURL=chunk-3JF7SHLC.js.map
244
+ //# sourceMappingURL=chunk-SMLNDQFX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/abstract/provider.ts","../src/providers/abstract/llm.ts","../src/providers/mastra.ts","../src/providers/openai.ts","../src/providers/openrouter.ts"],"sourcesContent":["export abstract class AbstractProvider {\n readonly kind: string;\n\n constructor() {\n this.kind = (this.constructor as any).kind;\n if (!this.kind) throw new Error(`${this.constructor.name} must define \"static readonly kind\" as a constant property.`);\n }\n static withKind<\n TKind extends string,\n TThis extends abstract new (...args: any[]) => AbstractProvider\n >(this: TThis, kind: TKind) {\n const base = this as unknown as new (...args: any[]) => any;\n const derived = class extends base {\n static readonly kind: TKind = kind;\n declare readonly kind: TKind;\n };\n\n return derived as unknown as (new () => InstanceType<TThis> & { readonly kind: TKind }) & {\n readonly kind: TKind;\n };\n }\n}\n\nexport type ProviderResponse<TData = unknown> = {\n startedAt: number;\n completedAt: number;\n data: TData;\n};\n","import { AbstractProvider, ProviderResponse } from \"./provider\";\nimport {\n ResponseFormatJSONObject,\n ResponseFormatJSONSchema,\n ResponseFormatText,\n} from \"openai/resources/shared\";\nimport { ChatCompletionMessageParam } from \"openai/resources/chat/completions\";\n\nexport abstract class AbstractLLMProvider extends AbstractProvider {\n abstract forward(args: LLMProviderForwardArgs): Promise<ChatResponse>;\n}\n\nexport type LLMProviderForwardArgs = {\n messages: ChatCompletionMessageParam[];\n model: string;\n abortSignal?: AbortSignal;\n temperature?: number;\n responseFormat?:\n | ResponseFormatText\n | ResponseFormatJSONSchema\n | ResponseFormatJSONObject;\n};\n\nexport type ChatResponse = ProviderResponse<string> & {\n inputTokensUsed?: number;\n outputTokensUsed?: number;\n inputCost?: string;\n outputCost?: string;\n\n metadata?: Record<string, unknown>;\n};\n","import { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport {\n AbstractLLMProvider,\n type ChatResponse,\n type LLMProviderForwardArgs,\n} from \"./abstract/llm\";\nimport { MastraClient, type GetAgentResponse } from \"@mastra/client-js\";\n\nexport class MastraProvider extends AbstractLLMProvider.withKind(`${PEERBENCH_NAMESPACE}/llm/mastra`) {\n\n private readonly endpoint: string;\n private readonly authToken?: string;\n private client: MastraClient;\n private memory?: AgentMemoryOption;\n\n constructor(params: {\n endpoint: string;\n authToken?: string;\n memory?: AgentMemoryOption;\n }) {\n super();\n this.endpoint = params.endpoint;\n this.authToken = params.authToken;\n this.client = new MastraClient({\n baseUrl: this.endpoint,\n headers: this.authToken\n ? {\n Authorization: `Bearer ${this.authToken}`,\n }\n : undefined,\n });\n this.memory = params.memory;\n }\n\n override async forward(\n args: LLMProviderForwardArgs & {\n memory?: AgentMemoryOption;\n\n /**\n * The model that will be used as the brain for the agent.\n */\n modelName?: string\n }\n ): Promise<ChatResponse> {\n const apiMessages = args.messages\n .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .map((m) => ({\n role: m.role as \"user\" | \"assistant\",\n content: String((m as any).content ?? \"\"),\n }));\n\n const agent = this.client.getAgent(args.model);\n\n const startedAt = Date.now();\n const response = await agent.generate(\n {\n messages: apiMessages,\n runtimeContext: {\n \"model-id\": args.modelName,\n },\n },\n { memory: args.memory ?? this.memory }\n );\n\n return {\n data: response.text,\n startedAt,\n completedAt: Date.now(),\n };\n }\n\n async getAgentInfo(args: {\n agentId: string;\n runtimeContext?: MastraRuntimeContext;\n }) {\n return await this.client\n .getAgent(args.agentId)\n .details(args.runtimeContext);\n }\n\n async getAgents(args?: {\n runtimeContext?: MastraRuntimeContext;\n partial?: boolean;\n }): Promise<Record<string, GetAgentResponse>> {\n return this.client.getAgents(args?.runtimeContext, args?.partial);\n }\n}\n\n// NOTE: Mastra client does not export these types\nexport type AgentMemoryOption = Parameters<\n Parameters<MastraClient[\"getAgent\"]>[\"0\"] extends string\n ? ReturnType<MastraClient[\"getAgent\"]>[\"generate\"]\n : never\n>[0] extends { memory?: infer M }\n ? M\n : never;\n\ntype MastraRuntimeContext = Parameters<\n Parameters<MastraClient[\"getAgent\"]>[\"0\"] extends string\n ? ReturnType<MastraClient[\"getAgent\"]>[\"generate\"]\n : never\n>[0] extends { runtimeContext?: infer R }\n ? R\n : never;\n","import { RateLimiter } from \"@/utils\";\nimport { ChatCompletionMessageParam } from \"openai/resources/chat/completions\";\nimport {\n ResponseFormatJSONObject,\n ResponseFormatJSONSchema,\n ResponseFormatText,\n} from \"openai/resources/shared\";\nimport OpenAI, { APIError } from \"openai\";\nimport { AbstractLLMProvider, ChatResponse } from \"./abstract/llm\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\n\nexport class OpenAIProvider extends AbstractLLMProvider.withKind(`${PEERBENCH_NAMESPACE}/llm/openai`) {\n private client: OpenAI;\n private rateLimiter: RateLimiter;\n private maxRetries: number;\n\n constructor(config: {\n apiKey: string;\n baseURL: string;\n maxRetries?: number;\n timeout?: number;\n rateLimiter?: RateLimiter;\n }) {\n super();\n this.maxRetries = config.maxRetries ?? 3;\n this.rateLimiter =\n config.rateLimiter ??\n new RateLimiter({\n maxWeight: 20,\n timeWindow: 3_000,\n });\n\n this.client = new OpenAI({\n baseURL: config.baseURL,\n apiKey: config.apiKey,\n timeout: config.timeout,\n dangerouslyAllowBrowser: true,\n });\n }\n\n async forward(args: {\n messages: ChatCompletionMessageParam[];\n model: string;\n abortSignal?: AbortSignal;\n temperature?: number;\n responseFormat?:\n | ResponseFormatText\n | ResponseFormatJSONSchema\n | ResponseFormatJSONObject;\n }): Promise<ChatResponse> {\n let retryCount = this.maxRetries;\n while (retryCount > 0) {\n let startedAt: Date = new Date();\n\n try {\n const response = await this.rateLimiter.execute(\n async () => {\n // Capture the start time of the request\n startedAt = new Date();\n return await this.client.chat.completions.create(\n {\n model: args.model,\n messages: args.messages,\n temperature: args.temperature,\n response_format: args.responseFormat,\n },\n // Signal for request\n { signal: args.abortSignal }\n );\n },\n // Signal for rate limiting\n { signal: args.abortSignal }\n );\n\n if (\"error\" in response) {\n const err = response.error as any;\n throw new Error(\n `${err.message} - Code ${err.code} - ${JSON.stringify(err)}`\n );\n }\n\n if (!response?.choices?.[0]?.message?.content) {\n throw new Error(\"No content returned from the model\");\n }\n\n return {\n data: response.choices[0].message.content,\n\n inputTokensUsed: response?.usage?.prompt_tokens,\n outputTokensUsed: response?.usage?.completion_tokens,\n\n startedAt: startedAt.getTime(),\n completedAt: Date.now(),\n };\n } catch (err) {\n if (err instanceof APIError && err.status === 401) {\n throw new Error(`Invalid credentials provided`, { cause: err });\n }\n\n retryCount--;\n\n // More likely an empty HTTP response returned by the Provider\n // and it couldn't be parsed as JSON by the OpenAI SDK. We need to retry the request\n // More info can be found in the following links:\n // https://www.reddit.com/r/SillyTavernAI/comments/1ik95vr/deepseek_r1_on_openrouter_returning_blank_messages/\n // https://github.com/cline/cline/issues/60\n if (err instanceof SyntaxError) {\n console.debug(err);\n continue;\n }\n\n // If it was another error, just continue until we run out of retries\n if (retryCount !== 0) {\n continue;\n }\n\n throw new Error(\n `Failed to forward prompt to the model: ${err instanceof Error ? err.message : err}`,\n { cause: err }\n );\n }\n }\n\n throw new Error(\n `Failed to forward prompt to the model: Max retries reached`,\n { cause: new Error(\"Max retries reached\") }\n );\n }\n}\n","import {\n AbstractLLMProvider,\n ChatResponse,\n LLMProviderForwardArgs,\n} from \"./abstract/llm\";\nimport { RateLimiter } from \"@/utils\";\nimport { OpenAIProvider } from \"./openai\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport Decimal from \"decimal.js\";\nimport axios from \"axios\";\n\nconst baseURL = \"https://openrouter.ai/api/v1\";\nconst MODELS_CACHE_TTL = 1000 * 60 * 60 * 24; // 24 hours\n\nexport class OpenRouterProvider extends AbstractLLMProvider.withKind(`${PEERBENCH_NAMESPACE}/llm/openrouter.ai`) {\n private models: ModelsResponse | undefined = undefined;\n private modelsCachePromise: Promise<ModelsResponse | undefined> =\n Promise.resolve(undefined);\n private modelsUpdatedAt = 0;\n private openAIProvider: OpenAIProvider;\n\n constructor(config: {\n apiKey: string;\n maxRetries?: number;\n timeout?: number;\n rateLimiter?: RateLimiter;\n }) {\n super();\n this.openAIProvider = new OpenAIProvider({\n baseURL,\n apiKey: config.apiKey,\n maxRetries: config.maxRetries,\n timeout: config.timeout,\n rateLimiter: config.rateLimiter,\n });\n }\n\n override async forward(args: LLMProviderForwardArgs): Promise<ChatResponse> {\n // Update models cache concurrently (non-blocking)\n const [response] = await Promise.all([\n this.openAIProvider.forward(args),\n this.updateModelsCache().catch(() => {\n // Silently fail if cache update fails so we won't have cost info in the result\n }),\n ]);\n\n // Get the model info from the cache\n const modelInfo = this.models?.data.find((m) => m.id === args.model);\n let inputCost: string | undefined = undefined;\n let outputCost: string | undefined = undefined;\n\n if (modelInfo !== undefined) {\n // Use Decimal.js for more accurate calculation\n if (response.inputTokensUsed !== undefined) {\n inputCost = new Decimal(modelInfo.pricing.prompt)\n .mul(response.inputTokensUsed)\n .toFixed(10);\n }\n if (response.outputTokensUsed !== undefined) {\n outputCost = new Decimal(modelInfo.pricing.completion)\n .mul(response.outputTokensUsed)\n .toFixed(10);\n }\n }\n\n return {\n ...response,\n inputCost,\n outputCost,\n };\n }\n\n /**\n * Updates the cache that holds information about OpenRouter models\n * including pricing information. It will be valid for 24 hours as\n * long as the instance of this Provider object is alive.\n */\n private async updateModelsCache() {\n // Chain each update method call to the promise.\n // This approach prevents race conditions between multiple calls.\n // Since each call is chained to the end of the previous one,\n // each promise makes a request only if the models cache is not updated\n // in the last call. Otherwise it simply resolves to the cached value.\n this.modelsCachePromise = this.modelsCachePromise\n .then(async () => {\n if (\n // The data presented in the cache\n this.models !== undefined &&\n // The cache is still valid\n Date.now() - this.modelsUpdatedAt < MODELS_CACHE_TTL\n ) {\n return this.models;\n }\n\n // If the cache is not valid, update it\n return axios\n .get<ModelsResponse>(`${baseURL}/models`)\n .then((res) => res.data)\n .then((data) => {\n // Only get the models that supports text input and output\n data = {\n data: data.data.filter(\n (m) =>\n m.architecture.input_modalities.includes(\"text\") &&\n m.architecture.output_modalities.includes(\"text\") &&\n // These models are \"fast apply model\" and don't support multi turn conversations so don't include them\n ![\n \"morph/morph-v3-large\",\n \"morph/morph-v3-fast\",\n \"relace/relace-apply-3\",\n ].includes(m.id)\n ),\n };\n\n this.models = data;\n this.modelsUpdatedAt = Date.now();\n\n return data;\n });\n })\n .catch(() => undefined);\n\n // Wait for the promise chain to resolve\n await this.modelsCachePromise;\n }\n}\n\ntype PutModality = \"text\" | \"image\" | \"file\" | \"audio\";\ntype Modality = \"text->text\" | \"text+image->text\" | \"text+image->text+image\";\ntype ModelsResponse = {\n data: {\n readonly id: string;\n readonly canonical_slug: string;\n readonly hugging_face_id: null | string;\n readonly name: string;\n readonly created: number;\n readonly description: string;\n readonly context_length: number;\n readonly architecture: {\n readonly modality: Modality;\n readonly input_modalities: PutModality[];\n readonly output_modalities: PutModality[];\n readonly instruct_type: null | string;\n };\n readonly pricing: {\n readonly prompt: string;\n readonly completion: string;\n readonly request?: string;\n readonly image?: string;\n readonly web_search?: string;\n readonly internal_reasoning?: string;\n readonly input_cache_read?: string;\n readonly input_cache_write?: string;\n readonly audio?: string;\n };\n }[];\n};\n"],"mappings":"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","names":[]}
@@ -1,10 +1,10 @@
1
- import {
2
- buildSchemaDefiner
3
- } from "./chunk-OQE6TQXZ.js";
4
1
  import {
5
2
  CATEGORIES,
6
3
  PEERBENCH_NAMESPACE
7
4
  } from "./chunk-UHHHSYVE.js";
5
+ import {
6
+ buildSchemaDefiner
7
+ } from "./chunk-OQE6TQXZ.js";
8
8
  import {
9
9
  IdSchema
10
10
  } from "./chunk-NUEOE3K5.js";
@@ -41,4 +41,4 @@ export {
41
41
  defineSystemPromptSchema,
42
42
  SimpleSystemPromptSchemaV1
43
43
  };
44
- //# sourceMappingURL=chunk-Q6GSOHOP.js.map
44
+ //# sourceMappingURL=chunk-ZXTQJFGL.js.map
@@ -1,6 +1,6 @@
1
- import { A as AbstractProvider } from './provider-BDjGp2y-.js';
1
+ import { A as AbstractProvider } from './provider-DnEBdl1n.js';
2
2
  import z__default, { z } from 'zod';
3
- import { A as AbstractScorer } from './abstract-Dec9Sc5O.js';
3
+ import { A as AbstractScorer } from './abstract-BdgLjkNC.js';
4
4
 
5
5
  declare const IdSchema: z__default.ZodString;
6
6
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { I as IdGenerator, P as ProviderCtor, S as ScorerCtor } from './index-BAioQhp2.js';
2
- export { A as AbstractClassConstructor, C as ClassConstructor, b as Id, a as InferExtension, M as MaybePromise, c as ScoringMethod, W as WidenZodObject } from './index-BAioQhp2.js';
1
+ import { I as IdGenerator, P as ProviderCtor, S as ScorerCtor } from './index-Cn20kPrz.js';
2
+ export { A as AbstractClassConstructor, C as ClassConstructor, b as Id, a as InferExtension, M as MaybePromise, c as ScoringMethod, W as WidenZodObject } from './index-Cn20kPrz.js';
3
3
  export { R as RateLimiter, b as RateLimiterCallOptions, a as RateLimiterOptions } from './rate-limiter-CSmVIRsM.js';
4
4
  import z__default from 'zod';
5
- import { A as AbstractProvider } from './provider-BDjGp2y-.js';
6
- import { A as AbstractScorer } from './abstract-Dec9Sc5O.js';
5
+ import { A as AbstractProvider } from './provider-DnEBdl1n.js';
6
+ import { A as AbstractScorer } from './abstract-BdgLjkNC.js';
7
7
 
8
8
  declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
9
9
 
package/dist/index.js CHANGED
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  defineRunner
3
3
  } from "./chunk-RTEAK4II.js";
4
- import {
5
- ScoringMethod
6
- } from "./chunk-HMQYGCKI.js";
7
4
  import {
8
5
  CATEGORIES,
9
6
  PEERBENCH_NAMESPACE
@@ -16,6 +13,9 @@ import {
16
13
  sleep,
17
14
  stringToBuffer
18
15
  } from "./chunk-4UBK6452.js";
16
+ import {
17
+ ScoringMethod
18
+ } from "./chunk-HMQYGCKI.js";
19
19
  import "./chunk-PZ5AY32C.js";
20
20
 
21
21
  // src/errors/polyfill.ts
@@ -1,4 +1,4 @@
1
- import { A as AbstractProvider, P as ProviderResponse } from './provider-BDjGp2y-.js';
1
+ import { A as AbstractProvider, P as ProviderResponse } from './provider-DnEBdl1n.js';
2
2
  import { ResponseFormatText, ResponseFormatJSONSchema, ResponseFormatJSONObject } from 'openai/resources/shared';
3
3
  import { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
4
4
 
@@ -1,5 +1,5 @@
1
- import { A as AbstractScorer, B as BaseScorerResult } from './abstract-Dec9Sc5O.js';
2
- import { A as AbstractLLMProvider } from './llm-BND163ns.js';
1
+ import { A as AbstractScorer, B as BaseScorerResult } from './abstract-BdgLjkNC.js';
2
+ import { A as AbstractLLMProvider } from './llm-8ecJmwKJ.js';
3
3
  import { R as RateLimiter } from './rate-limiter-CSmVIRsM.js';
4
4
  import z__default from 'zod';
5
5
 
@@ -8,8 +8,12 @@ type MCQScorerParams = {
8
8
  choices: Record<string, string>;
9
9
  correctAnswers: string[];
10
10
  };
11
- declare class MCQScorer extends AbstractScorer {
11
+ declare const MCQScorer_base: (new () => AbstractScorer & {
12
12
  readonly kind: "peerbench.ai/mcq";
13
+ }) & {
14
+ readonly kind: "peerbench.ai/mcq";
15
+ };
16
+ declare class MCQScorer extends MCQScorer_base {
13
17
  private regexScorer;
14
18
  score(params: MCQScorerParams): Promise<BaseScorerResult & {
15
19
  extractedAnswers: string[];
@@ -17,8 +21,12 @@ declare class MCQScorer extends AbstractScorer {
17
21
  private buildPatternsForAnswer;
18
22
  }
19
23
 
20
- declare class LLMAsAJudgeScorer extends AbstractScorer {
24
+ declare const LLMAsAJudgeScorer_base: (new () => AbstractScorer & {
21
25
  readonly kind: "peerbench.ai/llm-as-a-judge";
26
+ }) & {
27
+ readonly kind: "peerbench.ai/llm-as-a-judge";
28
+ };
29
+ declare class LLMAsAJudgeScorer extends LLMAsAJudgeScorer_base {
22
30
  private provider;
23
31
  constructor(config: {
24
32
  provider: AbstractLLMProvider;
@@ -0,0 +1,16 @@
1
+ declare abstract class AbstractProvider {
2
+ readonly kind: string;
3
+ constructor();
4
+ static withKind<TKind extends string, TThis extends abstract new (...args: any[]) => AbstractProvider>(this: TThis, kind: TKind): (new () => InstanceType<TThis> & {
5
+ readonly kind: TKind;
6
+ }) & {
7
+ readonly kind: TKind;
8
+ };
9
+ }
10
+ type ProviderResponse<TData = unknown> = {
11
+ startedAt: number;
12
+ completedAt: number;
13
+ data: TData;
14
+ };
15
+
16
+ export { AbstractProvider as A, type ProviderResponse as P };
@@ -1,12 +1,16 @@
1
- import { A as AbstractLLMProvider, L as LLMProviderForwardArgs, C as ChatResponse } from '../llm-BND163ns.js';
2
- export { A as AbstractProvider, P as ProviderResponse } from '../provider-BDjGp2y-.js';
1
+ import { A as AbstractLLMProvider, L as LLMProviderForwardArgs, C as ChatResponse } from '../llm-8ecJmwKJ.js';
2
+ export { A as AbstractProvider, P as ProviderResponse } from '../provider-DnEBdl1n.js';
3
3
  import { MastraClient, GetAgentResponse } from '@mastra/client-js';
4
4
  import { R as RateLimiter } from '../rate-limiter-CSmVIRsM.js';
5
5
  import { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
6
6
  import { ResponseFormatText, ResponseFormatJSONSchema, ResponseFormatJSONObject } from 'openai/resources/shared';
7
7
 
8
- declare class MastraProvider extends AbstractLLMProvider {
9
- readonly kind = "mastra";
8
+ declare const MastraProvider_base: (new () => AbstractLLMProvider & {
9
+ readonly kind: "peerbench.ai/llm/mastra";
10
+ }) & {
11
+ readonly kind: "peerbench.ai/llm/mastra";
12
+ };
13
+ declare class MastraProvider extends MastraProvider_base {
10
14
  private readonly endpoint;
11
15
  private readonly authToken?;
12
16
  private client;
@@ -39,8 +43,12 @@ type MastraRuntimeContext = Parameters<Parameters<MastraClient["getAgent"]>["0"]
39
43
  runtimeContext?: infer R;
40
44
  } ? R : never;
41
45
 
42
- declare class OpenAIProvider extends AbstractLLMProvider {
46
+ declare const OpenAIProvider_base: (new () => AbstractLLMProvider & {
43
47
  readonly kind: "peerbench.ai/llm/openai";
48
+ }) & {
49
+ readonly kind: "peerbench.ai/llm/openai";
50
+ };
51
+ declare class OpenAIProvider extends OpenAIProvider_base {
44
52
  private client;
45
53
  private rateLimiter;
46
54
  private maxRetries;
@@ -60,8 +68,12 @@ declare class OpenAIProvider extends AbstractLLMProvider {
60
68
  }): Promise<ChatResponse>;
61
69
  }
62
70
 
63
- declare class OpenRouterProvider extends AbstractLLMProvider {
71
+ declare const OpenRouterProvider_base: (new () => AbstractLLMProvider & {
72
+ readonly kind: "peerbench.ai/llm/openrouter.ai";
73
+ }) & {
64
74
  readonly kind: "peerbench.ai/llm/openrouter.ai";
75
+ };
76
+ declare class OpenRouterProvider extends OpenRouterProvider_base {
65
77
  private models;
66
78
  private modelsCachePromise;
67
79
  private modelsUpdatedAt;
@@ -4,7 +4,7 @@ import {
4
4
  MastraProvider,
5
5
  OpenAIProvider,
6
6
  OpenRouterProvider
7
- } from "../chunk-3JF7SHLC.js";
7
+ } from "../chunk-SMLNDQFX.js";
8
8
  import "../chunk-UHHHSYVE.js";
9
9
  import "../chunk-4UBK6452.js";
10
10
  import "../chunk-PZ5AY32C.js";
@@ -1,8 +1,8 @@
1
- import { W as WidenZodObject, I as IdGenerator } from '../index-BAioQhp2.js';
2
- export { d as IdSchema } from '../index-BAioQhp2.js';
1
+ import { W as WidenZodObject, I as IdGenerator } from '../index-Cn20kPrz.js';
2
+ export { d as IdSchema } from '../index-Cn20kPrz.js';
3
3
  import z__default, { z } from 'zod';
4
- import '../provider-BDjGp2y-.js';
5
- import '../abstract-Dec9Sc5O.js';
4
+ import '../provider-DnEBdl1n.js';
5
+ import '../abstract-BdgLjkNC.js';
6
6
 
7
7
  declare const BaseResponseSchemaV1: z__default.ZodObject<{
8
8
  id: z__default.ZodString;
@@ -58,7 +58,7 @@ declare const defineResponseSchema: <TBaseSchema extends WidenZodObject<z__defau
58
58
  namespace: TNamespace extends undefined ? U["namespace"] : z__default.ZodLiteral<TNamespace>;
59
59
  kind: TKind extends undefined ? U["kind"] : z__default.ZodLiteral<`${TKind}.rs`>;
60
60
  schemaVersion: TSchemaVersion extends undefined ? U["schemaVersion"] : z__default.ZodLiteral<TSchemaVersion>;
61
- }, z__default.core.$strip> : never>, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z__default.core.output<TBaseSchema extends z__default.ZodObject<infer U extends Readonly<{
61
+ }, z__default.core.$strip> : never>, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z__default.core.output<TBaseSchema extends z__default.ZodObject<infer U extends Readonly<{
62
62
  [k: string]: z__default.core.$ZodType<unknown, unknown, z__default.core.$ZodTypeInternals<unknown, unknown>>;
63
63
  }>, z__default.core.$strip> ? z__default.ZodObject<Omit<U, "kind" | "namespace" | "schemaVersion"> & TFields & {
64
64
  namespace: TNamespace extends undefined ? U["namespace"] : z__default.ZodLiteral<TNamespace>;
@@ -115,7 +115,7 @@ declare const defineTestCaseSchema: <TBaseSchema extends WidenZodObject<z.ZodObj
115
115
  namespace: TNamespace extends undefined ? U["namespace"] : z.ZodLiteral<TNamespace>;
116
116
  kind: TKind extends undefined ? U["kind"] : z.ZodLiteral<`${TKind}.tc`>;
117
117
  schemaVersion: TSchemaVersion extends undefined ? U["schemaVersion"] : z.ZodLiteral<TSchemaVersion>;
118
- }, z.core.$strip> : never>, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z.core.output<TBaseSchema extends z.ZodObject<infer U extends Readonly<{
118
+ }, z.core.$strip> : never>, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z.core.output<TBaseSchema extends z.ZodObject<infer U extends Readonly<{
119
119
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
120
120
  }>, z.core.$strip> ? z.ZodObject<Omit<U, "kind" | "namespace" | "schemaVersion"> & TFields & {
121
121
  namespace: TNamespace extends undefined ? U["namespace"] : z.ZodLiteral<TNamespace>;
@@ -188,7 +188,7 @@ declare const defineScoreSchema: <TBaseSchema extends WidenZodObject<z__default.
188
188
  namespace: TNamespace extends undefined ? U["namespace"] : z__default.ZodLiteral<TNamespace>;
189
189
  kind: TKind extends undefined ? U["kind"] : z__default.ZodLiteral<`${TKind}.sc`>;
190
190
  schemaVersion: TSchemaVersion extends undefined ? U["schemaVersion"] : z__default.ZodLiteral<TSchemaVersion>;
191
- }, z__default.core.$strip> : never>, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z__default.core.output<TBaseSchema extends z__default.ZodObject<infer U extends Readonly<{
191
+ }, z__default.core.$strip> : never>, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z__default.core.output<TBaseSchema extends z__default.ZodObject<infer U extends Readonly<{
192
192
  [k: string]: z__default.core.$ZodType<unknown, unknown, z__default.core.$ZodTypeInternals<unknown, unknown>>;
193
193
  }>, z__default.core.$strip> ? z__default.ZodObject<Omit<U, "kind" | "namespace" | "schemaVersion"> & TFields & {
194
194
  namespace: TNamespace extends undefined ? U["namespace"] : z__default.ZodLiteral<TNamespace>;
@@ -1,7 +1,7 @@
1
- import { W as WidenZodObject, I as IdGenerator } from '../../index-BAioQhp2.js';
1
+ import { W as WidenZodObject, I as IdGenerator } from '../../index-Cn20kPrz.js';
2
2
  import { z } from 'zod';
3
- import '../../provider-BDjGp2y-.js';
4
- import '../../abstract-Dec9Sc5O.js';
3
+ import '../../provider-DnEBdl1n.js';
4
+ import '../../abstract-BdgLjkNC.js';
5
5
 
6
6
  declare const BaseSystemPromptSchemaV1: z.ZodObject<{
7
7
  id: z.ZodString;
@@ -53,7 +53,7 @@ declare const defineSystemPromptSchema: <TBaseSchema extends WidenZodObject<z.Zo
53
53
  namespace: TNamespace extends undefined ? U["namespace"] : z.ZodLiteral<TNamespace>;
54
54
  kind: TKind extends undefined ? U["kind"] : z.ZodLiteral<`${TKind}.sys-prompt`>;
55
55
  schemaVersion: TSchemaVersion extends undefined ? U["schemaVersion"] : z.ZodLiteral<TSchemaVersion>;
56
- }, z.core.$strip> : never>, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z.core.output<TBaseSchema extends z.ZodObject<infer U extends Readonly<{
56
+ }, z.core.$strip> : never>, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<z.core.output<TBaseSchema extends z.ZodObject<infer U extends Readonly<{
57
57
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
58
58
  }>, z.core.$strip> ? z.ZodObject<Omit<U, "kind" | "namespace" | "schemaVersion"> & TFields & {
59
59
  namespace: TNamespace extends undefined ? U["namespace"] : z.ZodLiteral<TNamespace>;
@@ -101,7 +101,7 @@ declare const SimpleSystemPromptSchemaV1: z.ZodObject<Omit<{
101
101
  kind: `${string}/simple.sys-prompt`;
102
102
  schemaVersion: 1;
103
103
  metadata?: Record<string, unknown> | undefined;
104
- }, "id" | "kind" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
104
+ }, "kind" | "id" | "namespace" | "schemaVersion">, generator: IdGenerator): Promise<{
105
105
  id: string;
106
106
  version: number;
107
107
  content: string;
@@ -2,9 +2,9 @@ import {
2
2
  BaseSystemPromptSchemaV1,
3
3
  SimpleSystemPromptSchemaV1,
4
4
  defineSystemPromptSchema
5
- } from "../../chunk-Q6GSOHOP.js";
6
- import "../../chunk-OQE6TQXZ.js";
5
+ } from "../../chunk-ZXTQJFGL.js";
7
6
  import "../../chunk-UHHHSYVE.js";
7
+ import "../../chunk-OQE6TQXZ.js";
8
8
  import "../../chunk-NUEOE3K5.js";
9
9
  import "../../chunk-PZ5AY32C.js";
10
10
  export {
@@ -1,8 +1,8 @@
1
- import { A as AbstractScorer } from '../abstract-Dec9Sc5O.js';
2
- export { B as BaseScorerResult } from '../abstract-Dec9Sc5O.js';
3
- export { b as LLMAsAJudgeCriterion, c as LLMAsAJudgeScoreParams, L as LLMAsAJudgeScorer, a as MCQScorer, M as MCQScorerParams } from '../llm-judge-BS_oNYUK.js';
4
- import '../llm-BND163ns.js';
5
- import '../provider-BDjGp2y-.js';
1
+ import { A as AbstractScorer } from '../abstract-BdgLjkNC.js';
2
+ export { B as BaseScorerResult } from '../abstract-BdgLjkNC.js';
3
+ export { b as LLMAsAJudgeCriterion, c as LLMAsAJudgeScoreParams, L as LLMAsAJudgeScorer, a as MCQScorer, M as MCQScorerParams } from '../llm-judge-BuF80-5-.js';
4
+ import '../llm-8ecJmwKJ.js';
5
+ import '../provider-DnEBdl1n.js';
6
6
  import 'openai/resources/shared';
7
7
  import 'openai/resources/chat/completions';
8
8
  import '../rate-limiter-CSmVIRsM.js';
@@ -48,11 +48,15 @@ type RegexScorerParams = {
48
48
  */
49
49
  allowPartialScoring?: boolean;
50
50
  };
51
+ declare const RegexScorer_base: (new () => AbstractScorer & {
52
+ readonly kind: "peerbench.ai/regex";
53
+ }) & {
54
+ readonly kind: "peerbench.ai/regex";
55
+ };
51
56
  /**
52
57
  * Generic Regex scorer. It scores the given input against a set of regex patterns.
53
58
  */
54
- declare class RegexScorer extends AbstractScorer {
55
- readonly kind: "peerbench.ai/regex";
59
+ declare class RegexScorer extends RegexScorer_base {
56
60
  score(params: RegexScorerParams): Promise<{
57
61
  value: number;
58
62
  extractedAnswers: {
@@ -3,7 +3,7 @@ import {
3
3
  LLMAsAJudgeScorer,
4
4
  MCQScorer,
5
5
  RegexScorer
6
- } from "../chunk-DNGT4SJC.js";
6
+ } from "../chunk-3JHDJEY3.js";
7
7
  import "../chunk-UHHHSYVE.js";
8
8
  import "../chunk-4UBK6452.js";
9
9
  import "../chunk-PZ5AY32C.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peerbench",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Tooling help work with AI benchmarking data and create trustworthy AI",
5
5
  "keywords": [
6
6
  "ai",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/abstract/provider.ts","../src/providers/abstract/llm.ts","../src/providers/mastra.ts","../src/providers/openai.ts","../src/providers/openrouter.ts"],"sourcesContent":["export abstract class AbstractProvider {\n abstract readonly kind: string;\n}\n\nexport type ProviderResponse<TData = unknown> = {\n startedAt: number;\n completedAt: number;\n data: TData;\n};\n","import { AbstractProvider, ProviderResponse } from \"./provider\";\nimport {\n ResponseFormatJSONObject,\n ResponseFormatJSONSchema,\n ResponseFormatText,\n} from \"openai/resources/shared\";\nimport { ChatCompletionMessageParam } from \"openai/resources/chat/completions\";\n\nexport abstract class AbstractLLMProvider extends AbstractProvider {\n abstract forward(args: LLMProviderForwardArgs): Promise<ChatResponse>;\n}\n\nexport type LLMProviderForwardArgs = {\n messages: ChatCompletionMessageParam[];\n model: string;\n abortSignal?: AbortSignal;\n temperature?: number;\n responseFormat?:\n | ResponseFormatText\n | ResponseFormatJSONSchema\n | ResponseFormatJSONObject;\n};\n\nexport type ChatResponse = ProviderResponse<string> & {\n inputTokensUsed?: number;\n outputTokensUsed?: number;\n inputCost?: string;\n outputCost?: string;\n\n metadata?: Record<string, unknown>;\n};\n","import {\n AbstractLLMProvider,\n type ChatResponse,\n type LLMProviderForwardArgs,\n} from \"./abstract/llm\";\nimport { MastraClient, type GetAgentResponse } from \"@mastra/client-js\";\n\nexport class MastraProvider extends AbstractLLMProvider {\n override readonly kind = \"mastra\";\n\n private readonly endpoint: string;\n private readonly authToken?: string;\n private client: MastraClient;\n private memory?: AgentMemoryOption;\n\n constructor(params: {\n endpoint: string;\n authToken?: string;\n memory?: AgentMemoryOption;\n }) {\n super();\n this.endpoint = params.endpoint;\n this.authToken = params.authToken;\n this.client = new MastraClient({\n baseUrl: this.endpoint,\n headers: this.authToken\n ? {\n Authorization: `Bearer ${this.authToken}`,\n }\n : undefined,\n });\n this.memory = params.memory;\n }\n\n override async forward(\n args: LLMProviderForwardArgs & {\n memory?: AgentMemoryOption;\n\n /**\n * The model that will be used as the brain for the agent.\n */\n modelName?: string\n }\n ): Promise<ChatResponse> {\n const apiMessages = args.messages\n .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .map((m) => ({\n role: m.role as \"user\" | \"assistant\",\n content: String((m as any).content ?? \"\"),\n }));\n\n const agent = this.client.getAgent(args.model);\n\n const startedAt = Date.now();\n const response = await agent.generate(\n {\n messages: apiMessages,\n runtimeContext: {\n \"model-id\": args.modelName,\n },\n },\n { memory: args.memory ?? this.memory }\n );\n\n return {\n data: response.text,\n startedAt,\n completedAt: Date.now(),\n };\n }\n\n async getAgentInfo(args: {\n agentId: string;\n runtimeContext?: MastraRuntimeContext;\n }) {\n return await this.client\n .getAgent(args.agentId)\n .details(args.runtimeContext);\n }\n\n async getAgents(args?: {\n runtimeContext?: MastraRuntimeContext;\n partial?: boolean;\n }): Promise<Record<string, GetAgentResponse>> {\n return this.client.getAgents(args?.runtimeContext, args?.partial);\n }\n}\n\n// NOTE: Mastra client does not export these types\nexport type AgentMemoryOption = Parameters<\n Parameters<MastraClient[\"getAgent\"]>[\"0\"] extends string\n ? ReturnType<MastraClient[\"getAgent\"]>[\"generate\"]\n : never\n>[0] extends { memory?: infer M }\n ? M\n : never;\n\ntype MastraRuntimeContext = Parameters<\n Parameters<MastraClient[\"getAgent\"]>[\"0\"] extends string\n ? ReturnType<MastraClient[\"getAgent\"]>[\"generate\"]\n : never\n>[0] extends { runtimeContext?: infer R }\n ? R\n : never;\n","import { RateLimiter } from \"@/utils\";\nimport { ChatCompletionMessageParam } from \"openai/resources/chat/completions\";\nimport {\n ResponseFormatJSONObject,\n ResponseFormatJSONSchema,\n ResponseFormatText,\n} from \"openai/resources/shared\";\nimport OpenAI, { APIError } from \"openai\";\nimport { AbstractLLMProvider, ChatResponse } from \"./abstract/llm\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\n\nexport class OpenAIProvider extends AbstractLLMProvider {\n override readonly kind = `${PEERBENCH_NAMESPACE}/llm/openai` as const;\n\n private client: OpenAI;\n private rateLimiter: RateLimiter;\n private maxRetries: number;\n\n constructor(config: {\n apiKey: string;\n baseURL: string;\n maxRetries?: number;\n timeout?: number;\n rateLimiter?: RateLimiter;\n }) {\n super();\n this.maxRetries = config.maxRetries ?? 3;\n this.rateLimiter =\n config.rateLimiter ??\n new RateLimiter({\n maxWeight: 20,\n timeWindow: 3_000,\n });\n\n this.client = new OpenAI({\n baseURL: config.baseURL,\n apiKey: config.apiKey,\n timeout: config.timeout,\n dangerouslyAllowBrowser: true,\n });\n }\n\n async forward(args: {\n messages: ChatCompletionMessageParam[];\n model: string;\n abortSignal?: AbortSignal;\n temperature?: number;\n responseFormat?:\n | ResponseFormatText\n | ResponseFormatJSONSchema\n | ResponseFormatJSONObject;\n }): Promise<ChatResponse> {\n let retryCount = this.maxRetries;\n while (retryCount > 0) {\n let startedAt: Date = new Date();\n\n try {\n const response = await this.rateLimiter.execute(\n async () => {\n // Capture the start time of the request\n startedAt = new Date();\n return await this.client.chat.completions.create(\n {\n model: args.model,\n messages: args.messages,\n temperature: args.temperature,\n response_format: args.responseFormat,\n },\n // Signal for request\n { signal: args.abortSignal }\n );\n },\n // Signal for rate limiting\n { signal: args.abortSignal }\n );\n\n if (\"error\" in response) {\n const err = response.error as any;\n throw new Error(\n `${err.message} - Code ${err.code} - ${JSON.stringify(err)}`\n );\n }\n\n if (!response?.choices?.[0]?.message?.content) {\n throw new Error(\"No content returned from the model\");\n }\n\n return {\n data: response.choices[0].message.content,\n\n inputTokensUsed: response?.usage?.prompt_tokens,\n outputTokensUsed: response?.usage?.completion_tokens,\n\n startedAt: startedAt.getTime(),\n completedAt: Date.now(),\n };\n } catch (err) {\n if (err instanceof APIError && err.status === 401) {\n throw new Error(`Invalid credentials provided`, { cause: err });\n }\n\n retryCount--;\n\n // More likely an empty HTTP response returned by the Provider\n // and it couldn't be parsed as JSON by the OpenAI SDK. We need to retry the request\n // More info can be found in the following links:\n // https://www.reddit.com/r/SillyTavernAI/comments/1ik95vr/deepseek_r1_on_openrouter_returning_blank_messages/\n // https://github.com/cline/cline/issues/60\n if (err instanceof SyntaxError) {\n console.debug(err);\n continue;\n }\n\n // If it was another error, just continue until we run out of retries\n if (retryCount !== 0) {\n continue;\n }\n\n throw new Error(\n `Failed to forward prompt to the model: ${err instanceof Error ? err.message : err}`,\n { cause: err }\n );\n }\n }\n\n throw new Error(\n `Failed to forward prompt to the model: Max retries reached`,\n { cause: new Error(\"Max retries reached\") }\n );\n }\n}\n","import {\n AbstractLLMProvider,\n ChatResponse,\n LLMProviderForwardArgs,\n} from \"./abstract/llm\";\nimport { RateLimiter } from \"@/utils\";\nimport { OpenAIProvider } from \"./openai\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport Decimal from \"decimal.js\";\nimport axios from \"axios\";\n\nconst baseURL = \"https://openrouter.ai/api/v1\";\nconst MODELS_CACHE_TTL = 1000 * 60 * 60 * 24; // 24 hours\n\nexport class OpenRouterProvider extends AbstractLLMProvider {\n override readonly kind = `${PEERBENCH_NAMESPACE}/llm/openrouter.ai` as const;\n\n private models: ModelsResponse | undefined = undefined;\n private modelsCachePromise: Promise<ModelsResponse | undefined> =\n Promise.resolve(undefined);\n private modelsUpdatedAt = 0;\n private openAIProvider: OpenAIProvider;\n\n constructor(config: {\n apiKey: string;\n maxRetries?: number;\n timeout?: number;\n rateLimiter?: RateLimiter;\n }) {\n super();\n this.openAIProvider = new OpenAIProvider({\n baseURL,\n apiKey: config.apiKey,\n maxRetries: config.maxRetries,\n timeout: config.timeout,\n rateLimiter: config.rateLimiter,\n });\n }\n\n override async forward(args: LLMProviderForwardArgs): Promise<ChatResponse> {\n // Update models cache concurrently (non-blocking)\n const [response] = await Promise.all([\n this.openAIProvider.forward(args),\n this.updateModelsCache().catch(() => {\n // Silently fail if cache update fails so we won't have cost info in the result\n }),\n ]);\n\n // Get the model info from the cache\n const modelInfo = this.models?.data.find((m) => m.id === args.model);\n let inputCost: string | undefined = undefined;\n let outputCost: string | undefined = undefined;\n\n if (modelInfo !== undefined) {\n // Use Decimal.js for more accurate calculation\n if (response.inputTokensUsed !== undefined) {\n inputCost = new Decimal(modelInfo.pricing.prompt)\n .mul(response.inputTokensUsed)\n .toFixed(10);\n }\n if (response.outputTokensUsed !== undefined) {\n outputCost = new Decimal(modelInfo.pricing.completion)\n .mul(response.outputTokensUsed)\n .toFixed(10);\n }\n }\n\n return {\n ...response,\n inputCost,\n outputCost,\n };\n }\n\n /**\n * Updates the cache that holds information about OpenRouter models\n * including pricing information. It will be valid for 24 hours as\n * long as the instance of this Provider object is alive.\n */\n private async updateModelsCache() {\n // Chain each update method call to the promise.\n // This approach prevents race conditions between multiple calls.\n // Since each call is chained to the end of the previous one,\n // each promise makes a request only if the models cache is not updated\n // in the last call. Otherwise it simply resolves to the cached value.\n this.modelsCachePromise = this.modelsCachePromise\n .then(async () => {\n if (\n // The data presented in the cache\n this.models !== undefined &&\n // The cache is still valid\n Date.now() - this.modelsUpdatedAt < MODELS_CACHE_TTL\n ) {\n return this.models;\n }\n\n // If the cache is not valid, update it\n return axios\n .get<ModelsResponse>(`${baseURL}/models`)\n .then((res) => res.data)\n .then((data) => {\n // Only get the models that supports text input and output\n data = {\n data: data.data.filter(\n (m) =>\n m.architecture.input_modalities.includes(\"text\") &&\n m.architecture.output_modalities.includes(\"text\") &&\n // These models are \"fast apply model\" and don't support multi turn conversations so don't include them\n ![\n \"morph/morph-v3-large\",\n \"morph/morph-v3-fast\",\n \"relace/relace-apply-3\",\n ].includes(m.id)\n ),\n };\n\n this.models = data;\n this.modelsUpdatedAt = Date.now();\n\n return data;\n });\n })\n .catch(() => undefined);\n\n // Wait for the promise chain to resolve\n await this.modelsCachePromise;\n }\n}\n\ntype PutModality = \"text\" | \"image\" | \"file\" | \"audio\";\ntype Modality = \"text->text\" | \"text+image->text\" | \"text+image->text+image\";\ntype ModelsResponse = {\n data: {\n readonly id: string;\n readonly canonical_slug: string;\n readonly hugging_face_id: null | string;\n readonly name: string;\n readonly created: number;\n readonly description: string;\n readonly context_length: number;\n readonly architecture: {\n readonly modality: Modality;\n readonly input_modalities: PutModality[];\n readonly output_modalities: PutModality[];\n readonly instruct_type: null | string;\n };\n readonly pricing: {\n readonly prompt: string;\n readonly completion: string;\n readonly request?: string;\n readonly image?: string;\n readonly web_search?: string;\n readonly internal_reasoning?: string;\n readonly input_cache_read?: string;\n readonly input_cache_write?: string;\n readonly audio?: string;\n };\n }[];\n};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/scorers/abstract.ts","../src/scorers/regex.ts","../src/scorers/mcq.ts","../src/scorers/llm-judge.ts"],"sourcesContent":["export abstract class AbstractScorer {\n abstract readonly kind: string;\n\n abstract score(params: any): Promise<BaseScorerResult | null>;\n}\n\nexport type BaseScorerResult = {\n value: number;\n explanation?: string;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n};\n","import { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport { AbstractScorer, BaseScorerResult } from \"./abstract\";\n\nexport type RegexPattern = {\n /**\n * The regex pattern to match against the response\n */\n regex: RegExp;\n\n /**\n * The index of the capture group to extract (1-based, like match[1])\n * If not provided, defaults to 1 (first capture group)\n */\n captureGroupIndex?: number;\n\n /**\n * Optional function to transform the extracted value before validation\n */\n transform?: (value: string) => string | undefined;\n};\n\nexport type RegexScorerParams = {\n /**\n * The input text to score\n */\n input: string;\n\n /**\n * Array of regex patterns to try (in order, first match wins)\n */\n patterns: RegexPattern[];\n\n /**\n * Expected value(s) to match against. Can be a record of expected values for named groups, or a validation function\n */\n expectedValue:\n | Record<string, string>\n | ((groupName: string, match: string) => boolean);\n\n /**\n * Optional: Which match to use when multiple matches are found\n * Defaults to \"last\" (uses the last match found)\n */\n matchPreference?: \"first\" | \"last\";\n\n /**\n * Optional: If true, allows partial scoring based on how many groups match\n * For example, if 2 groups are expected and only 1 matches, score would be 0.5\n * Defaults to false (all-or-nothing scoring)\n */\n allowPartialScoring?: boolean;\n};\n\n/**\n * Generic Regex scorer. It scores the given input against a set of regex patterns.\n */\nexport class RegexScorer extends AbstractScorer {\n override readonly kind = `${PEERBENCH_NAMESPACE}/regex` as const;\n\n override async score(params: RegexScorerParams) {\n // Collect all named group names from all patterns\n const allGroupNames = new Set<string>();\n for (const pattern of params.patterns) {\n const regexSource = pattern.regex.source;\n const namedGroupRegex = /\\(\\?<(\\w+)>/g;\n\n while (true) {\n const match = namedGroupRegex.exec(regexSource);\n if (match === null) {\n break;\n }\n\n if (match[1]) {\n allGroupNames.add(match[1]);\n }\n }\n }\n\n // Initialize result object with all group names set to null (aka not found yet)\n const extractedValues: Record<string, string | null> = {};\n for (const groupName of allGroupNames) {\n extractedValues[groupName] = null;\n }\n\n // Try regex patterns in order, stop at first successful match\n const matchPreference = params.matchPreference ?? \"last\";\n for (const pattern of params.patterns) {\n const matches = Array.from(params.input.matchAll(pattern.regex));\n const match = matchPreference === \"first\" ? matches[0] : matches.at(-1);\n\n if (match && match.groups) {\n // Extract all named groups from this match\n let hasExtractedValue = false;\n for (const [groupName, groupValue] of Object.entries(match.groups)) {\n if (groupValue !== undefined) {\n let value = groupValue;\n\n // Apply transformation if provided\n if (pattern.transform) {\n const transformed = pattern.transform(value);\n if (transformed === undefined) {\n continue;\n }\n value = transformed;\n }\n\n extractedValues[groupName] = value;\n hasExtractedValue = true;\n }\n }\n // If we extracted at least one value, stop processing further patterns\n if (hasExtractedValue) {\n break;\n }\n } else if (match) {\n // Fallback to captureGroupIndex if no named groups\n // For unnamed groups, we can't add to extractedValues by name\n // They are only used for scoring if no named groups are found\n const captureGroupIndex = pattern.captureGroupIndex ?? 1;\n const extractedValue = match[captureGroupIndex];\n\n if (extractedValue !== undefined) {\n // Apply transformation if provided\n if (pattern.transform) {\n const transformed = pattern.transform(extractedValue);\n if (transformed === undefined) {\n continue;\n }\n // For unnamed groups, we can't store in extractedValues\n // but we can use it for scoring if no named groups were found\n }\n // If we have an extracted value (even if unnamed), stop processing\n // Note: This is a fallback case, so we break here too\n break;\n }\n }\n }\n\n // Calculate score based on matched value\n const allowPartial = params.allowPartialScoring ?? false;\n let score = 0;\n\n if (typeof params.expectedValue === \"function\") {\n // To get proper type inference, cast it using \"as\"\n const validator = params.expectedValue as typeof params.expectedValue;\n const extractedEntries = Object.entries(extractedValues).filter(\n ([, value]) => value !== null\n );\n\n // If no values were extracted, score is 0\n if (extractedEntries.length === 0) {\n score = 0;\n } else {\n if (allowPartial) {\n // Count how many extracted values pass validation\n const passingCount = extractedEntries.filter(\n ([groupName, extractedValue]) =>\n validator(groupName, extractedValue as string)\n ).length;\n score = passingCount / extractedEntries.length;\n } else {\n // All extracted values must pass validation\n const allMatch = extractedEntries.every(\n ([groupName, extractedValue]) =>\n validator(groupName, extractedValue as string)\n );\n score = allMatch ? 1 : 0;\n }\n }\n } else {\n const expectedEntries = Object.entries(params.expectedValue);\n const totalExpected = expectedEntries.length;\n\n if (allowPartial) {\n // Count how many expected values match their extracted values\n const matchingCount = expectedEntries.filter(([key, expectedValue]) => {\n const extractedValue = extractedValues[key];\n return extractedValue !== null && extractedValue === expectedValue;\n }).length;\n score = totalExpected > 0 ? matchingCount / totalExpected : 0;\n } else {\n // All expected values must match\n const allMatch = expectedEntries.every(([key, expectedValue]) => {\n const extractedValue = extractedValues[key];\n return extractedValue !== null && extractedValue === expectedValue;\n });\n score = allMatch ? 1 : 0;\n }\n }\n\n return {\n value: score,\n extractedAnswers: Object.fromEntries(\n Object.entries(extractedValues).filter(\n (entry): entry is [string, string] => entry[1] !== null\n )\n ),\n } satisfies BaseScorerResult;\n }\n}\n","import { parseResponseAsJSON } from \"@/utils\";\nimport { AbstractScorer, BaseScorerResult } from \"./abstract\";\nimport { RegexScorer, RegexPattern, RegexScorerParams } from \"./regex\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\n\nexport type MCQScorerParams = {\n response: string;\n choices: Record<string, string>;\n correctAnswers: string[];\n};\n\nexport class MCQScorer extends AbstractScorer {\n override readonly kind = `${PEERBENCH_NAMESPACE}/mcq` as const;\n private regexScorer = new RegexScorer();\n\n async score(params: MCQScorerParams): Promise<\n BaseScorerResult & {\n extractedAnswers: string[];\n }\n > {\n const { response, choices, correctAnswers } = params;\n const normalizedCorrectAnswers = correctAnswers.map((ca) =>\n ca.toUpperCase()\n );\n\n // Direct answer comparison\n const normalizedResponse = response.trim().toUpperCase();\n if (normalizedCorrectAnswers.includes(normalizedResponse)) {\n return {\n value: 1,\n extractedAnswers: [normalizedResponse],\n };\n }\n\n // Try to parse the response as JSON (original behavior: returns early if parsed)\n const json = parseResponseAsJSON<{ answer: string }>(response);\n if (json !== undefined && typeof json === \"object\") {\n const extractedAnswer =\n json.answer !== undefined ? getFirstLetter(json.answer) : undefined;\n\n if (extractedAnswer !== undefined) {\n const normalizedExtracted = extractedAnswer.trim().toUpperCase();\n if (normalizedCorrectAnswers.includes(normalizedExtracted)) {\n return {\n value: 1,\n extractedAnswers: [extractedAnswer],\n };\n }\n\n // Response parsed as JSON but does not represent the correct answer\n return {\n value: 0,\n extractedAnswers:\n json.answer === undefined\n ? []\n : [extractedAnswer ?? String(json.answer)],\n };\n }\n }\n\n // Build patterns for all correctAnswers\n const patterns: RegexPattern[] = [];\n for (const answer of Object.values(params.choices)) {\n const answerPatterns = this.buildPatternsForAnswer(answer);\n patterns.push(...answerPatterns);\n }\n\n // Create validation function that handles choices matching\n // New RegexScorer API expects (groupName: string, match: string) => boolean\n const validateAnswer = (groupName: string, extracted: string): boolean => {\n const normalizedExtracted = extracted.trim().toUpperCase();\n\n // Check if extracted value is in correctAnswers\n if (normalizedCorrectAnswers.includes(normalizedExtracted)) {\n return true;\n }\n\n // Check if extracted text matches any choice value, and that choice key is correct\n // Note: When transform uppercases the value, we need to compare case-insensitively\n const answerOption = Object.entries(choices).find(\n ([, value]) =>\n value.trim().toUpperCase() === extracted.trim().toUpperCase()\n );\n\n if (\n answerOption &&\n normalizedCorrectAnswers.includes(answerOption[0].toUpperCase())\n ) {\n return true;\n }\n\n return false;\n };\n\n // Build regex scorer params\n const regexParams: RegexScorerParams = {\n input: response,\n patterns,\n expectedValue: validateAnswer,\n matchPreference: \"last\",\n };\n\n // Call regex scorer\n const result = await this.regexScorer.score(regexParams);\n\n return {\n value: result.value,\n extractedAnswers: Object.entries(result.extractedAnswers).map(\n ([, value]) => value\n ),\n };\n }\n\n private buildPatternsForAnswer(answerText: string): RegexPattern[] {\n const escapedAnswer = escapeRegex(answerText);\n\n return [\n {\n // \"<!NO ANSWER!>\" - This pattern matches but has no capture group, so it won't extract anything\n regex: /<!NO ANSWER!>/g,\n },\n // Specific patterns for the full answer text (checked first)\n {\n // \"Answer is $\\boxed{answer text}$\"\n regex: new RegExp(\n `[Aa]nswer is \\\\$\\\\\\\\boxed\\\\{(?<answer>${escapedAnswer})\\\\}\\\\$`,\n \"g\"\n ),\n transform: (value: string) => value.toUpperCase(),\n },\n {\n // \"Answer is answer text\"\n regex: new RegExp(`[Aa]nswer is\\\\s+(?<answer>${escapedAnswer})`, \"g\"),\n transform: (value: string) => value.toUpperCase(),\n },\n {\n // \"Answer is **answer text**\"\n regex: new RegExp(\n `[Aa]nswer is\\\\s+\\\\**(?<answer>${escapedAnswer})\\\\**`,\n \"g\"\n ),\n transform: (value: string) => value.toUpperCase(),\n },\n // Generic patterns (checked after specific patterns)\n {\n // \"Answer is $\\boxed{A}$.\"\n regex: /[Aa]nswer is \\$\\\\boxed\\{(?<answer>[A-Z])\\}\\$\\.?/g,\n },\n {\n // \"Answer is A\" - match single letter only when it's a complete standalone answer.\n // Pattern matches: \"Answer is\" + whitespace + single letter + end or punctuation\n regex: /[Aa]nswer is\\s+(?<answer>[A-Z])(?=\\s*$|[.,;:!?])/g,\n },\n {\n // \"Answer is **A**\"\n regex: /[Aa]nswer is\\s+\\**(?<answer>[A-Z])\\**/g,\n },\n {\n // \"A: answer text\"\n regex: /(?<answer>[A-Z]):.+/g,\n },\n {\n // \"A) answer text\"\n regex: /(?<answer>[A-Z])\\)\\s*.+/g,\n },\n {\n // \"A)\"\n regex: /(?<answer>[A-Z])\\)/g,\n },\n ];\n }\n}\n\nfunction getFirstLetter(text: string): string | undefined {\n const match = text.match(/[A-Za-z]/);\n return match ? match[0].toUpperCase() : undefined;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { AbstractLLMProvider } from \"@/providers/abstract/llm\";\nimport { parseResponseAsJSON } from \"@/utils\";\nimport { RateLimiter } from \"@/utils/rate-limiter\";\nimport { AbstractScorer, BaseScorerResult } from \"./abstract\";\nimport { PEERBENCH_NAMESPACE } from \"@/constants\";\nimport z from \"zod\";\n\nexport class LLMAsAJudgeScorer extends AbstractScorer {\n override readonly kind = `${PEERBENCH_NAMESPACE}/llm-as-a-judge` as const;\n\n private provider: AbstractLLMProvider;\n\n constructor(config: {\n provider: AbstractLLMProvider;\n rateLimiter?: RateLimiter;\n }) {\n super();\n this.provider = config.provider;\n }\n\n override async score<T extends z.ZodRawShape>(\n params: LLMAsAJudgeScoreParams & { fieldsToExtract: T }\n ): Promise<ScorerResultWithExtractedFields<T> | null>;\n override async score(\n params: LLMAsAJudgeScoreParams & { fieldsToExtract?: never }\n ): Promise<ScorerResultWithoutExtractedFields | null>;\n override async score<T extends z.ZodRawShape>(\n params: LLMAsAJudgeScoreParams & { fieldsToExtract?: T }\n ): Promise<\n | ScorerResultWithoutExtractedFields\n | ScorerResultWithExtractedFields<T>\n | null\n > {\n const criteria = normalizeWeights(params.criteria);\n const systemPrompt = [];\n const responseSchema = z.object({\n results: z\n .array(\n z.object({\n id: z.string().describe(\"The id of the criterion\"),\n score: z.number().describe(\"The score of the criterion\"),\n explanation: z\n .string()\n .describe(\"The explanation of the criterion\"),\n })\n )\n .describe(\"The results of the evaluation per criterion\"),\n\n explanation: z\n .string()\n .describe(\n `The overall explanation for the score (less than ${params.maxExplanationLength ?? 200} characters)`\n ),\n\n ...(params.fieldsToExtract ?? {}),\n });\n\n if (params.systemPrompt) {\n systemPrompt.push(params.systemPrompt);\n } else {\n systemPrompt.push(\"You are a strict, fair evaluation judge.\");\n systemPrompt.push(\"Only use information from the rubric\");\n }\n\n systemPrompt.push(\n \"For each criterion return an integer score within the provided scale and a very brief justification (less than 2 sentences).\"\n );\n systemPrompt.push(\n [\n `Rubric: ${params.rubric}`,\n `Criteria:`,\n ...criteria.map(\n (criterion) =>\n `- ${criterion.id}: ${criterion.description} (weight: ${criterion.weight}, scale: ${criterion.scale?.min ?? 0}..${criterion.scale?.max ?? 5})`\n ),\n ].join(\"\\n\")\n );\n\n const responseJSONSchema = responseSchema.toJSONSchema();\n systemPrompt.push(\n `Reply back with the following JSON schema (strict):\\n${JSON.stringify(responseJSONSchema, null, 2)}\\n`\n );\n\n const userPrompt = [`Answer: ${params.response}`];\n const providerResponse = await this.provider.forward({\n messages: [\n {\n role: \"system\",\n content: systemPrompt.join(\"\\n\"),\n },\n {\n role: \"user\",\n content: userPrompt.join(\"\\n\"),\n },\n ],\n model: params.model,\n responseFormat: {\n type: \"json_schema\",\n json_schema: {\n name: \"judgeResult\",\n schema: responseJSONSchema,\n },\n },\n });\n\n const parsed = responseSchema.parse(\n parseResponseAsJSON(providerResponse.data)\n );\n\n const { explanation, results, ...extractedFields } = parsed;\n\n return {\n explanation,\n results,\n value: computeOverallScore(results, criteria),\n extractedFields: extractedFields as z.infer<z.ZodObject<T>>,\n\n provider: this.provider.kind,\n inputTokensUsed: providerResponse.inputTokensUsed,\n outputTokensUsed: providerResponse.outputTokensUsed,\n inputCost: providerResponse.inputCost,\n outputCost: providerResponse.outputCost,\n };\n }\n}\n\nexport type LLMAsAJudgeCriterion = {\n id: string;\n description: string;\n weight: number;\n scale?: {\n min: number;\n max: number;\n };\n};\n\nexport type LLMAsAJudgeScoreParams = {\n model: string;\n response: string;\n rubric: string;\n criteria: LLMAsAJudgeCriterion[];\n\n systemPrompt?: string;\n maxExplanationLength?: number;\n};\n\ntype ScorerResultWithoutExtractedFields = BaseScorerResult & {\n results: {\n id: string;\n score: number;\n explanation: string;\n }[];\n\n provider: string;\n inputTokensUsed?: number;\n outputTokensUsed?: number;\n inputCost?: string;\n outputCost?: string;\n};\n\ntype ScorerResultWithExtractedFields<T extends z.ZodRawShape> =\n ScorerResultWithoutExtractedFields & {\n extractedFields: z.infer<z.ZodObject<T>>;\n };\n\nfunction normalizeWeights(\n criteria: LLMAsAJudgeCriterion[]\n): LLMAsAJudgeCriterion[] {\n const sum = criteria.reduce((a, c) => a + (c.weight ?? 1), 0) || 1;\n return criteria.map((c) => ({ ...c, weight: (c.weight ?? 1) / sum }));\n}\n\nfunction computeOverallScore(\n results: ScorerResultWithoutExtractedFields[\"results\"],\n criteria: LLMAsAJudgeCriterion[]\n): number {\n let total = 0;\n for (const pc of results) {\n const criterion = criteria.find((c) => c.id === pc.id);\n const min = criterion?.scale?.min ?? 0;\n const max = criterion?.scale?.max ?? 5;\n const weight = criterion?.weight ?? 0;\n\n const score = Number(pc.score);\n if (!Number.isFinite(score)) continue;\n\n const clamped = Math.max(min, Math.min(max, score));\n const normalized01 = max === min ? 0 : (clamped - min) / (max - min);\n total += normalized01 * weight;\n }\n return Math.max(0, Math.min(1, total));\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +0,0 @@
1
- declare abstract class AbstractProvider {
2
- abstract readonly kind: string;
3
- }
4
- type ProviderResponse<TData = unknown> = {
5
- startedAt: number;
6
- completedAt: number;
7
- data: TData;
8
- };
9
-
10
- export { AbstractProvider as A, type ProviderResponse as P };