dizyann's picture
feat: support the full Crivo model family
6986878
Raw History Blame Contribute Delete
1.74 kB
/** Cross-runtime parity against the pinned PyTorch / Python ORT fixtures. */
import { resolve } from 'node:path'
import type { Question } from '../../src/decisions/adapters/crivo.js'
import { Crivo } from '../../src/decisions/adapters/crivo.js'
import { MODEL_SIZES } from '../../src/decisions/models.js'
for (const size of process.argv.slice(2).length ? process.argv.slice(2) : MODEL_SIZES) {
const directory = resolve('.cache/variants', size)
const fixture = await Bun.file(`${directory}/parity.json`).json()
for (const dtype of ['fp32', 'q8'] as const) {
const model = await Crivo.load({
modelId: directory,
dtype,
device: 'cpu',
localFilesOnly: true
})
let maxError = 0
try {
for (const sample of fixture.cases) {
const answers = await model.answerMany(
sample.state,
sample.questions.map((question: Question) => ({ question }))
)
for (const [index, answer] of answers.entries()) {
const expected: number[] = sample[dtype === 'q8' ? 'int8' : 'fp32'][index]
const actual =
answer.type === 'noul'
? [1 - answer.noul, answer.noul]
: Object.values(answer.probabilities)
for (const [column, value] of actual.entries()) {
const difference = Math.abs(value - (expected[column] ?? Number.NaN))
if (!Number.isFinite(difference) || difference > 1e-4)
throw new Error(`${size}/${dtype}: probability mismatch ${difference}`)
maxError = Math.max(maxError, difference)
}
}
}
} finally {
await model.dispose()
}
console.log(JSON.stringify({ size, dtype, maxProbabilityError: maxError }))
}
}