Skip to content

Latest commit

 

History

History

Folders and files

README.md

Value Stability — Paraphraser

Generates a paraphrased variant of each example (question + positive answer + negative answer) while preserving its meaning, stance, relationship to the Schwartz value, and — importantly — its length. Used to test how stable a steering direction is under semantic-preserving rewrites.

The same pipeline can also produce an adversarial variant, but this README focuses on the paraphraser.

Files

File Purpose
pipeline.py Loads the model and runs the perturbation loop (resumable).
prompts.py System + paraphrase/adversarial prompt templates.
parser.py Extracts the JSON fields from model output.
config.py Paths, model id, and defaults (all overridable via .env).

1. Requirements

  • Python deps: torch, transformers, pandas, tqdm, python-dotenv, huggingface_hub.
  • A Hugging Face token with access to the (gated) Gemma model.
  • A GPU large enough for the model. google/gemma-4-31B-it in bf16 needs roughly ~60 GB of VRAM (or multi-GPU / offload via device_map="auto").

2. Configure (.env at the repo root)

HF_TOKEN=hf_xxx                              # required for gated Gemma
PERTURBATION_MODEL_ID=google/gemma-4-31B-it  # model to use
PERTURBATION_MAX_NEW_TOKENS=512              # plenty for short rewrites
DEVICE_MAP=auto

# Point this at the dataset you want to paraphrase:
PERTURBATION_INPUT_CSV=final_dataset_v3.csv  # resolved under dataset_construction/data/
PARAPHRASE_OUTPUT_CSV=final_dataset_paraphrased.csv

Notes:

  • PERTURBATION_INPUT_CSV is resolved relative to dataset_construction/data/. To use a file elsewhere (e.g. your 200-row subset), pass an absolute path directly in code (see below) instead of relying on this variable.
  • Outputs are written to dataset_construction/data/perturb_result/.

3. Input format

The input CSV must contain these columns:

value, question, positive_answer, negative_answer

Any other columns (id, source, …) are carried through untouched.

4. Run the paraphraser

Option A — one perturbation type, explicit paths (recommended):

from value_stability.pipeline import PerturbationPipeline

pipe = PerturbationPipeline()   # loads the model from PERTURBATION_MODEL_ID
pipe.run_single_perturbation(
    "paraphrase",
    input_csv="value_stability/subseting/final_dataset_200_matched.csv",
    output_csv="dataset_construction/data/perturb_result/final_dataset_paraphrased.csv",
)

Option B — use the configured defaults (runs paraphrase + adversarial):

python -m value_stability.pipeline

The __main__ block uses the DEBUG_* paths in config.py. Check those point where you want before running, since by default DEBUG_INPUT_CSV is the full dataset, not a small sample.

5. Output

Three new columns are appended to a copy of the input, saved at PARAPHRASE_OUTPUT_CSV:

paraphrased_question, paraphrased_positive_answer, paraphrased_negative_answer

6. Resuming

The run is resumable and checkpointed per row — the output CSV is written after every row. If it is interrupted, just run the same command again: rows that already have a paraphrased_question are skipped and generation continues from where it stopped.