From tim-skills
Run synthetic (LLM-simulated) market research using Semantic Similarity Rating (SSR), the method from Maier et al. 2025 (arXiv:2510.08338). Use when estimating customer adoption, purchase intent, or willingness-to-pay for product concepts/features WITHOUT surveying real users: define target-segment personas, elicit free-text reactions, and map them to Likert intent distributions via embedding similarity. Triggers: "synthetic research", "SSR", "test these feature/product ideas", "willingness to pay", "which concept resonates", "simulated survey", "concept testing", "productized marketing research".
How this skill is triggered — by the user, by Claude, or both
Slash command
/tim-skills:ssr-market-researchThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Estimate how a target market will react to product concepts by simulating consumers with an
Estimate how a target market will react to product concepts by simulating consumers with an LLM and scoring their reactions with Semantic Similarity Rating (SSR). SSR avoids the "everything is a 3" failure mode of asking an LLM for numeric ratings directly.
If you ask an LLM "rate your purchase intent 1–5," it regresses to the center — low variance, unrealistic, ~50% accuracy. SSR fixes this with four design choices, all of which matter (dropping persona detail alone cut accuracy 92% → 50% in the paper):
The paper hit ~90% of human test–retest reliability this way, beating supervised models.
segments + personas → concepts to test → free-text reactions → ssr.py → intent distributions
(who) (what) (LLM impersonation) (scoring) (per concept × segment)
personas.json.concepts.json. Keep each concept self-contained — a respondent reads it cold.For every (persona × concept) pair, produce a 2–4 sentence first-person reaction answering "How likely would you be to adopt and pay for this, and why?" — in that persona's voice, with their specific concerns. Two ways to generate them:
references/workflow-example.md.Store as responses.json: a list of {persona_id, segment, concept, response_text}.
python3 scripts/ssr.py \
--responses responses.json \
--anchors scripts/anchors.json \
--out results.json
Outputs per-concept and per-(concept × segment): the Likert PMF, mean intent, top-2-box % (mass on the top two points = strong intent), bottom-box %, and n. Prints a ranked table to stdout. Requires the venv from "Setup" below.
python3 -m venv .venv && . .venv/bin/activate
pip install numpy model2vec openai
ssr.py defaults to OpenAI text-embedding-3-small (closest to the paper; sharpest
distribution spread). It reads OPENAI_API_KEY from the environment or a local .env file
(auto-loaded). If no key is found it falls back to local static embeddings
(minishlab/potion-base-8M, no torch, no key, free) with a printed notice — good enough for
ranking, just lower discrimination. Force local explicitly with --backend local.
scripts/ssr.py — the SSR scoring engine (embeddings → Likert PMFs → ranked report).scripts/anchors.json — 6 generic, domain-independent adoption/WTP anchor sets (1–5).references/methodology.md — the paper's method, math, and fidelity caveats in depth.references/workflow-example.md — how to generate reactions with parallel persona agents.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub thattimc/skills --plugin tim-skills