Ir al contenido

Proyecto independiente de I+D · Colonia

Frontera probabilística

Un componente probabilístico está acotado y no puede convertirse directamente en una salida de dominio autorizada.

No normativo

Versión del Companion
1.0
Corresponde a COADF Core
2.2
Estado
Vigente
Última revisión
Principios de COADF
P-1, P-5

Propiedad de arquitectura

COADF P-1 enuncia el mínimo: un componente probabilístico devuelve un valor junto con una confianza y el método con el que se obtuvo el valor, nunca un valor desnudo, y nunca llega directamente a una salida. Este patrón trata de la segunda mitad, que es la que las implementaciones pierden. La respuesta de un modelo puede entrar en el sistema. Lo que no puede es convertirse, por ningún camino, en aquello que el sistema trata como establecido.

Tienen que cumplirse tres cosas a la vez:

  • La salida tiene un tipo propio. Una propuesta y un registro autorizado son tipos distintos, tablas distintas o mensajes distintos. El código que tiene uno no puede pasarlo donde se espera el otro sin un paso explícito que alguien pueda revisar.
  • La frontera valida en tiempo de ejecución. El contrato se comprueba cuando llega la respuesta, en el proceso que la recibe, diga lo que diga el emisor sobre lo que comprobó.
  • La procedencia viaja con el valor. El método, el modelo y su versión, la versión del prompt y la ubicación en la fuente permanecen unidos a él en cada paso, serialización incluida. Sin ellos, P-4 no puede reconstruir y P-5 no puede declarar.

P-1 también exige que el componente informe una confianza. Cómo se expresa, se asigna y se usa la confianza corresponde a P-2, que COADF publica solo como principio. Este Companion no lo describe, y nada de lo que sigue depende de ello.

Por qué importa

La salida de un modelo procede de un proceso que no puede reproducirse a partir de sus entradas como sí puede la salida de un parser: el muestreo, las actualizaciones del modelo y los cambios de prompt la desplazan. Eso es aceptable para una propuesta e inaceptable para un hecho. El riesgo no es que un modelo se equivoque a veces; todo se equivoca a veces. El riesgo es perder la capacidad de decir qué valores vinieron de dónde, porque todo control posterior depende de ello. Una barrera solo detiene lo que puede ver, una declaración solo nombra lo que está marcado y una persona revisora solo comprueba lo que todavía apunta a su fuente.

La pérdida rara vez es una decisión. Ocurre en una línea de código corriente: una entidad del ORM rellenada con el JSON del modelo porque los nombres de los campos coincidían, un modelo de respuesta que descarta la procedencia porque nadie la añadió, una importación por lotes que evita el formulario donde vivía la validación. El patrón existe para que esa línea no pueda escribirse sin que nadie lo note.

Estrategias de implementación válidas

El aislamiento es arquitectónico, no necesariamente físico

No hacen falta microservicios. La propiedad se cumple cuando ningún camino de código permite al lado probabilístico producir un objeto autorizado, y un solo proceso puede mantenerla tan bien como una red. Conviene elegir la topología por sus propias razones (escalar por separado una carga de inferencia, aislar la biblioteca cliente de un proveedor, desplegar de forma independiente) y después construir la frontera en la forma elegida. Las cuatro figuras siguientes mantienen la misma propiedad en cuatro formas.

Arquitectura de ejemplo · No normativa

Monolito modular

Arquitectura de ejemplo, no normativa: un monolito modular en el que un cliente del modelo, un módulo de frontera, un núcleo de dominio y un adaptador de clasificación comparten un solo proceso, con la traza de auditoría y un servicio externo fuera de él.Dentro de un solo proceso: un cliente del modelo, marcado como probabilístico, pasa su respuesta bruta a un módulo de frontera, que pasa una Proposal al núcleo de dominio. Un adaptador de clasificación, también dentro del proceso, puede pasar un enriquecimiento al núcleo de dominio, y consulta un servicio de clasificación externo, fuera del proceso. El núcleo de dominio escribe entradas en la traza de auditoría, una base de datos aparte. El único camino del cliente del modelo al núcleo de dominio pasa por la frontera.Un proceso, una unidad desplegableCliente del modeloprobabilísticoFronteracontrato tipado,validación,procedenciaNúcleo de dominiopropuestas separadas deregistros verificadosAdaptadorde clasificación,tras un puertoTraza de auditoríade solo inserciónServicio externoclasificaciónrespuesta brutaProposalentradas
  • Flujo de datos en este ejemplo
  • Opcional: puede no estar disponible
Un solo proceso. La frontera es un módulo, y los contratos de importación impiden que el cliente del modelo llegue al núcleo de dominio si no es a través de ella.

Descripción textual. Dentro de un solo proceso: un cliente del modelo, marcado como probabilístico, pasa su respuesta bruta a un módulo de frontera, que pasa una Proposal al núcleo de dominio. Un adaptador de clasificación, también dentro del proceso, puede pasar un enriquecimiento al núcleo de dominio, y consulta un servicio de clasificación externo, fuera del proceso. El núcleo de dominio escribe entradas en la traza de auditoría, una base de datos aparte. El único camino del cliente del modelo al núcleo de dominio pasa por la frontera.

Arquitectura de ejemplo · No normativa

Orientado a servicios

Arquitectura de ejemplo, no normativa: un servicio de inferencia con un cliente del modelo y una frontera, y un servicio de dominio con su propia frontera, núcleo de dominio, adaptador de clasificación y traza de auditoría.Un servicio de inferencia contiene un cliente del modelo, marcado como probabilístico, y una frontera que valida lo que envía. Envía por HTTP, bajo un contrato JSON, a un servicio de dominio, cuya propia frontera valida lo que recibe y pasa una Proposal al núcleo de dominio. El servicio de dominio contiene también un adaptador de clasificación, que consulta un servicio externo y puede pasar un enriquecimiento al núcleo de dominio, y la traza de auditoría, en la que el núcleo de dominio escribe entradas. El servicio de inferencia no tiene ninguna conexión con la traza de auditoría.Servicio de inferenciaServicio de dominio y su almacénCliente del modeloprobabilísticoFronteravalida loque envíaFronteravalida loque recibeNúcleo de dominiopropuestas aparte deregistros verificadosAdaptador declasificaciónTraza de auditoríade solo inserciónServicio externoclasificaciónrespuesta brutaHTTP, JSONProposalentradas
  • Flujo de datos en este ejemplo
  • Opcional: puede no estar disponible
Dos servicios. Cada lado valida: el emisor, lo que envía; el receptor, lo que recibe. El servicio de inferencia no tiene credenciales para el almacén del dominio.

Descripción textual. Un servicio de inferencia contiene un cliente del modelo, marcado como probabilístico, y una frontera que valida lo que envía. Envía por HTTP, bajo un contrato JSON, a un servicio de dominio, cuya propia frontera valida lo que recibe y pasa una Proposal al núcleo de dominio. El servicio de dominio contiene también un adaptador de clasificación, que consulta un servicio externo y puede pasar un enriquecimiento al núcleo de dominio, y la traza de auditoría, en la que el núcleo de dominio escribe entradas. El servicio de inferencia no tiene ninguna conexión con la traza de auditoría.

Arquitectura de ejemplo · No normativa

Orientado a eventos

Arquitectura de ejemplo, no normativa: un worker de inferencia publica propuestas en un tópico, y un consumidor de dominio las valida al recibirlas antes de que el núcleo de dominio escriba entradas de auditoría.Un worker de inferencia contiene un cliente del modelo, marcado como probabilístico, y una frontera. Publica un mensaje en un tópico de propuestas. El cuerpo del mensaje lleva el trace_id de auditoría; sus cabeceras llevan el contexto de ejecución como un traceparent de W3C. Un consumidor de dominio lee el tópico, valida cada mensaje al recibirlo y pasa una Proposal al núcleo de dominio, que escribe entradas en la traza de auditoría.Worker de inferenciaConsumidor de dominioCliente del modeloprobabilísticoFronteravalida antesde publicarTópicopropuestasFronteravalida alrecibirNúcleo de dominiopropuestas aparte deregistros verificadosTraza de auditoríade solo insercióncuerpo: trace_idcabeceras: traceparentpublicarconsumirProposalentradas
  • Flujo de datos en este ejemplo
Un tópico entre los dos lados. El trace_id de auditoría viaja en el cuerpo del mensaje como parte del contrato; el contexto de ejecución viaja en las cabeceras del mensaje.

Descripción textual. Un worker de inferencia contiene un cliente del modelo, marcado como probabilístico, y una frontera. Publica un mensaje en un tópico de propuestas. El cuerpo del mensaje lleva el trace_id de auditoría; sus cabeceras llevan el contexto de ejecución como un traceparent de W3C. Un consumidor de dominio lee el tópico, valida cada mensaje al recibirlo y pasa una Proposal al núcleo de dominio, que escribe entradas en la traza de auditoría.

Arquitectura de ejemplo · No normativa

Despliegue nativo de la nube

Arquitectura de ejemplo, no normativa: un namespace de inferencia, un namespace de servicio de modelos y un namespace de registros, con salida desde inferencia permitida solo hacia el endpoint del modelo y hacia la recepción de propuestas.En el namespace de inferencia, un pod de inferencia ejecuta el cliente del modelo y su frontera. Puede enviar al endpoint del modelo, en el namespace de servicio de modelos, y a la recepción de propuestas, en el namespace de registros, solo por su puerto de API. La recepción de propuestas valida lo que recibe y pasa una Proposal al núcleo de dominio, que escribe en la traza de auditoría y la base de datos de registros. Una nota indica que el namespace de inferencia no tiene ninguna ruta ni ninguna credencial hacia esa base de datos.Namespace: inferenciaNamespace: servicio de modelosNamespace: registrosPod de inferenciacliente del modeloy fronteraEndpoint del modeloRecepción de propuestasvalidaal recibirNúcleo de dominiopropuestas aparte deregistros verificadosTraza de auditoría ybase de datos de registrosNi ruta nicredencial desde elnamespace de inferenciasalida permitidasolo puerto APIProposalentradas
  • Flujo de datos en este ejemplo
Tres namespaces. Los pods de inferencia pueden llegar al endpoint del modelo y al puerto de API de la recepción de propuestas; ninguna ruta ni ninguna credencial llega a la base de datos.

Descripción textual. En el namespace de inferencia, un pod de inferencia ejecuta el cliente del modelo y su frontera. Puede enviar al endpoint del modelo, en el namespace de servicio de modelos, y a la recepción de propuestas, en el namespace de registros, solo por su puerto de API. La recepción de propuestas valida lo que recibe y pasa una Proposal al núcleo de dominio, que escribe en la traza de auditoría y la base de datos de registros. Una nota indica que el namespace de inferencia no tiene ninguna ruta ni ninguna credencial hacia esa base de datos.

Los mismos cuatro elementos en cada topología

  • Tipos distintos. El lado probabilístico puede construir una propuesta y nada más. El registro autorizado lo construye solo el código de dominio, a partir de una propuesta y de algo que el lado probabilístico no puede producir.
  • Validación en tiempo de ejecución en cada lado receptor. Un esquema estricto: campos no declarados rechazados, sin conversión de tipos, vocabularios cerrados para los valores categóricos, longitudes acotadas. En una topología distribuida valida cada receptor, también el lado del dominio cuando el emisor es un servicio propio: “validamos antes de enviar” es una afirmación sobre otro desplegable, quizá sobre una versión anterior de él.
  • La procedencia en el contrato. Declarada, obligatoria y preservada por cada mapeador y serializador en el camino de salida.
  • Un paso de promoción explícito. La única vía de la propuesta al registro autorizado es una función, un endpoint o un comando que exige lo que el lado probabilístico no puede aportar. Para los valores derivados por un modelo de lenguaje, el fence público F-03 de COADF exige verificación humana antes de que lleguen a una salida publicada. La propia promoción queda registrada en la traza de auditoría.

Validación determinista en torno a una salida estocástica

Las comprobaciones que leen solo el valor (su forma, su vocabulario, su unidad, los rangos que define el propio dominio) se ejecutan antes de que ninguna persona lo mire. No hacen verdadero un valor. Hacen imposible un valor imposible, y lo hacen siempre de la misma manera, algo en lo que puede apoyarse la persona que revisa el valor.

Opciones de aplicación, de la más débil a la más fuerte

Qué detiene cada mecanismo de aplicación y qué no
MecanismoDetieneNo detiene
Separación de tiposLa promoción accidental en código que supera la comprobación de tiposCasts, tipado dinámico, reflexión
Validación de esquemas en tiempo de ejecuciónRespuestas mal formadas o que afirman de másUn valor bien formado que es erróneo
Prueba de arquitectura sobre las importacionesQue el módulo probabilístico importe código que escribe registrosImportaciones hechas por nombre en tiempo de ejecución; caminos de datos que no son importaciones
Permisos de base de datos por componenteQue un componente escriba en el almacén autorizadoComponentes que comparten credenciales
Despliegue separado y política de redQue un componente desplegado por separado llegue siquiera al almacénCualquier cosa dentro de un mismo proceso; clústeres cuyo plugin de red no aplica la política

La mayoría de los sistemas quiere los tres primeros siempre, y los dos últimos cuando el componente probabilístico se despliega por separado. El perfil de Python y FastAPI implementa los tres primeros; el perfil cloud-native añade los dos últimos.

Modos de fallo

  1. La salida del modelo se escribe directamente en el almacenamiento autorizado

    La respuesta se convierte en la entidad que el resto del sistema lee como hecho, porque los campos coincidían. Ninguna línea concreta es errónea. La frontera, sencillamente, no existe.

  2. Propuestas indistinguibles de datos verificados

    Una tabla, un tipo y un indicador que dice qué es cada cosa. El indicador toma por defecto el valor cómodo, o el propio JSON del modelo puede fijarlo.

  3. La procedencia se pierde en el camino de salida

    Un mapeador, un modelo de respuesta o una exportación omite el método y la fuente. Los frameworks que filtran la salida según un esquema declarado lo hacen sin ruido: FastAPI filtra una respuesta según su modelo de respuesta, y el serializador de Fastify omite las propiedades que un esquema de respuesta no enumera salvo que el esquema admita propiedades adicionales.

  4. Validación solo en la interfaz de usuario

    El formulario valida. La importación por lotes, el script de administración y el segundo cliente, no.

  5. Los sistemas posteriores no distinguen lo inferido de lo verificado

    El formato de exportación no tiene campo para el método, así que el sistema siguiente recibe un valor y nada más, y todos sus controles son ciegos a la diferencia.

  6. Se confía en la respuesta en bruto sin validación en tiempo de ejecución

    Un cast en TypeScript, un diccionario en Python, un mapeador permisivo en Java: el contrato existe en los tipos del código y en ninguna parte de su comportamiento. Las anotaciones de tipo de TypeScript se borran en la compilación, y sus tipados estándar declaran el resultado de JSON.parse como any.

  7. La conversión de tipos oculta el error del modelo

    Un análisis laxo convierte "12" en 12 y "true" en True. El número parece correcto y nunca fue un número. El modo estricto de Pydantic rechaza esa conversión; la configuración por defecto del validador de Fastify activa la conversión de tipos. Hay que saber cuál de los dos se está ejecutando.

  8. Reparación silenciosa

    La respuesta no supera la validación, así que se repite la llamada hasta que una respuesta la supera, y solo se conserva la última. Los fallos eran evidencia sobre el modelo, y han desaparecido.

  9. Validación omitida por velocidad

    Una optimización que construye objetos sin validar se convierte en el camino más fácil, y después en el atajo. model_construct de Pydantic crea un modelo sin validarlo, exactamente como está documentado.

Verificación

  • Prueba unitaria

    Pasa cuando: Cada respuesta mal formada se rechaza: un campo no declarado, un tipo convertible, una procedencia ausente, un atributo que nadie pidió.

    Prueba de dientes: Se elimina una restricción en una copia de trabajo (por ejemplo, la regla que rechaza campos no declarados): la prueba correspondiente tiene que fallar.

  • Prueba de arquitectura

    Pasa cuando: El módulo probabilístico no tiene ningún camino de importación hacia el código que escribe registros autorizados.

    Prueba de dientes: Se añade la importación prohibida en una copia de trabajo: el contrato falla y la compilación se detiene.

  • Prueba de contrato

    Pasa cuando: Productor y consumidor coinciden en el esquema de la propuesta, con los campos de procedencia obligatorios.

    Prueba de dientes: Se quita un campo de procedencia del esquema del productor: la prueba de contrato del consumidor falla.

  • Prueba de integración

    Pasa cuando: Cuando el componente probabilístico se despliega por separado, sus credenciales no pueden escribir en el almacén autorizado.

    Prueba de dientes: Se intenta la escritura con esas credenciales: la base de datos la rechaza.

  • Prueba de extremo a extremo

    Pasa cuando: No puede publicarse una salida cuyo atributo procede de una propuesta que nadie verificó.

    Prueba de dientes: Se planta una propuesta sin verificar y se solicita la publicación: rechazada, y el rechazo figura en la traza de auditoría.

Realizaciones alternativas

  • Interfaces solo de sugerencia. La salida del modelo se muestra a una persona como sugerencia y nunca se almacena como valor. Sencillo y robusto; renuncia a la trazabilidad de lo sugerido salvo que también se registren las sugerencias.
  • Un contrato compartido y neutral respecto del lenguaje (JSON Schema, Protocol Buffers) en lugar de modelos nativos de cada lenguaje. Mejor entre lenguajes; traslada la cuestión de la estrictez al esquema, donde las propiedades adicionales y los formatos tienen que decidirse de forma explícita.
  • Modos de salida estructurada de las API de modelos. Reducen las respuestas mal formadas en el productor. No eximen al consumidor de validar, porque el consumidor no puede verificar cómo se configuró el productor.
  • Almacenamiento separado para propuestas y registros, dos tablas o dos almacenes en lugar de una tabla con un estado. Más pesado, y hace visible la separación en cada consulta que cualquiera escriba.

Limitaciones

  • La frontera controla adónde puede ir la salida del modelo. No hace correcta la salida del modelo, y un valor erróneo bien formado supera todas las comprobaciones de este patrón.
  • La separación de tipos detiene accidentes, no intenciones. Quien tiene acceso de escritura al dominio puede construir a mano un objeto autorizado; la revisión de código y la traza de auditoría son lo que lo hace visible.
  • Este patrón no dice cuándo una propuesta necesita a una persona ni cómo se expresa la confianza. Eso corresponde a P-2 y P-3, que COADF publica solo como principios.
  • La validación vale lo que vale el contrato. Un esquema permisivo, validado de forma estricta, sigue siendo permisivo.

Fuentes

COADF Engineering Companion 1.0 · no normativo · corresponde a COADF Core 2.2

Derechos de publicación reservados. Por ahora no se concede ninguna licencia pública para el COADF Engineering Companion 1.0 ni para sus ejemplos de referencia.

Estado de propiedad intelectual y de publicación