Ir para o conteúdo

Projeto independente de P&D · Colônia

Fronteira probabilística

Um componente probabilístico é delimitado e não pode se tornar diretamente uma saída de domínio com autoridade.

Não normativo

Versão do Companion
1.0
Corresponde ao COADF Core
2.2
Status
Atual
Última revisão
Princípios do COADF
P-1, P-5

Propriedade de arquitetura

O COADF P-1 enuncia o mínimo: um componente probabilístico devolve um valor junto com uma confiança e o método pelo qual o valor foi obtido, nunca um valor nu, e nunca chega diretamente a uma saída. Este padrão trata da segunda metade, que é a metade que as implementações perdem. A resposta de um modelo pode entrar no sistema. O que ela não pode é se tornar, por caminho algum, aquilo que o sistema trata como estabelecido.

Três coisas precisam valer ao mesmo tempo:

  • A saída tem um tipo próprio. Uma proposta e um registro com autoridade são tipos diferentes, tabelas diferentes ou mensagens diferentes. Um código que tem um deles em mãos não consegue passá-lo onde se espera o outro sem uma etapa explícita que alguém possa revisar.
  • A fronteira valida em tempo de execução. O contrato é verificado quando a resposta chega, no processo que a recebe, diga o remetente o que disser ter verificado.
  • A procedência viaja com o valor. O método, o modelo e sua revisão, a revisão do prompt e a localização na fonte permanecem ligados ao valor em cada etapa, serialização incluída. Sem eles, o P-4 não consegue reconstruir e o P-5 não consegue declarar.

O P-1 também faz o componente informar uma confiança. Como a confiança é expressa, atribuída e usada pertence ao P-2, que o COADF publica apenas como princípio. Este Companion não a descreve, e nada abaixo depende dela.

Por que importa

A saída de um modelo vem de um processo que não pode ser reproduzido a partir de suas entradas como a saída de um parser pode: amostragem, atualizações do modelo e mudanças de prompt, tudo isso a desloca. Isso é aceitável para uma proposta e inaceitável para um fato. O risco não é um modelo às vezes errar; tudo às vezes erra. O risco é perder a capacidade de dizer quais valores vieram de onde, porque todo controle posterior depende disso. Um gate só detém o que consegue ver, uma declaração só nomeia o que está marcado, e uma pessoa revisora só confere o que ainda aponta para sua fonte.

A perda raramente é uma decisão. Ela acontece numa linha de código comum: uma entidade do ORM preenchida a partir do JSON do modelo porque os nomes dos campos por acaso coincidiam, um modelo de resposta que descarta a procedência porque ninguém a acrescentou, uma importação em lote que contorna o formulário onde a validação morava. O padrão existe para tornar impossível escrever essa linha sem perceber.

Estratégias de implementação válidas

O isolamento é arquitetural, não necessariamente físico

Microsserviços não são necessários. A propriedade vale quando nenhum caminho de código permite ao lado probabilístico produzir um objeto com autoridade, e um único processo consegue mantê-la tão bem quanto uma rede. A topologia se escolhe por razões próprias (escalar separadamente uma carga de inferência, isolar a biblioteca cliente de um fornecedor, fazer deploy de forma independente), e depois a fronteira se constrói na forma escolhida. As quatro figuras abaixo mantêm a mesma propriedade em quatro formas.

Arquitetura de exemplo · Não normativa

Monólito modular

Exemplo de arquitetura, não normativo: um monólito modular em que um cliente do modelo, um módulo de fronteira, um núcleo de domínio e um adaptador de classificação compartilham um processo, com a trilha de auditoria e um serviço externo fora dele.Dentro de um processo: um cliente do modelo, marcado como probabilístico, passa sua resposta bruta a um módulo de fronteira, que passa uma Proposal ao núcleo de domínio. Um adaptador de classificação, também dentro do processo, pode passar um enriquecimento ao núcleo de domínio, e consulta um serviço de classificação externo, fora do processo. O núcleo de domínio grava entradas na trilha de auditoria, um banco de dados separado. O único caminho do cliente do modelo até o núcleo de domínio passa pela fronteira.Um processo, uma unidade de deployClientedo modeloprobabilísticoFronteiracontrato tipado,validação, procedênciaNúcleo de domíniopropostas separadas dosregistros verificadosAdaptadorde classificação,atrás de uma portaTrilhade auditoriasomente de inserçãoServiço externoclassificaçãoresposta brutaProposalentradas
  • Fluxo de dados neste exemplo
  • Opcional: pode estar indisponível
Um processo. A fronteira é um módulo, e contratos de importação impedem que o cliente do modelo alcance o núcleo de domínio a não ser por meio dela.

Descrição textual. Dentro de um processo: um cliente do modelo, marcado como probabilístico, passa sua resposta bruta a um módulo de fronteira, que passa uma Proposal ao núcleo de domínio. Um adaptador de classificação, também dentro do processo, pode passar um enriquecimento ao núcleo de domínio, e consulta um serviço de classificação externo, fora do processo. O núcleo de domínio grava entradas na trilha de auditoria, um banco de dados separado. O único caminho do cliente do modelo até o núcleo de domínio passa pela fronteira.

Arquitetura de exemplo · Não normativa

Orientada a serviços

Exemplo de arquitetura, não normativo: um serviço de inferência com um cliente do modelo e uma fronteira, e um serviço de domínio com sua própria fronteira, núcleo de domínio, adaptador de classificação e trilha de auditoria.Um serviço de inferência contém um cliente do modelo, marcado como probabilístico, e uma fronteira que valida o que ele envia. Ele envia por HTTP, sob um contrato JSON, a um serviço de domínio, cuja própria fronteira valida o que recebe e passa uma Proposal ao núcleo de domínio. O serviço de domínio também contém um adaptador de classificação, que consulta um serviço externo e pode passar um enriquecimento ao núcleo de domínio, e a trilha de auditoria, na qual o núcleo de domínio grava entradas. O serviço de inferência não tem nenhuma conexão com a trilha de auditoria.Serviço de inferênciaServiço de domínio e seu armazenamentoClientedo modeloprobabilísticoFronteiravalida o queela enviaFronteiravalida o queela recebeNúcleo de domíniopropostas à parte dosregistros verificadosAdaptadorde classificaçãoTrilha de auditoriasomente de inserçãoServiço externoclassificaçãoresposta brutaHTTP, JSONProposalentradas
  • Fluxo de dados neste exemplo
  • Opcional: pode estar indisponível
Dois serviços. Cada lado valida: o remetente, o que envia; o destinatário, o que recebe. O serviço de inferência não tem credenciais para o armazenamento do domínio.

Descrição textual. Um serviço de inferência contém um cliente do modelo, marcado como probabilístico, e uma fronteira que valida o que ele envia. Ele envia por HTTP, sob um contrato JSON, a um serviço de domínio, cuja própria fronteira valida o que recebe e passa uma Proposal ao núcleo de domínio. O serviço de domínio também contém um adaptador de classificação, que consulta um serviço externo e pode passar um enriquecimento ao núcleo de domínio, e a trilha de auditoria, na qual o núcleo de domínio grava entradas. O serviço de inferência não tem nenhuma conexão com a trilha de auditoria.

Arquitetura de exemplo · Não normativa

Orientada a eventos

Exemplo de arquitetura, não normativo: um worker de inferência publica propostas em um tópico, e um consumidor de domínio as valida no recebimento antes que o núcleo de domínio grave entradas de auditoria.Um worker de inferência contém um cliente do modelo, marcado como probabilístico, e uma fronteira. Ele publica uma mensagem em um tópico de propostas. O corpo da mensagem carrega o trace_id de auditoria; seus cabeçalhos carregam o contexto de execução como um traceparent W3C. Um consumidor de domínio lê o tópico, valida cada mensagem no recebimento e passa uma Proposal ao núcleo de domínio, que grava entradas na trilha de auditoria.Worker de inferênciaConsumidor de domínioCliente do modeloprobabilísticoFronteiravalidaantes de publicarTópicopropostasFronteiravalidano recebimentoNúcleo de domíniopropostas à parte dosregistros verificadosTrilha de auditoriasomente de inserçãocorpo: trace_idcabeçalhos: traceparentpublicaconsomeProposalentradas
  • Fluxo de dados neste exemplo
Um tópico entre os dois lados. O trace_id de auditoria viaja no corpo da mensagem, como parte do contrato; o contexto de execução viaja nos cabeçalhos da mensagem.

Descrição textual. Um worker de inferência contém um cliente do modelo, marcado como probabilístico, e uma fronteira. Ele publica uma mensagem em um tópico de propostas. O corpo da mensagem carrega o trace_id de auditoria; seus cabeçalhos carregam o contexto de execução como um traceparent W3C. Um consumidor de domínio lê o tópico, valida cada mensagem no recebimento e passa uma Proposal ao núcleo de domínio, que grava entradas na trilha de auditoria.

Arquitetura de exemplo · Não normativa

Deploy cloud-native

Exemplo de arquitetura, não normativo: um namespace de inferência, um namespace de serviço de modelos e um namespace de registros, com o egress da inferência permitido apenas para o endpoint do modelo e para a recepção de propostas.No namespace de inferência, um pod de inferência executa o cliente do modelo e sua fronteira. Ele pode enviar ao endpoint do modelo, no namespace de serviço de modelos, e à recepção de propostas, no namespace de registros, somente pela porta de API desta. A recepção de propostas valida o que recebe e passa uma Proposal ao núcleo de domínio, que grava na trilha de auditoria e no banco de dados de registros. Uma nota afirma que o namespace de inferência não tem rota nem credencial para esse banco de dados.Namespace: inferênciaNamespace: serviço de modelosNamespace: registrosPod de inferênciacliente do modeloe fronteiraEndpoint do modeloRecepçãode propostas,valida ao receberNúcleo de domíniopropostas à parte dosregistros verificadosTrilha de auditoria ebanco de dados de registrosNenhuma rota e nenhumacredencial a partir donamespace de inferênciaegress permitidosó a porta de APIProposalentradas
  • Fluxo de dados neste exemplo
Três namespaces. Os pods de inferência podem alcançar o endpoint do modelo e a porta de API da recepção de propostas; nenhuma rota e nenhuma credencial alcança o banco de dados.

Descrição textual. No namespace de inferência, um pod de inferência executa o cliente do modelo e sua fronteira. Ele pode enviar ao endpoint do modelo, no namespace de serviço de modelos, e à recepção de propostas, no namespace de registros, somente pela porta de API desta. A recepção de propostas valida o que recebe e passa uma Proposal ao núcleo de domínio, que grava na trilha de auditoria e no banco de dados de registros. Uma nota afirma que o namespace de inferência não tem rota nem credencial para esse banco de dados.

Os mesmos quatro elementos em toda topologia

  • Tipos distintos. O lado probabilístico consegue construir uma proposta e nada mais. O registro com autoridade é construído apenas pelo código de domínio, a partir de uma proposta somada a algo que o lado probabilístico não consegue produzir.
  • Validação em tempo de execução em todo lado receptor. Um esquema estrito: campos não declarados rejeitados, nenhuma coerção de tipo, vocabulários fechados para valores categóricos, comprimentos limitados. Numa topologia distribuída cada receptor valida, inclusive o lado do domínio quando o remetente é um serviço próprio: “validamos antes de enviar” é uma afirmação sobre outra unidade implantável, possivelmente uma versão mais antiga dela.
  • Procedência no contrato. Declarada, obrigatória e preservada por todo mapeador e serializador no caminho de saída.
  • Uma etapa explícita de promoção. A única rota de uma proposta até um registro com autoridade é uma função, um endpoint ou um comando que exige o que o lado probabilístico não consegue fornecer. Para valores derivados por um modelo de linguagem, o fence público F-03 do COADF exige verificação humana antes que cheguem a uma saída publicada. A própria promoção fica registrada na trilha de auditoria.

Validação determinística em torno de uma saída estocástica

Verificações que leem apenas o valor (sua forma, seu vocabulário, sua unidade, os intervalos que o próprio domínio define) rodam antes que qualquer pessoa olhe para ele. Elas não tornam um valor verdadeiro. Elas tornam impossível um valor impossível, e fazem isso sempre do mesmo jeito, algo em que a pessoa revisora do valor pode se apoiar.

Opções de aplicação, da mais fraca à mais forte

O que cada mecanismo de aplicação detém, e o que não detém
MecanismoDetémNão detém
Separação de tiposPromoção acidental em código que passa na verificação de tiposCasts, tipagem dinâmica, reflexão
Validação de esquema em tempo de execuçãoRespostas malformadas ou que afirmam mais do que deveriamUm valor bem formado e errado
Teste de arquitetura sobre importaçõesO módulo probabilístico importar código que escreve registrosImportações feitas por nome em tempo de execução; caminhos de dados que não são importações
Permissões de banco de dados por componenteUm componente escrever no armazenamento com autoridadeComponentes que compartilham credenciais
Deploy separado e política de redeUm componente com deploy separado sequer alcançar o armazenamentoQualquer coisa dentro de um mesmo processo; clusters cujo plugin de rede não aplica a política

A maioria dos sistemas quer as três primeiras sempre, e as duas últimas quando o componente probabilístico tem deploy próprio. O perfil Python e FastAPI implementa as três primeiras; o perfil Cloud-native acrescenta as duas últimas.

Modos de falha

  1. Saída do modelo escrita direto no armazenamento com autoridade

    A resposta é convertida na entidade que o resto do sistema lê como fato, porque os campos coincidiam. Nenhuma linha isolada está errada. A fronteira simplesmente não existe.

  2. Propostas indistinguíveis de dados verificados

    Uma tabela, um tipo e uma flag que diz qual é qual. A flag assume por padrão o valor conveniente, ou o próprio JSON do modelo consegue defini-la.

  3. Procedência perdida no caminho de saída

    Um mapeador, um modelo de resposta ou uma exportação omite o método e a fonte. Frameworks que filtram a saída por um esquema declarado fazem isso sem ruído algum: o FastAPI filtra uma resposta pelo seu modelo de resposta, e o serializador do Fastify deixa de fora as propriedades que um esquema de resposta não lista, a menos que o esquema permita propriedades adicionais.

  4. Validação apenas na interface do usuário

    O formulário valida. A importação em lote, o script de administração e o segundo cliente, não.

  5. Sistemas a jusante não distinguem inferido de verificado

    O formato de exportação não tem campo para o método, então o sistema seguinte recebe um valor e nada mais, e todo controle que ele tem fica cego para a diferença.

  6. A resposta bruta tratada como confiável sem validação em tempo de execução

    Um cast em TypeScript, um dicionário em Python, um mapeador leniente em Java: o contrato existe nos tipos do código e em nenhum lugar do seu comportamento. As anotações de tipo do TypeScript são apagadas em tempo de compilação, e suas tipagens padrão declaram o resultado de JSON.parse como any.

  7. A coerção esconde o erro do modelo

    Uma análise permissiva transforma "12" em 12 e "true" em True. O número parece certo e nunca foi um número. O modo estrito do Pydantic recusa essa coerção; a configuração padrão do validador do Fastify ativa a coerção de tipos. É preciso saber qual dos dois está rodando.

  8. Reparo silencioso

    A resposta falha na validação, então a chamada é repetida até que uma resposta passe, e só a última é guardada. As falhas eram evidência sobre o modelo, e se perderam.

  9. Validação contornada por desempenho

    Uma otimização que constrói objetos sem validação vira o caminho mais fácil e, depois, o desvio. O model_construct do Pydantic cria um modelo sem validá-lo, exatamente como documentado.

Verificação

  • Teste unitário

    Passa quando: Cada resposta malformada é rejeitada: um campo não declarado, um tipo coercível, uma procedência ausente, um atributo que ninguém pediu.

    Prova de dentes: Apagar uma restrição numa cópia descartável (por exemplo, a regra que rejeita campos não declarados): o teste correspondente precisa falhar.

  • Teste de arquitetura

    Passa quando: O módulo probabilístico não tem caminho de importação até o código que escreve registros com autoridade.

    Prova de dentes: Acrescentar a importação proibida numa cópia descartável: o contrato falha e o build para.

  • Teste de contrato

    Passa quando: Produtor e consumidor concordam sobre o esquema da proposta, com os campos de procedência obrigatórios.

    Prova de dentes: Remover um campo de procedência do esquema do produtor: o teste de contrato do consumidor falha.

  • Teste de integração

    Passa quando: Quando o componente probabilístico tem deploy próprio, suas credenciais não conseguem escrever no armazenamento com autoridade.

    Prova de dentes: Tentar a escrita com essas credenciais: o banco de dados a recusa.

  • Teste de ponta a ponta

    Passa quando: Uma saída cujo atributo veio de uma proposta que ninguém verificou não pode ser publicada.

    Prova de dentes: Plantar uma proposta não verificada e pedir a publicação: recusada, e a recusa está na trilha de auditoria.

Realizações alternativas

  • Interfaces só de sugestão. A saída do modelo é mostrada a uma pessoa como sugestão e nunca armazenada como valor. Simples e forte; abre mão da rastreabilidade do que foi sugerido, a menos que as sugestões também sejam registradas.
  • Um contrato compartilhado e neutro em relação à linguagem (JSON Schema, Protocol Buffers) em vez de modelos nativos da linguagem. Melhor entre linguagens; desloca a questão do rigor para o esquema, onde propriedades adicionais e formatos precisam ser decididos explicitamente.
  • Modos de saída estruturada das APIs de modelos. Reduzem respostas malformadas no produtor. Não dispensam o consumidor de validar, porque o consumidor não consegue verificar como o produtor foi configurado.
  • Armazenamento separado para propostas e registros, duas tabelas ou dois armazenamentos em vez de uma tabela com um status. Mais pesado, e torna a separação visível em toda consulta que alguém escrever.

Limitações

  • A fronteira controla para onde a saída do modelo pode ir. Ela não torna a saída do modelo correta, e um valor bem formado e errado passa em todas as verificações deste padrão.
  • A separação de tipos detém acidentes, não intenção. Quem desenvolve com acesso de escrita ao domínio consegue construir à mão um objeto com autoridade; a revisão de código e a trilha de auditoria são o que torna isso visível.
  • Este padrão não diz quando uma proposta precisa de uma pessoa, nem como a confiança é expressa. Isso pertence ao P-2 e ao P-3, que o COADF publica apenas como princípios.
  • A validação só é tão boa quanto o contrato. Um esquema permissivo, validado com rigor, continua permissivo.

Fontes

COADF Engineering Companion 1.0 · não normativo · corresponde ao COADF Core 2.2

Direitos de publicação reservados. Nenhuma licença pública é concedida, no momento, para o COADF Engineering Companion 1.0 nem para seus exemplos de referência.

Status de propriedade intelectual e de publicação