claimcheck-rules / python /deploy.md
NagaYu's picture
Add the Python reference implementation (Gradio UI + REST API) for self-hosting
0675e3e verified
|
Raw
History Blame Contribute Delete
15.6 kB

ClaimCheck デプロイ手順

Hugging Face Spaces の無料枠(CPU basic)に、コピペで配置するための手順です。 所要時間は 5〜10 分。GPU も課金設定も不要です。


1. Space を新規作成する

https://huggingface.co/new-space を開き、次のとおり設定します。

項目 値
Owner 自分のユーザー名(または組織)
Space name ClaimCheck(任意)
License apache-2.0
Select the Space SDK Gradio
Space hardware CPU basic · 2 vCPU · 16GB · FREE
Visibility Public / Private どちらでも可

「Create Space」を押すと、空のリポジトリができます。 このあと README.md を push すると、その先頭の YAML frontmatter が Space 設定を上書きするので、ここでテンプレートを選ぶ必要はありません。


2. clone → 4ファイル配置 → push

YOUR_NAME と ClaimCheck を自分のものに置き換えて、まとめて実行します。 Git の認証には、write 権限を付けた アクセストークン を使ってください(パスワード欄にトークンを貼ります)。

git clone https://huggingface.co/spaces/YOUR_NAME/ClaimCheck
cd ClaimCheck

作成した 4 ファイル(app.py / requirements.txt / README.md / deploy.md)をこのディレクトリにコピーしてから:

git add app.py requirements.txt README.md deploy.md && git commit -m "Add ClaimCheck: LLM answer verification gate" && git push

push の直後から Space がビルドを始めます。ログは Space ページの「Logs」タブで見られます。 依存は 3 つだけなので、通常 1〜2 分で Running になります。

大きなファイルは置かないこと。 モデルもデータセットも同梱しません。検証は全てローカルの決定的処理です。

ローカルで先に動かして確認したい場合

pip install -r requirements.txt && python app.py

http://127.0.0.1:7860 が開きます。Spaces 上と同じ挙動です。


3. Secrets に HF_TOKEN を設定する(任意)

これは任意です。設定しなくても全機能が動きます。

設定すると、Enrichment(文脈と応答の関連度を補助スコアとして取得する機能)が有効になります。 ただし無料アカウントの推論クレジットは 月 $0.10 程度 しかないため、これはあくまで飾りです。トークンが無い・期限切れ・レート制限・タイムアウトのいずれでも None を返し、主機能であるローカル検証はそのまま動き続けます(3回連続で失敗すると自動的に呼び出しを止めます)。

設定する場合:

  1. Space ページ → Settings → Variables and secrets
  2. New secret を押す
  3. Name に HF_TOKEN、Value に自分のアクセストークン(read 権限で十分)
  4. 保存すると Space が自動で再起動します

他の環境変数(LOG_CAPACITY, MAX_TEXT_CHARS, PRICE_IN_PER_1K など)も同じ画面から設定できます。秘密でない値は Secrets ではなく Variables で構いません。 価格を入れておくと、Retry タブの節約試算が「トークン数」ではなく「金額」で出ます。


4. 動作確認

Space が Running になったら、以下を順に確認してください。 初期値がそのまま入っているので、基本的にボタンを押すだけです。

4-1. 文脈に無い数値が赤く出ること

Verify タブを開くと、Answer と Context に例文が入っています。Verify を押します。

応答本文が色分けされ、次のようになれば成功です。

箇所 期待する色 理由
12,000 1,800 3,400人 2024年3月15日 🟩 緑 (supported) 文脈にそのまま存在する
15% 🟦 青 (derived) 文脈の数値から計算できる
3,250人 🟥 赤 (contradicted) 文脈は 3,200人。近いが違う
https://example.com/ir/2025 🟥 赤 (contradicted) 文脈は /ir/2024。捏造リンク
7.2% 🟧 橙 (unsupported) 文脈のどこにも無い

自分で試すなら、Answer の末尾に「解約率は99.9%です。」のように文脈に無い数値を足して Verify を押してください。橙または赤になります。

上の表に出ている grounding_score と coverage は必ず両方見てください。 Answer を「詳細は担当部署にお問い合わせください。」だけに書き換えて Verify すると、grounding_score は高いのに coverage が 0 になります。これが「何も検証できていない」状態です。

4-2. 「導出」判定を確認する

15% が 🟦 青 (derived) になり、Full result の該当 claim の evidence に

derivable from context: 1,800 / 12,000 * 100 (percentage) = 15

と出ていることを確認します。文脈に 15 という文字列は存在しませんが、1,800 ÷ 12,000 × 100 で導出できるため supported ではなく derived になります。

4-3. Retry タブで再試行用の指示文が出ること

Retry タブに移り、入力欄は空のまま 「Build retry instruction」を押します(Verify タブの結果を自動で読みます)。

  • 上の欄に、失敗した主張だけを列挙した日本語の指示文が出ます
  • 下の JSON に blind_retry_tokens / targeted_retry_tokens / saved_tokens / saved_cost の試算が出ます

試算の読み方: saved_tokens は符号付きです。文脈が小さいと、指示文のほうが長くなってマイナスになることがあります(targeted_is_cheaper: false)。これは不具合ではなく事実で、隠すほうが有害です。実運用の RAG のように文脈が数千トークンあると、はっきりプラスになります。 また PRICE_* を設定していると、出力トークンの単価が入力より高いため、トークン数はマイナスでも金額はプラスになることがあります。どちらを基準に判断したかは comparison_basis に出ます。

4-4. 実際のエンドポイントを取得する

API Docs タブに、この Space の実際のパスが表示されます(Gradio のバージョンによってプレフィックスが変わるため、ハードコードせず起動時に検出しています)。

最終的な正解はページ最下部の 「Use via API」 リンクです。ここに gradio_client と curl の両方のサンプルが出るので、そちらを正としてください。

# Space ページ最下部の「Use via API」で確認できる形
curl -s -X POST https://YOUR_NAME-claimcheck.hf.space/gradio_api/call/verify \
  -H 'Content-Type: application/json' \
  -d '{"data": ["営業利益率は15%です。", "営業利益は1,800百万円、売上高は12,000百万円でした。", "", "", "", "", "{}"]}'

Health タブで mode / uptime / events_logged / mean_latency_ms も確認しておくと、後で遅くなったときの比較対象になります。


5. 運用の型

いきなり block から始めないこと

これが最も重要です。検証器は偽陽性で信頼を失います。一度「またこいつが誤検知した」と思われたら、その後どれだけ精度を上げても使われません。

段階的に締めていきます。

第1段階:観測だけ(1〜2週間)

verdict は見るが、何もブロックしない。ログを貯めることだけが目的です。

{
  "block_on_critical_safety": true,
  "block_on_leak": false,
  "retry_on_contradicted": 9999,
  "retry_grounding": 0.0,
  "annotate_grounding": 1.0
}

これで安全違反(APIキー等)以外は annotate 止まりになります。 tags_json に {"model": "...", "prompt_version": "..."} を必ず入れてください。Dashboard の比較表がこれで初めて意味を持ちます。

第2段階:Audit で偽陽性を潰す

Audit タブを毎日見ます。unsupported / contradicted と判定された主張が一覧に出るので、実は正しかったものに false_positive のチェックを入れて保存します。

画面に出る 偽陽性率 (false_positive_rate) が判断材料です。型別 (by_type) も出るので、どの検証が足を引っ張っているかが分かります。

経験則として、false_positive_rate が 0.1 を超えているうちは retry に進まないでください。

第3段階:retry を有効にする

偽陽性率が落ち着いたら、まず contradicted(最も確度が高い)だけで再試行させます。

{ "retry_on_contradicted": 1, "retry_grounding": 0.5 }

第4段階:block はごく一部だけ

block は原則として**安全違反(既定で有効)**に限定します。 幻覚検出を理由に block するなら、対象を絞ってください(例:金額・日付を含む回答のみ、contradicted が 2 件以上のときだけ)。

Dashboard の使い方

  • model × prompt_version 比較表 — プロンプトを変えたときに、grounding_mean / coverage_mean / contradicted_rate が改善したのか悪化したのかを見ます。これが無いと「なんとなく良くなった気がする」で終わります。
  • 累積節約 — Retry を targeted に切り替えた効果です。
  • 検査遅延 p50/p95/max — ClaimCheck 自体のコスト。数百ms を超え始めたら第6節を見てください。

記録はメモリ上にしかありません。 ディスクは非永続で、48時間無操作でスリープします。再起動すると イベントログも偽陽性の印も全部消えます。必要な分は Dashboard と Audit の CSV を定期的に落としてください。


6. よくある失敗と対処

偽陽性が多い

まず ENTITY を切ってください。 圧倒的に最大の原因です。

{ "enable_entity": false }

一般名詞(Machine Learning)、略語の展開(文脈 World Health Organization / 応答 WHO)、固有名詞らしく見えるだけの語が、片端から unsupported になります。

NUMERIC と DATE から始めてください。 この2つが最も確度が高く、かつ「危険な幻覚は具体的」という前提に最も素直に合致します。

{ "enable_numeric": true, "enable_date": true,
  "enable_entity": false, "enable_quote": false, "enable_url": false }

それでも数値で誤検知が出る場合:

症状 対処
丸めた数値(約1,200 → 1200)で落ちる これは正常に supported になります。ならない場合は numeric_tolerance を 0.02 程度に
近い別の数値と勝手に照合される contradiction_rel を 0.25 → 0.10 に下げる(照合窓を狭める)
引用が言い換えで approximate になる 仕様どおりです。言い換えを許すなら approx_ratio を下げるのではなく、プロンプト側で原文引用を指示してください

coverage が低い

応答が抽象的すぎます。 ツール側の問題ではありません。

verify.unverified_sentences に、検証できなかった文がそのまま入っています。まずそれを読んでください。「ご検討ください」「一般的には〜と言われています」のような文ばかりなら、そもそも検証できる主張が存在しません。

対処はプロンプト側です。具体的な根拠提示を求めるよう促します。

回答には、文脈中の該当する数値・日付・原文の引用を必ず含めてください。
文脈に根拠が無い事項については「文脈に記載がありません」と明記してください。
推測で数値や日付を補わないでください。

これを入れると coverage は目に見えて上がります。同時に、モデルが具体的に書くぶん 検証できる範囲が広がり、幻覚も捕まえやすくなります。

coverage が低いまま grounding_score だけ高い状態を「検証済み」と報告しないでください。README の警告のとおり、それは「検証できるものが無かった」という意味です。

検査が遅い

無料枠は 2 vCPU です。典型的な応答なら数ミリ秒、20,000文字の最悪ケースでも 100ms 未満で終わりますが、遅くなったら順に:

  1. MAX_TEXT_CHARS を下げる(例 20000 → 8000)。最も効きます。入力は安全に切り詰められ、warnings に truncation が記録されます。
  2. ENTITY 検証を無効化する({"enable_entity": false})。抽出も照合も減ります。偽陽性対策と一石二鳥です。
  3. 導出探索を切る({"enable_derivation": false})。文脈中の数値が非常に多いときに効きます。derive_max_terms を 2 にするだけでも軽くなります。 3b. 近似照合の予算を絞る({"fuzzy_budget_ms": 80})。引用が多い応答で効きます。予算切れは counts.fuzzy_budget_exhausted と notes に必ず出るので、黙って精度が落ちることはありません。
  4. MAX_CLAIMS を下げる(既定 1500)。打ち切った件数は counts.claims_dropped_by_cap と notes に必ず出るので、黙って減ることはありません。
  5. UI_CONCURRENCY を下げる(既定 4)。同時実行で CPU を食い合っている場合。

Health タブと Dashboard の遅延表 (p50/p95/max) で、変更の前後を比べてください。

その他

症状 原因と対処
ビルドが失敗する requirements.txt に余計な依存を足していないか確認。torch / transformers は無料枠に入りません
起動が遅い 初回は依存のインストール分です。2回目以降はキャッシュが効きます
数時間後に見に行ったら固まっている 48時間無操作のスリープです。アクセスすれば起きます(初回は数十秒)
ログが消えた 仕様です。非永続ディスク + メモリ上のリングバッファ。CSV で落としてください
Enrichment が常に null HF_TOKEN 未設定、または推論クレジット切れ。任意機能なので放置して構いません。 Health タブの enrichment.last_error に理由が出ます
verdict が全部 annotate になる 検証できる主張が見つかっていません。「coverage が低い」の項を参照
条番号・型番が赤くなりすぎる 仕様です。識別子は「一致か誤りか」しかなく、第12条 に対する 第13条 は最も危険な捏造なので contradicted にしています。緩めるなら enable_entity: false で ENTITY ごと切ってください
notes に「budget ran out」と出る fuzzy_budget_ms / max_claims / derive_budget_ms の上限に当たりました。打ち切った事実は必ず出力に残ります。上限を上げるか、入力を短くしてください