moonalign

A MoonBit-native bilingual paragraph and sentence alignment toolkit with dynamic-programming based matching and a practical CLI.

alignment
bilingual
nlp
translation
corpus
moon add LL728/moonalign@0.1.0
Download zip
Author
Version
0.1.0
License
Apache-2.0
Last updated
5 days ago
Downloads
2
README

#MoonAlign

MoonAlign 是一个面向双语平行语料构建的 MoonBit 工具包。它基于:

  • 段落/句子切分
  • 轻量长度模型
  • 动态规划对齐
  • 可解释的 1-1 / 1-2 / 2-1 对齐结果

项目目标不是做“重模型翻译评估器”,而是提供一个在 MoonBit 生态里可复用、可扩展、可继续演进的基础组件:

  • 作为库嵌入语料清洗、翻译工作流、术语对照工具
  • 作为 CLI 直接生成 JSON / TSV 对齐结果
  • 作为后续更复杂特征工程或统计模型的底座

#Features

  • sentenceparagraph 两种切分模式
  • 动态规划搜索最稳定的对齐路径
  • 支持 1-11-22-1 等小范围合并
  • 输出结构化 JSON 报告或 TSV 表格
  • 对齐报告包含全局长度比、告警与逐步得分
  • 通过 evaluate 计算 gold set 的 precision、recall、F1 与覆盖率
  • 内置可离线运行的 Tatoeba 小样本基准和合并路径回归夹具

#Quick Start

moon check moon test moon run cmd/main -- \ --source-text "MoonBit favors stable tooling. MoonAlign builds corpora." \ --target-text "MoonBit 强调稳定工具链。MoonAlign 用来构建语料。" \ --mode sentence \ --format json

也可以输出 TSV:

moon run cmd/main -- \ --source-text "MoonAlign builds bilingual corpora." \ --target-text "MoonAlign 用来构建双语语料。" \ --format tsv

运行内置基准并输出 JSON 指标:

moon run --target wasm-gc cmd/main -- --benchmark

#Public API

///|
test "basic alignment" {
let report = @moonalign.align(
"MoonBit favors maintainable tooling.\n", "MoonBit 强调可维护的工具链。\n",
)
inspect(report.pairs.length(), content="1")
inspect(report.pairs[0].move_kind, content="1-1")
}

#Design Notes

  • 对齐特征当前以长度启发式为主,优先保证稳定、透明、易调参。
  • ASCII 词元和 CJK 字符使用不同权重,减轻中英长度尺度不一致的问题。
  • 当大量 1-2 / 2-1 合并出现时,报告会给出告警,提示重新检查切句或源文本质量。
  • 基准指标用于暴露当前模型边界,不把长度启发式的结果包装成翻译质量分数;后续可加入词典锚点、语言识别或领域先验。

#Repository Notes

  • 主要 MoonBit 源码规模目前约 995 行(不含 _build/.mooncakes/)。
  • 公开接口通过 moon info 生成 pkg.generated.mbti,便于验收时审查 API 面。
  • 代码、示例文本、README 与测试全部由本仓库维护;基准样本单独标注了 Tatoeba 来源与许可证。
  • 详细来源与实现说明见 SOURCES.md

#Roadmap

  • 词典/锚点特征
  • 段落先验约束
  • gold set 评估命令与基准报告
  • mooncakes.io 发布与版本化 API

#
AlignOptions

pub struct AlignOptions {
segment_mode : SegmentMode
max_fan_out : Int
join_penalty : Double
deviation_penalty : Double
min_sentence_chars : Int
preserve_paragraphs : Bool
} derive(
Debug
)

#
AlignmentMetrics

pub struct AlignmentMetrics {
predicted_pairs : Int
gold_pairs : Int
exact_pairs : Int
precision : Double
recall : Double
f1 : Double
source_coverage : Double
target_coverage : Double
merged_pairs : Int
average_score : Double
} derive(ToJson,
Debug
)

#
AlignmentPair

pub struct AlignmentPair {
source_start : Int
source_end : Int
target_start : Int
target_end : Int
source_text : String
target_text : String
source_char_weight : Double
target_char_weight : Double
source_tokens : Int
target_tokens : Int
score : Double
move_kind : String
} derive(ToJson,
Debug
)

#
AlignmentReport

pub struct AlignmentReport {
options : Json
source_count : Int
target_count : Int
estimated_ratio : Double
warnings : Array[String]
pairs : Array[AlignmentPair]
} derive(ToJson,
Debug
)

#
BackPointer

type BackPointer derive(Eq,
Debug
)

#
BenchmarkCase

pub struct BenchmarkCase {
name : String
source : String
target : String
gold_pairs : Array[GoldPair]
source_url : String
license : String
} derive(ToJson,
Debug
)

#
BenchmarkResult

pub struct BenchmarkResult {
name : String
metrics : AlignmentMetrics
warnings : Array[String]
} derive(ToJson,
Debug
)

#
GoldPair

pub struct GoldPair {
source_start : Int
source_end : Int
target_start : Int
target_end : Int
} derive(Eq, ToJson,
Debug
)

#
SegmentMode

pub enum SegmentMode {
Paragraph
Sentence
} derive(Eq,
Debug
)

#
TextUnit

pub struct TextUnit {
id : Int
paragraph_index : Int
sentence_index : Int
text : String
normalized : String
char_weight : Double
token_count : Int
} derive(ToJson,
Debug
)

#
align

fn align(source_text : String, target_text : String, options? : AlignOptions) -> AlignmentReport

#
align_texts

fn align_texts(source_text : String, target_text : String, options? : AlignOptions) -> AlignmentReport

#
align_units

fn align_units(source_units : Array[TextUnit], target_units : Array[TextUnit], options? : AlignOptions) -> AlignmentReport

#
align_with_mode

fn align_with_mode(source_text : String, target_text : String, mode? : SegmentMode) -> AlignmentReport

#
benchmark_case

fn benchmark_case(case : BenchmarkCase) -> BenchmarkResult

#
benchmark_cases

fn benchmark_cases() -> Array[BenchmarkCase]

#
benchmark_suite

fn benchmark_suite() -> Array[BenchmarkResult]

#
benchmark_to_json_string

fn benchmark_to_json_string(indent? : Int) -> String

#
default_options

fn default_options() -> AlignOptions

#
evaluate

fn evaluate(report : AlignmentReport, gold_pairs : Array[GoldPair]) -> AlignmentMetrics

#
gold_pair

fn gold_pair(source_start~ : Int, source_end~ : Int, target_start~ : Int, target_end~ : Int) -> GoldPair

#
normalize_text

fn normalize_text(text : String) -> String

#
options_to_json

fn options_to_json(options : AlignOptions) -> Json

#
paragraph_mode

fn paragraph_mode() -> SegmentMode

#
report_to_json_string

fn report_to_json_string(report : AlignmentReport, indent? : Int) -> String

#
report_to_tsv

fn report_to_tsv(report : AlignmentReport) -> String

#
segment_text

fn segment_text(text : String, options? : AlignOptions) -> Array[TextUnit]

#
sentence_mode

fn sentence_mode() -> SegmentMode

#
with_max_fan_out

fn with_max_fan_out(options : AlignOptions, max_fan_out : Int) -> AlignOptions

#
with_min_sentence_chars

fn with_min_sentence_chars(options : AlignOptions, min_sentence_chars : Int) -> AlignOptions

#
with_preserve_paragraphs

fn with_preserve_paragraphs(options : AlignOptions, preserve : Bool) -> AlignOptions

#
with_segment_mode

fn with_segment_mode(options : AlignOptions, mode : SegmentMode) -> AlignOptions