peerbench 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/benchmarks/index.d.ts +17 -17
- package/dist/benchmarks/index.js +6 -6
- package/dist/{chunk-ZEWI24CV.js → chunk-DNGT4SJC.js} +2 -2
- package/dist/{chunk-ZEWI24CV.js.map → chunk-DNGT4SJC.js.map} +1 -1
- package/dist/{chunk-R76XA2K6.js → chunk-HPPCDSJ3.js} +12 -6
- package/dist/chunk-HPPCDSJ3.js.map +1 -0
- package/dist/{chunk-ERALDEZY.js → chunk-JFLUJLGT.js} +4 -1
- package/dist/chunk-JFLUJLGT.js.map +1 -0
- package/dist/{json-file-ZwzLUbje.d.ts → json-file-Bgv9TLcX.d.ts} +1 -0
- package/dist/{llm-DNj_tp2T.d.ts → llm-BND163ns.d.ts} +1 -0
- package/dist/{llm-judge-QThCZ9TQ.d.ts → llm-judge-BS_oNYUK.d.ts} +1 -1
- package/dist/providers/index.d.ts +19 -4
- package/dist/providers/index.js +1 -1
- package/dist/scorers/index.d.ts +2 -2
- package/dist/scorers/index.js +1 -1
- package/dist/storages/index.d.ts +2 -2
- package/dist/storages/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ERALDEZY.js.map +0 -1
- package/dist/chunk-R76XA2K6.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { I as IdGenerator } from '../index-BAioQhp2.js';
|
|
2
2
|
import z__default, { z } from 'zod';
|
|
3
|
-
import { A as AbstractLLMProvider } from '../llm-
|
|
4
|
-
import { a as MCQScorer, L as LLMAsAJudgeScorer } from '../llm-judge-
|
|
5
|
-
import { J as JSONFileStorage } from '../json-file-
|
|
3
|
+
import { A as AbstractLLMProvider } from '../llm-BND163ns.js';
|
|
4
|
+
import { a as MCQScorer, L as LLMAsAJudgeScorer } from '../llm-judge-BS_oNYUK.js';
|
|
5
|
+
import { J as JSONFileStorage } from '../json-file-Bgv9TLcX.js';
|
|
6
6
|
import '../provider-BDjGp2y-.js';
|
|
7
7
|
import '../abstract-Dec9Sc5O.js';
|
|
8
8
|
import 'openai/resources/shared';
|
|
@@ -199,8 +199,8 @@ declare const MCQScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
199
199
|
namespace: "peerbench.ai";
|
|
200
200
|
kind: "llm/mcq.sc";
|
|
201
201
|
schemaVersion: 1;
|
|
202
|
-
explanation?: string | undefined;
|
|
203
202
|
metadata?: Record<string, unknown> | undefined;
|
|
203
|
+
explanation?: string | undefined;
|
|
204
204
|
scorerAISystemPrompt?: string | undefined;
|
|
205
205
|
scorerAISystemPromptId?: string | undefined;
|
|
206
206
|
scorerAIProvider?: string | undefined;
|
|
@@ -218,8 +218,8 @@ declare const MCQScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
218
218
|
namespace: "peerbench.ai";
|
|
219
219
|
kind: "llm/mcq.sc";
|
|
220
220
|
schemaVersion: 1;
|
|
221
|
-
explanation?: string | undefined;
|
|
222
221
|
metadata?: Record<string, unknown> | undefined;
|
|
222
|
+
explanation?: string | undefined;
|
|
223
223
|
scorerAISystemPrompt?: string | undefined;
|
|
224
224
|
scorerAISystemPromptId?: string | undefined;
|
|
225
225
|
scorerAIProvider?: string | undefined;
|
|
@@ -238,8 +238,8 @@ declare const MCQScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
238
238
|
namespace: "peerbench.ai";
|
|
239
239
|
kind: "llm/mcq.sc";
|
|
240
240
|
schemaVersion: 1;
|
|
241
|
-
explanation?: string | undefined;
|
|
242
241
|
metadata?: Record<string, unknown> | undefined;
|
|
242
|
+
explanation?: string | undefined;
|
|
243
243
|
scorerAISystemPrompt?: string | undefined;
|
|
244
244
|
scorerAISystemPromptId?: string | undefined;
|
|
245
245
|
scorerAIProvider?: string | undefined;
|
|
@@ -257,8 +257,8 @@ declare const MCQScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
257
257
|
namespace: "peerbench.ai";
|
|
258
258
|
kind: "llm/mcq.sc";
|
|
259
259
|
schemaVersion: 1;
|
|
260
|
-
explanation?: string | undefined;
|
|
261
260
|
metadata?: Record<string, unknown> | undefined;
|
|
261
|
+
explanation?: string | undefined;
|
|
262
262
|
scorerAISystemPrompt?: string | undefined;
|
|
263
263
|
scorerAISystemPromptId?: string | undefined;
|
|
264
264
|
scorerAIProvider?: string | undefined;
|
|
@@ -541,8 +541,8 @@ declare const MultiTurnScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
541
541
|
namespace: "peerbench.ai";
|
|
542
542
|
kind: "llm/multi-turn.sc";
|
|
543
543
|
schemaVersion: 1;
|
|
544
|
-
explanation?: string | undefined;
|
|
545
544
|
metadata?: Record<string, unknown> | undefined;
|
|
545
|
+
explanation?: string | undefined;
|
|
546
546
|
scorerAISystemPrompt?: string | undefined;
|
|
547
547
|
scorerAISystemPromptId?: string | undefined;
|
|
548
548
|
scorerAIProvider?: string | undefined;
|
|
@@ -563,8 +563,8 @@ declare const MultiTurnScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
563
563
|
namespace: "peerbench.ai";
|
|
564
564
|
kind: "llm/multi-turn.sc";
|
|
565
565
|
schemaVersion: 1;
|
|
566
|
-
explanation?: string | undefined;
|
|
567
566
|
metadata?: Record<string, unknown> | undefined;
|
|
567
|
+
explanation?: string | undefined;
|
|
568
568
|
scorerAISystemPrompt?: string | undefined;
|
|
569
569
|
scorerAISystemPromptId?: string | undefined;
|
|
570
570
|
scorerAIProvider?: string | undefined;
|
|
@@ -586,8 +586,8 @@ declare const MultiTurnScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
586
586
|
namespace: "peerbench.ai";
|
|
587
587
|
kind: "llm/multi-turn.sc";
|
|
588
588
|
schemaVersion: 1;
|
|
589
|
-
explanation?: string | undefined;
|
|
590
589
|
metadata?: Record<string, unknown> | undefined;
|
|
590
|
+
explanation?: string | undefined;
|
|
591
591
|
scorerAISystemPrompt?: string | undefined;
|
|
592
592
|
scorerAISystemPromptId?: string | undefined;
|
|
593
593
|
scorerAIProvider?: string | undefined;
|
|
@@ -608,8 +608,8 @@ declare const MultiTurnScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
608
608
|
namespace: "peerbench.ai";
|
|
609
609
|
kind: "llm/multi-turn.sc";
|
|
610
610
|
schemaVersion: 1;
|
|
611
|
-
explanation?: string | undefined;
|
|
612
611
|
metadata?: Record<string, unknown> | undefined;
|
|
612
|
+
explanation?: string | undefined;
|
|
613
613
|
scorerAISystemPrompt?: string | undefined;
|
|
614
614
|
scorerAISystemPromptId?: string | undefined;
|
|
615
615
|
scorerAIProvider?: string | undefined;
|
|
@@ -809,8 +809,8 @@ declare const QAScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
809
809
|
namespace: "peerbench.ai";
|
|
810
810
|
kind: "llm/qa.sc";
|
|
811
811
|
schemaVersion: 1;
|
|
812
|
-
explanation?: string | undefined;
|
|
813
812
|
metadata?: Record<string, unknown> | undefined;
|
|
813
|
+
explanation?: string | undefined;
|
|
814
814
|
scorerAISystemPrompt?: string | undefined;
|
|
815
815
|
scorerAISystemPromptId?: string | undefined;
|
|
816
816
|
scorerAIProvider?: string | undefined;
|
|
@@ -827,8 +827,8 @@ declare const QAScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
827
827
|
namespace: "peerbench.ai";
|
|
828
828
|
kind: "llm/qa.sc";
|
|
829
829
|
schemaVersion: 1;
|
|
830
|
-
explanation?: string | undefined;
|
|
831
830
|
metadata?: Record<string, unknown> | undefined;
|
|
831
|
+
explanation?: string | undefined;
|
|
832
832
|
scorerAISystemPrompt?: string | undefined;
|
|
833
833
|
scorerAISystemPromptId?: string | undefined;
|
|
834
834
|
scorerAIProvider?: string | undefined;
|
|
@@ -846,8 +846,8 @@ declare const QAScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
846
846
|
namespace: "peerbench.ai";
|
|
847
847
|
kind: "llm/qa.sc";
|
|
848
848
|
schemaVersion: 1;
|
|
849
|
-
explanation?: string | undefined;
|
|
850
849
|
metadata?: Record<string, unknown> | undefined;
|
|
850
|
+
explanation?: string | undefined;
|
|
851
851
|
scorerAISystemPrompt?: string | undefined;
|
|
852
852
|
scorerAISystemPromptId?: string | undefined;
|
|
853
853
|
scorerAIProvider?: string | undefined;
|
|
@@ -864,8 +864,8 @@ declare const QAScoreSchemaV1: z.ZodObject<Omit<{
|
|
|
864
864
|
namespace: "peerbench.ai";
|
|
865
865
|
kind: "llm/qa.sc";
|
|
866
866
|
schemaVersion: 1;
|
|
867
|
-
explanation?: string | undefined;
|
|
868
867
|
metadata?: Record<string, unknown> | undefined;
|
|
868
|
+
explanation?: string | undefined;
|
|
869
869
|
scorerAISystemPrompt?: string | undefined;
|
|
870
870
|
scorerAISystemPromptId?: string | undefined;
|
|
871
871
|
scorerAIProvider?: string | undefined;
|
|
@@ -973,8 +973,8 @@ declare const peerbenchRunner: (params: {
|
|
|
973
973
|
namespace: "peerbench.ai";
|
|
974
974
|
kind: "llm/mcq.sc";
|
|
975
975
|
schemaVersion: 1;
|
|
976
|
-
explanation?: string | undefined;
|
|
977
976
|
metadata?: Record<string, unknown> | undefined;
|
|
977
|
+
explanation?: string | undefined;
|
|
978
978
|
scorerAISystemPrompt?: string | undefined;
|
|
979
979
|
scorerAISystemPromptId?: string | undefined;
|
|
980
980
|
scorerAIProvider?: string | undefined;
|
|
@@ -991,8 +991,8 @@ declare const peerbenchRunner: (params: {
|
|
|
991
991
|
namespace: "peerbench.ai";
|
|
992
992
|
kind: "llm/qa.sc";
|
|
993
993
|
schemaVersion: 1;
|
|
994
|
-
explanation?: string | undefined;
|
|
995
994
|
metadata?: Record<string, unknown> | undefined;
|
|
995
|
+
explanation?: string | undefined;
|
|
996
996
|
scorerAISystemPrompt?: string | undefined;
|
|
997
997
|
scorerAISystemPromptId?: string | undefined;
|
|
998
998
|
scorerAIProvider?: string | undefined;
|
package/dist/benchmarks/index.js
CHANGED
|
@@ -4,6 +4,10 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
defineRunner
|
|
6
6
|
} from "../chunk-QY5MPNNB.js";
|
|
7
|
+
import {
|
|
8
|
+
LLMAsAJudgeScorer,
|
|
9
|
+
MCQScorer
|
|
10
|
+
} from "../chunk-DNGT4SJC.js";
|
|
7
11
|
import {
|
|
8
12
|
BaseResponseSchemaV1,
|
|
9
13
|
BaseScoreSchemaV1,
|
|
@@ -18,14 +22,10 @@ import {
|
|
|
18
22
|
} from "../chunk-HMQYGCKI.js";
|
|
19
23
|
import {
|
|
20
24
|
JSONFileStorage
|
|
21
|
-
} from "../chunk-
|
|
22
|
-
import {
|
|
23
|
-
LLMAsAJudgeScorer,
|
|
24
|
-
MCQScorer
|
|
25
|
-
} from "../chunk-ZEWI24CV.js";
|
|
25
|
+
} from "../chunk-JFLUJLGT.js";
|
|
26
26
|
import {
|
|
27
27
|
AbstractLLMProvider
|
|
28
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-HPPCDSJ3.js";
|
|
29
29
|
import {
|
|
30
30
|
PEERBENCH_NAMESPACE
|
|
31
31
|
} from "../chunk-UHHHSYVE.js";
|
|
@@ -274,10 +274,10 @@ var LLMAsAJudgeScorer = class extends AbstractScorer {
|
|
|
274
274
|
),
|
|
275
275
|
...params.fieldsToExtract ?? {}
|
|
276
276
|
});
|
|
277
|
-
systemPrompt.push("You are a strict, fair evaluation judge.");
|
|
278
277
|
if (params.systemPrompt) {
|
|
279
278
|
systemPrompt.push(params.systemPrompt);
|
|
280
279
|
} else {
|
|
280
|
+
systemPrompt.push("You are a strict, fair evaluation judge.");
|
|
281
281
|
systemPrompt.push("Only use information from the rubric");
|
|
282
282
|
}
|
|
283
283
|
systemPrompt.push(
|
|
@@ -362,4 +362,4 @@ export {
|
|
|
362
362
|
MCQScorer,
|
|
363
363
|
LLMAsAJudgeScorer
|
|
364
364
|
};
|
|
365
|
-
//# sourceMappingURL=chunk-
|
|
365
|
+
//# sourceMappingURL=chunk-DNGT4SJC.js.map
|
|
@@ -1 +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 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 systemPrompt.push(\"You are a strict, fair evaluation judge.\");\n\n if (params.systemPrompt) {\n systemPrompt.push(params.systemPrompt);\n } else {\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
|
+
{"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":[]}
|
|
@@ -20,18 +20,18 @@ var MastraProvider = class extends AbstractLLMProvider {
|
|
|
20
20
|
endpoint;
|
|
21
21
|
authToken;
|
|
22
22
|
client;
|
|
23
|
-
|
|
24
|
-
warnedAboutResponseFormat = false;
|
|
23
|
+
memory;
|
|
25
24
|
constructor(params) {
|
|
26
25
|
super();
|
|
27
26
|
this.endpoint = params.endpoint;
|
|
28
27
|
this.authToken = params.authToken;
|
|
29
28
|
this.client = new MastraClient({
|
|
30
29
|
baseUrl: this.endpoint,
|
|
31
|
-
headers: {
|
|
30
|
+
headers: this.authToken ? {
|
|
32
31
|
Authorization: `Bearer ${this.authToken}`
|
|
33
|
-
}
|
|
32
|
+
} : void 0
|
|
34
33
|
});
|
|
34
|
+
this.memory = params.memory;
|
|
35
35
|
}
|
|
36
36
|
async forward(args) {
|
|
37
37
|
const apiMessages = args.messages.filter((m) => m.role === "user" || m.role === "assistant").map((m) => ({
|
|
@@ -47,7 +47,7 @@ var MastraProvider = class extends AbstractLLMProvider {
|
|
|
47
47
|
"model-id": args.model
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
{ memory: args.memory }
|
|
50
|
+
{ memory: args.memory ?? this.memory }
|
|
51
51
|
);
|
|
52
52
|
return {
|
|
53
53
|
data: response.text,
|
|
@@ -55,6 +55,12 @@ var MastraProvider = class extends AbstractLLMProvider {
|
|
|
55
55
|
completedAt: Date.now()
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
+
async getAgentInfo(args) {
|
|
59
|
+
return await this.client.getAgent(args.agentId).details(args.runtimeContext);
|
|
60
|
+
}
|
|
61
|
+
async getAgents(args) {
|
|
62
|
+
return this.client.getAgents(args?.runtimeContext, args?.partial);
|
|
63
|
+
}
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
// src/providers/openai.ts
|
|
@@ -226,4 +232,4 @@ export {
|
|
|
226
232
|
OpenAIProvider,
|
|
227
233
|
OpenRouterProvider
|
|
228
234
|
};
|
|
229
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-HPPCDSJ3.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 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.model,\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":[]}
|
|
@@ -4,6 +4,9 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/storages/abstract.ts
|
|
6
6
|
var AbstractStorage = class {
|
|
7
|
+
async count() {
|
|
8
|
+
throw new Error("Method not implemented.");
|
|
9
|
+
}
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
// src/storages/file.ts
|
|
@@ -109,4 +112,4 @@ export {
|
|
|
109
112
|
JSONFileStorage,
|
|
110
113
|
JSONFileStorageCodec
|
|
111
114
|
};
|
|
112
|
-
//# sourceMappingURL=chunk-
|
|
115
|
+
//# sourceMappingURL=chunk-JFLUJLGT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storages/abstract.ts","../src/storages/file.ts","../src/storages/json-file.ts"],"sourcesContent":["export abstract class AbstractStorage<TObject> {\n abstract init(params?: unknown): Promise<void>;\n abstract read(key: string, params?: unknown): Promise<TObject | null>;\n abstract readAll(params?: unknown): Promise<TObject[]>;\n abstract write(\n key: string,\n value: TObject,\n params?: unknown\n ): Promise<unknown>;\n\n async count(): Promise<number> {\n throw new Error(\"Method not implemented.\");\n }\n}\n","import { FileHandle, open } from \"node:fs/promises\";\nimport { AbstractStorage } from \"./abstract\";\n\nexport class FileStorage<TObject> extends AbstractStorage<TObject> {\n protected path: string;\n protected codec: AbstractFileStorageCodec<TObject>;\n protected fileHandle: FileHandle | undefined;\n\n constructor(config: {\n path: string;\n codec: AbstractFileStorageCodec<TObject>;\n }) {\n super();\n this.path = config.path;\n this.codec = config.codec;\n }\n\n async init(): Promise<void> {\n this.fileHandle = await open(this.path, \"r+\");\n }\n\n override async read(\n _key: string,\n _params?: unknown\n ): Promise<TObject | null> {\n throw new Error(\"Method not implemented.\");\n }\n\n override async readAll(_params?: unknown): Promise<TObject[]> {\n this.assertInitialized();\n\n return await this.codec.readAll({\n fileHandle: {\n readAt: this.readAt.bind(this),\n readChunks: this.readChunks.bind(this),\n size: this.size.bind(this),\n },\n });\n }\n\n override async write(\n _key: string,\n _value: TObject,\n _params?: unknown\n ): Promise<unknown> {\n throw new Error(\"Method not implemented.\");\n }\n\n protected async *readChunks(params: {\n startOffset?: number;\n chunkSize: number;\n }): AsyncIterable<{ offset: number; bytes: Uint8Array }> {\n this.assertInitialized();\n\n const fileSize = await this.size();\n let offset = params.startOffset ?? 0;\n\n // NOTE: What if the file size changed during the iteration?\n while (offset < fileSize) {\n const length = Math.min(params.chunkSize, fileSize - offset);\n if (length === 0) break;\n\n const bytes = await this.readAt(offset, length);\n if (bytes.length === 0) break;\n yield { offset, bytes };\n offset += bytes.length;\n }\n }\n\n protected async size(): Promise<number> {\n this.assertInitialized();\n\n return await this.fileHandle.stat().then((stat) => stat.size);\n }\n\n protected async readAt(offset: number, length: number): Promise<Uint8Array> {\n this.assertInitialized();\n\n const buffer = new Uint8Array(length);\n const result = await this.fileHandle.read(buffer, 0, length, offset);\n\n return new Uint8Array(buffer.subarray(0, result.bytesRead));\n }\n\n protected assertInitialized(): asserts this is this & {\n fileHandle: FileHandle;\n } {\n if (!this.fileHandle) {\n throw new Error(\"File Storage is not initialized\");\n }\n }\n}\n\nexport type FileStorageFileHandle = {\n size(): Promise<number>;\n readAt(offset: number, length: number): Promise<Uint8Array>;\n readChunks(params: {\n startOffset?: number;\n chunkSize: number;\n }): AsyncIterable<{ offset: number; bytes: Uint8Array }>;\n};\n\nexport abstract class AbstractFileStorageCodec<TObject> {\n abstract readAll(params: {\n fileHandle: FileStorageFileHandle;\n }): Promise<TObject[]>;\n // TODO: Add other methods like write, append, read one etc.\n}\n","import { bufferToString } from \"@/utils\";\nimport {\n AbstractFileStorageCodec,\n FileStorage,\n FileStorageFileHandle,\n} from \"./file\";\nimport z from \"zod\";\n\nexport class JSONFileStorage<TObject> extends FileStorage<TObject> {\n declare codec: JSONFileStorageCodec<TObject>;\n\n constructor(config: {\n path: string;\n chunkSize?: number;\n schema: z.ZodType<TObject>;\n }) {\n super({\n path: config.path,\n codec: new JSONFileStorageCodec({\n chunkSize: config.chunkSize,\n schema: config.schema,\n }),\n });\n }\n}\n\nexport class JSONFileStorageCodec<\n TObject,\n> extends AbstractFileStorageCodec<TObject> {\n private chunkSize: number;\n private schema: z.ZodType<TObject>;\n\n constructor(config: { chunkSize?: number; schema: z.ZodType<TObject> }) {\n super();\n this.chunkSize = config?.chunkSize ?? 64 * 1024;\n this.schema = config.schema;\n }\n\n async readAll(params: {\n fileHandle: FileStorageFileHandle;\n }): Promise<TObject[]> {\n const wholeFile: Uint8Array = new Uint8Array(\n await params.fileHandle.size()\n );\n for await (const chunk of params.fileHandle.readChunks({\n chunkSize: this.chunkSize,\n })) {\n wholeFile.set(chunk.bytes, chunk.offset);\n }\n\n return this.schema.array().parse(JSON.parse(bufferToString(wholeFile)));\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,6 +6,7 @@ declare abstract class AbstractStorage<TObject> {
|
|
|
6
6
|
abstract read(key: string, params?: unknown): Promise<TObject | null>;
|
|
7
7
|
abstract readAll(params?: unknown): Promise<TObject[]>;
|
|
8
8
|
abstract write(key: string, value: TObject, params?: unknown): Promise<unknown>;
|
|
9
|
+
count(): Promise<number>;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
declare class FileStorage<TObject> extends AbstractStorage<TObject> {
|
|
@@ -17,6 +17,7 @@ type ChatResponse = ProviderResponse<string> & {
|
|
|
17
17
|
outputTokensUsed?: number;
|
|
18
18
|
inputCost?: string;
|
|
19
19
|
outputCost?: string;
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export { AbstractLLMProvider as A, type ChatResponse as C, type LLMProviderForwardArgs as L };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as AbstractScorer, B as BaseScorerResult } from './abstract-Dec9Sc5O.js';
|
|
2
|
-
import { A as AbstractLLMProvider } from './llm-
|
|
2
|
+
import { A as AbstractLLMProvider } from './llm-BND163ns.js';
|
|
3
3
|
import { R as RateLimiter } from './rate-limiter-CSmVIRsM.js';
|
|
4
4
|
import z__default from 'zod';
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as AbstractLLMProvider, L as LLMProviderForwardArgs, C as ChatResponse } from '../llm-
|
|
1
|
+
import { A as AbstractLLMProvider, L as LLMProviderForwardArgs, C as ChatResponse } from '../llm-BND163ns.js';
|
|
2
2
|
export { A as AbstractProvider, P as ProviderResponse } from '../provider-BDjGp2y-.js';
|
|
3
|
-
import { MastraClient } from '@mastra/client-js';
|
|
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';
|
|
@@ -10,19 +10,34 @@ declare class MastraProvider extends AbstractLLMProvider {
|
|
|
10
10
|
private readonly endpoint;
|
|
11
11
|
private readonly authToken?;
|
|
12
12
|
private client;
|
|
13
|
-
private
|
|
14
|
-
private warnedAboutResponseFormat;
|
|
13
|
+
private memory?;
|
|
15
14
|
constructor(params: {
|
|
16
15
|
endpoint: string;
|
|
17
16
|
authToken?: string;
|
|
17
|
+
memory?: AgentMemoryOption;
|
|
18
18
|
});
|
|
19
19
|
forward(args: LLMProviderForwardArgs & {
|
|
20
20
|
memory?: AgentMemoryOption;
|
|
21
|
+
/**
|
|
22
|
+
* The model that will be used as the brain for the agent.
|
|
23
|
+
*/
|
|
24
|
+
modelName?: string;
|
|
21
25
|
}): Promise<ChatResponse>;
|
|
26
|
+
getAgentInfo(args: {
|
|
27
|
+
agentId: string;
|
|
28
|
+
runtimeContext?: MastraRuntimeContext;
|
|
29
|
+
}): Promise<GetAgentResponse>;
|
|
30
|
+
getAgents(args?: {
|
|
31
|
+
runtimeContext?: MastraRuntimeContext;
|
|
32
|
+
partial?: boolean;
|
|
33
|
+
}): Promise<Record<string, GetAgentResponse>>;
|
|
22
34
|
}
|
|
23
35
|
type AgentMemoryOption = Parameters<Parameters<MastraClient["getAgent"]>["0"] extends string ? ReturnType<MastraClient["getAgent"]>["generate"] : never>[0] extends {
|
|
24
36
|
memory?: infer M;
|
|
25
37
|
} ? M : never;
|
|
38
|
+
type MastraRuntimeContext = Parameters<Parameters<MastraClient["getAgent"]>["0"] extends string ? ReturnType<MastraClient["getAgent"]>["generate"] : never>[0] extends {
|
|
39
|
+
runtimeContext?: infer R;
|
|
40
|
+
} ? R : never;
|
|
26
41
|
|
|
27
42
|
declare class OpenAIProvider extends AbstractLLMProvider {
|
|
28
43
|
readonly kind: "peerbench.ai/llm/openai";
|
package/dist/providers/index.js
CHANGED
package/dist/scorers/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { A as AbstractScorer } from '../abstract-Dec9Sc5O.js';
|
|
2
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-
|
|
4
|
-
import '../llm-
|
|
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
5
|
import '../provider-BDjGp2y-.js';
|
|
6
6
|
import 'openai/resources/shared';
|
|
7
7
|
import 'openai/resources/chat/completions';
|
package/dist/scorers/index.js
CHANGED
package/dist/storages/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AbstractStorage } from '../json-file-
|
|
2
|
-
export { c as AbstractFileStorageCodec, F as FileStorage, b as FileStorageFileHandle, J as JSONFileStorage, a as JSONFileStorageCodec } from '../json-file-
|
|
1
|
+
import { A as AbstractStorage } from '../json-file-Bgv9TLcX.js';
|
|
2
|
+
export { c as AbstractFileStorageCodec, F as FileStorage, b as FileStorageFileHandle, J as JSONFileStorage, a as JSONFileStorageCodec } from '../json-file-Bgv9TLcX.js';
|
|
3
3
|
import * as better_sqlite3 from 'better-sqlite3';
|
|
4
4
|
import 'node:fs/promises';
|
|
5
5
|
import 'zod';
|
package/dist/storages/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storages/abstract.ts","../src/storages/file.ts","../src/storages/json-file.ts"],"sourcesContent":["export abstract class AbstractStorage<TObject> {\n abstract init(params?: unknown): Promise<void>;\n abstract read(key: string, params?: unknown): Promise<TObject | null>;\n abstract readAll(params?: unknown): Promise<TObject[]>;\n abstract write(\n key: string,\n value: TObject,\n params?: unknown\n ): Promise<unknown>;\n}\n","import { FileHandle, open } from \"node:fs/promises\";\nimport { AbstractStorage } from \"./abstract\";\n\nexport class FileStorage<TObject> extends AbstractStorage<TObject> {\n protected path: string;\n protected codec: AbstractFileStorageCodec<TObject>;\n protected fileHandle: FileHandle | undefined;\n\n constructor(config: {\n path: string;\n codec: AbstractFileStorageCodec<TObject>;\n }) {\n super();\n this.path = config.path;\n this.codec = config.codec;\n }\n\n async init(): Promise<void> {\n this.fileHandle = await open(this.path, \"r+\");\n }\n\n override async read(\n _key: string,\n _params?: unknown\n ): Promise<TObject | null> {\n throw new Error(\"Method not implemented.\");\n }\n\n override async readAll(_params?: unknown): Promise<TObject[]> {\n this.assertInitialized();\n\n return await this.codec.readAll({\n fileHandle: {\n readAt: this.readAt.bind(this),\n readChunks: this.readChunks.bind(this),\n size: this.size.bind(this),\n },\n });\n }\n\n override async write(\n _key: string,\n _value: TObject,\n _params?: unknown\n ): Promise<unknown> {\n throw new Error(\"Method not implemented.\");\n }\n\n protected async *readChunks(params: {\n startOffset?: number;\n chunkSize: number;\n }): AsyncIterable<{ offset: number; bytes: Uint8Array }> {\n this.assertInitialized();\n\n const fileSize = await this.size();\n let offset = params.startOffset ?? 0;\n\n // NOTE: What if the file size changed during the iteration?\n while (offset < fileSize) {\n const length = Math.min(params.chunkSize, fileSize - offset);\n if (length === 0) break;\n\n const bytes = await this.readAt(offset, length);\n if (bytes.length === 0) break;\n yield { offset, bytes };\n offset += bytes.length;\n }\n }\n\n protected async size(): Promise<number> {\n this.assertInitialized();\n\n return await this.fileHandle.stat().then((stat) => stat.size);\n }\n\n protected async readAt(offset: number, length: number): Promise<Uint8Array> {\n this.assertInitialized();\n\n const buffer = new Uint8Array(length);\n const result = await this.fileHandle.read(buffer, 0, length, offset);\n\n return new Uint8Array(buffer.subarray(0, result.bytesRead));\n }\n\n protected assertInitialized(): asserts this is this & {\n fileHandle: FileHandle;\n } {\n if (!this.fileHandle) {\n throw new Error(\"File Storage is not initialized\");\n }\n }\n}\n\nexport type FileStorageFileHandle = {\n size(): Promise<number>;\n readAt(offset: number, length: number): Promise<Uint8Array>;\n readChunks(params: {\n startOffset?: number;\n chunkSize: number;\n }): AsyncIterable<{ offset: number; bytes: Uint8Array }>;\n};\n\nexport abstract class AbstractFileStorageCodec<TObject> {\n abstract readAll(params: {\n fileHandle: FileStorageFileHandle;\n }): Promise<TObject[]>;\n // TODO: Add other methods like write, append, read one etc.\n}\n","import { bufferToString } from \"@/utils\";\nimport {\n AbstractFileStorageCodec,\n FileStorage,\n FileStorageFileHandle,\n} from \"./file\";\nimport z from \"zod\";\n\nexport class JSONFileStorage<TObject> extends FileStorage<TObject> {\n declare codec: JSONFileStorageCodec<TObject>;\n\n constructor(config: {\n path: string;\n chunkSize?: number;\n schema: z.ZodType<TObject>;\n }) {\n super({\n path: config.path,\n codec: new JSONFileStorageCodec({\n chunkSize: config.chunkSize,\n schema: config.schema,\n }),\n });\n }\n}\n\nexport class JSONFileStorageCodec<\n TObject,\n> extends AbstractFileStorageCodec<TObject> {\n private chunkSize: number;\n private schema: z.ZodType<TObject>;\n\n constructor(config: { chunkSize?: number; schema: z.ZodType<TObject> }) {\n super();\n this.chunkSize = config?.chunkSize ?? 64 * 1024;\n this.schema = config.schema;\n }\n\n async readAll(params: {\n fileHandle: FileStorageFileHandle;\n }): Promise<TObject[]> {\n const wholeFile: Uint8Array = new Uint8Array(\n await params.fileHandle.size()\n );\n for await (const chunk of params.fileHandle.readChunks({\n chunkSize: this.chunkSize,\n })) {\n wholeFile.set(chunk.bytes, chunk.offset);\n }\n\n return this.schema.array().parse(JSON.parse(bufferToString(wholeFile)));\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -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","import {\n AbstractLLMProvider,\n type ChatResponse,\n type LLMProviderForwardArgs,\n} from \"./abstract/llm\";\nimport { MastraClient } 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 warnedAboutSystemMessages = false;\n private warnedAboutResponseFormat = false;\n\n constructor(params: { endpoint: string; authToken?: string }) {\n super();\n this.endpoint = params.endpoint;\n this.authToken = params.authToken;\n this.client = new MastraClient({\n baseUrl: this.endpoint,\n headers: {\n Authorization: `Bearer ${this.authToken}`,\n },\n });\n }\n\n override async forward(\n args: LLMProviderForwardArgs & {\n memory?: AgentMemoryOption;\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.model,\n },\n },\n { memory: args.memory }\n );\n\n return {\n data: response.text,\n startedAt,\n completedAt: Date.now(),\n };\n }\n}\n\n// NOTE: Mastra client does not export this type\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","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":[]}
|