Synthetic face pool — 1000 StyleGAN headshots, ComfyUI hot-swap, 60x smaller thumbs

Worker cards now ship a real photo per person instead of monogram tiles:

  - fetch_face_pool.py pulls 1000 faces from thispersondoesnotexist.com
  - tag_face_pool.py runs deepface for gender/race/age, excludes <22yo
  - manifest.jsonl: 952 servable, gender/race buckets populated
  - /headshots/_thumbs/ pre-resized to 384px webp (587KB -> 11KB,
    60x smaller; without this Chrome's parallel-connection budget
    drops ~75% of tiles in a 40-card grid)
  - /headshots/:key gender x race x age intersection bucketing with
    gender-only fallback when intersection is sparse
  - /headshots/generate/:key ComfyUI on-demand for the contractor
    profile spotlight (cold ~1.5s, cached ~1ms; worker-derived
    djb2 seed makes faces deterministic-per-worker but unique
    across workers sharing the same prompt)
  - serve_imagegen.py _cache_key() now includes seed (was caching
    by prompt only -> 3 different worker seeds collapsed to 1
    cached image; verified fix produces 3 distinct md5s)
  - confidence-default name resolution: Xavier->man+hispanic,
    Aisha->woman+black, etc. Every worker resolves to a bucket.

End-to-end: playwright run on /?q=forklift+operators+IL -> 21/21
cards loaded, 0 broken, all 384px webp.

Cache + binary pool gitignored; manifest tracked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-28 06:01:04 -05:00
co-authored by Claude Opus 4.7
parent 10ed3bc630
commit a3b65f314e
8 changed files with 1575 additions and 216 deletions
+3 -1
View File
@@ -2397,7 +2397,9 @@ function addWorkerInsight(parent,name,detail,why,idx,highlight){
if(faceKey){
var img=document.createElement('img');
img.alt='';
img.loading='lazy';
// No lazy-loading: thumbs are 384x384 webp (~11KB) so eager
// load is cheap (~500KB for 50 cards) and avoids the off-screen
// tile flash + scroll-jitter that lazy decode produces here.
var qs = '?g=' + gHint + '&e=' + eHint;
img.src = P + '/headshots/' + encodeURIComponent(faceKey) + qs;
img.onerror=function(){ this.remove(); };