@aipack-ai/eval 1.1.7 → 1.1.8
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/src/cli.d.ts +4 -0
- package/dist/src/cli.js +200 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/core/compare.d.ts +28 -0
- package/dist/src/core/compare.js +101 -0
- package/dist/src/core/compare.js.map +1 -0
- package/dist/src/core/embedding.d.ts +33 -0
- package/dist/src/core/embedding.js +68 -0
- package/dist/src/core/embedding.js.map +1 -0
- package/dist/src/core/import.d.ts +30 -0
- package/dist/src/core/import.js +111 -0
- package/dist/src/core/import.js.map +1 -0
- package/dist/src/core/judge-llm.d.ts +13 -0
- package/dist/src/core/judge-llm.js +47 -0
- package/dist/src/core/judge-llm.js.map +1 -0
- package/dist/src/core/live.d.ts +34 -0
- package/dist/src/core/live.js +45 -0
- package/dist/src/core/live.js.map +1 -1
- package/dist/src/core/runner.js +48 -4
- package/dist/src/core/runner.js.map +1 -1
- package/dist/src/core/scorer/index.d.ts +20 -2
- package/dist/src/core/scorer/index.js +36 -9
- package/dist/src/core/scorer/index.js.map +1 -1
- package/dist/src/core/scorer/llm-judge.d.ts +43 -0
- package/dist/src/core/scorer/llm-judge.js +111 -0
- package/dist/src/core/scorer/llm-judge.js.map +1 -0
- package/dist/src/core/scorer/semantic.d.ts +27 -0
- package/dist/src/core/scorer/semantic.js +74 -0
- package/dist/src/core/scorer/semantic.js.map +1 -0
- package/dist/src/core/types.d.ts +19 -0
- package/dist/src/core/validate.js +3 -3
- package/dist/src/core/validate.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* packages/eval/src/core/scorer/llm-judge.ts - LLM-as-judge 评分器(M5)
|
|
3
|
+
*
|
|
4
|
+
* 开放性回答的终审(EVAL_PLAN.md 4.2 硬性约束):
|
|
5
|
+
* - judge 模型与被测模型异源(装配层校验,见 live.ts assertJudgeDistinct)
|
|
6
|
+
* - 输出强制 JSON(score + reason + evidence),解析失败视为 scorer
|
|
7
|
+
* 自身错误 → 跳过该评分器而非判用例失败
|
|
8
|
+
* - judge prompt 版本纳入元数据(JUDGE_PROMPT_VERSION / params.promptVersion),
|
|
9
|
+
* 改 rubric 不 invalidate 全部历史结果
|
|
10
|
+
*/
|
|
11
|
+
export const JUDGE_PROMPT_VERSION = 1;
|
|
12
|
+
function truncate(s, n) {
|
|
13
|
+
return s.length <= n ? s : `${s.slice(0, n)}…`;
|
|
14
|
+
}
|
|
15
|
+
function formatTrajectory(calls) {
|
|
16
|
+
if (calls.length === 0)
|
|
17
|
+
return '(无工具调用)';
|
|
18
|
+
return calls
|
|
19
|
+
.map((c, i) => `${i + 1}. ${c.name}(${JSON.stringify(c.args ?? {})})${c.isError ? ' [error]' : ''}`)
|
|
20
|
+
.join('\n');
|
|
21
|
+
}
|
|
22
|
+
/** 组装 judge prompt(版本化:改 rubric / 格式不影响历史结果的含义) */
|
|
23
|
+
export function buildJudgePrompt(params, output, trajectory) {
|
|
24
|
+
const version = params.promptVersion ?? JUDGE_PROMPT_VERSION;
|
|
25
|
+
const criteria = params.criteria.map((c, i) => `${i + 1}. ${c}`).join('\n');
|
|
26
|
+
return [
|
|
27
|
+
`你是严格的评测 judge(prompt v${version})。请逐条依据以下 rubric 评判 agent 回答的质量:`,
|
|
28
|
+
'',
|
|
29
|
+
criteria,
|
|
30
|
+
'',
|
|
31
|
+
'── Agent 最终输出 ──',
|
|
32
|
+
output,
|
|
33
|
+
'',
|
|
34
|
+
'── 工具调用轨迹(时间序) ──',
|
|
35
|
+
formatTrajectory(trajectory),
|
|
36
|
+
'',
|
|
37
|
+
'要求:',
|
|
38
|
+
'- score 为 0~1 的数字(全部 rubric 满足 = 1,完全不满足 = 0)',
|
|
39
|
+
'- reason 必须给出理由并引用证据',
|
|
40
|
+
'- 只输出一个 JSON 对象,不要输出其他任何文本:',
|
|
41
|
+
' {"score": <0~1>, "reason": "<理由>", "evidence": "<命中的原文片段或调用序号>"}',
|
|
42
|
+
].join('\n');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 解析 judge 输出。宽容处理:截取首个 '{' 到最后一个 '}'。
|
|
46
|
+
* 解析失败返回 undefined(scorer 自身错误 → 跳过,不判用例失败)。
|
|
47
|
+
*/
|
|
48
|
+
export function parseJudgeResponse(raw) {
|
|
49
|
+
const start = raw.indexOf('{');
|
|
50
|
+
const end = raw.lastIndexOf('}');
|
|
51
|
+
if (start < 0 || end <= start)
|
|
52
|
+
return undefined;
|
|
53
|
+
let parsed;
|
|
54
|
+
try {
|
|
55
|
+
parsed = JSON.parse(raw.slice(start, end + 1));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
if (!parsed || typeof parsed !== 'object')
|
|
61
|
+
return undefined;
|
|
62
|
+
const { score, reason, evidence } = parsed;
|
|
63
|
+
if (typeof score !== 'number' || !Number.isFinite(score))
|
|
64
|
+
return undefined;
|
|
65
|
+
const clamped = Math.min(Math.max(score, 0), 1);
|
|
66
|
+
return {
|
|
67
|
+
score: clamped,
|
|
68
|
+
reason: typeof reason === 'string' && reason ? reason : '(judge 未给出理由)',
|
|
69
|
+
evidence: typeof evidence === 'string' ? evidence : undefined,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 执行 LLM-as-judge。
|
|
74
|
+
* 返回 undefined = 评分器跳过(缺 judge 装配 / judge 输出解析失败 / judge 调用失败),
|
|
75
|
+
* 不判用例失败(EVAL_PLAN.md 4.2)。
|
|
76
|
+
*/
|
|
77
|
+
export async function runLlmJudge(trace, params, deps) {
|
|
78
|
+
if (!deps)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (!Array.isArray(params.criteria) || params.criteria.length === 0) {
|
|
81
|
+
return {
|
|
82
|
+
scorer: 'llm-judge',
|
|
83
|
+
score: 0,
|
|
84
|
+
passed: false,
|
|
85
|
+
reason: "评分器参数缺少非空数组字段 'criteria'",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const prompt = buildJudgePrompt(params, trace.result.content, trace.trajectory);
|
|
89
|
+
let raw;
|
|
90
|
+
try {
|
|
91
|
+
raw = await deps.complete(prompt);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
console.error('[eval] llm-judge 调用失败(跳过):', e.message);
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const verdict = parseJudgeResponse(raw);
|
|
98
|
+
if (!verdict) {
|
|
99
|
+
console.error('[eval] llm-judge 输出解析失败(跳过):', truncate(raw, 120));
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
const passed = verdict.score >= 0.5;
|
|
103
|
+
return {
|
|
104
|
+
scorer: 'llm-judge',
|
|
105
|
+
score: verdict.score,
|
|
106
|
+
passed,
|
|
107
|
+
reason: `[${deps.modelLabel ?? 'judge'} v${params.promptVersion ?? JUDGE_PROMPT_VERSION}] ${verdict.reason}`,
|
|
108
|
+
evidence: verdict.evidence,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=llm-judge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-judge.js","sourceRoot":"","sources":["../../../../src/core/scorer/llm-judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAStC,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS;IACpC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAuB;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,KAAK;SACT,GAAG,CACF,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CACvF;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,MAAc,EACd,UAA4B;IAE5B,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,IAAI,oBAAoB,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5E,OAAO;QACL,yBAAyB,OAAO,kCAAkC;QAClE,EAAE;QACF,QAAQ;QACR,EAAE;QACF,kBAAkB;QAClB,MAAM;QACN,EAAE;QACF,mBAAmB;QACnB,gBAAgB,CAAC,UAAU,CAAC;QAC5B,EAAE;QACF,KAAK;QACL,+CAA+C;QAC/C,sBAAsB;QACtB,6BAA6B;QAC7B,oEAAoE;KACrE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAiC,CAAC;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,OAAO;QACL,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe;QACvE,QAAQ,EAAE,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;KAC9D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAe,EACf,MAAmB,EACnB,IAAgB;IAEhB,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,0BAA0B;SACnC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAChF,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;QAClE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAClE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC;IACpC,OAAO;QACL,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM;QACN,MAAM,EAAE,IAAI,IAAI,CAAC,UAAU,IAAI,OAAO,KAAK,MAAM,CAAC,aAAa,IAAI,oBAAoB,KAAK,OAAO,CAAC,MAAM,EAAE;QAC5G,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* packages/eval/src/core/scorer/semantic.ts - 语义评分器(M5)
|
|
3
|
+
*
|
|
4
|
+
* embedding 相似度粗筛开放性回答:期望文本与最终输出各算一次 embedding,
|
|
5
|
+
* 余弦相似度 ≥ threshold 即通过。低成本低精度,只做开放性回答的粗筛
|
|
6
|
+
* (EVAL_PLAN.md 4.2:语义评分器)。
|
|
7
|
+
*
|
|
8
|
+
* embedding 注入点(EmbedFn)由调用方装配(见 core/embedding.ts 的
|
|
9
|
+
* OpenAI 兼容实现),单测可注入 stub;缺 embed 时评分器跳过(不判失败)。
|
|
10
|
+
*/
|
|
11
|
+
import type { RunTrace, ScoreResult } from '../types';
|
|
12
|
+
/** 文本 → 向量(由调用方注入:真实 provider / 测试 stub) */
|
|
13
|
+
export type EmbedFn = (text: string) => Promise<number[]>;
|
|
14
|
+
export interface SemanticParams {
|
|
15
|
+
/** 期望语义的参考文本 */
|
|
16
|
+
expected: string;
|
|
17
|
+
/** 通过阈值(缺省 0.75,0~1) */
|
|
18
|
+
threshold?: number;
|
|
19
|
+
}
|
|
20
|
+
export declare const SEMANTIC_DEFAULT_THRESHOLD = 0.75;
|
|
21
|
+
/** 余弦相似度(零向量返回 0) */
|
|
22
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
23
|
+
/**
|
|
24
|
+
* 执行语义评分。
|
|
25
|
+
* 返回 undefined = 评分器跳过(缺 embed 注入点),不判用例失败。
|
|
26
|
+
*/
|
|
27
|
+
export declare function runSemanticScorer(trace: RunTrace, params: SemanticParams, embed?: EmbedFn): Promise<ScoreResult | undefined>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* packages/eval/src/core/scorer/semantic.ts - 语义评分器(M5)
|
|
3
|
+
*
|
|
4
|
+
* embedding 相似度粗筛开放性回答:期望文本与最终输出各算一次 embedding,
|
|
5
|
+
* 余弦相似度 ≥ threshold 即通过。低成本低精度,只做开放性回答的粗筛
|
|
6
|
+
* (EVAL_PLAN.md 4.2:语义评分器)。
|
|
7
|
+
*
|
|
8
|
+
* embedding 注入点(EmbedFn)由调用方装配(见 core/embedding.ts 的
|
|
9
|
+
* OpenAI 兼容实现),单测可注入 stub;缺 embed 时评分器跳过(不判失败)。
|
|
10
|
+
*/
|
|
11
|
+
export const SEMANTIC_DEFAULT_THRESHOLD = 0.75;
|
|
12
|
+
/** 余弦相似度(零向量返回 0) */
|
|
13
|
+
export function cosineSimilarity(a, b) {
|
|
14
|
+
if (a.length === 0 || a.length !== b.length)
|
|
15
|
+
return 0;
|
|
16
|
+
let dot = 0;
|
|
17
|
+
let na = 0;
|
|
18
|
+
let nb = 0;
|
|
19
|
+
for (let i = 0; i < a.length; i++) {
|
|
20
|
+
dot += a[i] * b[i];
|
|
21
|
+
na += a[i] * a[i];
|
|
22
|
+
nb += b[i] * b[i];
|
|
23
|
+
}
|
|
24
|
+
if (na === 0 || nb === 0)
|
|
25
|
+
return 0;
|
|
26
|
+
return dot / Math.sqrt(na * nb);
|
|
27
|
+
}
|
|
28
|
+
function truncate(s, n) {
|
|
29
|
+
return s.length <= n ? s : `${s.slice(0, n)}…`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 执行语义评分。
|
|
33
|
+
* 返回 undefined = 评分器跳过(缺 embed 注入点),不判用例失败。
|
|
34
|
+
*/
|
|
35
|
+
export async function runSemanticScorer(trace, params, embed) {
|
|
36
|
+
if (!embed) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const expected = params.expected;
|
|
40
|
+
if (typeof expected !== 'string' || !expected) {
|
|
41
|
+
return {
|
|
42
|
+
scorer: 'semantic',
|
|
43
|
+
score: 0,
|
|
44
|
+
passed: false,
|
|
45
|
+
reason: "评分器参数缺少字符串字段 'expected'",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const threshold = typeof params.threshold === 'number' && params.threshold > 0 && params.threshold <= 1
|
|
49
|
+
? params.threshold
|
|
50
|
+
: SEMANTIC_DEFAULT_THRESHOLD;
|
|
51
|
+
try {
|
|
52
|
+
const [expVec, actVec] = await Promise.all([
|
|
53
|
+
embed(expected),
|
|
54
|
+
embed(trace.result.content),
|
|
55
|
+
]);
|
|
56
|
+
const sim = cosineSimilarity(expVec, actVec);
|
|
57
|
+
const passed = sim >= threshold;
|
|
58
|
+
return {
|
|
59
|
+
scorer: 'semantic',
|
|
60
|
+
score: sim,
|
|
61
|
+
passed,
|
|
62
|
+
reason: passed
|
|
63
|
+
? `语义相似度 ${sim.toFixed(3)} ≥ 阈值 ${threshold}`
|
|
64
|
+
: `语义相似度 ${sim.toFixed(3)} < 阈值 ${threshold}`,
|
|
65
|
+
evidence: `expected: ${truncate(expected, 80)} / actual: ${truncate(trace.result.content, 80)}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
// embedding 调用失败视为 scorer 自身错误,不判用例失败(跳过)
|
|
70
|
+
console.error('[eval] semantic scorer embedding 失败(跳过):', e.message);
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=semantic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../../../src/core/scorer/semantic.ts"],"names":[],"mappings":"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"}
|
package/dist/src/core/types.d.ts
CHANGED
|
@@ -265,6 +265,25 @@ export interface RunConfig {
|
|
|
265
265
|
maxTotalTokens?: number;
|
|
266
266
|
/** live 模式单请求超时 ms */
|
|
267
267
|
requestTimeoutMs?: number;
|
|
268
|
+
/**
|
|
269
|
+
* LLM-as-judge 的异源模型('provider/modelId');缺省读 AIPACK_EVAL_JUDGE_MODEL。
|
|
270
|
+
* 用例含 llm-judge 评分器时必填;与被测模型相同则拒绝(同源偏置)。
|
|
271
|
+
*/
|
|
272
|
+
judgeModel?: string;
|
|
273
|
+
/** judge API Key(缺省 AIPACK_EVAL_JUDGE_API_KEY / <PROVIDER>_API_KEY) */
|
|
274
|
+
judgeApiKey?: string;
|
|
275
|
+
/** judge 端点覆盖 */
|
|
276
|
+
judgeBaseUrl?: string;
|
|
277
|
+
/** semantic 评分器的 embedding 模型;缺省读 AIPACK_EVAL_EMBEDDING_MODEL */
|
|
278
|
+
embedModel?: string;
|
|
279
|
+
/** embedding API Key(缺省 AIPACK_EVAL_EMBEDDING_API_KEY / OPENAI_API_KEY) */
|
|
280
|
+
embedApiKey?: string;
|
|
281
|
+
/** embedding 端点覆盖(OpenAI 兼容 /embeddings) */
|
|
282
|
+
embedBaseUrl?: string;
|
|
283
|
+
/** 直接注入 judge StreamFn(自托管 / 测试用),配合 judgeFrameworkModel */
|
|
284
|
+
judgeStreamFn?: StreamFn;
|
|
285
|
+
/** 与 judgeStreamFn 配套的框架 Model */
|
|
286
|
+
judgeFrameworkModel?: Model;
|
|
268
287
|
}
|
|
269
288
|
export interface BaselineFile {
|
|
270
289
|
/** 生成 baseline 的 runId */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* loader 加载 JSON 后立即校验,坏用例在运行前暴露(fail fast)。
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { ALL_SCORER_TYPES } from './scorer/index.js';
|
|
7
7
|
const ORIGINS = [
|
|
8
8
|
'handwritten',
|
|
9
9
|
'trace',
|
|
@@ -65,8 +65,8 @@ export function validateEvalCase(c) {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
for (const s of c.scorers ?? []) {
|
|
68
|
-
if (!
|
|
69
|
-
errors.push(at(`scorers 含未知类型 '${s.type}'(支持: ${
|
|
68
|
+
if (!ALL_SCORER_TYPES.includes(s.type)) {
|
|
69
|
+
errors.push(at(`scorers 含未知类型 '${s.type}'(支持: ${ALL_SCORER_TYPES.join(', ')})`));
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
const hasScorers = Boolean(c.expected) || (c.scorers?.length ?? 0) > 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/core/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/core/validate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipack-ai/eval",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "aipack Eval 体系:EvalCase 格式 + 规则评分器 + Runner(mock fixture replay)+ 报告与 baseline 门禁",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"node": ">=18.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@aipack-ai/agent": "1.1.
|
|
38
|
+
"@aipack-ai/agent": "1.1.8"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^20.12.0",
|