{
  "id": 684368,
  "title": "[25th Place] DPC Solution: Contextual ByT5-Large Ensemble, Chunking, and MBR",
  "url": "/competitions/deep-past-initiative-machine-translation/discussion/684368",
  "author_name": "FX-6300",
  "post_date": "2026-03-24T16:21:20.233000",
  "votes": 2,
  "comment_count": 0,
  "views": 0,
  "content": "<p>First, I would like to thank the Kaggle hosts for organizing this competition and for providing such an interesting problem.</p>\n<h1>Summary</h1>\n<p>My final solution was a contextual ByT5-large system with chunked ensemble inference, but the biggest gains came from data work rather than model changes.</p>\n<ul>\n<li><strong>Data</strong>: built a larger published row-wise corpus from OARE/CDLI, added a smaller auxiliary full-sequence corpus, and filled missing translations with formula-aware Gemini prompting</li>\n<li><strong>Black-box Distillation</strong>: used a stronger closed model to generate pseudo-labels, then trained a smaller open model on the resulting parallel data</li>\n<li><strong>Style adaptation</strong>: repeatedly cleaned names, formulaic expressions, punctuation, and  handling to better match the compact English style of train.csv</li>\n<li><strong>Training</strong>: trained ByT5-large with a main row-wise contextual objective and a lighter auxiliary full-sequence objective</li>\n<li><strong>Inference</strong>: chunked long test transliterations with a chi-square chunker, added local lookback/lookahead context, ensembled four checkpoints, reranked with MBR, and applied deterministic post-editing</li>\n</ul>\n<p>Overall, the system was built around three ideas: better corpus construction, stronger style adaptation, and more careful chunk-level inference.</p>\n<pre><code>Approximate contribution to the final score (from ablations)\n\nPrivate LB:\nData adaptation   [########################......] +0.93\nChunking          [#########.....................] +0.15 to +0.35\nByT5-Large        [#########.....................] +0.35\nEnsemble + MBR    [###...........................] +0.11\nPost-edit / GR    [..............................] ~0.00\n\nPublic LB:\nData adaptation   [##########################....] +1.00\nChunking          [##############################] +0.82 to +1.15\nByT5-Large        [###################...........] +0.73\nEnsemble + MBR    [..............................] no consistent gain\nPost-edit / GR    [###...........................] +0.10\n</code></pre>\n<h1>Datasets</h1>\n<p>I prepared two corpora for training:</p>\n<ul>\n<li><strong>published row-wise corpus:</strong> 46,503 transliteration/translation pairs were prepared; 46,502 were retained in the final adapted corpus</li>\n<li><strong>auxiliary full-sequence corpus:</strong> 1,359 transliteration/translation pairs were prepared; 1,358 were used in training after filtering one overlength example</li>\n</ul>\n<h2>(Main Corpus) Published Corpus Construction</h2>\n<h3>1. Obtain raw data from source APIs</h3>\n<p>I found several useful APIs.</p>\n<h4>oare.byu.edu</h4>\n<ul>\n<li><p>UUID feeder:\n<code>https://oare.byu.edu/api/v2/search?characters=&amp;textTitle=AKT&amp;page=1&amp;rows=100&amp;mode=respectAllBoundaries</code></p></li>\n<li><p>Tablet feeder:\n<code>https://oare.byu.edu/api/v2/text_epigraphies/text/${uuid}?forceAllowAdminView=false</code></p></li>\n</ul>\n<h4>CDLI</h4>\n<p>CDLI provides an easy way to download all Old Assyrian tablets:</p>\n<pre><code>curl -L 'https://cdli.earth/search?period=old+ass&amp;limit=10000&amp;aspect=inscriptions&amp;format=atf' -o old_assyrian.atf\n</code></pre>\n<p>After downloading the data from CDLI, I converted it into the OARE format.</p>\n<h3>2. Merge</h3>\n<p>I merged the two datasets above. After that, I grouped the rows of each tablet into 4–6 chunks; if fewer than two lines remained, I merged them into the previous chunk.</p>\n<p>An example after merging:</p>\n<pre><code>{\"text_id\": \"055b4918-e8aa-4442-99b6-cc4d6f33adf4\", \"designation\": \"AKT 1 30\", \"header_raw\": \"&amp;055b4918-e8aa-4442-99b6-cc4d6f33adf4 = AKT 1 30\", \"atf\": {\"lang\": \"akk\"}, \"sections\": [\"tablet\", \"obverse\", \"reverse\"], \"lines\": [{\"label\": [\"1\", \"2\", \"3\", \"4\"], \"section\": \"obverse\", \"text\": \"4 i-lá-tim ku nu ki ša a-mur-IŠTAR ma-aḫ-ri-ni a-du-ú ù i-ku-pì-a\", \"translation\": null}, {\"label\": [\"5\", \"6\", \"7\", \"8\"], \"section\": \"obverse\", \"text\": \"iš ru mu ma i-na 3 i-lá-tim 3 GÚ 7+0.5 ma-na URUDU is ni qú\", \"translation\": null}, {\"label\": [\"9\", \"10\", \"11\", \"12\"], \"section\": \"reverse\", \"text\": \"a-ḫa-ma i-na 1 i-li-im 20+6 ma-na ta &lt;gap&gt; mu &lt;gap&gt; ù ša a-ba-ri-im\", \"translation\": null}, {\"label\": [\"13\", \"14\", \"15\"], \"section\": \"reverse\", \"text\": \"is ni qú ú IGI a-šur-iš-tí-kál IGI en-nam-a-a\", \"translation\": null}], \"annotations\": []}\n</code></pre>\n<h3>3. Translate merged transliteration units with Gemini 3 Flash Preview</h3>\n<p>I used Gemini 3 Flash Preview to fill in missing translations.</p>\n<p>Prompt example:</p>\n<pre><code>Use the following reference notes while translating Old Assyrian transliteration lines:\n\n{reference_text}\n\nTask:\n- Translate each `text` into concise scholarly English.\n- Keep placeholders and damage markers such as `&lt;gap&gt;`, `[ ... ]`, `/` intact when possible.\n- Keep proper names transliterated.\n- Translate in the same sequence as the input items.\n- Return ONLY JSON with this exact schema:\n  {\n    \"translations\": [\n      {\"line_index\": 0, \"translation\": \"...\"}\n    ]\n  }\n- Include all line_index values exactly once.\n- Keep output order identical to input order.\n\nInput JSON:\n{payload_json}\n</code></pre>\n<p><code>reference_text</code>:</p>\n<pre><code>## Old Assyrian Formulaic Phrases (Patterns 1–12) — Prompt-ready English Descriptions\n\n&gt; Placeholders: `{PN}` (personal name), `{Place}`, `{Amount}`, `{Goods}`, `{MonthName}`.\n\n### 1.1) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} from {SenderPN(s)}:”\n\n### 1.2) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} ù {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} and {RecipientPN} from {SenderPN(s)}:”\n\n### 2.1) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}(-ma) a-na {RecipientPN} qí-bi-ma`\n- **English meaning:** “From {SenderPN} to {RecipientPN}:”\n\n### 2.2) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}-ma a-na {RecipientPN} {RecipientPN} ú {RecipientPN} qí-bi₄-ma a-na {RecipientPN} qí-bi₄-ma`\n- **English meaning:** \"From {SenderPN} to {RecipientPN}, {RecipientPN} and {RecipientPN}; specifically to {RecipientPN}:\"\n\n### 3) Well-being / peace formula\n- **Transliteration template:** `a-na-kam šu-ul-mu-um i-ba-ší`\n- **English meaning:** “All is well here / Peace reigns here.”\n\n### 4) Seal notation (legal label)\n- **Transliteration template:** `KIŠIB {PN} DUMU {FatherPN}`\n- **English meaning:** “Seal of {PN}, son of {FatherPN}.”\n\n### 5) Witness list / “before (the eyes of)”\n- **Transliteration template:** `IGI {Witness1PN} … IGI {WitnessNPN}`\n- **English meaning:** “In the presence of {Witness...} / Witnessed by {Witness...}.”\n\n### 6) kārum (trade colony) procedural/legal clause\n- **Transliteration template:** `a-na a-wa-tim a-ni-a-tim kà-ru-um {Place} i-dí-ni-a-tí(-ma)`\n- **English meaning:** “Regarding these proceedings/matters, the kārum of {Place} granted/issued (to us) ...”\n\n### 7) Oath/testimony “before Aššur’s dagger”\n- **Transliteration template:** `IGI GÍR ša a-šùr ší-bu-tí-ni ni-dí-in`\n- **English meaning:** “We gave our testimony (swore) before Aššur’s dagger.”\n\n### 8) Debt obligation formula (“X owes Y”)\n- **Transliteration template:** `{Amount} KÙ.BABBAR i-ṣé-er {CreditorPN} ... {DebtorPN} i-šu-ú`\n- **English meaning:** “{DebtorPN} owes {Amount} of silver to {CreditorPN}.”\n\n### 9) Receipt / acknowledgement (“has received”)\n- **Transliteration template:** `{Goods/Amount} ... {ReceiverPN} il₅-qé`\n- **English meaning:** “{ReceiverPN} has received {Goods/Amount}.”\n\n### 10) Return/repayment clause\n- **Transliteration template:** `i-tù-ra-ma {Amount/Goods} ...`\n- **English meaning:** “And he returned (it) / and he repaid (...).”\n\n### 11) Dating clause: week + month + eponym (limmu)\n- **Transliteration template:** `iš-tù ḫa-mu-uš-tim ... ITU.KAM {MonthName} li-mu-um {EponymPN} DUMU {FatherPN}`\n- **English meaning:** “Reckoned from the week of ...; month {MonthName}; eponymy (limmu-year) of {EponymPN} son of {FatherPN}.”\n\n### 12) Interest rate clause (per mina per month)\n- **Transliteration template:** `a-na 1 ma-na-im {X} GÍN.TA i-na ITU.KAM ṣí-ib-tám ú-ṣú-bu`\n- **English meaning:** “They will add interest at {X} shekels per 1 mina per month.”\n</code></pre>\n<h2>(Main Corpus) Unmatched Published Corpus</h2>\n<h3>1. Match IDs</h3>\n<p>I matched IDs between the main corpus and <code>published_texts.csv</code> and obtained unmatched transliteration records.</p>\n<h3>2. Split sentences with a chi-square-based chunker</h3>\n<p>Before translating the unmatched published corpus, I split each long transliteration into shorter chunk-sized units with a chi-square-based chunker.</p>\n<p>My working hypothesis was that physical row and edge breaks on tablets often behave like weak punctuation. They do not correspond perfectly to modern sentence boundaries, but they frequently coincide with discourse shifts such as a new legal formula, witness clause, dating clause, or procedural statement. I therefore used the already row-segmented training corpus as weak supervision for where a long unsegmented span might also be safely split.</p>\n<p>Concretely, for each adjacent token pair <code>X || Y</code>, I counted how often the pair stayed within one training row (<code>no_split</code>) and how often a row boundary fell between them (<code>split</code>). Pairs whose boundary rate was unusually high relative to the corpus-wide average received a positive boundary score; pairs that usually stayed together received a negative one. When chunking the target corpus, dynamic programming then searched for cuts that balanced these learned boundary preferences against a target length (<code>min_chunk=16</code>, <code>max_chunk=32</code>, <code>hard_max=47</code>).</p>\n<p>A concrete example is the recurrent legal phrase <code>a-na a-wa-tim a-ni-a-tim ...</code>. The pair <code>a-wa-tim || a-ni-a-tim</code> was learned as a relatively strong candidate boundary:</p>\n<table>\n<thead>\n<tr>\n<th>boundary candidate</th>\n<th>split_count</th>\n<th>no_split_count</th>\n<th>pair_boundary_rate</th>\n<th>global_boundary_rate</th>\n<th>signed_sqrt_chi_square</th>\n<th>chunk_boundary_score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>a-wa-tim || a-ni-a-tim</code></td>\n<td>33</td>\n<td>226</td>\n<td>0.1274</td>\n<td>0.0410</td>\n<td>7.0189</td>\n<td>2.0424</td>\n</tr>\n</tbody>\n</table>\n<p>Even though this pair also occurred many times inside a row, its boundary rate was still about three times higher than the corpus-wide average. In other words, the chunker learned that a break here was substantially more plausible than for an average token transition, so when the surrounding length constraints also fit, it preferred that cut.</p>\n<p>Example:</p>\n<pre><code>scope total length: 46 tokens\n\nchunk 1 (tokens 1-25):\nILLAT šu-nu-nu i-na za-al-pá ni-kà-sí i-sí-ú-ma 7 ma-na 3 GÍN KÙ.BABBAR ni-pí-il-tí &lt;gap&gt; a-šu-mì &lt;gap&gt; ša &lt;gap&gt; ku-&lt;gap&gt; ILLAT &lt;gap&gt; DUMU &lt;gap&gt; ú-ša-&lt;gap&gt; a-na a-wa-tim\n\nchunk 2 (tokens 26-46):\na-ni-a-tim kà-ru-um kà-ni-iš i-dí-ni-a-tí-ma IGI GÍR ša a-šur ṭup-pá-am ni-dí-in IGI dan-a-šur DUMU ša-lim-a-ḫi-im IGI pí-lá-aḫ-a-šur bi-lu-um IGI šu-IŠTAR DUMU da-da-nim\n\nchosen boundary:\na-wa-tim || a-ni-a-tim\nsigned_sqrt_chi_square = 7.01886377\nchunk_boundary_score = 2.04236877\n</code></pre>\n<h3>3. Translate unmatched transliteration records with Gemini 3 Flash Preview</h3>\n<p>I used Gemini 3 Flash Preview to translate the unmatched published transliteration records. The prompt here drifted slightly from the one used in the earlier stage, but not for any especially principled reason. In hindsight these two stages should have shared a single cleaned-up prompt template; instead, under time pressure, I ended up with duplicated prompt variants and lower-quality code than I would have liked.</p>\n<p>Prompt (<code>formulaic_phrase_section</code> is the same as the previously mentioned <code>Old Assyrian Formulaic Phrases (Patterns 1–12)</code> markdown):</p>\n<pre><code>return (\n    \"# Task\\n\"\n    \"Translate the current Old Assyrian / Akkadian transliteration line into English.\\n\"\n    \"Use the surrounding lines only as context. Do not translate the previous or following lines.\\n\\n\"\n    \"## Output Format\\n\"\n    'Return JSON only in the form `{\"translation\": \"...\"}`.\\n\\n'\n    \"## Rules\\n\"\n    \"- No commentary, notes, markdown, or transliteration in the answer.\\n\"\n    \"- Preserve uncertainty and damage tersely when the source is fragmentary.\\n\"\n    \"- Keep names transliterated if they are uncertain.\\n\"\n    \"- Translate measures and numbers naturally when possible.\\n\"\n    \"- If the line is too fragmentary, still give the best partial English translation.\\n\\n\"\n    f\"{formulaic_phrase_section}\\n\\n\"\n    \"## Record\\n\"\n    f\"- **Text ID:** {text_id}\\n\"\n    f\"- **Designation:** {designation}\\n\\n\"\n    \"## Context From The Same Text\\n\"\n    \"### Previous Lines\\n\"\n    f\"{previous_context or '- none'}\\n\\n\"\n    \"### Current Line\\n\"\n    f\"- **Label:** {label_text}\\n\"\n    f\"  **Section:** {section}\\n\"\n    f\"  **Transliteration:** {transliteration}\\n\\n\"\n    \"### Following Lines\\n\"\n    f\"{following_context or '- none'}\\n\"\n)\n</code></pre>\n<h2>(Auxiliary Corpus) Refined <code>train.csv</code></h2>\n<p>I generated retranslated outputs with a model in the score-33.0 class, but used them only for length-based filtering: I excluded cases whose retranslated output length fell outside the +/-10% range. For the actual auxiliary data, I kept the transliteration and translation sentences from <code>train.csv</code>.</p>\n<h2>(Auxiliary Corpus) Larsen 2002</h2>\n<p>I used <a href=\"https://www.kaggle.com/datasets/mpware/dpc-larsen\" target=\"_blank\">DPC - Larsen</a> by MPWARE as an auxiliary corpus.</p>\n<h1>Data Adaptation</h1>\n<p>The raw Gemini translations were only a starting point. Relative to <code>train.csv</code>, they differed systematically in the following respects:</p>\n<ul>\n<li><strong>[Names/Places]</strong> personal-name and place-name spellings often oscillated between anglicized, normalized, and more scholarly transliterated forms</li>\n<li><strong>[Formulae]</strong> recurrent Old Assyrian formulae were translated with inconsistent wording and register</li>\n<li><strong>[OA terms]</strong> some Old Assyrian-specific concepts and terms were difficult to render consistently in compact, dataset-style English</li>\n<li><strong>[Punctuation]</strong> punctuation conventions, especially the use of commas, colons, and semicolons in lists, clauses, and reported speech, did not match the training-side house style</li>\n<li><strong>[Gap handling]</strong> <code>&lt;gap&gt;</code> and other damage markers were often handled inconsistently, either left as spurious English fragments or removed too aggressively</li>\n</ul>\n<p>I therefore treated data adaptation as an iterative patch-and-audit pipeline over two corpora: the published row-wise corpus and the longer auxiliary corpus.</p>\n<h2>What Worked</h2>\n<h3>[Formulae]</h3>\n<p>I kept the normalization of recurrent seal headings, witness clauses, debt clauses, payment clauses, and kinship formulas so that the English matched the compact, formulaic style of <code>train.csv</code>.</p>\n<p>Example:</p>\n<pre><code>10 shekels of refined silver are with Ikupi-Aššur son of Puzur-Ištar.\n-&gt; 10 shekels of refined silver are owed by Ikupi-Aššur son of Puzur-Ištar.\n\nthey shall pay within one month.\n-&gt; they will pay within one month.\n\nfine copper -&gt; good copper\n\nIf he does not pay -&gt; If he has not paid\n</code></pre>\n<h3>[OA terms]</h3>\n<p>For distinctive Old Assyrian terms, I generally did not rewrite the corpus text itself. Instead, I registered preferred equivalents in a glossary and applied them later in post-processing. My reasoning was that keeping these marked terms unchanged during translation reduced the risk of introducing odd lexical variation, while their distinctiveness also made them easy to replace deterministically afterward.</p>\n<p>Example:</p>\n<pre><code>kārum -&gt; colony\n\nmonth Bēltī-ekallim -&gt; month 1\n</code></pre>\n<h3>[Punctuation]</h3>\n<p>I kept the punctuation alignment that split clause-like semicolon chains into sentence-like units, as well as the later conservative speech-framing cleanup used in the final branch.</p>\n<p>Example:</p>\n<pre><code>Aššur-rē'ī owes it; from the week of Akūtum\n-&gt; Aššur-rē'ī owes it. From the week of Akūtum\n</code></pre>\n<h3>[Gap handling]</h3>\n<p>I removed <code>&lt;gap&gt;</code> from the translation when the transliteration had no corresponding <code>&lt;gap&gt;</code>. When the transliteration contained fewer <code>&lt;gap&gt;</code> markers than the translation, I also removed a final translation-side <code>&lt;gap&gt;</code> when it was attached to an adjacent alphanumeric character.</p>\n<p>Example:</p>\n<pre><code>&lt;gap&gt;seize (him) and the silver and its interest&lt;gap&gt;\n-&gt; seize (him) and the silver and its interest\n\nWith his deposits&lt;gap&gt;\n-&gt; With his deposits\n</code></pre>\n<h2>What Did Not Work Reliably</h2>\n<h3>[Names/Places]</h3>\n<p>I first tried broader normalization of personal and place names, including (1) simple replacements based on occurrence counts in the <code>train.csv</code> and (2) preferences for more scholarly spellings in the <code>onomasticon.csv</code>, especially long-vowel forms. In practice, however, I could not find a consistently effective methodology. I therefore retained only a small set of changes that seemed to improve the LB, added them to a glossary, and used that glossary in post-processing, even if the changes did not appear to follow a fully consistent principle.</p>\n<p>Example:</p>\n<pre><code>Abua -&gt; Abuwa\nAdudua -&gt; Aduduwa\nAgua -&gt; Aguwa\nAkua -&gt; Akuwa\nSamāya -&gt; Samaya\n</code></pre>\n<h2>🎯 Lottery</h2>\n<h3>[Names/Places]</h3>\n<p>As a lottery-ticket heuristic, I compared <code>train.csv</code> with <code>published_texts.csv</code>, manually inspected the top 100 cases whose frequency in <code>train.csv</code> looked implausibly low, and added selected entries to a normalization dictionary. The top five personal-name examples were as follows:</p>\n<pre><code>i-ku-pì-a -&gt; Ikupia\ni-dí-a-šur -&gt; Idi-Aššur\nšál-ma-a-šur -&gt; Šalma-Aššur\ni-dí-sú-en -&gt; Idi-Suen\nšu-be-lim -&gt; Šu-Belim\n</code></pre>\n<h3>[Punctuation]</h3>\n<p>As another lottery-ticket heuristic, I replaced <code>Thus you (said):</code>, <code>Thus (said) PN:</code>, and related <code>Thus</code>-based expressions outside letter openings. The score began to drop partway through this line of experimentation, but I still kept this direction because the translation style of <code>train.csv</code> used <code>Thus</code> far less often.</p>\n<p>Example:</p>\n<pre><code>Thus you (said):\n-&gt; You said:\n\nThus (said) Ennam-Suen:\n-&gt; Ennam-Suen said:\n</code></pre>\n<p>In other words, after the manual auxiliary cleanup stage, the auxiliary corpus was stable, and the remaining adaptation work focused on bringing the published row-wise corpus closer to the auxiliary / <code>train.csv</code> punctuation and discourse style.</p>\n<h1>Training</h1>\n<p>For the final <code>byt5-large</code> runs, I optimized two data streams in parallel: a main row-wise objective on the adapted published corpus (<strong>46,502</strong> transliteration/translation pairs) and a secondary full-sequence objective on a smaller auxiliary corpus (<strong>1,358</strong> examples used in training). The main corpus taught row-level alignment in the competition format, while the auxiliary corpus helped preserve longer-range fluency and formulaic phrasing.</p>\n<p>For offline model selection, I used the script's default random approximate 80/10/10 split on the final 46,502-example main row-wise corpus, which produced <strong>37,202</strong> training rows, <strong>4,650</strong> validation rows, and <strong>4,650</strong> test rows in the seed-42 run.</p>\n<h2>1. Create lookback, source, and lookahead sequences for the main objective</h2>\n<p>Before training, each row in the main corpus was converted into a context-augmented input of the form:</p>\n<pre><code>[LOOKBACK_ONLY] &lt;previous tokens&gt; [SOURCE] &lt;current row&gt; [LOOKAHEAD_ONLY] &lt;next tokens&gt;\n</code></pre>\n<p>In the final setting, each row received up to four tokens of left context and up to four tokens of right context, drawn from earlier and later rows within the same tablet/document. The target remained only the English translation of the current row, so the surrounding text served only as additional source-side evidence. Thus, this was row-wise contextual training, not the chi-square chunking used later at inference time.</p>\n<pre><code>cdli_id:\nbce88917-e85f-02a8-609f-3f2d37c0d85d.tablet.4\n\ntransliteration:\nša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur\n\nmodel_input:\n[LOOKBACK_ONLY] šu-a-šur i-šu-ú 1 ṭup-pu-um [SOURCE] ša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur [LOOKAHEAD_ONLY] ba-lá-ṭí-šu-nu-ma a-na pu-šu-ke-en6 DUMU\n\ntarget:\nof 2 minas of silver which Buzazu owes to Belanum; these 4 tablets according to the proxy of Belanum, son of Šu-Aššur.\n</code></pre>\n<h2>2. Add an auxiliary full-sequence objective</h2>\n<p>The auxiliary examples were longer, style-cleaned translations derived from cleaned train-side material and Larsen-related texts. They were not row-wise context windows; instead, they exposed the model to longer document-scale source/target mappings.</p>\n<p>Implementation-wise, the main loss was computed on the row-wise contextual batches above, and during the same optimizer step I also sampled one auxiliary batch and added <code>0.3 * aux_loss</code> before the parameter update. For the final setting, the auxiliary loader used <code>batch_size=1</code>, <code>max_source_length=1536</code>, and <code>max_target_length=1536</code>. One overlength auxiliary example was filtered out before training, leaving <strong>1,358</strong> auxiliary examples in the final training set.</p>\n<p>The main training hyperparameters for the final <code>byt5-large</code> models were:</p>\n<ul>\n<li>model: <code>google/byt5-large</code></li>\n<li>epochs: <code>4</code></li>\n<li>batch size: <code>32</code></li>\n<li>learning rate: <code>2e-4</code></li>\n<li>weight decay: <code>0.01</code></li>\n<li>max source length: <code>448</code></li>\n<li>max target length: <code>448</code></li>\n<li>warmup steps: <code>465</code></li>\n<li>gradient clipping: <code>1.0</code></li>\n</ul>\n<p>I trained the same configuration with different random seeds (<code>42</code>, <code>60</code>, <code>28</code>, and <code>52</code>) and selected the best checkpoint from each run based on validation loss.</p>\n<h1>Inference</h1>\n<h2>1. Chunk test rows with local context</h2>\n<p>At inference time, I first normalized the source-side division-number notation, then split each test transliteration with the same chi-square chunker described above. I used <code>min_chunk=16</code> and <code>max_chunk=32</code>, so the model saw chunk-sized units rather than entire long test rows at once.</p>\n<p>For each chunk, I then constructed a context-augmented input in the same format used during training:</p>\n<pre><code>[LOOKBACK_ONLY] &lt;previous tokens&gt; [SOURCE] &lt;current chunk&gt; [LOOKAHEAD_ONLY] &lt;next tokens&gt;\n</code></pre>\n<p>In the final setting, I used <code>lookback_tokens=4</code> and <code>lookahead_tokens=4</code>. If this context was too short in characters, I allowed the neighboring window to expand slightly until it reached a small minimum textual mass. This kept the prediction target local to one chunk while still exposing nearby formulae, names, and discourse cues.</p>\n<h2>2. Candidate generation and MBR selection</h2>\n<p>I ensembled four <code>byt5-large</code> checkpoints at inference time: two runs trained on the final row-wise adapted corpus produced by the last data-adaptation pass, and two runs trained on the immediately preceding row-wise adapted version from one step earlier in that same pipeline. Their mixture weights were not uniform; the two checkpoints from the final adapted corpus contributed <code>0.2</code> each, and the two checkpoints from the preceding adapted corpus contributed <code>0.3</code> each. Generation used <code>max_source_length=448</code>, and the decoding budget for the target side was scaled adaptively between <code>192</code> and <code>448</code> new tokens depending on the encoded source length.</p>\n<p>For each chunk and each checkpoint, I generated a heterogeneous candidate pool:</p>\n<ul>\n<li><code>4</code> standard beam candidates</li>\n<li><code>4</code> diverse-beam candidates</li>\n<li><code>6</code> nucleus-sampling candidates (<code>2</code> samples each at temperatures <code>0.55</code>, <code>0.75</code>, and <code>0.95</code>)</li>\n</ul>\n<p>This yielded up to <code>56</code> raw candidates per chunk before deduplication across the four checkpoints.</p>\n<p>I then selected the final chunk translation with minimum Bayes risk decoding over the pooled candidate set. The MBR gain combined sentence-level chrF++, sentence BLEU, token-level Jaccard overlap, and a mild length bonus centered on the median candidate length. I weighted chrF++ most heavily (<code>6.0</code>), followed by BLEU (<code>2.0</code>), while Jaccard and the length bonus each received weight <code>1.0</code>. Within each checkpoint, the evidence mass was distributed uniformly across its candidates, and the total contribution of each checkpoint was then scaled by the mixture weights above. When several hypotheses remained close, ranking was further stabilized by support count and generation score.</p>\n<h2>3. Reconstruct rows and post-edit</h2>\n<p>After MBR selection, I concatenated the winning chunk translations in their original order to recover one English translation per test row. I then applied a small deterministic cleanup and post-editing pipeline: normalization of transliteration-style characters and quotation marks, removal of residual bracketed uncertainty markers, source-aware handling of <code>&lt;gap&gt;</code>, restoration of competition-specific number and glossary conventions, and two lightweight logistic-regression post-editors to nudge the output toward the training-set style.</p>\n<h1>Ablation Study</h1>\n<h2>Single Model vs Ensemble (MBR)</h2>\n<ul>\n<li>MBR ensembling yielded a modest improvement on the Private LB compared with the single-model runs, while no consistent improvement was observed on the Public LB.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large(seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.4389</td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 28)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>37.7196</td>\n<td>36.9437</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 42)</td>\n<td>The preceding adapted corpus</td>\n<td>chi-square</td>\n<td>38.1309</td>\n<td>37.6288</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 60)</td>\n<td>The preceding adapted corpus</td>\n<td>chi-square</td>\n<td>38.3819</td>\n<td>37.1679</td>\n</tr>\n<tr>\n<td>Ensemble (MBR)</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td><strong>38.5514</strong></td>\n<td>37.4818</td>\n</tr>\n</tbody>\n</table>\n<h2>Effect of glossary replacement(GR), post-processes(PP)</h2>\n<ul>\n<li>In the single-model setting, removing post-processing or glossary replacement led to lower Public LB scores, while the effect on the Private LB was small and less consistent. This suggests that both techniques were beneficial mainly for Public LB performance.</li>\n</ul>\n<h3>Single Model</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large(seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.4389</td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52) -PP</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.4362</td>\n<td>37.6650</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52) -PP-GR</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4443</strong></td>\n<td>37.6819</td>\n</tr>\n</tbody>\n</table>\n<h3>Ensemble</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Ensemble (MBR)</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td>38.5514</td>\n<td>37.4818</td>\n</tr>\n<tr>\n<td>Ensemble (MBR) -PP</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td>38.5614</td>\n<td><strong>37.4821</strong></td>\n</tr>\n<tr>\n<td>Ensemble (MBR) -PP-GR</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td><strong>38.5686</strong></td>\n<td>37.3774</td>\n</tr>\n</tbody>\n</table>\n<h2>ByT5-Large vs. ByT5-Base</h2>\n<ul>\n<li>The benefit of ByT5-Large became clearer after style adaptation; on the pre-adaptation corpus, its performance was not consistently better than ByT5-Base, particularly on the public LB.</li>\n</ul>\n<h3>On the Final Adapted Corpus</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4389</strong></td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.0925</td>\n<td>37.0492</td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>37.9296</td>\n<td>37.0533</td>\n</tr>\n</tbody>\n</table>\n<h3>On the Pre-adaptation Corpus</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td><strong>37.5068</strong></td>\n<td>36.7824</td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td>37.0518</td>\n<td>36.5225</td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td>37.1781</td>\n<td><strong>36.9766</strong></td>\n</tr>\n</tbody>\n</table>\n<h2>Effect of Data Adaptation</h2>\n<ul>\n<li>Data adaptation improved performance on both the Private and Public LBs, indicating that adapting the corpus was effective for this task.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td>37.5068</td>\n<td>36.7824</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4389</strong></td>\n<td><strong>37.7799</strong></td>\n</tr>\n</tbody>\n</table>\n<h2>Effect of the chi-square chunker</h2>\n<ul>\n<li>The chi-square chunker outperformed both the [SOURCE]-only setting and fixed 16-token chunking on both leaderboards, suggesting that the chunking strategy was important for strong performance.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4389</strong></td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td><code>[SOURCE]</code> only (max_source_length/max_new_tokens 768 tokens)</td>\n<td>38.2861</td>\n<td>36.6346</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>fixed 16-token chunks</td>\n<td>38.0926</td>\n<td>36.9625</td>\n</tr>\n</tbody>\n</table>\n<h1>Appendix</h1>\n<h2>Early in this competition</h2>\n<ul>\n<li>I tried few-shot RAG + babylem-like lemmatizer approaches with Qwen3 Next or Kimi Linear, but I could not achieve a score above 22.x.</li>\n</ul>\n<h2>Tried But Did Not Work</h2>\n<ul>\n<li>Moses SMT<ul>\n<li>There were too many unknown terms, which exceeded the capacity of SMT systems</li></ul></li>\n<li>Source Contrastive Decoding (EACL 2024)<ul>\n<li><a href=\"https://arxiv.org/pdf/2309.07098\" target=\"_blank\">https://arxiv.org/pdf/2309.07098</a></li>\n<li>I used in-batch alternative sources instead of the paper’s random sampling scheme, so a more faithful implementation may still improve performance.</li></ul></li>\n<li>Auxiliary full-sequence training<ul>\n<li>Training ByT5-base/small on the auxiliary transliteration–translation pairs at their original sequence lengths was not particularly effective as a standalone setting, although the same data was still useful as an auxiliary objective. Longer sequences also tended to produce stronger repetition. I was not able to test whether ByT5-large would behave differently on these longer sequences, since I did not have sufficient computational resources to run it with a sufficiently large batch size.</li></ul></li>\n<li>Encoder-Only byt5<ul>\n<li>I extracted the encoder modules from the original ByT5 models and used them like BERT.</li></ul></li>\n</ul>\n<h2>Environment</h2>\n<h2>Local</h2>\n<ul>\n<li>CPU: Ryzen7 9800X3D (8 cores)</li>\n<li>GPU: RTX 5090 (VRAM 32GB)</li>\n<li>RAM: 192GB</li>\n</ul>\n<h2>vast.ai</h2>\n<ul>\n<li>For the final two days, local hardware alone was not enough to finish training in time, so I used an RTX 5090 instance on Vast.ai.</li>\n</ul>\n<hr>\n<p>Thanks again to the hosts for this competition. I learned a lot from this problem, especially about corpus construction and style alignment. I am also grateful to the community for sharing many interesting ideas throughout the competition.</p>",
  "messages": [
    {
      "id": 3427861,
      "postDate": "2026-03-24T16:21:20.233Z",
      "content": "<p>First, I would like to thank the Kaggle hosts for organizing this competition and for providing such an interesting problem.</p>\n<h1>Summary</h1>\n<p>My final solution was a contextual ByT5-large system with chunked ensemble inference, but the biggest gains came from data work rather than model changes.</p>\n<ul>\n<li><strong>Data</strong>: built a larger published row-wise corpus from OARE/CDLI, added a smaller auxiliary full-sequence corpus, and filled missing translations with formula-aware Gemini prompting</li>\n<li><strong>Black-box Distillation</strong>: used a stronger closed model to generate pseudo-labels, then trained a smaller open model on the resulting parallel data</li>\n<li><strong>Style adaptation</strong>: repeatedly cleaned names, formulaic expressions, punctuation, and  handling to better match the compact English style of train.csv</li>\n<li><strong>Training</strong>: trained ByT5-large with a main row-wise contextual objective and a lighter auxiliary full-sequence objective</li>\n<li><strong>Inference</strong>: chunked long test transliterations with a chi-square chunker, added local lookback/lookahead context, ensembled four checkpoints, reranked with MBR, and applied deterministic post-editing</li>\n</ul>\n<p>Overall, the system was built around three ideas: better corpus construction, stronger style adaptation, and more careful chunk-level inference.</p>\n<pre><code>Approximate contribution to the final score (from ablations)\n\nPrivate LB:\nData adaptation   [########################......] +0.93\nChunking          [#########.....................] +0.15 to +0.35\nByT5-Large        [#########.....................] +0.35\nEnsemble + MBR    [###...........................] +0.11\nPost-edit / GR    [..............................] ~0.00\n\nPublic LB:\nData adaptation   [##########################....] +1.00\nChunking          [##############################] +0.82 to +1.15\nByT5-Large        [###################...........] +0.73\nEnsemble + MBR    [..............................] no consistent gain\nPost-edit / GR    [###...........................] +0.10\n</code></pre>\n<h1>Datasets</h1>\n<p>I prepared two corpora for training:</p>\n<ul>\n<li><strong>published row-wise corpus:</strong> 46,503 transliteration/translation pairs were prepared; 46,502 were retained in the final adapted corpus</li>\n<li><strong>auxiliary full-sequence corpus:</strong> 1,359 transliteration/translation pairs were prepared; 1,358 were used in training after filtering one overlength example</li>\n</ul>\n<h2>(Main Corpus) Published Corpus Construction</h2>\n<h3>1. Obtain raw data from source APIs</h3>\n<p>I found several useful APIs.</p>\n<h4>oare.byu.edu</h4>\n<ul>\n<li><p>UUID feeder:\n<code>https://oare.byu.edu/api/v2/search?characters=&amp;textTitle=AKT&amp;page=1&amp;rows=100&amp;mode=respectAllBoundaries</code></p></li>\n<li><p>Tablet feeder:\n<code>https://oare.byu.edu/api/v2/text_epigraphies/text/${uuid}?forceAllowAdminView=false</code></p></li>\n</ul>\n<h4>CDLI</h4>\n<p>CDLI provides an easy way to download all Old Assyrian tablets:</p>\n<pre><code>curl -L 'https://cdli.earth/search?period=old+ass&amp;limit=10000&amp;aspect=inscriptions&amp;format=atf' -o old_assyrian.atf\n</code></pre>\n<p>After downloading the data from CDLI, I converted it into the OARE format.</p>\n<h3>2. Merge</h3>\n<p>I merged the two datasets above. After that, I grouped the rows of each tablet into 4–6 chunks; if fewer than two lines remained, I merged them into the previous chunk.</p>\n<p>An example after merging:</p>\n<pre><code>{\"text_id\": \"055b4918-e8aa-4442-99b6-cc4d6f33adf4\", \"designation\": \"AKT 1 30\", \"header_raw\": \"&amp;055b4918-e8aa-4442-99b6-cc4d6f33adf4 = AKT 1 30\", \"atf\": {\"lang\": \"akk\"}, \"sections\": [\"tablet\", \"obverse\", \"reverse\"], \"lines\": [{\"label\": [\"1\", \"2\", \"3\", \"4\"], \"section\": \"obverse\", \"text\": \"4 i-lá-tim ku nu ki ša a-mur-IŠTAR ma-aḫ-ri-ni a-du-ú ù i-ku-pì-a\", \"translation\": null}, {\"label\": [\"5\", \"6\", \"7\", \"8\"], \"section\": \"obverse\", \"text\": \"iš ru mu ma i-na 3 i-lá-tim 3 GÚ 7+0.5 ma-na URUDU is ni qú\", \"translation\": null}, {\"label\": [\"9\", \"10\", \"11\", \"12\"], \"section\": \"reverse\", \"text\": \"a-ḫa-ma i-na 1 i-li-im 20+6 ma-na ta &lt;gap&gt; mu &lt;gap&gt; ù ša a-ba-ri-im\", \"translation\": null}, {\"label\": [\"13\", \"14\", \"15\"], \"section\": \"reverse\", \"text\": \"is ni qú ú IGI a-šur-iš-tí-kál IGI en-nam-a-a\", \"translation\": null}], \"annotations\": []}\n</code></pre>\n<h3>3. Translate merged transliteration units with Gemini 3 Flash Preview</h3>\n<p>I used Gemini 3 Flash Preview to fill in missing translations.</p>\n<p>Prompt example:</p>\n<pre><code>Use the following reference notes while translating Old Assyrian transliteration lines:\n\n{reference_text}\n\nTask:\n- Translate each `text` into concise scholarly English.\n- Keep placeholders and damage markers such as `&lt;gap&gt;`, `[ ... ]`, `/` intact when possible.\n- Keep proper names transliterated.\n- Translate in the same sequence as the input items.\n- Return ONLY JSON with this exact schema:\n  {\n    \"translations\": [\n      {\"line_index\": 0, \"translation\": \"...\"}\n    ]\n  }\n- Include all line_index values exactly once.\n- Keep output order identical to input order.\n\nInput JSON:\n{payload_json}\n</code></pre>\n<p><code>reference_text</code>:</p>\n<pre><code>## Old Assyrian Formulaic Phrases (Patterns 1–12) — Prompt-ready English Descriptions\n\n&gt; Placeholders: `{PN}` (personal name), `{Place}`, `{Amount}`, `{Goods}`, `{MonthName}`.\n\n### 1.1) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} from {SenderPN(s)}:”\n\n### 1.2) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} ù {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} and {RecipientPN} from {SenderPN(s)}:”\n\n### 2.1) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}(-ma) a-na {RecipientPN} qí-bi-ma`\n- **English meaning:** “From {SenderPN} to {RecipientPN}:”\n\n### 2.2) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}-ma a-na {RecipientPN} {RecipientPN} ú {RecipientPN} qí-bi₄-ma a-na {RecipientPN} qí-bi₄-ma`\n- **English meaning:** \"From {SenderPN} to {RecipientPN}, {RecipientPN} and {RecipientPN}; specifically to {RecipientPN}:\"\n\n### 3) Well-being / peace formula\n- **Transliteration template:** `a-na-kam šu-ul-mu-um i-ba-ší`\n- **English meaning:** “All is well here / Peace reigns here.”\n\n### 4) Seal notation (legal label)\n- **Transliteration template:** `KIŠIB {PN} DUMU {FatherPN}`\n- **English meaning:** “Seal of {PN}, son of {FatherPN}.”\n\n### 5) Witness list / “before (the eyes of)”\n- **Transliteration template:** `IGI {Witness1PN} … IGI {WitnessNPN}`\n- **English meaning:** “In the presence of {Witness...} / Witnessed by {Witness...}.”\n\n### 6) kārum (trade colony) procedural/legal clause\n- **Transliteration template:** `a-na a-wa-tim a-ni-a-tim kà-ru-um {Place} i-dí-ni-a-tí(-ma)`\n- **English meaning:** “Regarding these proceedings/matters, the kārum of {Place} granted/issued (to us) ...”\n\n### 7) Oath/testimony “before Aššur’s dagger”\n- **Transliteration template:** `IGI GÍR ša a-šùr ší-bu-tí-ni ni-dí-in`\n- **English meaning:** “We gave our testimony (swore) before Aššur’s dagger.”\n\n### 8) Debt obligation formula (“X owes Y”)\n- **Transliteration template:** `{Amount} KÙ.BABBAR i-ṣé-er {CreditorPN} ... {DebtorPN} i-šu-ú`\n- **English meaning:** “{DebtorPN} owes {Amount} of silver to {CreditorPN}.”\n\n### 9) Receipt / acknowledgement (“has received”)\n- **Transliteration template:** `{Goods/Amount} ... {ReceiverPN} il₅-qé`\n- **English meaning:** “{ReceiverPN} has received {Goods/Amount}.”\n\n### 10) Return/repayment clause\n- **Transliteration template:** `i-tù-ra-ma {Amount/Goods} ...`\n- **English meaning:** “And he returned (it) / and he repaid (...).”\n\n### 11) Dating clause: week + month + eponym (limmu)\n- **Transliteration template:** `iš-tù ḫa-mu-uš-tim ... ITU.KAM {MonthName} li-mu-um {EponymPN} DUMU {FatherPN}`\n- **English meaning:** “Reckoned from the week of ...; month {MonthName}; eponymy (limmu-year) of {EponymPN} son of {FatherPN}.”\n\n### 12) Interest rate clause (per mina per month)\n- **Transliteration template:** `a-na 1 ma-na-im {X} GÍN.TA i-na ITU.KAM ṣí-ib-tám ú-ṣú-bu`\n- **English meaning:** “They will add interest at {X} shekels per 1 mina per month.”\n</code></pre>\n<h2>(Main Corpus) Unmatched Published Corpus</h2>\n<h3>1. Match IDs</h3>\n<p>I matched IDs between the main corpus and <code>published_texts.csv</code> and obtained unmatched transliteration records.</p>\n<h3>2. Split sentences with a chi-square-based chunker</h3>\n<p>Before translating the unmatched published corpus, I split each long transliteration into shorter chunk-sized units with a chi-square-based chunker.</p>\n<p>My working hypothesis was that physical row and edge breaks on tablets often behave like weak punctuation. They do not correspond perfectly to modern sentence boundaries, but they frequently coincide with discourse shifts such as a new legal formula, witness clause, dating clause, or procedural statement. I therefore used the already row-segmented training corpus as weak supervision for where a long unsegmented span might also be safely split.</p>\n<p>Concretely, for each adjacent token pair <code>X || Y</code>, I counted how often the pair stayed within one training row (<code>no_split</code>) and how often a row boundary fell between them (<code>split</code>). Pairs whose boundary rate was unusually high relative to the corpus-wide average received a positive boundary score; pairs that usually stayed together received a negative one. When chunking the target corpus, dynamic programming then searched for cuts that balanced these learned boundary preferences against a target length (<code>min_chunk=16</code>, <code>max_chunk=32</code>, <code>hard_max=47</code>).</p>\n<p>A concrete example is the recurrent legal phrase <code>a-na a-wa-tim a-ni-a-tim ...</code>. The pair <code>a-wa-tim || a-ni-a-tim</code> was learned as a relatively strong candidate boundary:</p>\n<table>\n<thead>\n<tr>\n<th>boundary candidate</th>\n<th>split_count</th>\n<th>no_split_count</th>\n<th>pair_boundary_rate</th>\n<th>global_boundary_rate</th>\n<th>signed_sqrt_chi_square</th>\n<th>chunk_boundary_score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>a-wa-tim || a-ni-a-tim</code></td>\n<td>33</td>\n<td>226</td>\n<td>0.1274</td>\n<td>0.0410</td>\n<td>7.0189</td>\n<td>2.0424</td>\n</tr>\n</tbody>\n</table>\n<p>Even though this pair also occurred many times inside a row, its boundary rate was still about three times higher than the corpus-wide average. In other words, the chunker learned that a break here was substantially more plausible than for an average token transition, so when the surrounding length constraints also fit, it preferred that cut.</p>\n<p>Example:</p>\n<pre><code>scope total length: 46 tokens\n\nchunk 1 (tokens 1-25):\nILLAT šu-nu-nu i-na za-al-pá ni-kà-sí i-sí-ú-ma 7 ma-na 3 GÍN KÙ.BABBAR ni-pí-il-tí &lt;gap&gt; a-šu-mì &lt;gap&gt; ša &lt;gap&gt; ku-&lt;gap&gt; ILLAT &lt;gap&gt; DUMU &lt;gap&gt; ú-ša-&lt;gap&gt; a-na a-wa-tim\n\nchunk 2 (tokens 26-46):\na-ni-a-tim kà-ru-um kà-ni-iš i-dí-ni-a-tí-ma IGI GÍR ša a-šur ṭup-pá-am ni-dí-in IGI dan-a-šur DUMU ša-lim-a-ḫi-im IGI pí-lá-aḫ-a-šur bi-lu-um IGI šu-IŠTAR DUMU da-da-nim\n\nchosen boundary:\na-wa-tim || a-ni-a-tim\nsigned_sqrt_chi_square = 7.01886377\nchunk_boundary_score = 2.04236877\n</code></pre>\n<h3>3. Translate unmatched transliteration records with Gemini 3 Flash Preview</h3>\n<p>I used Gemini 3 Flash Preview to translate the unmatched published transliteration records. The prompt here drifted slightly from the one used in the earlier stage, but not for any especially principled reason. In hindsight these two stages should have shared a single cleaned-up prompt template; instead, under time pressure, I ended up with duplicated prompt variants and lower-quality code than I would have liked.</p>\n<p>Prompt (<code>formulaic_phrase_section</code> is the same as the previously mentioned <code>Old Assyrian Formulaic Phrases (Patterns 1–12)</code> markdown):</p>\n<pre><code>return (\n    \"# Task\\n\"\n    \"Translate the current Old Assyrian / Akkadian transliteration line into English.\\n\"\n    \"Use the surrounding lines only as context. Do not translate the previous or following lines.\\n\\n\"\n    \"## Output Format\\n\"\n    'Return JSON only in the form `{\"translation\": \"...\"}`.\\n\\n'\n    \"## Rules\\n\"\n    \"- No commentary, notes, markdown, or transliteration in the answer.\\n\"\n    \"- Preserve uncertainty and damage tersely when the source is fragmentary.\\n\"\n    \"- Keep names transliterated if they are uncertain.\\n\"\n    \"- Translate measures and numbers naturally when possible.\\n\"\n    \"- If the line is too fragmentary, still give the best partial English translation.\\n\\n\"\n    f\"{formulaic_phrase_section}\\n\\n\"\n    \"## Record\\n\"\n    f\"- **Text ID:** {text_id}\\n\"\n    f\"- **Designation:** {designation}\\n\\n\"\n    \"## Context From The Same Text\\n\"\n    \"### Previous Lines\\n\"\n    f\"{previous_context or '- none'}\\n\\n\"\n    \"### Current Line\\n\"\n    f\"- **Label:** {label_text}\\n\"\n    f\"  **Section:** {section}\\n\"\n    f\"  **Transliteration:** {transliteration}\\n\\n\"\n    \"### Following Lines\\n\"\n    f\"{following_context or '- none'}\\n\"\n)\n</code></pre>\n<h2>(Auxiliary Corpus) Refined <code>train.csv</code></h2>\n<p>I generated retranslated outputs with a model in the score-33.0 class, but used them only for length-based filtering: I excluded cases whose retranslated output length fell outside the +/-10% range. For the actual auxiliary data, I kept the transliteration and translation sentences from <code>train.csv</code>.</p>\n<h2>(Auxiliary Corpus) Larsen 2002</h2>\n<p>I used <a href=\"https://www.kaggle.com/datasets/mpware/dpc-larsen\" target=\"_blank\">DPC - Larsen</a> by MPWARE as an auxiliary corpus.</p>\n<h1>Data Adaptation</h1>\n<p>The raw Gemini translations were only a starting point. Relative to <code>train.csv</code>, they differed systematically in the following respects:</p>\n<ul>\n<li><strong>[Names/Places]</strong> personal-name and place-name spellings often oscillated between anglicized, normalized, and more scholarly transliterated forms</li>\n<li><strong>[Formulae]</strong> recurrent Old Assyrian formulae were translated with inconsistent wording and register</li>\n<li><strong>[OA terms]</strong> some Old Assyrian-specific concepts and terms were difficult to render consistently in compact, dataset-style English</li>\n<li><strong>[Punctuation]</strong> punctuation conventions, especially the use of commas, colons, and semicolons in lists, clauses, and reported speech, did not match the training-side house style</li>\n<li><strong>[Gap handling]</strong> <code>&lt;gap&gt;</code> and other damage markers were often handled inconsistently, either left as spurious English fragments or removed too aggressively</li>\n</ul>\n<p>I therefore treated data adaptation as an iterative patch-and-audit pipeline over two corpora: the published row-wise corpus and the longer auxiliary corpus.</p>\n<h2>What Worked</h2>\n<h3>[Formulae]</h3>\n<p>I kept the normalization of recurrent seal headings, witness clauses, debt clauses, payment clauses, and kinship formulas so that the English matched the compact, formulaic style of <code>train.csv</code>.</p>\n<p>Example:</p>\n<pre><code>10 shekels of refined silver are with Ikupi-Aššur son of Puzur-Ištar.\n-&gt; 10 shekels of refined silver are owed by Ikupi-Aššur son of Puzur-Ištar.\n\nthey shall pay within one month.\n-&gt; they will pay within one month.\n\nfine copper -&gt; good copper\n\nIf he does not pay -&gt; If he has not paid\n</code></pre>\n<h3>[OA terms]</h3>\n<p>For distinctive Old Assyrian terms, I generally did not rewrite the corpus text itself. Instead, I registered preferred equivalents in a glossary and applied them later in post-processing. My reasoning was that keeping these marked terms unchanged during translation reduced the risk of introducing odd lexical variation, while their distinctiveness also made them easy to replace deterministically afterward.</p>\n<p>Example:</p>\n<pre><code>kārum -&gt; colony\n\nmonth Bēltī-ekallim -&gt; month 1\n</code></pre>\n<h3>[Punctuation]</h3>\n<p>I kept the punctuation alignment that split clause-like semicolon chains into sentence-like units, as well as the later conservative speech-framing cleanup used in the final branch.</p>\n<p>Example:</p>\n<pre><code>Aššur-rē'ī owes it; from the week of Akūtum\n-&gt; Aššur-rē'ī owes it. From the week of Akūtum\n</code></pre>\n<h3>[Gap handling]</h3>\n<p>I removed <code>&lt;gap&gt;</code> from the translation when the transliteration had no corresponding <code>&lt;gap&gt;</code>. When the transliteration contained fewer <code>&lt;gap&gt;</code> markers than the translation, I also removed a final translation-side <code>&lt;gap&gt;</code> when it was attached to an adjacent alphanumeric character.</p>\n<p>Example:</p>\n<pre><code>&lt;gap&gt;seize (him) and the silver and its interest&lt;gap&gt;\n-&gt; seize (him) and the silver and its interest\n\nWith his deposits&lt;gap&gt;\n-&gt; With his deposits\n</code></pre>\n<h2>What Did Not Work Reliably</h2>\n<h3>[Names/Places]</h3>\n<p>I first tried broader normalization of personal and place names, including (1) simple replacements based on occurrence counts in the <code>train.csv</code> and (2) preferences for more scholarly spellings in the <code>onomasticon.csv</code>, especially long-vowel forms. In practice, however, I could not find a consistently effective methodology. I therefore retained only a small set of changes that seemed to improve the LB, added them to a glossary, and used that glossary in post-processing, even if the changes did not appear to follow a fully consistent principle.</p>\n<p>Example:</p>\n<pre><code>Abua -&gt; Abuwa\nAdudua -&gt; Aduduwa\nAgua -&gt; Aguwa\nAkua -&gt; Akuwa\nSamāya -&gt; Samaya\n</code></pre>\n<h2>🎯 Lottery</h2>\n<h3>[Names/Places]</h3>\n<p>As a lottery-ticket heuristic, I compared <code>train.csv</code> with <code>published_texts.csv</code>, manually inspected the top 100 cases whose frequency in <code>train.csv</code> looked implausibly low, and added selected entries to a normalization dictionary. The top five personal-name examples were as follows:</p>\n<pre><code>i-ku-pì-a -&gt; Ikupia\ni-dí-a-šur -&gt; Idi-Aššur\nšál-ma-a-šur -&gt; Šalma-Aššur\ni-dí-sú-en -&gt; Idi-Suen\nšu-be-lim -&gt; Šu-Belim\n</code></pre>\n<h3>[Punctuation]</h3>\n<p>As another lottery-ticket heuristic, I replaced <code>Thus you (said):</code>, <code>Thus (said) PN:</code>, and related <code>Thus</code>-based expressions outside letter openings. The score began to drop partway through this line of experimentation, but I still kept this direction because the translation style of <code>train.csv</code> used <code>Thus</code> far less often.</p>\n<p>Example:</p>\n<pre><code>Thus you (said):\n-&gt; You said:\n\nThus (said) Ennam-Suen:\n-&gt; Ennam-Suen said:\n</code></pre>\n<p>In other words, after the manual auxiliary cleanup stage, the auxiliary corpus was stable, and the remaining adaptation work focused on bringing the published row-wise corpus closer to the auxiliary / <code>train.csv</code> punctuation and discourse style.</p>\n<h1>Training</h1>\n<p>For the final <code>byt5-large</code> runs, I optimized two data streams in parallel: a main row-wise objective on the adapted published corpus (<strong>46,502</strong> transliteration/translation pairs) and a secondary full-sequence objective on a smaller auxiliary corpus (<strong>1,358</strong> examples used in training). The main corpus taught row-level alignment in the competition format, while the auxiliary corpus helped preserve longer-range fluency and formulaic phrasing.</p>\n<p>For offline model selection, I used the script's default random approximate 80/10/10 split on the final 46,502-example main row-wise corpus, which produced <strong>37,202</strong> training rows, <strong>4,650</strong> validation rows, and <strong>4,650</strong> test rows in the seed-42 run.</p>\n<h2>1. Create lookback, source, and lookahead sequences for the main objective</h2>\n<p>Before training, each row in the main corpus was converted into a context-augmented input of the form:</p>\n<pre><code>[LOOKBACK_ONLY] &lt;previous tokens&gt; [SOURCE] &lt;current row&gt; [LOOKAHEAD_ONLY] &lt;next tokens&gt;\n</code></pre>\n<p>In the final setting, each row received up to four tokens of left context and up to four tokens of right context, drawn from earlier and later rows within the same tablet/document. The target remained only the English translation of the current row, so the surrounding text served only as additional source-side evidence. Thus, this was row-wise contextual training, not the chi-square chunking used later at inference time.</p>\n<pre><code>cdli_id:\nbce88917-e85f-02a8-609f-3f2d37c0d85d.tablet.4\n\ntransliteration:\nša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur\n\nmodel_input:\n[LOOKBACK_ONLY] šu-a-šur i-šu-ú 1 ṭup-pu-um [SOURCE] ša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur [LOOKAHEAD_ONLY] ba-lá-ṭí-šu-nu-ma a-na pu-šu-ke-en6 DUMU\n\ntarget:\nof 2 minas of silver which Buzazu owes to Belanum; these 4 tablets according to the proxy of Belanum, son of Šu-Aššur.\n</code></pre>\n<h2>2. Add an auxiliary full-sequence objective</h2>\n<p>The auxiliary examples were longer, style-cleaned translations derived from cleaned train-side material and Larsen-related texts. They were not row-wise context windows; instead, they exposed the model to longer document-scale source/target mappings.</p>\n<p>Implementation-wise, the main loss was computed on the row-wise contextual batches above, and during the same optimizer step I also sampled one auxiliary batch and added <code>0.3 * aux_loss</code> before the parameter update. For the final setting, the auxiliary loader used <code>batch_size=1</code>, <code>max_source_length=1536</code>, and <code>max_target_length=1536</code>. One overlength auxiliary example was filtered out before training, leaving <strong>1,358</strong> auxiliary examples in the final training set.</p>\n<p>The main training hyperparameters for the final <code>byt5-large</code> models were:</p>\n<ul>\n<li>model: <code>google/byt5-large</code></li>\n<li>epochs: <code>4</code></li>\n<li>batch size: <code>32</code></li>\n<li>learning rate: <code>2e-4</code></li>\n<li>weight decay: <code>0.01</code></li>\n<li>max source length: <code>448</code></li>\n<li>max target length: <code>448</code></li>\n<li>warmup steps: <code>465</code></li>\n<li>gradient clipping: <code>1.0</code></li>\n</ul>\n<p>I trained the same configuration with different random seeds (<code>42</code>, <code>60</code>, <code>28</code>, and <code>52</code>) and selected the best checkpoint from each run based on validation loss.</p>\n<h1>Inference</h1>\n<h2>1. Chunk test rows with local context</h2>\n<p>At inference time, I first normalized the source-side division-number notation, then split each test transliteration with the same chi-square chunker described above. I used <code>min_chunk=16</code> and <code>max_chunk=32</code>, so the model saw chunk-sized units rather than entire long test rows at once.</p>\n<p>For each chunk, I then constructed a context-augmented input in the same format used during training:</p>\n<pre><code>[LOOKBACK_ONLY] &lt;previous tokens&gt; [SOURCE] &lt;current chunk&gt; [LOOKAHEAD_ONLY] &lt;next tokens&gt;\n</code></pre>\n<p>In the final setting, I used <code>lookback_tokens=4</code> and <code>lookahead_tokens=4</code>. If this context was too short in characters, I allowed the neighboring window to expand slightly until it reached a small minimum textual mass. This kept the prediction target local to one chunk while still exposing nearby formulae, names, and discourse cues.</p>\n<h2>2. Candidate generation and MBR selection</h2>\n<p>I ensembled four <code>byt5-large</code> checkpoints at inference time: two runs trained on the final row-wise adapted corpus produced by the last data-adaptation pass, and two runs trained on the immediately preceding row-wise adapted version from one step earlier in that same pipeline. Their mixture weights were not uniform; the two checkpoints from the final adapted corpus contributed <code>0.2</code> each, and the two checkpoints from the preceding adapted corpus contributed <code>0.3</code> each. Generation used <code>max_source_length=448</code>, and the decoding budget for the target side was scaled adaptively between <code>192</code> and <code>448</code> new tokens depending on the encoded source length.</p>\n<p>For each chunk and each checkpoint, I generated a heterogeneous candidate pool:</p>\n<ul>\n<li><code>4</code> standard beam candidates</li>\n<li><code>4</code> diverse-beam candidates</li>\n<li><code>6</code> nucleus-sampling candidates (<code>2</code> samples each at temperatures <code>0.55</code>, <code>0.75</code>, and <code>0.95</code>)</li>\n</ul>\n<p>This yielded up to <code>56</code> raw candidates per chunk before deduplication across the four checkpoints.</p>\n<p>I then selected the final chunk translation with minimum Bayes risk decoding over the pooled candidate set. The MBR gain combined sentence-level chrF++, sentence BLEU, token-level Jaccard overlap, and a mild length bonus centered on the median candidate length. I weighted chrF++ most heavily (<code>6.0</code>), followed by BLEU (<code>2.0</code>), while Jaccard and the length bonus each received weight <code>1.0</code>. Within each checkpoint, the evidence mass was distributed uniformly across its candidates, and the total contribution of each checkpoint was then scaled by the mixture weights above. When several hypotheses remained close, ranking was further stabilized by support count and generation score.</p>\n<h2>3. Reconstruct rows and post-edit</h2>\n<p>After MBR selection, I concatenated the winning chunk translations in their original order to recover one English translation per test row. I then applied a small deterministic cleanup and post-editing pipeline: normalization of transliteration-style characters and quotation marks, removal of residual bracketed uncertainty markers, source-aware handling of <code>&lt;gap&gt;</code>, restoration of competition-specific number and glossary conventions, and two lightweight logistic-regression post-editors to nudge the output toward the training-set style.</p>\n<h1>Ablation Study</h1>\n<h2>Single Model vs Ensemble (MBR)</h2>\n<ul>\n<li>MBR ensembling yielded a modest improvement on the Private LB compared with the single-model runs, while no consistent improvement was observed on the Public LB.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large(seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.4389</td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 28)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>37.7196</td>\n<td>36.9437</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 42)</td>\n<td>The preceding adapted corpus</td>\n<td>chi-square</td>\n<td>38.1309</td>\n<td>37.6288</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 60)</td>\n<td>The preceding adapted corpus</td>\n<td>chi-square</td>\n<td>38.3819</td>\n<td>37.1679</td>\n</tr>\n<tr>\n<td>Ensemble (MBR)</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td><strong>38.5514</strong></td>\n<td>37.4818</td>\n</tr>\n</tbody>\n</table>\n<h2>Effect of glossary replacement(GR), post-processes(PP)</h2>\n<ul>\n<li>In the single-model setting, removing post-processing or glossary replacement led to lower Public LB scores, while the effect on the Private LB was small and less consistent. This suggests that both techniques were beneficial mainly for Public LB performance.</li>\n</ul>\n<h3>Single Model</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large(seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.4389</td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52) -PP</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.4362</td>\n<td>37.6650</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52) -PP-GR</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4443</strong></td>\n<td>37.6819</td>\n</tr>\n</tbody>\n</table>\n<h3>Ensemble</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Ensemble (MBR)</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td>38.5514</td>\n<td>37.4818</td>\n</tr>\n<tr>\n<td>Ensemble (MBR) -PP</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td>38.5614</td>\n<td><strong>37.4821</strong></td>\n</tr>\n<tr>\n<td>Ensemble (MBR) -PP-GR</td>\n<td>N/A</td>\n<td>chi-square</td>\n<td><strong>38.5686</strong></td>\n<td>37.3774</td>\n</tr>\n</tbody>\n</table>\n<h2>ByT5-Large vs. ByT5-Base</h2>\n<ul>\n<li>The benefit of ByT5-Large became clearer after style adaptation; on the pre-adaptation corpus, its performance was not consistently better than ByT5-Base, particularly on the public LB.</li>\n</ul>\n<h3>On the Final Adapted Corpus</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4389</strong></td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>38.0925</td>\n<td>37.0492</td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td>37.9296</td>\n<td>37.0533</td>\n</tr>\n</tbody>\n</table>\n<h3>On the Pre-adaptation Corpus</h3>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td><strong>37.5068</strong></td>\n<td>36.7824</td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td>37.0518</td>\n<td>36.5225</td>\n</tr>\n<tr>\n<td>Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td>37.1781</td>\n<td><strong>36.9766</strong></td>\n</tr>\n</tbody>\n</table>\n<h2>Effect of Data Adaptation</h2>\n<ul>\n<li>Data adaptation improved performance on both the Private and Public LBs, indicating that adapting the corpus was effective for this task.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Pre-adaptation corpus</td>\n<td>chi-square</td>\n<td>37.5068</td>\n<td>36.7824</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4389</strong></td>\n<td><strong>37.7799</strong></td>\n</tr>\n</tbody>\n</table>\n<h2>Effect of the chi-square chunker</h2>\n<ul>\n<li>The chi-square chunker outperformed both the [SOURCE]-only setting and fixed 16-token chunking on both leaderboards, suggesting that the chunking strategy was important for strong performance.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Corpus</th>\n<th>Chunker</th>\n<th>Private LB</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>chi-square</td>\n<td><strong>38.4389</strong></td>\n<td><strong>37.7799</strong></td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td><code>[SOURCE]</code> only (max_source_length/max_new_tokens 768 tokens)</td>\n<td>38.2861</td>\n<td>36.6346</td>\n</tr>\n<tr>\n<td>Single ByT5-Large (seed 52)</td>\n<td>Final adapted corpus</td>\n<td>fixed 16-token chunks</td>\n<td>38.0926</td>\n<td>36.9625</td>\n</tr>\n</tbody>\n</table>\n<h1>Appendix</h1>\n<h2>Early in this competition</h2>\n<ul>\n<li>I tried few-shot RAG + babylem-like lemmatizer approaches with Qwen3 Next or Kimi Linear, but I could not achieve a score above 22.x.</li>\n</ul>\n<h2>Tried But Did Not Work</h2>\n<ul>\n<li>Moses SMT<ul>\n<li>There were too many unknown terms, which exceeded the capacity of SMT systems</li></ul></li>\n<li>Source Contrastive Decoding (EACL 2024)<ul>\n<li><a href=\"https://arxiv.org/pdf/2309.07098\" target=\"_blank\">https://arxiv.org/pdf/2309.07098</a></li>\n<li>I used in-batch alternative sources instead of the paper’s random sampling scheme, so a more faithful implementation may still improve performance.</li></ul></li>\n<li>Auxiliary full-sequence training<ul>\n<li>Training ByT5-base/small on the auxiliary transliteration–translation pairs at their original sequence lengths was not particularly effective as a standalone setting, although the same data was still useful as an auxiliary objective. Longer sequences also tended to produce stronger repetition. I was not able to test whether ByT5-large would behave differently on these longer sequences, since I did not have sufficient computational resources to run it with a sufficiently large batch size.</li></ul></li>\n<li>Encoder-Only byt5<ul>\n<li>I extracted the encoder modules from the original ByT5 models and used them like BERT.</li></ul></li>\n</ul>\n<h2>Environment</h2>\n<h2>Local</h2>\n<ul>\n<li>CPU: Ryzen7 9800X3D (8 cores)</li>\n<li>GPU: RTX 5090 (VRAM 32GB)</li>\n<li>RAM: 192GB</li>\n</ul>\n<h2>vast.ai</h2>\n<ul>\n<li>For the final two days, local hardware alone was not enough to finish training in time, so I used an RTX 5090 instance on Vast.ai.</li>\n</ul>\n<hr>\n<p>Thanks again to the hosts for this competition. I learned a lot from this problem, especially about corpus construction and style alignment. I am also grateful to the community for sharing many interesting ideas throughout the competition.</p>",
      "rawMarkdown": "First, I would like to thank the Kaggle hosts for organizing this competition and for providing such an interesting problem.\n\n# Summary\n\nMy final solution was a contextual ByT5-large system with chunked ensemble inference, but the biggest gains came from data work rather than model changes.\n\n+ **Data**: built a larger published row-wise corpus from OARE/CDLI, added a smaller auxiliary full-sequence corpus, and filled missing translations with formula-aware Gemini prompting\n+ **Black-box Distillation**: used a stronger closed model to generate pseudo-labels, then trained a smaller open model on the resulting parallel data\n+ **Style adaptation**: repeatedly cleaned names, formulaic expressions, punctuation, and <gap> handling to better match the compact English style of train.csv\n+ **Training**: trained ByT5-large with a main row-wise contextual objective and a lighter auxiliary full-sequence objective\n+ **Inference**: chunked long test transliterations with a chi-square chunker, added local lookback/lookahead context, ensembled four checkpoints, reranked with MBR, and applied deterministic post-editing\n\nOverall, the system was built around three ideas: better corpus construction, stronger style adaptation, and more careful chunk-level inference.\n\n```\nApproximate contribution to the final score (from ablations)\n\nPrivate LB:\nData adaptation   [########################......] +0.93\nChunking          [#########.....................] +0.15 to +0.35\nByT5-Large        [#########.....................] +0.35\nEnsemble + MBR    [###...........................] +0.11\nPost-edit / GR    [..............................] ~0.00\n\nPublic LB:\nData adaptation   [##########################....] +1.00\nChunking          [##############################] +0.82 to +1.15\nByT5-Large        [###################...........] +0.73\nEnsemble + MBR    [..............................] no consistent gain\nPost-edit / GR    [###...........................] +0.10\n```\n\n# Datasets\n\nI prepared two corpora for training:\n\n- **published row-wise corpus:** 46,503 transliteration/translation pairs were prepared; 46,502 were retained in the final adapted corpus\n- **auxiliary full-sequence corpus:** 1,359 transliteration/translation pairs were prepared; 1,358 were used in training after filtering one overlength example\n\n## (Main Corpus) Published Corpus Construction\n\n### 1. Obtain raw data from source APIs\n\nI found several useful APIs.\n\n#### oare.byu.edu\n\n- UUID feeder:\n  `https://oare.byu.edu/api/v2/search?characters=&textTitle=AKT&page=1&rows=100&mode=respectAllBoundaries`\n\n- Tablet feeder:\n  `https://oare.byu.edu/api/v2/text_epigraphies/text/${uuid}?forceAllowAdminView=false`\n\n#### CDLI\n\nCDLI provides an easy way to download all Old Assyrian tablets:\n\n```bash\ncurl -L 'https://cdli.earth/search?period=old+ass&limit=10000&aspect=inscriptions&format=atf' -o old_assyrian.atf\n```\n\nAfter downloading the data from CDLI, I converted it into the OARE format.\n\n### 2. Merge\n\nI merged the two datasets above. After that, I grouped the rows of each tablet into 4–6 chunks; if fewer than two lines remained, I merged them into the previous chunk.\n\nAn example after merging:\n\n```json\n{\"text_id\": \"055b4918-e8aa-4442-99b6-cc4d6f33adf4\", \"designation\": \"AKT 1 30\", \"header_raw\": \"&055b4918-e8aa-4442-99b6-cc4d6f33adf4 = AKT 1 30\", \"atf\": {\"lang\": \"akk\"}, \"sections\": [\"tablet\", \"obverse\", \"reverse\"], \"lines\": [{\"label\": [\"1\", \"2\", \"3\", \"4\"], \"section\": \"obverse\", \"text\": \"4 i-lá-tim ku nu ki ša a-mur-IŠTAR ma-aḫ-ri-ni a-du-ú ù i-ku-pì-a\", \"translation\": null}, {\"label\": [\"5\", \"6\", \"7\", \"8\"], \"section\": \"obverse\", \"text\": \"iš ru mu ma i-na 3 i-lá-tim 3 GÚ 7+0.5 ma-na URUDU is ni qú\", \"translation\": null}, {\"label\": [\"9\", \"10\", \"11\", \"12\"], \"section\": \"reverse\", \"text\": \"a-ḫa-ma i-na 1 i-li-im 20+6 ma-na ta <gap> mu <gap> ù ša a-ba-ri-im\", \"translation\": null}, {\"label\": [\"13\", \"14\", \"15\"], \"section\": \"reverse\", \"text\": \"is ni qú ú IGI a-šur-iš-tí-kál IGI en-nam-a-a\", \"translation\": null}], \"annotations\": []}\n```\n\n### 3. Translate merged transliteration units with Gemini 3 Flash Preview\n\nI used Gemini 3 Flash Preview to fill in missing translations.\n\nPrompt example:\n\n```text\nUse the following reference notes while translating Old Assyrian transliteration lines:\n\n{reference_text}\n\nTask:\n- Translate each `text` into concise scholarly English.\n- Keep placeholders and damage markers such as `<gap>`, `[ ... ]`, `/` intact when possible.\n- Keep proper names transliterated.\n- Translate in the same sequence as the input items.\n- Return ONLY JSON with this exact schema:\n  {\n    \"translations\": [\n      {\"line_index\": 0, \"translation\": \"...\"}\n    ]\n  }\n- Include all line_index values exactly once.\n- Keep output order identical to input order.\n\nInput JSON:\n{payload_json}\n```\n\n`reference_text`:\n\n```text\n## Old Assyrian Formulaic Phrases (Patterns 1–12) — Prompt-ready English Descriptions\n\n> Placeholders: `{PN}` (personal name), `{Place}`, `{Amount}`, `{Goods}`, `{MonthName}`.\n\n### 1.1) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} from {SenderPN(s)}:”\n\n### 1.2) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} ù {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} and {RecipientPN} from {SenderPN(s)}:”\n\n### 2.1) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}(-ma) a-na {RecipientPN} qí-bi-ma`\n- **English meaning:** “From {SenderPN} to {RecipientPN}:”\n\n### 2.2) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}-ma a-na {RecipientPN} {RecipientPN} ú {RecipientPN} qí-bi₄-ma a-na {RecipientPN} qí-bi₄-ma`\n- **English meaning:** \"From {SenderPN} to {RecipientPN}, {RecipientPN} and {RecipientPN}; specifically to {RecipientPN}:\"\n\n### 3) Well-being / peace formula\n- **Transliteration template:** `a-na-kam šu-ul-mu-um i-ba-ší`\n- **English meaning:** “All is well here / Peace reigns here.”\n\n### 4) Seal notation (legal label)\n- **Transliteration template:** `KIŠIB {PN} DUMU {FatherPN}`\n- **English meaning:** “Seal of {PN}, son of {FatherPN}.”\n\n### 5) Witness list / “before (the eyes of)”\n- **Transliteration template:** `IGI {Witness1PN} … IGI {WitnessNPN}`\n- **English meaning:** “In the presence of {Witness...} / Witnessed by {Witness...}.”\n\n### 6) kārum (trade colony) procedural/legal clause\n- **Transliteration template:** `a-na a-wa-tim a-ni-a-tim kà-ru-um {Place} i-dí-ni-a-tí(-ma)`\n- **English meaning:** “Regarding these proceedings/matters, the kārum of {Place} granted/issued (to us) ...”\n\n### 7) Oath/testimony “before Aššur’s dagger”\n- **Transliteration template:** `IGI GÍR ša a-šùr ší-bu-tí-ni ni-dí-in`\n- **English meaning:** “We gave our testimony (swore) before Aššur’s dagger.”\n\n### 8) Debt obligation formula (“X owes Y”)\n- **Transliteration template:** `{Amount} KÙ.BABBAR i-ṣé-er {CreditorPN} ... {DebtorPN} i-šu-ú`\n- **English meaning:** “{DebtorPN} owes {Amount} of silver to {CreditorPN}.”\n\n### 9) Receipt / acknowledgement (“has received”)\n- **Transliteration template:** `{Goods/Amount} ... {ReceiverPN} il₅-qé`\n- **English meaning:** “{ReceiverPN} has received {Goods/Amount}.”\n\n### 10) Return/repayment clause\n- **Transliteration template:** `i-tù-ra-ma {Amount/Goods} ...`\n- **English meaning:** “And he returned (it) / and he repaid (...).”\n\n### 11) Dating clause: week + month + eponym (limmu)\n- **Transliteration template:** `iš-tù ḫa-mu-uš-tim ... ITU.KAM {MonthName} li-mu-um {EponymPN} DUMU {FatherPN}`\n- **English meaning:** “Reckoned from the week of ...; month {MonthName}; eponymy (limmu-year) of {EponymPN} son of {FatherPN}.”\n\n### 12) Interest rate clause (per mina per month)\n- **Transliteration template:** `a-na 1 ma-na-im {X} GÍN.TA i-na ITU.KAM ṣí-ib-tám ú-ṣú-bu`\n- **English meaning:** “They will add interest at {X} shekels per 1 mina per month.”\n```\n\n## (Main Corpus) Unmatched Published Corpus\n\n### 1. Match IDs\n\nI matched IDs between the main corpus and `published_texts.csv` and obtained unmatched transliteration records.\n\n### 2. Split sentences with a chi-square-based chunker\n\nBefore translating the unmatched published corpus, I split each long transliteration into shorter chunk-sized units with a chi-square-based chunker.\n\nMy working hypothesis was that physical row and edge breaks on tablets often behave like weak punctuation. They do not correspond perfectly to modern sentence boundaries, but they frequently coincide with discourse shifts such as a new legal formula, witness clause, dating clause, or procedural statement. I therefore used the already row-segmented training corpus as weak supervision for where a long unsegmented span might also be safely split.\n\nConcretely, for each adjacent token pair `X || Y`, I counted how often the pair stayed within one training row (`no_split`) and how often a row boundary fell between them (`split`). Pairs whose boundary rate was unusually high relative to the corpus-wide average received a positive boundary score; pairs that usually stayed together received a negative one. When chunking the target corpus, dynamic programming then searched for cuts that balanced these learned boundary preferences against a target length (`min_chunk=16`, `max_chunk=32`, `hard_max=47`).\n\nA concrete example is the recurrent legal phrase `a-na a-wa-tim a-ni-a-tim ...`. The pair `a-wa-tim || a-ni-a-tim` was learned as a relatively strong candidate boundary:\n\n| boundary candidate | split_count | no_split_count | pair_boundary_rate | global_boundary_rate | signed_sqrt_chi_square | chunk_boundary_score |\n| --- | ---: | ---: | ---: | ---: | ---: | ---: |\n| `a-wa-tim || a-ni-a-tim` | 33 | 226 | 0.1274 | 0.0410 | 7.0189 | 2.0424 |\n\nEven though this pair also occurred many times inside a row, its boundary rate was still about three times higher than the corpus-wide average. In other words, the chunker learned that a break here was substantially more plausible than for an average token transition, so when the surrounding length constraints also fit, it preferred that cut.\n\nExample:\n\n```text\nscope total length: 46 tokens\n\nchunk 1 (tokens 1-25):\nILLAT šu-nu-nu i-na za-al-pá ni-kà-sí i-sí-ú-ma 7 ma-na 3 GÍN KÙ.BABBAR ni-pí-il-tí <gap> a-šu-mì <gap> ša <gap> ku-<gap> ILLAT <gap> DUMU <gap> ú-ša-<gap> a-na a-wa-tim\n\nchunk 2 (tokens 26-46):\na-ni-a-tim kà-ru-um kà-ni-iš i-dí-ni-a-tí-ma IGI GÍR ša a-šur ṭup-pá-am ni-dí-in IGI dan-a-šur DUMU ša-lim-a-ḫi-im IGI pí-lá-aḫ-a-šur bi-lu-um IGI šu-IŠTAR DUMU da-da-nim\n\nchosen boundary:\na-wa-tim || a-ni-a-tim\nsigned_sqrt_chi_square = 7.01886377\nchunk_boundary_score = 2.04236877\n```\n\n### 3. Translate unmatched transliteration records with Gemini 3 Flash Preview\n\nI used Gemini 3 Flash Preview to translate the unmatched published transliteration records. The prompt here drifted slightly from the one used in the earlier stage, but not for any especially principled reason. In hindsight these two stages should have shared a single cleaned-up prompt template; instead, under time pressure, I ended up with duplicated prompt variants and lower-quality code than I would have liked.\n\nPrompt (`formulaic_phrase_section` is the same as the previously mentioned `Old Assyrian Formulaic Phrases (Patterns 1–12)` markdown):\n\n```python\nreturn (\n    \"# Task\\n\"\n    \"Translate the current Old Assyrian / Akkadian transliteration line into English.\\n\"\n    \"Use the surrounding lines only as context. Do not translate the previous or following lines.\\n\\n\"\n    \"## Output Format\\n\"\n    'Return JSON only in the form `{\"translation\": \"...\"}`.\\n\\n'\n    \"## Rules\\n\"\n    \"- No commentary, notes, markdown, or transliteration in the answer.\\n\"\n    \"- Preserve uncertainty and damage tersely when the source is fragmentary.\\n\"\n    \"- Keep names transliterated if they are uncertain.\\n\"\n    \"- Translate measures and numbers naturally when possible.\\n\"\n    \"- If the line is too fragmentary, still give the best partial English translation.\\n\\n\"\n    f\"{formulaic_phrase_section}\\n\\n\"\n    \"## Record\\n\"\n    f\"- **Text ID:** {text_id}\\n\"\n    f\"- **Designation:** {designation}\\n\\n\"\n    \"## Context From The Same Text\\n\"\n    \"### Previous Lines\\n\"\n    f\"{previous_context or '- none'}\\n\\n\"\n    \"### Current Line\\n\"\n    f\"- **Label:** {label_text}\\n\"\n    f\"  **Section:** {section}\\n\"\n    f\"  **Transliteration:** {transliteration}\\n\\n\"\n    \"### Following Lines\\n\"\n    f\"{following_context or '- none'}\\n\"\n)\n```\n\n## (Auxiliary Corpus) Refined `train.csv`\n\nI generated retranslated outputs with a model in the score-33.0 class, but used them only for length-based filtering: I excluded cases whose retranslated output length fell outside the +/-10% range. For the actual auxiliary data, I kept the transliteration and translation sentences from `train.csv`.\n\n## (Auxiliary Corpus) Larsen 2002\n\nI used [DPC - Larsen](https://www.kaggle.com/datasets/mpware/dpc-larsen) by MPWARE as an auxiliary corpus.\n\n# Data Adaptation\n\nThe raw Gemini translations were only a starting point. Relative to `train.csv`, they differed systematically in the following respects:\n\n- **[Names/Places]** personal-name and place-name spellings often oscillated between anglicized, normalized, and more scholarly transliterated forms\n- **[Formulae]** recurrent Old Assyrian formulae were translated with inconsistent wording and register\n- **[OA terms]** some Old Assyrian-specific concepts and terms were difficult to render consistently in compact, dataset-style English\n- **[Punctuation]** punctuation conventions, especially the use of commas, colons, and semicolons in lists, clauses, and reported speech, did not match the training-side house style\n- **[Gap handling]** `<gap>` and other damage markers were often handled inconsistently, either left as spurious English fragments or removed too aggressively\n\nI therefore treated data adaptation as an iterative patch-and-audit pipeline over two corpora: the published row-wise corpus and the longer auxiliary corpus.\n\n## What Worked\n\n### [Formulae]\n\nI kept the normalization of recurrent seal headings, witness clauses, debt clauses, payment clauses, and kinship formulas so that the English matched the compact, formulaic style of `train.csv`.\n\nExample:\n\n```text\n10 shekels of refined silver are with Ikupi-Aššur son of Puzur-Ištar.\n-> 10 shekels of refined silver are owed by Ikupi-Aššur son of Puzur-Ištar.\n\nthey shall pay within one month.\n-> they will pay within one month.\n\nfine copper -> good copper\n\nIf he does not pay -> If he has not paid\n```\n\n### [OA terms]\n\nFor distinctive Old Assyrian terms, I generally did not rewrite the corpus text itself. Instead, I registered preferred equivalents in a glossary and applied them later in post-processing. My reasoning was that keeping these marked terms unchanged during translation reduced the risk of introducing odd lexical variation, while their distinctiveness also made them easy to replace deterministically afterward.\n\nExample:\n\n```text\nkārum -> colony\n\nmonth Bēltī-ekallim -> month 1\n```\n\n### [Punctuation]\n\nI kept the punctuation alignment that split clause-like semicolon chains into sentence-like units, as well as the later conservative speech-framing cleanup used in the final branch.\n\nExample:\n\n```text\nAššur-rē'ī owes it; from the week of Akūtum\n-> Aššur-rē'ī owes it. From the week of Akūtum\n```\n\n### [Gap handling]\n\nI removed `<gap>` from the translation when the transliteration had no corresponding `<gap>`. When the transliteration contained fewer `<gap>` markers than the translation, I also removed a final translation-side `<gap>` when it was attached to an adjacent alphanumeric character.\n\nExample:\n\n```text\n<gap>seize (him) and the silver and its interest<gap>\n-> seize (him) and the silver and its interest\n\nWith his deposits<gap>\n-> With his deposits\n```\n\n## What Did Not Work Reliably\n\n### [Names/Places]\n\nI first tried broader normalization of personal and place names, including (1) simple replacements based on occurrence counts in the `train.csv` and (2) preferences for more scholarly spellings in the `onomasticon.csv`, especially long-vowel forms. In practice, however, I could not find a consistently effective methodology. I therefore retained only a small set of changes that seemed to improve the LB, added them to a glossary, and used that glossary in post-processing, even if the changes did not appear to follow a fully consistent principle.\n\nExample:\n\n```text\nAbua -> Abuwa\nAdudua -> Aduduwa\nAgua -> Aguwa\nAkua -> Akuwa\nSamāya -> Samaya\n```\n\n## 🎯 Lottery\n\n### [Names/Places]\n\nAs a lottery-ticket heuristic, I compared `train.csv` with `published_texts.csv`, manually inspected the top 100 cases whose frequency in `train.csv` looked implausibly low, and added selected entries to a normalization dictionary. The top five personal-name examples were as follows:\n\n```text\ni-ku-pì-a -> Ikupia\ni-dí-a-šur -> Idi-Aššur\nšál-ma-a-šur -> Šalma-Aššur\ni-dí-sú-en -> Idi-Suen\nšu-be-lim -> Šu-Belim\n```\n\n### [Punctuation]\n\nAs another lottery-ticket heuristic, I replaced `Thus you (said):`, `Thus (said) PN:`, and related `Thus`-based expressions outside letter openings. The score began to drop partway through this line of experimentation, but I still kept this direction because the translation style of `train.csv` used `Thus` far less often.\n\nExample:\n\n```text\nThus you (said):\n-> You said:\n\nThus (said) Ennam-Suen:\n-> Ennam-Suen said:\n```\n\nIn other words, after the manual auxiliary cleanup stage, the auxiliary corpus was stable, and the remaining adaptation work focused on bringing the published row-wise corpus closer to the auxiliary / `train.csv` punctuation and discourse style.\n\n# Training\n\nFor the final `byt5-large` runs, I optimized two data streams in parallel: a main row-wise objective on the adapted published corpus (**46,502** transliteration/translation pairs) and a secondary full-sequence objective on a smaller auxiliary corpus (**1,358** examples used in training). The main corpus taught row-level alignment in the competition format, while the auxiliary corpus helped preserve longer-range fluency and formulaic phrasing.\n\nFor offline model selection, I used the script's default random approximate 80/10/10 split on the final 46,502-example main row-wise corpus, which produced **37,202** training rows, **4,650** validation rows, and **4,650** test rows in the seed-42 run.\n\n## 1. Create lookback, source, and lookahead sequences for the main objective\n\nBefore training, each row in the main corpus was converted into a context-augmented input of the form:\n\n```text\n[LOOKBACK_ONLY] <previous tokens> [SOURCE] <current row> [LOOKAHEAD_ONLY] <next tokens>\n```\n\nIn the final setting, each row received up to four tokens of left context and up to four tokens of right context, drawn from earlier and later rows within the same tablet/document. The target remained only the English translation of the current row, so the surrounding text served only as additional source-side evidence. Thus, this was row-wise contextual training, not the chi-square chunking used later at inference time.\n\n```text\ncdli_id:\nbce88917-e85f-02a8-609f-3f2d37c0d85d.tablet.4\n\ntransliteration:\nša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur\n\nmodel_input:\n[LOOKBACK_ONLY] šu-a-šur i-šu-ú 1 ṭup-pu-um [SOURCE] ša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur [LOOKAHEAD_ONLY] ba-lá-ṭí-šu-nu-ma a-na pu-šu-ke-en6 DUMU\n\ntarget:\nof 2 minas of silver which Buzazu owes to Belanum; these 4 tablets according to the proxy of Belanum, son of Šu-Aššur.\n```\n\n## 2. Add an auxiliary full-sequence objective\n\nThe auxiliary examples were longer, style-cleaned translations derived from cleaned train-side material and Larsen-related texts. They were not row-wise context windows; instead, they exposed the model to longer document-scale source/target mappings.\n\nImplementation-wise, the main loss was computed on the row-wise contextual batches above, and during the same optimizer step I also sampled one auxiliary batch and added `0.3 * aux_loss` before the parameter update. For the final setting, the auxiliary loader used `batch_size=1`, `max_source_length=1536`, and `max_target_length=1536`. One overlength auxiliary example was filtered out before training, leaving **1,358** auxiliary examples in the final training set.\n\nThe main training hyperparameters for the final `byt5-large` models were:\n\n- model: `google/byt5-large`\n- epochs: `4`\n- batch size: `32`\n- learning rate: `2e-4`\n- weight decay: `0.01`\n- max source length: `448`\n- max target length: `448`\n- warmup steps: `465`\n- gradient clipping: `1.0`\n\nI trained the same configuration with different random seeds (`42`, `60`, `28`, and `52`) and selected the best checkpoint from each run based on validation loss.\n\n# Inference\n\n## 1. Chunk test rows with local context\n\nAt inference time, I first normalized the source-side division-number notation, then split each test transliteration with the same chi-square chunker described above. I used `min_chunk=16` and `max_chunk=32`, so the model saw chunk-sized units rather than entire long test rows at once.\n\nFor each chunk, I then constructed a context-augmented input in the same format used during training:\n\n```text\n[LOOKBACK_ONLY] <previous tokens> [SOURCE] <current chunk> [LOOKAHEAD_ONLY] <next tokens>\n```\n\nIn the final setting, I used `lookback_tokens=4` and `lookahead_tokens=4`. If this context was too short in characters, I allowed the neighboring window to expand slightly until it reached a small minimum textual mass. This kept the prediction target local to one chunk while still exposing nearby formulae, names, and discourse cues.\n\n## 2. Candidate generation and MBR selection\n\nI ensembled four `byt5-large` checkpoints at inference time: two runs trained on the final row-wise adapted corpus produced by the last data-adaptation pass, and two runs trained on the immediately preceding row-wise adapted version from one step earlier in that same pipeline. Their mixture weights were not uniform; the two checkpoints from the final adapted corpus contributed `0.2` each, and the two checkpoints from the preceding adapted corpus contributed `0.3` each. Generation used `max_source_length=448`, and the decoding budget for the target side was scaled adaptively between `192` and `448` new tokens depending on the encoded source length.\n\nFor each chunk and each checkpoint, I generated a heterogeneous candidate pool:\n\n- `4` standard beam candidates\n- `4` diverse-beam candidates\n- `6` nucleus-sampling candidates (`2` samples each at temperatures `0.55`, `0.75`, and `0.95`)\n\nThis yielded up to `56` raw candidates per chunk before deduplication across the four checkpoints.\n\nI then selected the final chunk translation with minimum Bayes risk decoding over the pooled candidate set. The MBR gain combined sentence-level chrF++, sentence BLEU, token-level Jaccard overlap, and a mild length bonus centered on the median candidate length. I weighted chrF++ most heavily (`6.0`), followed by BLEU (`2.0`), while Jaccard and the length bonus each received weight `1.0`. Within each checkpoint, the evidence mass was distributed uniformly across its candidates, and the total contribution of each checkpoint was then scaled by the mixture weights above. When several hypotheses remained close, ranking was further stabilized by support count and generation score.\n\n## 3. Reconstruct rows and post-edit\n\nAfter MBR selection, I concatenated the winning chunk translations in their original order to recover one English translation per test row. I then applied a small deterministic cleanup and post-editing pipeline: normalization of transliteration-style characters and quotation marks, removal of residual bracketed uncertainty markers, source-aware handling of `<gap>`, restoration of competition-specific number and glossary conventions, and two lightweight logistic-regression post-editors to nudge the output toward the training-set style.\n\n# Ablation Study\n\n## Single Model vs Ensemble (MBR)\n\n+ MBR ensembling yielded a modest improvement on the Private LB compared with the single-model runs, while no consistent improvement was observed on the Public LB.\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large(seed 52) | Final adapted corpus | chi-square | 38.4389 | **37.7799** |\n| Single ByT5-Large (seed 28) | Final adapted corpus  | chi-square | 37.7196 | 36.9437 |\n| Single ByT5-Large (seed 42) | The preceding adapted corpus  | chi-square | 38.1309 | 37.6288 |\n| Single ByT5-Large (seed 60) | The preceding adapted corpus  | chi-square | 38.3819 | 37.1679 |\n| Ensemble (MBR) | N/A | chi-square | **38.5514** | 37.4818 |\n\n## Effect of glossary replacement(GR), post-processes(PP)\n\n+ In the single-model setting, removing post-processing or glossary replacement led to lower Public LB scores, while the effect on the Private LB was small and less consistent. This suggests that both techniques were beneficial mainly for Public LB performance.\n\n### Single Model\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large(seed 52) | Final adapted corpus | chi-square | 38.4389 | **37.7799** |\n| Single ByT5-Large (seed 52) -PP | Final adapted corpus | chi-square | 38.4362 | 37.6650 |\n| Single ByT5-Large (seed 52) -PP-GR | Final adapted corpus | chi-square | **38.4443** | 37.6819|\n\n### Ensemble\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Ensemble (MBR) | N/A | chi-square | 38.5514 | 37.4818 |\n| Ensemble (MBR) -PP | N/A | chi-square | 38.5614 | **37.4821** |\n| Ensemble (MBR) -PP-GR | N/A | chi-square | **38.5686** | 37.3774|\n\n## ByT5-Large vs. ByT5-Base \n\n+ The benefit of ByT5-Large became clearer after style adaptation; on the pre-adaptation corpus, its performance was not consistently better than ByT5-Base, particularly on the public LB.\n\n### On the Final Adapted Corpus\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Final adapted corpus | chi-square | **38.4389** | **37.7799** |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4) | Final adapted corpus | chi-square | 38.0925 | 37.0492 |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4) | Final adapted corpus | chi-square | 37.9296 | 37.0533 |\n\n### On the Pre-adaptation Corpus\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Pre-adaptation corpus | chi-square | **37.5068** | 36.7824 |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4) | Pre-adaptation corpus | chi-square | 37.0518 | 36.5225 |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4) | Pre-adaptation corpus | chi-square | 37.1781 | **36.9766** |\n\n## Effect of Data Adaptation\n\n+ Data adaptation improved performance on both the Private and Public LBs, indicating that adapting the corpus was effective for this task.\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Pre-adaptation corpus | chi-square | 37.5068 | 36.7824 |\n| Single ByT5-Large (seed 52) | Final adapted corpus | chi-square | **38.4389** | **37.7799** |\n\n## Effect of the chi-square chunker\n\n+ The chi-square chunker outperformed both the [SOURCE]-only setting and fixed 16-token chunking on both leaderboards, suggesting that the chunking strategy was important for strong performance.\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Final adapted corpus | chi-square | **38.4389** | **37.7799** |\n| Single ByT5-Large (seed 52) | Final adapted corpus | `[SOURCE]` only (max_source_length/max_new_tokens 768 tokens) | 38.2861 | 36.6346 |\n| Single ByT5-Large (seed 52) | Final adapted corpus | fixed 16-token chunks | 38.0926 | 36.9625 |\n\n# Appendix\n\n## Early in this competition\n\n- I tried few-shot RAG + babylem-like lemmatizer approaches with Qwen3 Next or Kimi Linear, but I could not achieve a score above 22.x.\n\n## Tried But Did Not Work\n\n- Moses SMT\n  - There were too many unknown terms, which exceeded the capacity of SMT systems\n- Source Contrastive Decoding (EACL 2024)\n  - https://arxiv.org/pdf/2309.07098\n  - I used in-batch alternative sources instead of the paper’s random sampling scheme, so a more faithful implementation may still improve performance.\n- Auxiliary full-sequence training\n  - Training ByT5-base/small on the auxiliary transliteration–translation pairs at their original sequence lengths was not particularly effective as a standalone setting, although the same data was still useful as an auxiliary objective. Longer sequences also tended to produce stronger repetition. I was not able to test whether ByT5-large would behave differently on these longer sequences, since I did not have sufficient computational resources to run it with a sufficiently large batch size.\n- Encoder-Only byt5\n  - I extracted the encoder modules from the original ByT5 models and used them like BERT.\n\n## Environment\n\n## Local\n\n+ CPU: Ryzen7 9800X3D (8 cores)\n+ GPU: RTX 5090 (VRAM 32GB)\n+ RAM: 192GB\n\n## vast.ai\n\n+ For the final two days, local hardware alone was not enough to finish training in time, so I used an RTX 5090 instance on Vast.ai.\n\n----\n\nThanks again to the hosts for this competition. I learned a lot from this problem, especially about corpus construction and style alignment. I am also grateful to the community for sharing many interesting ideas throughout the competition.\n",
      "votes": 2
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "3427861": "First, I would like to thank the Kaggle hosts for organizing this competition and for providing such an interesting problem.\n\n# Summary\n\nMy final solution was a contextual ByT5-large system with chunked ensemble inference, but the biggest gains came from data work rather than model changes.\n\n+ **Data**: built a larger published row-wise corpus from OARE/CDLI, added a smaller auxiliary full-sequence corpus, and filled missing translations with formula-aware Gemini prompting\n+ **Black-box Distillation**: used a stronger closed model to generate pseudo-labels, then trained a smaller open model on the resulting parallel data\n+ **Style adaptation**: repeatedly cleaned names, formulaic expressions, punctuation, and <gap> handling to better match the compact English style of train.csv\n+ **Training**: trained ByT5-large with a main row-wise contextual objective and a lighter auxiliary full-sequence objective\n+ **Inference**: chunked long test transliterations with a chi-square chunker, added local lookback/lookahead context, ensembled four checkpoints, reranked with MBR, and applied deterministic post-editing\n\nOverall, the system was built around three ideas: better corpus construction, stronger style adaptation, and more careful chunk-level inference.\n\n```\nApproximate contribution to the final score (from ablations)\n\nPrivate LB:\nData adaptation   [########################......] +0.93\nChunking          [#########.....................] +0.15 to +0.35\nByT5-Large        [#########.....................] +0.35\nEnsemble + MBR    [###...........................] +0.11\nPost-edit / GR    [..............................] ~0.00\n\nPublic LB:\nData adaptation   [##########################....] +1.00\nChunking          [##############################] +0.82 to +1.15\nByT5-Large        [###################...........] +0.73\nEnsemble + MBR    [..............................] no consistent gain\nPost-edit / GR    [###...........................] +0.10\n```\n\n# Datasets\n\nI prepared two corpora for training:\n\n- **published row-wise corpus:** 46,503 transliteration/translation pairs were prepared; 46,502 were retained in the final adapted corpus\n- **auxiliary full-sequence corpus:** 1,359 transliteration/translation pairs were prepared; 1,358 were used in training after filtering one overlength example\n\n## (Main Corpus) Published Corpus Construction\n\n### 1. Obtain raw data from source APIs\n\nI found several useful APIs.\n\n#### oare.byu.edu\n\n- UUID feeder:\n  `https://oare.byu.edu/api/v2/search?characters=&textTitle=AKT&page=1&rows=100&mode=respectAllBoundaries`\n\n- Tablet feeder:\n  `https://oare.byu.edu/api/v2/text_epigraphies/text/${uuid}?forceAllowAdminView=false`\n\n#### CDLI\n\nCDLI provides an easy way to download all Old Assyrian tablets:\n\n```bash\ncurl -L 'https://cdli.earth/search?period=old+ass&limit=10000&aspect=inscriptions&format=atf' -o old_assyrian.atf\n```\n\nAfter downloading the data from CDLI, I converted it into the OARE format.\n\n### 2. Merge\n\nI merged the two datasets above. After that, I grouped the rows of each tablet into 4–6 chunks; if fewer than two lines remained, I merged them into the previous chunk.\n\nAn example after merging:\n\n```json\n{\"text_id\": \"055b4918-e8aa-4442-99b6-cc4d6f33adf4\", \"designation\": \"AKT 1 30\", \"header_raw\": \"&055b4918-e8aa-4442-99b6-cc4d6f33adf4 = AKT 1 30\", \"atf\": {\"lang\": \"akk\"}, \"sections\": [\"tablet\", \"obverse\", \"reverse\"], \"lines\": [{\"label\": [\"1\", \"2\", \"3\", \"4\"], \"section\": \"obverse\", \"text\": \"4 i-lá-tim ku nu ki ša a-mur-IŠTAR ma-aḫ-ri-ni a-du-ú ù i-ku-pì-a\", \"translation\": null}, {\"label\": [\"5\", \"6\", \"7\", \"8\"], \"section\": \"obverse\", \"text\": \"iš ru mu ma i-na 3 i-lá-tim 3 GÚ 7+0.5 ma-na URUDU is ni qú\", \"translation\": null}, {\"label\": [\"9\", \"10\", \"11\", \"12\"], \"section\": \"reverse\", \"text\": \"a-ḫa-ma i-na 1 i-li-im 20+6 ma-na ta <gap> mu <gap> ù ša a-ba-ri-im\", \"translation\": null}, {\"label\": [\"13\", \"14\", \"15\"], \"section\": \"reverse\", \"text\": \"is ni qú ú IGI a-šur-iš-tí-kál IGI en-nam-a-a\", \"translation\": null}], \"annotations\": []}\n```\n\n### 3. Translate merged transliteration units with Gemini 3 Flash Preview\n\nI used Gemini 3 Flash Preview to fill in missing translations.\n\nPrompt example:\n\n```text\nUse the following reference notes while translating Old Assyrian transliteration lines:\n\n{reference_text}\n\nTask:\n- Translate each `text` into concise scholarly English.\n- Keep placeholders and damage markers such as `<gap>`, `[ ... ]`, `/` intact when possible.\n- Keep proper names transliterated.\n- Translate in the same sequence as the input items.\n- Return ONLY JSON with this exact schema:\n  {\n    \"translations\": [\n      {\"line_index\": 0, \"translation\": \"...\"}\n    ]\n  }\n- Include all line_index values exactly once.\n- Keep output order identical to input order.\n\nInput JSON:\n{payload_json}\n```\n\n`reference_text`:\n\n```text\n## Old Assyrian Formulaic Phrases (Patterns 1–12) — Prompt-ready English Descriptions\n\n> Placeholders: `{PN}` (personal name), `{Place}`, `{Amount}`, `{Goods}`, `{MonthName}`.\n\n### 1.1) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} from {SenderPN(s)}:”\n\n### 1.2) Recipient-first address (letter opening)\n- **Transliteration template:** `a-na {RecipientPN} ù {RecipientPN} qí-bi-ma um-ma {SenderPN(s)}(-ma)`\n- **English meaning:** “To {RecipientPN} and {RecipientPN} from {SenderPN(s)}:”\n\n### 2.1) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}(-ma) a-na {RecipientPN} qí-bi-ma`\n- **English meaning:** “From {SenderPN} to {RecipientPN}:”\n\n### 2.2) Sender-first address (variant letter opening)\n- **Transliteration template:** `um-ma {SenderPN}-ma a-na {RecipientPN} {RecipientPN} ú {RecipientPN} qí-bi₄-ma a-na {RecipientPN} qí-bi₄-ma`\n- **English meaning:** \"From {SenderPN} to {RecipientPN}, {RecipientPN} and {RecipientPN}; specifically to {RecipientPN}:\"\n\n### 3) Well-being / peace formula\n- **Transliteration template:** `a-na-kam šu-ul-mu-um i-ba-ší`\n- **English meaning:** “All is well here / Peace reigns here.”\n\n### 4) Seal notation (legal label)\n- **Transliteration template:** `KIŠIB {PN} DUMU {FatherPN}`\n- **English meaning:** “Seal of {PN}, son of {FatherPN}.”\n\n### 5) Witness list / “before (the eyes of)”\n- **Transliteration template:** `IGI {Witness1PN} … IGI {WitnessNPN}`\n- **English meaning:** “In the presence of {Witness...} / Witnessed by {Witness...}.”\n\n### 6) kārum (trade colony) procedural/legal clause\n- **Transliteration template:** `a-na a-wa-tim a-ni-a-tim kà-ru-um {Place} i-dí-ni-a-tí(-ma)`\n- **English meaning:** “Regarding these proceedings/matters, the kārum of {Place} granted/issued (to us) ...”\n\n### 7) Oath/testimony “before Aššur’s dagger”\n- **Transliteration template:** `IGI GÍR ša a-šùr ší-bu-tí-ni ni-dí-in`\n- **English meaning:** “We gave our testimony (swore) before Aššur’s dagger.”\n\n### 8) Debt obligation formula (“X owes Y”)\n- **Transliteration template:** `{Amount} KÙ.BABBAR i-ṣé-er {CreditorPN} ... {DebtorPN} i-šu-ú`\n- **English meaning:** “{DebtorPN} owes {Amount} of silver to {CreditorPN}.”\n\n### 9) Receipt / acknowledgement (“has received”)\n- **Transliteration template:** `{Goods/Amount} ... {ReceiverPN} il₅-qé`\n- **English meaning:** “{ReceiverPN} has received {Goods/Amount}.”\n\n### 10) Return/repayment clause\n- **Transliteration template:** `i-tù-ra-ma {Amount/Goods} ...`\n- **English meaning:** “And he returned (it) / and he repaid (...).”\n\n### 11) Dating clause: week + month + eponym (limmu)\n- **Transliteration template:** `iš-tù ḫa-mu-uš-tim ... ITU.KAM {MonthName} li-mu-um {EponymPN} DUMU {FatherPN}`\n- **English meaning:** “Reckoned from the week of ...; month {MonthName}; eponymy (limmu-year) of {EponymPN} son of {FatherPN}.”\n\n### 12) Interest rate clause (per mina per month)\n- **Transliteration template:** `a-na 1 ma-na-im {X} GÍN.TA i-na ITU.KAM ṣí-ib-tám ú-ṣú-bu`\n- **English meaning:** “They will add interest at {X} shekels per 1 mina per month.”\n```\n\n## (Main Corpus) Unmatched Published Corpus\n\n### 1. Match IDs\n\nI matched IDs between the main corpus and `published_texts.csv` and obtained unmatched transliteration records.\n\n### 2. Split sentences with a chi-square-based chunker\n\nBefore translating the unmatched published corpus, I split each long transliteration into shorter chunk-sized units with a chi-square-based chunker.\n\nMy working hypothesis was that physical row and edge breaks on tablets often behave like weak punctuation. They do not correspond perfectly to modern sentence boundaries, but they frequently coincide with discourse shifts such as a new legal formula, witness clause, dating clause, or procedural statement. I therefore used the already row-segmented training corpus as weak supervision for where a long unsegmented span might also be safely split.\n\nConcretely, for each adjacent token pair `X || Y`, I counted how often the pair stayed within one training row (`no_split`) and how often a row boundary fell between them (`split`). Pairs whose boundary rate was unusually high relative to the corpus-wide average received a positive boundary score; pairs that usually stayed together received a negative one. When chunking the target corpus, dynamic programming then searched for cuts that balanced these learned boundary preferences against a target length (`min_chunk=16`, `max_chunk=32`, `hard_max=47`).\n\nA concrete example is the recurrent legal phrase `a-na a-wa-tim a-ni-a-tim ...`. The pair `a-wa-tim || a-ni-a-tim` was learned as a relatively strong candidate boundary:\n\n| boundary candidate | split_count | no_split_count | pair_boundary_rate | global_boundary_rate | signed_sqrt_chi_square | chunk_boundary_score |\n| --- | ---: | ---: | ---: | ---: | ---: | ---: |\n| `a-wa-tim || a-ni-a-tim` | 33 | 226 | 0.1274 | 0.0410 | 7.0189 | 2.0424 |\n\nEven though this pair also occurred many times inside a row, its boundary rate was still about three times higher than the corpus-wide average. In other words, the chunker learned that a break here was substantially more plausible than for an average token transition, so when the surrounding length constraints also fit, it preferred that cut.\n\nExample:\n\n```text\nscope total length: 46 tokens\n\nchunk 1 (tokens 1-25):\nILLAT šu-nu-nu i-na za-al-pá ni-kà-sí i-sí-ú-ma 7 ma-na 3 GÍN KÙ.BABBAR ni-pí-il-tí <gap> a-šu-mì <gap> ša <gap> ku-<gap> ILLAT <gap> DUMU <gap> ú-ša-<gap> a-na a-wa-tim\n\nchunk 2 (tokens 26-46):\na-ni-a-tim kà-ru-um kà-ni-iš i-dí-ni-a-tí-ma IGI GÍR ša a-šur ṭup-pá-am ni-dí-in IGI dan-a-šur DUMU ša-lim-a-ḫi-im IGI pí-lá-aḫ-a-šur bi-lu-um IGI šu-IŠTAR DUMU da-da-nim\n\nchosen boundary:\na-wa-tim || a-ni-a-tim\nsigned_sqrt_chi_square = 7.01886377\nchunk_boundary_score = 2.04236877\n```\n\n### 3. Translate unmatched transliteration records with Gemini 3 Flash Preview\n\nI used Gemini 3 Flash Preview to translate the unmatched published transliteration records. The prompt here drifted slightly from the one used in the earlier stage, but not for any especially principled reason. In hindsight these two stages should have shared a single cleaned-up prompt template; instead, under time pressure, I ended up with duplicated prompt variants and lower-quality code than I would have liked.\n\nPrompt (`formulaic_phrase_section` is the same as the previously mentioned `Old Assyrian Formulaic Phrases (Patterns 1–12)` markdown):\n\n```python\nreturn (\n    \"# Task\\n\"\n    \"Translate the current Old Assyrian / Akkadian transliteration line into English.\\n\"\n    \"Use the surrounding lines only as context. Do not translate the previous or following lines.\\n\\n\"\n    \"## Output Format\\n\"\n    'Return JSON only in the form `{\"translation\": \"...\"}`.\\n\\n'\n    \"## Rules\\n\"\n    \"- No commentary, notes, markdown, or transliteration in the answer.\\n\"\n    \"- Preserve uncertainty and damage tersely when the source is fragmentary.\\n\"\n    \"- Keep names transliterated if they are uncertain.\\n\"\n    \"- Translate measures and numbers naturally when possible.\\n\"\n    \"- If the line is too fragmentary, still give the best partial English translation.\\n\\n\"\n    f\"{formulaic_phrase_section}\\n\\n\"\n    \"## Record\\n\"\n    f\"- **Text ID:** {text_id}\\n\"\n    f\"- **Designation:** {designation}\\n\\n\"\n    \"## Context From The Same Text\\n\"\n    \"### Previous Lines\\n\"\n    f\"{previous_context or '- none'}\\n\\n\"\n    \"### Current Line\\n\"\n    f\"- **Label:** {label_text}\\n\"\n    f\"  **Section:** {section}\\n\"\n    f\"  **Transliteration:** {transliteration}\\n\\n\"\n    \"### Following Lines\\n\"\n    f\"{following_context or '- none'}\\n\"\n)\n```\n\n## (Auxiliary Corpus) Refined `train.csv`\n\nI generated retranslated outputs with a model in the score-33.0 class, but used them only for length-based filtering: I excluded cases whose retranslated output length fell outside the +/-10% range. For the actual auxiliary data, I kept the transliteration and translation sentences from `train.csv`.\n\n## (Auxiliary Corpus) Larsen 2002\n\nI used [DPC - Larsen](https://www.kaggle.com/datasets/mpware/dpc-larsen) by MPWARE as an auxiliary corpus.\n\n# Data Adaptation\n\nThe raw Gemini translations were only a starting point. Relative to `train.csv`, they differed systematically in the following respects:\n\n- **[Names/Places]** personal-name and place-name spellings often oscillated between anglicized, normalized, and more scholarly transliterated forms\n- **[Formulae]** recurrent Old Assyrian formulae were translated with inconsistent wording and register\n- **[OA terms]** some Old Assyrian-specific concepts and terms were difficult to render consistently in compact, dataset-style English\n- **[Punctuation]** punctuation conventions, especially the use of commas, colons, and semicolons in lists, clauses, and reported speech, did not match the training-side house style\n- **[Gap handling]** `<gap>` and other damage markers were often handled inconsistently, either left as spurious English fragments or removed too aggressively\n\nI therefore treated data adaptation as an iterative patch-and-audit pipeline over two corpora: the published row-wise corpus and the longer auxiliary corpus.\n\n## What Worked\n\n### [Formulae]\n\nI kept the normalization of recurrent seal headings, witness clauses, debt clauses, payment clauses, and kinship formulas so that the English matched the compact, formulaic style of `train.csv`.\n\nExample:\n\n```text\n10 shekels of refined silver are with Ikupi-Aššur son of Puzur-Ištar.\n-> 10 shekels of refined silver are owed by Ikupi-Aššur son of Puzur-Ištar.\n\nthey shall pay within one month.\n-> they will pay within one month.\n\nfine copper -> good copper\n\nIf he does not pay -> If he has not paid\n```\n\n### [OA terms]\n\nFor distinctive Old Assyrian terms, I generally did not rewrite the corpus text itself. Instead, I registered preferred equivalents in a glossary and applied them later in post-processing. My reasoning was that keeping these marked terms unchanged during translation reduced the risk of introducing odd lexical variation, while their distinctiveness also made them easy to replace deterministically afterward.\n\nExample:\n\n```text\nkārum -> colony\n\nmonth Bēltī-ekallim -> month 1\n```\n\n### [Punctuation]\n\nI kept the punctuation alignment that split clause-like semicolon chains into sentence-like units, as well as the later conservative speech-framing cleanup used in the final branch.\n\nExample:\n\n```text\nAššur-rē'ī owes it; from the week of Akūtum\n-> Aššur-rē'ī owes it. From the week of Akūtum\n```\n\n### [Gap handling]\n\nI removed `<gap>` from the translation when the transliteration had no corresponding `<gap>`. When the transliteration contained fewer `<gap>` markers than the translation, I also removed a final translation-side `<gap>` when it was attached to an adjacent alphanumeric character.\n\nExample:\n\n```text\n<gap>seize (him) and the silver and its interest<gap>\n-> seize (him) and the silver and its interest\n\nWith his deposits<gap>\n-> With his deposits\n```\n\n## What Did Not Work Reliably\n\n### [Names/Places]\n\nI first tried broader normalization of personal and place names, including (1) simple replacements based on occurrence counts in the `train.csv` and (2) preferences for more scholarly spellings in the `onomasticon.csv`, especially long-vowel forms. In practice, however, I could not find a consistently effective methodology. I therefore retained only a small set of changes that seemed to improve the LB, added them to a glossary, and used that glossary in post-processing, even if the changes did not appear to follow a fully consistent principle.\n\nExample:\n\n```text\nAbua -> Abuwa\nAdudua -> Aduduwa\nAgua -> Aguwa\nAkua -> Akuwa\nSamāya -> Samaya\n```\n\n## 🎯 Lottery\n\n### [Names/Places]\n\nAs a lottery-ticket heuristic, I compared `train.csv` with `published_texts.csv`, manually inspected the top 100 cases whose frequency in `train.csv` looked implausibly low, and added selected entries to a normalization dictionary. The top five personal-name examples were as follows:\n\n```text\ni-ku-pì-a -> Ikupia\ni-dí-a-šur -> Idi-Aššur\nšál-ma-a-šur -> Šalma-Aššur\ni-dí-sú-en -> Idi-Suen\nšu-be-lim -> Šu-Belim\n```\n\n### [Punctuation]\n\nAs another lottery-ticket heuristic, I replaced `Thus you (said):`, `Thus (said) PN:`, and related `Thus`-based expressions outside letter openings. The score began to drop partway through this line of experimentation, but I still kept this direction because the translation style of `train.csv` used `Thus` far less often.\n\nExample:\n\n```text\nThus you (said):\n-> You said:\n\nThus (said) Ennam-Suen:\n-> Ennam-Suen said:\n```\n\nIn other words, after the manual auxiliary cleanup stage, the auxiliary corpus was stable, and the remaining adaptation work focused on bringing the published row-wise corpus closer to the auxiliary / `train.csv` punctuation and discourse style.\n\n# Training\n\nFor the final `byt5-large` runs, I optimized two data streams in parallel: a main row-wise objective on the adapted published corpus (**46,502** transliteration/translation pairs) and a secondary full-sequence objective on a smaller auxiliary corpus (**1,358** examples used in training). The main corpus taught row-level alignment in the competition format, while the auxiliary corpus helped preserve longer-range fluency and formulaic phrasing.\n\nFor offline model selection, I used the script's default random approximate 80/10/10 split on the final 46,502-example main row-wise corpus, which produced **37,202** training rows, **4,650** validation rows, and **4,650** test rows in the seed-42 run.\n\n## 1. Create lookback, source, and lookahead sequences for the main objective\n\nBefore training, each row in the main corpus was converted into a context-augmented input of the form:\n\n```text\n[LOOKBACK_ONLY] <previous tokens> [SOURCE] <current row> [LOOKAHEAD_ONLY] <next tokens>\n```\n\nIn the final setting, each row received up to four tokens of left context and up to four tokens of right context, drawn from earlier and later rows within the same tablet/document. The target remained only the English translation of the current row, so the surrounding text served only as additional source-side evidence. Thus, this was row-wise contextual training, not the chi-square chunking used later at inference time.\n\n```text\ncdli_id:\nbce88917-e85f-02a8-609f-3f2d37c0d85d.tablet.4\n\ntransliteration:\nša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur\n\nmodel_input:\n[LOOKBACK_ONLY] šu-a-šur i-šu-ú 1 ṭup-pu-um [SOURCE] ša 2 ma-na KÙ.BABBAR ša i-ṣé-er bu-za-zu-ma be-lá-num-ma i-šu-ú 4 ṭup-pè-e a-ni-ú-tim a ma-lá na-áš-pár-tim ša be-lá-nim DUMU šu-a-šur [LOOKAHEAD_ONLY] ba-lá-ṭí-šu-nu-ma a-na pu-šu-ke-en6 DUMU\n\ntarget:\nof 2 minas of silver which Buzazu owes to Belanum; these 4 tablets according to the proxy of Belanum, son of Šu-Aššur.\n```\n\n## 2. Add an auxiliary full-sequence objective\n\nThe auxiliary examples were longer, style-cleaned translations derived from cleaned train-side material and Larsen-related texts. They were not row-wise context windows; instead, they exposed the model to longer document-scale source/target mappings.\n\nImplementation-wise, the main loss was computed on the row-wise contextual batches above, and during the same optimizer step I also sampled one auxiliary batch and added `0.3 * aux_loss` before the parameter update. For the final setting, the auxiliary loader used `batch_size=1`, `max_source_length=1536`, and `max_target_length=1536`. One overlength auxiliary example was filtered out before training, leaving **1,358** auxiliary examples in the final training set.\n\nThe main training hyperparameters for the final `byt5-large` models were:\n\n- model: `google/byt5-large`\n- epochs: `4`\n- batch size: `32`\n- learning rate: `2e-4`\n- weight decay: `0.01`\n- max source length: `448`\n- max target length: `448`\n- warmup steps: `465`\n- gradient clipping: `1.0`\n\nI trained the same configuration with different random seeds (`42`, `60`, `28`, and `52`) and selected the best checkpoint from each run based on validation loss.\n\n# Inference\n\n## 1. Chunk test rows with local context\n\nAt inference time, I first normalized the source-side division-number notation, then split each test transliteration with the same chi-square chunker described above. I used `min_chunk=16` and `max_chunk=32`, so the model saw chunk-sized units rather than entire long test rows at once.\n\nFor each chunk, I then constructed a context-augmented input in the same format used during training:\n\n```text\n[LOOKBACK_ONLY] <previous tokens> [SOURCE] <current chunk> [LOOKAHEAD_ONLY] <next tokens>\n```\n\nIn the final setting, I used `lookback_tokens=4` and `lookahead_tokens=4`. If this context was too short in characters, I allowed the neighboring window to expand slightly until it reached a small minimum textual mass. This kept the prediction target local to one chunk while still exposing nearby formulae, names, and discourse cues.\n\n## 2. Candidate generation and MBR selection\n\nI ensembled four `byt5-large` checkpoints at inference time: two runs trained on the final row-wise adapted corpus produced by the last data-adaptation pass, and two runs trained on the immediately preceding row-wise adapted version from one step earlier in that same pipeline. Their mixture weights were not uniform; the two checkpoints from the final adapted corpus contributed `0.2` each, and the two checkpoints from the preceding adapted corpus contributed `0.3` each. Generation used `max_source_length=448`, and the decoding budget for the target side was scaled adaptively between `192` and `448` new tokens depending on the encoded source length.\n\nFor each chunk and each checkpoint, I generated a heterogeneous candidate pool:\n\n- `4` standard beam candidates\n- `4` diverse-beam candidates\n- `6` nucleus-sampling candidates (`2` samples each at temperatures `0.55`, `0.75`, and `0.95`)\n\nThis yielded up to `56` raw candidates per chunk before deduplication across the four checkpoints.\n\nI then selected the final chunk translation with minimum Bayes risk decoding over the pooled candidate set. The MBR gain combined sentence-level chrF++, sentence BLEU, token-level Jaccard overlap, and a mild length bonus centered on the median candidate length. I weighted chrF++ most heavily (`6.0`), followed by BLEU (`2.0`), while Jaccard and the length bonus each received weight `1.0`. Within each checkpoint, the evidence mass was distributed uniformly across its candidates, and the total contribution of each checkpoint was then scaled by the mixture weights above. When several hypotheses remained close, ranking was further stabilized by support count and generation score.\n\n## 3. Reconstruct rows and post-edit\n\nAfter MBR selection, I concatenated the winning chunk translations in their original order to recover one English translation per test row. I then applied a small deterministic cleanup and post-editing pipeline: normalization of transliteration-style characters and quotation marks, removal of residual bracketed uncertainty markers, source-aware handling of `<gap>`, restoration of competition-specific number and glossary conventions, and two lightweight logistic-regression post-editors to nudge the output toward the training-set style.\n\n# Ablation Study\n\n## Single Model vs Ensemble (MBR)\n\n+ MBR ensembling yielded a modest improvement on the Private LB compared with the single-model runs, while no consistent improvement was observed on the Public LB.\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large(seed 52) | Final adapted corpus | chi-square | 38.4389 | **37.7799** |\n| Single ByT5-Large (seed 28) | Final adapted corpus  | chi-square | 37.7196 | 36.9437 |\n| Single ByT5-Large (seed 42) | The preceding adapted corpus  | chi-square | 38.1309 | 37.6288 |\n| Single ByT5-Large (seed 60) | The preceding adapted corpus  | chi-square | 38.3819 | 37.1679 |\n| Ensemble (MBR) | N/A | chi-square | **38.5514** | 37.4818 |\n\n## Effect of glossary replacement(GR), post-processes(PP)\n\n+ In the single-model setting, removing post-processing or glossary replacement led to lower Public LB scores, while the effect on the Private LB was small and less consistent. This suggests that both techniques were beneficial mainly for Public LB performance.\n\n### Single Model\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large(seed 52) | Final adapted corpus | chi-square | 38.4389 | **37.7799** |\n| Single ByT5-Large (seed 52) -PP | Final adapted corpus | chi-square | 38.4362 | 37.6650 |\n| Single ByT5-Large (seed 52) -PP-GR | Final adapted corpus | chi-square | **38.4443** | 37.6819|\n\n### Ensemble\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Ensemble (MBR) | N/A | chi-square | 38.5514 | 37.4818 |\n| Ensemble (MBR) -PP | N/A | chi-square | 38.5614 | **37.4821** |\n| Ensemble (MBR) -PP-GR | N/A | chi-square | **38.5686** | 37.3774|\n\n## ByT5-Large vs. ByT5-Base \n\n+ The benefit of ByT5-Large became clearer after style adaptation; on the pre-adaptation corpus, its performance was not consistently better than ByT5-Base, particularly on the public LB.\n\n### On the Final Adapted Corpus\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Final adapted corpus | chi-square | **38.4389** | **37.7799** |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4) | Final adapted corpus | chi-square | 38.0925 | 37.0492 |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4) | Final adapted corpus | chi-square | 37.9296 | 37.0533 |\n\n### On the Pre-adaptation Corpus\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Pre-adaptation corpus | chi-square | **37.5068** | 36.7824 |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 3e-4) | Pre-adaptation corpus | chi-square | 37.0518 | 36.5225 |\n| Single ByT5-Base (seed 52, epochs 5, learning rate 2e-4) | Pre-adaptation corpus | chi-square | 37.1781 | **36.9766** |\n\n## Effect of Data Adaptation\n\n+ Data adaptation improved performance on both the Private and Public LBs, indicating that adapting the corpus was effective for this task.\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Pre-adaptation corpus | chi-square | 37.5068 | 36.7824 |\n| Single ByT5-Large (seed 52) | Final adapted corpus | chi-square | **38.4389** | **37.7799** |\n\n## Effect of the chi-square chunker\n\n+ The chi-square chunker outperformed both the [SOURCE]-only setting and fixed 16-token chunking on both leaderboards, suggesting that the chunking strategy was important for strong performance.\n\n| Method | Corpus | Chunker | Private LB | Public LB |\n|---|---|---|---:|---:|\n| Single ByT5-Large (seed 52) | Final adapted corpus | chi-square | **38.4389** | **37.7799** |\n| Single ByT5-Large (seed 52) | Final adapted corpus | `[SOURCE]` only (max_source_length/max_new_tokens 768 tokens) | 38.2861 | 36.6346 |\n| Single ByT5-Large (seed 52) | Final adapted corpus | fixed 16-token chunks | 38.0926 | 36.9625 |\n\n# Appendix\n\n## Early in this competition\n\n- I tried few-shot RAG + babylem-like lemmatizer approaches with Qwen3 Next or Kimi Linear, but I could not achieve a score above 22.x.\n\n## Tried But Did Not Work\n\n- Moses SMT\n  - There were too many unknown terms, which exceeded the capacity of SMT systems\n- Source Contrastive Decoding (EACL 2024)\n  - https://arxiv.org/pdf/2309.07098\n  - I used in-batch alternative sources instead of the paper’s random sampling scheme, so a more faithful implementation may still improve performance.\n- Auxiliary full-sequence training\n  - Training ByT5-base/small on the auxiliary transliteration–translation pairs at their original sequence lengths was not particularly effective as a standalone setting, although the same data was still useful as an auxiliary objective. Longer sequences also tended to produce stronger repetition. I was not able to test whether ByT5-large would behave differently on these longer sequences, since I did not have sufficient computational resources to run it with a sufficiently large batch size.\n- Encoder-Only byt5\n  - I extracted the encoder modules from the original ByT5 models and used them like BERT.\n\n## Environment\n\n## Local\n\n+ CPU: Ryzen7 9800X3D (8 cores)\n+ GPU: RTX 5090 (VRAM 32GB)\n+ RAM: 192GB\n\n## vast.ai\n\n+ For the final two days, local hardware alone was not enough to finish training in time, so I used an RTX 5090 instance on Vast.ai.\n\n----\n\nThanks again to the hosts for this competition. I learned a lot from this problem, especially about corpus construction and style alignment. I am also grateful to the community for sharing many interesting ideas throughout the competition.\n"
  }
}