Flujos / JevModel
API de detección de spam para formularios y comentarios: Turnstile, Akismet o una capa de decisión Jev
Dónde encaja un desafío (Cloudflare Turnstile), un servicio de reputación antispam (Akismet) y una comprobación tipada Jev Choice/Noul frente al spam de formularios, comentarios y registros, con una cola de cuarentena en lugar de borrados silenciosos.
Última actualización:
Respuesta breve: tres capas, y Jev es solo la última
- El spam de formularios y comentarios es de tres tipos: envíos automáticos de bots, patrones de spam conocidos y contenido escrito por personas que igualmente no quieres (ofertas fuera de tema, enlaces). Cada uno pide una herramienta distinta.
- Capa de desafío: Cloudflare Turnstile solo protege un formulario si tu servidor valida cada token con la API Siteverify; los tokens valen 300 segundos y se validan una sola vez.
- Capa de reputación: comment-check de Akismet recibe api_key, blog y user_ip (obligatorios) más campos de contenido y autor, y responde "true" (spam) o "false"; cualquier otra respuesta es un error, no un veredicto.
- Capa de decisión: JevModel solo lee el texto que envías y devuelve respuestas tipadas, como un Choice entre real_inquiry / sales_pitch / spam y una probabilidad Noul de “necesita que lo mire una persona”. No tiene reputación de IP ni base compartida de spam, así que úsalo tras las dos primeras capas y pon en cuarentena en vez de borrar.
Tres tipos de spam en formularios y comentarios
“API de detección de spam” abarca problemas distintos, y mezclarlos es como se borran leads reales. Primero, los envíos automáticos: scripts que rellenan cualquier formulario. Lo mejor es frenarlos antes de leer el texto, con un desafío como Cloudflare Turnstile. Segundo, el spam conocido: mensajes y remitentes que coinciden con patrones vistos en muchos sitios, para lo que existe un servicio de reputación como Akismet. Tercero, mensajes escritos por personas que igualmente no quieres: una venta en frío por tu formulario de contacto, una agencia SEO bajo un artículo, un registro cuya bio es solo un enlace. Pasan el desafío porque los envía una persona y pueden no parecer spam clásico, así que la decisión depende de tu propia política. Solo en este tercer tipo aporta algo un modelo de decisión de texto como Jev. Esta guía trata formularios, comentarios y registros; para el spam de la bandeja de entrada, deja el filtrado a tu proveedor de correo, como explica la guía de clasificación de emails.
Use Jev for review queuesClasificación de emails con IA: reglas, prompts LLM o una API de decisión tipada para el correo entranteScore leads on a useful rubricCapa 1: bloquear envíos automáticos con Cloudflare Turnstile
Turnstile coloca un widget en el formulario que genera un token, y la documentación de Cloudflare deja claro que la validación en el servidor es obligatoria: el widget del cliente por sí solo no protege nada. Tu handler envía POST https://challenges.cloudflare.com/turnstile/v0/siteverify con tu clave secreta y el token (la IP del visitante es opcional) y lee el campo success del JSON. Los tokens valen 300 segundos, solo se validan una vez (repetir devuelve timeout-or-duplicate) y tienen como máximo 2048 caracteres. Rechaza el envío si la validación falla, antes de gastar nada más en él. Esta capa no dice nada sobre el significado del mensaje; solo responde si una sesión de navegador superó el desafío.
Capa 2: comprobar spam conocido con Akismet
El endpoint comment-check de Akismet, POST https://rest.akismet.com/1.1/comment-check, recibe campos form-encoded. api_key, blog (la URL de tu sitio) y user_ip son obligatorios; comment_content, comment_author, comment_author_email, user_agent y comment_type son opcionales, y la documentación de Akismet dice que más datos suelen dar más precisión. comment_type no se limita a comentarios de blog: los valores documentados incluyen comment, forum-post, reply, contact-form, signup y message. El cuerpo de respuesta es la cadena literal "true" para spam o "false" para no spam; cualquier otra cosa, como "invalid", es un error y puede llegar con HTTP 200, así que no la trates como veredicto. La cabecera X-akismet-pro-tip: discard marca spam evidente que puedes descartar sin revisar. Para pruebas, Akismet documenta comment_author akismet-guaranteed-spam (siempre spam), user_role administrator (nunca spam) e is_test=1 para marcar las llamadas de prueba.
Evaluate a Jev workflowCapa 3: una decisión Jev para mensajes humanos pero no deseados
Lo que queda tras las capas 1 y 2 es sobre todo una cuestión de política: ¿es una consulta real, una venta o spam según tu definición? JevModel lo responde con salida tipada. Envías el mensaje como state y haces preguntas con nombre: un Choice cuyos criteria definen real_inquiry, sales_pitch y spam con tus palabras, y una pregunta Noul (sí/no) como “una persona debería mirarlo antes de descartarlo”. La respuesta trae el label elegido con una probabilidad por label y una probabilidad para el Noul, con las que puedes enrutar. Ten claro lo que esta capa no es. Jev solo lee el state que envías: no tiene reputación de IP ni de remitente, ni base compartida de spam visto en otros sitios, y JevModel no entrena un modelo con tus reportes; no ofrece entrenamiento personalizado. No sustituye a un desafío ni a Akismet, y no debería ser la única razón para borrar un mensaje.
Choice, Score, and NoulJev probability, confidence and human-review thresholdsClasificación de intención en texto de producto y soporte: reglas, LLM y APIs tipadasTurnstile vs Akismet vs Jev: qué responde cada capa
La tabla compara entradas y contratos de salida según la documentación de cada proveedor. No es un benchmark de precisión; mide cualquier capa con tus propios envíos.
Jev or rules?How to classify text with the JevModel API| Dimensión | Cloudflare Turnstile | Akismet | JevModel (Jev) |
|---|---|---|---|
| Pregunta que responde | ¿Superó esta sesión de navegador un desafío? | ¿Parecen spam conocido este contenido y remitente? | ¿Qué label tuyo encaja con este texto según tus definiciones? |
| Entrada | Token del widget + clave secreta (IP opcional) | api_key, blog, user_ip obligatorios; contenido, autor y tipo opcionales | Solo el state que envías y preguntas con nombre |
| Salida | JSON con success y códigos de error | "true" / "false"; otras respuestas son errores; posible aviso discard | Respuestas tipadas: Choice con probabilidad por label, probabilidad Noul, Score |
| Señales más allá del texto | Sí, señales del desafío del navegador | Sí, la IP y los campos de remitente que pasas | No, nada fuera del state |
| Mejor lugar en el flujo | Primero: rechazar antes de leer | Segundo: descartar o marcar spam conocido | Último: repartir lo que queda en tus colas |
Ejemplo de código: un handler de formulario de contacto con decisión Jev
El esbozo siguiente se ejecuta después de que Turnstile y Akismet hayan dejado pasar el envío. Manda el mensaje como state de tipo objeto, para que el modelo vea qué es cada campo, y hace dos preguntas en una petición: un Choice sobre el tipo de mensaje y un Noul sobre si una persona debe revisarlo. Sigue el contrato documentado: POST /api/v1/systemone con una clave Bearer de una cuenta verificada, state más preguntas con nombre, y una respuesta con code 0 y data.answers. No hay campo model porque el sitio siempre llama a typesafe/jev-1.13 vía OpenRouter. La API no tiene clave de idempotencia, así que no reintentes una petición que quizá ya tuvo éxito; una ejecución fallida se reembolsa. Envía solo los campos que la decisión necesita: nombre, email y teléfono no suelen aportar nada a “¿es una venta?”.
JevModel API: request and responseChoice, Score, and NoulAI Decision Flows with Jev and human review// Illustrative only. Runs after Turnstile and Akismet have passed the submission.
// JEVMODEL_API_KEY comes from JevModel Console -> API keys (verified account).
async function decide(form) {
const res = await fetch("https://jevmodel.app/api/v1/systemone", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.JEVMODEL_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
// Send only what the decision needs; no name, email or phone.
state: { form: "contact", subject: form.subject, message: form.message },
questions: {
kind: {
type: "choice",
instructions: "What kind of contact-form message is this, by our definitions?",
criteria: {
real_inquiry: "A person asking about our product, an order, or working with us as a customer.",
sales_pitch: "Someone selling us a service: SEO, leads, development, marketing.",
spam: "Gibberish, link dropping, scams, or text unrelated to any business purpose.",
},
},
review: {
type: "noul",
instructions: "Should a person read this before it is moved out of the inbox?",
criteria: {
true: "It might be a real customer or partner, or the intent is unclear.",
false: "It is clearly an unsolicited pitch or spam.",
},
},
},
}),
});
const body = await res.json();
if (body.code !== 0) return { route: "inbox", reason: body.message }; // fail open
const { kind, review } = body.data.answers;
return {
kind: kind.choice,
probabilities: kind.probabilities,
needsReview: review.noul, // probability that the answer is true
};
}
Enrutado: cuarentena, no borrado
Un falso positivo en un formulario de contacto es un cliente perdido del que nunca sabrás, así que diseña el enrutado en torno a eso. Una política viable: real_inquiry va a la bandeja o al CRM como siempre; spam con baja probabilidad de revisión va a una carpeta de cuarentena que alguien repasa periódicamente; sales_pitch va a su propia carpeta y no a la papelera; todo lo que tenga alta probabilidad de revisión, o donde ningún label gane con claridad, va a la bandeja con una etiqueta. Si la llamada a Jev falla (code distinto de cero, timeout, INSUFFICIENT_TOKENS), deja pasar y entrega el mensaje; un filtro que se come leads cuando está caído es peor que ninguno. Fija los umbrales con tus datos: etiqueta a mano unos cientos de envíos pasados, pásalos por las mismas preguntas y elige el punto donde las cuarentenas erróneas sean lo bastante raras para ti. La confianza Choice que describe TypeSafe, (p − 1/n)/(1 − 1/n), ajusta por el número de labels pero no es precisión calibrada. Vuelve a comprobar tras cambiar definiciones.
Jev probability, confidence and human-review thresholdsEvaluate a Jev workflowAI Decision Flows with Jev and human reviewLista de comprobación antes de activarlo
1) Valida en el servidor el token de Turnstile en cada envío; nunca confíes solo en el widget. 2) Trata cualquier respuesta de Akismet distinta de "true" o "false" como error, y usa is_test=1 y los valores de prueba documentados mientras desarrollas. 3) Escribe los criteria de Jev con tus palabras, con ejemplos reales de ofertas que no quieres, y mantén un label de consultas reales al menos igual de específico. 4) Quita los campos personales que la decisión no necesita. 5) Pon en cuarentena en vez de borrar, y deja pasar cuando una capa no esté disponible. 6) Etiqueta a mano una muestra, mide las cuarentenas erróneas y vuelve a medir tras cada cambio; no publiques una cifra de precisión que no hayas medido. 7) Presupuesta tokens: cada envío que llega a la capa 3 es una petición normal, y las cuentas verificadas empiezan con 100.000 tokens gratis. Para moderar publicaciones con cola de revisión, ve content-moderation; para puntuar leads reales, ve lead-scoring.
Use Jev for review queuesScore leads on a useful rubricJevModel pricing and free Jev runsPrivate runs and historyClasificación de emails con IA: reglas, prompts LLM o una API de decisión tipada para el correo entranteClasificación de intención en texto de producto y soporte: reglas, LLM y APIs tipadasJev probability, confidence and human-review thresholdsEvaluate a Jev workflowJevModel API: request and responsePreguntas frecuentes
¿Puede Jev sustituir a Akismet como API de detección de spam?
No. Akismet usa la IP y los campos de remitente que le pasas y patrones de spam que ve en muchos sitios; Jev solo lee el texto que envías y no tiene base compartida de spam ni reputación de IP. Úsalo después de un desafío y una comprobación de reputación, para la cuestión de política de si un mensaje humano es una consulta real, una venta o spam según tus definiciones.
¿Debo usar Jev para filtrar spam de correo?
No. Deja el filtrado de spam de la bandeja a tu proveedor de correo, que ve señales de autenticación y reputación del remitente que Jev no ve. Jev sirve después de la entrega, para enrutar correo legítimo a tus colas; ve la guía de clasificación de emails.
¿Cómo evito borrar leads reales?
Pon en cuarentena en vez de borrar, da a las ventas su propia carpeta, manda a una persona todo lo que tenga alta probabilidad de revisión y deja pasar cuando una capa falle. Fija los umbrales con una muestra etiquetada a mano de tus envíos pasados y revísalos tras cambiar definiciones.
¿JevModel ve la IP del visitante o aprende de mis reportes de spam?
Solo ve el state que envías. Si no incluyes IP, email o nombre, JevModel no los tiene. No hay endpoint de feedback para reportes de spam ni entrenamiento personalizado; mejora los resultados afinando las definiciones de labels. Las ejecuciones quedan en tu historial, y la guía de privacidad explica cómo eliminarlas.
JevModel es independiente y no está afiliado a TypeSafe AI.