
산술/Discop 스테가노그래픽 코더를 사용하여 LLM 채팅 토큰 선택에 여러 개의 비밀 메시지를 임베드하고, 비트 정확한 디코딩 및 스테가날리시스 평가를 제공합니다.
LLM 채팅 대화에 대한 언어 스테가노그래피 연구 코드로, 단일 스트림 기준(baseline)과 배치 방식의 다중 스트림(HiTMS) 프로토콜을 포함합니다. 이 프로토콜은 여러 개의 독립적인 비밀 메시지를 한 번에 숨기고 GPU 배칭(batching)을 활용하여 훨씬 더 높은 처리량을 달성합니다.
Bob 모델이 질문을 하고, Alice 모델이 대답하면서 스테가노그래픽 코더(steganographic coder)를 통해 페이로드를 토큰 선택에 비밀리에 인코딩합니다. Bob은 Alice의 응답에 모델을 다시 실행하여 비트를 복구합니다. 인코딩과 디코딩은 비트 단위로 정확하므로 비밀 정보가 무손실로 복구됩니다.
arithmetic*.py)discop*.py)single_stream.py): 프레이밍 오버헤드 없음 — 모든 채널 비트가 페이로드입니다 (~100% 활용률).protocol.py): 라운드에 걸쳐 분할된 m개의 비밀 스트림, PRF 기반 스트림→슬롯 매핑, 유인(decoy) 슬롯, 16비트 길이 헤더, 필러 키스트림. 각 라운드의 여러 응답은 한 번의 배치 순전파(batched forward pass) 로 생성되므로 처리량이 배치 크기에 비례하여 확장됩니다.실험에 사용된 모델: meta-llama/Llama-3.2-3B-Instruct 및 google/gemma-3-4b-it. 데이터셋: databricks/databricks-dolly-15k 및 HuggingFaceH4/no_robots의 창의적/개방형 하위 집합.
| 경로 | 설명 |
|---|---|
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-as-a-judge 비인지성 점수기 (호출당 QA 1개, 재개 가능). |
gen_cover.py | 페이로드 없는 "커버(cover)" 텍스트 생성 (스테가날리시스 참조용). |
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/ | 이전 스크립트/풀, 참고용으로 유지됨. |
data/는 논문의 모든 실험 결과 — 용량, 처리량, 활용률, 심사위원 점수 및 탐지기 AUROC — 를 시도당 하나의 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 # judge_quality.py에만 필요
LLM을 실행하려면 CUDA GPU가 필요합니다. Llama 및 Gemma 체크포인트는 Hugging Face Hub에서 게이트되어 있으므로, 처음 사용 전에 huggingface-cli login(해당 모델에 대한 액세스 권한이 부여된 상태)을 실행하세요.
질문 풀 구축 (1회):
python build_question_pool.py # -> dolly15k_creative_questions.json
python build_norobots_pool.py # -> norobots_creative_questions.json
단일 상세 시도 (기본 확인):
# 다중 스트림
CUDA_VISIBLE_DEVICES=0 python multi_round_demo.py
# 단일 스트림
CUDA_VISIBLE_DEVICES=0 python single_stream_demo.py
# 모델/코더/풀을 환경 변수로 재정의
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
전체 실험 (재개 가능 — 동일한 명령을 다시 실행하여 계속):
# 다중 스트림 (8개 스트림 x 1024비트), 모든 모델/풀/코더 조합, 500회 시도
CUDA_VISIBLE_DEVICES=0 python run_sweep.py --trials 500
# 단일 스트림 기준
CUDA_VISIBLE_DEVICES=0 python run_single_sweep.py --trials 500
# 스트림 수 스케일링 (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 # 계획만, API 호출 없음
python judge_quality.py --limit 2 # 소규모 실시간 스모크 테스트
python judge_quality.py # 전체 실행 (재개 가능)
python judge_quality.py --aggregate-only # 점수 테이블 재계산
각 드라이버는 시드(프롬프트 셔플링, 페이로드 샘플링, 샘플링 RNG, torch.manual_seed)를 고정하고 결정론적이고 패스 인지(pass-aware) 방식의 프롬프트 스트림에서 프롬프트를 소비하므로, 전체 스윕은 끝까지 재현 가능하며 중단 후 체크포인트에서 정확히 재개됩니다.
OPENAI_API_key.txt, *.key, .env는 무시됩니다.