Text Generation
PEFT
Safetensors
lora
trl
grpo
gdpo
dpo
divpo
rlhf
diversity
creative-writing
mode-collapse
Instructions to use Mercity/creative-writing-llm with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use Mercity/creative-writing-llm with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Add model card
Browse files
README.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
base_model: Qwen/Qwen3-4B-Instruct-2507
|
| 4 |
+
library_name: peft
|
| 5 |
+
pipeline_tag: text-generation
|
| 6 |
+
tags:
|
| 7 |
+
- lora
|
| 8 |
+
- peft
|
| 9 |
+
- trl
|
| 10 |
+
- grpo
|
| 11 |
+
- gdpo
|
| 12 |
+
- dpo
|
| 13 |
+
- divpo
|
| 14 |
+
- rlhf
|
| 15 |
+
- diversity
|
| 16 |
+
- creative-writing
|
| 17 |
+
- mode-collapse
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
# Diversity-aware post-training for creative story generation (Qwen3-4B)
|
| 21 |
+
|
| 22 |
+
Research artifacts for a controlled study of **whether RL post-training can raise the
|
| 23 |
+
*semantic* diversity of short-story generation without paying for it in quality**.
|
| 24 |
+
|
| 25 |
+
Everything here is measured, not asserted: the repo carries the LoRA adapters, the
|
| 26 |
+
scored generation pool they were selected from, the per-step reward telemetry, the
|
| 27 |
+
judge-calibration evidence, the experiment reports, and the source that produced all
|
| 28 |
+
of it.
|
| 29 |
+
|
| 30 |
+
> β οΈ **Work in progress.** Only **E0** (quality-only baseline) has finished its full
|
| 31 |
+
> 300-step run. **E1** was still training when this snapshot was uploaded β its
|
| 32 |
+
> checkpoints stop at **step 200 of 300**. **E2, E3 and E4 have not been trained yet**;
|
| 33 |
+
> their configs are present, their adapters are not. No cross-arm comparison exists yet,
|
| 34 |
+
> and none should be read into this repo.
|
| 35 |
+
|
| 36 |
+
---
|
| 37 |
+
|
| 38 |
+
## The finding this study is built around
|
| 39 |
+
|
| 40 |
+
Sampling the **base** policy 16 times per prompt over 1,000 prompts (16,000 scored
|
| 41 |
+
stories, `outputs/pool_4b/`) gives a mean **effective rank of 2.006 out of a ceiling of
|
| 42 |
+
16**. Sixteen independent samples of the same prompt span roughly two effective
|
| 43 |
+
directions in embedding space; mean pairwise distance is 0.132, i.e. same-prompt stories
|
| 44 |
+
sit at about 0.87 cosine similarity.
|
| 45 |
+
|
| 46 |
+
Quality-only RL does not fix this. E0 ran 300 steps of GRPO on the judge's quality score
|
| 47 |
+
alone and moved judge quality **+0.30** (6.557 β 6.860, first vs. last quarter of the run)
|
| 48 |
+
while the diversity statistics stayed flat (mean pairwise deviation 0.1354 β 0.1391;
|
| 49 |
+
mean group log-det β12.81 β β12.64). The held-out checkpoint study
|
| 50 |
+
(`outputs/ckpt_study/`, 10 prompts Γ 6 samples per checkpoint) tells the same story:
|
| 51 |
+
|
| 52 |
+
| step | judge quality | effective rank | deviation |
|
| 53 |
+
|---|---|---|---|
|
| 54 |
+
| 0 (base) | 6.65 | 1.677 | 0.130 |
|
| 55 |
+
| 100 | 6.78 | 1.655 | 0.128 |
|
| 56 |
+
| 200 | 6.75 | 1.700 | 0.135 |
|
| 57 |
+
| 300 | 7.03 | 1.712 | 0.139 |
|
| 58 |
+
|
| 59 |
+
Craft improves; the model still writes the same story six times. That gap is what the
|
| 60 |
+
diversity arms exist to close.
|
| 61 |
+
|
| 62 |
+
---
|
| 63 |
+
|
| 64 |
+
## Method
|
| 65 |
+
|
| 66 |
+
**Base policy.** `Qwen/Qwen3-4B-Instruct-2507`, LoRA **r=32, alpha=64, dropout 0.0** on all
|
| 67 |
+
attention and MLP projections (`q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj`).
|
| 68 |
+
|
| 69 |
+
**Online arms.** GRPO via **TRL 1.10** with `multi_objective_aggregation="normalize_then_sum"`,
|
| 70 |
+
which is a line-for-line implementation of **GDPO** (arXiv 2601.05242): each reward channel is
|
| 71 |
+
normalized *within its prompt group* before the channels are summed and the advantage is
|
| 72 |
+
normalized batch-wise. Generation is **vLLM colocated** in the training process. G=8 samples per
|
| 73 |
+
prompt, generation batch 16 (2 prompts Γ 8), `max_completion_length=1024`, lr 3e-5 with
|
| 74 |
+
`constant_with_warmup`, beta (KL) 0.02, 300 steps. Everything ran on a **single RTX 5090 (32 GB)** β
|
| 75 |
+
the 32 GB budget is what forced the 4B policy, since colocated GRPO needs two resident copies of
|
| 76 |
+
the weights.
|
| 77 |
+
|
| 78 |
+
**Offline arms.** DPO over preference pairs mined from the same 16k pool
|
| 79 |
+
(beta 0.1, sigmoid loss, lr 5e-6, epochs chosen for optimizer-step parity across arms).
|
| 80 |
+
|
| 81 |
+
**Reward channels.**
|
| 82 |
+
|
| 83 |
+
- `quality` β judge score, per story.
|
| 84 |
+
- `deviation` `d_i` β mean embedding distance from a sample to the rest of its group
|
| 85 |
+
(`BAAI/bge-base-en-v1.5`), credited only if judge quality β₯ tau=5.
|
| 86 |
+
- `marginal` `m_i` β the sample's marginal contribution to the group's log-determinant
|
| 87 |
+
(a set-level diversity volume), z-scored within group.
|
| 88 |
+
|
| 89 |
+
Every diversity credit is **per-sample by construction**. A single set-level scalar shared by a
|
| 90 |
+
whole group has zero within-group variance and therefore contributes exactly nothing to a GRPO
|
| 91 |
+
advantage β the failure mode diagnosed in `prior_run/` and written up in
|
| 92 |
+
`logs/experiments/00_prior_run_autopsy.md`.
|
| 93 |
+
|
| 94 |
+
**Judge.** `deepseek-v4-flash-0731` via OpenRouter, scoring **one story at a time on an absolute
|
| 95 |
+
rubric** (not batched relative scoring), with reasoning disabled. Calibrated before any training
|
| 96 |
+
against four cells with known ordering: detects incoherence (Ξ 2.25), detects repetition (Ξ 4.67),
|
| 97 |
+
not saturated (sd 0.76). See `logs/experiments/01_judge_calibration.md`.
|
| 98 |
+
|
| 99 |
+
**Programmatic gates.** Completeness, 150β600 word window, 4-gram / line loop detection and
|
| 100 |
+
`finish_reason == "length"` are checked deterministically before a story is ever judged, so
|
| 101 |
+
truncated or degenerate text cannot earn reward through any channel.
|
| 102 |
+
|
| 103 |
+
### The arms
|
| 104 |
+
|
| 105 |
+
| arm | type | reward / objective | status in this repo |
|
| 106 |
+
|---|---|---|---|
|
| 107 |
+
| **E0-baseline** | GRPO | quality only β the collapse control | β
complete, 300 steps + `final` |
|
| 108 |
+
| **E1-div-individual** | GRPO | quality + pairwise deviation `d_i` (alpha 0.5, gated at tau=5) | π‘ partial, steps 50β200 of 300 |
|
| 109 |
+
| **E2-div-group** | GRPO | quality + deviation + log-det marginal `m_i` (alpha 0.5, gamma 0.5) | β¬ config only, not trained |
|
| 110 |
+
| **E3-multipos** | DPO | multi-positive, deviation-weighted loss; 4 greedy-diverse chosens vs. rotating negatives (3,593 rows) | β¬ config + pairs only |
|
| 111 |
+
| **E4a-divpo-emb** | DPO | faithful DivPO, embedding-deviation criterion (956 rows, rho=7) | β¬ config + pairs only |
|
| 112 |
+
| **E4b-divpo-prob** | DPO | faithful DivPO, lowest length-normalized logprob among quality β₯ rho | β¬ config + pairs only |
|
| 113 |
+
|
| 114 |
+
---
|
| 115 |
+
|
| 116 |
+
## Repository layout
|
| 117 |
+
|
| 118 |
+
```
|
| 119 |
+
outputs/
|
| 120 |
+
E0-baseline/ LoRA adapters: checkpoint-{50..300} + final
|
| 121 |
+
reward_history.json per-step reward telemetry (300 steps)
|
| 122 |
+
trl_log_history.json full TRL log history
|
| 123 |
+
judge_cost.json judge call/token/USD accounting
|
| 124 |
+
E1-div-individual/ same structure, checkpoints 50-200 (run in progress)
|
| 125 |
+
pool_4b/ pool_train.jsonl 16,000 scored base-policy stories
|
| 126 |
+
emb_train.npy their bge-base-en-v1.5 embeddings
|
| 127 |
+
summary_train.json pool-level summary stats
|
| 128 |
+
pairs_4b/ divpo_emb_train.jsonl, divpo_prob_train.jsonl,
|
| 129 |
+
multipos_train.jsonl, pair_stats_train.json
|
| 130 |
+
ckpt_study/E0-baseline/ stories.md, raw.json, metrics.csv (per-checkpoint story dumps)
|
| 131 |
+
logs/
|
| 132 |
+
experiments/ the written reports (start here)
|
| 133 |
+
figures/ plots referenced by the reports
|
| 134 |
+
configs/ one YAML per arm, with the reasoning for every knob in comments
|
| 135 |
+
src/ all Python: training, rewards, diversity, judge, gates, eval, tests
|
| 136 |
+
data/ train/eval prompt splits + split metadata
|
| 137 |
+
prior_run/ the previous, failed run's artifacts (see autopsy)
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
**Read the reports in this order:** `00_prior_run_autopsy.md` β `01_judge_calibration.md` β
|
| 141 |
+
`02_setup_and_deviations.md` β `03_pool_4b_baseline.md` β `04_E0_checkpoint_story_study.md` β
|
| 142 |
+
`E0-baseline.md`.
|
| 143 |
+
|
| 144 |
+
### Data schemas
|
| 145 |
+
|
| 146 |
+
`outputs/pool_4b/pool_train.jsonl` β one story per line:
|
| 147 |
+
`prompt_id, prompt, idx, text, n_words, n_tokens, finish_reason, gate_passed, gate_reasons,
|
| 148 |
+
ends_cleanly, quality, novelty, deviation, marginal, group_logdet, mean_logprob, cumlogprob`.
|
| 149 |
+
Row *i* of `emb_train.npy` corresponds to line *i* of the JSONL.
|
| 150 |
+
|
| 151 |
+
`outputs/pairs_4b/*.jsonl` β DPO rows: `prompt_id, prompt, chosen, rejected` (+ per-row weight
|
| 152 |
+
for the multi-positive set).
|
| 153 |
+
|
| 154 |
+
`data/` β 1,000 train and 50 eval prompts (seed 42), filtered to 10β60 words from 272,600 scanned;
|
| 155 |
+
`split_meta.json` also carries the exact system prompt used for every generation in the study.
|
| 156 |
+
|
| 157 |
+
---
|
| 158 |
+
|
| 159 |
+
## Using an adapter
|
| 160 |
+
|
| 161 |
+
Each checkpoint directory is a standard PEFT adapter (`adapter_model.safetensors` +
|
| 162 |
+
`adapter_config.json`, ~253 MB each).
|
| 163 |
+
|
| 164 |
+
```python
|
| 165 |
+
from huggingface_hub import snapshot_download
|
| 166 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 167 |
+
from peft import PeftModel
|
| 168 |
+
|
| 169 |
+
path = snapshot_download(
|
| 170 |
+
"Mercity/creative-writing-llm",
|
| 171 |
+
allow_patterns="outputs/E0-baseline/final/*",
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
+
tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-4B-Instruct-2507")
|
| 175 |
+
base = AutoModelForCausalLM.from_pretrained(
|
| 176 |
+
"Qwen/Qwen3-4B-Instruct-2507", dtype="auto", device_map="auto"
|
| 177 |
+
)
|
| 178 |
+
model = PeftModel.from_pretrained(base, f"{path}/outputs/E0-baseline/final")
|
| 179 |
+
|
| 180 |
+
system = (
|
| 181 |
+
"You are a fiction writer. Write a complete short story of 200-500 words responding "
|
| 182 |
+
"to the writing prompt.\nWrite only the story: no title, no preamble, no commentary, "
|
| 183 |
+
"no author's note.\nFinish inside the word budget. The story must reach a real ending, "
|
| 184 |
+
"not stop mid-scene."
|
| 185 |
+
)
|
| 186 |
+
msgs = [{"role": "system", "content": system},
|
| 187 |
+
{"role": "user", "content": "A lighthouse keeper receives a letter addressed to the sea."}]
|
| 188 |
+
ids = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device)
|
| 189 |
+
out = model.generate(ids, max_new_tokens=1024, temperature=1.0, top_p=1.0, do_sample=True)
|
| 190 |
+
print(tok.decode(out[0][ids.shape[-1]:], skip_special_tokens=True))
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
Swap `outputs/E0-baseline/final` for `outputs/E0-baseline/checkpoint-150`,
|
| 194 |
+
`outputs/E1-div-individual/checkpoint-200`, etc. The study sampled at T=1.0 during training and
|
| 195 |
+
T=0.9 / top_p=0.95 for the checkpoint story study.
|
| 196 |
+
|
| 197 |
+
---
|
| 198 |
+
|
| 199 |
+
## Selected numbers
|
| 200 |
+
|
| 201 |
+
**Base-policy pool** (`logs/experiments/03_pool_4b_baseline.md`, n=16,000):
|
| 202 |
+
|
| 203 |
+
| metric | value |
|
| 204 |
+
|---|---|
|
| 205 |
+
| gate pass rate | 0.992 |
|
| 206 |
+
| judge quality (mean Β± sd) | 6.447 Β± 0.833 |
|
| 207 |
+
| mean pairwise deviation | 0.1321 |
|
| 208 |
+
| mean group log-det | β30.42 |
|
| 209 |
+
| **mean effective rank (ceiling 16)** | **2.006 Β± 0.323** |
|
| 210 |
+
| corr(quality, effective rank) | β0.108 |
|
| 211 |
+
| corr(deviation, effective rank) | 0.992 |
|
| 212 |
+
|
| 213 |
+
Quality and diversity are **largely independent** across prompts (r = β0.108), so a method that
|
| 214 |
+
raises diversity without lowering quality is exploiting existing slack rather than defying a
|
| 215 |
+
tradeoff.
|
| 216 |
+
|
| 217 |
+
**E0 run** (`logs/experiments/E0-baseline.md`, 300 steps, 4,800 stories judged, verdict *healthy*):
|
| 218 |
+
|
| 219 |
+
| metric | early (first 25%) | late (last 25%) | Ξ |
|
| 220 |
+
|---|---|---|---|
|
| 221 |
+
| judge quality (passing) | 6.557 | 6.860 | **+0.303** |
|
| 222 |
+
| mean deviation | 0.1354 | 0.1391 | +0.004 |
|
| 223 |
+
| mean log-det | β12.81 | β12.64 | +0.165 |
|
| 224 |
+
| gate pass | 0.9925 | 0.9875 | β0.005 |
|
| 225 |
+
| policy entropy | 1.2535 | 1.2274 | β0.026 (β2.1%) |
|
| 226 |
+
|
| 227 |
+
No entropy collapse, and the reward-hacking trip conditions (diversity up while quality or
|
| 228 |
+
validity falls) were not tripped. Judge cost for the whole E0 run: **$0.84** over 5,109 calls.
|
| 229 |
+
|
| 230 |
+
**Qualitative** (`logs/experiments/04_E0_checkpoint_story_study.md`): the collapse is a *tonal
|
| 231 |
+
monoculture*, not a lexical one β 92β95% of stories carry solemn/elegiac vocabulary against ~15%
|
| 232 |
+
comic, even on explicitly comic prompts, and verbatim opening duplication *rises* with
|
| 233 |
+
quality-only training. This predicts that n-gram metrics (distinct-4, self-BLEU) will separate the
|
| 234 |
+
arms far less than effective rank does.
|
| 235 |
+
|
| 236 |
+
---
|
| 237 |
+
|
| 238 |
+
## Environment
|
| 239 |
+
|
| 240 |
+
torch 2.13.0+cu130 Β· vLLM 0.27.1 Β· transformers 5.15.0 Β· TRL 1.10.0 Β· PEFT 0.20.0 Β·
|
| 241 |
+
sentence-transformers 5.7.0 (`BAAI/bge-base-en-v1.5`) Β· single RTX 5090, 32.6 GB, sm_120.
|
| 242 |
+
FlashInfer is disabled (it misdetects sm_120); Liger is disabled because it suppresses TRL's
|
| 243 |
+
`entropy` metric.
|
| 244 |
+
|
| 245 |
+
## Caveats and honest notes
|
| 246 |
+
|
| 247 |
+
- **E1 is mid-flight.** Its checkpoints are a snapshot at step 200/300 and its reports do not
|
| 248 |
+
exist yet. E2/E3/E4 are unrun. Do not read arm comparisons out of this repo.
|
| 249 |
+
- **`04_E0_checkpoint_story_study.md` documents an earlier, partial 163-step E0 run** (at the
|
| 250 |
+
pre-correction lr 3e-6). `outputs/ckpt_study/E0-baseline/metrics.csv` is the *regenerated*
|
| 251 |
+
version covering all checkpoints of the final 300-step run; where they disagree, trust the CSV.
|
| 252 |
+
- **Learning rate deviates from the plan** (3e-5, not 3e-6): at 3e-6 the adapter was effectively
|
| 253 |
+
frozen β KL pinned near 8e-4 for 171 steps with every metric inside its noise band. The evidence
|
| 254 |
+
is recorded in the config comments and `02_setup_and_deviations.md`.
|
| 255 |
+
- **Optimizer/scheduler/RNG state is not included** for E1's checkpoints. It is resume-only state,
|
| 256 |
+
is rotated away by `save_total_limit`, and none of it is needed to load or evaluate an adapter.
|
| 257 |
+
- **`prior_run/train.py` is a redacted copy** β the original contained a hard-coded OpenRouter API
|
| 258 |
+
key, replaced here with a placeholder. Nothing else in the file was changed.
|
| 259 |
+
- **Judge is not perfect.** It fails the truncation-sensitivity check (AβB = 1.33 against a 2.0
|
| 260 |
+
bar), which is tolerated only because truncation is caught deterministically by the gates before
|
| 261 |
+
any story reaches the judge. Pool-scoring judge failure rate was 0.45%.
|
| 262 |
+
- Every deviation from the original plan is enumerated in `logs/experiments/02_setup_and_deviations.md`
|
| 263 |
+
rather than discovered in a footnote.
|
| 264 |
+
|
| 265 |
+
## References
|
| 266 |
+
|
| 267 |
+
- GDPO β group-wise reward normalization for multi-objective RL, arXiv 2601.05242 (Liu et al., NVIDIA)
|
| 268 |
+
- DivPO β Lanchantin et al., 2025 (diverse preference optimization)
|
| 269 |
+
- Effective rank β Roy & Vetterli, the exp-entropy of the Gram spectrum, used here as the primary
|
| 270 |
+
continuous mode-count metric (k-means + silhouette was measured to be unable to separate collapse
|
| 271 |
+
from spread and was demoted)
|
| 272 |
+
|
| 273 |
+
## License
|
| 274 |
+
|
| 275 |
+
Apache-2.0, matching the `Qwen/Qwen3-4B-Instruct-2507` base model. The prompt splits derive from a
|
| 276 |
+
public writing-prompts corpus; stories in `outputs/pool_4b/` are model generations.
|