Buckets:

glennmatlin's picture
|
download
raw
15.6 kB
# Data Attribution for Social Reasoning in Pre-Training Corpus
This repo is a workspace for running Bergson's quick start workflow on datasets like Dolma and SocialIQA.
## Install
1. Bootstrap the required local dependencies from the main checkout:
```bash
bash scripts/bootstrap_local_deps.sh
```
This script is idempotent. It clones `bergson` and `olmes` when missing, checks out the pinned commits, and applies the tracked local patches.
2. Install build dependencies:
```bash
sudo apt-get update && sudo apt-get install -y build-essential g++
```
3. Then setup the Python environment via `uv`:
```bash
uv pip install setuptools pybind11
uv sync --no-build-isolation
```
This project currently targets Python 3.12. The pinned `ai2-olmes` checkout still requires `<3.13`.
For a fresh git worktree, run `bash scripts/bootstrap/setup_worktree.sh` before the first `uv` command. It bootstraps the shared local dependencies from the main checkout, links them into the worktree, copies gitignored files (`settings.local.json`, `autopilot/state.json`, `uv.lock`) from the main checkout, installs `pybind11` for local builds, and then runs `uv sync --frozen`. The script uses uv's default cache (`~/.cache/uv`) for fast CoW clones on APFS; override with `UV_CACHE_DIR` if needed.
After bootstrap, use `uv run --no-sync ...` for routine verification commands in the worktree:
```bash
uv run --no-sync pytest -q
uv run --no-sync ruff check .
uv run --no-sync ruff format --check .
```
This avoids a second sync/build step during `uv run`. Plain `uv run ...` may try to resolve the build-system requirements for `setuptools` and `wheel`, which can fail in sandboxed or offline sessions.
If dependencies changed, rerun `bash scripts/bootstrap/setup_worktree.sh` or `uv sync --no-build-isolation` before using `--no-sync` again. If `uv run --no-sync ...` still fails, fall back to `./.venv/bin/python -m pytest ...` or `./.venv/bin/ruff ...`.
### Optional pre-push checks
Install the repo-local pre-push hook when you want push-time quality checks:
```bash
bash scripts/bootstrap/install_git_hooks.sh
```
The hook runs only before `git push`. It checks the commits being pushed with
`git diff --check`, then runs `ruff check` and `ruff format --check` on pushed
Python files. It does not run on every commit.
## R2 credentials
R2 hosts the raw 6T `.jsonl.zst` source corpus and the original per-shard sidecars. Many workflows can stay HF-only since the sidecars are now mirrored to `HCAI-Lab/soc91-labels`, `HCAI-Lab/soc91-stats`, and `HCAI-Lab/soc139-quality-sidecars` (see `docs/data_home/README.md`). You only need R2 for the raw shards or when you want per-shard sidecar granularity.
R2 scripts expect `R2_ACCESS_KEY_ID` and `R2_SECRET_ACCESS_KEY` in the environment.
If the credentials live in 1Password, use the wrapper script:
```bash
bash scripts/bootstrap/with_r2_credentials.sh \
uv run python scripts/validation/analyze_sidecar_labels.py \
--output-dir ~/scratch/soc91/eda \
--max-shards 5
```
The wrapper defaults to the 1Password item `Research` / `Cloudflare R2 API Credentials`.
Override the lookup with `OP_R2_VAULT`, `OP_R2_ITEM`, `OP_R2_ACCESS_KEY_FIELD`, and
`OP_R2_SECRET_ACCESS_KEY_FIELD` if needed.
## Phoenix sidecar EDA
The sidecar EDA CLI now supports a fixed-manifest workflow for Phoenix CPU jobs.
Create a benchmark manifest from completed sidecars:
```bash
bash scripts/bootstrap/with_r2_credentials.sh \
uv run python scripts/validation/analyze_sidecar_labels.py \
--mode manifest \
--output-dir ~/scratch/soc91/eda_benchmark \
--manifest-path ~/scratch/soc91/eda_benchmark/completed_sidecars_manifest.jsonl \
--max-shards 1000 \
--chunk-count 32
```
Run a single benchmark job on Phoenix:
```bash
sbatch scripts/slurm/eda/sidecar_eda_benchmark_phoenix.sbatch
```
Run a chunked Phoenix array from an existing manifest:
```bash
sbatch --array=0-31 scripts/slurm/eda/sidecar_eda_array_phoenix.sbatch \
--export=MANIFEST_PATH=~/scratch/soc91/eda_benchmark/completed_sidecars_manifest.jsonl,CHUNK_COUNT=32,OUTDIR=~/scratch/soc91/sidecar_eda_runs/current
sbatch --dependency=afterok:<array_job_id> scripts/slurm/eda/sidecar_eda_merge_phoenix.sbatch \
--export=OUTDIR=~/scratch/soc91/sidecar_eda_runs/current
```
Worker jobs write `state.json`, `benchmark.json`, and the SQLite cache under each worker directory.
The merge job reads those worker artifacts and writes the final CSV and JSON outputs in `OUTDIR`.
The current Phoenix-safe default is `CHUNK_COUNT=32`, which stays below the `embers` submit limit we hit in practice.
Using a fixed `CHUNK_COUNT` keeps shard-to-worker assignment stable across reruns as the completed set grows,
which lets unchanged shards reuse the same worker cache instead of shifting between chunk directories.
To launch the full Phoenix path in one step:
```bash
scripts/slurm/eda/launch_sidecar_eda_phoenix.sh
```
Optional overrides:
- `CHUNK_COUNT=32`
- `RUN_ID=soc101_full_hash_YYYYMMDD_HHMMSS`
- `RUN_ROOT=$HOME/scratch/soc91/sidecar_eda_runs`
- `MAX_SHARDS=1000` for a bounded dry run
- `PYTHONEXEC=/path/to/python`
## Modal sidecar EDA
The current SOC-101 Modal entrypoint is `scripts/modal/sidecar_eda.py`.
It writes run artifacts under `soc91-stats/sidecar-eda/<run_id>/` in R2, maps
worker chunks in parallel, and merges the final outputs in place.
Run a bounded check:
```bash
python3 -m modal run scripts/modal/sidecar_eda.py --max-shards 1000 --chunk-count 32
```
Run the full current completed-sidecar set:
```bash
python3 -m modal run scripts/modal/sidecar_eda.py --chunk-count 128
```
## Bergson + Transformers version note (OLMo3)
This repo currently vendors Bergson from `./bergson` and pins that checkout through `scripts/bootstrap_local_deps.sh`.
The current pinned upstream release is `v0.9.0`.
Historical note:
- Older Bergson releases in the `v0.4.x` line pinned `transformers<4.56.0`.
- This repo carried a local override so OLMo3-compatible Transformers versions could be used.
- Upstream removed that transformers pin before `v0.9.0`, so that local Bergson patch is no longer the default path here.
The vendored workflow stays in place so bootstrap and worktree setup can reproduce the exact Bergson release used by the repo.
⚠️ Upstream docs and code are not perfectly aligned on every CLI example. Treat the installed `bergson --help` output as the source of truth when updating or running repo scripts.
## Bergson quick start (smoke)
This follows the Bergson quick start tutorial.
⚠️ The exact CLI flags depend on the installed Bergson version. Start by running `bergson --help` in the current project environment and use that output as the source of truth.
Build an index on a small dataset:
```bash
uv run bergson build runs/quickstart \
--model EleutherAI/pythia-14m \
--dataset NeelNanda/pile-10k \
--truncation
```
Query the index interactively:
```bash
uv run bergson query runs/quickstart
```
## Pool sample dataset
The primary corpus for attribution experiments is a 175B-token random sample drawn from the full ~9T-token `allenai/dolma3_pool`. This avoids the confounding effects of AllenAI's RegMix upsampling in the curated mix.
**Dataset:** https://huggingface.co/datasets/HCAI-Lab/archive-dolma3-pool-150b
| Property | Value |
|----------|-------|
| Source | `allenai/dolma3_pool` (~9T tokens, 2732 shards) |
| Total tokens | 175,000,463,223 (175.0B) |
| Total docs | 163,560,678 |
| Format | `.jsonl.zst` (100 shards) + `.parquet` manifests |
| Sampling | Uniform random, seed=42, 5 jobs x 20 workers |
| Storage | ~568 GB |
The sample is organized as `job_{0-4}/worker_{000-019}/train-00000.jsonl.zst` with per-worker parquet manifests containing `doc_id`, `shard_path`, `token_count`, `weborganizer_topic`, and `weborganizer_format`. WebOrganizer labels are null in the source pool data and are populated downstream by the enrichment pipeline (SOC-5).
The 25B token excess over the 150B target provides headroom for downstream cleaning (blank/short doc removal).
## Sidecar corpus manifest
The unified corpus manifest now supports a sidecar-join path for the deduplicated 6T workflow.
This path reads completed `soc91-labels/*.parquet` sidecars plus their `.stats.json` files,
streams the matching source shards, and writes a partitioned Parquet dataset with one row per
document and no text payload.
The sidecar-backed manifest retains:
- `doc_id`, `shard_path`, `source_family`
- `original_word_count`, `estimated_token_count`, `token_count`
- canonical sampling labels in `weborganizer_topic`, `weborganizer_format`, and `bin_id`
- URL and noURL top-1 label ids, label strings, and confidences
- URL and noURL probability vectors when they are present in the sidecar schema
Local example:
```bash
uv run data-attribution-corpus-manifest \
--sidecar-dir /path/to/sidecars \
--source-dir /path/to/source_shards \
--output /path/to/corpus_manifest_dataset
```
R2 example:
```bash
uv run data-attribution-corpus-manifest \
--sidecar-r2-prefix soc91-labels \
--bucket soc127-dedup \
--endpoint-url https://0934ab8e84ac8f4e81decaf3eb121337.r2.cloudflarestorage.com \
--output /path/to/corpus_manifest_dataset
```
Reusable work-manifest snapshot:
```bash
uv run data-attribution-corpus-manifest \
--sidecar-r2-prefix soc91-labels \
--bucket soc127-dedup \
--write-work-manifest runs/manifests/soc95_work_manifest.jsonl \
--manifest-only \
--output /tmp/soc95-manifest-snapshot
```
When a saved work manifest contains R2 sidecar keys, later runs may still pass
`--source-dir /path/to/local/source_root` to read source shards locally while
continuing to fetch sidecar parquet files from R2.
This writes:
- `data/*.parquet` shard partitions
- `meta/*.json` per-sidecar join metadata
- `manifest_summary.json`
- `bin_totals.parquet`
- `bin_totals.csv`
- `mismatch_report.jsonl`
Exact sidecar schema inventory for rerun planning:
```bash
uv run data-attribution-sidecar-schema-inventory \
--sidecar-r2-prefix soc91-labels \
--bucket soc127-dedup \
--output-dir runs/reports/soc95_sidecar_schema_inventory \
--chunk-count 32
```
This writes a reusable completed-sidecar snapshot, per-chunk JSONL outputs, a merged exact old/new schema inventory, and `old_schema_sidecar_ids.txt` plus `old_schema_sidecar_keys.txt` for rerun handoff.
For the Modal CPU execution path, see [docs/SOC95_MODAL_RUNBOOK.md](docs/SOC95_MODAL_RUNBOOK.md).
To draw sampling manifests from a SOC-95 dataset root, use the supported manifest sampler:
```bash
uv run data-attribution-manifest-sample \
--input /path/to/corpus_manifest_dataset \
--output-dir /path/to/sample_outputs
```
This loader keeps the base manifest unchanged, drops unsampleable rows such as null topic/bin rows for the sampling path only, and writes:
- `pool_bin_stats.parquet`
- `pool_stratified_manifest.parquet`
- `pool_representative_manifest.parquet`
## WebOrganizer report
I keep the reusable WebOrganizer report workflow in [docs/WEBORGANIZER_REPORT.md](docs/WEBORGANIZER_REPORT.md).
It is the path I use when I want the 24 x 24 topic x format figures, concentration table, note, and metadata for a new datapool.
Local example:
```bash
uv run data-attribution-weborganizer-report \
--eda-dir artifacts/dolma_eda \
--output-dir artifacts/weborganizer_report \
--run-label pool-150b \
--format all \
--representative-manifest /path/to/representative.parquet \
--stratified-manifest /path/to/stratified_dir
```
The paper-facing alias `data-attribution-paper-figures` still points to the same implementation for the current paper cycle.
## Dolma subset
For Dolma, the simplest way to keep the run bounded is to use a sliced split (example sizes shown):
```bash
uv run bergson build runs/dolma_small \
--model EleutherAI/pythia-14m \
--dataset allenai/dolma3_mix-150B-1025 \
--subset default \
--split "train[:1024]" \
--truncation
```
## SocialIQA dataset
I can construct prompt strings from `allenai/social_i_qa` on Hugging Face instead of relying on the committed v1.4 archive.
If we want a labeled split for "correct answer" completions, we should start with the train/validation splits that contain `correct`.
The SocialIQA manifest and export helpers now emit a `completion` field with the correct choice when labels are available so Bergson
builds can point `--prompt_column prompt` and `--completion_column completion` at the generated JSONL.
## Repo smoke: SocialIQA on Dolma (GPU only)
This is the bounded smoke path we run manually (not in CI). Defaults: Dolma slice `train[:4509]`, SocialIQA sample 100 `train` queries, model `allenai/Olmo-3-1025-7B`, projection_dim 16, bf16, truncation on, skip_preconditioners on. Outputs go to `runs/attributions/<run_id>` by default.
1. Precache (requires `HF_TOKEN`):
`uv run data-attribution-precache --dataset-repo-id allenai/dolma3_mix-150B-1025 --allow-full-download --snapshot`
2. Dolma index:
`uv run data-attribution-dolma-train --train-slice 4509 --model-id allenai/Olmo-3-1025-7B`
3. Dolma doc text sidecar (aligns doc_id to text/source_id):
`uv run data-attribution-dolma-metadata --train-slice 4509 --model-id allenai/Olmo-3-1025-7B --run-root runs/dolma_train_allenai-Olmo-3-1025-7B_train4509_proj16_bf16`
4. SocialIQA queries + query index:
`uv run data-attribution-socialiqa-queries --split train --sample-size 100 --model-id allenai/Olmo-3-1025-7B`
5. Attribution with doc metadata:
`uv run data-attribution run --query-gradients runs/socialiqa_allenai-Olmo-3-1025-7B_train_proj16_bf16 --index-path runs/dolma_train_allenai-Olmo-3-1025-7B_train4509_proj16_bf16 --metadata-path runs/dolma_train_allenai-Olmo-3-1025-7B_train4509_proj16_bf16/metadata.parquet --metadata-join-keys text source_id`
Optional analysis helper: join doc text and query prompts into the attribution parquet:
`uv run data-attribution-enrich --attributions runs/attributions/<run_id>/attributions.parquet --doc-metadata runs/dolma_train_allenai-Olmo-3-1025-7B_train4509_proj16_bf16/metadata.parquet --query-index runs/socialiqa_allenai-Olmo-3-1025-7B_train_proj16_bf16`
See `notes/BERGSON_COOKBOOK.md` for details and troubleshooting.
## Plan
`PLAN.md` tracks the current approach. The current direction is to keep a quickstart-first workflow and avoid a custom runner until the basic Bergson pipeline is working end to end.
## Hugging Face auth (rate limits)
Some Hugging Face endpoints will rate limit unauthenticated requests.
I keep secrets in `.env.secret` (git-ignored) and load them in scripts that need them.
The repo defaults Hugging Face caches to `./.hf_cache`; smoke helpers auto-source `.env.secret` and set `HF_HOME`, `HF_DATASETS_CACHE`, `HUGGINGFACE_HUB_CACHE`, and `TRANSFORMERS_CACHE` to that path.
1. Create `.env.secret` by copying `.env.secret.example`.
2. Set `HF_TOKEN` to a read-only Hugging Face token.
3. Re-run `data-attribution-precache --snapshot --allow-full-download --dataset-repo-id allenai/dolma3_mix-150B-1025`.
4. If you hit 429 rate limits, retry with `--max-workers 1 --retry-attempts 10`.
## Precache allowlists
The precache CLI only accepts predefined model and dataset ids.
Allowed model ids:
- `allenai/Olmo-3-1025-7B`
- `allenai/Olmo-3-1125-32B`
Allowed dataset ids:
- `allenai/dolma3_mix-150B-1025` (subset: `default`)
## Ingest policy
`data-attribution ingest` only reads from local Dolma shards.
Provide `--cache-dir` or `--download-dir` pointing at the prepared shards.
Use `data-attribution-precache` to fetch shards before ingesting.

Xet Storage Details

Size:
15.6 kB
·
Xet hash:
153df0f06cadc3c0bad138873725de5b239cf9f1f9b808d2333c83e6881f04f2

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.