Eu queria um jeito de trazer definições de modelos type-safe e totalmente amarradas ao código para predições determinísticas no runtime.

Foi pra isso que eu construí essa biblioteca. Você define modelos preditivos direto em TypeScript, compila pra artefatos imutáveis no build, e roda 100% in-process.


Logística: Sincronização

Pense em como você define um banco de dados com um ORM. Você define um schema, roda um gerador, e tem um cliente type-safe que se mantém em sincronia com suas estruturas de dados. Caso algo mude, a build falha, você conserta e tudo se acerta.

Eu queria esse mesmo workflow: um comando que gere um artefato, e um runtime que é só uma chamada de função. Sem sidecars, sem Python em produção, sem latência. Só predições simples e determinísticas (e type-safe).


O que o PrisML faz

Você define um modelo em TypeScript, referenciando diretamente seus tipos existentes — não um dict Python, não um YAML:

import { defineModel } from '@vncsleal/prisml';

export const churnModel = defineModel<User>({
  name: 'UserChurn',
  modelName: 'User',
  output: {
    field: 'churned',
    taskType: 'binary_classification',
    resolver: (user) => user.churned,
  },
  features: {
    diasDeConta: (u) => Math.floor((Date.now() - u.createdAt.getTime()) / 86400000),
    isPremium: (u) => u.plano === 'premium',
    origemCadastro: (u) => u.signupSource,
  },
  algorithm: { name: 'forest', version: '1.0.0' },
  qualityGates: [
    { metric: 'f1', threshold: 0.75, comparison: 'gte' },
  ],
});

defineModel<User> é amarrado ao tipo User gerado pelo Prisma. Tipagem na definição. Renomeou um campo, o TypeScript aponta antes de rodar o treinamento, não depois de um deploy.

Você treina no build:

npx prisml train --config ./prisml.config.ts --schema ./prisma/schema.prisma

Isso gera dois arquivos — UserChurn.onnx e UserChurn.metadata.json.

No runtime, a predição é uma chamada de função in-process:

import { PredictionSession } from '@vncsleal/prisml';

const session = new PredictionSession();
await session.initializeModel(
  './models/UserChurn.metadata.json',
  './models/UserChurn.onnx',
  currentSchemaHash
);

const result = await session.predict('UserChurn', user, resolvers);
// result.prediction → 'churned' | 'retained'
// result.probability → 0.84

Python só é necessário pra treinar (scikit-learn + skl2onnx). O runtime é Node puro.


Proteção contra schema drift

O artefato armazena um hash SHA256 do seu schema Prisma no treinamento. Na inicialização, esse hash é verificado antes de qualquer inferência. Caso o schema mude sem retreinar:

SchemaDriftError: Schema hash mismatch for model 'UserChurn'.
  compilado: a3f9c2b1...
  runtime:   d74e81a0...
Run 'prisml train' pra recompilar contra o schema atual.

Essa foi minha solução para um modelo que degrada silenciosamente sem ninguém perceber porque uma feature foi renomeada dias atrás.


Escolhas de design e tradeoffs

ML em grande escalam geralmente precisa de pipelines complexos. Mas pra maioria das necessidades de produto que eu vejo (risco de churn, estimativa de LTV, ranking de recomendação) esse overhead acaba travando a implementação.

O PrisML foi pensado para isso. É pra quem quer poder preditivo rodando dentro do app Node sem os impostos de manutenção de uma stack de ML separada. Se você quer um modelo confiável, amarrado ao seu schema e fácil de buildar, vale a pena testar.

Website: getprisml.vercel.app
Github: github.com/vncsleal/prisml