@qvac/translation-nmtcpp 0.19.0 → 0.19.2
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.
- package/README.md +21 -0
- package/index.d.ts +18 -0
- package/index.js +61 -19
- package/package.json +1 -1
- package/prebuilds/android-arm64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__translation-nmtcpp.bare.exports +14 -27
- package/prebuilds/darwin-x64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/darwin-x64/qvac__translation-nmtcpp.bare.exports +90 -105
- package/prebuilds/ios-arm64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/ios-arm64/qvac__translation-nmtcpp.bare.exports +16 -29
- package/prebuilds/ios-arm64-simulator/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/ios-arm64-simulator/qvac__translation-nmtcpp.bare.exports +16 -29
- package/prebuilds/ios-x64-simulator/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/ios-x64-simulator/qvac__translation-nmtcpp.bare.exports +88 -89
- package/prebuilds/linux-arm64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/linux-x64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/win32-x64/qvac__translation-nmtcpp.bare +0 -0
- package/prebuilds/win32-x64/qvac__translation-nmtcpp.bare.exports +0 -0
- package/test/integration/fit.test.js +141 -0
- package/test/mobile/integration.auto.cjs +4 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('brittle')
|
|
4
|
+
const fs = require('bare-fs')
|
|
5
|
+
const os = require('bare-os')
|
|
6
|
+
const path = require('bare-path')
|
|
7
|
+
const process = require('bare-process')
|
|
8
|
+
const TranslationNmtcpp = require('../../index.js')
|
|
9
|
+
const { ensureIndicTransModel, ensureBergamotModel, TEST_TIMEOUT } = require('./utils')
|
|
10
|
+
|
|
11
|
+
test('fit rejects a relative model path before native use', (t) => {
|
|
12
|
+
let error
|
|
13
|
+
try {
|
|
14
|
+
TranslationNmtcpp.assessFit({
|
|
15
|
+
files: { model: 'model.bin' },
|
|
16
|
+
config: { modelType: TranslationNmtcpp.ModelTypes.IndicTrans }
|
|
17
|
+
})
|
|
18
|
+
} catch (caught) {
|
|
19
|
+
error = caught
|
|
20
|
+
}
|
|
21
|
+
t.ok(error instanceof TypeError)
|
|
22
|
+
t.ok(error && error.message.includes('absolute path'))
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('fit reports a missing model without loading it', (t) => {
|
|
26
|
+
const result = TranslationNmtcpp.assessFit({
|
|
27
|
+
files: { model: path.resolve(__dirname, 'missing-model.bin') },
|
|
28
|
+
config: { modelType: TranslationNmtcpp.ModelTypes.IndicTrans }
|
|
29
|
+
})
|
|
30
|
+
t.is(result.status, 'error')
|
|
31
|
+
t.is(result.reason, 'model-unreadable')
|
|
32
|
+
t.is(result.modelBytes, 0)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('fit reads model, pivot, and vocab files below a Unicode directory', (t) => {
|
|
36
|
+
const dir = path.join(os.tmpdir(), `nmt-fit-${process.pid}-${Date.now()}-módèles-日本語`)
|
|
37
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
38
|
+
try {
|
|
39
|
+
const files = {
|
|
40
|
+
model: path.join(dir, 'model.intgemm.bin'),
|
|
41
|
+
pivotModel: path.join(dir, 'pivot.intgemm.bin'),
|
|
42
|
+
srcVocab: path.join(dir, 'src.spm'),
|
|
43
|
+
dstVocab: path.join(dir, 'dst.spm'),
|
|
44
|
+
pivotSrcVocab: path.join(dir, 'pivot-src.spm'),
|
|
45
|
+
pivotDstVocab: path.join(dir, 'pivot-dst.spm')
|
|
46
|
+
}
|
|
47
|
+
for (const file of Object.values(files)) fs.writeFileSync(file, Buffer.alloc(64))
|
|
48
|
+
|
|
49
|
+
const fit = TranslationNmtcpp.assessFit({
|
|
50
|
+
files,
|
|
51
|
+
config: { modelType: TranslationNmtcpp.ModelTypes.Bergamot }
|
|
52
|
+
})
|
|
53
|
+
t.is(fit.modelBytes, 64 * 6)
|
|
54
|
+
t.ok(!fit.report.includes('unreadable'), 'every UTF-8 path was inspected')
|
|
55
|
+
} finally {
|
|
56
|
+
fs.rmSync(dir, { recursive: true, force: true })
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
function checkRealModelFit(t, request) {
|
|
61
|
+
const fit = TranslationNmtcpp.assessFit(request)
|
|
62
|
+
t.comment(`backend=${fit.backend} status=${fit.status} reason=${fit.reason}`)
|
|
63
|
+
t.ok(fit.modelBytes > 0, 'model file bytes were inspected')
|
|
64
|
+
if (fit.freeBytes === 0) {
|
|
65
|
+
t.is(fit.status, 'error')
|
|
66
|
+
t.is(fit.reason, 'device-memory-unavailable')
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
t.ok(fit.requiredBytes > fit.modelBytes, 'load allowance includes overhead')
|
|
70
|
+
t.ok(fit.freeBytes > 0, 'current device memory was queried')
|
|
71
|
+
t.ok(fit.report.includes('Translation load estimate:'), 'a readable report was returned')
|
|
72
|
+
t.ok(
|
|
73
|
+
fit.status === 'fits' ||
|
|
74
|
+
fit.status === 'does-not-fit' ||
|
|
75
|
+
(fit.status === 'error' && fit.reason === 'insufficient-evidence'),
|
|
76
|
+
'the ordinary assessment has a capacity verdict or explicitly reports uncertainty'
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// The same real model cannot fit when the caller reserves every available
|
|
80
|
+
// byte. This checks the capacity decision without assuming a runner's RAM.
|
|
81
|
+
const reserved = TranslationNmtcpp.assessFit({
|
|
82
|
+
...request,
|
|
83
|
+
marginBytes: Number.MAX_SAFE_INTEGER
|
|
84
|
+
})
|
|
85
|
+
t.is(reserved.status, 'does-not-fit')
|
|
86
|
+
t.is(reserved.reason, 'does-not-fit')
|
|
87
|
+
t.ok(reserved.modelBytes >= fit.modelBytes)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
test(
|
|
91
|
+
'fit assesses a real IndicTrans model without loading it',
|
|
92
|
+
{ timeout: TEST_TIMEOUT },
|
|
93
|
+
async (t) => {
|
|
94
|
+
const model = await ensureIndicTransModel()
|
|
95
|
+
checkRealModelFit(t, {
|
|
96
|
+
files: { model },
|
|
97
|
+
config: { modelType: TranslationNmtcpp.ModelTypes.IndicTrans, use_gpu: false }
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
test(
|
|
103
|
+
'fit gives an empty canonical GPU backend precedence over its alias',
|
|
104
|
+
{ timeout: TEST_TIMEOUT },
|
|
105
|
+
async (t) => {
|
|
106
|
+
const model = await ensureIndicTransModel()
|
|
107
|
+
const files = { model }
|
|
108
|
+
const config = { modelType: TranslationNmtcpp.ModelTypes.IndicTrans, use_gpu: true }
|
|
109
|
+
const automatic = TranslationNmtcpp.assessFit({ files, config })
|
|
110
|
+
const conflicting = TranslationNmtcpp.assessFit({
|
|
111
|
+
files,
|
|
112
|
+
config: { ...config, gpu_backend: '', gpuBackend: 'no-such-backend' }
|
|
113
|
+
})
|
|
114
|
+
t.is(conflicting.status, automatic.status)
|
|
115
|
+
t.is(conflicting.reason, automatic.reason)
|
|
116
|
+
t.is(conflicting.backend, automatic.backend)
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
test(
|
|
121
|
+
'fit assesses a real Bergamot model without loading it',
|
|
122
|
+
{ timeout: TEST_TIMEOUT },
|
|
123
|
+
async (t) => {
|
|
124
|
+
const modelDir = await ensureBergamotModel()
|
|
125
|
+
const names = fs.readdirSync(modelDir)
|
|
126
|
+
const modelName = names.find((name) => name.includes('.intgemm'))
|
|
127
|
+
const vocabName = names.find((name) => name.endsWith('.spm'))
|
|
128
|
+
t.ok(modelName, 'Bergamot weights are available')
|
|
129
|
+
t.ok(vocabName, 'Bergamot vocabulary is available')
|
|
130
|
+
if (!modelName || !vocabName) return
|
|
131
|
+
|
|
132
|
+
checkRealModelFit(t, {
|
|
133
|
+
files: {
|
|
134
|
+
model: path.join(modelDir, modelName),
|
|
135
|
+
srcVocab: path.join(modelDir, vocabName),
|
|
136
|
+
dstVocab: path.join(modelDir, vocabName)
|
|
137
|
+
},
|
|
138
|
+
config: { modelType: TranslationNmtcpp.ModelTypes.Bergamot }
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
)
|
|
@@ -11,6 +11,10 @@ async function runEsmDefaultExport (options = {}) { // eslint-disable-line no-un
|
|
|
11
11
|
return runIntegrationModule('../integration/esm-default-export.test.js', options)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
async function runFit (options = {}) { // eslint-disable-line no-unused-vars
|
|
15
|
+
return runIntegrationModule('../integration/fit.test.js', options)
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
async function runIndictrans (options = {}) { // eslint-disable-line no-unused-vars
|
|
15
19
|
return runIntegrationModule('../integration/indictrans.test.js', options)
|
|
16
20
|
}
|