> ## Documentation Index > Fetch the complete documentation index at: https://docs.typesafe.ai/llms.txt > Use this file to discover all available pages before exploring further. # Advanced: structure > Instructions, Choice options, Score levels, and Noul criteria all accept JSON structure. export function TypesafeExample({example, display, title}) { const keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$"; function compressToEncodedURIComponent(input) { if (input == null) return ""; return _compress(input, 6, function (a) { return keyStrUriSafe.charAt(a); }); } function _compress(uncompressed, bitsPerChar, getCharFromInt) { if (uncompressed == null) return ""; var i, value, context_dictionary = {}, context_dictionaryToCreate = {}, context_c = "", context_wc = "", context_w = "", context_enlargeIn = 2, context_dictSize = 3, context_numBits = 2, context_data = [], context_data_val = 0, context_data_position = 0, ii; for (ii = 0; ii < uncompressed.length; ii += 1) { context_c = uncompressed.charAt(ii); if (!Object.prototype.hasOwnProperty.call(context_dictionary, context_c)) { context_dictionary[context_c] = context_dictSize++; context_dictionaryToCreate[context_c] = true; } context_wc = context_w + context_c; if (Object.prototype.hasOwnProperty.call(context_dictionary, context_wc)) { context_w = context_wc; } else { if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) { if (context_w.charCodeAt(0) < 256) { for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } } value = context_w.charCodeAt(0); for (i = 0; i < 8; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } } else { value = 1; for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1 | value; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = 0; } value = context_w.charCodeAt(0); for (i = 0; i < 16; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } } context_enlargeIn--; if (context_enlargeIn == 0) { context_enlargeIn = Math.pow(2, context_numBits); context_numBits++; } delete context_dictionaryToCreate[context_w]; } else { value = context_dictionary[context_w]; for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } } context_enlargeIn--; if (context_enlargeIn == 0) { context_enlargeIn = Math.pow(2, context_numBits); context_numBits++; } context_dictionary[context_wc] = context_dictSize++; context_w = String(context_c); } } if (context_w !== "") { if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) { if (context_w.charCodeAt(0) < 256) { for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } } value = context_w.charCodeAt(0); for (i = 0; i < 8; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } } else { value = 1; for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1 | value; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = 0; } value = context_w.charCodeAt(0); for (i = 0; i < 16; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } } context_enlargeIn--; if (context_enlargeIn == 0) { context_enlargeIn = Math.pow(2, context_numBits); context_numBits++; } delete context_dictionaryToCreate[context_w]; } else { value = context_dictionary[context_w]; for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } } context_enlargeIn--; if (context_enlargeIn == 0) { context_enlargeIn = Math.pow(2, context_numBits); context_numBits++; } } value = 2; for (i = 0; i < context_numBits; i++) { context_data_val = context_data_val << 1 | value & 1; if (context_data_position == bitsPerChar - 1) { context_data_position = 0; context_data.push(getCharFromInt(context_data_val)); context_data_val = 0; } else { context_data_position++; } value = value >> 1; } while (true) { context_data_val = context_data_val << 1; if (context_data_position == bitsPerChar - 1) { context_data.push(getCharFromInt(context_data_val)); break; } else context_data_position++; } return context_data.join(""); } function buildHref(ex) { const documentText = ex.state === undefined ? "" : typeof ex.state === "string" ? ex.state : JSON.stringify(ex.state, null, 2); return "https://console.typesafe.ai/decode#share/" + compressToEncodedURIComponent(JSON.stringify({ apiVersion: "v1", documentText, promptsText: JSON.stringify(ex.questions, null, 2), selectedModels: ex.selectedModels })); } const displayedExample = display === "questions" ? example.questions : example.state === undefined ? { questions: example.questions } : { state: example.state, questions: example.questions }; const code = JSON.stringify(displayedExample, null, 2); const href = buildHref(example); return
{code}
Try it in the Playground →
; } System One models are trained to understand structure. ## Where structure is allowed Every one of these fields is an [`EntryType`](/sdk/javascript/api/type-aliases/EntryType). | Field | Applies to | Accepted shape | | --------------------------------------- | ------------------- | -------------------------------------- | | `instructions` | Choice, Score, Noul | `string`, `object`, `array`, or `null` | | `criteria` values (option descriptions) | Choice | `string`, `object`, `array`, or `null` | | `criteria` entries (level descriptions) | Score | `string`, `object`, `array`, or `null` | | `criteria.true` and `criteria.false` | Noul | `string`, `object`, `array`, or `null` | ## When to structure a question * **When it helps with clarity.** When a question has multiple parts, putting them in the form of JSON helps with clarity because the keys are labeled. * **When question needs supporting data.** A schema, a taxonomy, or a database row is already JSON. Use the JSON entirely or pass in the relevant subfields instead of serializing them into a string template. ## Structured instructions One `field` object describes the field being checked, and each question refers to it by key. The same shape drives a Noul that verifies a value, a Choice that picks one from candidates, and two Scores that place a value on a scale. In code, you could loop over the potential records and build one of these questions per field, all sent in a single call. The [SDE cascade cookbook](/cookbooks/sde_cascade) does something similar to this. Arrays work too. Use one when the instruction is a list of things to check or to compare: ```json theme={null} "instructions": { "question": "Does the claimed sender identity conflict with the sending domain?", "compare": ["ticket.sender.display_name", "ticket.sender.email"], "focus": "Compare the named organization with the email domain." } ``` ## Structured Choice options A Choice option description can be a structured object as well. ### JSON rubric for boundary clarification The example tells the model what each option does and does *not* cover. It sharpens the boundary between options. ### Walking a taxonomy To classify into a deep taxonomy, ask one Choice per level and walk the tree in code. At each step the options are the children of the current node, and each option's value is the child's tree. Doing so lets the model see what lives under a branch before committing to it, which matters when the item belongs to a leaf whose name is not obvious from the branch name alone. Here the state is a product listing and the first question picks a top-level department. The bottle plausibly fits under two departments. Showing the subtrees lets the model see that both `Sporting Goods > Cycling > Bike Bottles & Cages` and `Home & Kitchen > Drinkware > Water Bottles` exist, and weigh the listing's emphasis on bike cages against everyday drinkware. The `probabilities` on this answer tell you whether the split is close enough to explore both branches. Once a department is chosen, ask the next Choice with that department's children as the options and their subtrees as the values, and repeat until you reach a leaf. In code this could be a loop over a nested dict, where each question's `criteria` is simply the current node. The [Hierarchical Classification cookbook](/cookbooks/hierarchical_classification) shows an example of a similar walk of the tree, including a beam search that keeps several candidate paths alive when the probabilities are close. Subtrees can get large. If a branch is too large, trim the value to its direct children and a sample of leaves. ## Structured Score levels Each entry in a Score `criteria` array can be an object. ## Structured Noul criteria Noul `criteria` is optional, and when the yes/no boundary is subtle, structured `true` and `false` descriptions let you pin it down with a definition and examples on each side.