kristenq commited on
Commit
5dbb619
·
1 Parent(s): b98c717

Upload app files

Browse files
Files changed (7) hide show
  1. .gitattributes +1 -0
  2. README.md +20 -12
  3. index.html +52 -19
  4. mediapipe_genai_bundle.js +4 -0
  5. script.js +171 -0
  6. style.css +409 -16
  7. worker.js +65 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ myemoji-gemma-3-270m-it.task filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,12 +1,20 @@
1
- ---
2
- title: Emoji Gemma
3
- emoji: 📉
4
- colorFrom: pink
5
- colorTo: pink
6
- sdk: static
7
- pinned: false
8
- license: apache-2.0
9
- short_description: 'Translate text to emojis with Gemma 3 270M running entirely '
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
1
+ # Run a fine-tuned Gemma 3 270M model in the browser with MediaPipe LLM Inference API
2
+
3
+ This app demonstrates how to generate emojis from a text input using a fine-tuned Gemma 3 270M model running directly in the browser. For this demo you'll just change one line of code to point to your MediaPipe Task model bundle.
4
+
5
+ ## Run the demo
6
+ 1. Download the app files in this directory and include your .task model bundle in the local app folder.
7
+ 2. In the worker.js file, update the `modelPath` to point to the .task file.
8
+ 3. Open terminal on your computer and navigate (`cd`) to the app folder.
9
+ 4. Run `npx serve` to start the local server.
10
+ 5. Open the provided `localhost` address in your browser to run the app.
11
+
12
+ ## How it works
13
+ This demo sets up a simple web server to host a frontend where users can enter a text prompt. This starts a generation process in a web worker to avoid blocking the main UI thread. The worker uses a bundled version of the MediaPipe Tasks GenAI package ([@mediapipe/tasks-genai](https://www.npmjs.com/package/@mediapipe/tasks-genai)) to generate a response from the model and send it back to the user.
14
+
15
+ **Requirements:** Browser with [WebGPU support](https://caniuse.com/webgpu)
16
+
17
+ ## Resources
18
+ * [Notebook: Fine-tune Gemma 3 270M](https://github.com/google-gemini/gemma-cookbook/blob/main/Demos/Emoji-Gemma-on-Web/resources/Fine_tune_Gemma_3_270M_for_emoji_generation.ipynb)
19
+ * [Notebook: Convert Gemma 3 270M for use with MediaPipe](https://github.com/google-gemini/gemma-cookbook/blob/main/Demos/Emoji-Gemma-on-Web/resources/Convert_Gemma_3_270M_to_LiteRT_for_MediaPipe_LLM_Inference_API.ipynb)
20
+ * [MediaPipe LLM Inference Web documentation](https://ai.google.dev/edge/mediapipe/solutions/genai/llm_inference/web_js)
index.html CHANGED
@@ -1,19 +1,52 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Emoji generator</title>
8
+ <link rel="preload" href="worker.js" />
9
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
+ <link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;600;800&family=Noto+Color+Emoji&display=swap"
12
+ rel="stylesheet" />
13
+ <link rel="stylesheet" href="style.css" />
14
+ </head>
15
+
16
+ <body>
17
+ <div class="background" aria-hidden="true" aria-disabled="true">
18
+ <div class="background-blob-1"></div>
19
+ <div class="background-blob-2"></div>
20
+ <div class="background-blob-3"></div>
21
+ </div>
22
+ <div class="container">
23
+ <h1 class="google-sans-medium">Emoji generator</h1>
24
+ <p class="text-cta">Translate text to fun combinations of emoji with your own Gemma model ✨</p>
25
+ <div class="input-container">
26
+ <input type="text" id="prompt-input" aria-label="Type any phrase and get suggestions" placeholder="Type any phrase and get suggestions">
27
+ <button disabled type="submit" id="generate-btn" aria-label="Generate emojis">
28
+ <svg class="arrow" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16">
29
+ <path d="M.59 14.59 2 16l8-8-8-8L.59 1.41 7.17 8" fill="#fff" />
30
+ </svg>
31
+ <svg class="loader" width="18" height="18" viewBox="0 0 18 18" fill="none"
32
+ xmlns="http://www.w3.org/2000/svg">
33
+ <circle cx="9" cy="9" r="8" stroke="white" stroke-width="2" />
34
+ </svg>
35
+ </button>
36
+ </div>
37
+ <div class="output-container">
38
+ <div id="response-output" class="response-box"></div>
39
+ <div id="status-message">Loading model...</div>
40
+ </div>
41
+ </div>
42
+ <div class="footer">
43
+ <p>Powered by <a href="https://huggingface.co/google/gemma-3-270m-it">Gemma 3 270M</a> and <a href="https://ai.google.dev/edge/mediapipe/">MediaPipe</a></p>
44
+ <a href="https://github.com/google-gemini/gemma-cookbook/tree/main/Demos/Emoji-Gemma-on-Web" target="_blank">View on GitHub<svg fill="none" xmlns="http://www.w3.org/2000/svg"
45
+ viewBox="0 0 7 12">
46
+ <path d="m.06 10.4.94.93L6.33 6 1 .67l-.94.94L4.45 6" fill="#327AC3" />
47
+ </svg></a>
48
+ </div>
49
+ <script type="module" src="script.js"></script>
50
+ </body>
51
+
52
+ </html>
mediapipe_genai_bundle.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ var BundledCode=(()=>{var gt=Object.defineProperty;var Ir=Object.getOwnPropertyDescriptor;var Tr=Object.getOwnPropertyNames;var Pr=Object.prototype.hasOwnProperty;var Lr=(e,t)=>{for(var n in t)gt(e,n,{get:t[n],enumerable:!0})},Or=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Tr(t))!Pr.call(e,i)&&i!==n&&gt(e,i,{get:()=>t[i],enumerable:!(r=Ir(t,i))||r.enumerable});return e};var jr=e=>Or(gt({},"__esModule",{value:!0}),e);var Ui={};Lr(Ui,{FilesetResolver:()=>ne,LlmInference:()=>A,TaskRunner:()=>Ze});var de=typeof self<"u"?self:{};function jn(e){e:{for(var t=["CLOSURE_FLAGS"],n=de,r=0;r<t.length;r++)if((n=n[t[r]])==null){t=null;break e}t=n}return(e=t&&t[e])!=null&&e}var kr,xr=typeof TextEncoder<"u";function kn(e){if(xr)e=(kr||=new TextEncoder).encode(e);else{let n=0,r=new Uint8Array(3*e.length);for(let i=0;i<e.length;i++){var t=e.charCodeAt(i);if(t<128)r[n++]=t;else{if(t<2048)r[n++]=t>>6|192;else{if(t>=55296&&t<=57343){if(t<=56319&&i<e.length){let o=e.charCodeAt(++i);if(o>=56320&&o<=57343){t=1024*(t-55296)+o-56320+65536,r[n++]=t>>18|240,r[n++]=t>>12&63|128,r[n++]=t>>6&63|128,r[n++]=63&t|128;continue}i--}t=65533}r[n++]=t>>12|224,r[n++]=t>>6&63|128}r[n++]=63&t|128}}e=n===r.length?r:r.subarray(0,n)}return e}var It,Ur=jn(610401301),Wt=jn(748402147);function $t(){var e=de.navigator;return e&&(e=e.userAgent)?e:""}var Ht=de.navigator;It=Ht&&Ht.userAgentData||null;var xn={},Te=null;function Br(e){let t=e.length,n=3*t/4;n%3?n=Math.floor(n):"=.".indexOf(e[t-1])!=-1&&(n="=.".indexOf(e[t-2])!=-1?n-2:n-1);let r=new Uint8Array(n),i=0;return function(o,s){function a(c){for(;u<o.length;){let l=o.charAt(u++),p=Te[l];if(p!=null)return p;if(!/^[\s\xa0]*$/.test(l))throw Error("Unknown base64 encoding at char: "+l)}return c}Un();let u=0;for(;;){let c=a(-1),l=a(0),p=a(64),d=a(64);if(d===64&&c===-1)break;s(c<<2|l>>4),p!=64&&(s(l<<4&240|p>>2),d!=64&&s(p<<6&192|d))}}(e,function(o){r[i++]=o}),i!==n?r.subarray(0,i):r}function Un(){if(!Te){Te={};var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),t=["+/=","+/","-_=","-_.","-_"];for(let n=0;n<5;n++){let r=e.concat(t[n].split(""));xn[n]=r;for(let i=0;i<r.length;i++){let o=r[i];Te[o]===void 0&&(Te[o]=i)}}}}var Nr=typeof Uint8Array<"u",Bn=!(!(Ur&&It&&It.brands.length>0)&&($t().indexOf("Trident")!=-1||$t().indexOf("MSIE")!=-1))&&typeof btoa=="function",qt=/[-_.]/g,Fr={"-":"+",_:"/",".":"="};function Dr(e){return Fr[e]||""}function Kt(e){if(!Bn)return Br(e);e=qt.test(e)?e.replace(qt,Dr):e,e=atob(e);let t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function Tt(e){return Nr&&e!=null&&e instanceof Uint8Array}var Be={};function _t(){return Rr||=new H(null,Be)}var H=class{constructor(e,t){if(Nn(t),this.i=e,e!=null&&e.length===0)throw Error("ByteString should be constructed with non-empty values")}},Rr,Mr;function Nn(e){if(e!==Be)throw Error("illegal external caller")}function Fn(e,t){e.__closure__error__context__984382||(e.__closure__error__context__984382={}),e.__closure__error__context__984382.severity=t}function Ne(e){return Fn(e=Error(e),"warning"),e}function He(e,t){if(e!=null){var n=Mr??={},r=n[e]||0;r>=t||(n[e]=r+1,Fn(e=Error(),"incident"),function(i){de.setTimeout(()=>{throw i},0)}(e))}}var et=typeof Symbol=="function"&&typeof Symbol()=="symbol";function Me(e,t,n=!1){return typeof Symbol=="function"&&typeof Symbol()=="symbol"?n&&Symbol.for&&e?Symbol.for(e):e!=null?Symbol(e):Symbol():t}var Vr=Me("jas",void 0,!0),Ee=Me(void 0,"1oa"),Pt=Me(void 0,"0ubsb"),Cr=Me(void 0,"0actk"),tt=Me("m_m","na",!0),Dn={fa:{value:0,configurable:!0,writable:!0,enumerable:!1}},Rn=Object.defineProperties,m=et?Vr:"fa",pe,Yt=[];function Mn(e,t){et||m in e||Rn(e,Dn),e[m]|=t}function O(e,t){et||m in e||Rn(e,Dn),e[m]=t}function Nt(){return typeof BigInt=="function"}O(Yt,7),pe=Object.freeze(Yt);var nt={};function R(e,t){return t===void 0?e.i!==me&&!!(2&(0|e.m[m])):!!(2&t)&&e.i!==me}var me={},Gr=Object.freeze({});function rt(e){return e.ma=!0,e}var zr=rt(e=>typeof e=="number"),Vn=rt(e=>typeof e=="string"),Wr=rt(e=>typeof e=="boolean"),it=typeof de.BigInt=="function"&&typeof de.BigInt(0)=="bigint",$r=rt(e=>it?e>=qr&&e<=Yr:e[0]==="-"?Jt(e,Hr):Jt(e,Kr)),Hr=Number.MIN_SAFE_INTEGER.toString(),qr=it?BigInt(Number.MIN_SAFE_INTEGER):void 0,Kr=Number.MAX_SAFE_INTEGER.toString(),Yr=it?BigInt(Number.MAX_SAFE_INTEGER):void 0;function Jt(e,t){if(e.length>t.length)return!1;if(e.length<t.length||e===t)return!0;for(let n=0;n<e.length;n++){let r=e[n],i=t[n];if(r>i)return!1;if(r<i)return!0}}var Jr,y=0,b=0;function Xt(e){let t=e>>>0;y=t,b=(e-t)/4294967296>>>0}function ge(e){if(e<0){Xt(-e);let[t,n]=Ft(y,b);y=t>>>0,b=n>>>0}else Xt(e)}function Cn(e,t){let n=4294967296*t+(e>>>0);return Number.isSafeInteger(n)?n:Fe(e,t)}function Fe(e,t){if(e>>>=0,(t>>>=0)<=2097151)var n=""+(4294967296*t+e);else Nt()?n=""+(BigInt(t)<<BigInt(32)|BigInt(e)):(e=(16777215&e)+6777216*(n=16777215&(e>>>24|t<<8))+6710656*(t=t>>16&65535),n+=8147497*t,t*=2,e>=1e7&&(n+=e/1e7>>>0,e%=1e7),n>=1e7&&(t+=n/1e7>>>0,n%=1e7),n=t+Zt(n)+Zt(e));return n}function Zt(e){return e=String(e),"0000000".slice(e.length)+e}function ot(e){if(e.length<16)ge(Number(e));else if(Nt())e=BigInt(e),y=Number(e&BigInt(4294967295))>>>0,b=Number(e>>BigInt(32)&BigInt(4294967295));else{let t=+(e[0]==="-");b=y=0;let n=e.length;for(let r=t,i=(n-t)%6+t;i<=n;r=i,i+=6){let o=Number(e.slice(r,i));b*=1e6,y=1e6*y+o,y>=4294967296&&(b+=Math.trunc(y/4294967296),b>>>=0,y>>>=0)}if(t){let[r,i]=Ft(y,b);y=r,b=i}}}function Ft(e,t){return t=~t,e?e=1+~e:t+=1,[e,t]}function Le(e){return Array.prototype.slice.call(e)}var Xr=typeof BigInt=="function"?BigInt.asIntN:void 0,Zr=typeof BigInt=="function"?BigInt.asUintN:void 0,Oe=Number.isSafeInteger,we=Number.isFinite,qe=Math.trunc;function yt(e){if(e!=null&&typeof e!="number")throw Error(`Value of float/double field must be a number, found ${typeof e}: ${e}`);return e}function Gn(e){return e==null||typeof e=="number"?e:e==="NaN"||e==="Infinity"||e==="-Infinity"?Number(e):void 0}function re(e){if(e!=null&&typeof e!="boolean"){var t=typeof e;throw Error(`Expected boolean but got ${t!="object"?t:e?Array.isArray(e)?"array":t:"null"}: ${e}`)}return e}function Q(e){return e==null||typeof e=="boolean"?e:typeof e=="number"?!!e:void 0}var Qr=/^-?([1-9][0-9]*|0)(\.[0-9]+)?$/;function zn(e){switch(typeof e){case"bigint":return!0;case"number":return we(e);case"string":return Qr.test(e);default:return!1}}function Wn(e){if(typeof e!="number"||!we(e))throw Ne("int32");return 0|e}function Lt(e){return e==null?e:Wn(e)}function ve(e){if(e==null)return e;if(typeof e=="string"&&e)e=+e;else if(typeof e!="number")return;return we(e)?0|e:void 0}function Ke(e){if(e==null)return e;if(typeof e=="string"&&e)e=+e;else if(typeof e!="number")return;return we(e)?e>>>0:void 0}function Qt(e){if(e[0]==="-")return!1;let t=e.length;return t<20||t===20&&Number(e.substring(0,6))<184467}function ei(e){if(e==null)return e;var t=typeof e;if(t==="bigint")return String(Zr(64,e));if(zn(e)){if(t==="string")return t=qe(Number(e)),Oe(t)&&t>=0?e=String(t):((t=e.indexOf("."))!==-1&&(e=e.substring(0,t)),Qt(e)||(ot(e),e=Fe(y,b))),e;if(t==="number")return(e=qe(e))>=0&&Oe(e)?e:function(n){if(n<0){ge(n);var r=Fe(y,b);return n=Number(r),Oe(n)?n:r}return Qt(r=String(n))?r:(ge(n),Cn(y,b))}(e)}}function Dt(e){return e==null||typeof e=="string"?e:void 0}function $n(e,t,n){if(e!=null&&e[tt]===nt)return e;if(Array.isArray(e)){var r=0|e[m];return(n=r|32&n|2&n)!==r&&O(e,n),new t(e)}}function st(e,t,n,r){var i=r!==void 0;r=!!r;let o=[];var s=e.length;let a,u=4294967295,c=!1,l=!!(64&t),p=l?128&t?0:-1:void 0;for(1&t||(a=s&&e[s-1],a!=null&&typeof a=="object"&&a.constructor===Object?u=--s:a=void 0,!l||128&t||i||(c=!0,u=u-p+p)),t=void 0,i=0;i<s;i++){let d=e[i];if(d!=null&&(d=n(d,r))!=null)if(l&&i>=u){let _=i-p;(t??={})[_]=d}else o[i]=d}if(a)for(let d in a){if((e=a[d])==null||(e=n(e,r))==null)continue;let _;s=+d,l&&!Number.isNaN(s)&&(_=s+p)<u?o[_]=e:(t??={})[d]=e}return t&&(c?o.push(t):o[u]=t),o}function Rt(e){switch(typeof e){case"number":return Number.isFinite(e)?e:""+e;case"bigint":return $r(e)?Number(e):""+e;case"boolean":return e?1:0;case"object":if(Array.isArray(e)){var t=0|e[m];return e.length===0&&1&t?void 0:st(e,t,Rt)}if(e!=null&&e[tt]===nt)return Hn(e);if(e instanceof H){if((t=e.i)==null)e="";else if(typeof t=="string")e=t;else{if(Bn){for(var n="",r=0,i=t.length-10240;r<i;)n+=String.fromCharCode.apply(null,t.subarray(r,r+=10240));n+=String.fromCharCode.apply(null,r?t.subarray(r):t),t=btoa(n)}else{n===void 0&&(n=0),Un(),n=xn[n],r=Array(Math.floor(t.length/3)),i=n[64]||"";let c=0,l=0;for(;c<t.length-2;c+=3){var o=t[c],s=t[c+1],a=t[c+2],u=n[o>>2];o=n[(3&o)<<4|s>>4],s=n[(15&s)<<2|a>>6],a=n[63&a],r[l++]=u+o+s+a}switch(u=0,a=i,t.length-c){case 2:a=n[(15&(u=t[c+1]))<<2]||i;case 1:t=t[c],r[l]=n[t>>2]+n[(3&t)<<4|u>>4]+a+i}t=r.join("")}e=e.i=t}return e}return}return e}function Hn(e){return st(e=e.m,0|e[m],Rt)}var ti,ni;function ri(e,t,n){return qn(e,t[0],t[1],n?1:2)}function qn(e,t,n,r=0){if(e==null){var i=32;n?(e=[n],i|=128):e=[],t&&(i=-8380417&i|(1023&t)<<13)}else{if(!Array.isArray(e))throw Error("narr");if(i=0|e[m],Wt&&1&i)throw Error("rfarr");if(2048&i&&!(2&i)&&function(){if(Wt)throw Error("carr");He(Cr,5)}(),256&i)throw Error("farr");if(64&i)return r!==0||2048&i||O(e,2048|i),e;if(n&&(i|=128,n!==e[0]))throw Error("mid");e:{i|=64;var o=(n=e).length;if(o){var s=o-1;let u=n[s];if(u!=null&&typeof u=="object"&&u.constructor===Object){if((s-=t=128&i?0:-1)>=1024)throw Error("pvtlmt");for(var a in u)(o=+a)<s&&(n[o+t]=u[a],delete u[a]);i=-8380417&i|(1023&s)<<13;break e}}if(t){if((a=Math.max(t,o-(128&i?0:-1)))>1024)throw Error("spvt");i=-8380417&i|(1023&a)<<13}}}return i|=64,r===0&&(i|=2048),O(e,i),e}function ii(e,t){if(typeof e!="object")return e;if(Array.isArray(e)){var n=0|e[m];return e.length===0&&1&n?e=void 0:2&n||(!t||4096&n||16&n?e=Ye(e,n,!1,t&&!(16&n)):(Mn(e,34),4&n&&Object.freeze(e))),e}return e!=null&&e[tt]===nt?R(e,n=0|(t=e.m)[m])?e:Yn(e,t,n)?Kn(e,t):Ye(t,n):e instanceof H?e:void 0}function Kn(e,t,n){return e=new e.constructor(t),n&&(e.i=me),e.o=me,e}function Ye(e,t,n,r){return r??=!!(34&t),e=st(e,t,ii,r),r=32,n&&(r|=2),O(e,t=8380609&t|r),e}function at(e){if(e.i!==me)return!1;var t=e.m;return Mn(t=Ye(t,0|t[m]),2048),e.m=t,e.i=void 0,e.o=void 0,!0}function Se(e){if(!at(e)&&R(e,0|e.m[m]))throw Error()}function _e(e,t){t===void 0&&(t=0|e[m]),32&t&&!(4096&t)&&O(e,4096|t)}function Yn(e,t,n){return!!(2&n)||!(!(32&n)||4096&n)&&(O(t,2|n),e.i=me,!0)}function N(e,t,n){if((e=ut(e.m,t,void 0,n))!==null)return e}function ut(e,t,n,r){if(t===-1)return null;let i=t+(n?0:-1),o=e.length-1,s,a;if(!(o<1+(n?0:-1))){if(i>=o)if(s=e[o],s!=null&&typeof s=="object"&&s.constructor===Object)n=s[t],a=!0;else{if(i!==o)return;n=s}else n=e[i];if(r&&n!=null){if((r=r(n))==null)return r;if(!Object.is(r,n))return a?s[t]=r:e[i]=r,r}return n}}function ie(e,t,n){Se(e),C(e=e.m,0|e[m],t,n)}function C(e,t,n,r,i){let o=n+(i?0:-1);var s=e.length-1;if(s>=1+(i?0:-1)&&o>=s){let a=e[s];if(a!=null&&typeof a=="object"&&a.constructor===Object)return a[n]=r,t}return o<=s?(e[o]=r,t):(r!==void 0&&(n>=(s=(t??=0|e[m])>>13&1023||536870912)?r!=null&&(e[s+(i?0:-1)]={[n]:r}):e[o]=r),t)}function Jn(e,t,n,r,i){let o=e.m,s=0|o[m];r=R(e,s)?1:r,i=!!i||r===3,r===2&&at(e)&&(o=e.m,s=0|o[m]);let a=(e=Zn(o,t))===pe?7:0|e[m],u=Qn(a,s);var c=!(4&u);if(c){4&u&&(e=Le(e),a=0,u=je(u,s),s=C(o,s,t,e));let l=0,p=0;for(;l<e.length;l++){let d=n(e[l]);d!=null&&(e[p++]=d)}p<l&&(e.length=p),n=-513&(4|u),u=n&=-1025,u&=-4097}return u!==a&&(O(e,u),2&u&&Object.freeze(e)),Xn(e,u,o,s,t,r,c,i)}function Xn(e,t,n,r,i,o,s,a){let u=t;return o===1||o===4&&(2&t||!(16&t)&&32&r)?$e(t)||((t|=!e.length||s&&!(4096&t)||32&r&&!(4096&t||16&t)?2:256)!==u&&O(e,t),Object.freeze(e)):(o===2&&$e(t)&&(e=Le(e),u=0,t=je(t,r),r=C(n,r,i,e)),$e(t)||(a||(t|=16),t!==u&&O(e,t))),2&t||!(4096&t||16&t)||_e(n,r),e}function Zn(e,t,n){return e=ut(e,t,n),Array.isArray(e)?e:pe}function Qn(e,t){return 2&t&&(e|=2),1|e}function $e(e){return!!(2&e)&&!!(4&e)||!!(256&e)}function er(e,t,n){Se(e);let r=0|(e=e.m)[m];if(n==null)C(e,r,t);else{var i=n===pe?7:0|n[m],o=i,s=$e(i),a=s||Object.isFrozen(n);for(s||(i=0),a||(n=Le(n),o=0,i=je(i,r),a=!1),i|=5,s=0;s<n.length;s++){let u=n[s],c=Wn(u);Object.is(u,c)||(a&&(n=Le(n),o=0,i=je(i,r),a=!1),n[s]=c)}i!==o&&(a&&(n=Le(n),i=je(i,r)),O(n,i)),C(e,r,t,n)}}function B(e,t,n,r){Se(e),C(e=e.m,0|e[m],t,(r==="0"?Number(n)===0:n===r)?void 0:n)}function en(e){if(et)return e[Ee]??(e[Ee]=new Map);if(Ee in e)return e[Ee];let t=new Map;return Object.defineProperty(e,Ee,{value:t}),t}function tn(e,t,n){var r=Qe;let i=e.get(r);if(i!=null)return i;i=0;for(let o=0;o<r.length;o++){let s=r[o];ut(t,s)!=null&&(i!==0&&(n=C(t,n,i)),i=s)}return e.set(r,i),i}function De(e,t,n){let r=e.m,i=0|r[m];if(t=function(a,u,c,l){let p=!1;if((l=ut(a,l,void 0,d=>{let _=$n(d,c,u);return p=_!==d&&_!=null,_}))!=null)return p&&!R(l)&&_e(a,u),l}(r,i,t,n),t==null)return t;if(i=0|r[m],!R(e,i)){var o,s=t;let a=s.m,u=0|a[m];(o=R(s,u)?Yn(s,a,u)?Kn(s,a,!0):new s.constructor(Ye(a,u,!1)):s)!==t&&(at(e)&&(r=e.m,i=0|r[m]),i=C(r,i,n,t=o),_e(r,i))}return t}function tr(e){return e==null&&(e=void 0),e}function Z(e,t,n){return ie(e,t,n=tr(n)),n&&!R(n)&&_e(e.m),e}function je(e,t){return-273&(2&t?2|e:-3&e)}function Pe(e,t,n,r){var i=r;Se(e);var o=r=e.m,s=0|r[m];let a=R(e,s)?1:2;a===2&&at(e)&&(s=0|(o=e.m)[m]);let u=(e=Zn(o,t))===pe?7:0|e[m];var c=Qn(u,s);let l=!(4&c);if(l){var p=e,d=s;let _=!!(2&c);_&&(d|=2);let k=!_,M=!0,x=0,oe=0;for(;x<p.length;x++){let W=$n(p[x],n,d);if(W instanceof n){if(!_){let se=R(W);k&&=!se,M&&=se}p[oe++]=W}}oe<x&&(p.length=oe),c|=4,c=M?-4097&c:4096|c,c=k?8|c:-9&c}c!==u&&(O(e,c),2&c&&Object.freeze(e)),t=e=Xn(e,c,o,s,t,a,l,!0),i=i??new n,t.push(i),o=n=t===pe?7:0|t[m],(i=R(i))?(n&=-9,t.length===1&&(n&=-4097)):n|=4096,n!==o&&O(t,n),i||_e(r)}function T(e,t){return Ke(N(e,t))??0}function V(e,t,n){B(e,t,Lt(n),0)}function Ae(e,t,n){if(n!=null){if(typeof n!="number"||!we(n))throw Ne("uint32");n>>>=0}ie(e,t,n)}function P(e,t,n){if(n!=null&&typeof n!="string")throw Error();B(e,t,n,"")}function f(e,t,n){if(Se(e),t=(e=Jn(e,t,Dt,2,!0)).push,typeof n!="string")throw Error();t.call(e,n)}var ae=class{constructor(e,t,n){if(this.buffer=e,n&&!t)throw Error()}};function nn(e){if(typeof e=="string")return new ae(Kt(e),!0);if(Array.isArray(e))return new ae(new Uint8Array(e),!0);if(e.constructor===Uint8Array)return new ae(e,!1);if(e.constructor===ArrayBuffer)return e=new Uint8Array(e),new ae(e,!1);if(e.constructor===H){Nn(Be);var t=e.i;return t=((t=t==null||Tt(t)?t:typeof t=="string"?Kt(t):null)==null?t:e.i=t)||new Uint8Array(0),new ae(t,!0,e)}if(e instanceof Uint8Array)return e=e.constructor===Uint8Array?e:new Uint8Array(e.buffer,e.byteOffset,e.byteLength),new ae(e,!1);throw Error()}function rn(e){return e?/^\d+$/.test(e)?(ot(e),new Ot(y,b)):null:oi||=new Ot(0,0)}var Ot=class{constructor(e,t){this.j=e>>>0,this.i=t>>>0}},oi;function on(e){return e?/^-?\d+$/.test(e)?(ot(e),new jt(y,b)):null:si||=new jt(0,0)}var jt=class{constructor(e,t){this.j=e>>>0,this.i=t>>>0}},si;function he(e,t,n){for(;n>0||t>127;)e.i.push(127&t|128),t=(t>>>7|n<<25)>>>0,n>>>=7;e.i.push(t)}function ct(e,t){for(;t>127;)e.i.push(127&t|128),t>>>=7;e.i.push(t)}function lt(e,t){if(t>=0)ct(e,t);else{for(let n=0;n<9;n++)e.i.push(127&t|128),t>>=7;e.i.push(1)}}function Je(e,t){t.length!==0&&(e.l.push(t),e.j+=t.length)}function K(e,t,n){ct(e.i,8*t+n)}function ht(e,t){return K(e,t,2),t=e.i.end(),Je(e,t),t.push(e.j),t}function ft(e,t){var n=t.pop();for(n=e.j+e.i.length()-n;n>127;)t.push(127&n|128),n>>>=7,e.j++;t.push(n),e.j++}function Xe(e,t,n){K(e,t,2),ct(e.i,n.length),Je(e,e.i.end()),Je(e,n)}function G(){let e=class{constructor(){throw Error()}};return Object.setPrototypeOf(e,e.prototype),e}var Ve=G(),nr=G(),dt=G(),pt=G(),ai=G(),ui=G(),ci=G(),rr=G(),li=G(),Mt=G(),v=class{constructor(e,t){this.m=qn(e,t)}toJSON(){return Hn(this)}};v.prototype[tt]=nt,v.prototype.toString=function(){return this.m.toString()};var z=class{constructor(e,t){this.i=e,e=Ve,this.j=!!e&&t===e||!1}};function ir(e,t,n,r,i){(t=sr(t,r))!=null&&(n=ht(e,n),i(t,e),ft(e,n))}var hi=new z(ir,Ve),fi=new z(ir,Ve),sn=Symbol(),an=Symbol(),or;function mt(e){var t=di,n=pi,r=e[sn];if(r)return r;(r={}).la=e,r.W=function(l){switch(typeof l){case"boolean":return ti||=[0,void 0,!0];case"number":return l>0?void 0:l===0?ni||=[0,void 0]:[-l,void 0];case"string":return[0,l];case"object":return l}}(e[0]);var i=e[1];let o=1;i&&i.constructor===Object&&(r.ba=i,typeof(i=e[++o])=="function"&&(r.ga=!0,or??=e[o+1],i=e[o+=2]));let s={};for(;i&&Array.isArray(i)&&i.length&&typeof i[0]=="number"&&i[0]>0;){for(var a=0;a<i.length;a++)s[i[a]]=i;i=e[++o]}for(a=1;i!==void 0;){let l;typeof i=="number"&&(a+=i,i=e[++o]);var u=void 0;if(i instanceof z?l=i:(l=hi,o--),l?.j){i=e[++o],u=e;var c=o;typeof i=="function"&&(i=i(),u[c]=i),u=i}for(c=a+1,typeof(i=e[++o])=="number"&&i<0&&(c-=i,i=e[++o]);a<c;a++)u?n(r,a,l,u):t(r,a,l)}return e[sn]=r}function sr(e,t){return e instanceof v?e.m:Array.isArray(e)?ri(e,t,!1):void 0}function di(e,t,n){e[t]=n.i}function pi(e,t,n,r){let i,o,s=n.i;e[t]=(a,u,c)=>s(a,u,c,o||=mt(r).W,i||=ar(r))}function ar(e){let t=e[an];if(!t){let n=mt(e);t=(r,i)=>ur(r,i,n),e[an]=t}return t}function ur(e,t,n){(function(r,i,o){let s=128&i?0:-1,a=r.length;var u;(u=!!a)&&(u=(u=r[a-1])!=null&&typeof u=="object"&&u.constructor===Object);let c=a+(u?-1:0);for(i=128&i?1:0;i<c;i++)o(i-s,r[i]);if(u){r=r[a-1];for(let l in r)!isNaN(l)&&o(+l,r[l])}})(e,0|e[m],(r,i)=>{if(i!=null){var o=function(s,a){var u=s[a];if(u)return u;if((u=s.ba)&&(u=u[a])){var c=(u=Array.isArray(u)?u[0]instanceof z?u:[fi,u]:[u,void 0])[0].i;if(u=u[1]){let l=ar(u),p=mt(u).W;u=s.ga?or(p,l):(d,_,k)=>c(d,_,k,p,l)}else u=c;return s[a]=u}}(n,r);o?o(t,i,r):r<500||He(Pt,3)}})}var bt,te=0,ue=te;if(Vn(ue)){if(!/^\s*(?:-?[1-9]\d*|0)?\s*$/.test(ue))throw Error(String(ue))}else if((bt=zr(ue))&&(bt=!Number.isSafeInteger(ue)),bt)throw Error(String(ue));function Vt(e,t){if(Array.isArray(t)){var n=0|t[m];if(4&n)return t;for(var r=0,i=0;r<t.length;r++){let o=e(t[r]);o!=null&&(t[i++]=o)}return i<r&&(t.length=i),O(t,-1537&(5|n)),2&n&&Object.freeze(t),t}}function I(e,t){return new z(e,t)}function cr(e,t,n){(t=Gn(t))!=null&&(K(e,n,5),e=e.i,(n=Jr||=new DataView(new ArrayBuffer(8))).setFloat32(0,+t,!0),b=0,t=y=n.getUint32(0,!0),e.i.push(t>>>0&255),e.i.push(t>>>8&255),e.i.push(t>>>16&255),e.i.push(t>>>24&255))}function Ct(e,t,n){(t=ve(t))!=null&&t!=null&&(K(e,n,0),lt(e.i,t))}function lr(e,t,n){(t=Q(t))!=null&&(K(e,n,0),e.i.i.push(t?1:0))}function Gt(e,t,n){(t=Dt(t))!=null&&Xe(e,n,kn(t))}function hr(e,t,n,r,i){(t=sr(t,r))!=null&&(n=ht(e,n),i(t,e),ft(e,n))}function fr(e,t,n){(t=ve(t))!=null&&(t=parseInt(t,10),K(e,n,0),lt(e.i,t))}it||(te=Wr(te)?te?"1":"0":Vn(te)?te.trim()||"0":String(te));var ye,Ge=I(cr,rr),kt=I(cr,rr),wt=I(function(e,t,n){if(t=function(r){if(r==null)return r;var i=typeof r;if(i==="bigint")return String(Xr(64,r));if(zn(r)){if(i==="string"){if(i=qe(Number(r)),Oe(i))r=String(i);else if((i=r.indexOf("."))!==-1&&(r=r.substring(0,i)),i=r.length,!(r[0]==="-"?i<20||i===20&&Number(r.substring(0,7))>-922337:i<19||i===19&&Number(r.substring(0,6))<922337))if(ot(r),r=y,2147483648&(i=b))if(Nt())r=""+(BigInt(0|i)<<BigInt(32)|BigInt(r>>>0));else{let[s,a]=Ft(r,i);r="-"+Fe(s,a)}else r=Fe(r,i);return r}if(i==="number"){if(r=qe(r),!Oe(r)){ge(r),i=y;var o=b;(r=2147483648&o)&&(o=~o>>>0,(i=1+~i>>>0)==0&&(o=o+1>>>0)),r=typeof(i=Cn(i,o))=="number"?r?-i:i:r?"-"+i:i}return r}}}(t),t!=null&&(typeof t=="string"&&on(t),t!=null))switch(K(e,n,0),typeof t){case"number":e=e.i,ge(t),he(e,y,b);break;case"bigint":n=BigInt.asUintN(64,t),n=new jt(Number(n&BigInt(4294967295)),Number(n>>BigInt(32))),he(e.i,n.j,n.i);break;default:n=on(t),he(e.i,n.j,n.i)}},ui),mi=I(function(e,t,n){if((t=ei(t))!=null&&(typeof t=="string"&&rn(t),t!=null))switch(K(e,n,0),typeof t){case"number":e=e.i,ge(t),he(e,y,b);break;case"bigint":n=BigInt.asUintN(64,t),n=new Ot(Number(n&BigInt(4294967295)),Number(n>>BigInt(32))),he(e.i,n.j,n.i);break;default:n=rn(t),he(e.i,n.j,n.i)}},ci),D=I(Ct,pt);ye=new z(function(e,t,n){if((t=Vt(ve,t))!=null&&t.length){n=ht(e,n);for(let r=0;r<t.length;r++)lt(e.i,t[r]);ft(e,n)}},pt);var L,g=I(Ct,pt),gi=I(Ct,pt),S=I(lr,nr),w=I(lr,nr),E=I(Gt,dt);L=new z(function(e,t,n){if((t=Vt(Dt,t))!=null)for(let s=0;s<t.length;s++){var r=e,i=n,o=t[s];o!=null&&Xe(r,i,kn(o))}},dt);var zt,j=I(Gt,dt),dr=I(Gt,dt),F=function(e,t,n=Ve){return new z(t,n)}(0,function(e,t,n,r,i){if(Array.isArray(t))for(let o=0;o<t.length;o++)hr(e,t[o],n,r,i)}),U=new z(hr,Ve),_i=I(function(e,t,n){(t=Ke(t))!=null&&t!=null&&(K(e,n,0),ct(e.i,t))},ai),X=I(fr,Mt);zt=new z(function(e,t,n){if((t=Vt(ve,t))!=null&&t.length){n=ht(e,n);for(let r=0;r<t.length;r++)lt(e.i,t[r]);ft(e,n)}},Mt);var q=I(fr,Mt);function Ce(e){return function(){let t=new class{constructor(){this.l=[],this.j=0,this.i=new class{constructor(){this.i=[]}length(){return this.i.length}end(){let s=this.i;return this.i=[],s}}}};ur(this.m,t,mt(e)),Je(t,t.i.end());let n=new Uint8Array(t.j),r=t.l,i=r.length,o=0;for(let s=0;s<i;s++){let a=r[s];n.set(a,o),o+=a.length}return t.l=[n],n}}function vt(e,t){if(t!=null)if(Array.isArray(t))ie(e,2,st(t,0,Rt));else{if(!(typeof t=="string"||t instanceof H||Tt(t)))throw Error("invalid value in Any.value field: "+t+" expected a ByteString, a base64 encoded string, a Uint8Array or a jspb array");if(t!=null){if(typeof t=="string")t=t?new H(t,Be):_t();else if(t.constructor!==H){if(!Tt(t))throw Error();t=t.length?new H(new Uint8Array(t),Be):_t()}}B(e,2,t,_t())}}var ce=class extends v{constructor(e){super(e)}},un=[0,j,I(function(e,t,n){if(t!=null){if(t instanceof v){let r=t.oa;return void(r?(t=r(t),t!=null&&Xe(e,n,nn(t).buffer)):He(Pt,3))}if(Array.isArray(t))return void He(Pt,3)}(t=t==null||typeof t=="string"||t instanceof H?t:void 0)!=null&&Xe(e,n,nn(t).buffer)},li)],St,cn=globalThis.trustedTypes;function ln(e){var t;return St===void 0&&(St=function(){let n=null;if(!cn)return n;try{let r=i=>i;n=cn.createPolicy("goog#html",{createHTML:r,createScript:r,createScriptURL:r})}catch{}return n}()),e=(t=St)?t.createScriptURL(e):e,new class{constructor(n){this.i=n}toString(){return this.i+""}}(e)}function yi(e,...t){if(t.length===0)return ln(e[0]);let n=e[0];for(let r=0;r<t.length;r++)n+=encodeURIComponent(t[r])+e[r+1];return ln(n)}var pr={};pr[336783863]=[0,E,S,-1,D,[0,[1,2,3,4,5,6,7,8,9],U,[0],U,[0,S,E,S,X,-1,zt,E,-1,[0,S,-1],X,S,-1],U,[0,E,-2],U,[0,D,S,1,S,-3],U,[0,D,X,S,-1,ye,X,-1,S],U,[0,E,-2],U,[0,E,X],U,[0,X,E,-1,S],U,[0,X,-1]],[0,E],S,[0,[1,3],[2,4],U,[0,ye],-1,U,[0,L],-1,F,[0,E,-1]],E];var hn=class extends v{constructor(e){super(e)}},fn=[0,wt,-1,w,-3,wt,ye,j,g,wt,-1,w,g,w,-2,j],$=class extends v{constructor(e){super(e,500)}N(e){return Z(this,7,e)}},ke=[-1,{}],dn=[0,E,1,ke],pn=[0,E,L,ke];function Y(e,t){Pe(e,1,$,t)}var mr=class extends v{constructor(e){super(e,500)}N(e){return Z(this,1001,e)}};mr.prototype.j=Ce([-500,F,[-500,j,-1,L,-3,[-2,pr,S],F,un,g,-1,dn,pn,F,[0,j,w],j,fn,g,L,987,L],4,F,[-500,E,-1,[-1,{}],998,E],F,[-500,E,L,-1,[-2,{},S],997,L,-1],g,F,[-500,E,L,ke,998,L],L,g,dn,pn,F,[0,j,-1,ke],L,-2,fn,j,-1,w,[0,w,_i],978,ke,F,un]);var mn=class extends v{constructor(e){super(e)}},ze,bi=new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11]);async function gr(){if(ze===void 0)try{await WebAssembly.instantiate(bi),ze=!0}catch{ze=!1}return ze}async function Ie(e,t=yi``){let n=await gr()?"wasm_internal":"wasm_nosimd_internal";return{wasmLoaderPath:`${t}/${e}_${n}.js`,wasmBinaryPath:`${t}/${e}_${n}.wasm`}}var ne=class{};function gn(e){function t(s,a){return new ReadableStream({start(){},async pull(u){i=i.then(async()=>{if(s.cache.length>0)u.enqueue(s.cache.shift());else{var{value:c,done:l}=await e.read();c&&(a.active&&a.cache.push(c),s.active&&u.enqueue(c)),l&&u.close()}}),await i},cancel(){s.active=!1,s.cache.length=0,a.active||e.cancel()}})}var n={cache:[],active:!0};let r={cache:[],active:!0},i=Promise.resolve(),o=t(n,r);return n=t(r,n),[o.getReader(),n.getReader()]}async function _n(e,t){let n=new Uint8Array(t),r=0;for(;r<t;){let{value:i,done:o}=await e.read();if(i){let s=i.subarray(0,t-r);n.set(s,r),r+=s.length}if(o)throw Error(`Expected ${t} bytes, but stream ended after reading ${r} bytes.`)}return await e.cancel(),n}ne.forVisionTasks=function(e){return Ie("vision",e)},ne.forTextTasks=function(e){return Ie("text",e)},ne.forGenAiExperimentalTasks=function(e){return Ie("genai_experimental",e)},ne.forGenAiTasks=function(e){return Ie("genai",e)},ne.forAudioTasks=function(e){return Ie("audio",e)},ne.isSimdSupported=function(){return gr()};var wi=[[0,async e=>{let t=new TextEncoder().encode("TFL3").length;return e=await _n(e,t+4),new TextDecoder("utf-8").decode(e.subarray(4,t+4))==="TFL3"}],[1,async e=>(e=await _n(e,6))[4]===80&&e[5]===75]];function vi(){var e=navigator;return typeof OffscreenCanvas<"u"&&(!function(t=navigator){return(t=t.userAgent).includes("Safari")&&!t.includes("Chrome")}(e)||!!((e=e.userAgent.match(/Version\/([\d]+).*Safari/))&&e.length>=1&&Number(e[1])>=17))}async function yn(e){if(typeof importScripts!="function"){let t=document.createElement("script");return t.src=e.toString(),t.crossOrigin="anonymous",new Promise((n,r)=>{t.addEventListener("load",()=>{n()},!1),t.addEventListener("error",i=>{r(i)},!1),document.body.appendChild(t)})}importScripts(e.toString())}function h(e,t,n){e.o||console.error("No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target"),n(t=e.h.stringToNewUTF8(t)),e.h._free(t)}function bn(e,t,n){e.o||console.error("No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target");let r=new Uint32Array(t.length);for(let i=0;i<t.length;i++)r[i]=e.h.stringToNewUTF8(t[i]);t=e.h._malloc(4*r.length),e.h.HEAPU32.set(r,t>>2),n(t);for(let i of r)e.h._free(i);e.h._free(t)}function J(e,t,n){e.h.simpleListeners=e.h.simpleListeners||{},e.h.simpleListeners[t]=n}function ee(e,t,n){let r=[];e.h.simpleListeners=e.h.simpleListeners||{},e.h.simpleListeners[t]=(i,o,s)=>{o?(n(r,s),r=[]):r.push(i)}}var Si=(wn=class{constructor(e,t){this.l=!0,this.h=e,this.i=null,this.j=0,this.o=typeof this.h._addIntToInputStream=="function",t!==void 0?this.h.canvas=t:vi()?this.h.canvas=new OffscreenCanvas(1,1):(console.warn("OffscreenCanvas not supported and GraphRunner constructor glCanvas parameter is undefined. Creating backup canvas."),this.h.canvas=document.createElement("canvas"))}async initializeGraph(e){let t=await(await fetch(e)).arrayBuffer();e=!(e.endsWith(".pbtxt")||e.endsWith(".textproto")),this.setGraph(new Uint8Array(t),e)}setGraphFromString(e){this.setGraph(new TextEncoder().encode(e),!1)}setGraph(e,t){let n=e.length,r=this.h._malloc(n);this.h.HEAPU8.set(e,r),t?this.h._changeBinaryGraph(n,r):this.h._changeTextGraph(n,r),this.h._free(r)}configureAudio(e,t,n,r,i){this.h._configureAudio||console.warn('Attempting to use configureAudio without support for input audio. Is build dep ":gl_graph_runner_audio" missing?'),h(this,r||"input_audio",o=>{h(this,i=i||"audio_header",s=>{this.h._configureAudio(o,s,e,t??0,n)})})}setAutoResizeCanvas(e){this.l=e}setAutoRenderToScreen(e){this.h._setAutoRenderToScreen(e)}setGpuBufferVerticalFlip(e){this.h.gpuOriginForWebTexturesIsBottomLeft=e}attachErrorListener(e){this.h.errorListener=e}attachEmptyPacketListener(e,t){this.h.emptyPacketListeners=this.h.emptyPacketListeners||{},this.h.emptyPacketListeners[e]=t}addAudioToStream(e,t,n){this.addAudioToStreamWithShape(e,0,0,t,n)}addAudioToStreamWithShape(e,t,n,r,i){let o=4*e.length;this.j!==o&&(this.i&&this.h._free(this.i),this.i=this.h._malloc(o),this.j=o),this.h.HEAPF32.set(e,this.i/4),h(this,r,s=>{this.h._addAudioToInputStream(this.i,t,n,s,i)})}addGpuBufferToStream(e,t,n){h(this,t,r=>{if(!this.h.canvas)throw Error("No OpenGL canvas configured.");r?this.h._bindTextureToStream(r):this.h._bindTextureToCanvas();let i=this.h.canvas.getContext("webgl2")||this.h.canvas.getContext("webgl");if(!i)throw Error("Failed to obtain WebGL context from the provided canvas. `getContext()` should only be invoked with `webgl` or `webgl2`.");this.h.gpuOriginForWebTexturesIsBottomLeft&&i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!0),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,e),this.h.gpuOriginForWebTexturesIsBottomLeft&&i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!1);let[o,s]=e.videoWidth!==void 0?[e.videoWidth,e.videoHeight]:e.naturalWidth!==void 0?[e.naturalWidth,e.naturalHeight]:e.displayWidth!==void 0?[e.displayWidth,e.displayHeight]:[e.width,e.height];!this.l||o===this.h.canvas.width&&s===this.h.canvas.height||(this.h.canvas.width=o,this.h.canvas.height=s);let[a,u]=[o,s];this.h._addBoundTextureToStream(r,a,u,n)})}addBoolToStream(e,t,n){h(this,t,r=>{this.h._addBoolToInputStream(e,r,n)})}addDoubleToStream(e,t,n){h(this,t,r=>{this.h._addDoubleToInputStream(e,r,n)})}addFloatToStream(e,t,n){h(this,t,r=>{this.h._addFloatToInputStream(e,r,n)})}addIntToStream(e,t,n){h(this,t,r=>{this.h._addIntToInputStream(e,r,n)})}addUintToStream(e,t,n){h(this,t,r=>{this.h._addUintToInputStream(e,r,n)})}addStringToStream(e,t,n){h(this,t,r=>{h(this,e,i=>{this.h._addStringToInputStream(i,r,n)})})}addStringRecordToStream(e,t,n){h(this,t,r=>{bn(this,Object.keys(e),i=>{bn(this,Object.values(e),o=>{this.h._addFlatHashMapToInputStream(i,o,Object.keys(e).length,r,n)})})})}addProtoToStream(e,t,n,r){h(this,n,i=>{h(this,t,o=>{let s=this.h._malloc(e.length);this.h.HEAPU8.set(e,s),this.h._addProtoToInputStream(s,e.length,o,i,r),this.h._free(s)})})}addEmptyPacketToStream(e,t){h(this,e,n=>{this.h._addEmptyPacketToInputStream(n,t)})}addBoolVectorToStream(e,t,n){h(this,t,r=>{let i=this.h._allocateBoolVector(e.length);if(!i)throw Error("Unable to allocate new bool vector on heap.");for(let o of e)this.h._addBoolVectorEntry(i,o);this.h._addBoolVectorToInputStream(i,r,n)})}addDoubleVectorToStream(e,t,n){h(this,t,r=>{let i=this.h._allocateDoubleVector(e.length);if(!i)throw Error("Unable to allocate new double vector on heap.");for(let o of e)this.h._addDoubleVectorEntry(i,o);this.h._addDoubleVectorToInputStream(i,r,n)})}addFloatVectorToStream(e,t,n){h(this,t,r=>{let i=this.h._allocateFloatVector(e.length);if(!i)throw Error("Unable to allocate new float vector on heap.");for(let o of e)this.h._addFloatVectorEntry(i,o);this.h._addFloatVectorToInputStream(i,r,n)})}addIntVectorToStream(e,t,n){h(this,t,r=>{let i=this.h._allocateIntVector(e.length);if(!i)throw Error("Unable to allocate new int vector on heap.");for(let o of e)this.h._addIntVectorEntry(i,o);this.h._addIntVectorToInputStream(i,r,n)})}addUintVectorToStream(e,t,n){h(this,t,r=>{let i=this.h._allocateUintVector(e.length);if(!i)throw Error("Unable to allocate new unsigned int vector on heap.");for(let o of e)this.h._addUintVectorEntry(i,o);this.h._addUintVectorToInputStream(i,r,n)})}addStringVectorToStream(e,t,n){h(this,t,r=>{let i=this.h._allocateStringVector(e.length);if(!i)throw Error("Unable to allocate new string vector on heap.");for(let o of e)h(this,o,s=>{this.h._addStringVectorEntry(i,s)});this.h._addStringVectorToInputStream(i,r,n)})}addBoolToInputSidePacket(e,t){h(this,t,n=>{this.h._addBoolToInputSidePacket(e,n)})}addDoubleToInputSidePacket(e,t){h(this,t,n=>{this.h._addDoubleToInputSidePacket(e,n)})}addFloatToInputSidePacket(e,t){h(this,t,n=>{this.h._addFloatToInputSidePacket(e,n)})}addIntToInputSidePacket(e,t){h(this,t,n=>{this.h._addIntToInputSidePacket(e,n)})}addUintToInputSidePacket(e,t){h(this,t,n=>{this.h._addUintToInputSidePacket(e,n)})}addStringToInputSidePacket(e,t){h(this,t,n=>{h(this,e,r=>{this.h._addStringToInputSidePacket(r,n)})})}addProtoToInputSidePacket(e,t,n){h(this,n,r=>{h(this,t,i=>{let o=this.h._malloc(e.length);this.h.HEAPU8.set(e,o),this.h._addProtoToInputSidePacket(o,e.length,i,r),this.h._free(o)})})}addBoolVectorToInputSidePacket(e,t){h(this,t,n=>{let r=this.h._allocateBoolVector(e.length);if(!r)throw Error("Unable to allocate new bool vector on heap.");for(let i of e)this.h._addBoolVectorEntry(r,i);this.h._addBoolVectorToInputSidePacket(r,n)})}addDoubleVectorToInputSidePacket(e,t){h(this,t,n=>{let r=this.h._allocateDoubleVector(e.length);if(!r)throw Error("Unable to allocate new double vector on heap.");for(let i of e)this.h._addDoubleVectorEntry(r,i);this.h._addDoubleVectorToInputSidePacket(r,n)})}addFloatVectorToInputSidePacket(e,t){h(this,t,n=>{let r=this.h._allocateFloatVector(e.length);if(!r)throw Error("Unable to allocate new float vector on heap.");for(let i of e)this.h._addFloatVectorEntry(r,i);this.h._addFloatVectorToInputSidePacket(r,n)})}addIntVectorToInputSidePacket(e,t){h(this,t,n=>{let r=this.h._allocateIntVector(e.length);if(!r)throw Error("Unable to allocate new int vector on heap.");for(let i of e)this.h._addIntVectorEntry(r,i);this.h._addIntVectorToInputSidePacket(r,n)})}addUintVectorToInputSidePacket(e,t){h(this,t,n=>{let r=this.h._allocateUintVector(e.length);if(!r)throw Error("Unable to allocate new unsigned int vector on heap.");for(let i of e)this.h._addUintVectorEntry(r,i);this.h._addUintVectorToInputSidePacket(r,n)})}addStringVectorToInputSidePacket(e,t){h(this,t,n=>{let r=this.h._allocateStringVector(e.length);if(!r)throw Error("Unable to allocate new string vector on heap.");for(let i of e)h(this,i,o=>{this.h._addStringVectorEntry(r,o)});this.h._addStringVectorToInputSidePacket(r,n)})}attachBoolListener(e,t){J(this,e,t),h(this,e,n=>{this.h._attachBoolListener(n)})}attachBoolVectorListener(e,t){ee(this,e,t),h(this,e,n=>{this.h._attachBoolVectorListener(n)})}attachIntListener(e,t){J(this,e,t),h(this,e,n=>{this.h._attachIntListener(n)})}attachIntVectorListener(e,t){ee(this,e,t),h(this,e,n=>{this.h._attachIntVectorListener(n)})}attachUintListener(e,t){J(this,e,t),h(this,e,n=>{this.h._attachUintListener(n)})}attachUintVectorListener(e,t){ee(this,e,t),h(this,e,n=>{this.h._attachUintVectorListener(n)})}attachDoubleListener(e,t){J(this,e,t),h(this,e,n=>{this.h._attachDoubleListener(n)})}attachDoubleVectorListener(e,t){ee(this,e,t),h(this,e,n=>{this.h._attachDoubleVectorListener(n)})}attachFloatListener(e,t){J(this,e,t),h(this,e,n=>{this.h._attachFloatListener(n)})}attachFloatVectorListener(e,t){ee(this,e,t),h(this,e,n=>{this.h._attachFloatVectorListener(n)})}attachStringListener(e,t){J(this,e,t),h(this,e,n=>{this.h._attachStringListener(n)})}attachStringVectorListener(e,t){ee(this,e,t),h(this,e,n=>{this.h._attachStringVectorListener(n)})}attachProtoListener(e,t,n){J(this,e,t),h(this,e,r=>{this.h._attachProtoListener(r,n||!1)})}attachProtoVectorListener(e,t,n){ee(this,e,t),h(this,e,r=>{this.h._attachProtoVectorListener(r,n||!1)})}attachAudioListener(e,t,n){this.h._attachAudioListener||console.warn('Attempting to use attachAudioListener without support for output audio. Is build dep ":gl_graph_runner_audio_out" missing?'),J(this,e,(r,i)=>{r=new Float32Array(r.buffer,r.byteOffset,r.length/4),t(r,i)}),h(this,e,r=>{this.h._attachAudioListener(r,n||!1)})}finishProcessing(){this.h._waitUntilIdle()}closeGraph(){this.h._closeGraph(),this.h.simpleListeners=void 0,this.h.emptyPacketListeners=void 0}},class extends wn{ia(){this.h._registerModelResourcesGraphService()}}),wn;async function Ei(e,t){let n=await(async(r,i,o)=>{var s=A;if(r&&await yn(r),!self.ModuleFactory||i&&(await yn(i),!self.ModuleFactory))throw Error("ModuleFactory not set.");return self.Module&&o&&((r=self.Module).locateFile=o.locateFile,o.mainScriptUrlOrBlob&&(r.mainScriptUrlOrBlob=o.mainScriptUrlOrBlob)),o=await self.ModuleFactory(self.Module||o),self.ModuleFactory=self.Module=void 0,new s(o,null)})(e.wasmLoaderPath,e.assetLoaderPath,{locateFile:r=>r.endsWith(".wasm")?e.wasmBinaryPath.toString():e.assetBinaryPath&&r.endsWith(".data")?e.assetBinaryPath.toString():r});return await n.N(t),n}async function Et(e,t){return Ei(e,t)}function vn(e){try{let t=e.J.length;if(t===1)throw Error(e.J[0].message);if(t>1)throw Error("Encountered multiple errors: "+e.J.map(n=>n.message).join(", "))}finally{e.J=[]}}function le(e,t){e.I=Math.max(e.I,t)}var Ze=class{constructor(e){this.j=e,this.J=[],this.I=0,this.j.setAutoRenderToScreen(!1)}setGraph(e,t){this.j.attachErrorListener((n,r)=>{this.J.push(Error(r))}),this.j.ia(),this.j.setGraph(e,t),vn(this)}finishProcessing(){this.j.finishProcessing(),vn(this)}close(){this.j.closeGraph()}};Ze.prototype.close=Ze.prototype.close;var be=class extends v{constructor(e){super(e)}j(){return ve(N(this,2))??0}};function Sn(e,t){Z(e,1,t)}var Ai=class extends v{constructor(e){super(e)}},_r=[0,q,g,kt,-1,D];function Ii(e,t,n,r){if(e.data!==void 0){var i=new Uint8Array(e.data.buffer,t,n);return r===1&&function(o,s,a){o.i.push([s,a]),o.i.sort((u,c)=>u[0]-c[0]),s=0;for(let[u,c]of o.i){let l=c;(a=u)<=s&&(s=Math.max(s,a+l))}s===o.length&&(o.data=void 0)}(e,t,n),i}}be.prototype.l=Ce(_r);var xt=class{constructor(t){this.i=[],this.data=t,this.length=t.length}};function yr(e,t){return new Ti(async()=>{let{value:n,done:r}=await e.read();return r?void 0:n},t)}async function En(e,t,n,r,i){if(i===2)return e.i=[],e.j=()=>Promise.resolve(void 0),setTimeout(()=>{e.l()},0),Promise.resolve(0);for(;e.size<n+r;){var o=await e.j();if(o===void 0)break;e.i.push(new xt(o))}if(e.size<n+r)throw Error(`Data size is too small: ${e.size}, expected at least ${n+r}.`);o=t._malloc(r)>>>0;let s=0;for(let a=0;a<e.i.length;a++){let u=e.i[a];if(n>=u.length){n-=u.length;continue}let c=Math.min(r,u.length-n);if((n=Ii(u,n,c,i))===void 0)throw Error("Data has already been released.");if(t.HEAPU8.set(n,o+s),n=0,s+=c,(r-=c)===0)break}if(r!==0)throw Error("Data not found.");return Promise.resolve(o)}var Ti=class{constructor(e,t){this.i=[],this.j=e,this.l=t}get size(){let e=0;for(let t=0;t<this.i.length;t++)e+=this.i[t].length;return e}};function xe(e){return typeof e=="object"&&e!=null&&"imageSource"in e}function Ue(e){return typeof e=="object"&&e!=null&&"audioSource"in e}async function An(e,t,n){e=new wr(e,n);let r=0;for(t=t.getReader();;){let{value:i,done:o}=await t.read();if(o)break;e.set(i,r),r+=i.byteLength}if(n!==r)throw br(e),Error(`File could not be fully loaded to memory, so was not retained. Loaded ${r}/${n} bytes before failure`);return e}function br(e){if(e.i)try{e.h._free(e.j)}catch{}finally{e.i=!1}}var wr=class{constructor(e,t){this.h=e,this.l=t,this.j=this.h._malloc(t)>>>0,this.o=this.h.HEAPU8,this.i=!!this.j}get offset(){if(!this.i)throw Error("WasmFileReference has been freed.");return this.j}get size(){if(!this.i)throw Error("WasmFileReference has been freed.");return this.l}set(e,t){this.o.set(e,this.j+(t??0))}},vr=class extends v{constructor(e){super(e)}};vr.prototype.j=Ce([0,j,2,L,g,w]);var Pi=class extends v{constructor(e){super(e)}},Li=class extends v{constructor(e){super(e)}},Oi=class extends v{constructor(e){super(e)}},Sr=class extends v{constructor(e){super(e)}},At=[0,g,-6,1,g,1,[0,w,q,-2],[0,w,kt],q,-2,[0,w,-1,q,kt,X,D,S,-1],1,w,g,D,-1,[0,q,g],w,-1,Ge,g,-5,Ge,-1,[0,D,Ge],D,S,[0,D,-2],Ge,[0,g],[0,g,-4],S,D,-2,S],In=[0,j,-2],Tn=[0,[4,6],At,g,1,gi,L,dr,zt,In,D,[0,[0,g,-1,F,[0,g,[0,g,-1],-1,[0,q,-1],w],w,-2,g,-1],[0,g,-1,w],At,w,g,[0,g]],E,-3,[0,g,w],At,[0,In,-2],ye];Sr.prototype.j=Ce([0,j,8,[0,w,-6],1,g,1,g,[0,F,[0,j,mi,-1,q],Tn,g],[0,g,w,-3],1,q,1,Tn,1,g,5,q,ye,1,_r,w,g]);var ji=class extends v{constructor(e){super(e)}},Er=class extends v{constructor(e){super(e)}},Qe=[2,4];Er.prototype.j=Ce([0,Qe,g,dr,g,U,[0,1,j]]);var ki=function(e){return class extends e{constructor(){super(...arguments),this.P=!1,this.F=this.H=0}M(){if(this.P)throw Error("Cannot process because LLM inference engine is currently loading or processing.");this.P=!0}L(){this.P=!1}async createLlmInferenceEngine(t,n){this.M();try{let r=yr(t,()=>{});await this.h.createLlmInferenceEngine(T(n,2)??512,De(n,be,3)?.j()??40,Q(N(n,6))??!1??!1,T(n,7)??0,Q(N(n,8))??!1??!1,(i,o,s)=>En(r,this.h,i,o,s))}finally{this.L()}}async aa(t,n){this.M();try{await this.ka(t),await this.h.ccall("CreateLlmInferenceEngineConverted","void",["number","number","boolean"],[T(n,2)??512,De(n,be,3)?.j()??40,Q(N(n,6))??!1??!1],{async:!0})}finally{this.L()}}V(){this.M();try{let t=this.h;t.ccall("DeleteLlmInferenceEngine","void",[],[],{async:!1}),this.H&&(t._FreeSession(this.H),this.F===this.H&&(this.F=0),this.H=0),this.F&&(t._FreeSession(this.F),this.F=0)}finally{this.L()}}async R(t,n,r){this.M();try{let i=[],o=this.h;o._userProgressListener=(d,_)=>{d&&i.push(d),r&&r(d,_)};let s=n.l(),a=s.length,u=this.h._malloc(a);this.h.HEAPU8.set(s,u);let c=t.some(Ue),l=t.some(xe);o.ccallNum=o.ccall;let p=await o.ccallNum("MakeSessionForPredict","number",["number","number","boolean","boolean"],[u,a,l,c],{async:!0});n=[];for(let d of t)if(typeof d=="string")h(this,d,_=>{o._AddTextQueryChunk(p,_)});else if(xe(d)){let{image:_,width:k,height:M}=await this.da(d.imageSource),x=typeof OffscreenCanvas<"u"?new OffscreenCanvas(k,M):document.createElement("canvas");x.width=k,x.height=M;let oe=x.getContext("2d");oe.drawImage(_,0,0);let W=oe.getImageData(0,0,k,M),se=this.h._malloc(W.width*W.height*4);this.h.HEAPU8.set(W.data,se),o._AddImageQueryChunk(p,se,W.width,W.height),n.push(se)}else{if(!Ue(d))throw Error("Unsupported PromptPart type in query.");{let _=await fetch(d.audioSource);if(!_.ok)throw Error(`Audio fetch for ${d.audioSource} had error: ${_.status}`);let k=await _.arrayBuffer(),M=new Uint8Array(k),x=this.h._malloc(M.length);this.h.HEAPU8.set(M,x),o._AddAudioQueryChunk(p,x,M.length),n.push(x)}}await o.ccall("PredictSession","void",["number"],[p],{async:!0}),t=!0,l&&this.F===0&&(this.F=p,t=!1),c&&this.H===0&&(this.H=p,t=!1),t&&o._FreeSession(p);for(let d of n)this.h._free(d);return n.length=0,r&&r("",!0),this.h._free(u),o._userProgressListener=void 0,i.join("")}finally{this.L()}}S(t){this.M();let n=0,r="";for(let i of t)typeof i=="string"?r+=i:xe(i)?n+=260:Ue(i)&&console.warn("sizeInTokens is not yet implemented for audio; audio tokens will not be counted");try{let i;return h(this,r,o=>{i=this.h._GetSizeInTokens(o)}),n+i}finally{this.L()}}async ka(t){t=await async function(n){let r=[];for(var i=0;;){let{done:o,value:s}=await n.read();if(o)break;r.push(s),i+=s.length}if(r.length===0)return new Uint8Array(0);if(r.length===1)return r[0];n=new Uint8Array(i),i=0;for(let o of r)n.set(o,i),i+=o.length;return n}(t);try{this.h.FS_unlink("llm.task")}catch{}this.h.FS_createDataFile("/","llm.task",t,!0,!1,!1)}async da(t){if(typeof t=="string"){let n=new Image;n.src=t,n.crossOrigin="Anonymous";try{await n.decode()}catch{throw Error(`Image from URL ${t} failed to load`)}return{image:n,width:n.naturalWidth,height:n.naturalHeight}}if(t instanceof HTMLImageElement){try{await t.decode()}catch{throw Error("Image from HTMLImageElement failed to load")}return{image:t,width:t.naturalWidth,height:t.naturalHeight}}return t instanceof HTMLVideoElement?{image:t,width:t.videoWidth,height:t.videoHeight}:t instanceof VideoFrame?{image:t,width:t.displayWidth,height:t.displayHeight}:{image:t,width:t.width,height:t.height}}}}(function(e){return class Ar extends e{static async ja(n,r){let i;r||=await Ar.X();let o=[];for(let s of n?.requiredFeatures??[])r.features.has(s)?o.push(s):console.warn(`WebGPU feature ${s} is not supported.`);n={...n,requiredFeatures:o};try{i=await r.requestDevice(n)}catch(s){throw console.error("Unable to initialize WebGPU with the requested features."),s}return(n=i).adapterInfo||(n.adapterInfo=r.info),i}static async X(n){if(!(n=await navigator.gpu.requestAdapter(n)))throw Error("Unable to request adapter from navigator.gpu; Ensure WebGPU is enabled.");return n}ea(n){if(r)typeof HTMLCanvasElement<"u"&&r instanceof HTMLCanvasElement&&(r.id="canvas_webgpu");else var r=new OffscreenCanvas(1,1);r.getContext("webgpu").configure({device:n,format:navigator.gpu.getPreferredCanvasFormat()}),this.h.preinitializedWebGPUDevice=n}Z(){return this.h.ccall("closeGraph","void",[],[],{async:!0})}}}(function(e){return class extends e{addStreamingReaderToInputSidePacket(t,n){this.h.addStreamingReaderToInputSidePacket((r,i,o)=>En(t,this.h,r,i,o),n)}}}(function(e){return class extends e{Y(t,n){h(this,"lora_model_ref_in",r=>{this.h._addRawDataSpanToInputStream(t.offset,t.size,r,n)})}}}(class extends Si{})))),Re=class extends ki{},Ut=class{constructor(e){this.j=e,this.i=Pn,Pn++}},Pn=1,Bt=class{constructor(){let t,n;this.promise=new Promise((r,i)=>{t=r,n=i}),this.resolve=t,this.reject=n}};function Ln(e){return e===1?1:e+e%2}async function We(){let e=await Re.X({powerPreference:"high-performance"});var t=e.limits.maxBufferSize,n=e.limits.maxStorageBufferBindingSize;return t<524550144&&console.warn(`This WebGPU device is unable to execute most LLM tasks, because the required maxBufferSize is usually at least 524550144, but your device only supports maxBufferSize of ${t}`),n<524550144&&console.warn(`The WebGPU device is unable to execute LLM tasks, because the required maxStorageBufferBindingSize is usually at least 524550144, but your device only supports maxStorageBufferBindingSize of ${n}`),t={requiredFeatures:["shader-f16"],requiredLimits:{maxStorageBufferBindingSize:n,maxBufferSize:t,maxStorageBuffersPerShaderStage:e.limits.maxStorageBuffersPerShaderStage}},e.features.has("subgroups")&&(console.warn("Experimental Chromium WGSL subgroup support detected. Enabling this feature in the inference engine."),n=["shader-f16","subgroups"],e.features.has("subgroups-f16")&&n.push("subgroups-f16"),t.requiredFeatures=n),Re.ja(t,e)}function fe(e){if(e.D.length>0){let t=[...e.D];if(e.D.length=0,!e.o)throw t;e.o.reject(t),e.o=void 0}}function xi(e){let t=function(r){let i=new mr;f(i,10,"text_in"),f(i,10,"token_cost_in"),f(i,10,"lora_model_id_to_apply_in"),f(i,10,"lora_model_ref_in"),f(i,10,"lora_model_id_to_load_in"),f(i,16,"streaming_reader"),f(i,15,"text_out"),f(i,15,"text_end"),f(i,15,"token_cost_out");var o=new $;P(o,2,"TokenizerInputBuildCalculator"),f(o,3,"PROMPT:text_in"),f(o,3,"LORA_ID:lora_model_id_to_apply_in"),f(o,4,"prompt"),Y(i,o),P(o=new $,2,"ModelDataCalculator"),f(o,6,"MODEL_DATA:__side_packet_1"),f(o,6,"MODEL_TYPE:model_type"),f(o,5,"READ_DATA_FN:streaming_reader"),f(o,3,"LORA_MODEL_SPAN:lora_model_ref_in"),f(o,3,"LORA_MODEL_ID:lora_model_id_to_load_in"),f(o,4,"LORA_DATA:lora_model_data"),Y(i,o),P(o=new $,2,"Gpt2UnicodeMappingCalculator"),f(o,5,"MODEL_TYPE:model_type"),f(o,6,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),Y(i,o),P(o=new ce,1,"type.googleapis.com/odml.infra.proto.TokenizerCalculatorOptions");var s=new Er,a=T(r.i,2);V(s,1,a),P(a=new ji,2,"spm_vocab_model"),a=tr(a);e:{Se(s);var u=s.m,c=0|u[m];if(a==null){var l=en(u);if(tn(l,u,c)!==4)break e;l.set(Qe,0)}else{let p=en(l=u),d=tn(p,l,c);d!==4&&(d&&(c=C(l,c,d)),p.set(Qe,4))}C(u,c,4,a)}return a&&!R(a)&&_e(s.m),V(s,3,2),vt(o,s.j()),P(s=new $,2,"TokenizerCalculator"),Pe(s,8,ce,o),f(s,5,"MODEL_DATA:__side_packet_1"),f(s,3,"PROMPT_AND_INPUT_OPTIONS:prompt"),f(s,5,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),f(s,6,"PROCESSOR_GETTER:__input_side_1"),f(s,4,"IDS_AND_INPUT_OPTIONS:__stream_0"),Y(i,s),P(o=new ce,1,"type.googleapis.com/odml.infra.proto.LlmGpuCalculatorOptions"),V(s=new Sr,12,3),P(s,1,"llm.tflite"),V(s,14,0),a=Ln(T(r.i,5)),V(s,22,a),a=De(r.i,be,3),Z(s,31,a),B(a=new Pi,1,re(!0),!1),Q(N(r.i,6))!=null&&(Q(N(r.i,6))??!1)&&B(a,1,re(!1),!1),B(a,2,re(!0),!1),B(a,5,re(!0),!1),Z(s,10,a),a=Jn(r.i,4,ve,Gr===void 0?2:4),er(s,29,a),a=new Oi,V(u=new Li,1,1),l=T(r.i,2),V(u,2,l),Z(a,1,u),Z(s,20,a),vt(o,s.j()),P(s=new $,2,"LlmGpuCalculator"),Pe(s,8,ce,o),f(s,3,"IDS_AND_INPUT_OPTIONS:__stream_0"),f(s,3,"FINISH:finish"),f(s,3,"LORA_DATA:lora_model_data"),f(s,5,"MODEL_DATA:__side_packet_1"),f(s,4,"DECODED_IDS:__stream_3"),f(s,4,"OUTPUT_END:__stream_4"),P(o=new hn,1,"FINISH"),B(o,2,re(!0),!1),Pe(s,13,hn,o),Y(i,s),P(o=new $,2,"IsPacketPresentCalculator"),f(o,3,"__stream_4"),f(o,4,"text_end"),Y(i,o),P(o=new ce,1,"type.googleapis.com/odml.infra.proto.DetokenizerCalculatorOptions"),s=new vr,r=Ln(T(r.i,5)),V(s,5,r),f(s,4,"<eos>"),f(s,4,"<|endoftext|>"),vt(o,s.j()),P(r=new $,2,"DetokenizerCalculator"),Pe(r,8,ce,o),f(r,3,"IDS_AND_INPUT_OPTIONS:__stream_3"),f(r,5,"PROCESSOR_GETTER:__input_side_1"),f(r,5,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),f(r,5,"MODEL_DATA:__side_packet_1"),f(r,4,"FINISH_AND_INPUT_OPTIONS:finish"),f(r,4,"WORDS:text_out"),Y(i,r),P(r=new $,2,"TokenCostCalculator"),f(r,3,"PROMPT:token_cost_in"),f(r,5,"PROCESSOR_GETTER:__input_side_1"),f(r,5,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),f(r,4,"NUM_TOKENS:token_cost_out"),Y(i,r),i}(e);e.j.attachStringVectorListener("text_out",(r,i)=>{r=function(o,s){return o==null||o.length===0?[]:o.map(a=>(a=(a=a.replaceAll("\u2581"," ")).replaceAll("<0x0A>",`
2
+ `),s&&(a=a.trimStart()),a.split("\\[eod\\]",1)[0]))}(r,e.G.length===0),r.forEach((o,s)=>{s<T(e.i,5)&&e.G[s].push(o)}),e.v&&e.D.length===0&&(e.A?(r.length>T(e.i,5)&&r.pop(),e.v(r,!1)):e.v(r[0],!1)),le(e,i)}),e.j.attachEmptyPacketListener("text_out",r=>{le(e,r)}),e.j.attachBoolListener("text_end",(r,i)=>{le(e,i);try{fe(e)}catch(o){throw e.l=!1,o}if(e.o&&(e.o.resolve(e.G.map(o=>o.join(""))),e.o=void 0),e.v)if(e.A){for(r=[],i=0;i<T(e.i,5);i++)r.push("");e.v(r,!0)}else e.v("",!0);e.l=!1,e.A=void 0}),e.j.attachEmptyPacketListener("text_end",r=>{e.l=!1,e.A=void 0,le(e,r),fe(e),e.o&&(e.o.resolve(e.G.map(i=>i.join(""))),e.o=void 0)}),e.j.attachIntListener("token_cost_out",(r,i)=>{e.T=r,le(e,i)}),e.U&&e.j.addStreamingReaderToInputSidePacket(e.U,"streaming_reader");let n=t.j();return e.C?.removeEventListener("uncapturederror",e.K),e.j.Z().then(()=>{e.C?.addEventListener("uncapturederror",e.K),e.D.length=0,e.setGraph(new Uint8Array(n),!0),e.finishProcessing()})}function On(e,t,n,r){if(e.v=typeof n=="function"?n:r,(r=(t=Array.isArray(t)?t:[t]).filter(i=>xe(i)).length)>0&&(Ke(N(e.i,7))==null||T(e.i,7)<r))throw Error(`maxNumImages is set to ${Ke(N(e.i,7))!=null?T(e.i,7):0}, but the query included ${r} images.`);if((r=t.filter(i=>Ue(i)).length)>0&&(Q(N(e.i,8))==null||!Q(N(e.i,8))))throw Error(`supportAudio was not enabled, but the query included ${r} audio chunks.`);if(e.B){if(e.A&&T(e.i,5)>1)throw Error("Multi-response generation is not supported for converted LLM models (.task format) yet, nor is it supported for multimodality. Please use the .bin format without multimodality or request only one response.");if(n instanceof Ut)throw Error("LoRA is not supported for converted LLM models (.task format) yet, nor is it supported for multimodality. Please use the .bin format without multimodality to use LoRA.");return e.j.R(t,e.u,(i,o)=>{e.D.length===0&&e.v&&(e.A?e.v([i],o):e.v(i,o))}).then(i=>(fe(e),[i]))}if(e.l)throw Error("Previous invocation or loading is still ongoing.");for(e.l=!0,e.G.length=0,r=0;r<T(e.i,5);r++)e.G[r]=[];if(r=e.I+1,e.j.addStringToStream(t.join(""),"text_in",r),n instanceof Ut){if(n.j!==e)throw e.l=!1,e.A=void 0,Error("The LoRA model was not loaded by this LLM Inference task.");e.j.addUintToStream(n.i,"lora_model_id_to_apply_in",r)}else e.j.addEmptyPacketToStream("lora_model_id_to_apply_in",r);return e.finishProcessing(),e.o=new Bt,e.o.promise}var A=class extends Ze{constructor(e,t){if(super(new Re(e,t)),this.G=[],this.O=this.B=this.l=!1,this.D=[],this.K=n=>{if((n=n.error).message.match(/exceeds the max buffer size limit/))throw Error(`Failed to run this LLM model because it requires a buffer size that exceeds the maximum size your device supports, but you could try a smaller LLM model or different device.
3
+ WebGPU throws: "${n.message}"`);if(n.message.match(/is larger than the maximum storage buffer binding size/))throw Error(`Failed to run this LLM model because it requires a storage buffer binding size that exceeds the maximum size your device supports, but you could try a smaller LLM model or different device.
4
+ WebGPU throws: "${n.message}"`);this.D.push(n)},this.i=new Ai,Sn(this.i,new mn),this.u=new be,Z(this.i,3,this.u),Ae(this.i,2,512),e=this.u,!we(2))throw Ne("enum");B(e,1,2,0),V(this.u,2,40),B(this.u,3,yt(1),0),ie(this.u,5,Lt(0)),B(this.u,4,yt(.8),0),Ae(this.i,5,1)}async N(e){if(this.l)throw Error("Cannot set options while loading or processing.");if(e.baseOptions?.modelAssetPath&&e.baseOptions?.modelAssetBuffer)throw Error("Cannot set both baseOptions.modelAssetPath and baseOptions.modelAssetBuffer");let t,n=new Promise(s=>{t=s});if(e.baseOptions?.modelAssetPath){var r=await fetch(e.baseOptions.modelAssetPath.toString());if(!r.ok)throw Error(`Failed to fetch model: ${e.baseOptions.modelAssetPath} (${r.status})`);if(!r.body)throw Error(`Failed to fetch model: ${e.baseOptions.modelAssetPath} (no body)`);r=r.body.getReader()}else e.baseOptions?.modelAssetBuffer instanceof Uint8Array?r=function(s){return new ReadableStream({start(){},async pull(a){a.enqueue(s),a.close()}})}(e.baseOptions.modelAssetBuffer).getReader():e.baseOptions?.modelAssetBuffer instanceof ReadableStreamDefaultReader?(r=e.baseOptions.modelAssetBuffer,e.baseOptions.modelAssetBuffer=void 0):t();if(!r)throw Error("No model asset provided.");{let[s,a]=gn(r);this.O=await async function(u){let c=[],l;for(let[d,_]of wi){let k=d;var p=_;[u,l]=gn(u),p=await p(l),await l.cancel(),p&&c.push(k)}if(await u.cancel(),c.length===0)throw Error("No model format matched.");if(c.length===1)return c[0];throw Error(`Multiple model formats matched: ${c}`)}(a)===1;var i="maxNumImages"in e&&e.maxNumImages?e.maxNumImages:0;Ae(this.i,7,i);var o="supportAudio"in e&&!!e.supportAudio;ie(this.i,8,re(o)),this.O||i>0||o?(this.B=!0,r=s):(this.B=!1,this.U=yr(s,t))}if(e.baseOptions?.gpuOptions?.device&&(this.C&&this.C.removeEventListener("uncapturederror",this.K),this.C=e.baseOptions.gpuOptions.device,this.j.ea(this.C),this.C.addEventListener("uncapturederror",this.K)),"maxTokens"in e&&Ae(this.i,2,e.maxTokens??512),"topK"in e&&V(this.u,2,e.topK??40),"temperature"in e&&B(this.u,4,yt(e.temperature??.8),0),"randomSeed"in e&&ie(this.u,5,Lt(e.randomSeed??0)),"loraRanks"in e&&function(s,a){er(s,4,a)}(this.i,e.loraRanks??[]),"numResponses"in e){if((i=e.numResponses??1)<1)throw Error("'numResponses' must be at least 1.");if(this.B&&i>1)throw Error("'numResponses > 1' is not supported for converted LLM models yet, and is also not supported with multimodality.");Ae(this.i,5,i),o=De(this.i,be,3),i>1&&o&&(o.j()<=1||(N(o,4,Gn)??0)<=0)&&console.warn("To generate multiple responses, it is expected topK > 1 and temperature > 0; otherwise, all the generated responses may be the same.")}return"forceF32"in e&&e.forceF32!==void 0&&ie(this.i,6,re(e.forceF32)),this.B?(this.j.V(),this.O?this.j.aa(r,this.i).then(()=>{fe(this)}):this.j.createLlmInferenceEngine(r,this.i).then(()=>{fe(this)})):(this.l=!0,e=xi(this).then(()=>{}),Promise.all([n,e]).then(()=>{this.l=!1,fe(this)}))}get baseOptions(){return De(this.i,mn,1)}set baseOptions(e){Sn(this.i,e)}get isIdle(){return!this.l&&!this.o}R(e,t,n){return T(this.i,5)>1&&console.warn("'numResponses' is set larger than 1 and this function only returns the first response, so we recommend either using 'generateResponses()' to obtain multiple responses, or else setting 'numResponses' to 1 for better performance."),this.A=!1,On(this,e,t,n).then(r=>r[0])}ca(e,t,n){return this.A=!0,On(this,e,t,n)}S(e){if(e=Array.isArray(e)?e:[e],this.B)return this.j.S(e);if(this.l)throw Error("Previous invocation or loading is still ongoing.");if(e.some(xe))throw Error("sizeInTokens requires maxNumImages > 0 for images.");if(e.some(Ue))throw Error("sizeInTokens requires supportAudio for audio.");return e=e.join(""),this.l=!0,this.T=void 0,this.j.addStringToStream(e,"token_cost_in",this.I+1),this.finishProcessing(),this.l=!1,this.T}async ha(e){if(this.B)throw Error("LoRA is not supported for converted LLM models (.task format) yet, nor is it supported for multimodality. Please use the old format (.bin) without multimodality to use LoRA.");if(this.l)throw Error("Cannot load LoRA model while loading or processing.");if(this.l=!0,e instanceof Uint8Array){var t=new wr(this.j.h,e.length);t.set(e),e=t}else e=e instanceof Blob?await async function(r,i){return An(r,i.stream(),i.size)}(this.j.h,e):await async function(r,i){i=await fetch(i.toString());let o=Number(i.headers.get("content-length"));if(!i.body)throw Error("Response body is not available.");if(!o)throw Error("File size is 0.");return An(r,i.body,o)}(this.j.h,e);t=new Ut(this);let n=this.I+1;return this.j.Y(e,n),this.j.addUintToStream(t.i,"lora_model_id_to_load_in",n),this.finishProcessing(),br(e),le(this,n),this.l=!1,t}close(){this.B&&this.j.V(),this.C?.removeEventListener("uncapturederror",this.K),super.close()}};A.prototype.loadLoraModel=A.prototype.ha,A.prototype.sizeInTokens=A.prototype.S,A.prototype.generateResponses=A.prototype.ca,A.prototype.generateResponse=A.prototype.R,A.prototype.setOptions=A.prototype.N,A.createWebGpuDevice=We,A.createFromModelPath=async function(e,t){return Et(e,t={baseOptions:{gpuOptions:{device:await We()},modelAssetPath:t}})},A.createFromModelBuffer=async function(e,t){return Et(e,t={baseOptions:{gpuOptions:{device:await We()},modelAssetBuffer:t}})},A.createFromOptions=async function(e,t){if(!t.baseOptions?.gpuOptions?.device){let n=await We();t.baseOptions=t.baseOptions??{},t.baseOptions.gpuOptions=t?.baseOptions?.gpuOptions??{},t.baseOptions.gpuOptions.device=n}return Et(e,t)};return jr(Ui);})();
script.js ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Set up DOM references
2
+ const generateBtn = document.getElementById("generate-btn");
3
+ const promptInput = document.getElementById("prompt-input");
4
+ const responseOutput = document.getElementById("response-output");
5
+ const statusMessageContainer = document.getElementById("status-message");
6
+
7
+ const workerPath = './worker.js';
8
+ let worker;
9
+ let modelReady = false;
10
+
11
+ // Handle the click-to-copy event for an emoji translation result
12
+ function handleEmojiButtonClick(result) {
13
+ navigator.clipboard.writeText(result);
14
+ statusMessageContainer.textContent = `Copied to clipboard: ${result}`;
15
+ console.log(`[UI] Copied "${result}" to clipboard.`);
16
+ }
17
+
18
+ // Create and append a button for an emoji translation result
19
+ function createEmojiButton(result) {
20
+ const button = document.createElement("button");
21
+ button.textContent = result;
22
+ button.onclick = () => handleEmojiButtonClick(result);
23
+ responseOutput.appendChild(button);
24
+ }
25
+
26
+ // Check for WebGPU availability and displays an error message if it's not available
27
+ function checkWebGPU() {
28
+ if (!navigator.gpu) {
29
+ statusMessageContainer.innerHTML = `
30
+ This application requires WebGPU to run the model in your browser.
31
+ Please update your browser to enable WebGPU support, try a different browser (like Chrome or Edge, version 113+), or ensure your GPU drivers are up to date.</br></br>
32
+ For more details, read the <a href="https://github.com/gpuweb/gpuweb/wiki/Implementation-Status" target="_blank" style="f; color: #286aac">WebGPU Implementation Status</a>.
33
+ `;
34
+ generateBtn.disabled = true;
35
+ return false;
36
+ }
37
+ return true;
38
+ }
39
+
40
+ // Main function to run worker
41
+ async function initializeModelInWorker() {
42
+ console.log("[UI] Initializing application...");
43
+
44
+ // Create a simulated progress loader that clears once the model loads
45
+ if (!checkWebGPU()) {
46
+ return;
47
+ }
48
+ let loadingInterval;
49
+ let progress = 0;
50
+ statusMessageContainer.textContent = "Loading model (0%)";
51
+ loadingInterval = setInterval(() => {
52
+ if (progress < 99) {
53
+ progress++;
54
+ }
55
+ statusMessageContainer.textContent = `Loading model (${progress}%)`;
56
+ }, 70);
57
+
58
+ // Create a new worker to run the model in a separate thread
59
+ worker = new Worker(workerPath);
60
+ console.log("[UI] Worker created.");
61
+
62
+ // Listen for messages from the worker
63
+ worker.onmessage = (event) => {
64
+ const { type, data } = event.data;
65
+ console.log("[UI] Received message from worker:", { type, data });
66
+
67
+ switch (type) {
68
+ case "loaded":
69
+ clearInterval(loadingInterval); // Stop the fake loader
70
+ statusMessageContainer.textContent = `Loading model (100%)`; // Show 100% briefly
71
+ modelReady = true;
72
+ generateBtn.disabled = false; // Enable the generation button upon model load
73
+ setTimeout(() => {
74
+ statusMessageContainer.innerHTML = ``; // Then empty status message
75
+ }, 500);
76
+ break;
77
+
78
+ case "result":
79
+ const line = data.trim();
80
+ if (line) {
81
+ createEmojiButton(line);
82
+ }
83
+ break;
84
+
85
+ case "complete":
86
+ responseComplete();
87
+ break;
88
+ case "error":
89
+ clearInterval(loadingInterval);
90
+ console.error("Worker error:", data);
91
+ if (modelReady) {
92
+ // Error during generation
93
+ generateBtn.classList.remove('generating');
94
+ statusMessageContainer.textContent =
95
+ "Failed to generate response. Check the console for errors.";
96
+ generateBtn.disabled = false; // Re-enable button
97
+ } else {
98
+ // Error during model loading
99
+ statusMessageContainer.textContent = "Failed to load model. Please refresh the page.";
100
+ }
101
+ break;
102
+ }
103
+ };
104
+
105
+ // Start loading the model in the worker
106
+ console.log('[UI] Sending "load" message to worker.');
107
+ worker.postMessage({ type: "load" });
108
+ }
109
+
110
+ function responseComplete() {
111
+ generateBtn.classList.remove('generating');
112
+ generateBtn.disabled = false;
113
+
114
+ if (responseOutput.childElementCount === 0) {
115
+ statusMessageContainer.textContent = "No results";
116
+ } else {
117
+ // Clear the status message if we have results
118
+ statusMessageContainer.textContent = "Click to copy emojis";
119
+ // For accessibility, move focus to the first result so keyboard users can navigate them.
120
+ responseOutput.firstChild.focus();
121
+ }
122
+ }
123
+
124
+ function resetUI() {
125
+ console.log("[UI] Resetting UI state.");
126
+ generateBtn.classList.add('generating');
127
+ generateBtn.disabled = true;
128
+ responseOutput.innerHTML = ""; // Clear previous buttons
129
+ statusMessageContainer.textContent = "Generating..."; // Set generating status
130
+ }
131
+
132
+ async function generateResponse() {
133
+ const prompt = promptInput.value.trim();
134
+ if (!prompt) {
135
+ statusMessageContainer.textContent = "Please enter a prompt.";
136
+ return;
137
+ }
138
+
139
+ if (!worker || !modelReady) {
140
+ statusMessageContainer.textContent = "Model is not ready yet. Please wait.";
141
+ return;
142
+ }
143
+
144
+ resetUI();
145
+
146
+ // Send prompt to worker to start generation
147
+ console.log(
148
+ `[UI] Sending "generate" message to worker with prompt: "${prompt}"`
149
+ );
150
+ worker.postMessage({ type: "generate", data: { prompt } });
151
+ }
152
+
153
+ // After the script is loaded, initialize the text generator.
154
+ async function initializeAndAttachListeners() {
155
+ console.log("[UI] Starting initialization and attaching listeners.");
156
+
157
+ await initializeModelInWorker();
158
+
159
+ generateBtn.addEventListener("click", generateResponse);
160
+
161
+ // Add event listener for "Enter" key press in the prompt input field
162
+ promptInput.addEventListener("keydown", function (event) {
163
+ if (event.key === "Enter" && !event.shiftKey && !generateBtn.disabled) {
164
+ console.log('[UI] "Enter" key pressed, triggering generation.');
165
+ event.preventDefault(); // Prevents the default action (form submission/new line)
166
+ generateResponse();
167
+ }
168
+ });
169
+ }
170
+
171
+ initializeAndAttachListeners();
style.css CHANGED
@@ -1,28 +1,421 @@
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
  h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
 
 
 
 
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
 
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
 
1
  body {
2
+ font-family: "Google Sans", sans-serif, "Noto Color Emoji", "Apple Color Emoji",
3
+ "Segoe UI Emoji", "Segoe UI Symbol";
4
+ font-optical-sizing: auto;
5
+ font-weight: 400;
6
+ font-style: normal;
7
+ font-variation-settings: "wdth" 100;
8
+ background-color: #ffffff;
9
+ color: #286aac;
10
+ display: flex;
11
+ flex-flow: column;
12
+ align-items: center;
13
+ margin: 0;
14
+ padding: 10px;
15
+ box-sizing: border-box;
16
+ }
17
+ body,html {
18
+ width: 100%;
19
+ height: 100%;
20
+ }
21
+
22
+ .noto-color-emoji-regular {
23
+ font-family: "Noto Color Emoji", sans-serif;
24
+ font-weight: 400;
25
+ font-style: normal;
26
+ }
27
+
28
+ .google-sans-medium {
29
+ font-family: "Google Sans", sans-serif;
30
+ font-optical-sizing: auto;
31
+ font-weight: 600;
32
+ font-style: normal;
33
+ font-variation-settings: "wdth" 100;
34
+ }
35
+
36
+ #wordmark {
37
+ position: absolute;
38
+ top: 10px;
39
+ left: 10px;
40
+ width: 173px;
41
+ height: 24px;
42
+ }
43
+
44
+ .google-sans-regular {
45
+ font-family: "Google Sans", sans-serif;
46
+ font-optical-sizing: auto;
47
+ font-weight: 400;
48
+ font-style: normal;
49
+ font-variation-settings: "wdth" 100;
50
+ }
51
+
52
+ .text-cta {
53
+ width: 395px;
54
+ font-size: 16px;
55
+ line-height: 140%;
56
+ text-align: center;
57
+ /* opacity: 0.7; */
58
+ margin: 0;
59
+ margin-bottom: 20px;
60
+ max-width: 100%;
61
+ }
62
+
63
+ .container {
64
+ display: flex;
65
+ flex-direction: column;
66
+ align-items: center;
67
+ justify-content: center;
68
+ width: 100%;
69
+ max-width: 1000px;
70
+ box-sizing: border-box;
71
+ padding-top: 40px;
72
+ margin: auto 0;
73
  }
74
 
75
  h1 {
76
+ margin-top: 0;
77
+ font-size: 51px;
78
+ line-height: 100%;
79
+ text-align: center;
80
+ letter-spacing: -1.30014px;
81
+ color: #1064d3;
82
+ margin-bottom: 24px;
83
+ }
84
+
85
+ h2 {
86
+ color: #3c4043;
87
+ }
88
+
89
+ .input-container {
90
+ display: flex;
91
+ flex-direction: row;
92
+ gap: 10px;
93
+ margin-bottom: 10px;
94
+ width: 100%;
95
+ position: relative;
96
+ }
97
+
98
+ #prompt-input {
99
+ width: 100%;
100
+ height: 64px;
101
+ background: #ffffff;
102
+ box-shadow: 4px 18px 24px rgba(13, 11, 48, 0.0425185),
103
+ 1px 4px 6px rgba(14, 16, 60, 0.0274815);
104
+ border-radius: 32px;
105
+ border: none;
106
+ font-family: "Google Sans", "Noto Color Emoji", sans-serif;
107
+ font-style: normal;
108
+ font-weight: 400;
109
+ font-size: 16px;
110
+ line-height: 20px;
111
+ padding: 0 74px 0 1.1rem;
112
+ color: #323232;
113
+ }
114
+
115
+ #prompt-input::placeholder {
116
+ color: #c0c0c0;
117
+ }
118
+
119
+ .output-container {
120
+ min-height: 120px;
121
+ flex-shrink: 0;
122
+ display: flex;
123
+ flex-flow: column;
124
+ align-items: center;
125
+ gap: 10px;
126
+ padding-bottom: 20px;
127
+ max-width: 100%;
128
+ }
129
+
130
+ .response-box {
131
+ display: flex;
132
+ flex-flow: row;
133
+ flex-wrap: wrap;
134
+ justify-content: center;
135
+ gap: 10px;
136
+ }
137
+
138
+ .response-box button {
139
+ background: none;
140
+ border: none;
141
+ display: flex;
142
+ flex-direction: row;
143
+ justify-content: center;
144
+ align-items: center;
145
+ padding: 12px;
146
+ min-width: 98px;
147
+ box-sizing: content-box;
148
+ height: 24px;
149
+ background: #ffffff;
150
+ box-shadow: -2px 4px 3.5px rgba(0, 0, 0, 0.04);
151
+ border-radius: 37px;
152
+ cursor: pointer;
153
+ flex-shrink: 0;
154
+ font-family: "Noto Color Emoji", sans-serif;
155
+ font-weight: 400;
156
+ font-style: normal;
157
+ font-size: 18px;
158
+ transition: background-color 0.2s, border-color 0.1s;
159
+ animation: fadeInScaleUp 0.3s ease-out forwards;
160
+ border: 1px solid #ffffff;
161
+ }
162
+
163
+ .response-box button:hover {
164
+ border-color: #1064d3;
165
+ }
166
+
167
+ @keyframes fadeInScaleUp {
168
+ from {
169
+ opacity: 0;
170
+ transform: scale(0.8);
171
+ }
172
+ to {
173
+ opacity: 1;
174
+ transform: scale(1);
175
+ }
176
+ }
177
+ #status-message {
178
+ text-align: center;
179
+ }
180
+ /* Button styles for the generate button */
181
+
182
+ #generate-btn {
183
+ align-self: flex-end;
184
+ position: absolute;
185
+ width: 62px;
186
+ height: 52px;
187
+ right: 6px;
188
+ top: calc(64px / 2 - 52px / 2);
189
+ background: #2776e0;
190
+ border-radius: 99px;
191
+ border: none;
192
+ cursor: pointer;
193
+ transition: background-color 0.3s;
194
+ display: grid;
195
+ place-items: center;
196
+ }
197
+
198
+ #generate-btn svg {
199
+ width: 18px;
200
+ height: 18px;
201
+ }
202
+
203
+ #generate-btn svg.arrow {
204
+ transition: opacity 0.2s, scale 0.35s ease-out, transform 0.2s;
205
  }
206
 
207
+ #generate-btn:hover:not(:disabled),
208
+ #generate-btn:focus:not(:disabled) {
209
+ background-color: #185abc;
210
+ }
211
+ #generate-btn:hover:not(:disabled) svg,
212
+ #generate-btn:focus:not(:disabled) svg {
213
+ transform: translateX(3px);
214
+ }
215
+
216
+ #generate-btn:disabled {
217
+ background-color: #ccc;
218
+ cursor: not-allowed;
219
+ }
220
+
221
+ #generate-btn.generating:disabled svg.arrow {
222
+ opacity: 0;
223
+ scale: 0.2;
224
+ }
225
+
226
+ #generate-btn svg.loader {
227
+ position: absolute;
228
+ top: calc(50% - 9px);
229
+ left: calc(50% - 9px);
230
+ opacity: 0;
231
+ scale: 0.2;
232
+ transition: opacity 0.15s, scale 0.25s ease-out;
233
+ animation: rotator 1.4s linear infinite;
234
+ }
235
+
236
+ #generate-btn.generating:disabled svg.loader {
237
+ opacity: 1;
238
+ scale: 1;
239
+ }
240
+
241
+ #generate-btn svg.loader circle {
242
+ stroke-dasharray: 50; /* 2 * PI * 8 */
243
+ transform-origin: center;
244
+ transition: opacity 0.25s, scale 0.35s ease-out;
245
+ animation: dash 1.4s ease-in-out infinite;
246
+ }
247
+ @keyframes rotator {
248
+ to {
249
+ transform: rotate(360deg);
250
+ }
251
+ }
252
+
253
+ @keyframes dash {
254
+ 0% {
255
+ stroke-dashoffset: 75;
256
+ }
257
+ 50% {
258
+ stroke-dashoffset: 50; /* 1/4 of circumference */
259
+ }
260
+
261
+ 75% {
262
+ stroke-dashoffset: 25; /* 1/4 of circumference */
263
+ }
264
+ 100% {
265
+ stroke-dashoffset: -25;
266
+ }
267
+ }
268
+
269
+ /* Background styles for the blobs and pattern, purely visuals, disable if performance is impacted */
270
+ .background {
271
+ position: fixed;
272
+ top: 0;
273
+ left: 0;
274
+ width: 100%;
275
+ height: 100%;
276
+ z-index: -1;
277
+ background-color: #fafeff;
278
+ pointer-events: none;
279
+ &::after {
280
+ content: "";
281
+ position: absolute;
282
+ top: 0;
283
+ left: 0;
284
+ width: 100%;
285
+ height: 100%;
286
+ background-image: url(data:image/webp;base64,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);
287
+ background-size: 128px 128px;
288
+ background-repeat: repeat;
289
+ mix-blend-mode: overlay;
290
+ }
291
+ }
292
+
293
+ .background-blob-1 {
294
+ position: absolute;
295
+ top: 5vh;
296
+ right: -10vw;
297
+ width: 40vw;
298
+ height: 30vh;
299
+ border-radius: 50%;
300
+ background-color: #b1c5ff;
301
+ filter: blur(150px);
302
+ opacity: 0.5;
303
+ }
304
+
305
+ .background-blob-2 {
306
+ position: absolute;
307
+ bottom: -10vh;
308
+ right: -25vw;
309
+ width: 50vw;
310
+ height: 50vh;
311
+ border-radius: 50%;
312
+ background-color: #b1c5ff;
313
+ filter: blur(100px);
314
+ opacity: 0.3;
315
+ }
316
+
317
+ .background-blob-3 {
318
+ position: absolute;
319
+ top: 60vh;
320
+ left: 0;
321
+ width: 100vw;
322
+ height: 40vh;
323
+ border-radius: 50%;
324
+ background-color: #0b8bf7;
325
+ filter: blur(111px);
326
+ opacity: 0.15;
327
+ }
328
+
329
+ /* Footer styles */
330
+ .footer {
331
+ width: 100%;
332
+ display: flex;
333
+ flex-direction: row;
334
+ justify-content: space-between;
335
+ font-size: 14px;
336
+ font-family: "Google Sans";
337
+ font-style: normal;
338
+ font-weight: 600;
339
+ font-size: 13px;
340
+ line-height: 140%;
341
+ }
342
+
343
+ .footer a,
344
  p {
345
+ margin: 0;
346
+ display: inline;
347
+ color: #286aac;
348
+ }
349
+
350
+ .footer a {
351
+ text-decoration: none;
352
+ transition: color 0.1s;
353
  }
354
 
355
+ .footer a svg {
356
+ width: 7px;
357
+ height: 12px;
358
+ position: relative;
359
+ top: 1px;
360
+ margin-left: 6px;
361
+ transition: transform 0.3s;
362
  }
363
 
364
+ .footer a:hover {
365
+ color: #075099;
366
+ }
367
+
368
+ .footer a:hover svg {
369
+ transform: translateX(3px);
370
+ }
371
+
372
+ .footer a svg path {
373
+ transition: fill 0.1s;
374
+ }
375
+
376
+ .footer a:hover svg path {
377
+ fill: #075099;
378
+ }
379
+ @media screen and (min-width: 768px) {
380
+ body {
381
+ padding: 20px;
382
+ }
383
+ .footer {
384
+ font-size: 16px;
385
+ }
386
+ #wordmark {
387
+ left: 20px;
388
+ top: 20px;
389
+ }
390
+ .text-cta {
391
+ margin-bottom: 44px;
392
+ }
393
+ .input-container {
394
+ gap: 20px;
395
+ margin-bottom: 20px;
396
+ }
397
+ #prompt-input {
398
+ height: 74px;
399
+ border-radius: 37px;
400
+ font-size: 20px;
401
+ line-height: 25px;
402
+ padding: 0 92px 0 37px;
403
+ }
404
+
405
+ #generate-btn {
406
+ width: 74px;
407
+ height: 59px;
408
+ right: 9px;
409
+ top: calc(74px / 2 - 59px / 2);
410
+ }
411
+ .output-container {
412
+ gap: 20px;
413
+ }
414
+ .response-box button {
415
+ padding: 22px;
416
+ min-width: 128px;
417
+ height: 30px;
418
+ font-size: 24px;
419
+ }
420
+ }
421
  }
worker.js ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // This demo requires importScripts, so we use a local, pre-built JavaScript bundle.
2
+
3
+ importScripts('/mediapipe_genai_bundle.js'); // from npm @mediapipe/tasks-genai@0.10.24
4
+
5
+ const { FilesetResolver, LlmInference } = self.BundledCode;
6
+
7
+ let llmInference;
8
+ let modelPath = './myemoji-gemma-3-270m-it.task'; // UPDATE TO MATCH YOUR MODEL FILE
9
+
10
+ // Listen for messages from the main thread
11
+ self.onmessage = async (event) => {
12
+ const { type, data } = event.data;
13
+ console.log("[Worker] Received message:", { type, data });
14
+
15
+ switch (type) {
16
+ case "load":
17
+ try {
18
+ console.log("[Worker] Loading model...");
19
+ // Load the model in the worker thread
20
+ const genai = await FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');
21
+ llmInference = await LlmInference.createFromOptions(genai, {
22
+ baseOptions: {
23
+ modelAssetPath: modelPath
24
+ },
25
+ maxTokens: 32,
26
+ temperature: .8,
27
+ forceF32: true,
28
+ });
29
+ console.log("[Worker] Model loaded successfully.");
30
+ self.postMessage({ type: "loaded" });
31
+ } catch (error) {
32
+ console.error("[Worker] Error loading model:", error);
33
+ self.postMessage({ type: "error", data: error.message });
34
+ }
35
+ break;
36
+
37
+ case "generate":
38
+ if (!llmInference) {
39
+ console.error("[Worker] Generation failed: model not loaded yet.");
40
+ self.postMessage({ type: "error", data: "Model not loaded yet." });
41
+ return;
42
+ }
43
+ try {
44
+ const generatedResponses = new Set();
45
+ const prompt = `<start_of_turn>user\nTranslate this text to emoji: ${data.prompt}<end_of_turn>\n<start_of_turn>model\n`;
46
+ // Request 3 unique, clean responses from the model
47
+ for (let i = 0; i < 3; i++) {
48
+ const modifiedPrompt = prompt + ' '.repeat(i);
49
+ const rawResponse = await llmInference.generateResponse(modifiedPrompt);
50
+ const cleanResponse = rawResponse.replace(/[^\p{Emoji}\s\u200D]/gu, '').trim();
51
+ if (cleanResponse) {
52
+ generatedResponses.add(cleanResponse);
53
+ }
54
+ }
55
+ generatedResponses.forEach(response => {
56
+ self.postMessage({ type: "result", data: response + '\n' });
57
+ });
58
+ self.postMessage({ type: "complete" });
59
+ } catch (error) {
60
+ console.error("[Worker] Error during generation:", error);
61
+ self.postMessage({ type: "error", data: error.message });
62
+ }
63
+ break;
64
+ }
65
+ };