用于基于LLM聊天对话的语言隐写的研究代码,包含单流基线和批量**多流(HiTMS)**协议,可同时隐藏多条独立秘密消息,并利用GPU批处理实现更高的吞吐量。
Bob 模型提出问题;Alice 模型通过隐写编码器将载荷秘密编码到其令牌选择中,从而给出回答;Bob 在 Alice 的回复上重新运行模型以恢复比特。编码和解码是比特精确的,因此秘密被无损恢复。
arithmetic*.py)discop*.py)single_stream.py):无帧开销——每个信道比特都是载荷(约100%利用率)。protocol.py):将 m 个秘密流分片到多轮,采用PRF驱动的流→槽映射、诱饵槽、16位长度头和填充密钥流。每轮的多个响应在一次批量前向传播中生成,因此吞吐量随批大小扩展。实验中使用的模型:meta-llama/Llama-3.2-3B-Instruct 和 google/gemma-3-4b-it。数据集:databricks/databricks-dolly-15k 和 HuggingFaceH4/no_robots 的创意/开放式子集。
data/ 保存了论文中每个实验的结果——容量、吞吐量、利用率、评判者得分和检测器AUROC——每个试验一个JSON对象。完整模式参见 data/README.md。
生成的隐写文本本身不包含在内:原始日志嵌入了每个片段的问答,使其约为1 GB,因此 export_data.py 会去除这些字段并保留所有测量值(约24 MB)。所有驱动程序都有固定种子,因此重新运行扫描会精确重新生成文本。
原始输出目录(
sweep_logs/、single_sweep_logs/、scaling_logs/、judge_logs/、cover_logs/、run_logs/、steganalysis_logs/)被git忽略——它们很大(最后一个包含数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密钥,两者均被git忽略):
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 已被忽略。| 路径 | 描述 |
|---|
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 消融实验:将单个单元分片到多个GPU,然后通过覆盖检查合并。 |
judge_quality.py | 基于LLM评判的不可感知性评分器(每次调用一个问答,可恢复)。 |
gen_cover.py | 无载荷的“封面”文本生成(隐写分析参考)。 |
steganalysis_bert.py | 封面 vs 隐写检测器(BERT / RoBERTa / DeBERTa-v3 / ELECTRA)。 |
export_data.py | 在 data/ 中构建可发布的仅摘要镜像。 |
build_question_pool.py, build_norobots_pool.py | 从HF数据集构建问题池。 |
*_creative_questions.json | 预构建的问题池。 |
legacy/ | 早期脚本/池,保留以供参考。 |