DBBE fetch script, refreshed artifact index, de-anonymized metadata
Browse files- .pytest_cache/.gitignore +2 -0
- .pytest_cache/CACHEDIR.TAG +4 -0
- .pytest_cache/README.md +8 -0
- .pytest_cache/v/cache/nodeids +98 -0
- MODEL_CARDS_INDEX.md +8 -9
- NOTICE +1 -1
- README.md +9 -3
- REPRODUCING.md +1 -1
- Stoicheia_demo.ipynb +1 -1
- pyproject.toml +2 -1
- scripts/build_notebook.py +2 -2
- scripts/fetch_dbbe.py +74 -0
.pytest_cache/.gitignore
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Created by pytest automatically.
|
| 2 |
+
*
|
.pytest_cache/CACHEDIR.TAG
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Signature: 8a477f597d28d172789f06886806bc55
|
| 2 |
+
# This file is a cache directory tag created by pytest.
|
| 3 |
+
# For information about cache directory tags, see:
|
| 4 |
+
# https://bford.info/cachedir/spec.html
|
.pytest_cache/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# pytest cache directory #
|
| 2 |
+
|
| 3 |
+
This directory contains data from the pytest's cache plugin,
|
| 4 |
+
which provides the `--lf` and `--ff` options, as well as the `cache` fixture.
|
| 5 |
+
|
| 6 |
+
**Do not** commit this to version control.
|
| 7 |
+
|
| 8 |
+
See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.
|
.pytest_cache/v/cache/nodeids
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"tests/test_data.py::test_conllu_roundtrip",
|
| 3 |
+
"tests/test_data.py::test_packing_invariants",
|
| 4 |
+
"tests/test_data.py::test_span_alignment",
|
| 5 |
+
"tests/test_data_meta.py::test_multitier_loader_yields_region_century_and_survives_windowing",
|
| 6 |
+
"tests/test_data_meta.py::test_shardset_defaults_unk_when_columns_absent",
|
| 7 |
+
"tests/test_data_meta.py::test_shardset_reads_region_century_columns",
|
| 8 |
+
"tests/test_edits.py::test_grave_fold",
|
| 9 |
+
"tests/test_edits.py::test_inapplicable",
|
| 10 |
+
"tests/test_edits.py::test_roundtrip[\\u03a3\\u03c9\\u03ba\\u03c1\\u03ac\\u03c4\\u03b7\\u03c2-\\u03a3\\u03c9\\u03ba\\u03c1\\u03ac\\u03c4\\u03b7\\u03c2]",
|
| 11 |
+
"tests/test_edits.py::test_roundtrip[\\u03b4\\u02bc-\\u03b4\\u03ad]",
|
| 12 |
+
"tests/test_edits.py::test_roundtrip[\\u03b8\\u03b5\\u03ce-\\u03b8\\u03b5\\u03cc\\u03c2]",
|
| 13 |
+
"tests/test_edits.py::test_roundtrip[\\u03ba\\u1f00\\u03b3\\u03ce-\\u03ba\\u1f00\\u03b3\\u03ce]",
|
| 14 |
+
"tests/test_edits.py::test_roundtrip[\\u03bc\\u03b1\\u03b8\\u03b7\\u03c4\\u1f74\\u03c2-\\u03bc\\u03b1\\u03b8\\u03b7\\u03c4\\u03ae\\u03c2]",
|
| 15 |
+
"tests/test_edits.py::test_roundtrip[\\u03bf\\u1f50\\u03ba-\\u03bf\\u1f50]",
|
| 16 |
+
"tests/test_edits.py::test_roundtrip[\\u03c4\\u03b9\\u03bb\\u03bb\\u03cc\\u03bc\\u03b5\\u03bd\\u03bf\\u03c2-\\u03c4\\u03af\\u03bb\\u03bb\\u03c9]",
|
| 17 |
+
"tests/test_edits.py::test_roundtrip[\\u1f00\\u03bd\\u03b8\\u03c1\\u03ce\\u03c0\\u03bf\\u03c5-\\u1f04\\u03bd\\u03b8\\u03c1\\u03c9\\u03c0\\u03bf\\u03c2]",
|
| 18 |
+
"tests/test_edits.py::test_roundtrip[\\u1f20\\u03bd\\u03b5\\u03af\\u03c7\\u03b5\\u03c4\\u03bf-\\u1f00\\u03bd\\u03ad\\u03c7\\u03c9]",
|
| 19 |
+
"tests/test_hf_release_smoke.py::test_decode_boundaries_keeps_punctuation",
|
| 20 |
+
"tests/test_hf_release_smoke.py::test_decode_diacritics_keeps_punctuation_and_boundary",
|
| 21 |
+
"tests/test_hf_release_smoke.py::test_decode_restoration_fills_masked_gap_and_keeps_punctuation",
|
| 22 |
+
"tests/test_hf_release_smoke.py::test_decode_restoration_handles_fully_masked_dia_and_boundary",
|
| 23 |
+
"tests/test_hf_release_smoke.py::test_processor_round_trips_punctuation_with_no_masking",
|
| 24 |
+
"tests/test_hf_release_smoke.py::test_restore_elastic_sweeps_widths_and_ranks_by_confidence",
|
| 25 |
+
"tests/test_hf_release_smoke.py::test_tiny_model_forward_pass_shapes",
|
| 26 |
+
"tests/test_insc_eval_whole.py::test_eval_span_whole_never_overlaps_real_lacuna",
|
| 27 |
+
"tests/test_insc_eval_whole.py::test_eval_span_whole_runs_end_to_end",
|
| 28 |
+
"tests/test_insc_eval_whole.py::test_eval_span_whole_skips_records_with_no_valid_position",
|
| 29 |
+
"tests/test_insc_lacuna.py::test_iphi_cap_plane_captured_not_discarded",
|
| 30 |
+
"tests/test_insc_lacuna.py::test_iphi_known_length_dash_run_marked_real_lacuna",
|
| 31 |
+
"tests/test_insc_lacuna.py::test_iphi_no_lacuna_when_no_dash",
|
| 32 |
+
"tests/test_insc_lacuna.py::test_papyri_dash_run_exact_length",
|
| 33 |
+
"tests/test_insc_lacuna.py::test_papyri_ellipsis_gets_random_stand_in_width_in_range",
|
| 34 |
+
"tests/test_insc_lacuna.py::test_papyri_mixed_dash_and_ellipsis_in_one_text",
|
| 35 |
+
"tests/test_insc_smoke.py::test_restoration_forward_pass_with_masked_gap",
|
| 36 |
+
"tests/test_marks.py::test_ambiguous_mask_matches_reference",
|
| 37 |
+
"tests/test_marks.py::test_bracketize_roundtrip",
|
| 38 |
+
"tests/test_marks.py::test_concat_verses_boundaries",
|
| 39 |
+
"tests/test_marks.py::test_enforce_circumflex_heavy_leaves_non_circumflex_alone",
|
| 40 |
+
"tests/test_marks.py::test_enforce_circumflex_heavy_overrides_light",
|
| 41 |
+
"tests/test_marks.py::test_insert_marks_roundtrip",
|
| 42 |
+
"tests/test_marks.py::test_macron_roundtrip_against_plain_column",
|
| 43 |
+
"tests/test_marks.py::test_merge_vowelless_syllables",
|
| 44 |
+
"tests/test_marks.py::test_merge_vowelless_syllables_leaves_real_syllables_alone",
|
| 45 |
+
"tests/test_marks.py::test_norma_lines_parse",
|
| 46 |
+
"tests/test_marks.py::test_parse_macron_combining_marks",
|
| 47 |
+
"tests/test_marks.py::test_parse_macron_simple",
|
| 48 |
+
"tests/test_marks.py::test_parse_scan_simple",
|
| 49 |
+
"tests/test_marks.py::test_scan_corpus_lines_encode",
|
| 50 |
+
"tests/test_meta_conditioning.py::test_collate_propagates_region_century",
|
| 51 |
+
"tests/test_meta_conditioning.py::test_collate_unk_constants_match_meta_vocab",
|
| 52 |
+
"tests/test_meta_conditioning.py::test_data_py_unk_constants_match_meta_vocab",
|
| 53 |
+
"tests/test_meta_conditioning.py::test_model_ignores_region_century_when_disabled",
|
| 54 |
+
"tests/test_meta_conditioning.py::test_pack_batch_propagates_region_century_and_defaults_unk",
|
| 55 |
+
"tests/test_meta_conditioning.py::test_parse_year_rejects_sentinels_and_junk",
|
| 56 |
+
"tests/test_meta_conditioning.py::test_record_century_id_midpoint_and_fallback",
|
| 57 |
+
"tests/test_meta_conditioning.py::test_region_to_id_known_and_unknown",
|
| 58 |
+
"tests/test_meter_hf_release_smoke.py::test_ambiguous_mask_and_mark_insertion",
|
| 59 |
+
"tests/test_meter_hf_release_smoke.py::test_bracketize_basic",
|
| 60 |
+
"tests/test_meter_hf_release_smoke.py::test_convert_checkpoint_to_hf_meter_kind",
|
| 61 |
+
"tests/test_meter_hf_release_smoke.py::test_meter_model_forward_and_decode_shapes",
|
| 62 |
+
"tests/test_noising.py::test_channel_dropout_frequencies",
|
| 63 |
+
"tests/test_noising.py::test_channel_masks_are_genuinely_patchy_sometimes",
|
| 64 |
+
"tests/test_noising.py::test_elastic_preserves_visible_chars_and_lengths",
|
| 65 |
+
"tests/test_noising.py::test_halfword_pattern_only_masks_within_single_words",
|
| 66 |
+
"tests/test_noising.py::test_halfword_span_always_within_the_word_and_hits_all_anchors",
|
| 67 |
+
"tests/test_noising.py::test_iid_rate_matches_t",
|
| 68 |
+
"tests/test_noising.py::test_is_real_lacuna_none_is_fully_backward_compatible",
|
| 69 |
+
"tests/test_noising.py::test_labels_only_at_masked_positions_fixed_patterns",
|
| 70 |
+
"tests/test_noising.py::test_mixture_covers_all_patterns",
|
| 71 |
+
"tests/test_noising.py::test_real_lacuna_excluded_from_elastic_rebuild_too",
|
| 72 |
+
"tests/test_noising.py::test_real_lacuna_never_selected_as_synthetic_target_fixed_patterns",
|
| 73 |
+
"tests/test_noising.py::test_substitute_never_uses_mask_token_and_label_is_true_char",
|
| 74 |
+
"tests/test_noising.py::test_word_masking_respects_boundaries",
|
| 75 |
+
"tests/test_normalize.py::test_capital_with_breathing",
|
| 76 |
+
"tests/test_normalize.py::test_dia_pack_unpack_roundtrip",
|
| 77 |
+
"tests/test_normalize.py::test_drops_nongreek_record",
|
| 78 |
+
"tests/test_normalize.py::test_elision_apostrophe_is_word_boundary",
|
| 79 |
+
"tests/test_normalize.py::test_final_and_lunate_sigma_merge",
|
| 80 |
+
"tests/test_normalize.py::test_iota_subscript_and_diaeresis",
|
| 81 |
+
"tests/test_normalize.py::test_kai_ho_logos",
|
| 82 |
+
"tests/test_normalize.py::test_punct_without_space_is_sentence_final",
|
| 83 |
+
"tests/test_normalize.py::test_restore_polytonic_simple",
|
| 84 |
+
"tests/test_normalize.py::test_roundtrip_on_real_records[pristine/pristine-00000.parquet]",
|
| 85 |
+
"tests/test_normalize.py::test_roundtrip_on_real_records[repaired/repaired-00000.parquet]",
|
| 86 |
+
"tests/test_packing.py::test_pack_batch_metadata_dropout_default_off_matches_prior_behavior",
|
| 87 |
+
"tests/test_packing.py::test_pack_batch_metadata_dropout_forces_unk_sometimes",
|
| 88 |
+
"tests/test_packing.py::test_pack_batch_real_lacuna_never_supervised",
|
| 89 |
+
"tests/test_packing.py::test_packing_labels_only_at_masked",
|
| 90 |
+
"tests/test_packing.py::test_packing_no_doc_crossing_and_fill",
|
| 91 |
+
"tests/test_syntax_smoke.py::test_joint_model_forward_pass",
|
| 92 |
+
"tests/test_ud_conversion.py::test_auxp_promotes_nominal_to_obl",
|
| 93 |
+
"tests/test_ud_conversion.py::test_coord_promotes_first_conjunct_with_generic_fallback",
|
| 94 |
+
"tests/test_ud_conversion.py::test_empty_sentence",
|
| 95 |
+
"tests/test_ud_conversion.py::test_pnom_copula_reversal",
|
| 96 |
+
"tests/test_ud_conversion.py::test_simple_sentence_sbj_pred_atr",
|
| 97 |
+
"tests/test_ud_conversion.py::test_xpos_to_upos_feats_verb_and_noun"
|
| 98 |
+
]
|
MODEL_CARDS_INDEX.md
CHANGED
|
@@ -27,18 +27,17 @@ All built on `Stoicheia-doc_clean`.
|
|
| 27 |
| [`Ericu950/Stoicheia-meter`](https://huggingface.co/Ericu950/Stoicheia-meter) | macronization (vowel length) + metrical scansion, trained jointly |
|
| 28 |
| [`Ericu950/Stoicheia-macronizer`](https://huggingface.co/Ericu950/Stoicheia-macronizer) | macronization only — the arm the paper's macronization ablation is measured on |
|
| 29 |
|
| 30 |
-
Not released as a model: the authorship-attribution / hermeneutic probes, which are
|
| 31 |
-
designed to be fine-tuned per-task rather than distributed as a general-purpose model
|
| 32 |
-
(see the paper's Discussion section).
|
| 33 |
-
|
| 34 |
## Datasets
|
| 35 |
|
| 36 |
| dataset | what it is |
|
| 37 |
|---|---|
|
| 38 |
-
| [`Ericu950/AncientGreek`](https://huggingface.co/datasets/Ericu950/AncientGreek) |
|
| 39 |
-
| [`Ericu950/SyntheticAncientGreek-CorpusCorporum`](https://huggingface.co/datasets/Ericu950/SyntheticAncientGreek-CorpusCorporum) | bronze synthetic augmentation tier |
|
| 40 |
| [`Ericu950/Inscriptions_2`](https://huggingface.co/datasets/Ericu950/Inscriptions_2) | PHI inscriptions used for the 10-fold split and restoration fine-tuning |
|
|
|
|
|
|
|
| 41 |
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
| 27 |
| [`Ericu950/Stoicheia-meter`](https://huggingface.co/Ericu950/Stoicheia-meter) | macronization (vowel length) + metrical scansion, trained jointly |
|
| 28 |
| [`Ericu950/Stoicheia-macronizer`](https://huggingface.co/Ericu950/Stoicheia-macronizer) | macronization only — the arm the paper's macronization ablation is measured on |
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
## Datasets
|
| 31 |
|
| 32 |
| dataset | what it is |
|
| 33 |
|---|---|
|
| 34 |
+
| [`Ericu950/AncientGreek`](https://huggingface.co/datasets/Ericu950/AncientGreek) | pretraining corpus, ~361M words in `pristine` and `repaired` tiers |
|
| 35 |
+
| [`Ericu950/SyntheticAncientGreek-CorpusCorporum`](https://huggingface.co/datasets/Ericu950/SyntheticAncientGreek-CorpusCorporum) | bronze synthetic augmentation tier, machine-translated from Latin |
|
| 36 |
| [`Ericu950/Inscriptions_2`](https://huggingface.co/datasets/Ericu950/Inscriptions_2) | PHI inscriptions used for the 10-fold split and restoration fine-tuning |
|
| 37 |
+
| [`Ericu950/Stoicheia-meter-silver`](https://huggingface.co/datasets/Ericu950/Stoicheia-meter-silver) | silver macronization/scansion training data (Hypotactic-derived + constraint-solver mined) |
|
| 38 |
+
| [`Ericu950/norma`](https://huggingface.co/datasets/Ericu950/norma) | mirror of the *Norma Syllabarum Graecarum* benchmark, in the exact split the paper evaluates on |
|
| 39 |
|
| 40 |
+
`AncientGreek` omits the Database of Byzantine Book Epigrams, which is CC BY-NC-SA and so
|
| 41 |
+
cannot travel inside a CC BY-SA compilation; `scripts/fetch_dbbe.py` refetches it under its
|
| 42 |
+
own terms. Not re-released at all: the OGA/AGDT treebank splits, which come from Celano's
|
| 43 |
+
own repository and are cited rather than duplicated.
|
NOTICE
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
Stoicheia
|
| 2 |
-
Copyright 2026
|
| 3 |
|
| 4 |
This product is licensed under the Apache License, Version 2.0 (see LICENSE).
|
| 5 |
|
|
|
|
| 1 |
Stoicheia
|
| 2 |
+
Copyright 2026 Eric Cullhed and Albin Thörn Cleland
|
| 3 |
|
| 4 |
This product is licensed under the Apache License, Version 2.0 (see LICENSE).
|
| 5 |
|
README.md
CHANGED
|
@@ -18,7 +18,7 @@ macronization and scansion). All model repos are public: weights ship as `model.
|
|
| 18 |
loadable directly through `AutoModel.from_pretrained(..., trust_remote_code=True)`.
|
| 19 |
|
| 20 |
|
| 21 |
-
[](https://colab.research.google.com/github/
|
| 22 |
|
| 23 |
Run everything in the browser: [`Stoicheia_demo.ipynb`](Stoicheia_demo.ipynb) restores a lacuna of
|
| 24 |
unknown width, picks the checkpoint that has provably never read your document, tags and parses a
|
|
@@ -75,6 +75,10 @@ decides where the words end.
|
|
| 75 |
- `meter/` — macronization (vowel length) and metrical scansion, including the
|
| 76 |
*Norma* benchmark protocol and rule-based silver-data mining pipeline.
|
| 77 |
- `tests/` — CPU-only pytest suite.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
See [`REPRODUCING.md`](REPRODUCING.md) for the full environment setup and end-to-end
|
| 80 |
reproduction walkthrough.
|
|
@@ -85,9 +89,11 @@ reproduction walkthrough.
|
|
| 85 |
@misc{stoicheia2026,
|
| 86 |
title = {Stoicheia: Character-Level Masked Diffusion for Ancient Greek Textual
|
| 87 |
Restoration, Parsing, and Metrical Scansion},
|
| 88 |
-
author = {
|
| 89 |
year = {2026},
|
| 90 |
-
|
|
|
|
|
|
|
| 91 |
}
|
| 92 |
```
|
| 93 |
|
|
|
|
| 18 |
loadable directly through `AutoModel.from_pretrained(..., trust_remote_code=True)`.
|
| 19 |
|
| 20 |
|
| 21 |
+
[](https://colab.research.google.com/github/ericu9500/stoicheia/blob/main/Stoicheia_demo.ipynb)
|
| 22 |
|
| 23 |
Run everything in the browser: [`Stoicheia_demo.ipynb`](Stoicheia_demo.ipynb) restores a lacuna of
|
| 24 |
unknown width, picks the checkpoint that has provably never read your document, tags and parses a
|
|
|
|
| 75 |
- `meter/` — macronization (vowel length) and metrical scansion, including the
|
| 76 |
*Norma* benchmark protocol and rule-based silver-data mining pipeline.
|
| 77 |
- `tests/` — CPU-only pytest suite.
|
| 78 |
+
- `scripts/fetch_dbbe.py` — refetches the Database of Byzantine Book Epigrams, which the
|
| 79 |
+
released corpus omits: DBBE is CC BY-NC-SA, whose non-commercial clause a CC BY-SA
|
| 80 |
+
compilation cannot carry. Run it to reconstruct the pretraining corpus exactly (5,476
|
| 81 |
+
records, ~0.2M words, 0.1% of the total); what you build then inherits DBBE's terms.
|
| 82 |
|
| 83 |
See [`REPRODUCING.md`](REPRODUCING.md) for the full environment setup and end-to-end
|
| 84 |
reproduction walkthrough.
|
|
|
|
| 89 |
@misc{stoicheia2026,
|
| 90 |
title = {Stoicheia: Character-Level Masked Diffusion for Ancient Greek Textual
|
| 91 |
Restoration, Parsing, and Metrical Scansion},
|
| 92 |
+
author = {Cullhed, Eric and Th\"orn Cleland, Albin},
|
| 93 |
year = {2026},
|
| 94 |
+
eprint = {2608.XXXXX},
|
| 95 |
+
archivePrefix = {arXiv},
|
| 96 |
+
primaryClass = {cs.CL}
|
| 97 |
}
|
| 98 |
```
|
| 99 |
|
REPRODUCING.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
## 1. Environment
|
| 4 |
|
| 5 |
```bash
|
| 6 |
-
git clone https://github.com/
|
| 7 |
cd stoicheia
|
| 8 |
export STOICHEIA_DATA=/path/to/a/writable/data+checkpoints/directory
|
| 9 |
source env.sh
|
|
|
|
| 3 |
## 1. Environment
|
| 4 |
|
| 5 |
```bash
|
| 6 |
+
git clone https://github.com/ericu9500/stoicheia
|
| 7 |
cd stoicheia
|
| 8 |
export STOICHEIA_DATA=/path/to/a/writable/data+checkpoints/directory
|
| 9 |
source env.sh
|
Stoicheia_demo.ipynb
CHANGED
|
@@ -20,7 +20,7 @@
|
|
| 20 |
"4. macronize and scan a line of verse\n",
|
| 21 |
"5. score the macronizer against a hand-annotated benchmark\n",
|
| 22 |
"\n",
|
| 23 |
-
"Every model and dataset used below is public.
|
| 24 |
]
|
| 25 |
},
|
| 26 |
{
|
|
|
|
| 20 |
"4. macronize and scan a line of verse\n",
|
| 21 |
"5. score the macronizer against a hand-annotated benchmark\n",
|
| 22 |
"\n",
|
| 23 |
+
"Every model and dataset used below is public.\n"
|
| 24 |
]
|
| 25 |
},
|
| 26 |
{
|
pyproject.toml
CHANGED
|
@@ -10,7 +10,8 @@ readme = "README.md"
|
|
| 10 |
requires-python = ">=3.10"
|
| 11 |
license = { text = "Apache-2.0" }
|
| 12 |
authors = [
|
| 13 |
-
{ name = "
|
|
|
|
| 14 |
]
|
| 15 |
|
| 16 |
[tool.setuptools]
|
|
|
|
| 10 |
requires-python = ">=3.10"
|
| 11 |
license = { text = "Apache-2.0" }
|
| 12 |
authors = [
|
| 13 |
+
{ name = "Eric Cullhed" },
|
| 14 |
+
{ name = "Albin Thörn Cleland" },
|
| 15 |
]
|
| 16 |
|
| 17 |
[tool.setuptools]
|
scripts/build_notebook.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
-
"""Build the Stoicheia demo notebook (
|
| 3 |
import json, pathlib
|
| 4 |
|
| 5 |
ORG = "Ericu950"
|
|
@@ -25,7 +25,7 @@ cells = [
|
|
| 25 |
"4. macronize and scan a line of verse",
|
| 26 |
"5. score the macronizer against a hand-annotated benchmark",
|
| 27 |
"",
|
| 28 |
-
"Every model and dataset used below is public.
|
| 29 |
|
| 30 |
code("%pip install -q --upgrade transformers huggingface_hub safetensors torch datasets"),
|
| 31 |
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
+
"""Build the Stoicheia demo notebook (Colab-ready)."""
|
| 3 |
import json, pathlib
|
| 4 |
|
| 5 |
ORG = "Ericu950"
|
|
|
|
| 25 |
"4. macronize and scan a line of verse",
|
| 26 |
"5. score the macronizer against a hand-annotated benchmark",
|
| 27 |
"",
|
| 28 |
+
"Every model and dataset used below is public."),
|
| 29 |
|
| 30 |
code("%pip install -q --upgrade transformers huggingface_hub safetensors torch datasets"),
|
| 31 |
|
scripts/fetch_dbbe.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Fetch the Database of Byzantine Book Epigrams, which the corpus release omits.
|
| 3 |
+
|
| 4 |
+
DBBE is distributed under CC BY-NC-SA. The pretraining corpus is a CC BY-SA compilation,
|
| 5 |
+
and a non-commercial clause cannot be honoured inside one, so the 5,476 DBBE records
|
| 6 |
+
(~0.2M words, 0.1% of the corpus) are excluded from the released dataset even though they
|
| 7 |
+
were present in the corpus we pretrained on. This script rebuilds that corpus exactly, on
|
| 8 |
+
the reader's own terms rather than ours.
|
| 9 |
+
|
| 10 |
+
python scripts/fetch_dbbe.py --out dbbe.jsonl
|
| 11 |
+
|
| 12 |
+
Anything you build from the result inherits DBBE's non-commercial and share-alike terms.
|
| 13 |
+
See https://www.dbbe.ugent.be for the licence and citation policy.
|
| 14 |
+
"""
|
| 15 |
+
import argparse
|
| 16 |
+
import json
|
| 17 |
+
import time
|
| 18 |
+
import urllib.request
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
|
| 21 |
+
API = "https://www.dbbe.ugent.be/api/occurrences"
|
| 22 |
+
UA = {"User-Agent": "stoicheia-corpus-rebuild/1.0 (+https://github.com/ericu9500/stoicheia)"}
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def fetch_page(page, per_page, retries=3):
|
| 26 |
+
url = f"{API}?page={page}&limit={per_page}"
|
| 27 |
+
for attempt in range(retries):
|
| 28 |
+
try:
|
| 29 |
+
req = urllib.request.Request(url, headers=UA)
|
| 30 |
+
with urllib.request.urlopen(req, timeout=60) as r:
|
| 31 |
+
return json.loads(r.read().decode("utf-8"))
|
| 32 |
+
except Exception as e: # noqa: BLE001
|
| 33 |
+
if attempt == retries - 1:
|
| 34 |
+
raise
|
| 35 |
+
print(f" retry {attempt + 1} after {type(e).__name__}", flush=True)
|
| 36 |
+
time.sleep(5 * (attempt + 1))
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def main():
|
| 40 |
+
ap = argparse.ArgumentParser()
|
| 41 |
+
ap.add_argument("--out", default="dbbe.jsonl")
|
| 42 |
+
ap.add_argument("--per-page", type=int, default=100)
|
| 43 |
+
ap.add_argument("--max-pages", type=int, default=0, help="0 = until exhausted")
|
| 44 |
+
a = ap.parse_args()
|
| 45 |
+
|
| 46 |
+
out = Path(a.out)
|
| 47 |
+
n = page = 0
|
| 48 |
+
with out.open("w", encoding="utf-8") as fh:
|
| 49 |
+
while True:
|
| 50 |
+
page += 1
|
| 51 |
+
if a.max_pages and page > a.max_pages:
|
| 52 |
+
break
|
| 53 |
+
data = fetch_page(page, a.per_page)
|
| 54 |
+
items = data.get("data") or data.get("items") or []
|
| 55 |
+
if not items:
|
| 56 |
+
break
|
| 57 |
+
for it in items:
|
| 58 |
+
text = (it.get("text") or "").strip()
|
| 59 |
+
if not text:
|
| 60 |
+
continue
|
| 61 |
+
fh.write(json.dumps({"source": "dbbe",
|
| 62 |
+
"id": str(it.get("id", "")),
|
| 63 |
+
"license": "CC BY-NC-SA",
|
| 64 |
+
"text": text}, ensure_ascii=False) + "\n")
|
| 65 |
+
n += 1
|
| 66 |
+
print(f" page {page}: {n} records so far", flush=True)
|
| 67 |
+
time.sleep(1) # be polite to the API
|
| 68 |
+
|
| 69 |
+
print(f"wrote {n} records to {out}")
|
| 70 |
+
print("These records are CC BY-NC-SA: anything you merge them into inherits those terms.")
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
if __name__ == "__main__":
|
| 74 |
+
main()
|