Skip to content

Instantly share code, notes, and snippets.

@jojosati
Last active March 21, 2024 04:47
Show Gist options
  • Save jojosati/171fd942cfd4ae5b9a3cd2d014c00749 to your computer and use it in GitHub Desktop.
Save jojosati/171fd942cfd4ae5b9a3cd2d014c00749 to your computer and use it in GitHub Desktop.
Transformers.js: (v2) testing 20 AI models in single HTML
<!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