Bertalign
An automatic multilingual sentence aligner. Bertalign takes two texts that are translations of each other and works out which sentences correspond — including 1-to-many, many-to-1, and many-to-many mappings — producing aligned sentence pairs for translation study, corpus construction, or training data mining.
It implements the two-pass algorithm of Liu & Zhu (2022): sentences (and their overlapping concatenations) are embedded with LaBSE, a first dynamic programming pass finds approximate 1-1 anchors via top-k similarity search, and a second pass finds the optimal m-n alignment along that path.
This is a modernized fork of bfsujason/bertalign: packaged for PyPI, fully typed, GPU-accelerated end to end, with offline language detection and no network calls at alignment time.
Install
uv add bertalign # or: pip install bertalign
uv add "bertalign[sat]" # optional: neural sentence splitting (see below)
Python 3.12+. A CUDA GPU is used automatically when available, for both embedding and similarity search; everything also runs on CPU.
Usage
from bertalign import Bertalign
aligner = Bertalign(src_text, tgt_text)
aligner.align_sents()
for src_segment, tgt_segment in aligner.sent_pairs():
print(src_segment, "|||", tgt_segment)
Languages are detected automatically (offline, via
lingua). If your texts already hold
one sentence per line, pass is_split=True to skip splitting.
Aligning many document pairs reuses one loaded model automatically; to be explicit, share an encoder:
from bertalign import Bertalign, Encoder
encoder = Encoder("LaBSE")
for src_text, tgt_text in documents:
aligner = Bertalign(src_text, tgt_text, model=encoder)
aligner.align_sents()
Command line
bertalign source.txt target.txt > pairs.tsv
Inputs are plain-text files; output is one tab-separated pair per line
(internal whitespace is normalized during cleaning, so fields never contain
tabs). Options: --model (any sentence-transformers model), --max-align
(largest bead size), --is-split, --sat, --trust-remote-code,
--version.
Choosing a model
Any sentence-transformers model works via
model=/--model. On the text+berg German–French gold standard (RTX 5070,
this repository's scripts/benchmark_model.py):
| Model | Strict F1 | Lax F1 | Load + align |
|---|---|---|---|
| LaBSE (default) | 0.936 | 0.989 | 4.7 + 9.9 s |
| BAAI/bge-m3 | 0.935 | 0.992 | 38 + 35 s |
| google/embeddinggemma-300m | 0.928 | 0.986 | 33 + 29 s |
| intfloat/multilingual-e5-large | 0.919 | 0.988 | 35 + 35 s |
| Qwen/Qwen3-Embedding-0.6B | 0.915 | 0.990 | 27 + 24 s |
LaBSE remains the default: it was trained specifically for translation-pair retrieval, and it is both the most accurate on strict F1 and by far the fastest. Retrieval models that expect instruction prefixes (e5, Qwen3) lose accuracy here because bertalign embeds raw sentences.
Sentence splitting
The default splitter is rule-based (sentence-splitter) and supports 25 languages: Catalan, Chinese, Czech, Danish, Dutch, English, Finnish, French, German, Greek, Hungarian, Icelandic, Italian, Latvian, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, Slovak, Slovenian, Spanish, Swedish, and Turkish.
The sat extra adds neural splitting with
wtpsplit's SaT models
(state of the art on multilingual segmentation benchmarks, language-agnostic,
GPU-accelerated) — useful for noisy text or languages the rule splitter does
not cover:
from bertalign import Bertalign
from bertalign.sat import sat_splitter
aligner = Bertalign(src_text, tgt_text, splitter=sat_splitter())
or bertalign --sat source.txt target.txt on the command line.
Evaluation
The scorer from Vecalign ships as
bertalign.eval, and the repository carries the text+berg evaluation corpus:
just eval # gold-standard regression gate
uv run python scripts/benchmark_model.py BAAI/bge-m3 # benchmark another model
just eval must reproduce Strict F1 0.936 / Lax F1 0.989 exactly; it is the
correctness gate for any change to the aligner, kernels, or dependencies.
Development
uv sync --extra sat
just check # ruff (select = ALL), ty, vulture, pytest, build
Licence and citation
GPL-3.0-or-later, inherited from upstream. If you use Bertalign in research, cite:
Lei Liu & Min Zhu. 2022. Bertalign: Improved word embedding-based sentence alignment for Chinese–English parallel corpora of literary texts. Digital Scholarship in the Humanities. https://doi.org/10.1093/llc/fqac089
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bertalign-2.0.0.tar.gz.
File metadata
- Download URL: bertalign-2.0.0.tar.gz
- Upload date:
- Size: 31.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b738590754bb9326d8118cb1d3c0d456e743a68ea0036550fbe27e130a3867b2
|
|
| MD5 |
d31456250f6e0539005a7d3ab76bc42a
|
|
| BLAKE2b-256 |
56a1cca08a7ee1b38bd1a169213ba062e4b11ff16216bab89b3c6afdf312f8f5
|
File details
Details for the file bertalign-2.0.0-py3-none-any.whl.
File metadata
- Download URL: bertalign-2.0.0-py3-none-any.whl
- Upload date:
- Size: 32.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d541946af31fd8c71fab043cdd83cba9293e0c24f11bc37be6f3efd4b72e724
|
|
| MD5 |
674d092d4472a853395a7455519d509b
|
|
| BLAKE2b-256 |
b54b6e4d5ee99661d2cc1f2adfdd0ba50e30680b87d973ff90c8e4b1f4456d5c
|