7287a55707
Ship locked expert Call 1 seed: order cats before edge, species=best confidence, mill-count edge rules, Wild for cookies/burl, multi figure, feature_tag_ids only (no free-text bags, no grade). LISTS keys match the seed; feat- prefix stripped for the model. Gate and review UI apply feature_tag_ids. Seed auto-activates on deploy when still seed-authored.
171 lines
8.6 KiB
Markdown
171 lines
8.6 KiB
Markdown
# Prompts contract
|
||
|
||
Status: SPEC · 2026-09-18.
|
||
Owns prompt storage, prompt inputs, and the two inference calls.
|
||
|
||
## Requirements impact
|
||
|
||
| Requirement | Impact on this design |
|
||
|---|---|
|
||
| METADATA-5, METADATA-10, METADATA-15, METADATA-30 | taxonomy choices and cardinality |
|
||
| METADATA-35, METADATA-40, METADATA-45, METADATA-50 | Call 1 inputs, constraints, pre-fill, precedence |
|
||
| METADATA-55, METADATA-60, METADATA-65, METADATA-70 | Call 2 output, inputs, dimension safety, inference-off path |
|
||
| METADATA-75, METADATA-80, METADATA-85, METADATA-90, METADATA-95 | non-blocking, deterministic copy, pattern selection, fact block, overlay exclusion |
|
||
| METADATA-105, METADATA-106, METADATA-107 | prompt storage, revision interface, auth |
|
||
| METADATA-66 | generation logging |
|
||
| SETTINGS-30 | brand voice and geo context |
|
||
| REVIEW-40, REVIEW-50 | editability and field limits |
|
||
|
||
## 1. Storage and revisions
|
||
|
||
- Prompts live in the database, not in text files, with all revisions retained. Storage shape is
|
||
`docs/contracts/DATA-MODEL.md` §7 (`METADATA-105`).
|
||
- Revisions are append-only. Editing saves a new revision and moves the active pointer; a revision
|
||
is never updated or deleted. Reset to default and reset to revision are pointer moves.
|
||
- Each call reads the active revision fresh, and the revision used is recorded on the call
|
||
(`METADATA-66`).
|
||
- The seed text in §6 is read once on first run and written as revision 0 for each call. It is the
|
||
only prompt content that ships with the application.
|
||
|
||
## 2. Revision interface
|
||
|
||
REST, no UI (`METADATA-106`):
|
||
|
||
1. `POST /api/v1/prompts/{call}/revisions` appends a revision and returns it.
|
||
2. `POST /api/v1/prompts/{call}/activate` moves the active pointer to a revision.
|
||
3. `GET /api/v1/prompts/{call}` returns the active prompt and the revision list.
|
||
|
||
The interface is reachable on the trusted network only until it is authenticated (`METADATA-107`).
|
||
|
||
## 3. Call 1 — vision classification
|
||
|
||
Cites METADATA-35, METADATA-40, METADATA-45, METADATA-50.
|
||
|
||
**When.** Runs automatically after a calibrated draft uploads only when `inference_enabled` is
|
||
true; also on demand or retry. With inference off it is skipped and the fields are filled by hand.
|
||
|
||
**Inputs.**
|
||
- The clean processed photos at 1024 px long edge or less.
|
||
- Closed LISTS from the synced Woo cache only: `species`, `wood_categories`, `edge_terms`,
|
||
`figure_terms`, `feature_tags` (each with id + display name). Grade, thickness, and moisture are
|
||
not sent to Call 1.
|
||
- User metadata: SKU, length, thickness.
|
||
|
||
**Constraints.**
|
||
- The model may only choose values from the supplied LISTS; it never invents categories or terms.
|
||
- Feature tags are returned as `feature_tag_ids` from the supplied list only. Display names omit a
|
||
leading `feat-` prefix; Woo remains authoritative for the tag set. No free-text observation bags.
|
||
- Grade is never suggested (owner judgment).
|
||
- Decide wood categories before edge type. Cookies and burl cuts prefer Wild edge when that term
|
||
exists in the list.
|
||
|
||
**Result fields.** `species_id` + `species_confidence`; `wood_category_ids` +
|
||
`wood_category_confidence`; `edge_type_term_id` + `edge_confidence`; `figure_term_ids` +
|
||
`figure_confidence` (multi allowed); `feature_tag_ids` + `feature_tag_confidence`. Edge is singular;
|
||
figure and feature tags are multi.
|
||
|
||
**Pre-fill.** At or above the threshold (default 0.7) the field is pre-filled and remains
|
||
editable; below it the field stays empty and is not shown as a low-confidence guess. Typed values
|
||
always win. Call 1 is assist-only and never gates publish. A runtime failure is classified
|
||
recoverable or unrecoverable for the owner.
|
||
|
||
## 4. Call 2 — content prose
|
||
|
||
**When.** User-triggered only, via the Generate text control; never automatic. The control appears
|
||
only when content generation is enabled and the endpoint is reachable.
|
||
|
||
**Inputs.**
|
||
- The clean processed photos.
|
||
- The metadata confirmed or changed in review, including the primary and secondary wood categories
|
||
and the parent-category path.
|
||
- The literal dimension fact block, exact strings for species, figure term, length, thickness,
|
||
average width, width min–max, and board feet; no length-by-width-by-thickness rectangle
|
||
assumption.
|
||
- Brand voice and geo context.
|
||
|
||
No provider thread id is used, and Call 1's raw prompt and result are not sent (`METADATA-60`).
|
||
|
||
**Constraints.**
|
||
- The model writes prose only and never invents or alters a dimension; every number comes from the
|
||
fact block (`METADATA-65`).
|
||
- The dimension-overlay image is never sent (`METADATA-95`).
|
||
|
||
**Output.** The long `description` prose. The server assembles `name` and `short_description`
|
||
(`METADATA-55`, `METADATA-80`). The primary wood category selects the specialized prompt
|
||
(`METADATA-85`). The owner can edit the result (`REVIEW-40`).
|
||
|
||
## 5. Fallback and templates
|
||
|
||
- With inference off, the server produces the long description so create never lacks prose
|
||
(`METADATA-70`).
|
||
- The deterministic title and short-description patterns live in `docs/contracts/CONTENT-WOO.md`
|
||
(`METADATA-80`).
|
||
- The primary wood category selects the specialized Call 2 prompt (`METADATA-85`).
|
||
- All generated text stays within the field limits in `docs/contracts/WOO-API.md` §9
|
||
(`REVIEW-50`).
|
||
|
||
## 6. Seed prompt text
|
||
|
||
Read once on first run and written as revision 0 for each call (`METADATA-105`). Authored here with
|
||
the rest of the prompt discussion; the seed is the only prompt content that ships with the
|
||
application.
|
||
|
||
The seed is the starting point for tuning, not a final text. Both calls are revised ad hoc through
|
||
the §2 interface when UAT surfaces a miss.
|
||
|
||
**`call1` seed.** Shipped text in `backend/inference.py` (`CALL1_SEED`), mirrored here for review.
|
||
|
||
You are a wood identification expert for retail lumber slabs. Judge only from the photos and the
|
||
LISTS below. Use list ids only — never invent a name or id.
|
||
|
||
Work in this order: (1) species, (2) wood categories, (3) edge type, (4) figure, (5) feature tags.
|
||
Decide wood categories before edge type — edge rules depend on product form.
|
||
|
||
For each field, pick from its list and give a confidence 0–1 (1 = certain, 0 = no idea). Prefer
|
||
null or [] over a weak guess.
|
||
|
||
Species — which tree species is this slab. Match grain, color, and figure to the species list. If
|
||
more than one entry is plausible, return only the single highest-confidence match (one id). Null
|
||
only when none are credible.
|
||
|
||
Wood categories — product form / how it will be sold (live edge, dimensional, cookies & burl
|
||
slices, turning blanks, etc.). Choose every wood_categories id that clearly fits; often one,
|
||
sometimes more. [] if none fit. Finish this field before edge type.
|
||
|
||
Edge type — the long-edge mill profile. One id from edge_terms, or null only if none fit.
|
||
Meanings (match the closest list name):
|
||
• Square / square edge — both long edges milled straight (2 milled long edges).
|
||
• Live one side / Live Edge 1 side — one long edge milled, the other natural bark or waney
|
||
(1 milled long edge).
|
||
• Live both / Live edge 2 sides — neither long edge milled; both natural (0 milled long edges).
|
||
• Wild edge — use when the three mill-count cases do not fit, including cookies and burl
|
||
cuts/slices (no conventional slab long-edge pair). Prefer Wild for those forms rather than null.
|
||
|
||
Figure — visible figure in the wood (curl, quilt, spalt, plain, burl, …). Zero or more ids from
|
||
figure_terms that clearly apply.
|
||
|
||
Feature tags — defects and character marks the store tags for shoppers (knots, checks,
|
||
inclusions, …). Zero or more ids from feature_tags. If that list is empty, return [].
|
||
|
||
Return one JSON object with exactly these keys:
|
||
{"species_id": <id|null>, "species_confidence": <0-1>, "wood_category_ids": [<id>,...],
|
||
"wood_category_confidence": <0-1>, "edge_type_term_id": <id|null>, "edge_confidence": <0-1>,
|
||
"figure_term_ids": [<id>,...], "figure_confidence": <0-1>, "feature_tag_ids": [<id>,...],
|
||
"feature_tag_confidence": <0-1>}
|
||
|
||
Runtime appends `LISTS:` (JSON of the five closed lists) plus SKU/length/thickness and the photos.
|
||
|
||
**`call2` seed.** Write the long product description for the slab from the supplied photos and
|
||
listing facts. The name and short description are already built, so do not repeat them. Use the
|
||
brand voice and geo context given. The dimensions in the fact block are exact: use those strings
|
||
and invent no numbers. Write prose a premium lumber buyer would read.
|
||
|
||
## 7. Prompt management
|
||
|
||
- The active Call 1 and Call 2 revisions are editable through the §2 interface; saving creates a
|
||
new revision.
|
||
- A revision identifies its content, author, and timestamp; `inference_log` records the revision
|
||
used for each call.
|
||
- The revision interface requires authentication before it is exposed beyond the trusted network
|
||
(`METADATA-107`).
|