chore: CRM-NEW baseline
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
// 离线回归评测:不调用 LLM,覆盖意图/注入/商品词/lead/格式/引用审计等确定性逻辑。
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { quickClassify } = require('../bridge/src/intent');
|
||||
const { detectInjection } = require('../bridge/src/security');
|
||||
const { translateProductQuery } = require('../bridge/src/product-query');
|
||||
const { hasBuyingIntent, missingLeadContacts } = require('../bridge/src/lead-intent');
|
||||
const { markdownToHtml } = require('../bridge/src/markdown');
|
||||
const { auditAnswer } = require('../bridge/src/audit');
|
||||
|
||||
const ENTRIES = [
|
||||
{ title: 'Rings', category: 'jewelry/rings', url: 'https://www.yehwang.com/jewelry/rings', aliases: ['戒指', 'ringen'] },
|
||||
{ title: 'Earrings', category: 'jewelry/earrings', url: 'https://www.yehwang.com/jewelry/earrings', aliases: ['耳环'] },
|
||||
{ title: 'Necklaces', category: 'jewelry/necklaces', url: 'https://www.yehwang.com/jewelry/necklaces', aliases: ['项链'] },
|
||||
];
|
||||
const cases = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bridge/eval/golden.json'), 'utf8'));
|
||||
|
||||
function run(c) {
|
||||
if (c.type === 'intent') return quickClassify(c.message);
|
||||
if (c.type === 'injection') return detectInjection(c.message).level;
|
||||
if (c.type === 'product_query') return translateProductQuery(c.message, ENTRIES).query;
|
||||
if (c.type === 'lead') {
|
||||
const missing = missingLeadContacts(c.slots || {});
|
||||
return missing.join(',');
|
||||
}
|
||||
if (c.type === 'markdown') return markdownToHtml(c.message);
|
||||
if (c.type === 'audit') {
|
||||
const audit = auditAnswer({
|
||||
finalContent: c.message,
|
||||
toolResults: [{ results: [{ source_urls: c.tool_urls || [] }] }],
|
||||
toolCalls: [],
|
||||
});
|
||||
return String(audit.unverified_urls.length);
|
||||
}
|
||||
throw new Error(`unknown case type: ${c.type}`);
|
||||
}
|
||||
|
||||
function check(c, actual) {
|
||||
if (c.type === 'lead') return actual === (c.expect_missing || []).join(',');
|
||||
if (c.type === 'markdown') {
|
||||
return (c.expect_contains || []).every((s) => actual.includes(s))
|
||||
&& (c.expect_not_contains || []).every((s) => !actual.includes(s));
|
||||
}
|
||||
if (c.type === 'audit') return actual === String(c.expect_unverified);
|
||||
return actual === c.expect;
|
||||
}
|
||||
|
||||
let failed = 0;
|
||||
for (const c of cases) {
|
||||
const actual = run(c);
|
||||
const ok = check(c, actual);
|
||||
if (!ok) failed += 1;
|
||||
console.log(`${ok ? 'PASS' : 'FAIL'} ${c.id}${ok ? '' : ` expected=${JSON.stringify(c.expect || c.expect_missing || c.expect_contains)} actual=${JSON.stringify(actual)}`}`);
|
||||
}
|
||||
console.log(`\n${cases.length - failed}/${cases.length} passed`);
|
||||
process.exit(failed ? 1 : 0);
|
||||
Reference in New Issue
Block a user