feat(aihr): harden finance RAG retrieval and evidence gates
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { run } from './evaluate-knowledge-quality.mjs';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const baseUrl = process.env.AIHR_BASE_URL || 'https://wygj-api.localhost';
|
||||
const clientid = '428a8310cd442757ae699df5d894f051';
|
||||
const dataset = new URL('../tests/fixtures/data_quality/retrieval-finance-regression.json', import.meta.url);
|
||||
|
||||
function localUniqueActivePhone() {
|
||||
const sql = `
|
||||
select min(s.person_phone)
|
||||
from aihr_org_snapshot s
|
||||
where s.tenant_id = '000000'
|
||||
and lower(coalesce(s.employment_status, 'active')) in ('active', '在职')
|
||||
and s.person_phone regexp '^[0-9]{11}$'
|
||||
and (select count(distinct p.ext_party_id) from aihr_org_snapshot p
|
||||
where p.tenant_id = s.tenant_id and p.person_phone = s.person_phone
|
||||
and lower(coalesce(p.employment_status, 'active')) in ('active', '在职')) = 1
|
||||
and (select count(distinct e.person_phone) from aihr_org_snapshot e
|
||||
where e.tenant_id = s.tenant_id and e.ext_party_id = s.ext_party_id
|
||||
and lower(coalesce(e.employment_status, 'active')) in ('active', '在职')) = 1`;
|
||||
return execFileSync('docker', [
|
||||
'exec', 'wygj-mysql', 'mysql', '-uroot', '-proot', '--default-character-set=utf8mb4',
|
||||
'ry-vue', '-Nse', sql
|
||||
], { encoding: 'utf8' }).trim();
|
||||
}
|
||||
|
||||
const phone = process.env.AIHR_VERIFY_PHONE || localUniqueActivePhone();
|
||||
if (!phone) throw new Error('no bidirectionally unique active local employee is available');
|
||||
|
||||
execFileSync('docker', [
|
||||
'exec', 'wygj-redis', 'redis-cli', '-a', 'ruoyi123', 'del',
|
||||
`{global:rate_limit:/resource/sms/code:${phone}}:value`,
|
||||
`global:rate_limit:/resource/sms/code:${phone}`,
|
||||
`{global:rate_limit:/resource/sms/code:${phone}}:permits`
|
||||
], { stdio: 'ignore' });
|
||||
|
||||
if (new URL(baseUrl).hostname.endsWith('.localhost')) {
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
}
|
||||
|
||||
async function api(endpoint, init = {}) {
|
||||
const response = await fetch(`${baseUrl.replace(/\/$/, '')}${endpoint}`, {
|
||||
...init,
|
||||
headers: { clientid, ...(init.headers || {}) },
|
||||
signal: AbortSignal.timeout(30_000)
|
||||
});
|
||||
const payload = await response.json();
|
||||
if (!response.ok || Number(payload.code) !== 200) {
|
||||
throw new Error(`${endpoint} failed: HTTP ${response.status}, code ${payload.code}, ${payload.msg || ''}`);
|
||||
}
|
||||
return payload.data;
|
||||
}
|
||||
|
||||
await api(`/resource/sms/code?phonenumber=${encodeURIComponent(phone)}`);
|
||||
const login = await api('/auth/mobile/sms-login', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
phonenumber: phone,
|
||||
smsCode: process.env.AIHR_VERIFY_SMS_CODE || '123456',
|
||||
tenantId: '000000'
|
||||
})
|
||||
});
|
||||
if (!login?.access_token) throw new Error('mobile login returned no access token');
|
||||
|
||||
const result = await run({
|
||||
dataset: fileURLToPath(dataset),
|
||||
baseUrl,
|
||||
token: login.access_token,
|
||||
clientid,
|
||||
k: 20
|
||||
});
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
if (result.thresholdPassed === false) process.exitCode = 2;
|
||||
Reference in New Issue
Block a user