dipo 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dipo-0.2.0/LICENSE +21 -0
- dipo-0.2.0/PKG-INFO +278 -0
- dipo-0.2.0/README.md +238 -0
- dipo-0.2.0/dipo/__init__.py +22 -0
- dipo-0.2.0/dipo/__main__.py +103 -0
- dipo-0.2.0/dipo/common/__init__.py +0 -0
- dipo-0.2.0/dipo/common/log.py +65 -0
- dipo-0.2.0/dipo/common/training.py +613 -0
- dipo-0.2.0/dipo/rst/__init__.py +34 -0
- dipo-0.2.0/dipo/rst/data/__init__.py +0 -0
- dipo-0.2.0/dipo/rst/data/metrics.py +280 -0
- dipo-0.2.0/dipo/rst/data/reader.py +280 -0
- dipo-0.2.0/dipo/rst/data/seg_metrics.py +157 -0
- dipo-0.2.0/dipo/rst/data/tree.py +1106 -0
- dipo-0.2.0/dipo/rst/parsers/__init__.py +94 -0
- dipo-0.2.0/dipo/rst/parsers/common/__init__.py +0 -0
- dipo-0.2.0/dipo/rst/parsers/common/biaffine.py +49 -0
- dipo-0.2.0/dipo/rst/parsers/common/config.py +135 -0
- dipo-0.2.0/dipo/rst/parsers/common/curriculum.py +144 -0
- dipo-0.2.0/dipo/rst/parsers/common/detokenization.py +43 -0
- dipo-0.2.0/dipo/rst/parsers/common/encoding.py +474 -0
- dipo-0.2.0/dipo/rst/parsers/common/generative_eval.py +232 -0
- dipo-0.2.0/dipo/rst/parsers/common/inference.py +107 -0
- dipo-0.2.0/dipo/rst/parsers/common/pointer.py +47 -0
- dipo-0.2.0/dipo/rst/parsers/common/predict_cli.py +152 -0
- dipo-0.2.0/dipo/rst/parsers/common/segmentation.py +300 -0
- dipo-0.2.0/dipo/rst/parsers/common/seqgen.py +522 -0
- dipo-0.2.0/dipo/rst/parsers/common/sexp_constraints.py +763 -0
- dipo-0.2.0/dipo/rst/parsers/common/whitespace.py +110 -0
- dipo-0.2.0/dipo/rst/parsers/dmrst/__init__.py +2 -0
- dipo-0.2.0/dipo/rst/parsers/dmrst/configuration_dmrst.py +174 -0
- dipo-0.2.0/dipo/rst/parsers/dmrst/modeling_dmrst.py +818 -0
- dipo-0.2.0/dipo/rst/parsers/dmrst/predict_dmrst.py +9 -0
- dipo-0.2.0/dipo/rst/parsers/dmrst/train_dmrst.py +528 -0
- dipo-0.2.0/dipo/rst/parsers/gen/__init__.py +4 -0
- dipo-0.2.0/dipo/rst/parsers/gen/backbones/__init__.py +10 -0
- dipo-0.2.0/dipo/rst/parsers/gen/backbones/base.py +466 -0
- dipo-0.2.0/dipo/rst/parsers/gen/backbones/decoder_only.py +415 -0
- dipo-0.2.0/dipo/rst/parsers/gen/backbones/seq2seq.py +372 -0
- dipo-0.2.0/dipo/rst/parsers/gen/configuration_gen.py +299 -0
- dipo-0.2.0/dipo/rst/parsers/gen/decode.py +337 -0
- dipo-0.2.0/dipo/rst/parsers/gen/errors.py +31 -0
- dipo-0.2.0/dipo/rst/parsers/gen/eval_gen.py +176 -0
- dipo-0.2.0/dipo/rst/parsers/gen/modeling_gen.py +393 -0
- dipo-0.2.0/dipo/rst/parsers/gen/predict_gen.py +9 -0
- dipo-0.2.0/dipo/rst/parsers/gen/serializations/__init__.py +10 -0
- dipo-0.2.0/dipo/rst/parsers/gen/serializations/base.py +231 -0
- dipo-0.2.0/dipo/rst/parsers/gen/serializations/sexp.py +487 -0
- dipo-0.2.0/dipo/rst/parsers/gen/serializations/sr.py +351 -0
- dipo-0.2.0/dipo/rst/parsers/gen/train_gen.py +484 -0
- dipo-0.2.0/dipo/rst/parsers/hfhub/__init__.py +22 -0
- dipo-0.2.0/dipo/rst/parsers/hfhub/datasets.py +188 -0
- dipo-0.2.0/dipo/rst/parsers/hfhub/hub.py +502 -0
- dipo-0.2.0/dipo/rst/parsers/hfhub/push.py +49 -0
- dipo-0.2.0/dipo/rst/parsers/icl/__init__.py +14 -0
- dipo-0.2.0/dipo/rst/parsers/icl/_cli_common.py +48 -0
- dipo-0.2.0/dipo/rst/parsers/icl/configuration_icl.py +274 -0
- dipo-0.2.0/dipo/rst/parsers/icl/eval_icl.py +239 -0
- dipo-0.2.0/dipo/rst/parsers/icl/eval_metrics.py +95 -0
- dipo-0.2.0/dipo/rst/parsers/icl/modeling_icl.py +293 -0
- dipo-0.2.0/dipo/rst/parsers/icl/predict_icl.py +84 -0
- dipo-0.2.0/dipo/rst/parsers/icl/provider.py +445 -0
- dipo-0.2.0/dipo/rst/parsers/icl/serialize.py +748 -0
- dipo-0.2.0/dipo/rst/parsers/sr_biaffine/__init__.py +2 -0
- dipo-0.2.0/dipo/rst/parsers/sr_biaffine/configuration_sr_biaffine.py +82 -0
- dipo-0.2.0/dipo/rst/parsers/sr_biaffine/modeling_sr_biaffine.py +240 -0
- dipo-0.2.0/dipo/rst/parsers/sr_biaffine/predict_sr_biaffine.py +9 -0
- dipo-0.2.0/dipo/rst/parsers/sr_biaffine/train_sr_biaffine.py +369 -0
- dipo-0.2.0/dipo/rst/parsers/topdown_biaffine/__init__.py +2 -0
- dipo-0.2.0/dipo/rst/parsers/topdown_biaffine/configuration_topdown_biaffine.py +76 -0
- dipo-0.2.0/dipo/rst/parsers/topdown_biaffine/modeling_topdown_biaffine.py +216 -0
- dipo-0.2.0/dipo/rst/parsers/topdown_biaffine/predict_topdown_biaffine.py +9 -0
- dipo-0.2.0/dipo/rst/parsers/topdown_biaffine/train_topdown_biaffine.py +369 -0
- dipo-0.2.0/dipo/runs.py +745 -0
- dipo-0.2.0/dipo.egg-info/PKG-INFO +278 -0
- dipo-0.2.0/dipo.egg-info/SOURCES.txt +117 -0
- dipo-0.2.0/dipo.egg-info/dependency_links.txt +1 -0
- dipo-0.2.0/dipo.egg-info/entry_points.txt +3 -0
- dipo-0.2.0/dipo.egg-info/requires.txt +16 -0
- dipo-0.2.0/dipo.egg-info/top_level.txt +1 -0
- dipo-0.2.0/pyproject.toml +86 -0
- dipo-0.2.0/setup.cfg +4 -0
- dipo-0.2.0/tests/test_action_loss_chunked.py +106 -0
- dipo-0.2.0/tests/test_beam_nan_poisoning.py +95 -0
- dipo-0.2.0/tests/test_budget_range_gold_edu_forcer.py +369 -0
- dipo-0.2.0/tests/test_cjk_split.py +100 -0
- dipo-0.2.0/tests/test_decode_invariants.py +210 -0
- dipo-0.2.0/tests/test_decode_positional_budget.py +160 -0
- dipo-0.2.0/tests/test_edu_token_alignment.py +139 -0
- dipo-0.2.0/tests/test_encoder_backbones.py +274 -0
- dipo-0.2.0/tests/test_gen_accum_windows.py +143 -0
- dipo-0.2.0/tests/test_gen_batched_greedy_equivalence.py +180 -0
- dipo-0.2.0/tests/test_gen_batched_sexp_cascade.py +171 -0
- dipo-0.2.0/tests/test_gen_document_weights.py +39 -0
- dipo-0.2.0/tests/test_gen_equivalence.py +191 -0
- dipo-0.2.0/tests/test_gen_inference_method.py +44 -0
- dipo-0.2.0/tests/test_gen_overlength.py +90 -0
- dipo-0.2.0/tests/test_gen_train_smoke.py +165 -0
- dipo-0.2.0/tests/test_gold_edu_beam.py +183 -0
- dipo-0.2.0/tests/test_gold_edu_semantics_parity.py +96 -0
- dipo-0.2.0/tests/test_icl.py +491 -0
- dipo-0.2.0/tests/test_model_card.py +81 -0
- dipo-0.2.0/tests/test_peft_inert_fields.py +116 -0
- dipo-0.2.0/tests/test_qlora_4bit_loading.py +215 -0
- dipo-0.2.0/tests/test_retired_config_keys.py +66 -0
- dipo-0.2.0/tests/test_seq2seq_input_budget.py +190 -0
- dipo-0.2.0/tests/test_seqgen_checkpoint_and_batch.py +113 -0
- dipo-0.2.0/tests/test_sexp_constraints.py +712 -0
- dipo-0.2.0/tests/test_sexp_empty_tree_fallback.py +101 -0
- dipo-0.2.0/tests/test_sexp_roundtrip.py +100 -0
- dipo-0.2.0/tests/test_sexp_words_labels.py +176 -0
- dipo-0.2.0/tests/test_shift_reduce_roundtrip.py +141 -0
- dipo-0.2.0/tests/test_sr_biaffine.py +108 -0
- dipo-0.2.0/tests/test_sr_decode_state.py +105 -0
- dipo-0.2.0/tests/test_sr_deep_tree_degrades.py +63 -0
- dipo-0.2.0/tests/test_trainable_only_shadow_checkpoint.py +211 -0
- dipo-0.2.0/tests/test_training_checkpoint.py +181 -0
- dipo-0.2.0/tests/test_whitespace_input.py +174 -0
- dipo-0.2.0/tests/test_wsd_scheduler.py +62 -0
dipo-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Luke Gessler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
dipo-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dipo
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Dipo, the Discourse Parsing Omnibus: a collection of easy-to-use discourse parsers and associated code.
|
|
5
|
+
Author-email: Luke Gessler <lukegessler@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/larc-iu/dipo
|
|
8
|
+
Project-URL: Repository, https://github.com/larc-iu/dipo
|
|
9
|
+
Project-URL: Issues, https://github.com/larc-iu/dipo/issues
|
|
10
|
+
Keywords: discourse parsing,rhetorical structure theory,RST,NLP,computational linguistics
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: torch
|
|
25
|
+
Requires-Dist: transformers
|
|
26
|
+
Requires-Dist: huggingface_hub
|
|
27
|
+
Requires-Dist: tonga-config
|
|
28
|
+
Requires-Dist: lxml
|
|
29
|
+
Requires-Dist: rich
|
|
30
|
+
Requires-Dist: sentencepiece
|
|
31
|
+
Requires-Dist: sacremoses
|
|
32
|
+
Requires-Dist: peft
|
|
33
|
+
Requires-Dist: tensorboard
|
|
34
|
+
Requires-Dist: setuptools<81
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: ruff; extra == "dev"
|
|
37
|
+
Requires-Dist: build; extra == "dev"
|
|
38
|
+
Requires-Dist: twine; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# Dipo
|
|
42
|
+
|
|
43
|
+
The **<u>Di</u>scourse <u>P</u>arsing <u>O</u>mnibus** (Dipo, said like "depot") is a collection of easy-to-use discourse parsers and other code related to discourse parsing.
|
|
44
|
+
|
|
45
|
+
Dipo was formerly called IUDEX (`larc-iudex` on PyPI, with the command `iudex`).
|
|
46
|
+
|
|
47
|
+
## Setup
|
|
48
|
+
|
|
49
|
+
For the latest release:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
pip install dipo
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For the current state of `master`:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
pip install git+https://github.com/larc-iu/dipo
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or for development:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
git clone https://github.com/larc-iu/dipo && cd dipo
|
|
65
|
+
pip install -e .
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The old `iudex` command still works for now, as a deprecated alias of `dipo` that prints a notice. `import iudex` is now `import dipo`.
|
|
69
|
+
|
|
70
|
+
## Quick Start with Inference
|
|
71
|
+
|
|
72
|
+
Parse a sample document end-to-end with a pretrained DMRST model pulled from the HuggingFace Hub. From the command line:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
dipo dmrst predict \
|
|
76
|
+
--hub-id larc-iu/dmrst-ettin-400m-gum-12.1.0 \
|
|
77
|
+
--text "Although the experiment was carefully designed, the results were inconclusive. We plan to repeat it tonight."
|
|
78
|
+
```
|
|
79
|
+
This yields the parsed tree in `.rs3` format printed to `stdout`:
|
|
80
|
+
```xml
|
|
81
|
+
<rst>
|
|
82
|
+
<relations><!-- ... --></relations>
|
|
83
|
+
<body>
|
|
84
|
+
<segment id="1" parent="2" relname="adversative-concession">Although the experiment was carefully # designed,</segment>
|
|
85
|
+
<segment id="2" parent="4" relname="span">the results were inconclusive.</segment>
|
|
86
|
+
<segment id="3" parent="5" relname="span">We plan to repeat it tonight.</segment>
|
|
87
|
+
<group id="4" type="span" parent="3" relname="adversative-antithesis"/>
|
|
88
|
+
<group id="5" type="span"/>
|
|
89
|
+
</body>
|
|
90
|
+
</rst>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The same flow from Python:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from dipo.rst.parsers.dmrst.modeling_dmrst import DMRSTParser
|
|
97
|
+
parser = DMRSTParser.from_pretrained("larc-iu/dmrst-ettin-400m-gum-12.1.0")
|
|
98
|
+
tree = parser.predict_from_text(
|
|
99
|
+
"Although the experiment was carefully designed, "
|
|
100
|
+
"the results were inconclusive. "
|
|
101
|
+
"We plan to repeat it tonight."
|
|
102
|
+
)
|
|
103
|
+
print(tree.to_rs4_string())
|
|
104
|
+
```
|
|
105
|
+
Yields:
|
|
106
|
+
```xml
|
|
107
|
+
<rst>
|
|
108
|
+
<relations><!-- ... --></relations>
|
|
109
|
+
<body>
|
|
110
|
+
<segment id="1" parent="2" relname="adversative-concession">Although the experiment was carefully # designed,</segment>
|
|
111
|
+
<segment id="2" parent="4" relname="span">the results were inconclusive.</segment>
|
|
112
|
+
<segment id="3" parent="5" relname="span">We plan to repeat it tonight.</segment>
|
|
113
|
+
<group id="4" type="span" parent="3" relname="adversative-antithesis"/>
|
|
114
|
+
<group id="5" type="span"/>
|
|
115
|
+
</body>
|
|
116
|
+
</rst>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Inference CLI
|
|
120
|
+
|
|
121
|
+
To identify a model on the command line, you may use a configuration file (`--config`), a PyTorch checkpoint (`--checkpoint`), or a HuggingFace Hub repository (`--hub-id`).
|
|
122
|
+
|
|
123
|
+
To provide input, you may specify an inline string (`--text`), a path to a raw text file or directory (`--text-file`, for parsers which support this), or an RS3/RS4 file or directory with gold EDUs already supplied (`--input`).
|
|
124
|
+
|
|
125
|
+
For `--text-file` and `--input`, results are written to `--output-dir` as `.rs4` files.
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
# From the Hub, end-to-end on a directory of .txt files:
|
|
129
|
+
dipo dmrst predict \
|
|
130
|
+
--hub-id larc-iu/dmrst-ettin-400m-gum-12.1.0 \
|
|
131
|
+
--text-file path/to/docs/ \
|
|
132
|
+
--output-dir out/ \
|
|
133
|
+
--device cuda
|
|
134
|
+
|
|
135
|
+
# From an explicit checkpoint:
|
|
136
|
+
dipo dmrst predict \
|
|
137
|
+
--checkpoint checkpoints/<run_id>/best_model.pt \
|
|
138
|
+
--text-file path/to/doc.txt \
|
|
139
|
+
--output-dir out/
|
|
140
|
+
|
|
141
|
+
# From a trained run's config, parsing pre-segmented RS3/RS4 with gold EDUs:
|
|
142
|
+
dipo topdown_biaffine predict \
|
|
143
|
+
--config configs/topdown_biaffine_rstdt.jsonnet \
|
|
144
|
+
--input data/rstdt/test \
|
|
145
|
+
--output-dir out/
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Available Models
|
|
149
|
+
All official Dipo model releases are [tagged with `dipo` on the HuggingFace Hub](https://huggingface.co/models?other=dipo) (they also carry the old `iudex` tag for now).
|
|
150
|
+
|
|
151
|
+
All of the models below parse raw text end to end (segmentation and structure) and were trained on untokenized text, so plain prose works as input.
|
|
152
|
+
There is no need to tokenize it or to remove line breaks, and Chinese should be given unspaced.
|
|
153
|
+
Scores are original Parseval Full F1 on each corpus's test set, end to end from raw text.
|
|
154
|
+
|
|
155
|
+
| Hub ID | Parser | Backbone | Corpus | Test Full |
|
|
156
|
+
| --- | --- | --- | --- | --- |
|
|
157
|
+
| [`larc-iu/dmrst-ettin-400m-rstdt-coarse`](https://huggingface.co/larc-iu/dmrst-ettin-400m-rstdt-coarse) | `dmrst` | Ettin encoder 400M | RST-DT (English) | 53.2 |
|
|
158
|
+
| [`larc-iu/gen-sr-t5gemma-2-1b-1b-rstdt-coarse`](https://huggingface.co/larc-iu/gen-sr-t5gemma-2-1b-1b-rstdt-coarse) | `gen` | T5Gemma 2 1B-1B | RST-DT (English) | 49.6 |
|
|
159
|
+
| [`larc-iu/gen-sr-gemma-4-31b-it-rstdt-coarse`](https://huggingface.co/larc-iu/gen-sr-gemma-4-31b-it-rstdt-coarse) | `gen` | Gemma 4 31B | RST-DT (English) | 54.7 |
|
|
160
|
+
| [`larc-iu/dmrst-ettin-400m-gum-12.1.0`](https://huggingface.co/larc-iu/dmrst-ettin-400m-gum-12.1.0) | `dmrst` | Ettin encoder 400M | GUM 12.1.0 (English) | 45.6 |
|
|
161
|
+
| [`larc-iu/gen-sr-t5gemma-2-1b-1b-gum-12.1.0`](https://huggingface.co/larc-iu/gen-sr-t5gemma-2-1b-1b-gum-12.1.0) | `gen` | T5Gemma 2 1B-1B | GUM 12.1.0 (English) | 39.4 |
|
|
162
|
+
| [`larc-iu/gen-sr-gemma-4-31b-it-gum-12.1.0`](https://huggingface.co/larc-iu/gen-sr-gemma-4-31b-it-gum-12.1.0) | `gen` | Gemma 4 31B | GUM 12.1.0 (English) | 45.8 |
|
|
163
|
+
| [`larc-iu/dmrst-xlm-roberta-base-ert`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-ert) | `dmrst` | XLM-R base | RST Basque TreeBank | 27.6 |
|
|
164
|
+
| [`larc-iu/dmrst-xlm-roberta-base-pcc-2.2`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-pcc-2.2) | `dmrst` | XLM-R base | Potsdam Commentary Corpus 2.2 (German) | 18.6 |
|
|
165
|
+
| [`larc-iu/dmrst-xlm-roberta-base-prstc`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-prstc) | `dmrst` | XLM-R base | Persian RST Corpus | 32.2 |
|
|
166
|
+
| [`larc-iu/dmrst-xlm-roberta-base-gcdt`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-gcdt) | `dmrst` | XLM-R base | GCDT (Chinese) | 29.4 |
|
|
167
|
+
|
|
168
|
+
The `dmrst` models cannot see line breaks, so `predict_from_text` also starts a new segment at blank-line paragraph breaks and after short heading-like lines.
|
|
169
|
+
Pass `break_at_paragraphs=False` to use the model's own segmentation alone.
|
|
170
|
+
|
|
171
|
+
The `gen` models are built on a pretrained backbone, and loading one also downloads that backbone from the Hub.
|
|
172
|
+
The two Gemma 4 models are small adapters (about 0.5 GB), so they require accepting Google's terms for `google/gemma-4-31B-it` and a GPU with roughly 70 GB of memory.
|
|
173
|
+
The T5Gemma models store their full weights (about 4.4 GB).
|
|
174
|
+
They are invoked like the others, e.g. `dipo gen predict --hub-id larc-iu/gen-sr-t5gemma-2-1b-1b-gum-12.1.0 --text "..."`.
|
|
175
|
+
A document longer than a `gen` model's context window (16,384 tokens) is rejected with an error rather than silently truncated.
|
|
176
|
+
|
|
177
|
+
## Training
|
|
178
|
+
|
|
179
|
+
To train a new top-down biaffine parser on RSTDT:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
dipo topdown_biaffine train configs/topdown_biaffine_rstdt.jsonnet
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Note that `configs/topdown_biaffine_rstdt.jsonnet` is a configuration.
|
|
186
|
+
You may either edit it directly or copy and modify it in a new location.
|
|
187
|
+
|
|
188
|
+
### Training on Raw Text
|
|
189
|
+
|
|
190
|
+
Several corpora distribute their EDUs word-tokenized (`the drug trade ,`), and a parser trained on that text sees punctuation spacing at inference that real input never has.
|
|
191
|
+
`scripts/build_raw_text_data.py` writes untokenized copies of RST-DT, PCC, GCDT and the Persian corpus to `data/<corpus>_notok`, with identical trees, and the released models were trained on these.
|
|
192
|
+
RST-DT's raw text comes from the LDC release, which must be present at `data/rst_discourse_treebank`.
|
|
193
|
+
For unspaced Chinese, also set `split_cjk_tokens: true` in a DMRST config, so that every EDU boundary falls on a token boundary.
|
|
194
|
+
|
|
195
|
+
### Grabbing Example Configurations
|
|
196
|
+
|
|
197
|
+
Model configurations required for training are not bundled with the package distributed via PyPI.
|
|
198
|
+
|
|
199
|
+
To get them you may visit [the associated directory](https://github.com/larc-iu/dipo/tree/master/configs) and download the configurations you're interested in manually.
|
|
200
|
+
|
|
201
|
+
If you want to grab all of them at once, you can use the command line like so:
|
|
202
|
+
|
|
203
|
+
**bash / zsh / macOS / Linux:**
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
curl -fL https://github.com/larc-iu/dipo/archive/refs/heads/master.tar.gz \
|
|
207
|
+
| tar -xz --strip-components=1 --wildcards '*/configs'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Windows PowerShell:**
|
|
211
|
+
|
|
212
|
+
```powershell
|
|
213
|
+
Invoke-WebRequest https://github.com/larc-iu/dipo/archive/refs/heads/master.zip -OutFile dipo.zip
|
|
214
|
+
Expand-Archive dipo.zip -DestinationPath .
|
|
215
|
+
Move-Item dipo-master/configs configs
|
|
216
|
+
Remove-Item -Recurse -Force dipo-master, dipo.zip
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Either leaves you with a local `configs/` directory you can edit and pass to `dipo … train configs/<name>.jsonnet`.
|
|
220
|
+
|
|
221
|
+
### Configuration Hashes
|
|
222
|
+
|
|
223
|
+
Your configuration is used as the basis for a unique hash, which (by default) corresponds to a directory under `checkpoints/`.
|
|
224
|
+
This hash is used for several purposes.
|
|
225
|
+
For example, running the same config again resumes from the last epoch's checkpoint `last.pt` automatically if the run was interrupted.
|
|
226
|
+
|
|
227
|
+
To view all runs and their status, you may run the `runs list` subcommand:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
$ dipo runs list
|
|
231
|
+
Runs in checkpoints
|
|
232
|
+
┏━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━┓
|
|
233
|
+
┃ run_id ┃ run_name ┃ parser ┃ model_name ┃ train_dir ┃ best_val ┃ step ┃ modified ┃
|
|
234
|
+
┡━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━┩
|
|
235
|
+
│ 245b1d774676 │ - │ dmrst │ xlm-roberta-base │ data/gum_12.1.0/train │ 0.3099 │ 1704 │ 2026-05-18 18:02 │
|
|
236
|
+
│ 41bc0fe1dd50 │ - │ topdown_biaffine │ SpanBERT/spanbert-base-cased │ data/rstdt/train │ 0.7576 │ 2149 │ 2026-05-18 13:51 │
|
|
237
|
+
│ 91525e48d63d │ - │ topdown_biaffine │ SpanBERT/spanbert-base-cased │ data/gum_12.1.0/train │ 0.6364 │ 1899 │ 2026-05-18 14:31 │
|
|
238
|
+
│ ad934ca992d4 │ - │ dmrst │ xlm-roberta-base │ data/rstdt/train │ 0.4665 │ 3090 │ 2026-05-18 16:46 │
|
|
239
|
+
└──────────────┴──────────┴──────────────────┴──────────────────────────────┴───────────────────────┴───────────┴──────┴──────────────────┘
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Monitoring with TensorBoard
|
|
243
|
+
|
|
244
|
+
Every run writes TensorBoard scalars (train loss, learning rate, gradient norm, and dev metrics) to `<run_dir>/tb/`. Point TensorBoard at your checkpoints directory to watch any run live or compare runs:
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
tensorboard --logdir checkpoints/
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Pushing Models to HF Hub
|
|
251
|
+
You may host a trained model using each parser's `push` subcommand.
|
|
252
|
+
Each uploads `best_model.pt`, `config.json`, and an auto-generated `README.md` in a single commit:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
dipo topdown_biaffine push \
|
|
256
|
+
--config configs/topdown_biaffine_rstdt.jsonnet \
|
|
257
|
+
--repo-id larc-iu/topdown_biaffine-rstdt-coarse \
|
|
258
|
+
[--private] [--message "..."] [--token $HF_TOKEN]
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Citation
|
|
262
|
+
|
|
263
|
+
If you use Dipo in your research, please cite it as:
|
|
264
|
+
|
|
265
|
+
> Gessler, Luke. 2026. *Dipo: The Discourse Parsing Omnibus.* https://github.com/larc-iu/dipo.
|
|
266
|
+
|
|
267
|
+
BibTeX:
|
|
268
|
+
|
|
269
|
+
```bibtex
|
|
270
|
+
@misc{gessler-dipo-2026,
|
|
271
|
+
author = {Gessler, Luke},
|
|
272
|
+
title = {{Dipo: The Discourse Parsing Omnibus}},
|
|
273
|
+
year = {2026},
|
|
274
|
+
howpublished = {\url{https://github.com/larc-iu/dipo}},
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
If you use one of the included parser re-implementations, please **also** cite the original paper (see each model's Hub card for the canonical reference).
|
dipo-0.2.0/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Dipo
|
|
2
|
+
|
|
3
|
+
The **<u>Di</u>scourse <u>P</u>arsing <u>O</u>mnibus** (Dipo, said like "depot") is a collection of easy-to-use discourse parsers and other code related to discourse parsing.
|
|
4
|
+
|
|
5
|
+
Dipo was formerly called IUDEX (`larc-iudex` on PyPI, with the command `iudex`).
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
For the latest release:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
pip install dipo
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For the current state of `master`:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
pip install git+https://github.com/larc-iu/dipo
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or for development:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
git clone https://github.com/larc-iu/dipo && cd dipo
|
|
25
|
+
pip install -e .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The old `iudex` command still works for now, as a deprecated alias of `dipo` that prints a notice. `import iudex` is now `import dipo`.
|
|
29
|
+
|
|
30
|
+
## Quick Start with Inference
|
|
31
|
+
|
|
32
|
+
Parse a sample document end-to-end with a pretrained DMRST model pulled from the HuggingFace Hub. From the command line:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
dipo dmrst predict \
|
|
36
|
+
--hub-id larc-iu/dmrst-ettin-400m-gum-12.1.0 \
|
|
37
|
+
--text "Although the experiment was carefully designed, the results were inconclusive. We plan to repeat it tonight."
|
|
38
|
+
```
|
|
39
|
+
This yields the parsed tree in `.rs3` format printed to `stdout`:
|
|
40
|
+
```xml
|
|
41
|
+
<rst>
|
|
42
|
+
<relations><!-- ... --></relations>
|
|
43
|
+
<body>
|
|
44
|
+
<segment id="1" parent="2" relname="adversative-concession">Although the experiment was carefully # designed,</segment>
|
|
45
|
+
<segment id="2" parent="4" relname="span">the results were inconclusive.</segment>
|
|
46
|
+
<segment id="3" parent="5" relname="span">We plan to repeat it tonight.</segment>
|
|
47
|
+
<group id="4" type="span" parent="3" relname="adversative-antithesis"/>
|
|
48
|
+
<group id="5" type="span"/>
|
|
49
|
+
</body>
|
|
50
|
+
</rst>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The same flow from Python:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from dipo.rst.parsers.dmrst.modeling_dmrst import DMRSTParser
|
|
57
|
+
parser = DMRSTParser.from_pretrained("larc-iu/dmrst-ettin-400m-gum-12.1.0")
|
|
58
|
+
tree = parser.predict_from_text(
|
|
59
|
+
"Although the experiment was carefully designed, "
|
|
60
|
+
"the results were inconclusive. "
|
|
61
|
+
"We plan to repeat it tonight."
|
|
62
|
+
)
|
|
63
|
+
print(tree.to_rs4_string())
|
|
64
|
+
```
|
|
65
|
+
Yields:
|
|
66
|
+
```xml
|
|
67
|
+
<rst>
|
|
68
|
+
<relations><!-- ... --></relations>
|
|
69
|
+
<body>
|
|
70
|
+
<segment id="1" parent="2" relname="adversative-concession">Although the experiment was carefully # designed,</segment>
|
|
71
|
+
<segment id="2" parent="4" relname="span">the results were inconclusive.</segment>
|
|
72
|
+
<segment id="3" parent="5" relname="span">We plan to repeat it tonight.</segment>
|
|
73
|
+
<group id="4" type="span" parent="3" relname="adversative-antithesis"/>
|
|
74
|
+
<group id="5" type="span"/>
|
|
75
|
+
</body>
|
|
76
|
+
</rst>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Inference CLI
|
|
80
|
+
|
|
81
|
+
To identify a model on the command line, you may use a configuration file (`--config`), a PyTorch checkpoint (`--checkpoint`), or a HuggingFace Hub repository (`--hub-id`).
|
|
82
|
+
|
|
83
|
+
To provide input, you may specify an inline string (`--text`), a path to a raw text file or directory (`--text-file`, for parsers which support this), or an RS3/RS4 file or directory with gold EDUs already supplied (`--input`).
|
|
84
|
+
|
|
85
|
+
For `--text-file` and `--input`, results are written to `--output-dir` as `.rs4` files.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
# From the Hub, end-to-end on a directory of .txt files:
|
|
89
|
+
dipo dmrst predict \
|
|
90
|
+
--hub-id larc-iu/dmrst-ettin-400m-gum-12.1.0 \
|
|
91
|
+
--text-file path/to/docs/ \
|
|
92
|
+
--output-dir out/ \
|
|
93
|
+
--device cuda
|
|
94
|
+
|
|
95
|
+
# From an explicit checkpoint:
|
|
96
|
+
dipo dmrst predict \
|
|
97
|
+
--checkpoint checkpoints/<run_id>/best_model.pt \
|
|
98
|
+
--text-file path/to/doc.txt \
|
|
99
|
+
--output-dir out/
|
|
100
|
+
|
|
101
|
+
# From a trained run's config, parsing pre-segmented RS3/RS4 with gold EDUs:
|
|
102
|
+
dipo topdown_biaffine predict \
|
|
103
|
+
--config configs/topdown_biaffine_rstdt.jsonnet \
|
|
104
|
+
--input data/rstdt/test \
|
|
105
|
+
--output-dir out/
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Available Models
|
|
109
|
+
All official Dipo model releases are [tagged with `dipo` on the HuggingFace Hub](https://huggingface.co/models?other=dipo) (they also carry the old `iudex` tag for now).
|
|
110
|
+
|
|
111
|
+
All of the models below parse raw text end to end (segmentation and structure) and were trained on untokenized text, so plain prose works as input.
|
|
112
|
+
There is no need to tokenize it or to remove line breaks, and Chinese should be given unspaced.
|
|
113
|
+
Scores are original Parseval Full F1 on each corpus's test set, end to end from raw text.
|
|
114
|
+
|
|
115
|
+
| Hub ID | Parser | Backbone | Corpus | Test Full |
|
|
116
|
+
| --- | --- | --- | --- | --- |
|
|
117
|
+
| [`larc-iu/dmrst-ettin-400m-rstdt-coarse`](https://huggingface.co/larc-iu/dmrst-ettin-400m-rstdt-coarse) | `dmrst` | Ettin encoder 400M | RST-DT (English) | 53.2 |
|
|
118
|
+
| [`larc-iu/gen-sr-t5gemma-2-1b-1b-rstdt-coarse`](https://huggingface.co/larc-iu/gen-sr-t5gemma-2-1b-1b-rstdt-coarse) | `gen` | T5Gemma 2 1B-1B | RST-DT (English) | 49.6 |
|
|
119
|
+
| [`larc-iu/gen-sr-gemma-4-31b-it-rstdt-coarse`](https://huggingface.co/larc-iu/gen-sr-gemma-4-31b-it-rstdt-coarse) | `gen` | Gemma 4 31B | RST-DT (English) | 54.7 |
|
|
120
|
+
| [`larc-iu/dmrst-ettin-400m-gum-12.1.0`](https://huggingface.co/larc-iu/dmrst-ettin-400m-gum-12.1.0) | `dmrst` | Ettin encoder 400M | GUM 12.1.0 (English) | 45.6 |
|
|
121
|
+
| [`larc-iu/gen-sr-t5gemma-2-1b-1b-gum-12.1.0`](https://huggingface.co/larc-iu/gen-sr-t5gemma-2-1b-1b-gum-12.1.0) | `gen` | T5Gemma 2 1B-1B | GUM 12.1.0 (English) | 39.4 |
|
|
122
|
+
| [`larc-iu/gen-sr-gemma-4-31b-it-gum-12.1.0`](https://huggingface.co/larc-iu/gen-sr-gemma-4-31b-it-gum-12.1.0) | `gen` | Gemma 4 31B | GUM 12.1.0 (English) | 45.8 |
|
|
123
|
+
| [`larc-iu/dmrst-xlm-roberta-base-ert`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-ert) | `dmrst` | XLM-R base | RST Basque TreeBank | 27.6 |
|
|
124
|
+
| [`larc-iu/dmrst-xlm-roberta-base-pcc-2.2`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-pcc-2.2) | `dmrst` | XLM-R base | Potsdam Commentary Corpus 2.2 (German) | 18.6 |
|
|
125
|
+
| [`larc-iu/dmrst-xlm-roberta-base-prstc`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-prstc) | `dmrst` | XLM-R base | Persian RST Corpus | 32.2 |
|
|
126
|
+
| [`larc-iu/dmrst-xlm-roberta-base-gcdt`](https://huggingface.co/larc-iu/dmrst-xlm-roberta-base-gcdt) | `dmrst` | XLM-R base | GCDT (Chinese) | 29.4 |
|
|
127
|
+
|
|
128
|
+
The `dmrst` models cannot see line breaks, so `predict_from_text` also starts a new segment at blank-line paragraph breaks and after short heading-like lines.
|
|
129
|
+
Pass `break_at_paragraphs=False` to use the model's own segmentation alone.
|
|
130
|
+
|
|
131
|
+
The `gen` models are built on a pretrained backbone, and loading one also downloads that backbone from the Hub.
|
|
132
|
+
The two Gemma 4 models are small adapters (about 0.5 GB), so they require accepting Google's terms for `google/gemma-4-31B-it` and a GPU with roughly 70 GB of memory.
|
|
133
|
+
The T5Gemma models store their full weights (about 4.4 GB).
|
|
134
|
+
They are invoked like the others, e.g. `dipo gen predict --hub-id larc-iu/gen-sr-t5gemma-2-1b-1b-gum-12.1.0 --text "..."`.
|
|
135
|
+
A document longer than a `gen` model's context window (16,384 tokens) is rejected with an error rather than silently truncated.
|
|
136
|
+
|
|
137
|
+
## Training
|
|
138
|
+
|
|
139
|
+
To train a new top-down biaffine parser on RSTDT:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
dipo topdown_biaffine train configs/topdown_biaffine_rstdt.jsonnet
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Note that `configs/topdown_biaffine_rstdt.jsonnet` is a configuration.
|
|
146
|
+
You may either edit it directly or copy and modify it in a new location.
|
|
147
|
+
|
|
148
|
+
### Training on Raw Text
|
|
149
|
+
|
|
150
|
+
Several corpora distribute their EDUs word-tokenized (`the drug trade ,`), and a parser trained on that text sees punctuation spacing at inference that real input never has.
|
|
151
|
+
`scripts/build_raw_text_data.py` writes untokenized copies of RST-DT, PCC, GCDT and the Persian corpus to `data/<corpus>_notok`, with identical trees, and the released models were trained on these.
|
|
152
|
+
RST-DT's raw text comes from the LDC release, which must be present at `data/rst_discourse_treebank`.
|
|
153
|
+
For unspaced Chinese, also set `split_cjk_tokens: true` in a DMRST config, so that every EDU boundary falls on a token boundary.
|
|
154
|
+
|
|
155
|
+
### Grabbing Example Configurations
|
|
156
|
+
|
|
157
|
+
Model configurations required for training are not bundled with the package distributed via PyPI.
|
|
158
|
+
|
|
159
|
+
To get them you may visit [the associated directory](https://github.com/larc-iu/dipo/tree/master/configs) and download the configurations you're interested in manually.
|
|
160
|
+
|
|
161
|
+
If you want to grab all of them at once, you can use the command line like so:
|
|
162
|
+
|
|
163
|
+
**bash / zsh / macOS / Linux:**
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
curl -fL https://github.com/larc-iu/dipo/archive/refs/heads/master.tar.gz \
|
|
167
|
+
| tar -xz --strip-components=1 --wildcards '*/configs'
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Windows PowerShell:**
|
|
171
|
+
|
|
172
|
+
```powershell
|
|
173
|
+
Invoke-WebRequest https://github.com/larc-iu/dipo/archive/refs/heads/master.zip -OutFile dipo.zip
|
|
174
|
+
Expand-Archive dipo.zip -DestinationPath .
|
|
175
|
+
Move-Item dipo-master/configs configs
|
|
176
|
+
Remove-Item -Recurse -Force dipo-master, dipo.zip
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Either leaves you with a local `configs/` directory you can edit and pass to `dipo … train configs/<name>.jsonnet`.
|
|
180
|
+
|
|
181
|
+
### Configuration Hashes
|
|
182
|
+
|
|
183
|
+
Your configuration is used as the basis for a unique hash, which (by default) corresponds to a directory under `checkpoints/`.
|
|
184
|
+
This hash is used for several purposes.
|
|
185
|
+
For example, running the same config again resumes from the last epoch's checkpoint `last.pt` automatically if the run was interrupted.
|
|
186
|
+
|
|
187
|
+
To view all runs and their status, you may run the `runs list` subcommand:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
$ dipo runs list
|
|
191
|
+
Runs in checkpoints
|
|
192
|
+
┏━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━┓
|
|
193
|
+
┃ run_id ┃ run_name ┃ parser ┃ model_name ┃ train_dir ┃ best_val ┃ step ┃ modified ┃
|
|
194
|
+
┡━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━┩
|
|
195
|
+
│ 245b1d774676 │ - │ dmrst │ xlm-roberta-base │ data/gum_12.1.0/train │ 0.3099 │ 1704 │ 2026-05-18 18:02 │
|
|
196
|
+
│ 41bc0fe1dd50 │ - │ topdown_biaffine │ SpanBERT/spanbert-base-cased │ data/rstdt/train │ 0.7576 │ 2149 │ 2026-05-18 13:51 │
|
|
197
|
+
│ 91525e48d63d │ - │ topdown_biaffine │ SpanBERT/spanbert-base-cased │ data/gum_12.1.0/train │ 0.6364 │ 1899 │ 2026-05-18 14:31 │
|
|
198
|
+
│ ad934ca992d4 │ - │ dmrst │ xlm-roberta-base │ data/rstdt/train │ 0.4665 │ 3090 │ 2026-05-18 16:46 │
|
|
199
|
+
└──────────────┴──────────┴──────────────────┴──────────────────────────────┴───────────────────────┴───────────┴──────┴──────────────────┘
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Monitoring with TensorBoard
|
|
203
|
+
|
|
204
|
+
Every run writes TensorBoard scalars (train loss, learning rate, gradient norm, and dev metrics) to `<run_dir>/tb/`. Point TensorBoard at your checkpoints directory to watch any run live or compare runs:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
tensorboard --logdir checkpoints/
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Pushing Models to HF Hub
|
|
211
|
+
You may host a trained model using each parser's `push` subcommand.
|
|
212
|
+
Each uploads `best_model.pt`, `config.json`, and an auto-generated `README.md` in a single commit:
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
dipo topdown_biaffine push \
|
|
216
|
+
--config configs/topdown_biaffine_rstdt.jsonnet \
|
|
217
|
+
--repo-id larc-iu/topdown_biaffine-rstdt-coarse \
|
|
218
|
+
[--private] [--message "..."] [--token $HF_TOKEN]
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Citation
|
|
222
|
+
|
|
223
|
+
If you use Dipo in your research, please cite it as:
|
|
224
|
+
|
|
225
|
+
> Gessler, Luke. 2026. *Dipo: The Discourse Parsing Omnibus.* https://github.com/larc-iu/dipo.
|
|
226
|
+
|
|
227
|
+
BibTeX:
|
|
228
|
+
|
|
229
|
+
```bibtex
|
|
230
|
+
@misc{gessler-dipo-2026,
|
|
231
|
+
author = {Gessler, Luke},
|
|
232
|
+
title = {{Dipo: The Discourse Parsing Omnibus}},
|
|
233
|
+
year = {2026},
|
|
234
|
+
howpublished = {\url{https://github.com/larc-iu/dipo}},
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
If you use one of the included parser re-implementations, please **also** cite the original paper (see each model's Hub card for the canonical reference).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""This module declares the project's CLI surface that lives above any one
|
|
2
|
+
framework:
|
|
3
|
+
|
|
4
|
+
- `FRAMEWORKS`: dotted paths of framework modules (e.g. `dipo.rst`).
|
|
5
|
+
Each framework module exposes `PARSERS`, `PARSER_SCOPED_COMMANDS`,
|
|
6
|
+
and `GLOBAL_COMMANDS`. The dispatcher (`dipo/__main__.py`) imports
|
|
7
|
+
each and merges the three.
|
|
8
|
+
- `GLOBAL_COMMANDS`: `{cmd: module_path}` for project-level commands
|
|
9
|
+
that aren't owned by any single framework (e.g. `runs`, which walks
|
|
10
|
+
every framework's parser registry to tag rows by parser kind).
|
|
11
|
+
|
|
12
|
+
To add a sibling framework, append its dotted path to `FRAMEWORKS` and
|
|
13
|
+
give its `__init__.py` the three required attributes.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__version__ = "0.2.0"
|
|
17
|
+
|
|
18
|
+
FRAMEWORKS: list[str] = ["dipo.rst"]
|
|
19
|
+
|
|
20
|
+
GLOBAL_COMMANDS: dict[str, str] = {
|
|
21
|
+
"runs": "dipo.runs",
|
|
22
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""dipo CLI dispatcher.
|
|
2
|
+
|
|
3
|
+
`dipo <parser> <cmd>` or `dipo <cmd>` for globals. Routes by merging the
|
|
4
|
+
registries declared by each framework in `dipo.FRAMEWORKS`. See
|
|
5
|
+
`dipo/__init__.py` for the framework contract.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import importlib
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
import dipo
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _merge_frameworks() -> tuple[dict, dict, dict]:
|
|
15
|
+
"""Merge each framework's three registry dicts atop project-level
|
|
16
|
+
`dipo.GLOBAL_COMMANDS`. Aborts on a name collision."""
|
|
17
|
+
parsers: dict = {}
|
|
18
|
+
parser_scoped: dict = {}
|
|
19
|
+
global_cmds: dict = dict(dipo.GLOBAL_COMMANDS)
|
|
20
|
+
for fw_path in dipo.FRAMEWORKS:
|
|
21
|
+
fw = importlib.import_module(fw_path)
|
|
22
|
+
_merge_no_collide(parsers, fw.PARSERS, fw_path, "parser name")
|
|
23
|
+
_merge_no_collide(parser_scoped, fw.PARSER_SCOPED_COMMANDS, fw_path, "parser-scoped command")
|
|
24
|
+
_merge_no_collide(global_cmds, fw.GLOBAL_COMMANDS, fw_path, "global command")
|
|
25
|
+
return parsers, parser_scoped, global_cmds
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _merge_no_collide(dst: dict, src: dict, fw_path: str, kind: str) -> None:
|
|
29
|
+
for k, v in src.items():
|
|
30
|
+
if k in dst and dst[k] is not v:
|
|
31
|
+
sys.stderr.write(
|
|
32
|
+
f"dipo: {kind} {k!r} declared by both an earlier framework and {fw_path!r}. Rename one of them.\n"
|
|
33
|
+
)
|
|
34
|
+
sys.exit(2)
|
|
35
|
+
dst[k] = v
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
PARSERS, PARSER_SCOPED_COMMANDS, GLOBAL_COMMANDS = _merge_frameworks()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def main():
|
|
42
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
43
|
+
print(__doc__.strip())
|
|
44
|
+
print(f"\nKnown parsers: {', '.join(sorted(PARSERS))}")
|
|
45
|
+
print(f"Global commands: {', '.join(sorted(GLOBAL_COMMANDS))}")
|
|
46
|
+
sys.exit(0)
|
|
47
|
+
|
|
48
|
+
if len(sys.argv) < 2:
|
|
49
|
+
sys.stderr.write(__doc__.strip() + "\n\n")
|
|
50
|
+
sys.stderr.write(f"Known parsers: {', '.join(sorted(PARSERS))}\n")
|
|
51
|
+
sys.stderr.write(f"Global commands: {', '.join(sorted(GLOBAL_COMMANDS))}\n")
|
|
52
|
+
sys.exit(2)
|
|
53
|
+
|
|
54
|
+
head = sys.argv[1]
|
|
55
|
+
|
|
56
|
+
if head in GLOBAL_COMMANDS:
|
|
57
|
+
module = importlib.import_module(GLOBAL_COMMANDS[head])
|
|
58
|
+
sys.argv = [GLOBAL_COMMANDS[head]] + sys.argv[2:]
|
|
59
|
+
module.main()
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
if len(sys.argv) < 3:
|
|
63
|
+
sys.stderr.write(__doc__.strip() + "\n\n")
|
|
64
|
+
sys.stderr.write(f"Known parsers: {', '.join(sorted(PARSERS))}\n")
|
|
65
|
+
sys.exit(2)
|
|
66
|
+
|
|
67
|
+
parser_name = head
|
|
68
|
+
command = sys.argv[2]
|
|
69
|
+
|
|
70
|
+
if parser_name not in PARSERS:
|
|
71
|
+
sys.stderr.write(f"Unknown parser: {parser_name!r}\n")
|
|
72
|
+
sys.stderr.write(f"Known parsers: {', '.join(sorted(PARSERS))}\n")
|
|
73
|
+
sys.stderr.write(f"Global commands: {', '.join(sorted(GLOBAL_COMMANDS))}\n")
|
|
74
|
+
sys.exit(2)
|
|
75
|
+
|
|
76
|
+
if command in PARSER_SCOPED_COMMANDS:
|
|
77
|
+
shared_path = PARSER_SCOPED_COMMANDS[command]
|
|
78
|
+
module = importlib.import_module(shared_path)
|
|
79
|
+
sys.argv = [f"dipo {parser_name} {command}"] + sys.argv[3:]
|
|
80
|
+
module.main(parser_kind=parser_name)
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
module_path = f"{PARSERS[parser_name].package}.{command}_{parser_name}"
|
|
84
|
+
try:
|
|
85
|
+
module = importlib.import_module(module_path)
|
|
86
|
+
except ImportError as e:
|
|
87
|
+
sys.stderr.write(f"No such command {command!r} for parser {parser_name!r}\n")
|
|
88
|
+
sys.stderr.write(f" (tried to import {module_path}: {e})\n")
|
|
89
|
+
sys.exit(2)
|
|
90
|
+
|
|
91
|
+
sys.argv = [module_path] + sys.argv[3:]
|
|
92
|
+
module.main()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main_iudex():
|
|
96
|
+
"""Entry point of the deprecated `iudex` command, the old name of this project."""
|
|
97
|
+
sys.stderr.write("iudex: this command has been renamed to `dipo` and takes the same arguments. "
|
|
98
|
+
"`iudex` will be removed in a future release.\n")
|
|
99
|
+
main()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
main()
|
|
File without changes
|