Skip to content

Taxonomy FE Integration#7729

Open
nverjinski wants to merge 15 commits into
developfrom
taxonomy/fe-integration-attribute-schema
Open

Taxonomy FE Integration#7729
nverjinski wants to merge 15 commits into
developfrom
taxonomy/fe-integration-attribute-schema

Conversation

@nverjinski

@nverjinski nverjinski commented Jun 4, 2026

Copy link
Copy Markdown
Member

Note:

This PR should be merged after: #7605
This PR should have its Voodo version updated and be merged after: voxel51/design-system#142

📋 What changes are proposed in this pull request?

This PR seeks to extend field schemas in order to make it possible to define attributes that leverage Taxonomies for their values. When a user creates a new attribute of str or list<str> type and also sets the component type to dropdown, they should be able to select a predefined Taxonomy as the values of the dropdown. I extended the BE to accept a new taxonomy attribute on AttributeSpec and added validation relating to this new attribute in validate_label_schemas.py. This PR also includes changes to the front end UI.

A separate, upcoming PR will update the annotation smart form to consume this new attribute and render the new voodo TreeSelect component.

🧪 How is this patch tested? If it is not, please explain why.

Define a taxonomy with this script:
create_vehicle_taxonomy.py

  1. Define a new attribute in the label schema.
  2. Select string or string list as the type.
  3. Select Dropdown as the component.
  4. Select the new taxonomy from the dropdown
  5. Save
Screen.Recording.2026-06-05.at.3.01.24.PM.mov

📝 Release Notes

Is this a user-facing change that should be mentioned in the release notes?

  • No. You can skip the rest of this section.
  • Yes. Give a description of this change to be included in the release
    notes for FiftyOne users.

Added ability to choose a predefined taxonomy in lieu of manually defining values for a dropdown based schema attribute.

What areas of FiftyOne does this PR affect?

  • App: FiftyOne application changes
  • Build: Build and test infrastructure changes
  • Core: Core fiftyone Python library changes
  • Documentation: FiftyOne documentation changes
  • Other

Summary by CodeRabbit

Release Notes

  • New Features

    • Added taxonomy-based attribute values mode. Users can now toggle between "Simple" and "Taxonomy" modes when configuring dropdown attributes.
    • Dropdown attributes can now use pre-defined taxonomies instead of manual value lists.
  • Improvements

    • Enhanced validation and error handling for taxonomy configurations.
    • Improved messaging for taxonomy-related errors and unsupported component types.

Enterprise sync PR: https://github.com/voxel51/fiftyone-teams/pull/2822

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This pull request implements taxonomy-backed attribute values as an alternative to simple explicit values. It introduces an ontology type system to distinguish between annotation ontologies and taxonomies, extends the backend AttributeSpec with an optional taxonomy field enforcing mutual exclusivity with values, validates taxonomy settings in label schemas, updates the frontend form model to track values mode (simple vs. taxonomy), implements state handlers to manage taxonomy eligibility based on attribute type and component, and renders a UI toggle in AttributeFormContent to switch between ValuesList and OntologyPicker modes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • tom-vx51
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Taxonomy FE Integration' directly relates to the primary objective of extending frontend UI to support taxonomy selection for dropdown attributes.
Description check ✅ Passed The PR description covers all required template sections: related issues noted, changes clearly explained, testing steps provided with example script and video, and release notes completed with user-facing impact and affected areas selected.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch taxonomy/fe-integration-attribute-schema

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nverjinski nverjinski marked this pull request as ready for review June 5, 2026 19:58
@nverjinski nverjinski requested a review from a team as a code owner June 5, 2026 19:58

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@fiftyone/core/annotation/validate_label_schemas.py`:
- Line 729: The function _validate_taxonomy_setting currently lacks an explicit
return type; add a return type annotation "-> None" to its definition (i.e.,
change "def _validate_taxonomy_setting(field_name, taxonomy):" to include "->
None") so it follows repository conventions and satisfies static analysis;
update the function signature where _validate_taxonomy_setting is defined and
ensure any imports or type aliases used for parameters remain unchanged.
- Around line 408-411: The error message raised in the categorical field
validator uses the word "incompatible" for foac.TAXONOMY and foac.VALUES but the
string-field validator uses "mutually exclusive"; update the ValueError message
raised where foac.TAXONOMY and foac.VALUES are checked (the raise referencing
field_name, foac.TAXONOMY and foac.VALUES) to use the exact phrasing "mutually
exclusive" so both validators use consistent wording.

In `@fiftyone/server/routes/ontology.py`:
- Around line 201-202: Replace the hard-coded string "taxonomy" in the if-check
with the OntologyType constant: change the condition to compare doc.get("type")
against OntologyType.TAXONOMY (the same place where doc and name are used) so
the code uses the imported OntologyType enum/constant rather than a literal
string for better maintainability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 793e2be3-4d8e-4b40-bd28-c33b2dae4560

📥 Commits

Reviewing files that changed from the base of the PR and between 7f380c1 and f5bc463.

📒 Files selected for processing (16)
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/ApplyOntologySection.tsx
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/GUIContent/AttributeFormContent.tsx
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/GUIContent/useAttributeForm.ts
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/OntologyPicker.tsx
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/useOntologies.ts
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/utils.ts
  • fiftyone/core/annotation/attributes.py
  • fiftyone/core/annotation/constants.py
  • fiftyone/core/annotation/nodes.py
  • fiftyone/core/annotation/validate_label_schemas.py
  • fiftyone/server/routes/__init__.py
  • fiftyone/server/routes/ontology.py
  • tests/unittests/annotation/attribute_spec_tests.py
  • tests/unittests/annotation/validate_label_schemas_tests.py
  • tests/unittests/ontology_class_tests.py
  • tests/unittests/server/routes/test_ontology.py

Comment thread fiftyone/core/annotation/validate_label_schemas.py
Comment thread fiftyone/core/annotation/validate_label_schemas.py
Comment thread fiftyone/server/routes/ontology.py
@nverjinski nverjinski requested a review from erik-nieh June 5, 2026 20:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/GUIContent/AttributeFormContent.tsx`:
- Around line 91-101: The taxonomy tab gating only checks isTaxonomyEligible and
ignores ontology-derived read-only semantics; update the tab definition (id:
"taxonomy") to also consider isFromOntology from useAttributeForm.ts (where
isFromOntology is computed as !!formState._source) so the tab is disabled when
isFromOntology is true (e.g., disabled: !isTaxonomyEligible || isFromOntology)
and set the tooltip to indicate the attribute is read-only due to originating
from the ontology when isFromOntology is true; ensure this change prevents mode
switching for ontology-derived attributes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ad257ba3-a34e-4148-bdaa-5067224370c8

📥 Commits

Reviewing files that changed from the base of the PR and between f5bc463 and 94768f4.

📒 Files selected for processing (1)
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/GUIContent/AttributeFormContent.tsx

erik-nieh and others added 13 commits June 8, 2026 09:14
Returns the tree for a named Taxonomy, with optional node-rooting and
depth-truncation for lazy-fetch flows.

- New `OntologyTaxonomy` Starlette endpoint in
  `fiftyone/server/routes/ontology.py`, registered at
  `/ontologies/{name}/taxonomy`.
- Path param `name` resolves a Taxonomy via `load_ontology` (slug
  normalized internally). 404 when the name doesn't exist or resolves
  to a non-taxonomy ontology.
- Query param `?node=<name>` reframes the response root at a
  descendant node. 404 when no such node exists in the taxonomy.
- Query param `?depth=<n>` limits recursion to N levels below the
  response root. `depth=0` returns just the response root with no
  children. Truncated branches that had children are serialized with
  `values=[]` so the wire format distinguishes them from real leaves
  (which have no `values` key).
- Response envelope `{"taxonomy": {...}}` matches the precedent in
  this file. The base `Ontology.to_dict` is called explicitly so the
  full root tree isn't serialized just to be overwritten.

Tree-walking helpers live on `Node`:
- `Node.find(name)` — first-match descendant lookup (node names are
  unique within a taxonomy).
- `Node.truncated(depth)` — returns a copy truncated to N levels.

Tests cover all paths: full-tree fetch, node-query subtree, unknown
node 404, depth=0 root-only, depth=1 with truncated-branch and
real-leaf markers, node+depth combined, invalid/negative depth 400.
…g Nodes

For large taxonomies the dominant cost of the previous endpoint was
``Node.from_dict`` recursively constructing dataclass instances over
the whole tree (~400ms for 50k nodes). The endpoint is read-only and
only needs to slice and project a subtree, so it now operates on the
dict returned by pymongo and never hydrates Nodes.

- ``OntologyTaxonomy.get`` is async-native via motor; no
  ``run_sync_task`` wrapper.
- The Mongo fetch lives in ``_load_taxonomy_doc(name)``; the subtree
  filter (``?node=``, ``?depth=``) lives in ``_select_subtree(...)``;
  ``_load_taxonomy_response`` composes them.
- ``find_in_dict`` and ``truncate_dict`` move out of the route file
  into ``fiftyone/core/annotation/nodes.py`` alongside ``Node``.
  The earlier ``Node.find`` / ``Node.truncated`` methods are removed —
  the endpoint was their only caller.

Benchmark on the 50k-node stress taxonomy (whole-pipeline wall time):

  query           before     after
  full          ~575 ms    ~69 ms   (8.3x)
  depth=0       ~554 ms    ~21 ms   (26.7x)
  depth=1       ~469 ms    ~20 ms   (23.1x)
  depth=2       ~548 ms    ~20 ms   (27.3x)

Small / medium taxonomies were already sub-10ms and stay there.

Tests: swap the ``Node.find`` / ``Node.truncated`` tests for
equivalent ``find_in_dict`` / ``truncate_dict`` tests; the existing
endpoint tests pass without modification.
…d label schema validation to support the new taxonomy attribute
@nverjinski nverjinski force-pushed the taxonomy/fe-integration-attribute-schema branch from d616c58 to faeec89 Compare June 8, 2026 14:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/utils.ts`:
- Around line 387-396: The taxonomy branch is still serializing the default
value even though default inputs are hidden; update the object returned when
data.valuesMode === "taxonomy" to omit the default property (do not include the
"default" key) so stale unseen defaults are not persisted. Locate the branch
that checks data.valuesMode === "taxonomy" in utils.ts and remove or
conditionally exclude the default: defaultValue entry (ensure other fields like
name, type, component, range, read_only, taxonomy remain unchanged).

In `@tests/unittests/ontology_class_tests.py`:
- Around line 1194-1257: The file contains duplicate test class definitions for
FindInDictTests and TruncateDictTests that shadow earlier definitions; remove
the second set of definitions (the redefinitions of the classes FindInDictTests
and TruncateDictTests) so only the original test classes remain, preserving the
individual test methods that should be kept and ensuring imports of find_in_dict
and truncate_dict used in those tests remain in place.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c642689-de0d-405e-b7cb-b35655e02905

📥 Commits

Reviewing files that changed from the base of the PR and between 966cf5b and faeec89.

📒 Files selected for processing (12)
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/ApplyOntologySection.tsx
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/GUIContent/AttributeFormContent.tsx
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/GUIContent/useAttributeForm.ts
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/OntologyPicker.tsx
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/EditFieldLabelSchema/useOntologies.ts
  • app/packages/core/src/components/Modal/Sidebar/Annotate/SchemaManager/utils.ts
  • fiftyone/core/annotation/attributes.py
  • fiftyone/core/annotation/constants.py
  • fiftyone/core/annotation/validate_label_schemas.py
  • tests/unittests/annotation/attribute_spec_tests.py
  • tests/unittests/annotation/validate_label_schemas_tests.py
  • tests/unittests/ontology_class_tests.py

Comment thread tests/unittests/ontology_class_tests.py Outdated

@erik-nieh erik-nieh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks good, just some minor comments.

<ToggleSwitch
key={formState.valuesMode}
size={Size.Sm}
defaultIndex={formState.valuesMode === "taxonomy" ? 1 : 0}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because these strings are referenced in many places it might be nice to convert them to enums

);

const handleValuesModeChange = useCallback(
(mode: "simple" | "taxonomy") => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then enum would make this type implicit i think

TextColor,
TextVariant,
Toggle,
ToggleSwitch,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this functional with the voodoo change? like could merge this and then bump the voodoo lesion version later?



def _validate_applied_ontology(field_name: str, value: str) -> None:
def _validate_taxonomy_setting(field_name, taxonomy):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be worth extending this validation to make the ontology actually loads. Look in the validate applied ontology just below this.



def _validate_applied_ontology(field_name: str, value: str) -> None:
def _validate_taxonomy_setting(field_name, taxonomy):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is not strictly enforced in the code base, but I think it's a good precedence. It's just making sure these functions are typed. field_name: str, taxonomy_name: str

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants