Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ioai-translate

Structure-preserving LLM translation pipeline for IOAI contest documents.

Built for and battle-tested at IOAI 2026, where it translated every task statement, hint, and FAQ into 44 languages across three LLM providers. Designed so a future organising team can adopt it by editing two config files.

Why this and not "just ask an LLM"?

Contest documents are exam material: a mistranslated constraint costs a contestant points, and a mangled code block breaks their pipeline. This tool adds the guarantees a plain chat prompt cannot:

  • Technical content is byte-identical by construction. Code blocks, inline code, LaTeX/math, URLs, and HTML comments are frozen into placeholder tokens before the LLM sees the text, and restored afterwards. The model physically cannot alter your code.
  • No cross-language contamination. Every language is one fully independent API call — separate prompt, separate context. A validator additionally checks non-Latin outputs are written in the expected script.
  • Structural validation. Every output is compared against the source: heading levels and order, table dimensions, list counts, numbers in prose, placeholder integrity. Failures are reported per language in _report.md.
  • Delegation-driven model choice. Each language maps to the LLM family its national delegation trusts (configurable registry: OpenAI / Anthropic / Google / Qwen, with per-language fallbacks).
  • Translator notes. Models flag genuine ambiguities and source errors into a separate .notes.md for organiser review — stripped from the contestant-facing file.
  • Operational hardening learnt the hard way: fast-fail request timeouts, automatic corrective retry when a placeholder is mishandled, resume with --only-missing, stale-notes cleanup, per-language provider fallback.

Install

pip install ./ioai-translate        # or: pip install ioai-translate (if published)

Requires Python 3.10+. Provider SDKs (openai, anthropic, google-genai) are installed automatically; you only need API keys for the providers your registry actually uses.

Quick start

# 1. Scaffold an editable config
ioai-translate init

# 2. Add API keys
cp ioai-translate-config/.env.example ioai-translate-config/.env
#    edit the file, then:  set -a; source ioai-translate-config/.env; set +a

# 3. Translate
ioai-translate run statement.md

# 4. Build deliverable folders (one per language, + figures, + English)
ioai-translate organize output/statement --source path/to/task_dir

Outputs land in output/<stem>/:

File Purpose
<stem>.<code>.md the translation, structure-consistent with the source
<stem>.<code>.notes.md translator notes for organiser review (if any)
<stem>.en.md snapshot of the source that was translated
_report.md per-language status + validation results
by_language/ after organize: French [fr]/, English [en]/, …

Everyday commands

ioai-translate run doc.md --langs fr,ko,ar      # subset of languages
ioai-translate run doc.md --only-missing        # resume an interrupted run
ioai-translate run doc.md --dry-run             # inspect prompts, no API calls
ioai-translate run doc.md --context ioai-translate-config/prompts/context_support_doc.md
                                                # for FAQs / logistics docs
ioai-translate validate doc.md output/doc/      # re-check after manual edits

Configuration

ioai-translate init copies an editable config directory:

ioai-translate-config/
├── languages.json            # language registry + model registry
├── .env.example              # API key template
└── prompts/
    ├── base_prompt.md        # the general translation prompt
    ├── language_extensions.md# per-language instructions (## fr — French …)
    ├── skill.md              # translator checklist distilled from human review
    └── context_support_doc.md# example document-type context (FAQ-style docs)

For a new IOAI edition you typically edit only:

  1. languages.json — add/remove languages; set each language's family (which provider/model translates it), script (for the contamination check), and optional fallback_family / alias_of. Update the model_registry to the current best model of each provider family — verify model IDs against the live provider APIs, and override at runtime with the env_override variables without touching the file.
  2. prompts/language_extensions.md — per-language terminology conventions, registers, glossaries. Sections are keyed ## <code> — <Name>.

The base prompt encodes fidelity rules (no additions/omissions/hints, preserve ambiguity, exam register, prompt-injection guard, notes protocol) and rarely needs changes.

Environment variables

Variable Purpose
OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY / DASHSCOPE_API_KEY provider credentials
IOAI_MODEL_OPENAI etc. override a model id without editing languages.json
IOAI_REQUEST_TIMEOUT per-attempt timeout in seconds (default 240; raise to ~600 for very long documents in token-heavy scripts like Amharic)

Post-contest review: learn from human corrections

During the contest, team leaders review and fix the AI translations. Those edits are training signal — three subcommands close the loop:

# 1. Extract every human edit, per language, with automatic country→language
#    matching. Edits that merely mirror an official English statement revision
#    (detected via the ISC/English reference file) are tagged [OFFICIAL-UPDATE].
ioai-translate diff <contest-root> --out review/diffs
#    <contest-root> = task folders each containing AI-Translation/ (the
#    pipeline's by_language output) and Translations/ (the human-fixed files)

# 2. LLM-synthesize the diffs into guidance: per-language terminology rules,
#    recurring-mistake lists, and a ready-to-paste updated prompt-extension
#    section; plus a global report with base-prompt amendments and a skill.md
#    checklist (only cross-language patterns with cited evidence).
ioai-translate lessons review/diffs --out review/lessons

# 3. Leakage detector: audit every genuine (non-official) edit for added
#    information — extra hints, examples, or solution leakage that the English
#    source never contained. Outputs audit.md + machine-readable audit.json
#    with per-finding severity (info-added / hint / solution-leak /
#    content-removed).
ioai-translate audit <contest-root> --sources <dir-of-task-folders> --out review/audit

The review-stage model is set by IOAI_REVIEW_MODEL (default openai:gpt-5.6-sol; format provider:model).

The shipped prompts already contain one full cycle of this loop. At IOAI 2026 this workflow processed 353 document pairs (1,554 edits, half of them official-update mirrors): the distilled results live in the package as the "LESSONS FROM HUMAN REVIEW" section of base_prompt.md, reviewer-derived update blocks in 29 sections of language_extensions.md, and prompts/skill.md (the 10-point translator checklist). The 2026 audit verdict, for calibration: 0 solution leaks, 4 marginal hints, and 55 edits where reviewers accidentally dropped source nuance — the auditor watches both directions.

Operational notes (from IOAI 2026 production use)

  • Cost: a ~1,500-token statement ≈ $3 per 44-language run; a ~4,500-token FAQ ≈ $8–10. Output tokens dominate (~85%), so prompt caching helps little; OpenAI's Batch API (−50%) is the lever if cost matters.
  • Fund accounts before contest week and enable auto-recharge — the single most common failure mode is a provider running out of credit mid-run. Google's free tier (20 requests/day) cannot sustain a run; the key must belong to a billing-enabled project.
  • Images: relative image references survive translation verbatim; organize --source copies figure files into every language folder so they render. HTML <img> tags are preserved by prompt (not by freezing) — the validator will tell you if one was damaged.
  • Warn-level checks are advisory. Number warnings in Japanese/Korean/Thai are usually grammatical counters, not data loss; the validator never blocks on them. FAIL-level checks (headings, tables, placeholders) are real.
  • Run Kernel-style smoke tests early: --langs fr is a cheap probe that the keys, quota, and pipeline all work before you commit to 44 languages.

Development

pip install -e ./ioai-translate
python -m pytest ioai-translate/tests -q

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages