license:
- odc-by
- cc-by-nc-4.0
language: - en
task_categories: - text-generation
tags: - safety
- data-attribution
- data-filtering
- gradient-embeddings
- tulu
- sft
pretty_name: SafeTulu
size_categories: - 100K<n<1M
configs: - config_name: safe_tulu
default: true
data_files:- split: train
path: data/safe_tulu/*.parquet
- split: train
- config_name: removed_tulu
data_files:- split: train
path: data/removed_tulu/*.parquet
- split: train
- config_name: tulu_with_metadata
data_files:- split: train
path: data/tulu_with_metadata/*.parquet
- split: train
- config_name: saferlhf_with_metadata
data_files:- split: train
path: data/saferlhf_with_metadata/*.parquet
- split: train
SafeTulu
⚠️ Content warning:
saferlhf_with_metadatacontains harmful requests and harmful responses taken from PKU-SafeRLHF
SafeTulu is a version of the Tulu 3 SFT mixture with the examples most likely to harm a model's safety removed. Each Tulu 3 example is scored by how close its training gradient is to the gradients of harmful PKU-SafeRLHF examples, and the highest-scoring examples are removed.
Along with the filtered dataset, we release the gradient embedding of every Tulu 3 and SafeRLHF example and the score of every Tulu 3 example. This lets you build your own version of SafeTulu. Some customization examples: keeping and filtering only non-English data, removing only 10% of the data, etc.
🛠️ Build your own SafeTulu in the browser: Build Your Own SafeTulu. Pick a removal threshold and sources, see what gets removed, and download the data or push your version to the Hub.
Subsets
| Subset | Rows | What it is |
|---|---|---|
safe_tulu (default) |
771,823 | SafeTulu: the Tulu 3 examples we keep |
removed_tulu |
166,804 | The Tulu 3 examples we remove |
tulu_with_metadata |
938,627 | Every Tulu 3 example, with its gradient embedding, nearest SafeRLHF example, and score |
saferlhf_with_metadata |
43,469 | The harmful PKU-SafeRLHF examples used as the target, with gradient embeddings |
safe_tulu and removed_tulu split tulu_with_metadata with no overlap. Each subset has a single train split.
Fields
All subsets share these fields:
| Field | Type | Description |
|---|---|---|
document_id |
string | Example ID. For Tulu 3 it is the original ID, e.g. ai2-adapt-dev/tulu_v3.9_open_math_2_gsm8k_50k_14145. The prefix identifies the source. SafeRLHF IDs are UUIDs |
content_hash |
string | 128-character hex hash of the example's content |
messages |
list of {role, content} |
The conversation, in the Tulu 3 chat format |
tulu_with_metadata adds:
| Field | Type | Description |
|---|---|---|
gradient_embedding |
list of float32 (1,856) | Gradient embedding of the example |
target_document_id |
string | document_id of the nearest SafeRLHF example in gradient space |
cluster_id |
int64 | Index of that nearest SafeRLHF example: its zero-based position after sorting SafeRLHF document_ids. It matches cluster_id in saferlhf_with_metadata |
distance |
float32 | Distance from this example to its nearest SafeRLHF example |
score |
float64 | 1 − distance. Higher means closer to harmful data; the removed examples are the highest-scoring ones |
saferlhf_with_metadata adds gradient_embedding (1,856 floats) and cluster_id, as defined above.
Usage
Load SafeTulu for fine-tuning:
from datasets import load_dataset
ds = load_dataset("SaketR1/SafeTulu", "safe_tulu", split="train")
tulu_with_metadata is about 7.5 GB, almost all of it embeddings. If you only need the scores, read just those columns. Parquet stores columns separately, so this downloads tens of MB instead of the whole subset:
import pyarrow as pa
import pyarrow.parquet as pq
from huggingface_hub import HfFileSystem
fs = HfFileSystem()
files = fs.glob("datasets/SaketR1/SafeTulu/data/tulu_with_metadata/*.parquet")
scores = pa.concat_tables(
[pq.ParquetFile(fs.open(f, "rb")).read(columns=["document_id", "score"]) for f in files]
).to_pandas()
Make your own cut, for example removing the top 10% by score. This continues from the snippet above and reads only the text columns, skipping the embeddings:
import pyarrow.compute as pc
from datasets import Dataset
cutoff = scores.score.quantile(0.90)
keep = pa.array(scores.document_id[scores.score < cutoff])
parts = []
for f in files:
t = pq.ParquetFile(fs.open(f, "rb")).read(columns=["document_id", "content_hash", "messages"])
parts.append(t.filter(pc.is_in(t["document_id"], value_set=keep)))
custom = Dataset(pa.concat_tables(parts))
# custom.push_to_hub("your-name/safetulu-10pct")
The Space generates this script for any setting, including per-source cuts and exempting sources.
Licenses
- Tulu 3 subsets (
safe_tulu,removed_tulu,tulu_with_metadata): ODC-BY, following the Tulu 3 SFT mixture. Some of Tulu 3's sources carry their own terms; see the Tulu 3 dataset card. saferlhf_with_metadata: CC BY-NC 4.0, following PKU-SafeRLHF.
The gradient embeddings and scores are released under the same terms as the data they describe.
Intended use
- Fine-tuning models on a safer version of Tulu 3
- Research on data attribution and data filtering for safety
The SafeRLHF subset contains harmful content and is released only to support this research. Don't use it to train models to produce harmful output.