Repository navigation
Export the verified species data of opted-in projects as one platform-wide training set - #1571
Open
mohamedelabbas1996 wants to merge 3 commits into
Open
mohamedelabbas1996 wants to merge 3 commits into
mohamedelabbas1996 wants to merge 3 commits into
Conversation
✅ Deploy Preview for antenna-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
…ining A new project feature flag, share_verified_data_for_training, off by default. Only projects that turn it on go into the platform-wide training-data export. Co-Authored-By: Claude <noreply@anthropic.com>
…rquet A snapshot writes manifest.parquet (one row per verified species detection: label, split, box, crop and capture locations), one vector file per algorithm, and metadata.json. Rows follow verified_occurrence_ids and are streamed, so the query count does not grow with the number of rows. A snapshot records its counts per project; old snapshots lose their files but keep their counts. Superusers start one from the admin. Co-Authored-By: Claude <noreply@anthropic.com>
A Celery task runs one export under an advisory lock. A data migration adds its beat entry for Sundays at 03:00 with enabled=False, so an admin decides when exports start. Co-Authored-By: Claude <noreply@anthropic.com>
mohamedelabbas1996
force-pushed
the
feat/retrain-job-form
branch
from
October 30, 2026 05:20
6674160 to
cd3f048
Compare
mohamedelabbas1996
force-pushed
the
feat/training-data-export
branch
from
October 30, 2026 05:24
e7a6cb2 to
8693bf9
Compare
mohamedelabbas1996
changed the base branch from
feat/retrain-job-form
to
feat/retrain-training-set
October 30, 2026 05:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Retraining a classifier for the whole platform needs every verified species identification in Antenna, not one project at a time. This PR adds a periodic export that writes the verified species detections of every project that opted in into versioned Parquet files: a manifest (labels, split, box, crop and capture locations) and one vector file per algorithm. Projects share nothing unless a superuser turns on their
share_verified_data_for_trainingfeature flag. The weekly schedule is created switched off.The selection rule is the one the per-project training set already uses (
verified_occurrence_idsinami/ml/training/dataset.py): a non-withdrawn identification, on an occurrence determined to species. The export does not use occurrence sets, so it is not affected when the retraining stack moves to #1543.Stacked on #1504 (
feat/retrain-job-form, at70934961). Design notes:~/antenna/reviews/training-data-export-design.md(to be posted on the retraining epic).List of Changes
ProjectFeatureFlags.share_verified_data_for_training: bool = False(ami/main/models.py)TrainingDataSnapshotandTrainingDataSnapshotProject(ami/ml/models/training_data.py), admin with a per-project inline; saving a new snapshot queues the exportami/ml/training/export.py:manifest.parquet. Rows streamed with a server-side cursor and written in row groups, so memory stays flat. Split by occurrence with the existingsplit_forvectors/algorithm=<key>/part-00000.parquet:detection_id+fixed_size_list<halffloat>[dims]. A vector with the wrong length is skipped and countedmetadata.json: rules, files, algorithms, per-project counts. The same counts are stored on the snapshot rowsami.ml.tasks.export_training_data_snapshot; data migration adds adjango_celery_beatPeriodicTask(Sunday 03:00,enabled=False)SnapshotAlreadyRunningTRAINING_DATA_SNAPSHOTS_KEPT(default 4, env setting) are deleted; their counts staypyarrow==17.0.0inrequirements/base.txtDetailed Description
Files in a snapshot
Manifest columns:
detection_id, occurrence_id, source_image_id, deployment_id, project_id, site_id, device_id, taxon_id, taxon_name, taxon_rank, identification_id, identified_at, split, bbox, captured_at, crop_url, capture_path, capture_url.identification_id/identified_atare the latest non-withdrawn identification.capture_urlis built from the capture's public base URL only. Presigned URLs are not written, because they expire long before a snapshot is read;capture_pathis always there.Why Parquet and not image shards
Head retraining reads stored embeddings, so the vectors and labels are what it needs. Parquet is built from SQL alone, is much smaller than crops, and any common tool reads it. Image shards (WebDataset) can be built later from the manifest, which keeps crop and capture locations. Size estimates are in the design notes; they are estimates, not measured.
Queries
The number of queries depends on the number of algorithms, not on the number of detections. A test pins this with the query cache off, at 1 and 7 rows.
Not in this PR
Tests
Measured on 2026-10-30, in the CI compose stack:
makemigrations --check --dry-runreports no changes, andmanage.py test ami.exports ami.ml ami.jobsran 417 tests, OK (2 skipped). The 8 new tests are inami/ml/test_training_export.py:verified_occurrence_idsfor the same project;metadata.jsonread back with pyarrow andjson;How to Test the Changes
docker compose -f docker-compose.ci.yml run --rm django python manage.py test ami.ml.test_training_export docker compose -f docker-compose.ci.yml run --rm django python manage.py makemigrations --check --dry-runBy hand: in the Django admin, turn on
share_verified_data_for_trainingin a project's feature flags, then add a Training data snapshot. When it finishes, its files are listed on the snapshot and undertraining-data/in media storage.Base (2026-10-30)
Retargeted from #1504 to #1502: the export only needs #1502's rule for which occurrences count as verified species, so it can merge without waiting for the training job (#1503) or the form (#1504).