lightly-studio 0.4.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. lightly_studio/__init__.py +12 -0
  2. lightly_studio/api/__init__.py +0 -0
  3. lightly_studio/api/app.py +131 -0
  4. lightly_studio/api/cache.py +77 -0
  5. lightly_studio/api/db_tables.py +35 -0
  6. lightly_studio/api/features.py +5 -0
  7. lightly_studio/api/routes/api/annotation.py +305 -0
  8. lightly_studio/api/routes/api/annotation_label.py +87 -0
  9. lightly_studio/api/routes/api/annotations/__init__.py +7 -0
  10. lightly_studio/api/routes/api/annotations/create_annotation.py +52 -0
  11. lightly_studio/api/routes/api/caption.py +100 -0
  12. lightly_studio/api/routes/api/classifier.py +384 -0
  13. lightly_studio/api/routes/api/dataset.py +191 -0
  14. lightly_studio/api/routes/api/dataset_tag.py +266 -0
  15. lightly_studio/api/routes/api/embeddings2d.py +90 -0
  16. lightly_studio/api/routes/api/exceptions.py +114 -0
  17. lightly_studio/api/routes/api/export.py +114 -0
  18. lightly_studio/api/routes/api/features.py +17 -0
  19. lightly_studio/api/routes/api/frame.py +241 -0
  20. lightly_studio/api/routes/api/image.py +155 -0
  21. lightly_studio/api/routes/api/metadata.py +161 -0
  22. lightly_studio/api/routes/api/operator.py +75 -0
  23. lightly_studio/api/routes/api/sample.py +103 -0
  24. lightly_studio/api/routes/api/selection.py +87 -0
  25. lightly_studio/api/routes/api/settings.py +41 -0
  26. lightly_studio/api/routes/api/status.py +19 -0
  27. lightly_studio/api/routes/api/text_embedding.py +50 -0
  28. lightly_studio/api/routes/api/validators.py +17 -0
  29. lightly_studio/api/routes/api/video.py +133 -0
  30. lightly_studio/api/routes/healthz.py +13 -0
  31. lightly_studio/api/routes/images.py +104 -0
  32. lightly_studio/api/routes/video_frames_media.py +116 -0
  33. lightly_studio/api/routes/video_media.py +223 -0
  34. lightly_studio/api/routes/webapp.py +51 -0
  35. lightly_studio/api/server.py +94 -0
  36. lightly_studio/core/__init__.py +0 -0
  37. lightly_studio/core/add_samples.py +533 -0
  38. lightly_studio/core/add_videos.py +294 -0
  39. lightly_studio/core/dataset.py +780 -0
  40. lightly_studio/core/dataset_query/__init__.py +14 -0
  41. lightly_studio/core/dataset_query/boolean_expression.py +67 -0
  42. lightly_studio/core/dataset_query/dataset_query.py +317 -0
  43. lightly_studio/core/dataset_query/field.py +113 -0
  44. lightly_studio/core/dataset_query/field_expression.py +79 -0
  45. lightly_studio/core/dataset_query/match_expression.py +23 -0
  46. lightly_studio/core/dataset_query/order_by.py +79 -0
  47. lightly_studio/core/dataset_query/sample_field.py +37 -0
  48. lightly_studio/core/dataset_query/tags_expression.py +46 -0
  49. lightly_studio/core/image_sample.py +36 -0
  50. lightly_studio/core/loading_log.py +56 -0
  51. lightly_studio/core/sample.py +291 -0
  52. lightly_studio/core/start_gui.py +54 -0
  53. lightly_studio/core/video_sample.py +38 -0
  54. lightly_studio/dataset/__init__.py +0 -0
  55. lightly_studio/dataset/edge_embedding_generator.py +155 -0
  56. lightly_studio/dataset/embedding_generator.py +129 -0
  57. lightly_studio/dataset/embedding_manager.py +349 -0
  58. lightly_studio/dataset/env.py +20 -0
  59. lightly_studio/dataset/file_utils.py +49 -0
  60. lightly_studio/dataset/fsspec_lister.py +275 -0
  61. lightly_studio/dataset/mobileclip_embedding_generator.py +158 -0
  62. lightly_studio/dataset/perception_encoder_embedding_generator.py +260 -0
  63. lightly_studio/db_manager.py +166 -0
  64. lightly_studio/dist_lightly_studio_view_app/_app/env.js +1 -0
  65. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/0.GcXvs2l7.css +1 -0
  66. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/12.Dx6SXgAb.css +1 -0
  67. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/17.9X9_k6TP.css +1 -0
  68. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/18.BxiimdIO.css +1 -0
  69. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/2.CkOblLn7.css +1 -0
  70. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/ClassifierSamplesGrid.BJbCDlvs.css +1 -0
  71. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/LightlyLogo.BNjCIww-.png +0 -0
  72. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Bold.DGvYQtcs.ttf +0 -0
  73. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Italic-VariableFont_wdth_wght.B4AZ-wl6.ttf +0 -0
  74. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Medium.DVUZMR_6.ttf +0 -0
  75. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Regular.DxJTClRG.ttf +0 -0
  76. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-SemiBold.D3TTYgdB.ttf +0 -0
  77. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-VariableFont_wdth_wght.BZBpG5Iz.ttf +0 -0
  78. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.CefECEWA.css +1 -0
  79. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.D5tDcjY-.css +1 -0
  80. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.9X9_k6TP.css +1 -0
  81. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.BxiimdIO.css +1 -0
  82. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.Dx6SXgAb.css +1 -0
  83. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/transform._-1mPSEI.css +1 -0
  84. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/0dDyq72A.js +20 -0
  85. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/69_IOA4Y.js +1 -0
  86. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BK4An2kI.js +1 -0
  87. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BRmB-kJ9.js +1 -0
  88. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/B_1cpokE.js +1 -0
  89. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BiqpDEr0.js +1 -0
  90. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BpLiSKgx.js +1 -0
  91. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BscxbINH.js +39 -0
  92. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C1FmrZbK.js +1 -0
  93. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C80h3dJx.js +1 -0
  94. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C8mfFM-u.js +2 -0
  95. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CGY1p9L4.js +517 -0
  96. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/COfLknXM.js +1 -0
  97. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CWj6FrbW.js +1 -0
  98. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CYgJF_JY.js +1 -0
  99. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CmLg0ys7.js +1 -0
  100. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CvGjimpO.js +1 -0
  101. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D3RDXHoj.js +39 -0
  102. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D4y7iiT3.js +1 -0
  103. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D9SC3jBb.js +1 -0
  104. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DCuAdx1Q.js +20 -0
  105. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DDBy-_jD.js +1 -0
  106. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DIeogL5L.js +1 -0
  107. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DL9a7v5o.js +1 -0
  108. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DSKECuqX.js +39 -0
  109. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D_FFv0Oe.js +1 -0
  110. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DiZ5o5vz.js +1 -0
  111. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DkbXUtyG.js +1 -0
  112. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DmK2hulV.js +1 -0
  113. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DqnHaLTj.js +1 -0
  114. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DtWZc_tl.js +1 -0
  115. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DuUalyFS.js +1 -0
  116. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DwIonDAZ.js +1 -0
  117. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/Il-mSPmK.js +1 -0
  118. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KNLP4aJU.js +1 -0
  119. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KjYeVjkE.js +1 -0
  120. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/MErlcOXj.js +1 -0
  121. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VRI4prUD.js +1 -0
  122. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VYb2dkNs.js +1 -0
  123. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VqWvU2yF.js +1 -0
  124. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/dHC3otuL.js +1 -0
  125. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/da7Oy_lO.js +1 -0
  126. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/eAy8rZzC.js +2 -0
  127. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/erjNR5MX.js +1 -0
  128. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/f1oG3eFE.js +1 -0
  129. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rsLi1iKv.js +20 -0
  130. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rwuuBP9f.js +1 -0
  131. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/xGHZQ1pe.js +3 -0
  132. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/app.DrTRUgT3.js +2 -0
  133. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/start.BK5EOJl2.js +1 -0
  134. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/0.CIvTuljF.js +4 -0
  135. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/1.UBvSzxdA.js +1 -0
  136. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/10.CQ_tiLJa.js +1 -0
  137. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/11.KqkAcaxW.js +1 -0
  138. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/12.DoYsmxQc.js +1 -0
  139. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/13.571n2LZA.js +1 -0
  140. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/14.DGs689M-.js +1 -0
  141. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/15.CWG1ehzT.js +1 -0
  142. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/16.Dpq6jbSh.js +1 -0
  143. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/17.B5AZbHUU.js +1 -0
  144. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/18.CBga8cnq.js +1 -0
  145. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/2.D2HXgz-8.js +1090 -0
  146. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/3.f4HAg-y3.js +1 -0
  147. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/4.BKF4xuKQ.js +1 -0
  148. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/5.BAE0Pm_f.js +39 -0
  149. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/6.CouWWpzA.js +1 -0
  150. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/7.UBHT0ktp.js +1 -0
  151. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/8.FiYNElcc.js +1 -0
  152. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/9.B3-UaT23.js +1 -0
  153. lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/clustering.worker-DKqeLtG0.js +2 -0
  154. lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/search.worker-vNSty3B0.js +1 -0
  155. lightly_studio/dist_lightly_studio_view_app/_app/version.json +1 -0
  156. lightly_studio/dist_lightly_studio_view_app/apple-touch-icon-precomposed.png +0 -0
  157. lightly_studio/dist_lightly_studio_view_app/apple-touch-icon.png +0 -0
  158. lightly_studio/dist_lightly_studio_view_app/favicon.png +0 -0
  159. lightly_studio/dist_lightly_studio_view_app/index.html +45 -0
  160. lightly_studio/errors.py +5 -0
  161. lightly_studio/examples/example.py +25 -0
  162. lightly_studio/examples/example_coco.py +27 -0
  163. lightly_studio/examples/example_coco_caption.py +29 -0
  164. lightly_studio/examples/example_metadata.py +369 -0
  165. lightly_studio/examples/example_operators.py +111 -0
  166. lightly_studio/examples/example_selection.py +28 -0
  167. lightly_studio/examples/example_split_work.py +48 -0
  168. lightly_studio/examples/example_video.py +22 -0
  169. lightly_studio/examples/example_video_annotations.py +157 -0
  170. lightly_studio/examples/example_yolo.py +22 -0
  171. lightly_studio/export/coco_captions.py +69 -0
  172. lightly_studio/export/export_dataset.py +104 -0
  173. lightly_studio/export/lightly_studio_label_input.py +120 -0
  174. lightly_studio/export_schema.py +18 -0
  175. lightly_studio/export_version.py +57 -0
  176. lightly_studio/few_shot_classifier/__init__.py +0 -0
  177. lightly_studio/few_shot_classifier/classifier.py +80 -0
  178. lightly_studio/few_shot_classifier/classifier_manager.py +644 -0
  179. lightly_studio/few_shot_classifier/random_forest_classifier.py +495 -0
  180. lightly_studio/metadata/complex_metadata.py +47 -0
  181. lightly_studio/metadata/compute_similarity.py +84 -0
  182. lightly_studio/metadata/compute_typicality.py +67 -0
  183. lightly_studio/metadata/gps_coordinate.py +41 -0
  184. lightly_studio/metadata/metadata_protocol.py +17 -0
  185. lightly_studio/models/__init__.py +1 -0
  186. lightly_studio/models/annotation/__init__.py +0 -0
  187. lightly_studio/models/annotation/annotation_base.py +303 -0
  188. lightly_studio/models/annotation/instance_segmentation.py +56 -0
  189. lightly_studio/models/annotation/links.py +17 -0
  190. lightly_studio/models/annotation/object_detection.py +47 -0
  191. lightly_studio/models/annotation/semantic_segmentation.py +44 -0
  192. lightly_studio/models/annotation_label.py +47 -0
  193. lightly_studio/models/caption.py +49 -0
  194. lightly_studio/models/classifier.py +20 -0
  195. lightly_studio/models/dataset.py +70 -0
  196. lightly_studio/models/embedding_model.py +30 -0
  197. lightly_studio/models/image.py +96 -0
  198. lightly_studio/models/metadata.py +208 -0
  199. lightly_studio/models/range.py +17 -0
  200. lightly_studio/models/sample.py +154 -0
  201. lightly_studio/models/sample_embedding.py +36 -0
  202. lightly_studio/models/settings.py +69 -0
  203. lightly_studio/models/tag.py +96 -0
  204. lightly_studio/models/two_dim_embedding.py +16 -0
  205. lightly_studio/models/video.py +161 -0
  206. lightly_studio/plugins/__init__.py +0 -0
  207. lightly_studio/plugins/base_operator.py +60 -0
  208. lightly_studio/plugins/operator_registry.py +47 -0
  209. lightly_studio/plugins/parameter.py +70 -0
  210. lightly_studio/py.typed +0 -0
  211. lightly_studio/resolvers/__init__.py +0 -0
  212. lightly_studio/resolvers/annotation_label_resolver/__init__.py +22 -0
  213. lightly_studio/resolvers/annotation_label_resolver/create.py +27 -0
  214. lightly_studio/resolvers/annotation_label_resolver/delete.py +28 -0
  215. lightly_studio/resolvers/annotation_label_resolver/get_all.py +37 -0
  216. lightly_studio/resolvers/annotation_label_resolver/get_by_id.py +24 -0
  217. lightly_studio/resolvers/annotation_label_resolver/get_by_ids.py +25 -0
  218. lightly_studio/resolvers/annotation_label_resolver/get_by_label_name.py +24 -0
  219. lightly_studio/resolvers/annotation_label_resolver/names_by_ids.py +25 -0
  220. lightly_studio/resolvers/annotation_label_resolver/update.py +38 -0
  221. lightly_studio/resolvers/annotation_resolver/__init__.py +40 -0
  222. lightly_studio/resolvers/annotation_resolver/count_annotations_by_dataset.py +129 -0
  223. lightly_studio/resolvers/annotation_resolver/create_many.py +124 -0
  224. lightly_studio/resolvers/annotation_resolver/delete_annotation.py +87 -0
  225. lightly_studio/resolvers/annotation_resolver/delete_annotations.py +60 -0
  226. lightly_studio/resolvers/annotation_resolver/get_all.py +85 -0
  227. lightly_studio/resolvers/annotation_resolver/get_all_with_payload.py +179 -0
  228. lightly_studio/resolvers/annotation_resolver/get_by_id.py +34 -0
  229. lightly_studio/resolvers/annotation_resolver/get_by_id_with_payload.py +130 -0
  230. lightly_studio/resolvers/annotation_resolver/update_annotation_label.py +142 -0
  231. lightly_studio/resolvers/annotation_resolver/update_bounding_box.py +68 -0
  232. lightly_studio/resolvers/annotations/__init__.py +1 -0
  233. lightly_studio/resolvers/annotations/annotations_filter.py +88 -0
  234. lightly_studio/resolvers/caption_resolver.py +129 -0
  235. lightly_studio/resolvers/dataset_resolver/__init__.py +55 -0
  236. lightly_studio/resolvers/dataset_resolver/check_dataset_type.py +29 -0
  237. lightly_studio/resolvers/dataset_resolver/create.py +20 -0
  238. lightly_studio/resolvers/dataset_resolver/delete.py +20 -0
  239. lightly_studio/resolvers/dataset_resolver/export.py +267 -0
  240. lightly_studio/resolvers/dataset_resolver/get_all.py +19 -0
  241. lightly_studio/resolvers/dataset_resolver/get_by_id.py +16 -0
  242. lightly_studio/resolvers/dataset_resolver/get_by_name.py +12 -0
  243. lightly_studio/resolvers/dataset_resolver/get_dataset_details.py +27 -0
  244. lightly_studio/resolvers/dataset_resolver/get_hierarchy.py +31 -0
  245. lightly_studio/resolvers/dataset_resolver/get_or_create_child_dataset.py +58 -0
  246. lightly_studio/resolvers/dataset_resolver/get_parent_dataset_by_sample_id.py +27 -0
  247. lightly_studio/resolvers/dataset_resolver/get_parent_dataset_id.py +22 -0
  248. lightly_studio/resolvers/dataset_resolver/get_root_dataset.py +61 -0
  249. lightly_studio/resolvers/dataset_resolver/get_root_datasets_overview.py +41 -0
  250. lightly_studio/resolvers/dataset_resolver/update.py +25 -0
  251. lightly_studio/resolvers/embedding_model_resolver.py +120 -0
  252. lightly_studio/resolvers/image_filter.py +50 -0
  253. lightly_studio/resolvers/image_resolver/__init__.py +21 -0
  254. lightly_studio/resolvers/image_resolver/create_many.py +52 -0
  255. lightly_studio/resolvers/image_resolver/delete.py +20 -0
  256. lightly_studio/resolvers/image_resolver/filter_new_paths.py +23 -0
  257. lightly_studio/resolvers/image_resolver/get_all_by_dataset_id.py +117 -0
  258. lightly_studio/resolvers/image_resolver/get_by_id.py +14 -0
  259. lightly_studio/resolvers/image_resolver/get_dimension_bounds.py +75 -0
  260. lightly_studio/resolvers/image_resolver/get_many_by_id.py +22 -0
  261. lightly_studio/resolvers/image_resolver/get_samples_excluding.py +43 -0
  262. lightly_studio/resolvers/metadata_resolver/__init__.py +15 -0
  263. lightly_studio/resolvers/metadata_resolver/metadata_filter.py +163 -0
  264. lightly_studio/resolvers/metadata_resolver/sample/__init__.py +21 -0
  265. lightly_studio/resolvers/metadata_resolver/sample/bulk_update_metadata.py +46 -0
  266. lightly_studio/resolvers/metadata_resolver/sample/get_by_sample_id.py +24 -0
  267. lightly_studio/resolvers/metadata_resolver/sample/get_metadata_info.py +104 -0
  268. lightly_studio/resolvers/metadata_resolver/sample/get_value_for_sample.py +27 -0
  269. lightly_studio/resolvers/metadata_resolver/sample/set_value_for_sample.py +53 -0
  270. lightly_studio/resolvers/sample_embedding_resolver.py +132 -0
  271. lightly_studio/resolvers/sample_resolver/__init__.py +17 -0
  272. lightly_studio/resolvers/sample_resolver/count_by_dataset_id.py +16 -0
  273. lightly_studio/resolvers/sample_resolver/create.py +16 -0
  274. lightly_studio/resolvers/sample_resolver/create_many.py +25 -0
  275. lightly_studio/resolvers/sample_resolver/get_by_id.py +14 -0
  276. lightly_studio/resolvers/sample_resolver/get_filtered_samples.py +56 -0
  277. lightly_studio/resolvers/sample_resolver/get_many_by_id.py +22 -0
  278. lightly_studio/resolvers/sample_resolver/sample_filter.py +74 -0
  279. lightly_studio/resolvers/settings_resolver.py +62 -0
  280. lightly_studio/resolvers/tag_resolver.py +299 -0
  281. lightly_studio/resolvers/twodim_embedding_resolver.py +119 -0
  282. lightly_studio/resolvers/video_frame_resolver/__init__.py +23 -0
  283. lightly_studio/resolvers/video_frame_resolver/count_video_frames_annotations.py +83 -0
  284. lightly_studio/resolvers/video_frame_resolver/create_many.py +57 -0
  285. lightly_studio/resolvers/video_frame_resolver/get_all_by_dataset_id.py +63 -0
  286. lightly_studio/resolvers/video_frame_resolver/get_by_id.py +13 -0
  287. lightly_studio/resolvers/video_frame_resolver/get_table_fields_bounds.py +44 -0
  288. lightly_studio/resolvers/video_frame_resolver/video_frame_annotations_counter_filter.py +47 -0
  289. lightly_studio/resolvers/video_frame_resolver/video_frame_filter.py +57 -0
  290. lightly_studio/resolvers/video_resolver/__init__.py +27 -0
  291. lightly_studio/resolvers/video_resolver/count_video_frame_annotations_by_video_dataset.py +86 -0
  292. lightly_studio/resolvers/video_resolver/create_many.py +58 -0
  293. lightly_studio/resolvers/video_resolver/filter_new_paths.py +33 -0
  294. lightly_studio/resolvers/video_resolver/get_all_by_dataset_id.py +181 -0
  295. lightly_studio/resolvers/video_resolver/get_by_id.py +22 -0
  296. lightly_studio/resolvers/video_resolver/get_table_fields_bounds.py +72 -0
  297. lightly_studio/resolvers/video_resolver/get_view_by_id.py +52 -0
  298. lightly_studio/resolvers/video_resolver/video_count_annotations_filter.py +50 -0
  299. lightly_studio/resolvers/video_resolver/video_filter.py +98 -0
  300. lightly_studio/selection/__init__.py +1 -0
  301. lightly_studio/selection/mundig.py +143 -0
  302. lightly_studio/selection/select.py +203 -0
  303. lightly_studio/selection/select_via_db.py +273 -0
  304. lightly_studio/selection/selection_config.py +49 -0
  305. lightly_studio/services/annotations_service/__init__.py +33 -0
  306. lightly_studio/services/annotations_service/create_annotation.py +64 -0
  307. lightly_studio/services/annotations_service/delete_annotation.py +22 -0
  308. lightly_studio/services/annotations_service/get_annotation_by_id.py +31 -0
  309. lightly_studio/services/annotations_service/update_annotation.py +54 -0
  310. lightly_studio/services/annotations_service/update_annotation_bounding_box.py +36 -0
  311. lightly_studio/services/annotations_service/update_annotation_label.py +48 -0
  312. lightly_studio/services/annotations_service/update_annotations.py +29 -0
  313. lightly_studio/setup_logging.py +59 -0
  314. lightly_studio/type_definitions.py +31 -0
  315. lightly_studio/utils/__init__.py +3 -0
  316. lightly_studio/utils/download.py +94 -0
  317. lightly_studio/vendor/__init__.py +1 -0
  318. lightly_studio/vendor/mobileclip/ACKNOWLEDGEMENTS +422 -0
  319. lightly_studio/vendor/mobileclip/LICENSE +31 -0
  320. lightly_studio/vendor/mobileclip/LICENSE_weights_data +50 -0
  321. lightly_studio/vendor/mobileclip/README.md +5 -0
  322. lightly_studio/vendor/mobileclip/__init__.py +96 -0
  323. lightly_studio/vendor/mobileclip/clip.py +77 -0
  324. lightly_studio/vendor/mobileclip/configs/mobileclip_b.json +18 -0
  325. lightly_studio/vendor/mobileclip/configs/mobileclip_s0.json +18 -0
  326. lightly_studio/vendor/mobileclip/configs/mobileclip_s1.json +18 -0
  327. lightly_studio/vendor/mobileclip/configs/mobileclip_s2.json +18 -0
  328. lightly_studio/vendor/mobileclip/image_encoder.py +67 -0
  329. lightly_studio/vendor/mobileclip/logger.py +154 -0
  330. lightly_studio/vendor/mobileclip/models/__init__.py +10 -0
  331. lightly_studio/vendor/mobileclip/models/mci.py +933 -0
  332. lightly_studio/vendor/mobileclip/models/vit.py +433 -0
  333. lightly_studio/vendor/mobileclip/modules/__init__.py +4 -0
  334. lightly_studio/vendor/mobileclip/modules/common/__init__.py +4 -0
  335. lightly_studio/vendor/mobileclip/modules/common/mobileone.py +341 -0
  336. lightly_studio/vendor/mobileclip/modules/common/transformer.py +451 -0
  337. lightly_studio/vendor/mobileclip/modules/image/__init__.py +4 -0
  338. lightly_studio/vendor/mobileclip/modules/image/image_projection.py +113 -0
  339. lightly_studio/vendor/mobileclip/modules/image/replknet.py +188 -0
  340. lightly_studio/vendor/mobileclip/modules/text/__init__.py +4 -0
  341. lightly_studio/vendor/mobileclip/modules/text/repmixer.py +281 -0
  342. lightly_studio/vendor/mobileclip/modules/text/tokenizer.py +38 -0
  343. lightly_studio/vendor/mobileclip/text_encoder.py +245 -0
  344. lightly_studio/vendor/perception_encoder/LICENSE.PE +201 -0
  345. lightly_studio/vendor/perception_encoder/README.md +11 -0
  346. lightly_studio/vendor/perception_encoder/vision_encoder/__init__.py +0 -0
  347. lightly_studio/vendor/perception_encoder/vision_encoder/bpe_simple_vocab_16e6.txt.gz +0 -0
  348. lightly_studio/vendor/perception_encoder/vision_encoder/config.py +205 -0
  349. lightly_studio/vendor/perception_encoder/vision_encoder/config_src.py +264 -0
  350. lightly_studio/vendor/perception_encoder/vision_encoder/pe.py +766 -0
  351. lightly_studio/vendor/perception_encoder/vision_encoder/rope.py +352 -0
  352. lightly_studio/vendor/perception_encoder/vision_encoder/tokenizer.py +347 -0
  353. lightly_studio/vendor/perception_encoder/vision_encoder/transforms.py +36 -0
  354. lightly_studio-0.4.6.dist-info/METADATA +88 -0
  355. lightly_studio-0.4.6.dist-info/RECORD +356 -0
  356. lightly_studio-0.4.6.dist-info/WHEEL +4 -0
@@ -0,0 +1,52 @@
1
+ """Create annotation route."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from fastapi import APIRouter, Path
8
+ from fastapi.params import Body
9
+ from pydantic import BaseModel
10
+ from typing_extensions import Annotated
11
+
12
+ from lightly_studio.db_manager import SessionDep
13
+ from lightly_studio.models.annotation.annotation_base import (
14
+ AnnotationBaseTable,
15
+ AnnotationType,
16
+ AnnotationView,
17
+ )
18
+ from lightly_studio.services import annotations_service
19
+ from lightly_studio.services.annotations_service.create_annotation import AnnotationCreateParams
20
+
21
+ create_annotation_router = APIRouter()
22
+
23
+
24
+ class AnnotationCreateInput(BaseModel):
25
+ """API interface to create annotation."""
26
+
27
+ annotation_label_id: UUID
28
+ annotation_type: AnnotationType
29
+ parent_sample_id: UUID
30
+ x: int | None = None
31
+ y: int | None = None
32
+ width: int | None = None
33
+ height: int | None = None
34
+ segmentation_mask: list[int] | None = None
35
+
36
+
37
+ @create_annotation_router.post(
38
+ "/annotations",
39
+ response_model=AnnotationView,
40
+ )
41
+ def create_annotation(
42
+ dataset_id: Annotated[UUID, Path(title="Dataset Id", description="The ID of the dataset")],
43
+ session: SessionDep,
44
+ create_annotation_input: Annotated[AnnotationCreateInput, Body()],
45
+ ) -> AnnotationBaseTable:
46
+ """Create a new annotation."""
47
+ return annotations_service.create_annotation(
48
+ session=session,
49
+ annotation=AnnotationCreateParams(
50
+ dataset_id=dataset_id, **create_annotation_input.model_dump()
51
+ ),
52
+ )
@@ -0,0 +1,100 @@
1
+ """API routes for dataset captions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from fastapi import APIRouter, Body, HTTPException, Path
8
+ from pydantic import BaseModel
9
+ from typing_extensions import Annotated
10
+
11
+ from lightly_studio.api.routes.api.status import HTTP_STATUS_NOT_FOUND
12
+ from lightly_studio.db_manager import SessionDep
13
+ from lightly_studio.models.caption import CaptionCreate, CaptionTable, CaptionView
14
+ from lightly_studio.resolvers import caption_resolver, sample_resolver
15
+
16
+
17
+ # TODO(jonas, 11/2025): Use CaptionCreate instead when CaptionTable is linked to SampleTable.
18
+ class CaptionCreateInput(BaseModel):
19
+ """API interface to create caption."""
20
+
21
+ parent_sample_id: UUID
22
+ text: str = ""
23
+
24
+
25
+ captions_router = APIRouter(prefix="/datasets/{dataset_id}", tags=["captions"])
26
+
27
+
28
+ @captions_router.put("/captions/{sample_id}", response_model=CaptionView)
29
+ def update_caption_text(
30
+ session: SessionDep,
31
+ sample_id: Annotated[
32
+ UUID,
33
+ Path(title="Caption ID", description="ID of the caption to update"),
34
+ ],
35
+ text: Annotated[str, Body()],
36
+ ) -> CaptionTable:
37
+ """Update an existing caption in the database."""
38
+ return caption_resolver.update_text(session=session, sample_id=sample_id, text=text)
39
+
40
+
41
+ @captions_router.get("/captions/{sample_id}", response_model=CaptionView)
42
+ def get_caption(
43
+ session: SessionDep,
44
+ sample_id: Annotated[UUID, Path(title="Caption ID")],
45
+ ) -> CaptionTable:
46
+ """Retrieve an existing annotation from the database."""
47
+ captions = caption_resolver.get_by_ids(session, [sample_id])
48
+ if not captions:
49
+ raise ValueError(f"Caption with ID {sample_id} not found.")
50
+
51
+ return captions[0]
52
+
53
+
54
+ @captions_router.post(
55
+ "/captions",
56
+ response_model=CaptionView,
57
+ )
58
+ def create_caption(
59
+ session: SessionDep,
60
+ create_caption_input: Annotated[CaptionCreateInput, Body()],
61
+ ) -> CaptionTable:
62
+ """Create a new caption."""
63
+ # Get the parent sample
64
+ parent_sample = sample_resolver.get_by_id(
65
+ session=session, sample_id=create_caption_input.parent_sample_id
66
+ )
67
+ if parent_sample is None:
68
+ raise ValueError(f"Sample with ID {create_caption_input.parent_sample_id} not found.")
69
+
70
+ # Create the caption
71
+ sample_ids = caption_resolver.create_many(
72
+ session=session,
73
+ parent_dataset_id=parent_sample.dataset_id,
74
+ captions=[
75
+ CaptionCreate(
76
+ parent_sample_id=create_caption_input.parent_sample_id,
77
+ text=create_caption_input.text,
78
+ ),
79
+ ],
80
+ )
81
+ assert len(sample_ids) == 1, "Expected exactly one caption to be created."
82
+
83
+ # Fetch and return the created caption
84
+ return caption_resolver.get_by_ids(session=session, sample_ids=sample_ids)[0]
85
+
86
+
87
+ @captions_router.delete("/captions/{sample_id}")
88
+ def delete_caption(
89
+ session: SessionDep,
90
+ sample_id: Annotated[UUID, Path(title="Caption ID", description="ID of the caption to delete")],
91
+ ) -> dict[str, str]:
92
+ """Delete a caption from the database."""
93
+ try:
94
+ caption_resolver.delete_caption(session=session, sample_id=sample_id)
95
+ except ValueError as e:
96
+ raise HTTPException(
97
+ status_code=HTTP_STATUS_NOT_FOUND,
98
+ detail="Caption not found",
99
+ ) from e
100
+ return {"status": "deleted"}
@@ -0,0 +1,384 @@
1
+ """This module contains the API routes for managing classifiers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import io
6
+ from pathlib import Path
7
+ from uuid import UUID
8
+
9
+ from fastapi import APIRouter, UploadFile
10
+ from fastapi.responses import StreamingResponse
11
+ from pydantic import BaseModel
12
+
13
+ from lightly_studio.db_manager import SessionDep
14
+ from lightly_studio.few_shot_classifier.classifier import (
15
+ ExportType,
16
+ )
17
+ from lightly_studio.few_shot_classifier.classifier_manager import (
18
+ ClassifierManagerProvider,
19
+ )
20
+ from lightly_studio.models.classifier import EmbeddingClassifier
21
+
22
+ classifier_router = APIRouter()
23
+
24
+
25
+ class GetNegativeSamplesRequest(BaseModel):
26
+ """Request for getting negative samples for classifier training."""
27
+
28
+ positive_sample_ids: list[UUID]
29
+ dataset_id: UUID
30
+
31
+
32
+ class GetNegativeSamplesResponse(BaseModel):
33
+ """Response for getting negative samples for classifier training."""
34
+
35
+ negative_sample_ids: list[UUID]
36
+
37
+
38
+ @classifier_router.post("/classifiers/get_negative_samples")
39
+ def get_negative_samples(
40
+ request: GetNegativeSamplesRequest, session: SessionDep
41
+ ) -> GetNegativeSamplesResponse:
42
+ """Get negative samples for classifier training.
43
+
44
+ Args:
45
+ request: The request containing negative sample parameters.
46
+ session: Database session.
47
+
48
+ Returns:
49
+ The response containing negative sample IDs.
50
+ """
51
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
52
+ negative_samples = classifier_manager.provide_negative_samples(
53
+ session=session,
54
+ dataset_id=request.dataset_id,
55
+ selected_samples=request.positive_sample_ids,
56
+ )
57
+ # Extract just the sample IDs from the returned Sample objects
58
+ negative_sample_ids = [sample.sample_id for sample in negative_samples]
59
+ return GetNegativeSamplesResponse(negative_sample_ids=negative_sample_ids)
60
+
61
+
62
+ class SamplesToRefineResponse(BaseModel):
63
+ """Response for samples for classifier refinement.
64
+
65
+ Maps class names to lists of sample IDs. First class gets high confidence
66
+ samples, second class gets low confidence samples.
67
+ """
68
+
69
+ samples: dict[str, list[UUID]]
70
+
71
+
72
+ @classifier_router.get("/classifiers/{classifier_id}/samples_to_refine")
73
+ def samples_to_refine(
74
+ classifier_id: UUID,
75
+ dataset_id: UUID,
76
+ session: SessionDep,
77
+ ) -> SamplesToRefineResponse:
78
+ """Get samples for classifier refinement.
79
+
80
+ Args:
81
+ classifier_id: The ID of the classifier.
82
+ dataset_id: The ID of the dataset.
83
+ session: Database session.
84
+
85
+ Returns:
86
+ The response containing sample IDs for refinement.
87
+ """
88
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
89
+ samples = classifier_manager.get_samples_for_fine_tuning(
90
+ session=session, classifier_id=classifier_id, dataset_id=dataset_id
91
+ )
92
+ return SamplesToRefineResponse(samples=samples)
93
+
94
+
95
+ @classifier_router.get("/classifiers/{classifier_id}/sample_history")
96
+ def sample_history(
97
+ classifier_id: UUID,
98
+ ) -> SamplesToRefineResponse:
99
+ """Get all samples used in the classifier training.
100
+
101
+ Args:
102
+ classifier_id: The ID of the classifier.
103
+
104
+ Returns:
105
+ The response containing sample IDs used in the training.
106
+ """
107
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
108
+ samples = classifier_manager.get_annotations(classifier_id=classifier_id)
109
+ return SamplesToRefineResponse(samples=samples)
110
+
111
+
112
+ @classifier_router.post(
113
+ "/classifiers/{classifier_id}/commit_temp_classifier",
114
+ )
115
+ def commit_temp_classifier(
116
+ classifier_id: UUID,
117
+ ) -> None:
118
+ """Commit the classifier.
119
+
120
+ Args:
121
+ classifier_id: The ID of the classifier.
122
+
123
+ Returns:
124
+ None
125
+ """
126
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
127
+ classifier_manager.commit_temp_classifier(classifier_id=classifier_id)
128
+
129
+
130
+ @classifier_router.delete(
131
+ "/classifiers/{classifier_id}/drop_temp_classifier",
132
+ )
133
+ def drop_temp_classifier(
134
+ classifier_id: UUID,
135
+ ) -> None:
136
+ """Drop the classifier.
137
+
138
+ Args:
139
+ classifier_id: The ID of the classifier.
140
+
141
+ Returns:
142
+ None
143
+ """
144
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
145
+ classifier_manager.drop_temp_classifier(classifier_id=classifier_id)
146
+
147
+
148
+ class SaveClassifierRequest(BaseModel):
149
+ """Request for saving classifier to a file."""
150
+
151
+ file_path: str
152
+
153
+
154
+ @classifier_router.post(
155
+ "/classifiers/{classifier_id}/save_classifier_to_file/{export_type}",
156
+ )
157
+ def save_classifier_to_file(
158
+ classifier_id: UUID,
159
+ export_type: ExportType,
160
+ ) -> StreamingResponse:
161
+ """Save the classifier to a file.
162
+
163
+ Args:
164
+ classifier_id: The ID of the classifier.
165
+ export_type: The type of export (e.g., "sklearn", "lightly").
166
+
167
+ Returns:
168
+ StreamingResponse containing the pickled classifier file.
169
+ """
170
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
171
+ # Use BytesIO to capture the file content and send it as a response.
172
+ buffer = io.BytesIO()
173
+ classifier_manager.save_classifier_to_buffer(
174
+ classifier_id=classifier_id, buffer=buffer, export_type=export_type
175
+ )
176
+ buffer.seek(0)
177
+
178
+ # Get classifier name for the filename
179
+ classifier = classifier_manager.get_classifier_by_id(classifier_id=classifier_id)
180
+ filename = f"{classifier.classifier_name}.pkl"
181
+ headers = {
182
+ "Content-Disposition": f'attachment; filename="{filename}"',
183
+ "Content-Type": "application/octet-stream",
184
+ "Access-Control-Expose-Headers": "Content-Disposition",
185
+ }
186
+
187
+ return StreamingResponse(buffer, headers=headers, media_type="application/octet-stream")
188
+
189
+
190
+ class LoadClassifierRequest(BaseModel):
191
+ """Request for loading classifier from a file."""
192
+
193
+ file_path: str
194
+
195
+
196
+ class LoadClassifierResponse(BaseModel):
197
+ """Response for loading classifier from a file."""
198
+
199
+ classifier_id: UUID
200
+
201
+
202
+ @classifier_router.post(
203
+ "/classifiers/load_classifier_from_file",
204
+ )
205
+ def load_classifier_from_file(
206
+ request: LoadClassifierRequest,
207
+ session: SessionDep,
208
+ ) -> LoadClassifierResponse:
209
+ """Load the classifier from a file.
210
+
211
+ Args:
212
+ request: The request containing the file path.
213
+ session: Database session.
214
+
215
+ Returns:
216
+ Response with the ID of the loaded classifier.
217
+ """
218
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
219
+ classifier = classifier_manager.load_classifier_from_file(
220
+ session=session, file_path=Path(request.file_path)
221
+ )
222
+ return LoadClassifierResponse(classifier_id=classifier.classifier_id)
223
+
224
+
225
+ @classifier_router.post(
226
+ "/classifiers/load_classifier_from_buffer",
227
+ )
228
+ def load_classifier_from_buffer(
229
+ file: UploadFile,
230
+ session: SessionDep,
231
+ ) -> UUID:
232
+ """Load a classifier from an uploaded file buffer.
233
+
234
+ Args:
235
+ file: The uploaded classifier file.
236
+ session: Database session.
237
+
238
+ Returns:
239
+ The ID of the loaded classifier.
240
+ """
241
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
242
+
243
+ # Read file into buffer
244
+ buffer = io.BytesIO(file.file.read())
245
+
246
+ # Load classifier from buffer
247
+ classifier = classifier_manager.load_classifier_from_buffer(session=session, buffer=buffer)
248
+ return classifier.classifier_id
249
+
250
+
251
+ @classifier_router.post(
252
+ "/classifiers/{classifier_id}/train_classifier",
253
+ )
254
+ def train_classifier(
255
+ classifier_id: UUID,
256
+ session: SessionDep,
257
+ ) -> None:
258
+ """Train the classifier.
259
+
260
+ Args:
261
+ classifier_id: The ID of the classifier.
262
+ session: Database session.
263
+
264
+ Returns:
265
+ None
266
+ """
267
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
268
+ classifier_manager.train_classifier(session=session, classifier_id=classifier_id)
269
+
270
+
271
+ class UpdateAnnotationsRequest(BaseModel):
272
+ """Request for updating classifier annotations."""
273
+
274
+ annotations: dict[str, list[UUID]]
275
+
276
+
277
+ @classifier_router.post(
278
+ "/classifiers/{classifier_id}/update_annotations",
279
+ )
280
+ def update_classifiers_annotations(
281
+ classifier_id: UUID,
282
+ request: UpdateAnnotationsRequest,
283
+ ) -> None:
284
+ """Update the annotations for a classifier.
285
+
286
+ Args:
287
+ classifier_id: The ID of the classifier.
288
+ request: The request containing the new annotations.
289
+
290
+ Returns:
291
+ None
292
+
293
+ """
294
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
295
+ classifier_manager.update_classifiers_annotations(
296
+ classifier_id=classifier_id,
297
+ new_annotations=request.annotations,
298
+ )
299
+
300
+
301
+ class CreateClassifierRequest(BaseModel):
302
+ """Request model for creating a classifier."""
303
+
304
+ name: str
305
+ class_list: list[str]
306
+ dataset_id: UUID
307
+
308
+
309
+ class CreateClassifierResponse(BaseModel):
310
+ """Response model for creating a classifier."""
311
+
312
+ name: str
313
+ classifier_id: str
314
+
315
+
316
+ @classifier_router.post("/classifiers/create")
317
+ def create_classifier(
318
+ request: CreateClassifierRequest, session: SessionDep
319
+ ) -> CreateClassifierResponse:
320
+ """Create a new classifier.
321
+
322
+ Args:
323
+ request: The request containing classifier creation parameters.
324
+ session: Database session.
325
+
326
+ Returns:
327
+ Response with the name and ID of the classifier.
328
+
329
+ """
330
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
331
+ classifier = classifier_manager.create_classifier(
332
+ session=session,
333
+ name=request.name,
334
+ class_list=request.class_list,
335
+ dataset_id=request.dataset_id,
336
+ )
337
+ return CreateClassifierResponse(
338
+ name=classifier.few_shot_classifier.name,
339
+ classifier_id=str(classifier.classifier_id),
340
+ )
341
+
342
+
343
+ class GetAllClassifiersResponse(BaseModel):
344
+ """Response model for getting all active classifiers."""
345
+
346
+ classifiers: list[EmbeddingClassifier]
347
+
348
+
349
+ @classifier_router.get("/classifiers/get_all_classifiers")
350
+ def get_all_classifiers() -> GetAllClassifiersResponse:
351
+ """Get all active classifiers.
352
+
353
+ Returns:
354
+ Response with list of tuples containing classifier names and IDs.
355
+ """
356
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
357
+ classifiers = classifier_manager.get_all_classifiers()
358
+ return GetAllClassifiersResponse(classifiers=classifiers)
359
+
360
+
361
+ @classifier_router.post(
362
+ "/classifiers/{classifier_id}/run_on_dataset/{dataset_id}",
363
+ )
364
+ def run_classifier_route(
365
+ classifier_id: UUID,
366
+ dataset_id: UUID,
367
+ session: SessionDep,
368
+ ) -> None:
369
+ """Run the classifier on a dataset.
370
+
371
+ Args:
372
+ dataset_id: The ID of the dataset to run the classifier on.
373
+ classifier_id: The ID of the classifier.
374
+ session: Database session.
375
+
376
+ Returns:
377
+ None
378
+ """
379
+ classifier_manager = ClassifierManagerProvider.get_classifier_manager()
380
+ classifier_manager.run_classifier(
381
+ session=session,
382
+ classifier_id=classifier_id,
383
+ dataset_id=dataset_id,
384
+ )