LLMチャット対話における言語ステガノグラフィの研究用コードです。単一ストリームのベースラインと、複数の独立した秘密メッセージを同時に隠し、GPUバッチ処理を活用してはるかに高いスループットを実現するバッチ型**マルチストリーム(HiTMS)**プロトコルを含みます。
Bobモデルが質問し、Aliceモデルがステガノグラフィ符号器を介してペイロードをトークン選択に秘密裏に埋め込みながら応答します。BobはAliceの応答に対してモデルを再実行してビットを復元します。符号化と復号はビット単位で完全一致するため、秘密は無損失で復元されます。
arithmetic*.py)discop*.py)single_stream.py): フレーミングのオーバーヘッドなし — すべてのチャネルビットがペイロード(約100%の利用率)。protocol.py): m個の秘密ストリームをラウンド間で断片化し、PRF駆動のストリーム→スロット対応付け、デコイスロット、16ビット長ヘッダ、フィラーキーストリームを使用します。各ラウンドの複数の応答は1回のバッチ順伝播で生成されるため、スループットはバッチサイズに応じてスケールします。実験で使用したモデル: meta-llama/Llama-3.2-3B-Instruct と google/gemma-3-4b-it。データセット: databricks/databricks-dolly-15k と HuggingFaceH4/no_robots の創造的/自由回答サブセット。
| Path | Description |
|---|---|
arithmetic.py, arithmetic_batch.py | 算術符号化ステゴ(単一+バッチストリーム符号化/復号器)。 |
discop.py, discop_batch.py | Discopステゴ符号器 + 共有PRG(単一+バッチ)。 |
utils.py | 共有ヘルパー(ビット/整数変換、エントロピー、top-k、文末チェック)。 |
protocol.py | マルチストリームHiTMSプロトコル(ストリーム対応付け、デコイ、ヘッダ、フィラー)。 |
single_stream.py | 単一ストリームプロトコル(フレーミングなし。Lビット目で切り詰め)。 |
round_trip.py, batch_round_trip.py | 最小限のワンショット往復デモ/テスト。 |
multi_round_demo.py | マルチストリーム試行ランナー(run_trial)+ 詳細な単一試行デモ。 |
single_stream_demo.py | 単一ストリーム試行ランナー(run_single_trial)+ デモ。 |
run_sweep.py | {model}×{pool}×{coder} を対象としたマルチストリームスイープ(再開可能)。 |
run_single_sweep.py | 単一ストリーム版の対応するスイープ。 |
run_scaling_sweep.py | ストリーム数スケーリングスイープ(x ∈ {1,2,4,8,16,32,64})。任意のモデル/プール/符号器に対応。 |
run_x1_shards.py, run_x1_finish.sh, merge_x1_shards.py | x=1アブレーション: 1セルをGPU間でシャードし、カバレッジチェック付きでマージ。 |
judge_quality.py | LLM-as-a-judge 非知覚性スコアラー(呼び出しごとに1 QA、再開可能)。 |
gen_cover.py | ペイロードなしの「cover」テキスト生成(ステガノグラフィ解析の参照用)。 |
steganalysis_bert.py | cover対stego検出器(BERT / RoBERTa / DeBERTa-v3 / ELECTRA)。 |
export_data.py | 公開可能な要約専用ミラーを data/ に構築。 |
build_question_pool.py, build_norobots_pool.py | HFデータセットから質問プールを構築。 |
*_creative_questions.json | 構築済みの質問プール。 |
legacy/ | 以前のスクリプト/プール。参照用に保持。 |
data/ には論文内の全実験結果(容量、スループット、利用率、判定スコア、検出器AUROC)がトライアルごとに1つのJSONオブジェクトとして格納されます。完全なスキーマは data/README.md を参照してください。
生成されたステゴテキスト自体は含まれません。生ログにはすべての断片について質問と応答が埋め込まれるため約1GBになりますが、export_data.py はそれらのフィールドを取り除き、すべての測定値(約24MB)を保持します。すべてのドライバはシード固定されているため、スイープを再実行するとテキストが正確に再生成されます。
生の出力ディレクトリ(
sweep_logs/、single_sweep_logs/、scaling_logs/、judge_logs/、cover_logs/、run_logs/、steganalysis_logs/)はgitignore対象です。これらは大きく(最後のものは数GBの学習済み検出器チェックポイントを保持)、完全に再生成可能です。
conda create -n ems python=3.10 -y && conda activate ems
pip install torch transformers datasets numpy
pip install openai # only needed for judge_quality.py
LLMを実行するにはCUDA GPUが必要です。LlamaとGemmaのチェックポイントはHugging Face Hubでアクセス制限されているため、初回使用前に(それらのモデルへのアクセス権を付与した上で)huggingface-cli login を実行してください。
質問プールを構築します(一度だけ):
python build_question_pool.py # -> dolly15k_creative_questions.json
python build_norobots_pool.py # -> norobots_creative_questions.json
単一の詳細トライアル(健全性チェック):
# multi-stream
CUDA_VISIBLE_DEVICES=0 python multi_round_demo.py
# single-stream
CUDA_VISIBLE_DEVICES=0 python single_stream_demo.py
# override model / coder / pool via env
ROUND_TRIP_MODEL=google/gemma-3-4b-it STEGO_ALGORITHM=discop \
STEGO_QUESTION_POOL=norobots_creative_questions.json \
CUDA_VISIBLE_DEVICES=0 python multi_round_demo.py
完全な実験(再開可能 — 同じコマンドを再実行して続行):
# multi-stream (8 streams x 1024 bits), all model/pool/coder combos, 500 trials
CUDA_VISIBLE_DEVICES=0 python run_sweep.py --trials 500
# single-stream baseline
CUDA_VISIBLE_DEVICES=0 python run_single_sweep.py --trials 500
# stream-count scaling (dolly + Llama + Discop)
CUDA_VISIBLE_DEVICES=0 python run_scaling_sweep.py --x-values 4 8 16 32 64
非知覚性評価(OPENAI_API_KEY またはローカルの OPENAI_API_key.txt にOpenAIキーが必要です。いずれもgitignore対象):
python judge_quality.py --dry-run # plan only, no API calls
python judge_quality.py --limit 2 # tiny live smoke test
python judge_quality.py # full run (resumable)
python judge_quality.py --aggregate-only # recompute the score table
各ドライバはシードを固定し(プロンプトのシャッフル、ペイロードのサンプリング、サンプリング用RNG、torch.manual_seed)、決定論的でパスを認識するプロンプトストリームからプロンプトを消費します。そのため、スイープ全体はエンドツーエンドで再現可能であり、中断後はチェックポイントから正確に再開されます。
OPENAI_API_key.txt、*.key、.env は無視されます。