Read PRODUCT.md for the current product contract and PRD.md for the original experiment scope. This folder includes the live Worker, the local experiment harness, and the complete original dataset release.
Paste one comment and get ranked meme options at https://memes.significanthobbies.com. One-tap feedback is retained for 30 days so the ranking can improve. The live 3,000-reference catalogue contains 1,805 static memes and 1,195 usage-backed reaction GIFs; the earlier artwork fillers and six inert editing canvases are excluded. The workers.dev route remains an equivalent preview URL.
Requires Node.js 22 or newer. No dependency installation or build step.
cd /Users/sarthak/Desktop/fleet/meme-lab
node server.mjsOpen http://127.0.0.1:4317. npm start is equivalent. Stop with Ctrl+C. To use another port, set PORT=4318 node server.mjs or edit .env.
Immediately available without an AI model: the four-tab interface, catalogue/search, all source audits, opt-in image previews, prompt export, the explicitly labelled keyword baseline, local feedback and JSONL export. The baseline is not a functioning cultural-reasoning model.
The unchanged standalone browser can also be opened directly at original/meme_references_v1/preview.html. Its text works offline; source-hosted images require an explicit click and an internet connection. public/index.html is the new app shell and requires the local server—do not open that file directly.
cp .env.example .env
# Edit .env: set MEME_MODEL to an exact model name available in your runtime.
# For an existing Ollama installation, `ollama list` shows installed models.
node server.mjsExample configuration, with a placeholder to replace:
MEME_MODEL=your-installed-model-name
MEME_API_STYLE=ollama
MEME_API_BASE_URL=http://127.0.0.1:11434
MEME_ALLOW_REMOTE=falseOllama must already be running. The native adapter sends the catalogue as text to /api/chat, asks for structured JSON, and validates IDs locally. It does not see image pixels. Use an instruction-following model with sufficient context for the catalogue. The default context setting is 16,384 tokens; context allocation and runtime memory depend on your chosen model. No model is bundled, chosen for you, downloaded, or benchmarked here.
An existing chat-completions-compatible server can instead be configured with MEME_API_STYLE=chat_completions and a base URL ending at its API root, such as http://127.0.0.1:1234/v1. The adapter appends /chat/completions. Leave native Ollama's base URL without /api/chat or /v1.
Compatibility varies by provider. Set MEME_JSON_MODE=false only if your compatible endpoint rejects response_format; local validation still applies. A cloud endpoint requires HTTPS, the appropriate authorized API key, and MEME_ALLOW_REMOTE=true. The UI identifies a non-loopback endpoint. A loopback runtime can still invoke cloud models: use a genuinely local model for private conversations.
The managed Worker classifier now goes through the private Free AI FleetGateway service binding. It requests JSON with model auto, passes the existing fit and perspective instructions, and validates exact labels and numeric scores locally before ranking. The serious-input gate abstains when its classifier response is unavailable or malformed; regular ranking keeps the established deterministic/retrieval fallbacks. The gateway migration preserves request/response shapes and fit labels, but a general model's probability calibration is not equivalent to Jev's ordinal scoring. The source integration for Free AI Issue #83 is not yet merged or deployed, so this describes the pending source path rather than a live-release change.
The corrected 3,000-record index stores separate meaning and example vectors, for 6,000 vectors total. It contains 1,805 static meme templates and 1,195 usage-backed reaction GIFs; it contains no National Gallery artwork or empty editing canvases. The 41-item canonical coverage list includes owner-requested staples such as “My Name Is Jeff” and “I Love You 3000.” To reseed the index, confirm string metadata indexing for view plus boolean metadata indexing for control and core, wait for all mutations to finish, then call the tool's /seed endpoint in six bounded 500-record ranges (start=0,500,…,2500&limit=500). The core flag reserves ten shortlist positions for the retained baseline without preventing the broader catalogue from contributing the other twenty. Verify the corrected index and evaluation before switching production traffic.
The GIF tranche comes from the public GIF Reply research dataset: 1.56 million observed text-to-GIF conversation pairs with stable GIF hashes and GIPHY mappings. The 1,194 research-selected GIFs each appeared in at least 108 replies; “My Name Is Jeff” is included as an explicit owner-requested canonical entry. Usage evidence is not a redistribution licence, so these remain source previews with rights marked not established.
Load a smoke situation or paste your own. Start with the 30 reaction candidates and enriched descriptions. Compare Choose with model against names-only and the lexical control. Load a source image explicitly when needed. Add an optional replacement/note, then choose a verdict. “No meme belongs here” and “a better match exists” mean different things; the app keeps them separate.
For the controlled comparison, pre-label whether humour belongs, then choose Run blind A/B. The app freezes the context, style, pool and model; runs names-only and enriched conditions in seeded order; hides condition labels and rationales; and reveals them only after every successful arm is reviewed. Paired runs remain grouped in history, with condition-specific counts rather than one combined score.
If a model returns malformed or contradictory structured output, the adapter makes one constrained repair attempt through the same model. A failed repair remains an error; it never becomes a keyword result. The run records whether repair was attempted.
Each submission creates a local run file. Each verdict creates a feedback event; the history screen shows the latest verdict per run or paired arm. Exports retain all events. The smoke inputs are synthetic fixtures, not an independently labelled quality benchmark. See the protocol before treating results as evidence. The first live local-model engineering session is recorded in live_experiment_2026-09-19.md. The frozen 30-case paired holdout and its blind agent-review results are recorded in holdout_v1_report.md.
With a local model configured, the frozen holdout can be resumed without duplicating completed cases:
npm run experiment:holdout
npm run experiment:reviewOpen http://127.0.0.1:4318 for the isolated owner-review queue. Use http://127.0.0.1:4318/review to label each returned candidate as relevant, not relevant or unsure. Allowlisted candidate previews load automatically. The relevance queue is resumable and keeps conditions, rationales and pre-labels hidden. npm run experiment:summarize validates both blind-review artifacts and regenerates results/holdout-v1/summary.json.
| Path | Contents |
|---|---|
PRD.md, AGENT_HANDOFF.md |
Product spec and coding-agent handoff. |
public/, server.mjs, src/ |
Local UI, selectors, model adapters, safe local server, event store. |
prompts/, schemas/ |
Inspectable selector instructions and response schema. |
eval/smoke_cases.jsonl |
20 synthetic UI/behavior smoke cases. |
private/holdout_v1.jsonl |
Frozen 30-case holdout, never served by the app. |
results/holdout-v1/ |
Isolated paired runs, blind queues, reviews and machine-readable summary. |
tests/, scripts/ |
Offline, HTTP/mock-adapter, and package-integrity checks. |
docs/ |
Complete research index, audit addendum, experiment protocol, tests, current screenshots. |
original/meme_references_v1/ |
Every original release file, unchanged. |
original/meme_references_v1.zip |
The exact previously supplied ZIP. |
original/historical-preview.png |
Supplied older screenshot, visibly labelled historical by its filename. |
runs/ |
Private local run/feedback files; starts empty and is ignored by Git. |
npm test
npm run check
# Optional original validator:
python3 original/meme_references_v1/validate_dataset.pySee test_report.md for packaged test coverage. A live qwen2.5:3b Ollama holdout was subsequently run locally; its quality evidence and limitations are documented separately in holdout_v1_report.md. External asset availability was not comprehensively re-audited.
Annotations are drafts and evaluation labels are not human ground truth. Meme media is not bundled. Static images and GIFs load from their recorded providers, and no new permission clearance is implied. The canonical coverage report makes known gaps visible instead of padding the count with arbitrary reusable images.
The app listens on 127.0.0.1, makes no model request until asked, and does not prefetch remote images. Media loads contact the original provider. Pasting an exported prompt into another service shares its content. Local run files contain your full pasted conversations in plaintext; do not commit or share them accidentally. To reset, stop the server and remove the JSON event files inside runs/, retaining .gitkeep. There is no production authentication; do not expose this server through a tunnel or bind it publicly.
Keep .env out of Git. Original assets/annotations are never edited by the app. The preserved screenshot has outdated 50-reference counts; use the JSON catalogue and current UI for the 60-reference release. Audit addendum explains the discrepancy and what is still unverified.
When the optional APP_HEALTH_INGEST_KEY Worker secret is configured, API
endpoint measurements can be sent to App Health. Those measurements contain
only the fixed API route, method, response status, and duration; request paths,
query values, prompts, feedback, and identities are not included. Reporting is
disabled when the key is absent and never delays an API response.
The Anna working draft adds a user-uploaded photo/meme remix editor in the owner-selected Reference Desk direction. Generation uses Anna’s image API; private outputs use own-app files. The feature remains under verification and is not Store-published. See implementation and evidence and issue #19.