orca-sdk 0.1.1__py3-none-any.whl → 0.1.2__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 (185) hide show
  1. orca_sdk/__init__.py +10 -4
  2. orca_sdk/_shared/__init__.py +10 -0
  3. orca_sdk/_shared/metrics.py +393 -0
  4. orca_sdk/_shared/metrics_test.py +273 -0
  5. orca_sdk/_utils/analysis_ui.py +12 -10
  6. orca_sdk/_utils/analysis_ui_style.css +0 -3
  7. orca_sdk/_utils/auth.py +27 -29
  8. orca_sdk/_utils/data_parsing.py +28 -2
  9. orca_sdk/_utils/data_parsing_test.py +15 -15
  10. orca_sdk/_utils/pagination.py +126 -0
  11. orca_sdk/_utils/pagination_test.py +132 -0
  12. orca_sdk/_utils/prediction_result_ui.py +67 -21
  13. orca_sdk/_utils/tqdm_file_reader.py +12 -0
  14. orca_sdk/_utils/value_parser.py +45 -0
  15. orca_sdk/_utils/value_parser_test.py +39 -0
  16. orca_sdk/classification_model.py +439 -129
  17. orca_sdk/classification_model_test.py +334 -104
  18. orca_sdk/client.py +3747 -0
  19. orca_sdk/conftest.py +164 -19
  20. orca_sdk/credentials.py +120 -18
  21. orca_sdk/credentials_test.py +20 -0
  22. orca_sdk/datasource.py +259 -68
  23. orca_sdk/datasource_test.py +242 -0
  24. orca_sdk/embedding_model.py +425 -82
  25. orca_sdk/embedding_model_test.py +39 -13
  26. orca_sdk/job.py +337 -0
  27. orca_sdk/job_test.py +108 -0
  28. orca_sdk/memoryset.py +1341 -305
  29. orca_sdk/memoryset_test.py +350 -111
  30. orca_sdk/regression_model.py +684 -0
  31. orca_sdk/regression_model_test.py +369 -0
  32. orca_sdk/telemetry.py +449 -143
  33. orca_sdk/telemetry_test.py +43 -24
  34. {orca_sdk-0.1.1.dist-info → orca_sdk-0.1.2.dist-info}/METADATA +34 -16
  35. orca_sdk-0.1.2.dist-info/RECORD +40 -0
  36. {orca_sdk-0.1.1.dist-info → orca_sdk-0.1.2.dist-info}/WHEEL +1 -1
  37. orca_sdk/_generated_api_client/__init__.py +0 -3
  38. orca_sdk/_generated_api_client/api/__init__.py +0 -193
  39. orca_sdk/_generated_api_client/api/auth/__init__.py +0 -0
  40. orca_sdk/_generated_api_client/api/auth/check_authentication_auth_get.py +0 -128
  41. orca_sdk/_generated_api_client/api/auth/create_api_key_auth_api_key_post.py +0 -170
  42. orca_sdk/_generated_api_client/api/auth/delete_api_key_auth_api_key_name_or_id_delete.py +0 -156
  43. orca_sdk/_generated_api_client/api/auth/delete_org_auth_org_delete.py +0 -130
  44. orca_sdk/_generated_api_client/api/auth/list_api_keys_auth_api_key_get.py +0 -127
  45. orca_sdk/_generated_api_client/api/classification_model/__init__.py +0 -0
  46. orca_sdk/_generated_api_client/api/classification_model/create_evaluation_classification_model_model_name_or_id_evaluation_post.py +0 -183
  47. orca_sdk/_generated_api_client/api/classification_model/create_model_classification_model_post.py +0 -170
  48. orca_sdk/_generated_api_client/api/classification_model/delete_evaluation_classification_model_model_name_or_id_evaluation_task_id_delete.py +0 -168
  49. orca_sdk/_generated_api_client/api/classification_model/delete_model_classification_model_name_or_id_delete.py +0 -154
  50. orca_sdk/_generated_api_client/api/classification_model/get_evaluation_classification_model_model_name_or_id_evaluation_task_id_get.py +0 -170
  51. orca_sdk/_generated_api_client/api/classification_model/get_model_classification_model_name_or_id_get.py +0 -156
  52. orca_sdk/_generated_api_client/api/classification_model/list_evaluations_classification_model_model_name_or_id_evaluation_get.py +0 -161
  53. orca_sdk/_generated_api_client/api/classification_model/list_models_classification_model_get.py +0 -127
  54. orca_sdk/_generated_api_client/api/classification_model/predict_gpu_classification_model_name_or_id_prediction_post.py +0 -190
  55. orca_sdk/_generated_api_client/api/datasource/__init__.py +0 -0
  56. orca_sdk/_generated_api_client/api/datasource/create_datasource_datasource_post.py +0 -167
  57. orca_sdk/_generated_api_client/api/datasource/delete_datasource_datasource_name_or_id_delete.py +0 -156
  58. orca_sdk/_generated_api_client/api/datasource/get_datasource_datasource_name_or_id_get.py +0 -156
  59. orca_sdk/_generated_api_client/api/datasource/list_datasources_datasource_get.py +0 -127
  60. orca_sdk/_generated_api_client/api/default/__init__.py +0 -0
  61. orca_sdk/_generated_api_client/api/default/healthcheck_get.py +0 -118
  62. orca_sdk/_generated_api_client/api/default/healthcheck_gpu_get.py +0 -118
  63. orca_sdk/_generated_api_client/api/finetuned_embedding_model/__init__.py +0 -0
  64. orca_sdk/_generated_api_client/api/finetuned_embedding_model/create_finetuned_embedding_model_finetuned_embedding_model_post.py +0 -168
  65. orca_sdk/_generated_api_client/api/finetuned_embedding_model/delete_finetuned_embedding_model_finetuned_embedding_model_name_or_id_delete.py +0 -156
  66. orca_sdk/_generated_api_client/api/finetuned_embedding_model/embed_with_finetuned_model_gpu_finetuned_embedding_model_name_or_id_embedding_post.py +0 -189
  67. orca_sdk/_generated_api_client/api/finetuned_embedding_model/get_finetuned_embedding_model_finetuned_embedding_model_name_or_id_get.py +0 -156
  68. orca_sdk/_generated_api_client/api/finetuned_embedding_model/list_finetuned_embedding_models_finetuned_embedding_model_get.py +0 -127
  69. orca_sdk/_generated_api_client/api/memoryset/__init__.py +0 -0
  70. orca_sdk/_generated_api_client/api/memoryset/clone_memoryset_memoryset_name_or_id_clone_post.py +0 -181
  71. orca_sdk/_generated_api_client/api/memoryset/create_analysis_memoryset_name_or_id_analysis_post.py +0 -183
  72. orca_sdk/_generated_api_client/api/memoryset/create_memoryset_memoryset_post.py +0 -168
  73. orca_sdk/_generated_api_client/api/memoryset/delete_memories_memoryset_name_or_id_memories_delete_post.py +0 -181
  74. orca_sdk/_generated_api_client/api/memoryset/delete_memory_memoryset_name_or_id_memory_memory_id_delete.py +0 -167
  75. orca_sdk/_generated_api_client/api/memoryset/delete_memoryset_memoryset_name_or_id_delete.py +0 -156
  76. orca_sdk/_generated_api_client/api/memoryset/get_analysis_memoryset_name_or_id_analysis_analysis_task_id_get.py +0 -169
  77. orca_sdk/_generated_api_client/api/memoryset/get_memories_memoryset_name_or_id_memories_get_post.py +0 -188
  78. orca_sdk/_generated_api_client/api/memoryset/get_memory_memoryset_name_or_id_memory_memory_id_get.py +0 -169
  79. orca_sdk/_generated_api_client/api/memoryset/get_memoryset_memoryset_name_or_id_get.py +0 -156
  80. orca_sdk/_generated_api_client/api/memoryset/insert_memories_gpu_memoryset_name_or_id_memory_post.py +0 -184
  81. orca_sdk/_generated_api_client/api/memoryset/list_analyses_memoryset_name_or_id_analysis_get.py +0 -260
  82. orca_sdk/_generated_api_client/api/memoryset/list_memorysets_memoryset_get.py +0 -127
  83. orca_sdk/_generated_api_client/api/memoryset/memoryset_lookup_gpu_memoryset_name_or_id_lookup_post.py +0 -193
  84. orca_sdk/_generated_api_client/api/memoryset/query_memoryset_memoryset_name_or_id_memories_post.py +0 -188
  85. orca_sdk/_generated_api_client/api/memoryset/update_memories_gpu_memoryset_name_or_id_memories_patch.py +0 -191
  86. orca_sdk/_generated_api_client/api/memoryset/update_memory_gpu_memoryset_name_or_id_memory_patch.py +0 -187
  87. orca_sdk/_generated_api_client/api/pretrained_embedding_model/__init__.py +0 -0
  88. orca_sdk/_generated_api_client/api/pretrained_embedding_model/embed_with_pretrained_model_gpu_pretrained_embedding_model_model_name_embedding_post.py +0 -188
  89. orca_sdk/_generated_api_client/api/pretrained_embedding_model/get_pretrained_embedding_model_pretrained_embedding_model_model_name_get.py +0 -157
  90. orca_sdk/_generated_api_client/api/pretrained_embedding_model/list_pretrained_embedding_models_pretrained_embedding_model_get.py +0 -127
  91. orca_sdk/_generated_api_client/api/task/__init__.py +0 -0
  92. orca_sdk/_generated_api_client/api/task/abort_task_task_task_id_abort_delete.py +0 -154
  93. orca_sdk/_generated_api_client/api/task/get_task_status_task_task_id_status_get.py +0 -156
  94. orca_sdk/_generated_api_client/api/task/list_tasks_task_get.py +0 -243
  95. orca_sdk/_generated_api_client/api/telemetry/__init__.py +0 -0
  96. orca_sdk/_generated_api_client/api/telemetry/drop_feedback_category_with_data_telemetry_feedback_category_name_or_id_delete.py +0 -162
  97. orca_sdk/_generated_api_client/api/telemetry/get_feedback_category_telemetry_feedback_category_name_or_id_get.py +0 -156
  98. orca_sdk/_generated_api_client/api/telemetry/get_prediction_telemetry_prediction_prediction_id_get.py +0 -157
  99. orca_sdk/_generated_api_client/api/telemetry/list_feedback_categories_telemetry_feedback_category_get.py +0 -127
  100. orca_sdk/_generated_api_client/api/telemetry/list_predictions_telemetry_prediction_post.py +0 -175
  101. orca_sdk/_generated_api_client/api/telemetry/record_prediction_feedback_telemetry_prediction_feedback_put.py +0 -171
  102. orca_sdk/_generated_api_client/api/telemetry/update_prediction_telemetry_prediction_prediction_id_patch.py +0 -181
  103. orca_sdk/_generated_api_client/client.py +0 -216
  104. orca_sdk/_generated_api_client/errors.py +0 -38
  105. orca_sdk/_generated_api_client/models/__init__.py +0 -159
  106. orca_sdk/_generated_api_client/models/analyze_neighbor_labels_result.py +0 -84
  107. orca_sdk/_generated_api_client/models/api_key_metadata.py +0 -118
  108. orca_sdk/_generated_api_client/models/base_model.py +0 -55
  109. orca_sdk/_generated_api_client/models/body_create_datasource_datasource_post.py +0 -176
  110. orca_sdk/_generated_api_client/models/classification_evaluation_result.py +0 -114
  111. orca_sdk/_generated_api_client/models/clone_labeled_memoryset_request.py +0 -150
  112. orca_sdk/_generated_api_client/models/column_info.py +0 -114
  113. orca_sdk/_generated_api_client/models/column_type.py +0 -14
  114. orca_sdk/_generated_api_client/models/conflict_error_response.py +0 -80
  115. orca_sdk/_generated_api_client/models/create_api_key_request.py +0 -99
  116. orca_sdk/_generated_api_client/models/create_api_key_response.py +0 -126
  117. orca_sdk/_generated_api_client/models/create_labeled_memoryset_request.py +0 -259
  118. orca_sdk/_generated_api_client/models/create_rac_model_request.py +0 -209
  119. orca_sdk/_generated_api_client/models/datasource_metadata.py +0 -142
  120. orca_sdk/_generated_api_client/models/delete_memories_request.py +0 -70
  121. orca_sdk/_generated_api_client/models/embed_request.py +0 -127
  122. orca_sdk/_generated_api_client/models/embedding_finetuning_method.py +0 -9
  123. orca_sdk/_generated_api_client/models/evaluation_request.py +0 -180
  124. orca_sdk/_generated_api_client/models/evaluation_response.py +0 -140
  125. orca_sdk/_generated_api_client/models/feedback_type.py +0 -9
  126. orca_sdk/_generated_api_client/models/field_validation_error.py +0 -103
  127. orca_sdk/_generated_api_client/models/filter_item.py +0 -231
  128. orca_sdk/_generated_api_client/models/filter_item_field_type_0_item.py +0 -15
  129. orca_sdk/_generated_api_client/models/filter_item_field_type_2_item_type_1.py +0 -16
  130. orca_sdk/_generated_api_client/models/filter_item_op.py +0 -16
  131. orca_sdk/_generated_api_client/models/find_duplicates_analysis_result.py +0 -70
  132. orca_sdk/_generated_api_client/models/finetune_embedding_model_request.py +0 -259
  133. orca_sdk/_generated_api_client/models/finetune_embedding_model_request_training_args.py +0 -66
  134. orca_sdk/_generated_api_client/models/finetuned_embedding_model_metadata.py +0 -166
  135. orca_sdk/_generated_api_client/models/get_memories_request.py +0 -70
  136. orca_sdk/_generated_api_client/models/internal_server_error_response.py +0 -80
  137. orca_sdk/_generated_api_client/models/label_class_metrics.py +0 -108
  138. orca_sdk/_generated_api_client/models/label_prediction_memory_lookup.py +0 -274
  139. orca_sdk/_generated_api_client/models/label_prediction_memory_lookup_metadata.py +0 -68
  140. orca_sdk/_generated_api_client/models/label_prediction_result.py +0 -101
  141. orca_sdk/_generated_api_client/models/label_prediction_with_memories_and_feedback.py +0 -232
  142. orca_sdk/_generated_api_client/models/labeled_memory.py +0 -197
  143. orca_sdk/_generated_api_client/models/labeled_memory_insert.py +0 -108
  144. orca_sdk/_generated_api_client/models/labeled_memory_insert_metadata.py +0 -68
  145. orca_sdk/_generated_api_client/models/labeled_memory_lookup.py +0 -258
  146. orca_sdk/_generated_api_client/models/labeled_memory_lookup_metadata.py +0 -68
  147. orca_sdk/_generated_api_client/models/labeled_memory_metadata.py +0 -68
  148. orca_sdk/_generated_api_client/models/labeled_memory_metrics.py +0 -277
  149. orca_sdk/_generated_api_client/models/labeled_memory_update.py +0 -171
  150. orca_sdk/_generated_api_client/models/labeled_memory_update_metadata_type_0.py +0 -68
  151. orca_sdk/_generated_api_client/models/labeled_memoryset_metadata.py +0 -195
  152. orca_sdk/_generated_api_client/models/list_analyses_memoryset_name_or_id_analysis_get_type_type_0.py +0 -9
  153. orca_sdk/_generated_api_client/models/list_memories_request.py +0 -104
  154. orca_sdk/_generated_api_client/models/list_predictions_request.py +0 -234
  155. orca_sdk/_generated_api_client/models/list_predictions_request_sort_item_item_type_0.py +0 -9
  156. orca_sdk/_generated_api_client/models/list_predictions_request_sort_item_item_type_1.py +0 -9
  157. orca_sdk/_generated_api_client/models/lookup_request.py +0 -81
  158. orca_sdk/_generated_api_client/models/memoryset_analysis_request.py +0 -83
  159. orca_sdk/_generated_api_client/models/memoryset_analysis_request_type.py +0 -9
  160. orca_sdk/_generated_api_client/models/memoryset_analysis_response.py +0 -180
  161. orca_sdk/_generated_api_client/models/memoryset_analysis_response_config.py +0 -66
  162. orca_sdk/_generated_api_client/models/memoryset_analysis_response_type.py +0 -9
  163. orca_sdk/_generated_api_client/models/not_found_error_response.py +0 -100
  164. orca_sdk/_generated_api_client/models/not_found_error_response_resource_type_0.py +0 -20
  165. orca_sdk/_generated_api_client/models/prediction_feedback.py +0 -157
  166. orca_sdk/_generated_api_client/models/prediction_feedback_category.py +0 -115
  167. orca_sdk/_generated_api_client/models/prediction_feedback_request.py +0 -122
  168. orca_sdk/_generated_api_client/models/prediction_feedback_result.py +0 -102
  169. orca_sdk/_generated_api_client/models/prediction_request.py +0 -169
  170. orca_sdk/_generated_api_client/models/pretrained_embedding_model_metadata.py +0 -97
  171. orca_sdk/_generated_api_client/models/pretrained_embedding_model_name.py +0 -11
  172. orca_sdk/_generated_api_client/models/rac_head_type.py +0 -11
  173. orca_sdk/_generated_api_client/models/rac_model_metadata.py +0 -191
  174. orca_sdk/_generated_api_client/models/service_unavailable_error_response.py +0 -80
  175. orca_sdk/_generated_api_client/models/task.py +0 -198
  176. orca_sdk/_generated_api_client/models/task_status.py +0 -14
  177. orca_sdk/_generated_api_client/models/task_status_info.py +0 -133
  178. orca_sdk/_generated_api_client/models/unauthenticated_error_response.py +0 -72
  179. orca_sdk/_generated_api_client/models/unauthorized_error_response.py +0 -80
  180. orca_sdk/_generated_api_client/models/unprocessable_input_error_response.py +0 -94
  181. orca_sdk/_generated_api_client/models/update_prediction_request.py +0 -93
  182. orca_sdk/_generated_api_client/py.typed +0 -1
  183. orca_sdk/_generated_api_client/types.py +0 -56
  184. orca_sdk/_utils/task.py +0 -73
  185. orca_sdk-0.1.1.dist-info/RECORD +0 -175
orca_sdk/conftest.py CHANGED
@@ -6,24 +6,51 @@ from uuid import uuid4
6
6
  import pytest
7
7
  from datasets import ClassLabel, Dataset, Features, Value
8
8
 
9
- from ._generated_api_client.client import set_headers
10
9
  from ._utils.auth import _create_api_key, _delete_org
11
10
  from .classification_model import ClassificationModel
11
+ from .client import orca_api
12
12
  from .credentials import OrcaCredentials
13
13
  from .datasource import Datasource
14
14
  from .embedding_model import PretrainedEmbeddingModel
15
- from .memoryset import LabeledMemoryset
15
+ from .memoryset import LabeledMemoryset, ScoredMemoryset
16
+ from .regression_model import RegressionModel
16
17
 
17
- logging.basicConfig(level=logging.INFO)
18
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
18
19
 
19
20
  os.environ["ORCA_API_URL"] = os.environ.get("ORCA_API_URL", "http://localhost:1584/")
20
21
 
22
+ os.environ["ORCA_SAVE_TELEMETRY_SYNCHRONOUSLY"] = "true"
23
+
24
+
25
+ def skip_in_prod(reason: str):
26
+ """Custom decorator to skip tests when running against production API"""
27
+ PROD_API_URLs = ["https://api.orcadb.ai", "https://api.staging.orcadb.ai"]
28
+ return pytest.mark.skipif(
29
+ os.environ["ORCA_API_URL"] in PROD_API_URLs,
30
+ reason=reason,
31
+ )
32
+
33
+
34
+ def skip_in_ci(reason: str):
35
+ """Custom decorator to skip tests when running in CI"""
36
+ return pytest.mark.skipif(
37
+ os.environ.get("GITHUB_ACTIONS", "false") == "true",
38
+ reason=reason,
39
+ )
40
+
21
41
 
22
42
  def _create_org_id():
23
43
  # UUID start to identify test data (0xtest...)
24
44
  return "10e50000-0000-4000-a000-" + str(uuid4())[24:]
25
45
 
26
46
 
47
+ @pytest.fixture()
48
+ def api_url_reset():
49
+ original_base_url = orca_api.base_url
50
+ yield
51
+ orca_api.base_url = original_base_url
52
+
53
+
27
54
  @pytest.fixture(scope="session")
28
55
  def org_id():
29
56
  return _create_org_id()
@@ -70,22 +97,44 @@ def label_names():
70
97
 
71
98
 
72
99
  SAMPLE_DATA = [
73
- {"text": "i love soup", "label": 0, "key": "val1", "score": 0.1, "source_id": "s1"},
74
- {"text": "cats are cute", "label": 1, "key": "val2", "score": 0.2, "source_id": "s2"},
75
- {"text": "soup is good", "label": 0, "key": "val3", "score": 0.3, "source_id": "s3"},
76
- {"text": "i love cats", "label": 1, "key": "val4", "score": 0.4, "source_id": "s4"},
77
- {"text": "everyone loves cats", "label": 1, "key": "val5", "score": 0.5, "source_id": "s5"},
78
- {"text": "soup is great for the winter", "label": 0, "key": "val6", "score": 0.6, "source_id": "s6"},
100
+ {"value": "i love soup", "label": 0, "key": "g1", "score": 0.1, "source_id": "s1"},
101
+ {"value": "cats are cute", "label": 1, "key": "g1", "score": 0.9, "source_id": "s2"},
102
+ {"value": "soup is good", "label": 0, "key": "g1", "score": 0.1, "source_id": "s3"},
103
+ {"value": "i love cats", "label": 1, "key": "g1", "score": 0.9, "source_id": "s4"},
104
+ {"value": "everyone loves cats", "label": 1, "key": "g1", "score": 0.9, "source_id": "s5"},
105
+ {"value": "soup is great for the winter", "label": 0, "key": "g1", "score": 0.1, "source_id": "s6"},
106
+ {"value": "hot soup on a rainy day!", "label": 0, "key": "g1", "score": 0.1, "source_id": "s7"},
107
+ {"value": "cats sleep all day", "label": 1, "key": "g1", "score": 0.9, "source_id": "s8"},
108
+ {"value": "homemade soup recipes", "label": 0, "key": "g1", "score": 0.1, "source_id": "s9"},
109
+ {"value": "cats purr when happy", "label": 1, "key": "g2", "score": 0.9, "source_id": "s10"},
110
+ {"value": "chicken noodle soup is classic", "label": 0, "key": "g1", "score": 0.1, "source_id": "s11"},
111
+ {"value": "kittens are baby cats", "label": 1, "key": "g2", "score": 0.9, "source_id": "s12"},
112
+ {"value": "soup can be served cold too", "label": 0, "key": "g1", "score": 0.1, "source_id": "s13"},
113
+ {"value": "cats have nine lives", "label": 1, "key": "g2", "score": 0.9, "source_id": "s14"},
114
+ {"value": "tomato soup with grilled cheese", "label": 0, "key": "g1", "score": 0.1, "source_id": "s15"},
115
+ {"value": "cats are independent animals", "label": 1, "key": "g2", "score": 0.9, "source_id": "s16"},
116
+ {"value": "the beach is always fun", "label": None, "key": "g3", "score": None, "source_id": "s17"},
117
+ {"value": "i love the beach", "label": None, "key": "g3", "score": None, "source_id": "s18"},
118
+ {"value": "the ocean is healing", "label": None, "key": "g3", "score": None, "source_id": "s19"},
119
+ {
120
+ "value": "sandy feet, sand between my toes at the beach",
121
+ "label": None,
122
+ "key": "g3",
123
+ "score": None,
124
+ "source_id": "s20",
125
+ },
126
+ {"value": "i am such a beach bum", "label": None, "key": "g3", "score": None, "source_id": "s21"},
127
+ {"value": "i will always want to be at the beach", "label": None, "key": "g3", "score": None, "source_id": "s22"},
79
128
  ]
80
129
 
81
130
 
82
131
  @pytest.fixture(scope="session")
83
- def hf_dataset(label_names):
132
+ def hf_dataset(label_names: list[str]) -> Dataset:
84
133
  return Dataset.from_list(
85
134
  SAMPLE_DATA,
86
135
  features=Features(
87
136
  {
88
- "text": Value("string"),
137
+ "value": Value("string"),
89
138
  "label": ClassLabel(names=label_names),
90
139
  "key": Value("string"),
91
140
  "score": Value("float"),
@@ -96,22 +145,118 @@ def hf_dataset(label_names):
96
145
 
97
146
 
98
147
  @pytest.fixture(scope="session")
99
- def datasource(hf_dataset) -> Datasource:
100
- return Datasource.from_hf_dataset("test_datasource", hf_dataset)
148
+ def datasource(hf_dataset: Dataset) -> Datasource:
149
+ datasource = Datasource.from_hf_dataset("test_datasource", hf_dataset)
150
+ return datasource
151
+
152
+
153
+ EVAL_DATASET = [
154
+ {"value": "chicken noodle soup is the best", "label": 1, "score": 0.9}, # mislabeled
155
+ {"value": "cats are cute", "label": 0, "score": 0.1}, # mislabeled
156
+ {"value": "soup is great for the winter", "label": 0, "score": 0.1},
157
+ {"value": "i love cats", "label": 1, "score": 0.9},
158
+ ]
159
+
160
+
161
+ @pytest.fixture(scope="session")
162
+ def eval_datasource() -> Datasource:
163
+ eval_datasource = Datasource.from_list("eval_datasource", EVAL_DATASET)
164
+ return eval_datasource
101
165
 
102
166
 
103
167
  @pytest.fixture(scope="session")
104
- def memoryset(datasource) -> LabeledMemoryset:
105
- return LabeledMemoryset.create(
106
- "test_memoryset",
168
+ def eval_dataset() -> Dataset:
169
+ eval_dataset = Dataset.from_list(EVAL_DATASET)
170
+ return eval_dataset
171
+
172
+
173
+ @pytest.fixture(scope="session")
174
+ def readonly_memoryset(datasource: Datasource) -> LabeledMemoryset:
175
+ memoryset = LabeledMemoryset.create(
176
+ "test_readonly_memoryset",
107
177
  datasource=datasource,
108
178
  embedding_model=PretrainedEmbeddingModel.GTE_BASE,
109
- value_column="text",
110
179
  source_id_column="source_id",
111
180
  max_seq_length_override=32,
181
+ index_type="IVF_FLAT",
182
+ index_params={"n_lists": 100},
112
183
  )
184
+ return memoryset
185
+
113
186
 
187
+ @pytest.fixture(scope="function")
188
+ def writable_memoryset(datasource: Datasource, api_key: str) -> Generator[LabeledMemoryset, None, None]:
189
+ """
190
+ Function-scoped fixture that provides a writable memoryset for tests that mutate state.
114
191
 
192
+ This fixture creates a fresh `LabeledMemoryset` named 'test_writable_memoryset' before each test.
193
+ After the test, it attempts to restore the memoryset to its initial state by deleting any added entries
194
+ and reinserting sample data — unless the memoryset has been dropped by the test itself, in which case
195
+ it will be recreated on the next invocation.
196
+
197
+ Note: Re-creating the memoryset from scratch is surprisingly more expensive than cleaning it up.
198
+ """
199
+ # It shouldn't be possible for this memoryset to already exist
200
+ memoryset = LabeledMemoryset.create(
201
+ "test_writable_memoryset",
202
+ datasource=datasource,
203
+ embedding_model=PretrainedEmbeddingModel.GTE_BASE,
204
+ source_id_column="source_id",
205
+ max_seq_length_override=32,
206
+ if_exists="open",
207
+ )
208
+ try:
209
+ yield memoryset
210
+ finally:
211
+ # Restore the memoryset to a clean state for the next test.
212
+ OrcaCredentials.set_api_key(api_key, check_validity=False)
213
+
214
+ if LabeledMemoryset.exists("test_writable_memoryset"):
215
+ memoryset.refresh()
216
+
217
+ memory_ids = [memoryset[i].memory_id for i in range(len(memoryset))]
218
+
219
+ if memory_ids:
220
+ memoryset.delete(memory_ids)
221
+ memoryset.refresh()
222
+ assert len(memoryset) == 0
223
+ memoryset.insert(SAMPLE_DATA)
224
+ # If the test dropped the memoryset, do nothing — it will be recreated on the next use.
225
+
226
+
227
+ @pytest.fixture(scope="session")
228
+ def classification_model(readonly_memoryset: LabeledMemoryset) -> ClassificationModel:
229
+ model = ClassificationModel.create(
230
+ "test_classification_model",
231
+ readonly_memoryset,
232
+ num_classes=2,
233
+ memory_lookup_count=3,
234
+ description="test_description",
235
+ )
236
+ return model
237
+
238
+
239
+ # Add scored memoryset and regression model fixtures
115
240
  @pytest.fixture(scope="session")
116
- def model(memoryset) -> ClassificationModel:
117
- return ClassificationModel.create("test_model", memoryset, num_classes=2, memory_lookup_count=3)
241
+ def scored_memoryset(datasource: Datasource) -> ScoredMemoryset:
242
+ memoryset = ScoredMemoryset.create(
243
+ "test_scored_memoryset",
244
+ datasource=datasource,
245
+ embedding_model=PretrainedEmbeddingModel.GTE_BASE,
246
+ source_id_column="source_id",
247
+ max_seq_length_override=32,
248
+ index_type="IVF_FLAT",
249
+ index_params={"n_lists": 100},
250
+ )
251
+ return memoryset
252
+
253
+
254
+ @pytest.fixture(scope="session")
255
+ def regression_model(scored_memoryset: ScoredMemoryset) -> RegressionModel:
256
+ model = RegressionModel.create(
257
+ "test_regression_model",
258
+ scored_memoryset,
259
+ memory_lookup_count=3,
260
+ description="test_regression_description",
261
+ )
262
+ return model
orca_sdk/credentials.py CHANGED
@@ -1,8 +1,18 @@
1
1
  from datetime import datetime
2
- from typing import NamedTuple
2
+ from typing import Literal, NamedTuple
3
3
 
4
- from ._generated_api_client.api import check_authentication, list_api_keys
5
- from ._generated_api_client.client import get_base_url, get_headers, set_headers
4
+ import httpx
5
+ from httpx import ConnectError, Headers
6
+
7
+ from .client import orca_api
8
+
9
+ Scope = Literal["ADMINISTER", "PREDICT"]
10
+ """
11
+ The scopes of an API key.
12
+
13
+ - `ADMINISTER`: Can do anything, including creating and deleting organizations, models, and API keys.
14
+ - `PREDICT`: Can only call model.predict and perform CRUD operations on predictions.
15
+ """
6
16
 
7
17
 
8
18
  class ApiKeyInfo(NamedTuple):
@@ -16,6 +26,7 @@ class ApiKeyInfo(NamedTuple):
16
26
 
17
27
  name: str
18
28
  created_at: datetime
29
+ scopes: set[Scope]
19
30
 
20
31
 
21
32
  class OrcaCredentials:
@@ -24,11 +35,33 @@ class OrcaCredentials:
24
35
  """
25
36
 
26
37
  @staticmethod
27
- def get_api_url() -> str:
38
+ def is_authenticated() -> bool:
28
39
  """
29
- Get the Orca API base URL that is currently being used
40
+ Check if you are authenticated to interact with the Orca API
41
+
42
+ Returns:
43
+ True if you are authenticated, False otherwise
30
44
  """
31
- return get_base_url()
45
+ try:
46
+ return orca_api.GET("/auth")
47
+ except ValueError as e:
48
+ if "Invalid API key" in str(e):
49
+ return False
50
+ raise e
51
+
52
+ @staticmethod
53
+ def is_healthy() -> bool:
54
+ """
55
+ Check whether the API is healthy
56
+
57
+ Returns:
58
+ True if the API is healthy, False otherwise
59
+ """
60
+ try:
61
+ orca_api.GET("/check/healthy")
62
+ except Exception:
63
+ return False
64
+ return True
32
65
 
33
66
  @staticmethod
34
67
  def list_api_keys() -> list[ApiKeyInfo]:
@@ -38,22 +71,45 @@ class OrcaCredentials:
38
71
  Returns:
39
72
  A list of named tuples, with the name and creation date time of the API key
40
73
  """
41
- return [ApiKeyInfo(name=api_key.name, created_at=api_key.created_at) for api_key in list_api_keys()]
74
+ return [
75
+ ApiKeyInfo(
76
+ name=api_key["name"],
77
+ created_at=datetime.fromisoformat(api_key["created_at"]),
78
+ scopes=set(api_key["scope"]),
79
+ )
80
+ for api_key in orca_api.GET("/auth/api_key")
81
+ ]
42
82
 
43
83
  @staticmethod
44
- def is_authenticated() -> bool:
84
+ def create_api_key(name: str, scopes: set[Scope] = {"ADMINISTER"}) -> str:
45
85
  """
46
- Check if you are authenticated to interact with the Orca API
86
+ Create a new API key with the given name and scopes
87
+
88
+ Params:
89
+ name: The name of the API key
90
+ scopes: The scopes of the API key
47
91
 
48
92
  Returns:
49
- True if you are authenticated, False otherwise
93
+ The secret value of the API key. Make sure to save this value as it will not be shown again.
50
94
  """
51
- try:
52
- return check_authentication()
53
- except ValueError as e:
54
- if "Invalid API key" in str(e):
55
- return False
56
- raise e
95
+ res = orca_api.POST(
96
+ "/auth/api_key",
97
+ json={"name": name, "scope": list(scopes)},
98
+ )
99
+ return res["api_key"]
100
+
101
+ @staticmethod
102
+ def revoke_api_key(name: str) -> None:
103
+ """
104
+ Delete an API key
105
+
106
+ Params:
107
+ name: The name of the API key to delete
108
+
109
+ Raises:
110
+ ValueError: if the API key is not found
111
+ """
112
+ orca_api.DELETE("/auth/api_key/{name_or_id}", params={"name_or_id": name})
57
113
 
58
114
  @staticmethod
59
115
  def set_api_key(api_key: str, check_validity: bool = True):
@@ -70,6 +126,52 @@ class OrcaCredentials:
70
126
  Raises:
71
127
  ValueError: if the API key is invalid and `check_validity` is True
72
128
  """
73
- set_headers(get_headers() | {"Api-Key": api_key})
129
+ OrcaCredentials.set_api_headers({"Api-Key": api_key})
74
130
  if check_validity:
75
- check_authentication()
131
+ orca_api.GET("/auth")
132
+
133
+ @staticmethod
134
+ def get_api_url() -> str:
135
+ """
136
+ Get the base URL of the Orca API that is currently being used
137
+ """
138
+ return str(orca_api.base_url)
139
+
140
+ @staticmethod
141
+ def set_api_url(url: str, check_validity: bool = True):
142
+ """
143
+ Set the base URL for the Orca API
144
+
145
+ Args:
146
+ url: The base URL to set
147
+ check_validity: Whether to check if there is an API running at the given base URL
148
+
149
+ Raises:
150
+ ValueError: if there is no healthy API running at the given base URL and `check_validity` is True
151
+ """
152
+ # check if the base url is reachable before setting it
153
+ if check_validity:
154
+ try:
155
+ httpx.get(url, timeout=1)
156
+ except ConnectError as e:
157
+ raise ValueError(f"No API found at {url}") from e
158
+
159
+ orca_api.base_url = url
160
+
161
+ # check if the api passes the health check
162
+ if check_validity:
163
+ OrcaCredentials.is_healthy()
164
+
165
+ @staticmethod
166
+ def set_api_headers(headers: dict[str, str]):
167
+ """
168
+ Add or override default HTTP headers for all Orca API requests.
169
+
170
+ Params:
171
+ headers: Mapping of header names to their string values
172
+
173
+ Notes:
174
+ New keys are merged into the existing headers, this will overwrite headers with the
175
+ same name, but leave other headers untouched.
176
+ """
177
+ orca_api.headers.update(Headers(headers))
@@ -2,6 +2,7 @@ from uuid import uuid4
2
2
 
3
3
  import pytest
4
4
 
5
+ from .client import orca_api
5
6
  from .credentials import OrcaCredentials
6
7
 
7
8
 
@@ -35,3 +36,22 @@ def test_set_invalid_api_key(api_key):
35
36
  with pytest.raises(ValueError, match="Invalid API key"):
36
37
  OrcaCredentials.set_api_key(str(uuid4()))
37
38
  assert not OrcaCredentials.is_authenticated()
39
+
40
+
41
+ def test_set_api_url(api_url_reset):
42
+ OrcaCredentials.set_api_url("http://api.orcadb.ai")
43
+ assert str(orca_api.base_url) == "http://api.orcadb.ai"
44
+
45
+
46
+ def test_set_invalid_base_url():
47
+ with pytest.raises(ValueError, match="No API found at http://localhost:1582"):
48
+ OrcaCredentials.set_api_url("http://localhost:1582")
49
+
50
+
51
+ def test_is_healthy():
52
+ assert OrcaCredentials.is_healthy()
53
+
54
+
55
+ def test_is_healthy_false(api_url_reset):
56
+ OrcaCredentials.set_api_url("http://localhost:1582", check_validity=False)
57
+ assert not OrcaCredentials.is_healthy()