Skip to content

Commit

Permalink
Wasm test page for translating b/w non-English language pairs
Browse files Browse the repository at this point in the history
  • Loading branch information
abhi-agg committed Oct 18, 2021
1 parent c7b626d commit 7c2a9d6
Show file tree
Hide file tree
Showing 13 changed files with 1,448 additions and 522 deletions.
106 changes: 18 additions & 88 deletions wasm/README.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,25 @@
# Using Bergamot Translator in JavaScript

Instructions in this document assume current-directory to be
[wasm](https://github.com/browsermt/bergamot-translator/tree/main/wasm) within
bergamot-translator source.

The example file `bergamot.html` in the folder `test_page` demonstrates how to
use the bergamot translator in JavaScript via a `<script>` tag.

## Pre-requisites

**Download files required for translation**

Please note that [Using JS APIs](#using-js-apis) and [Demo](#demo) section below assumes that the [bergamot project specific model files](https://github.com/mozilla-applied-ml/bergamot-models) are already downloaded and present in the `test_page` folder. If this is not done then use following instructions to do so:

```bash
cd test_page
git clone --depth 1 --branch main --single-branch https://github.com/mozilla-applied-ml/bergamot-models
mkdir models
cp -rf bergamot-models/prod/* models
gunzip models/*/*
```
All the instructions below are meant to run from the current directory.

## Using JS APIs

```js
// The model configuration as YAML formatted string. For available configuration options, please check: https://marian-nmt.github.io/docs/cmd/marian-decoder/
// This example captures some of the most relevant options
const modelConfig = `beam-size: 1
normalize: 1.0
word-penalty: 0
max-length-break: 128
mini-batch-words: 1024
workspace: 128
max-length-factor: 2.0
skip-cost: true
cpu-threads: 0
quiet: true
quiet-translation: true
gemm-precision: int8shift
`;

// Download model, shortlist and vocabulary files and read them into buffers
const modelFile = `models/esen/model.esen.intgemm.alphas.bin`;
const shortlistFile = `models/esen/lex.50.50.esen.s2t.bin`;
const vocabFiles = [`models/${languagePair}/vocab.${vocabLanguagePair}.spm`,
`models/${languagePair}/vocab.${vocabLanguagePair}.spm`];
const uniqueVocabFiles = new Set(vocabFiles);

// Please refer to bergamot.html in test_page folder for downloadAsArrayBuffer function
const downloadedBuffers = await Promise.all([downloadAsArrayBuffer(modelFile), downloadAsArrayBuffer(shortlistFile)]);
const downloadedVocabBuffers = [];
for (let item of uniqueVocabFiles.values()) {
downloadedVocabBuffers.push(await downloadAsArrayBuffer(item));
}

const modelBuffer = downloadedBuffers[0];
const shortListBuffer = downloadedBuffers[1];
Please refer to the file `test_page/js/worker.js` that demonstrates how to use the bergamot translator in JavaScript via a `<script>` tag.

// Construct AlignedMemory instances from the buffers
var alignedModelMemory = constructAlignedMemoryFromBuffer(modelBuffer, 256); // Please refer to bergamot.html in test_page folder for this function
var alignedShortlistMemory = constructAlignedMemoryFromBuffer(shortListBuffer, 64); // Please refer to bergamot.html in test_page folder for this function
var alignedVocabsMemoryList = new Module.AlignedMemoryList;
downloadedVocabBuffers.forEach(item => alignedVocabsMemoryList.push_back(constructAlignedMemoryFromBuffer(item, 64)));
## Demo

// Instantiate the Translation Service
const translationService = new Module.Service(modelConfig, alignedModelMemory, alignedShortlistMemory, alignedVocabsMemoryList);
* Download bergamot model files required for translation

// Instantiate the arguments of translate() API i.e. ResponseOptions and input (vector<string>)
const responseOptions = new Module.ResponseOptions();
const input = new Module.VectorString;
Use following instructions to download [model files](https://github.com/mozilla/firefox-translations-models/) (make sure that `git-lfs` is installed and initialized before running these instructions):

// Initialize the input
input.push_back("Hola"); input.push_back("Mundo");

// translate the input; the result is a vector<Response>
const result = translationService.translate(input, responseOptions);

// Print original and translated text from each entry of vector<Response>
for (let i = 0; i < result.size(); i++) {
console.log(' original=' + result.get(i).getOriginalText() + ', translation=' + result.get(i).getTranslatedText());
}

// Don't forget to clean up the instances
translationService.delete();
responseOptions.delete();
input.delete();
```

## Demo

* Make sure that you followed [Pre-requisites](#pre-requisites) instructions before moving forward.
```bash
cd test_page
git clone --depth 1 --branch main --single-branch https://github.com/mozilla/firefox-translations-models/
mkdir models
cp -rf firefox-translations-models/models/prod/* models
cp -rf firefox-translations-models/models/dev/* models
gunzip models/*/*
```

* Start the test webserver (ensure you have the latest nodejs installed)
```bash
Expand All @@ -114,10 +44,10 @@ input.delete();

* Browse to the following page:
```
http://localhost:8000/bergamot.html
http://localhost:80
```

* Run some translations:
* Choose a model and press `Load Model`
* Type a sentence to be translated in the `From` textbox and press `Translate`
* See the results in the `To` and `Log` textboxes
* Perform translations:
* Choose the source and target languages using `From` and `To` dropdowns.
* Type a sentence to be translated in the `From` textbox.
* See the result in the `To` textbox.
61 changes: 58 additions & 3 deletions wasm/test_page/bergamot-httpserver.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
require(__dirname + '/helper.js');

const http = require('http');
const https = require('https')
const express = require('express');
const app = express();
const server = http.createServer(app);
const fs = require('fs');
const url = require('url');
const nocache = require('nocache');
const cors = require('cors');
const path = require('path');

let port = 8000;
if (process.argv[2]) {
port = process.argv[2];
}

let skipssl = 0;
if (process.argv[3]) {
skipssl = process.argv[3];
}

let certpath = "/etc/letsencrypt";
if (process.argv[4]) {
certpath = process.argv[4];
}

app.use(cors())
app.use(nocache());

app.get('/', cors(), function(req, res) {
if (!req.secure && skipssl != 1) {
return res.redirect("https://" + req.headers.host + req.url);
}
res.sendFile(path.join(__dirname + '/index.html'));
res.header('Cross-Origin-Embedder-Policy','require-corp');
res.header('Cross-Origin-Opener-Policy','same-origin');
res.header('Cross-Origin-Resource-Policy','same-origin');
});

app.get('/*.*' , cors(), function(req, res) {
var options = url.parse(req.url, true);
var mime = Helper.getMime(options);
Expand All @@ -34,5 +58,36 @@ function serveFile(res, pathName, mime) {
});
}

if (skipssl != 1){
https.createServer({
key: fs.readFileSync(`${certpath}/privkey.pem`),
cert: fs.readFileSync(`${certpath}/cert.pem`),
ca: fs.readFileSync(`${certpath}/chain.pem`),
},
app
).listen(443, () => {
console.log('Listening https port 443')
})
}

const Helper = {
types: {
"wasm" : "application/wasm"
, "js" : "application/javascript"
, "html" : "text/html"
, "htm" : "text/html"
, "ico" : "image/vnd.microsoft.icon"
, "css" : "text/css"
},
getMime: function(u) {
var ext = this.getExt(u.pathname).replace('.', '');
return this.types[ext.toLowerCase()] || 'application/octet-stream';
},
getExt: function(path) {
var i = path.lastIndexOf('.');
return (i < 0) ? '' : path.substr(i);
}
};

server.listen(port);
console.log(`HTTP and BinaryJS server started on port ${port}`);
console.log(`HTTP and BinaryJS server started on port ${port}`);
66 changes: 0 additions & 66 deletions wasm/test_page/bergamot.html

This file was deleted.

54 changes: 0 additions & 54 deletions wasm/test_page/bergamot.js

This file was deleted.

Loading

0 comments on commit 7c2a9d6

Please sign in to comment.