DocsGuides
Rating profiles
A rating is not universal. A street photographer, a wedding shooter and a wildlife photographer value different things, and set the keeper bar at very different heights. A profile captures both axes explicitly.
shoots rate ./raw --profile wedding
What a profile decides
1. WHAT matters — meritWeights
How the per-aspect CLIP scores combine into a single aesthetic merit. Aspects absent from the map count zero.
2. HOW strict — the star cut-offs and the focus gate
Where the 0–5 boundaries sit, and how hard technically-soft frames are punished.
| Field | Meaning |
|---|---|
focusReject |
Focus below this = technical reject, 0 stars, regardless of content |
focusSoft |
Focus below this = soft/missed focus, capped at focusSoftCap |
focusSoftCap |
The star ceiling applied to soft frames |
aestheticStars |
Merit cut-offs, descending. The first one the merit clears wins. |
The skill-level axis
For a beginner, technical aspects (exposure, sharpness, composition) should earn stars — nailing them is a real achievement. For a professional they are table stakes, so pro-oriented profiles zero them out and let content decide.
That axis lives in the same two fields: different weights, different thresholds.
The aspects
Seven contrastive aspect pairs, scored zero-shot by CLIP:
| Aspect | Probes |
|---|---|
overall |
General photographic quality |
composition |
Framing and structure |
exposure |
Technical exposure quality |
subject |
Subject presence and isolation |
sharpness |
Perceived acuity |
lighting |
Quality of light |
storytelling |
Narrative / the moment |
Every aspect is always scored and recorded in the sidecar, regardless of the profile's weights. The profile only decides how they aggregate — so you can re-derive a rating under a different profile without re-running inference.
Built-in profiles
street — the default
Street / documentary — content over craft, unforgiving bar (calibrated)
| Weights | storytelling 1.5 · overall 1.2 · subject 1.0 · lighting 1.0 |
| Focus gate | reject 0.30, soft 0.55, soft cap 1★ |
| 5★ at | merit ≥ 0.63 |
| 1★ at | merit ≥ 0.50 |
Technical competence is assumed, so exposure, sharpness and composition are zeroed entirely. Deliberately unforgiving: on a real shoot the mass of frames lands at 0 stars. That is the intended behaviour — you want the tail, not a flattering distribution.
This is the only profile calibrated against a real, hand-judged shoot.
generic
All-round, forgiving — technical competence counts (prior)
| Weights | overall 1.2 · subject 1.0 · storytelling 1.0 · composition 1.0 · lighting 1.0 · exposure 0.8 · sharpness 0.8 |
| Focus gate | reject 0.30, soft 0.50, soft cap 2★ |
| 5★ at | merit ≥ 0.62 |
| 1★ at | merit ≥ 0.38 |
A sensible default for a beginner or a mixed set. Technical craft counts toward the score and the bar is much lower, so a clean, well-made frame already earns a star or two.
portrait
Portrait — subject & light lead, eyes must be sharp (prior)
| Weights | subject 1.5 · lighting 1.2 · overall 1.0 · sharpness 0.6 · composition 0.5 · storytelling 0.5 |
| Focus gate | reject 0.35, soft 0.60, soft cap 1★ |
| 5★ at | merit ≥ 0.62 |
The subject and the light on it carry the frame. The focus gate is stricter — a soft portrait is a miss.
wildlife
Wildlife — sharp subject & behaviour, strict focus (prior)
| Weights | subject 1.5 · sharpness 1.2 · storytelling 1.0 · overall 1.0 · lighting 0.8 |
| Focus gate | reject 0.40, soft 0.65, soft cap 1★ |
| 5★ at | merit ≥ 0.62 |
The hardest focus gate of any profile: a soft animal is simply a miss.
wedding
Wedding — forgiving, a clean frame already counts (prior)
| Weights | subject 1.2 · overall 1.2 · lighting 1.0 · storytelling 1.0 · exposure 0.8 · composition 0.6 |
| Focus gate | reject 0.30, soft 0.50, soft cap 2★ |
| 5★ at | merit ≥ 0.60 |
| 1★ at | merit ≥ 0.37 |
Deliberately forgiving: on a wedding, a clean well-exposed frame is already a usable pick, and you deliver volume.
Known limit. True emotion and expression scoring is what a wedding profile most wants, and the current model has no such aspect. It arrives with a future model archive. Until then this profile is a reasonable prior, not a calibrated judge.
Choosing a profile
The presets are priors, not truth. Only street is calibrated. The honest way
to choose:
# Take 50 frames you have already judged yourself, then compare
for p in street generic portrait wildlife wedding; do
echo "── $p"
shoots rate ./sample-50 --profile "$p" --dry-run --json \
| jq -r '.results[] | "\(.stars)★ \(.file | split("/") | last)"' \
| sort -r
done
Pick the one that agrees with you most often. If none does — and that is a common, legitimate outcome — train your own.
Learned profiles
The real answer to "none of the presets is my eye" is to learn one from your own judgements. See Preference learning for the full pipeline.
Installing one
Drop the profile JSON into ~/.shoots/profiles/ and it becomes selectable by
filename:
cp my-eye.json ~/.shoots/profiles/
shoots rate ./raw --profile my-eye
Built-in names win over user profiles, so do not name a learned profile
street — it would be silently shadowed.
The linear-embedding shape
Learned profiles use type: "linear-embedding": the merit is a linear head over
the CLIP embedding, s(x) = w·x + b, squashed into [0,1]. The star cut-offs then
apply to that normalized score exactly as with a built-in profile.
{
"type": "linear-embedding",
"name": "my-eye",
"description": "Learned from 800 duels, June 2026",
"embeddingModel": "clip-vit-b32-int8", // guards the embedding space
"dim": 512,
"weights": [ /* 512 floats */ ],
"bias": -0.14,
"scoreNormalization": { "mean": 0.02, "std": 0.31 },
"focusReject": 0.3,
"focusSoft": 0.55,
"focusSoftCap": 1,
"aestheticStars": [
{ "min": 0.78, "stars": 5 },
{ "min": 0.62, "stars": 4 },
{ "min": 0.45, "stars": 3 },
{ "min": 0.28, "stars": 2 },
{ "min": 0.12, "stars": 1 }
]
}
Validation
Because these are external JSON files, every field is validated before use. A
malformed profile fails loudly with exit 2 rather than producing silent garbage
stars:
error: invalid profile my-eye.json: weights must be 512 finite numbers
embeddingModel guards that the profile is applied to the same CLIP space it was
learned on. Applying a profile trained on one model archive to another is a
category error and is rejected.
Listing what is available
An unknown profile name prints the full list — built-ins plus everything in
~/.shoots/profiles:
error: unknown rating profile 'foo' (available: street, generic, portrait, wildlife, wedding, my-eye, client-work)
Profiles in the pipeline config
- type: rate
profile: wedding
output: xmp
See Pipelines.
See also
rate— the command that consumes profiles- Preference learning — train your own
embeddings— the profile-neutral export profiles are learned from