GOVINDFROM commited on
Commit
0fa2d02
Β·
verified Β·
1 Parent(s): 59387b7

study write up

Browse files
Files changed (1) hide show
  1. README_STUDY.md +358 -0
README_STUDY.md ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DSG: Dynamic Story Graph
2
+
3
+ A revision aware narrative state for book length fiction, and a study of what
4
+ such a state is actually good for.
5
+
6
+ Every number on this page comes from a generated report under
7
+ `artifacts/report/`. Nothing is typed by hand. No large language model appears
8
+ in any metric.
9
+
10
+ ```bash
11
+ python -m dsg doctor # environment and corpus check
12
+ python -m pytest tests/dsg -q # 72 tests, no weights, no network
13
+ ```
14
+
15
+ ## Contents
16
+
17
+ 1. [What this is](#1-what-this-is)
18
+ 2. [The revision calculus](#2-the-revision-calculus)
19
+ 3. [Result one: maintaining a state](#3-result-one-maintaining-a-state)
20
+ 4. [Result two: writing with a state](#4-result-two-writing-with-a-state)
21
+ 5. [Result three: measuring a text](#5-result-three-measuring-a-text)
22
+ 6. [The benchmark](#6-the-benchmark)
23
+ 7. [Architecture](#7-architecture)
24
+ 8. [Reproducing](#8-reproducing)
25
+ 9. [Artifacts](#9-artifacts)
26
+ 10. [Limitations](#10-limitations)
27
+
28
+ ## 1. What this is
29
+
30
+ A reader builds a model of a novel as the novel arrives. At any point they know
31
+ only what they have been told. Fiction is written for that constraint and
32
+ exploits it: identity is withheld and later disclosed, beliefs are planted and
33
+ later corrected, and the world changes while what was true earlier stays true of
34
+ its moment.
35
+
36
+ Automatic narrative extraction usually ignores the constraint and reads the
37
+ finished text with full access to the ending. This project builds the state
38
+ forward instead, under a strict prefix causal rule, and then asks three
39
+ questions.
40
+
41
+ | question | answer | evidence |
42
+ |---|---|---|
43
+ | Can a maintained state stay coherent as a book proceeds? | Yes, and the update rules are what make it so | 28 novels, 3 extractor sizes |
44
+ | Does that state help a model write a long story? | No, in four separate designs | 12,600 generated chapters |
45
+ | Does its contradiction count measure how consistent a text is? | No, it measures the extractor | 215 novels vs 30 stories |
46
+
47
+ The second and third answers are negative. They are reported because they bound
48
+ what the first answer may claim.
49
+
50
+ ## 2. The revision calculus
51
+
52
+ Three update types that append only pipelines conflate.
53
+
54
+ | operation | fires when | effect on the earlier belief |
55
+ |---|---|---|
56
+ | `ELABORATE` | later text specifies what earlier text left open | refined in place, nothing retracted |
57
+ | `SUPERSEDE` | the story world changed | validity interval closed, kept as history |
58
+ | `REVISE` | the reader was wrong, it was never true | retracted, and so is anything derived from it |
59
+
60
+ The split between `SUPERSEDE` and `REVISE` is the operational form of a
61
+ narratological distinction, an event in the story versus a disclosure in the
62
+ telling. It is decided by an inspectable table in `dsg/lexicon.py`, covering
63
+ predicate mutability, evidential source and surface revelation markers. A
64
+ language model never makes that call.
65
+
66
+ Each assertion carries two clocks. Discourse time records while the reader held
67
+ the belief. Story time records while the fact held in the world. A reveal moves
68
+ the first without moving the second; a plot event moves the second.
69
+
70
+ Seven structural invariants are checked after every reading step, including
71
+ prefix causality: no assertion may cite text the reader has not reached.
72
+
73
+ ## 3. Result one: maintaining a state
74
+
75
+ Given a fixed stream of extracted assertions, a store with the full calculus
76
+ holds no self contradictory slots at all, while an append only store accumulates
77
+ them.
78
+
79
+ | corpus and extractor | documents | append only | DSG |
80
+ |---|---|---|---|
81
+ | PDNC, Qwen2.5 7B | 28 novels | 0.371 | **0.000** |
82
+ | PDNC, Qwen2.5 3B | 28 novels | 0.423 | **0.000** |
83
+ | PDNC, Qwen2.5 1.5B | 28 novels | 0.107 | **0.000** |
84
+ | LitBank, Qwen2.5 7B | 100 excerpts | 0.181 | **0.000** |
85
+
86
+ Share of single valued slots holding two or more live conflicting values. Lower
87
+ is better.
88
+
89
+ Each rung of the policy ladder adds exactly one mechanism, so each is priced on
90
+ its own. Every policy replays a byte identical cached proposal stream, so
91
+ differences are attributable to the representation and never to extractor
92
+ variance.
93
+
94
+ ![Mechanism ladder](../docs/figures/fig1-ladder-pdnc7b.png)
95
+
96
+ Reading the panels: persistent state buys a large amount of accuracy and at the
97
+ same time introduces contradiction. Fact revision removes that contradiction on
98
+ every book at no accuracy cost. Deferred commitment converts rollbacks into
99
+ monotone updates. Grey means the interval crosses zero.
100
+
101
+ ![Reading results](../docs/figures/fig2-reading-main.png)
102
+
103
+ The effect holds across extractor sizes.
104
+
105
+ ![Model scale](../docs/figures/fig5-model-scale.png)
106
+
107
+ **Scope.** This is a claim about representations given identical input. It is
108
+ established by holding extraction constant and varying only the update policy.
109
+ It is not a claim that the resulting state is a faithful model of the text. See
110
+ section 5.
111
+
112
+ **What identity accuracy does not show.** A pre registered falsifier fired here.
113
+ The calculus does not improve identity accuracy at any model size, for example
114
+ CoNLL F1 of 0.659 against 0.664 at 7B. What it buys is consistency, not
115
+ accuracy, and the write up says so.
116
+
117
+ ## 4. Result two: writing with a state
118
+
119
+ Four ways of putting the state into a writer's prompt, three runs, 12,600
120
+ chapters, 30 stories, conditions paired within story.
121
+
122
+ | memory given to the writer | violations | prompt tokens | verdict |
123
+ |---|---|---|---|
124
+ | none | 0.487 | 112 | floor |
125
+ | previous chapter | 0.312 | 1,017 | strong and cheap |
126
+ | full transcript | **0.254** | 5,362 | best, at five times the context |
127
+ | serialised state digest | 0.588 | 357 | worse than nothing |
128
+ | digest plus previous chapter | 0.379 | 1,194 | loses to previous chapter alone |
129
+ | beat conditioned retrieval | 0.571 | 212 | worse than nothing |
130
+ | retrieval plus previous chapter | 0.317 | 1,098 | ties previous chapter alone |
131
+ | plus the graph guard | 0.317 | 1,095 | no effect |
132
+
133
+ Paired bootstrap over stories, 95 percent intervals.
134
+
135
+ | comparison | difference | interval | excludes zero |
136
+ |---|---|---|---|
137
+ | serialised digest minus none | +0.083 | [+0.025, +0.142] | yes |
138
+ | beat retrieval minus none | +0.083 | [+0.038, +0.125] | yes |
139
+ | retrieval plus previous minus previous alone | +0.004 | [-0.042, +0.050] | no |
140
+ | guard minus no guard | +0.000 | [-0.033, +0.038] | no |
141
+
142
+ ![Canon violation over chapters](../docs/figures/fig3-canon-violation.png)
143
+
144
+ ![Generation summary](../docs/figures/fig4-generation-final.png)
145
+
146
+ Three things follow.
147
+
148
+ **This is not an extraction ceiling.** The state held 0.492 of the planted canon
149
+ at the moment of writing, half of it correctly, and conditioning on it still
150
+ added nothing. Improving extraction would not have rescued the result.
151
+
152
+ **It replicates a published negative.** The Narrative World Model paper reports
153
+ serialised current state at 0.358 against query conditioned retrieval at 0.898.
154
+ Our serialised digest is structurally their State Memory condition. We reproduce
155
+ their failure with a 3B open model, and find that their success condition does
156
+ not transfer.
157
+
158
+ **More context is not better.** The previous chapter alone at 1,017 tokens beats
159
+ the whole transcript at 5,362 in one run and comes close in another. Recency,
160
+ not volume, is what protects continuity.
161
+
162
+ ### A false positive caught
163
+
164
+ Run one also included a LoRA fine tuned on 6,876 state conditioned examples. It
165
+ scored 0.054 against 0.367 for the base model, an apparent seven fold win. It
166
+ was not real. The model had degenerated into pastiche of its training corpus,
167
+ reproducing even the hard wrap indentation of Project Gutenberg, and a model
168
+ that stops writing about the premise cannot violate its canon.
169
+
170
+ | | base conditions | tuned conditions |
171
+ |---|---|---|
172
+ | chapters mentioning any premise character | 1.000 | 0.765 to 0.812 |
173
+ | canon facts actively restated | 0.838 to 0.887 | 0.092 to 0.163 |
174
+
175
+ `on_premise` is now a first class metric so this cannot be reported as a win
176
+ again. The tuned arm is excluded from every conclusion.
177
+
178
+ ## 5. Result three: measuring a text
179
+
180
+ We tested the instrument's external validity and it failed. The test is reported
181
+ because it constrains section 3.
182
+
183
+ **Design.** 215 published novels and 30 generated stories, first 20 chapters
184
+ each, read with the same extraction prompt, the same reconciler and the same
185
+ policy. If the contradiction rate measures textual consistency, professionally
186
+ edited novels should score far below machine generated ones.
187
+
188
+ | population | documents | mean rate | median |
189
+ |---|---|---|---|
190
+ | published novels | 215 | 0.238 | 0.236 |
191
+ | generated stories | 30 | 0.212 | 0.167 |
192
+
193
+ **AUC 0.394, 95 percent interval [0.259, 0.534].** The interval spans chance.
194
+ Published novels score 0.238, which is not a credible rate of genuine self
195
+ contradiction in edited prose.
196
+
197
+ **Diagnosis.** The flagged conflicts in real novels are extraction artefacts. In
198
+ Peter Pan: `Mrs. Darling.occupation: [wife, mother]`, both true;
199
+ `Nana.material: [Newfoundland dog, dog]`, one thing at two precisions;
200
+ `Wendy.resides_in: [14, nursery]`, a house number and a room.
201
+
202
+ **Correction applied.** `occupation` is genuinely multi valued and was
203
+ reclassified. Refinement detection was broadened so a more precise restatement
204
+ is not treated as a rival value. Both populations dropped, human from 0.267 to
205
+ 0.238, and they still did not separate. Residual extraction noise dominates the
206
+ absolute level.
207
+
208
+ **What this licenses.** Section 3 stands, because it compares policies on
209
+ identical input and a shared noise floor cancels. What is forbidden is reporting
210
+ the contradiction rate as a measure of how consistent a text is, and we do not.
211
+
212
+ ## 6. The benchmark
213
+
214
+ Generated stories have no gold. Human judgement is expensive and a language
215
+ model judge is the thing being avoided. So the gold is planted.
216
+
217
+ Each premise fixes canon facts drawn from closed vocabularies whose
218
+ contradictions are enumerable: eye colour, metal, kinship, trade, birthplace. A
219
+ violation is a deterministic string test near a mention of its subject. A nearby
220
+ correction, for example "not gold but silver", is correctly not counted.
221
+
222
+ Canon is stated in chapter 1 and withheld from chapter 2 onward, so the
223
+ benchmark tests memory rather than prompt following.
224
+
225
+ Two properties make it durable. It is gold by construction, so unlike section 5
226
+ it does not depend on extraction quality at all. And it ships with
227
+ `on_premise`, the denominator that exposes the degenerate model artefact above.
228
+
229
+ The revision trace also yields a descriptive view of where a reader's model is
230
+ refined against where it is corrected.
231
+
232
+ ![Revision profile](../docs/figures/fig6-revision-profile.png)
233
+
234
+ Reported with a shuffled window control, because state growth alone manufactures
235
+ such trends. Under shuffling the elaboration trend disappears, so it is a
236
+ property of narrative order, while most of the revision trend survives, so it is
237
+ largely an artefact of the state getting larger.
238
+
239
+ ## 7. Architecture
240
+
241
+ ```
242
+ prefix causal boundary: at step t the system may read
243
+ window t and state from windows before t, nothing later
244
+
245
+ text ──> windows ──> LLM PROPOSES ──> RECONCILER DISPOSES ──> STATE
246
+ ^ typed lines classify, resolve entities
247
+ | never writes apply the calculus assertions
248
+ | check 7 invariants revision log
249
+ └───────── next window β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
250
+ ```
251
+
252
+ The language model has no write access. It emits proposals; a deterministic
253
+ reconciler classifies each one, resolves identity, applies the calculus and
254
+ enforces the invariants. Two consequences matter: the reasoning under test is
255
+ not a black box, and extraction can be cached and replayed so every policy sees
256
+ a byte identical stream.
257
+
258
+ | module | responsibility |
259
+ |---|---|
260
+ | `schemas.py` | assertions with two clocks, discourse time and story time |
261
+ | `lexicon.py` | predicate mutability, revelation markers, closed ranges |
262
+ | `matching.py` | conservative surface matching, title aware |
263
+ | `store.py` | the calculus, the policy ladder, the revision log |
264
+ | `invariants.py` | seven structural checks plus the bounded slot rate |
265
+ | `proposals.py` | prompt, tolerant line parser, policy free digest |
266
+ | `policies/runner.py` | replays one cached stream under any policy |
267
+ | `generate/` | planted canon, memory conditions, the graph guard |
268
+ | `eval/` | identity, mention probes, speaker, process, discrimination |
269
+ | `infra/` | Modal apps for extraction, dataset building, training, generation |
270
+
271
+ **Title aware matching.** In this corpus "Mr. Bennet", "Mrs. Bennet" and "Miss
272
+ Bennet" are three people who share a surname. Comparing surfaces with the
273
+ honorific stripped collapsed a household into one node, and 74 gold characters
274
+ in Pride and Prejudice into three. Titles are now distinguishing.
275
+
276
+ **The merge constraint.** An identity link may bind an unnamed reference to a
277
+ named character, or link two surface compatible names. It may not assert that
278
+ two separately named characters are one person, because a single bad link fuses
279
+ two people and the fused node then attracts more. This was adopted after
280
+ measurement: across 205 links on one novel, repetition did not separate good
281
+ from bad, since `Mr. Darcy -> Elizabeth` was proposed nine times, as often as
282
+ the correct `Mr. Bingley -> Bingley`.
283
+
284
+ ## 8. Reproducing
285
+
286
+ The GPU stage runs once per corpus and model. Everything downstream is
287
+ deterministic CPU work over cached proposals, so the whole study re scores for
288
+ free after a change to the calculus.
289
+
290
+ ```bash
291
+ # reading study
292
+ modal run dsg/infra/modal_extract.py::main --corpus pdnc --model qwen7b
293
+ python -m dsg study --corpus pdnc --proposals artifacts/proposals/pdnc-qwen7b-w3200 \
294
+ --out artifacts/results/pdnc-qwen7b
295
+ python -m dsg report --results artifacts/results/pdnc-qwen7b --out artifacts/report/pdnc-qwen7b
296
+
297
+ # generation study
298
+ scripts/run_pipeline.sh # dataset, LoRA, generation, report
299
+ STAGE=generate scripts/run_pipeline.sh # one stage
300
+
301
+ # operating on an unreliable connection
302
+ scripts/modal_control.sh status | stop | fetch
303
+ ```
304
+
305
+ Jobs are deliberately not detached. Losing the client kills the container, which
306
+ stops the billing. That is only safe because every stage checkpoints as it goes,
307
+ the dataset build every two chapters, the trainer every 50 steps, generation
308
+ after every chapter, and re running the same run id resumes. `scripts/supervise.sh`
309
+ waits for the network to return and retries, so progress accumulates across
310
+ drops.
311
+
312
+ `--backend mock` runs the entire pipeline with no weights and no network, which
313
+ is what continuous integration exercises.
314
+
315
+ ## 9. Artifacts
316
+
317
+ | artifact | location |
318
+ |---|---|
319
+ | training dataset, 6,876 examples from 215 novels | `GOVINDFROM/dsg-state-continuation` |
320
+ | LoRA adapter, validation loss 2.7182 to 2.5439 | `GOVINDFROM/dsg-writer-qwen3b` |
321
+ | results, figures, raw generations, extraction proposals | `GOVINDFROM/dsg-artifacts` |
322
+
323
+ Corpora are fetched from source and never redistributed here.
324
+
325
+ | corpus | supplies | source |
326
+ |---|---|---|
327
+ | PDNC, 28 novels | full text, gold alias sets, 37,131 gold quotations with speakers | Priya22/project-dialogism-novel-corpus |
328
+ | LitBank, 100 excerpts | gold coreference, short context control | dbamman/litbank |
329
+ | Project Gutenberg, 215 novels | training corpus for the writer | sedthh/gutenberg_english |
330
+
331
+ ## 10. Limitations
332
+
333
+ **Extraction is the binding constraint everywhere.** Capture by canon type at
334
+ chapter 20: eye colour 0.50, trade 0.38, hair 0.33, birthplace 0.23, object
335
+ material 0.12. The extractor is character centric and largely ignores objects.
336
+
337
+ **Identity gold is alias level.** PDNC alias sets are surface strings, not full
338
+ mention level coreference. The mention linking probe partly compensates but
339
+ covers only referring expressions inside quotations.
340
+
341
+ **We are not competitive with supervised coreference and do not claim to be.**
342
+ That line reaches roughly 81 CoNLL F1 on LitBank with supervised systems scored
343
+ on mention clusters. Our identity plane is unsupervised and scored on a
344
+ different item set. The numbers are not comparable.
345
+
346
+ **The generation premises are synthetic.** That is the price of controlled gold.
347
+ The method transfers to any premise with checkable attributes.
348
+
349
+ **One model family.** Everything is Qwen2.5. A second family would establish
350
+ that the negatives are not family specific.
351
+
352
+ **The `SUPERSEDE` versus `REVISE` decision is itself unevaluated.** It is the
353
+ conceptual centre and the least tested part. A few hundred hand annotated
354
+ conflict pairs would settle it.
355
+
356
+ **Nicknames are unrecoverable** under the merge constraint. "Lizzy" and
357
+ "Elizabeth" share no surface material, so the guard that correctly blocks
358
+ "Jane to Elizabeth" also blocks the correct "Lizzy to Elizabeth".