ワークフロー / JevModel
フォームとコメントのスパム検出API:Turnstile、Akismet、それともJevの判断レイヤー
お問い合わせフォーム、コメント、登録のスパムに対し、チャレンジ(Cloudflare Turnstile)、スパム評価サービス(Akismet)、型付きJev Choice/Noul判定がそれぞれどこに合うか。黙って削除せず隔離キューへ。
最終更新:
要点:3つのレイヤーがあり、Jevは最後の1つだけ
- フォームやコメントのスパムは3種類です。ボットによる自動送信、既知のスパムパターン、そして人が書いたが不要な内容(無関係な売り込み、リンク投下)。それぞれ別の道具が必要です。
- チャレンジ層:Cloudflare Turnstileがフォームを守るのは、サーバーが各トークンをSiteverify APIで検証したときだけです。トークンの有効期間は300秒で、検証は1回限りです。
- 評価層:Akismetのcomment-checkはapi_key、blog、user_ip(必須)と本文・投稿者の項目を受け取り、"true"(スパム)か"false"を返します。それ以外の応答はエラーで、判定ではありません。
- 判断層:JevModelは送ったテキストだけを読み、型付きの回答を返します。たとえばreal_inquiry/sales_pitch/spamのChoiceと、「人が見るべきか」のNoul確率。IP評価や共有スパムDBはないので、前の2層の後に置き、削除ではなく隔離してください。
フォームとコメントのスパムは3種類
「スパム検出API」は別々の問題をまとめた言葉で、混同すると本物の見込み客を消してしまいます。1つ目は自動送信。見つけたフォームを片端から埋めるスクリプトで、Cloudflare Turnstileのようなチャレンジで本文を読む前に止めるのが最善です。2つ目は既知のスパム。多くのサイトで見られたパターンに合うメッセージや送信者で、Akismetのような評価サービスの得意分野です。3つ目は、人が書いたがそれでも不要なメッセージ。お問い合わせフォームからの飛び込み営業、ブログ記事へのSEO代行の売り込み、リンクだけのプロフィールでの登録などです。人が送るのでチャレンジを通り、典型的なスパムにも見えないことがあるため、判断はあなた自身のポリシー次第です。Jevのようなテキスト判断モデルが役立つのはこの3つ目だけです。本ガイドはフォーム、コメント、登録が対象です。受信箱のスパムはメール事業者のフィルターに任せてください(メール分類ガイド参照)。
Jev でコンテンツの確認待ちを整理するAIによるメール分類:受信メールにはルール、LLMプロンプト、型付き意思決定APIのどれを使うかJev の明確な尺度で見込み客を評価するレイヤー1:Cloudflare Turnstileで自動送信を止める
Turnstileはフォームにウィジェットを置いてトークンを発行します。Cloudflareのドキュメントはサーバー側検証が必須だと明記しており、クライアントのウィジェットだけでは何も守れません。ハンドラーはシークレットキーとトークン(訪問者IPは任意)をhttps://challenges.cloudflare.com/turnstile/v0/siteverifyへPOSTし、JSONのsuccessを読みます。トークンの有効期間は300秒、検証は1回限り(再利用はtimeout-or-duplicate)、長さは最大2048文字です。検証に失敗したら、ほかのコストをかける前に送信を拒否します。このレイヤーはメッセージの意味には関知せず、ブラウザセッションがチャレンジを通過したかだけを答えます。
レイヤー2:Akismetで既知のスパムを確認する
Akismetのcomment-checkエンドポイントはPOST https://rest.akismet.com/1.1/comment-checkで、フォームエンコードの項目を受け取ります。api_key、blog(サイトのURL)、user_ipが必須で、comment_content、comment_author、comment_author_email、user_agent、comment_typeは任意です。Akismetのドキュメントは、データが多いほど一般に精度が上がるとしています。comment_typeはブログコメントに限らず、comment、forum-post、reply、contact-form、signup、messageなどが記載されています。応答本文は、スパムなら文字列"true"、そうでなければ"false"です。"invalid"などそれ以外はエラーで、HTTP 200で返ることもあるため判定として扱わないでください。X-akismet-pro-tip: discardヘッダーは、レビューせず捨ててよい明白なスパムを示します。テスト用には、comment_authorにakismet-guaranteed-spam(必ずスパム)、user_roleにadministrator(必ず非スパム)、そしてテスト呼び出しを示すis_test=1が記載されています。
Evaluate a Jev workflowレイヤー3:人が書いたが不要なメッセージをJevで判断する
レイヤー1と2を通った後に残るのは、ほぼポリシーの問題です。あなたの定義で、これは本物の問い合わせか、売り込みか、スパムか。JevModelはこれを型付きの出力で答えます。メッセージをstateとして送り、名前付きの質問を投げます。criteriaでreal_inquiry、sales_pitch、spamを自分の言葉で定義するChoiceと、「捨てる前に人が見るべき」といったNoul(はい/いいえ)の質問です。応答には選ばれたラベル、ラベルごとの確率、Noulの確率が含まれ、それでルーティングできます。このレイヤーが何でないかも明確にしておきます。Jevは送ったstateだけを読みます。IPや送信者の評価も、他サイトで見たスパムの共有データベースもなく、JevModelがあなたの報告でモデルを学習することもありません。カスタム学習も提供していません。チャレンジやAkismetの代わりにはならず、メッセージを削除する唯一の理由にもすべきではありません。
Choice, Score, and NoulJev probability, confidence and human-review thresholdsプロダクト/サポート文のインテント分類:ルール、LLM、型付きAPITurnstile・Akismet・Jevの比較:各レイヤーが答えること
この表は各社ドキュメントにある入力と出力の契約を比べたもので、精度のベンチマークではありません。どのレイヤーも自分の送信データで測ってください。
Jev or rules?How to classify text with the JevModel API| 観点 | Cloudflare Turnstile | Akismet | JevModel(Jev) |
|---|---|---|---|
| 答える問い | このブラウザセッションはチャレンジを通過したか | 内容と送信者は既知のスパムに見えるか | あなたの定義で、このテキストはどのラベルか |
| 入力 | ウィジェットのトークン+シークレットキー(訪問者IPは任意) | api_key・blog・user_ipが必須、本文・投稿者・種類は任意 | 送ったstateと名前付きの質問だけ |
| 出力 | successとエラーコードを含むJSON | "true"/"false"、それ以外はエラー、discardの指示が付く場合あり | 型付き回答:ラベル別確率付きChoice、Noul確率、Score |
| テキスト以外のシグナル | はい、ブラウザのチャレンジ信号 | はい、渡したIPと送信者の項目 | いいえ、state以外は使わない |
| フロー内の最適な位置 | 最初:読む前に拒否 | 2番目:既知のスパムを捨てる・印を付ける | 最後:残りを自分のキューに振り分ける |
コード例:Jev判定付きのお問い合わせフォームハンドラー
以下のスケッチは、TurnstileとAkismetが送信を通した後に動きます。メッセージをオブジェクト形式のstateで送るので、モデルはどの項目が何かを把握でき、1回のリクエストで2つの質問をします。メッセージの種類を問うChoiceと、人がレビューすべきかを問うNoulです。ドキュメントどおりの契約に従います。認証済みアカウントのBearerキーでPOST /api/v1/systemoneし、stateと名前付きの質問を送り、code 0とdata.answersを含む応答を受け取ります。本サイトは常にOpenRouter経由でtypesafe/jev-1.13を呼ぶため、modelフィールドはありません。APIに冪等キーはないので、成功した可能性のあるリクエストは再試行しないでください。失敗した実行は返金されます。送るのは判断に必要な項目だけにします。名前、メール、電話番号は「売り込みかどうか」の判断にたいてい役立ちません。
JevModel API:リクエストと応答Choice, Score, and NoulJev AI Decision Flows と人による確認// 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
};
}
ルーティング:削除せず隔離する
お問い合わせフォームでの誤判定は、気づくこともない失注です。ルーティングはそれを前提に設計します。実用的なポリシーの例:real_inquiryは通常どおり受信箱やCRMへ。レビュー確率の低いspamは隔離フォルダーへ送り、定期的に人が目を通す。sales_pitchはゴミ箱ではなく専用フォルダーへ。レビュー確率が高いもの、どのラベルもはっきり勝っていないものはタグを付けて受信箱へ。Jevの呼び出しが失敗したら(0以外のcode、タイムアウト、INSUFFICIENT_TOKENS)、通してメッセージを届けます。止まったときに見込み客を飲み込むスパムフィルターは、ないより悪いからです。しきい値は自分のデータで決めます。過去の送信数百件に人手でラベルを付け、同じ質問で実行し、誤隔離が許容できるほど少なくなる点を選びます。TypeSafeが説明するChoiceの信頼度(p − 1/n)/(1 − 1/n)はラベル数を補正しますが、較正された精度ではありません。定義を変えたら再確認してください。
Jev probability, confidence and human-review thresholdsEvaluate a Jev workflowJev AI Decision Flows と人による確認有効にする前のチェックリスト
1)すべての送信でTurnstileトークンをサーバー側で検証し、ウィジェットだけを信用しない。2)Akismetの応答が"true"か"false"以外ならエラーとして扱い、開発中はis_test=1とドキュメントのテスト値を使う。3)Jevのcriteriaは自分の言葉で書き、不要な売り込みの実例を入れ、本物の問い合わせのラベルも同じくらい具体的にする。4)判断に不要な個人情報の項目は除く。5)削除ではなく隔離し、どのレイヤーが使えなくても通す。6)サンプルに人手でラベルを付けて誤隔離を測り、変更後に測り直す。測っていない精度の数字は公表しない。7)トークンの予算:レイヤー3まで届いた送信は1件ごとに通常の1リクエストで、認証済みアカウントは100,000トークン無料から始まります。投稿のモデレーションとレビューキューはcontent-moderation、本物の見込み客のスコアリングはlead-scoringを参照してください。
Jev でコンテンツの確認待ちを整理するJev の明確な尺度で見込み客を評価するJevModel の料金と Jev 無料枠Private runs and historyAIによるメール分類:受信メールにはルール、LLMプロンプト、型付き意思決定APIのどれを使うかプロダクト/サポート文のインテント分類:ルール、LLM、型付きAPIJev probability, confidence and human-review thresholdsEvaluate a Jev workflowJevModel API:リクエストと応答よくある質問
JevはスパムAPIとしてAkismetの代わりになりますか?
いいえ。Akismetは渡されたIPや送信者の項目と、多くのサイトで見たスパムのパターンを使います。Jevは送ったテキストだけを読み、共有スパムDBもIP評価もありません。Jevはチャレンジと評価チェックの後に置き、人が書いたメッセージがあなたの定義で本物の問い合わせか、売り込みか、スパムかというポリシーの問いに使ってください。
メールのスパムフィルターにJevを使うべきですか?
いいえ。受信箱のスパム対策はメール事業者に任せてください。事業者はJevが見られない送信者認証や評価のシグナルを見ています。Jevが役立つのは配信後、正当なメールを自分のキューに振り分ける場面です。メール分類ガイドを参照してください。
本物の見込み客を消さないためには?
削除ではなく隔離し、売り込みは専用フォルダーへ、レビュー確率の高いものは人に回し、どこかのレイヤーでエラーが出たら通します。しきい値は自分の過去の送信に人手でラベルを付けたサンプルで決め、定義を変えたら再確認します。
JevModelは訪問者のIPを見たり、スパム報告から学習したりしますか?
見えるのは送ったstateだけです。IP、メール、名前を入れなければ、JevModelはそれらを持ちません。スパム報告のフィードバック用エンドポイントもカスタム学習もないので、結果はラベル定義を磨いて改善します。実行は履歴に残り、削除方法はプライバシーガイドにあります。
JevModel は独立したプロジェクトで、TypeSafe AI とは提携していません。