算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
designing-replay-vision-scanners【设计与创意】Designs a Replay Vision scanner that produces trustworthy observations: one visible question per scanner, a type chosen from the answer shape, a query that selects only sessions able to answer it, a prompt that demands on-screen proof and allows no or inconclusive, a model picked by the cost of a wrong answer, and a first-batch test pass. Sizing and …
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
A scanner is one prompt applied to one recording at a time. It watches the recording and writes an observation. Replay Vision fixes the watching part. It does not fix the thinking part. The thinking is the design work this skill covers.
Every scanner that produces useful observations shares three properties:
Design in this order: question, type, query, prompt, model, first-batch test. Then hand off to [[creating-replay-vision-scanners]] for sizing and the create call.
Write the question in one sentence before you touch the API. Then run three checks.
Only the recording can answer it. If an event already answers the question, build an insight instead. A rage click event already proves the rage click. The scanner question must add something the event cannot: "did the clicked control actually fail?"
One recording answers it. A scanner sees one recording and cannot compare it with recordings it has never seen. Push every cross-session question to a scout, a digest, or product analytics. Comparisons between experiment variants, trends over time, and "how common is this" all live outside the scanner prompt.
The answer has a fixed shape. A yes or no with proof. One tag from a short list. A score on a stated scale. A summary with fixed labeled lines. If you cannot name the answer shape, you do not have a question yet.
Reject these questions and rewrite them:
If the user has specific sessions in front of them and a one-off question, they do not need a scanner. Use vision-scanners-inline-scan instead.
| Answer shape | Type | Design rule |
|---|---|---|
| Yes or no, with proof | monitor | Set allow_inconclusive: true when many matched sessions never reach the flow in question. Yes only when the proof is on screen. |
| One label from a short list | classifier | Keep 5 to 9 tags. Always include an escape tag. multi_label defaults to true; set it false unless one session carries several jobs. |
| A number on a rubric | scorer | Use when the distribution matters more than any single observation. Define both ends of the scale in the prompt. |
| A fixed set of labeled lines about one recording | summarizer | Name the lines in the prompt (for example Journey, Friction, Outcome, Evidence). Never ask for free prose. |
scanner_type is locked after creation. Get this right before the create call.
Escape tags for classifiers are not optional. A classifier must pick a tag. Without nothing-broken, never-reached, cant-tell, or inconclusive in the list, the model invents friction on sessions that contain none. Make the escape tag exclusive: the prompt must say it never combines with a defect tag.
Use allow_freeform_tags: true only when the goal is taxonomy discovery, and say so in the prompt: "invent a short snake_case tag only when the recording clearly shows a job outside this list". The tag vocabulary lives in tags, so the prompt describes the dimension and does not need to restate the list. If the prompt does define each tag, keep the two lists identical. Freeform tags hide drift between them, so re-read both together after every edit.
The query decides which recordings deserve a judgment. The prompt decides what judgment to make. A better query improves quality more than another paragraph of prompt.
Build the query from the project's real data. Call read-data-schema with {"query": {"kind": "events"}}, or inspect existing scanners. Never invent an event name.
A query has one required part and two optional parts:
having_predicates entry on active_seconds. Add it when brief visits cannot answer the question. Leave it out when short sessions are the point, for example a render check or a drop-off question.filter_test_accounts: true and, where the project supports it, a person-property filter on the email domain. Leave it out when internal sessions are the population, for example a dogfood scanner.When the query is a conjunction of two events, the recording may contain both without them being related. Make the prompt verify the premise first (see Step 4). A session that viewed an issue and also opened an AI chat may have asked the AI about something else entirely.
The API strips date_from and date_to on save. The scanner's schedule controls time. Do not treat dates in an inherited query as a defect to fix.
Sizing the query against the credit budget is the job of [[creating-replay-vision-scanners]]. Do that before you create.
Write the prompt in eight parts, in this order:
Patterns that hold up in production:
Anti-patterns to strip out of any draft:
Each model has a fixed price per observation. Pick by asking what one wrong observation costs the reader.
If observations are close but not right, tighten the prompt before moving up a tier. A sharper instruction is usually cheaper than a bigger model.
Do not polish the prompt before it runs. The first batch shows how the prompt actually performs.
vision-scanners-scan-session for a handful of session IDs.vision-observations-label-create only after the user gives or confirms it. Add a sentence when the scanner got the premise wrong. To change the prompt yourself, use vision-scanners-update.scratch has placeholders to fill. The scout compares observations. The scanner never does.Return to Step 3 before Step 4 when the observations are mostly "no" or "inconclusive". A weak query is the usual cause, not a weak prompt.
These are PostHog's own scanners over PostHog's own product. Use the shapes, not the text.
Ghost bugs (monitor). Question: did the product contradict itself or dead-end the user in a task it invited? Query: a pageview URL regex on the product surface plus active_seconds > 30 plus test-account filter. Prompt: seven named contradiction patterns, a five-item no list, "both halves on screen", and "most sessions contain no such defect". Priciest tier, because one yes opens a bug.
Broken render (classifier). Question: did the page render correctly for this visitor? Query: visited_page contains the site domain. Tags: eight defect tags plus nothing-broken and cant-tell, the last two exclusive. Prompt: every defect tag needs page, location, and timestamp, or the model tags nothing-broken. Cheapest tier, because one wrong label only nudges a trend.
Escape to the AI assistant (summarizer). Question: what could the user not do in the UI right before they asked the assistant? Query: an issue-viewed event AND a chat-started event. Prompt: verify the two are related first, else output UNRELATED and stop. Then three fixed parts and one closing sentence that names the missing capability.
Product opportunity miner (monitor). Question: does this session reveal one concrete, testable product opportunity? Query: an OR of nine high-intent events, the product URL, active_seconds > 60, employee exclusion. Prompt: yes only when three conditions are visible, then Evidence, Unmet job, Smallest test, Alternative explanation. Priciest tier, sampled hard, credit-capped, and fed to a daily scout.
allow_inconclusive is off by default. A monitor without it must answer yes or no. That is fine when the query guarantees every session reaches the flow. When it does not, the model stretches ordinary sessions into findings.scanner_version. Past observations keep the old prompt, so compare ratings within one version.vision-observations-retry. Test a prompt edit on fresh sessions.