mt-eval-harness 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. mt_eval_harness/__init__.py +99 -0
  2. mt_eval_harness/__main__.py +6 -0
  3. mt_eval_harness/_dashboard_charts.py +148 -0
  4. mt_eval_harness/_dashboard_css.py +657 -0
  5. mt_eval_harness/_dashboard_js.py +462 -0
  6. mt_eval_harness/airgap_transport.py +832 -0
  7. mt_eval_harness/api.py +671 -0
  8. mt_eval_harness/auth.py +453 -0
  9. mt_eval_harness/cache.py +200 -0
  10. mt_eval_harness/card_reader.py +200 -0
  11. mt_eval_harness/champollion_config.py +516 -0
  12. mt_eval_harness/cli.py +3095 -0
  13. mt_eval_harness/compare.py +308 -0
  14. mt_eval_harness/confidence.py +499 -0
  15. mt_eval_harness/config.py +1499 -0
  16. mt_eval_harness/config_exporter.py +418 -0
  17. mt_eval_harness/connection_quality.py +596 -0
  18. mt_eval_harness/contamination.py +130 -0
  19. mt_eval_harness/contest.py +556 -0
  20. mt_eval_harness/contest_intake.py +380 -0
  21. mt_eval_harness/contest_node.py +831 -0
  22. mt_eval_harness/contest_prep.py +629 -0
  23. mt_eval_harness/corpora_browse.py +209 -0
  24. mt_eval_harness/corpus_build/__init__.py +35 -0
  25. mt_eval_harness/corpus_build/adapters/__init__.py +18 -0
  26. mt_eval_harness/corpus_build/adapters/alt_adapter.py +367 -0
  27. mt_eval_harness/corpus_build/adapters/americasnlp_adapter.py +86 -0
  28. mt_eval_harness/corpus_build/adapters/arabench_adapter.py +338 -0
  29. mt_eval_harness/corpus_build/adapters/base.py +148 -0
  30. mt_eval_harness/corpus_build/adapters/bouquet_adapter.py +352 -0
  31. mt_eval_harness/corpus_build/adapters/edtekla_adapter.py +604 -0
  32. mt_eval_harness/corpus_build/adapters/globalvoices_adapter.py +274 -0
  33. mt_eval_harness/corpus_build/adapters/in22_adapter.py +283 -0
  34. mt_eval_harness/corpus_build/adapters/lineparallel_adapter.py +489 -0
  35. mt_eval_harness/corpus_build/adapters/opus_adapter.py +406 -0
  36. mt_eval_harness/corpus_build/adapters/smol_adapter.py +295 -0
  37. mt_eval_harness/corpus_build/adapters/tatoeba_adapter.py +698 -0
  38. mt_eval_harness/corpus_build/adapters/tatoeba_api_adapter.py +220 -0
  39. mt_eval_harness/corpus_build/adapters/tatoeba_challenge_adapter.py +612 -0
  40. mt_eval_harness/corpus_build/adapters/tatoeba_opus_adapter.py +430 -0
  41. mt_eval_harness/corpus_build/adapters/tico19_adapter.py +278 -0
  42. mt_eval_harness/corpus_build/adapters/turkicxwmt_adapter.py +274 -0
  43. mt_eval_harness/corpus_build/adapters/wmt24pp_adapter.py +277 -0
  44. mt_eval_harness/corpus_build/adapters/wmt_general_adapter.py +257 -0
  45. mt_eval_harness/corpus_build/difficulty_estimator.py +240 -0
  46. mt_eval_harness/corpus_build/domain_classifier.py +303 -0
  47. mt_eval_harness/corpus_build/hf_download.py +361 -0
  48. mt_eval_harness/corpus_build/licensing.py +152 -0
  49. mt_eval_harness/corpus_build/sampling.py +186 -0
  50. mt_eval_harness/corpus_build/schema.py +238 -0
  51. mt_eval_harness/corpus_fetch.py +1450 -0
  52. mt_eval_harness/corpus_loader.py +566 -0
  53. mt_eval_harness/dashboard.py +296 -0
  54. mt_eval_harness/data/registry.json +345199 -0
  55. mt_eval_harness/exporter.py +453 -0
  56. mt_eval_harness/external_scoring.py +543 -0
  57. mt_eval_harness/interactive.py +364 -0
  58. mt_eval_harness/language_cards.py +1486 -0
  59. mt_eval_harness/language_cards_remote.py +203 -0
  60. mt_eval_harness/license_use.py +328 -0
  61. mt_eval_harness/method_bundle.py +653 -0
  62. mt_eval_harness/method_card_wizard.py +179 -0
  63. mt_eval_harness/method_loader.py +188 -0
  64. mt_eval_harness/method_manifest.py +72 -0
  65. mt_eval_harness/methods/__init__.py +68 -0
  66. mt_eval_harness/methods/amazon_translate.py +122 -0
  67. mt_eval_harness/methods/apertium.py +135 -0
  68. mt_eval_harness/methods/base_http_mt.py +411 -0
  69. mt_eval_harness/methods/deepl.py +133 -0
  70. mt_eval_harness/methods/google_translate.py +141 -0
  71. mt_eval_harness/methods/libretranslate.py +151 -0
  72. mt_eval_harness/methods/local_model.py +353 -0
  73. mt_eval_harness/methods/microsoft_translator.py +191 -0
  74. mt_eval_harness/methods/registry.py +71 -0
  75. mt_eval_harness/methods/tilde.py +122 -0
  76. mt_eval_harness/methods/translated.py +123 -0
  77. mt_eval_harness/metric_manifest.py +92 -0
  78. mt_eval_harness/metrics_comet.py +384 -0
  79. mt_eval_harness/metrics_fuse.py +162 -0
  80. mt_eval_harness/metrics_metricx.py +367 -0
  81. mt_eval_harness/model_bundle.py +472 -0
  82. mt_eval_harness/model_runner.py +647 -0
  83. mt_eval_harness/net_json.py +72 -0
  84. mt_eval_harness/pipeline.py +274 -0
  85. mt_eval_harness/plugin_discovery.py +819 -0
  86. mt_eval_harness/plugins/__init__.py +9 -0
  87. mt_eval_harness/plugins/champollion_prompts.py +93 -0
  88. mt_eval_harness/plugins/code_switching.py +342 -0
  89. mt_eval_harness/plugins/double_pass_compliance.py +129 -0
  90. mt_eval_harness/plugins/fst_installer.py +825 -0
  91. mt_eval_harness/plugins/giellalt_fst.py +351 -0
  92. mt_eval_harness/plugins/hallucination.py +343 -0
  93. mt_eval_harness/plugins/hooks.py +59 -0
  94. mt_eval_harness/plugins/igt_gloss.py +173 -0
  95. mt_eval_harness/plugins/metrics.py +72 -0
  96. mt_eval_harness/plugins/morph_segmentation.py +101 -0
  97. mt_eval_harness/plugins/prompts.py +54 -0
  98. mt_eval_harness/plugins/terminology.py +198 -0
  99. mt_eval_harness/plugins/tools.py +71 -0
  100. mt_eval_harness/plugins/writing_style.py +400 -0
  101. mt_eval_harness/power.py +318 -0
  102. mt_eval_harness/providers/__init__.py +28 -0
  103. mt_eval_harness/providers/anthropic_provider.py +294 -0
  104. mt_eval_harness/providers/base.py +106 -0
  105. mt_eval_harness/providers/gemini_provider.py +302 -0
  106. mt_eval_harness/providers/local_provider.py +98 -0
  107. mt_eval_harness/providers/openai_provider.py +276 -0
  108. mt_eval_harness/providers/openrouter.py +73 -0
  109. mt_eval_harness/providers/registry.py +102 -0
  110. mt_eval_harness/publish.py +3158 -0
  111. mt_eval_harness/qualifier_gate.py +181 -0
  112. mt_eval_harness/queue_runner.py +2215 -0
  113. mt_eval_harness/recommend.py +512 -0
  114. mt_eval_harness/reputation.py +492 -0
  115. mt_eval_harness/run_card.py +440 -0
  116. mt_eval_harness/runner.py +968 -0
  117. mt_eval_harness/sandbox_runner.py +1021 -0
  118. mt_eval_harness/scoring.py +473 -0
  119. mt_eval_harness/setup_wizard.py +611 -0
  120. mt_eval_harness/shared_task.py +111 -0
  121. mt_eval_harness/significance.py +678 -0
  122. mt_eval_harness/sovereign/__init__.py +44 -0
  123. mt_eval_harness/sovereign/airgap_ops.py +406 -0
  124. mt_eval_harness/sovereign/ceremony.py +524 -0
  125. mt_eval_harness/sovereign/local_ledger.py +307 -0
  126. mt_eval_harness/sovereign/score_manifest.py +194 -0
  127. mt_eval_harness/sovereign/sealed_run.py +231 -0
  128. mt_eval_harness/sovereign/secret_buffer.py +119 -0
  129. mt_eval_harness/sovereign/shamir_gf256.py +206 -0
  130. mt_eval_harness/sovereign/threshold_seal.py +436 -0
  131. mt_eval_harness/sovereign_service.py +138 -0
  132. mt_eval_harness/strategies/__init__.py +97 -0
  133. mt_eval_harness/strategies/batch.py +233 -0
  134. mt_eval_harness/strategies/method_strategy.py +60 -0
  135. mt_eval_harness/strategies/plugin_process.py +10 -0
  136. mt_eval_harness/strategies/single.py +129 -0
  137. mt_eval_harness/strategies/tool_call.py +238 -0
  138. mt_eval_harness/tester.py +1090 -0
  139. mt_eval_harness/transmission_policy.py +392 -0
  140. mt_eval_harness/verifier.py +1285 -0
  141. mt_eval_harness/watch.py +122 -0
  142. mt_eval_harness-0.1.0.dist-info/METADATA +408 -0
  143. mt_eval_harness-0.1.0.dist-info/RECORD +148 -0
  144. mt_eval_harness-0.1.0.dist-info/WHEEL +5 -0
  145. mt_eval_harness-0.1.0.dist-info/entry_points.txt +3 -0
  146. mt_eval_harness-0.1.0.dist-info/licenses/LICENSE +661 -0
  147. mt_eval_harness-0.1.0.dist-info/licenses/LICENSE-EXCEPTION.md +53 -0
  148. mt_eval_harness-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,99 @@
1
+ """
2
+ mt-eval — A configurable, language-agnostic evaluation
3
+ harness for machine translation pipelines.
4
+
5
+ Two-component architecture:
6
+ Run Harness: Executes translation experiments with configurable
7
+ model, prompt, tools, batching, and caching.
8
+ Test Harness: Analyzes run results offline with deterministic
9
+ linguistic metrics (chrF++, BLEU, COMET, exact match),
10
+ bootstrap confidence intervals, significance testing,
11
+ and extensible plugin metrics.
12
+
13
+ Any translation method can plug into the harness for regularized,
14
+ apple-to-apple comparison. See GUIDE.md for full documentation.
15
+ """
16
+
17
+ __version__ = "0.1.0"
18
+
19
+ # Public API — importable from the top-level package
20
+ from mt_eval_harness.config import (
21
+ RunConfig,
22
+ load_registry,
23
+ resolve_dataset,
24
+ load_method_card,
25
+ validate_method_card,
26
+ )
27
+ from mt_eval_harness.exporter import ExportConfig, export_plugin
28
+ from mt_eval_harness.corpus_loader import load_corpus
29
+ from mt_eval_harness.champollion_config import (
30
+ ChampollionRunConfig,
31
+ ChampollionPromptConfig, # Back-compat alias for ChampollionRunConfig
32
+ load_champollion_config,
33
+ build_champollion_system_prompt,
34
+ )
35
+ from mt_eval_harness.plugins.metrics import MetricPlugin
36
+ from mt_eval_harness.plugins.prompts import PromptProvider
37
+ from mt_eval_harness.plugins.champollion_prompts import ChampollionPromptProvider
38
+ from mt_eval_harness.plugins.hooks import PostTranslationHook
39
+ from mt_eval_harness.plugins.tools import ToolProvider
40
+ from mt_eval_harness.significance import (
41
+ SignificanceResult,
42
+ paired_bootstrap,
43
+ paired_approximate_randomization,
44
+ )
45
+ from mt_eval_harness.confidence import ConfidenceInterval, bootstrap_ci, compute_all_cis
46
+ from mt_eval_harness.metrics_comet import (
47
+ HAS_COMET,
48
+ COMETResult,
49
+ compute_comet,
50
+ corpus_comet,
51
+ DEFAULT_COMET_MODEL,
52
+ resolve_comet_model,
53
+ )
54
+ from mt_eval_harness.metrics_metricx import (
55
+ HAS_METRICX,
56
+ MetricXResult,
57
+ compute_metricx,
58
+ corpus_metricx,
59
+ DEFAULT_METRICX_MODEL,
60
+ METRICX_LOWER_IS_BETTER,
61
+ )
62
+
63
+ __all__ = [
64
+ "RunConfig",
65
+ "ExportConfig",
66
+ "export_plugin",
67
+ "load_corpus",
68
+ "ChampollionRunConfig",
69
+ "ChampollionPromptConfig", # Back-compat alias
70
+ "load_champollion_config",
71
+ "build_champollion_system_prompt",
72
+ "ChampollionPromptProvider",
73
+ "MetricPlugin",
74
+ "PromptProvider",
75
+ "PostTranslationHook",
76
+ "ToolProvider",
77
+ "SignificanceResult",
78
+ "paired_bootstrap",
79
+ "paired_approximate_randomization",
80
+ "ConfidenceInterval",
81
+ "bootstrap_ci",
82
+ "compute_all_cis",
83
+ "HAS_COMET",
84
+ "COMETResult",
85
+ "compute_comet",
86
+ "corpus_comet",
87
+ "DEFAULT_COMET_MODEL",
88
+ "resolve_comet_model",
89
+ "HAS_METRICX",
90
+ "MetricXResult",
91
+ "compute_metricx",
92
+ "corpus_metricx",
93
+ "DEFAULT_METRICX_MODEL",
94
+ "METRICX_LOWER_IS_BETTER",
95
+ "load_registry",
96
+ "resolve_dataset",
97
+ "load_method_card",
98
+ "validate_method_card",
99
+ ]
@@ -0,0 +1,6 @@
1
+ """Allow running the harness as a module: python -m mt_eval_harness"""
2
+
3
+ from mt_eval_harness.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,148 @@
1
+ """
2
+ Chart.js chart-builder functions, injected into the dashboard JS.
3
+ Separated from _dashboard_js.py to keep files manageable.
4
+ """
5
+
6
+ CHART_JS = r"""
7
+ // ── Shared Global State ─────────────────────────────────
8
+ // These are hoisted to global scope so both chart builders and the
9
+ // core IIFE can share R (reports), activeIdx, and helpers.
10
+ const R = window.__REPORTS || [];
11
+ let activeIdx = 0;
12
+ const $ = id => document.getElementById(id);
13
+ function runLabel(r, i) {
14
+ const c = r.config || {};
15
+ return (c.run_name || c.model || r.run_id || 'Run '+(i+1)).substring(0, 35);
16
+ }
17
+
18
+ // ── Chart.js Builders ───────────────────────────────────
19
+ const COLORS = ['#6366f1','#34d399','#f59e0b','#f87171','#a78bfa','#22d3ee','#fb923c','#e879f9'];
20
+ let barChart = null, histChart = null, radarChart = null;
21
+
22
+ function destroyCharts() {
23
+ [barChart, histChart, radarChart].forEach(c => { if (c) c.destroy(); });
24
+ barChart = histChart = radarChart = null;
25
+ }
26
+
27
+ // Grouped bar chart: Exact Match % and chrF++ per run
28
+ function buildBarChart() {
29
+ const sec = $('barchart-section');
30
+ if (R.length < 2) { sec.style.display = 'none'; return; }
31
+ sec.style.display = '';
32
+ const canvas = $('bar-canvas');
33
+ if (barChart) barChart.destroy();
34
+ const labels = R.map((r, i) => runLabel(r, i).substring(0, 22));
35
+ const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
36
+ const gridColor = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';
37
+ const textColor = isDark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.5)';
38
+ barChart = new Chart(canvas, {
39
+ type: 'bar',
40
+ data: {
41
+ labels,
42
+ datasets: [
43
+ {
44
+ label: 'Exact Match %',
45
+ data: R.map(r => ((r.overall || {}).exact_match_rate || 0) * 100),
46
+ backgroundColor: COLORS[0] + 'cc',
47
+ borderRadius: 4,
48
+ barPercentage: 0.7,
49
+ },
50
+ {
51
+ label: 'chrF++',
52
+ data: R.map(r => (r.overall || {}).corpus_chrf || 0),
53
+ backgroundColor: COLORS[1] + 'cc',
54
+ borderRadius: 4,
55
+ barPercentage: 0.7,
56
+ }
57
+ ]
58
+ },
59
+ options: {
60
+ responsive: true,
61
+ maintainAspectRatio: true,
62
+ plugins: {
63
+ legend: { labels: { color: textColor, font: { size: 11 } } },
64
+ tooltip: { mode: 'index', intersect: false }
65
+ },
66
+ scales: {
67
+ x: { ticks: { color: textColor, font: { size: 10 } }, grid: { color: gridColor } },
68
+ y: { beginAtZero: true, max: 100, ticks: { color: textColor }, grid: { color: gridColor } }
69
+ }
70
+ }
71
+ });
72
+ }
73
+
74
+ // chrF++ distribution histogram for active run
75
+ function buildHistogram() {
76
+ const entries = R[activeIdx].entries || [];
77
+ const sec = $('histogram-section');
78
+ if (!entries.length) { sec.style.display = 'none'; return; }
79
+ sec.style.display = '';
80
+ const canvas = $('hist-canvas');
81
+ if (histChart) histChart.destroy();
82
+ const bins = new Array(10).fill(0);
83
+ entries.forEach(e => { const b = Math.min(9, Math.floor((e.chrf_score || 0) / 10)); bins[b]++; });
84
+ const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
85
+ const gridColor = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';
86
+ const textColor = isDark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.5)';
87
+ histChart = new Chart(canvas, {
88
+ type: 'bar',
89
+ data: {
90
+ labels: ['0-10','10-20','20-30','30-40','40-50','50-60','60-70','70-80','80-90','90-100'],
91
+ datasets: [{
92
+ label: 'Entries',
93
+ data: bins,
94
+ backgroundColor: COLORS[activeIdx % COLORS.length] + 'aa',
95
+ borderRadius: 3,
96
+ }]
97
+ },
98
+ options: {
99
+ responsive: true,
100
+ maintainAspectRatio: true,
101
+ plugins: {
102
+ legend: { display: false },
103
+ tooltip: { callbacks: { title: ctx => 'chrF++ ' + ctx[0].label, label: ctx => ctx.raw + ' entries' } }
104
+ },
105
+ scales: {
106
+ x: { title: { display: true, text: 'chrF++ Score Range', color: textColor }, ticks: { color: textColor }, grid: { display: false } },
107
+ y: { beginAtZero: true, ticks: { color: textColor, stepSize: 1 }, grid: { color: gridColor } }
108
+ }
109
+ }
110
+ });
111
+ }
112
+
113
+ // Radar chart: multi-metric comparison across runs
114
+ function buildRadar() {
115
+ const sec = $('radar-section');
116
+ if (R.length < 2) { sec.style.display = 'none'; return; }
117
+ sec.style.display = '';
118
+ const canvas = $('radar-canvas');
119
+ if (radarChart) radarChart.destroy();
120
+ const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
121
+ const gridColor = isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)';
122
+ const textColor = isDark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.5)';
123
+ const metrics = ['exact_match_rate', 'corpus_chrf', 'corpus_bleu'];
124
+ const labels = ['Exact Match %', 'chrF++', 'BLEU'];
125
+ const datasets = R.map((r, i) => ({
126
+ label: runLabel(r, i).substring(0, 20),
127
+ data: metrics.map(k => {
128
+ let v = (r.overall || {})[k] || 0;
129
+ if (k === 'exact_match_rate') v *= 100;
130
+ return v;
131
+ }),
132
+ borderColor: COLORS[i % COLORS.length],
133
+ backgroundColor: COLORS[i % COLORS.length] + '22',
134
+ pointBackgroundColor: COLORS[i % COLORS.length],
135
+ pointRadius: 3,
136
+ }));
137
+ radarChart = new Chart(canvas, {
138
+ type: 'radar',
139
+ data: { labels, datasets },
140
+ options: {
141
+ responsive: true,
142
+ maintainAspectRatio: true,
143
+ plugins: { legend: { labels: { color: textColor, font: { size: 10 } } } },
144
+ scales: { r: { beginAtZero: true, max: 100, ticks: { color: textColor, backdropColor: 'transparent' }, grid: { color: gridColor }, pointLabels: { color: textColor } } }
145
+ }
146
+ });
147
+ }
148
+ """