Concept sets
Concept sets are reusable lists of coded choices.
Use them when the AI should pick from a controlled catalogue instead of inventing text.
Examples:
- Diagnoses.
- Medications.
- Procedure codes.
- Allergy lists.
- Visit reasons.
Why use codes?
A label is what people read. A code is what systems store.
| Label | Code |
|---|---|
| Rotator cuff tear | M75.1 |
| Bicipital tendinitis | M75.2 |
| Pain in joint | M25.5 |
The doctor sees the label. The HIS receives the code.
Inline choices
Use inline choices for small lists.
"pain-location": {
"title": "Pain location",
"type": "string",
"description": "Pick the main pain location",
"oneOf": [
{ "const": "ANTERIOR", "title": "Front" },
{ "const": "POSTERIOR", "title": "Back" },
{ "const": "LATERAL", "title": "Side" }
]
}
The saved answer is ANTERIOR, POSTERIOR, or LATERAL.
Reusable concept set
Use a saved concept set when the list is shared or long.
"diagnosis": {
"title": "Diagnosis",
"type": "string",
"description": "Select the main diagnosis",
"x-concept-set-id": 12
}
Tiep loads concept set 12, checks it belongs to the facility, and hydrates the choices before the form is used.
How the choices are presented
Small concept sets are shown as normal coded choices (a plain dropdown). Large ones are presented as a search box instead.
Both use the normal visual choice widgets: select for one answer and
multiselect for many answers. What differs is the field's
x-concept-mode:
x-concept-mode | Behaviour |
|---|---|
auto (default) | Inline when the set fits the cap, search when it is larger. |
inline | Force inline choices. Falls back to auto when over the cap. |
search | Force a search box, even for a small set. |
This matters for lists like medications. You do not want a dropdown with thousands of items — you want search.
How search works
The AI reads the form schema before it fills it in. For an inline field, the schema includes every choice and the AI picks one directly.
For a search field, the schema cannot carry the whole list — it would be too long.
The schema only mentions the concept set; the concepts stay in the database.
Search runs directly against the concepts table using Postgres fuzzy matching
(pg_trgm), so results are always in sync with the set — there is no separate
index to build or keep up to date.
When the AI extracts a value for a search field, it produces a human label like "Amoxicillin". Tiep fuzzy-searches the set for that label and replaces it with the canonical code stored on the concept.
When the mode is decided
You do not manage this by hand.
- When a form is built, Tiep counts the concepts in each referenced set.
- A field left as
autobecomes inline when the set fits the cap (50) and a search field when it is larger. inlineandsearchare honored as written, exceptinlineover the cap, which falls back toauto.
The decision is made per field at build time, so the same set can be inline in one form and a search box in another.
Multiple coded answers
For many answers, put the concept set on items.
"diagnoses": {
"title": "Diagnoses",
"type": "array",
"description": "Select all diagnoses mentioned in the visit",
"items": {
"type": "string",
"x-concept-set-id": 12
}
}
Versions
Concept sets are versioned by name.
Example:
When you set a version as current, Tiep re-publishes each active form that pointed at an older version of the same set as a new form version pointing at the chosen one. Historical and draft form versions stay anchored to the version they were built with, so old records keep their original meaning.
Simple rule
Use:
| Tool | When |
|---|---|
enum | Tiny list where label and value are the same. |
oneOf | Small coded list written directly in the form. |
x-concept-set-id | Reusable or large coded catalogue. |