Last active
March 21, 2024 04:47
-
-
Save jojosati/171fd942cfd4ae5b9a3cd2d014c00749 to your computer and use it in GitHub Desktop.
Transformers.js: (v2) testing 20 AI models in single HTML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>transformers AI v.2</title> | |
<meta property="og:title" content="transformers AI"> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" integrity="sha512-mG7Xo6XLlQ13JGPQLgLxI7bz8QlErrsE9rYQDRgF+6AlQHm9Tn5bh/vaIKxBmM9mULPC6yizAhEmKyGgNHCIvg==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | |
</head> | |
<body ng-app> | |
<div class="container" ng-controller="transformersCtrl"> | |
<h2> | |
transformers AI v.2 | |
</h2> | |
<div class="row"> | |
<div class="col-xs-12 col-md-6"> | |
<div class="form-group"> | |
<label> | |
spec ({{ speclist.length }}) | |
<a target="_blank" href="https://github.com/xenova/transformers.js#tasks"> | |
<i class="glyphicon glyphicon-new-window"></i> | |
</a> | |
</label> | |
<select class="form-control" | |
ng-options="item as item.label for item in speclist" | |
ng-model="selected" | |
ng-change="loadModel(selected);"></select> | |
</div> | |
<div ng-show="selected" class="help-block"> | |
<div>task: {{ selected.task }}</div> | |
<div ng-show="selected.model"> | |
model: {{ selected.model }} | |
<a ng-href="https://huggingface.co/{{ selected.model }}" target="_blank"> | |
<i class="glyphicon glyphicon-new-window"></i> | |
</a> | |
</div> | |
<div ng-show="selected.options">options: {{ selected.options | json }}</div> | |
</div> | |
</div> | |
</div> | |
<div class="row" ng-show="selected"> | |
<div class="col-xs-12 col-md-10"> | |
<div class="form-group" ng-show="selected.executer"> | |
<label>options | |
<span style="margin-left:8px"> | |
<a ng-show="selected.options" class="btn btn-xs btn-default" | |
ng-click="options = JSON.stringify(selected.options)" | |
>default</a> | |
</span> | |
</label> | |
<input class="form-control" type="text" ng-model="options"/> | |
</div> | |
<div class="form-group" ng-show="selected.executer"> | |
<label>{{ selected.src=='image' ? 'image url' : 'text' }} | |
<a class="btn btn-xs btn-default" ng-show="selected.src=='image'" | |
onclick="document.getElementById('filePicker').click()"> | |
<i class="glyphicon glyphicon-camera"></i> | |
</a> | |
<span style="margin-left:8px"> | |
<a ng-show="selected.sample && selected.sample != expr" class="btn btn-xs btn-default" | |
ng-click="expr = selected.sample" | |
>sample</a> | |
</span> | |
<input id="filePicker" type="file" style="display:none" multiple | |
onchange="angular.element(this).scope().addFile(this)" > | |
</label> | |
<textarea class="form-control" type="text" ng-model="expr"></textarea> | |
</div> | |
<div class="form-group" ng-show="expr"> | |
<button ng-show="selected.executer && !statusText" | |
class="btn btn-primary" | |
ng-click="statusText='processing..'; process(selected, expr, options)"> | |
process | |
</button> | |
</div> | |
<div class="text-warning">{{ statusText }}</div> | |
</div> | |
<div class="col-xs-12"> | |
<div class="row"> | |
<div ng-show="imgsrc" class="col-xs-12 col-sm-6 col-md-4"> | |
<img class="img-responsive" ng-src="{{ imgsrc }}" /> | |
</div> | |
<div class="col-xs-12" ng-class="imgsrc && 'col-sm-6 col-md-8'"> | |
<pre ng-show="result" class="bg-info">{{ result }}</pre> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script type="module"> | |
// Imported the cdn of the transformers library | |
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers'; | |
window.transformers = {pipeline, env} | |
</script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.32/angular.min.js" integrity="sha512-QaPMeB0UECrUSaJoWZfBkKK2LtKphYS6HM7krY98a3einXpAooyQQOv2FNm4r+umav2dQsfBHFiHnwBZovSjpw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |
<script> | |
function transformersCtrl($scope, $window, $timeout, $http, $q) { | |
$scope.speclist = [ | |
/* natural language */ | |
{ | |
label: 'text unmasker', | |
task: 'fill-mask', | |
model:'Xenova/bert-base-cased', | |
sample: 'The goal of life is [MASK].', | |
}, | |
{ | |
label: 'text Q&A', | |
task: 'question-answering', | |
model:'Xenova/distilbert-base-uncased-distilled-squad', | |
sample: 'Who was Jim Henson?', | |
options: 'Jim Henson was a nice puppet.', | |
}, | |
{ | |
label: 'text summarizer', | |
task: 'summarization', | |
model:'Xenova/distilbart-cnn-6-6', | |
sample: 'The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, ' + | |
'and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. ' + | |
'During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest ' + | |
'man-made structure in the world, a title it held for 41 years until the Chrysler Building in New ' + | |
'York City was finished in 1930. It was the first structure to reach a height of 300 metres. Due to ' + | |
'the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller than the ' + | |
'Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel Tower is the second ' + | |
'tallest free-standing structure in France after the Millau Viaduct.', | |
options: { max_new_tokens: 100 }, | |
}, | |
{ | |
label: 'text classifier', | |
task: 'sentiment-analysis', | |
model: 'Xenova/distilbert-base-uncased-finetuned-sst-2-english', | |
sample: 'I love transformers!' | |
}, | |
{ | |
label: 'text reviewer', | |
task: 'sentiment-analysis', | |
model:'Xenova/bert-base-multilingual-uncased-sentiment', | |
sample: 'The Shawshank Redemption is a true masterpiece of cinema.' | |
}, | |
{ | |
label: 'text generator', | |
task: 'text-generation', | |
model:'Xenova/distilgpt2', | |
sample: 'Once upon a time, there was', | |
options: { | |
temperature: 2, | |
max_new_tokens: 10, | |
repetition_penalty: 1.5, | |
no_repeat_ngram_size: 2, | |
num_beams: 2, | |
num_return_sequences: 2, | |
}, | |
}, | |
{ | |
label: 'code generator', | |
task: 'text-generation', | |
model:'Xenova/codegen-350M-mono', | |
sample: 'def fib(n):', | |
options: { max_new_tokens: 44 }, | |
}, | |
{ | |
label: 'text2text generator', | |
task: 'text2text-generation', | |
model:'Xenova/LaMini-Flan-T5-783M', | |
sample: 'Write me a love poem about cheese.', | |
options: { | |
max_new_tokens: 200, | |
temperature: 0.9, | |
repetition_penalty: 2.0, | |
no_repeat_ngram_size: 3, | |
}, | |
}, | |
{ | |
label: 'token classifier', | |
task: 'token-classification', | |
model:'Xenova/bert-base-NER', | |
sample: 'My name is Sarah and I live in London', | |
}, | |
{ | |
label: 'text translator', | |
task: 'translation', | |
model:'Xenova/nllb-200-distilled-600M', | |
sample: 'I like to walk my dog.', | |
options: { | |
src_lang: 'eng_Latn', | |
// tgt_lang: 'ell_Grek' | |
tgt_lang: 'tha_Thai' | |
}, | |
}, | |
{ | |
label: 'text zero-shot classifier', | |
task: 'zero-shot-classification', | |
model:'Xenova/mobilebert-uncased-mnli', | |
sample: 'Last week I upgraded my iOS version and ever since then my phone has been overheating whenever I use your app.', | |
options: [ 'mobile', 'billing', 'website', 'account access' ], | |
}, | |
/* vision */ | |
{ | |
label: 'image classifier', | |
task: 'image-classification', | |
model:'Xenova/vit-base-patch16-224', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/tiger.jpg', | |
options: { topk: 3 }, | |
}, | |
{ | |
label: 'image segmenter', | |
task: 'image-segmentation', | |
model:'Xenova/detr-resnet-50-panoptic', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/cats.jpg', | |
}, | |
{ | |
label: 'image detector', | |
task: 'object-detection', | |
model:'Xenova/detr-resnet-50', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/cats.jpg', | |
options: { | |
threshold: 0.5, | |
percentage: true, | |
}, | |
}, | |
/* mutimodal */ | |
{ | |
label: 'image document Q&A', | |
task: 'document-question-answering', | |
model:'Xenova/donut-base-finetuned-docvqa', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/invoice.png', | |
options: 'What is the invoice number?', | |
}, | |
{ | |
label: 'image doc recognitor', | |
task: 'image-to-text', | |
model:'Xenova/nougat-small', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/nougat_paper.png', | |
options: { | |
min_length: 1, | |
max_new_tokens: 40, | |
}, | |
// postload: function (spec, pipe) { | |
// spec.options.bad_words_ids = [pipe.tokenizer.unk_token_id] | |
// } | |
}, | |
{ | |
label: 'image captioner', | |
task: 'image-to-text', | |
model:'Xenova/vit-gpt2-image-captioning', | |
src: 'image', | |
sample: 'https://xenova.github.io/transformers.js/images/football-match.jpg', | |
options: { | |
max_length: 16, | |
num_beams: 4, | |
}, | |
}, | |
{ | |
label: 'image handwritten reader', | |
task: 'image-to-text', | |
model:'Xenova/trocr-small-handwritten', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/handwriting.jpg', | |
}, | |
{ | |
label: 'image zero-shot classifier', | |
task: 'zero-shot-image-classification', | |
model:'Xenova/clip-vit-base-patch32', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/tiger.jpg', | |
options: ['tiger', 'horse', 'dog'], | |
}, | |
{ | |
label: 'image zero-shot detector', | |
task: 'zero-shot-object-detection', | |
model:'Xenova/owlvit-base-patch32', | |
src: 'image', | |
sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/astronaut.png', | |
options: ['human face', 'rocket', 'helmet', 'american flag'], | |
}, | |
] | |
var utils = {} | |
utils.fileElem = function(file, id) { | |
if (file && file.files) // file may be DOM elem | |
file = file.files[id || 0] | |
return file | |
} | |
utils.fileRead = function (file, readmode, success, error) { | |
file = utils.fileElem(file) | |
var deferred = $q.defer() | |
var _success = function(resp){ | |
deferred.resolve(resp) | |
if (success) | |
success(resp) | |
} | |
var _error = function(resp) { | |
deferred.reject(resp) | |
if (error) | |
error(resp) | |
} | |
var reader = new FileReader(); | |
reader.onload = function(e) { | |
_success(reader.result) | |
} | |
reader.onerror = function (e) { | |
_error(reader.error) | |
} | |
reader[readmode || 'readAsBinaryString'](file); | |
return deferred.promise | |
} | |
utils.dataURLFileRead = function (file, success, error) { | |
return utils.fileRead(file, 'readAsDataURL', success, error) | |
} | |
$scope.loadModel = function (spec) { | |
$scope.statusText = '' | |
$scope.result = '' | |
$scope.imgsrc = null | |
$scope.expr = spec.sample; | |
$scope.options = spec.options? JSON.stringify(spec.options) : '' | |
if (!spec.executer) { | |
$scope.statusText = `loading model (${spec.label})..` | |
$window.transformers.pipeline(spec.task, spec.model) | |
.then(function(executer) { | |
console.debug('loaded:', spec.task) | |
spec.executer = executer | |
if (spec.postload) | |
spec.postload(spec, executer) | |
$scope.statusText = '' | |
}, function (err){ | |
$scope.statusText = `error loading: ${err}` | |
}) | |
.finally(function(){ | |
$scope.$digest() | |
}) | |
} | |
} | |
utils.httpDataURL = function (url) { | |
return $http({url: url, responseType: 'blob'}) | |
.then(function(resp){ | |
return utils.dataURLFileRead(resp.data) | |
}) | |
} | |
$scope.addFile = function (elem) { | |
// var file = utils.fileElem(elem) | |
// 2023-06-06 support multiple | |
angular.forEach(elem.files, function (file) { | |
if (!file) | |
return; | |
if (!/image/.test(file.type)) | |
return; | |
utils.dataURLFileRead(file).then(function(url){ | |
if (!url) | |
return | |
$scope.expr = url | |
$scope.imgsrc = url | |
$scope.result = null | |
}) | |
}) | |
} | |
$scope.process = function (spec, nval, options) { | |
$scope.result = '' | |
$scope.statusText = `processing ${spec.label}..` | |
if (spec && nval && spec.executer) { | |
if (options) { | |
try { | |
options = JSON.parse(options) | |
} | |
catch (err) { | |
$scope.statusText = `error options: ${err}` | |
return; | |
} | |
} | |
var promise = $q.when() | |
var payload = nval | |
if (/^data:image/.test(nval)) { | |
$scope.imgsrc = nval | |
} | |
if (spec.src=='image' && /^https?:/.test(nval)) { | |
$scope.imgsrc = null | |
promise = promise.then(function() { | |
return utils.httpDataURL(nval) | |
}) | |
.then(function (imgdata) { | |
$scope.imgsrc = imgdata | |
}) | |
} | |
promise.then(function() { | |
return $timeout(function (){ | |
// My slow CPU, give a while for the DOM update before extensively processing | |
return spec.executer(payload, options || spec.options) | |
}, 50) | |
}) | |
.then(function (result){ | |
console.debug(result) | |
if (options) | |
spec.options = options | |
var _nval = nval | |
if (_nval.length > 100) | |
_nval = _nval.slice(0, 100) + '...' | |
$scope.result = `${_nval}\n\n${JSON.stringify(result, null, 2)}` | |
}, function (err) { | |
$scope.result = JSON.stringify(err) | |
}) | |
.finally(function (){ | |
$scope.statusText = '' | |
$scope.$digest() | |
}) | |
} | |
else | |
$scope.result = nval | |
} | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment