Data Forge & Quality Moat (v0.47.0)
soup data forge — synthetic data pipeline
Chunk → judge → active-prune → JSONL with provenance.
# Smoke test of the plumbing only: no model runs, every answer is a canned placeholder line.
soup data forge --docs ./docs --output ./synth.jsonl --task sft --target-rows 100
# Real synthesis needs a live judge backend.
soup data forge --docs ./docs --output ./synth.jsonl --task sft --target-rows 5000 \
--judge-provider ollama --judge-model llama3.1 --provenance ./provenance.jsonWithout
--judge-providernothing is generated. The default judge is a deterministic offline stub that writesSynthesised answer (offline): ...as every assistant turn and exits 0.--teacheris only a label recorded in the provenance manifest (asjudge_id); it never loads or calls a model, so a stub run still names whatever you passed.--judge-providertakesollama(localhost only),anthropic(key fromANTHROPIC_API_KEY) orvllm.--hub modelscope|modelerspre-fetches--teacheronly when it is anowner/namerepo id.
--task picks the shape of what comes out: sft, preference or tool. --provenance writes a separate manifest, a single JSON document (not JSONL) of {version, row_count, records} where each record is {row_id, source_doc, judge_id, chunk_id, filter_score}, so a generated row can be traced back to the document it came from. The rest tune the pipeline: --uncertainty-threshold for the active-prune step, --max-chunk-chars for chunking, --judge-model / --judge-base-url for the judge, and --hub hf|modelscope|modelers for where the teacher is pulled from.
Each row carries provenance (source doc, chunk id, judge id, filter score).
soup data score — composite quality scorecard
PII + toxicity + langdetect + educational value, plus a Decontaminated cell that is always 0.
soup data score --input ./train.jsonlThe scorecard reports PII-flagged and toxic-flagged counts, the language mix and mean educational value. --benchmarks (mmlu, gsm8k, humaneval, truthfulqa, arc, hellaswag) is checked against that list and nothing else: no benchmark text is bundled or supplied to score, so nothing is compared and Decontaminated stays 0. Use soup data decontaminate --benchmark-file for real overlap removal. Like the individual filters, score reads only text, content and messages[].content; an Alpaca row with instruction and output scores as empty.
Each filter is also addressable individually:
soup data decontaminate --input ./train.jsonl --benchmark-file ./benchmarks/eval_sets.jsonl— drop rows whose n-grams overlap a benchmark file you supply (rows withtext,promptorcontent). Soup bundles no benchmark corpora:--benchmarks gsm8kalone only records a label and removes nothing, and with neither option the command exits 1. The kept rows go toclean.jsonlby default.soup data toxicity— keyword baseline today; a Llama-Guard backend is named in the source but is still unshipped as of v0.75.2soup data langdetect— 2-letter language code per rowsoup data pii— flag email / phone / SSN / credit-card patternssoup data educational— educational-value score per row [0, 1]
Soup is free and Apache-2.0. If it saved you a training run, starring the repo costs nothing and helps most. You can also fund the GPU time behind the work a 4 GB laptop cannot reach.