Mike0021 commited on
Commit
4b2c965
·
1 Parent(s): a1370a4

Ava visual upgrade: fitted face and skin, eyes, hair, teeth and lips, 3D turtleneck, glasses option, near-black background; retry dropped model downloads

Browse files
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* 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
  avatars/brunette.glb 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
  avatars/brunette.glb filter=lfs diff=lfs merge=lfs -text
37
+ avatars/ava-hd.glb filter=lfs diff=lfs merge=lfs -text
avatars/ava-eye-spec.webp ADDED
avatars/ava-hd.glb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aba0e4fe8dce8d10a95a710041190facb0ce37bfef88d147fdc035986f222260
3
+ size 23848952
avatars/ava-lids.webp ADDED
chunk-3kpcdt7z.css DELETED
@@ -1 +0,0 @@
1
- :root{--bg:#0a0b10;--bg-elev:#13151c;--bg-elev-2:#1b1e29;--border:#ffffff14;--border-strong:#ffffff29;--text:#f5f6fa;--text-dim:#f5f6faa6;--text-faint:#f5f6fa6b;--error:#ff6a75;--live:#22d3ee;--font-mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;--radius-sm:8px;--radius-md:14px}*{box-sizing:border-box}html,body{height:100%;margin:0}body{background:var(--bg);color:var(--text);overflow:hidden;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}#app{position:relative;height:100dvh}#stage{position:absolute;inset:0}#stage canvas{display:block}[hidden]{display:none!important}#loading{position:absolute;display:grid;font-family:var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint);background:var(--bg);pointer-events:none;place-items: center;transition:opacity .6s;font-size:12px;font-weight:500;inset:0}#loading.done{opacity:0}#topbar{position:absolute;display:flex;pointer-events:none;justify-content:space-between;align-items: flex-start;padding:18px 20px;top:0;left:0;right:0}#topbar>*{pointer-events:auto}#identity h1{letter-spacing:.01em;margin:0;font-size:15px;font-weight:600}#identity p{color:var(--text-faint);max-width:340px;margin:4px 0 0;font-size:12px;line-height:1.45}#identity strong{color:var(--text-dim);font-weight:500}.icon-btn{display:grid;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg-elev);color:var(--text-dim);cursor:pointer;touch-action:manipulation;place-items: center;width:36px;height:36px;padding:0;transition:color .15s,border-color .15s}.icon-btn:hover{color:var(--text);border-color:var(--border-strong)}.icon-btn.active{color:var(--error);border-color:var(--border-strong)}#main-btn{background:var(--text);color:var(--bg);cursor:pointer;touch-action:manipulation;border:none;border-radius:23px;min-width:190px;height:46px;padding:0 26px;transition:transform .12s,opacity .15s;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:14px;font-weight:600}#main-btn:hover:not(:disabled){transform:translateY(-1px)}#main-btn:disabled{pointer-events:none;opacity:.45;cursor:default}#main-btn.live{background:var(--bg-elev);color:var(--text);border:1px solid var(--border-strong)}#controls{position:absolute;display:flex;padding:0 20px calc(22px + env(safe-area-inset-bottom));flex-direction:column;align-items: center;gap:14px;bottom:0;left:0;right:0}#buttons{display:flex;align-items: center;gap:10px}#caption{font-family:var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--text-faint);transition:color .2s;font-size:11px;font-weight:500}#caption.live{color:var(--live)}#caption.error{color:var(--error);text-align:center;max-width:560px;line-height:1.5}#progress{background:var(--border-strong);overflow:hidden;border-radius:1px;width:min(240px,60vw);height:2px}#progress-fill{background:var(--text-dim);width:0;height:100%;transition:width .3s}#subtitles{position:absolute;border-radius:var(--radius-md);backdrop-filter:blur(6px);border:1px solid var(--border);text-align:center;text-wrap:balance;color:var(--text);opacity:0;pointer-events:none;display:-webkit-box;-webkit-line-clamp:3;overflow:hidden;background:#0a0b10b8;-webkit-box-orient:vertical;max-width:min(640px,100vw - 48px);padding:10px 16px;transition:opacity .25s;font-size:15px;line-height:1.5;bottom:118px;left:50%;transform:translate(-50%)}#subtitles.visible{opacity:1}#settings{border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--bg-elev);color:var(--text);width:min(440px,100vw - 40px);padding:22px;box-shadow:0 4px 18px #00000052}#settings::backdrop{backdrop-filter:blur(2px);background:#05060999}#settings h2{margin:0 0 16px;font-size:15px;font-weight:600}#settings label{display:block;color:var(--text-dim);margin-bottom:14px;font-size:12px}#settings select,#settings textarea,#settings input{display:block;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg-elev-2);color:var(--text);width:100%;margin-top:6px;padding:9px 11px;font-family:inherit;font-size:13px}#settings select:focus-visible{outline:1px solid var(--text-dim);outline-offset:1px}#settings textarea:focus-visible{outline:1px solid var(--text-dim);outline-offset:1px}#settings input:focus-visible{outline:1px solid var(--text-dim);outline-offset:1px}#settings textarea{resize:vertical}#settings .hint{display:block;margin-top:6px;font-size:11px;line-height:1.4}#settings .check-row{display:flex;align-items: center;gap:9px}#settings .check-row input{display:inline-block;accent-color:var(--text);width:auto;margin:0}.dialog-actions{display:flex;justify-content:space-between;gap:12px;margin-top:6px}#reset-prompt{color:var(--text-dim);cursor:pointer;background:0 0;border:none;padding:9px 0;font-size:13px}#reset-prompt:hover{color:var(--text)}.dialog-actions .primary{border-radius:var(--radius-sm);background:var(--text);color:var(--bg);cursor:pointer;border:none;padding:9px 20px;font-size:13px;font-weight:600}button:focus-visible{outline:2px solid var(--text-dim);outline-offset:2px}@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}}@media (max-width:600px){#identity p{display:none}#subtitles{font-size:14px;bottom:128px}}
 
 
chunk-4t726cmy.css ADDED
@@ -0,0 +1 @@
 
 
1
+ :root{--bg:#050506;--bg-elev:#13151c;--bg-elev-2:#1b1e29;--border:#ffffff14;--border-strong:#ffffff29;--text:#f5f6fa;--text-dim:#f5f6faa6;--text-faint:#f5f6fa6b;--error:#ff6a75;--live:#22d3ee;--font-mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;--radius-sm:8px;--radius-md:14px}*{box-sizing:border-box}html,body{height:100%;margin:0}body{background:var(--bg);color:var(--text);overflow:hidden;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}#app{position:relative;height:100dvh}#stage{position:absolute;background:#050506;inset:0}#stage canvas{display:block}[hidden]{display:none!important}#loading{position:absolute;display:grid;font-family:var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint);background:var(--bg);pointer-events:none;place-items: center;transition:opacity .6s;font-size:12px;font-weight:500;inset:0}#loading.done{opacity:0}#topbar{position:absolute;display:flex;pointer-events:none;justify-content:space-between;align-items: flex-start;padding:18px 20px;top:0;left:0;right:0}#topbar>*{pointer-events:auto}#identity h1{letter-spacing:.01em;margin:0;font-size:15px;font-weight:600}#identity p{color:var(--text-faint);max-width:340px;margin:4px 0 0;font-size:12px;line-height:1.45}#identity strong{color:var(--text-dim);font-weight:500}.icon-btn{display:grid;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg-elev);color:var(--text-dim);cursor:pointer;touch-action:manipulation;place-items: center;width:36px;height:36px;padding:0;transition:color .15s,border-color .15s}.icon-btn:hover{color:var(--text);border-color:var(--border-strong)}.icon-btn.active{color:var(--error);border-color:var(--border-strong)}#main-btn{background:var(--text);color:var(--bg);cursor:pointer;touch-action:manipulation;border:none;border-radius:23px;min-width:190px;height:46px;padding:0 26px;transition:transform .12s,opacity .15s;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:14px;font-weight:600}#main-btn:hover:not(:disabled){transform:translateY(-1px)}#main-btn:disabled{pointer-events:none;opacity:.45;cursor:default}#main-btn.live{background:var(--bg-elev);color:var(--text);border:1px solid var(--border-strong)}#controls{position:absolute;display:flex;padding:0 20px calc(22px + env(safe-area-inset-bottom));flex-direction:column;align-items: center;gap:14px;bottom:0;left:0;right:0}#buttons{display:flex;align-items: center;gap:10px}#caption{font-family:var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--text-faint);transition:color .2s;font-size:11px;font-weight:500}#caption.live{color:var(--live)}#caption.error{color:var(--error);text-align:center;max-width:560px;line-height:1.5}#progress{background:var(--border-strong);overflow:hidden;border-radius:1px;width:min(240px,60vw);height:2px}#progress-fill{background:var(--text-dim);width:0;height:100%;transition:width .3s}#subtitles{position:absolute;border-radius:var(--radius-md);backdrop-filter:blur(6px);border:1px solid var(--border);text-align:center;text-wrap:balance;color:var(--text);opacity:0;pointer-events:none;display:-webkit-box;-webkit-line-clamp:3;overflow:hidden;background:#0a0b10b8;-webkit-box-orient:vertical;max-width:min(640px,100vw - 48px);padding:10px 16px;transition:opacity .25s;font-size:15px;line-height:1.5;bottom:118px;left:50%;transform:translate(-50%)}#subtitles.visible{opacity:1}#settings{border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--bg-elev);color:var(--text);width:min(440px,100vw - 40px);padding:22px;box-shadow:0 4px 18px #00000052}#settings::backdrop{backdrop-filter:blur(2px);background:#05060999}#settings h2{margin:0 0 16px;font-size:15px;font-weight:600}#settings label{display:block;color:var(--text-dim);margin-bottom:14px;font-size:12px}#settings select,#settings textarea,#settings input{display:block;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg-elev-2);color:var(--text);width:100%;margin-top:6px;padding:9px 11px;font-family:inherit;font-size:13px}#settings select:focus-visible{outline:1px solid var(--text-dim);outline-offset:1px}#settings textarea:focus-visible{outline:1px solid var(--text-dim);outline-offset:1px}#settings input:focus-visible{outline:1px solid var(--text-dim);outline-offset:1px}#settings textarea{resize:vertical}#settings .hint{display:block;margin-top:6px;font-size:11px;line-height:1.4}#settings .check-row{display:flex;align-items: center;gap:9px}#settings .check-row input{display:inline-block;accent-color:var(--text);width:auto;margin:0}.dialog-actions{display:flex;justify-content:space-between;gap:12px;margin-top:6px}#reset-prompt{color:var(--text-dim);cursor:pointer;background:0 0;border:none;padding:9px 0;font-size:13px}#reset-prompt:hover{color:var(--text)}.dialog-actions .primary{border-radius:var(--radius-sm);background:var(--text);color:var(--bg);cursor:pointer;border:none;padding:9px 20px;font-size:13px;font-weight:600}button:focus-visible{outline:2px solid var(--text-dim);outline-offset:2px}@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}}@media (max-width:600px){#identity p{display:none}#subtitles{font-size:14px;bottom:128px}}
chunk-afwf4ypr.js → chunk-ra2pzgep.js RENAMED
The diff for this file is too large to render. See raw diff
 
index.html CHANGED
@@ -12,7 +12,7 @@
12
  rel="stylesheet"
13
  />
14
 
15
- <link rel="stylesheet" crossorigin href="./chunk-3kpcdt7z.css"><script type="module" crossorigin src="./chunk-afwf4ypr.js"></script></head>
16
  <body>
17
  <main id="app">
18
  <!-- The avatar is the hero: a full-viewport 3D stage. -->
@@ -63,6 +63,10 @@
63
  <input type="checkbox" id="subtitles-toggle" />
64
  Show subtitles while she speaks
65
  </label>
 
 
 
 
66
  <label>
67
  System prompt
68
  <textarea id="system-prompt" rows="10" spellcheck="false"></textarea>
 
12
  rel="stylesheet"
13
  />
14
 
15
+ <link rel="stylesheet" crossorigin href="./chunk-4t726cmy.css"><script type="module" crossorigin src="./chunk-ra2pzgep.js"></script></head>
16
  <body>
17
  <main id="app">
18
  <!-- The avatar is the hero: a full-viewport 3D stage. -->
 
63
  <input type="checkbox" id="subtitles-toggle" />
64
  Show subtitles while she speaks
65
  </label>
66
+ <label class="check-row">
67
+ <input type="checkbox" id="glasses-toggle" />
68
+ Wear glasses
69
+ </label>
70
  <label>
71
  System prompt
72
  <textarea id="system-prompt" rows="10" spellcheck="false"></textarea>
workers/model-worker.js CHANGED
@@ -24,7 +24,7 @@ import {
24
  DeviceLostError,
25
  } from "../vendor/Lfm3OmniForConditionalGeneration.js";
26
 
27
- const LOAD_ATTEMPTS = 3; // Chromium occasionally returns no adapter on a cold GPU process
28
  const LOAD_RETRY_MS = 1500;
29
  // Her replies stay in history as text only: her speech costs ~16 tokens/s and left
30
  // no room for what was said, so a 44-turn chat now fits and she still recalls it.
@@ -112,8 +112,10 @@ async function load({ model: modelId, system: sys }) {
112
  console.warn(`model load attempt ${attempt} failed:`, err);
113
  const adapterGlitch = /No WebGPU adapter/i.test(String(err?.message));
114
  if (adapterGlitch && attempt === LOAD_ATTEMPTS) lastErr = Object.assign(new Error(err.message), { name: "WebGPUUnavailable" });
115
- if (!adapterGlitch || attempt === LOAD_ATTEMPTS) break;
116
- await new Promise((r) => setTimeout(r, LOAD_RETRY_MS));
 
 
117
  }
118
  }
119
  post({ kind: "failed", name: lastErr?.name ?? "Error", message: lastErr?.message ?? String(lastErr) });
 
24
  DeviceLostError,
25
  } from "../vendor/Lfm3OmniForConditionalGeneration.js";
26
 
27
+ const LOAD_ATTEMPTS = 4; // Chromium occasionally returns no adapter on a cold GPU process, and networks drop requests
28
  const LOAD_RETRY_MS = 1500;
29
  // Her replies stay in history as text only: her speech costs ~16 tokens/s and left
30
  // no room for what was said, so a 44-turn chat now fits and she still recalls it.
 
112
  console.warn(`model load attempt ${attempt} failed:`, err);
113
  const adapterGlitch = /No WebGPU adapter/i.test(String(err?.message));
114
  if (adapterGlitch && attempt === LOAD_ATTEMPTS) lastErr = Object.assign(new Error(err.message), { name: "WebGPUUnavailable" });
115
+ // A multi-gigabyte download over a real connection will sometimes drop a request. That's worth another go, after a growing pause; what's already cached isn't fetched again.
116
+ const networkGlitch = /failed to fetch|networkerror|network error|load failed|err_/i.test(String(err?.message));
117
+ if ((!adapterGlitch && !networkGlitch) || attempt === LOAD_ATTEMPTS) break;
118
+ await new Promise((r) => setTimeout(r, LOAD_RETRY_MS * 2 ** (attempt - 1)));
119
  }
120
  }
121
  post({ kind: "failed", name: lastErr?.name ?? "Error", message: lastErr?.message ?? String(lastErr) });