orca-sdk 0.1.0__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 (175) hide show
  1. orca_sdk/__init__.py +19 -0
  2. orca_sdk/_generated_api_client/__init__.py +3 -0
  3. orca_sdk/_generated_api_client/api/__init__.py +193 -0
  4. orca_sdk/_generated_api_client/api/auth/__init__.py +0 -0
  5. orca_sdk/_generated_api_client/api/auth/check_authentication_auth_get.py +128 -0
  6. orca_sdk/_generated_api_client/api/auth/create_api_key_auth_api_key_post.py +170 -0
  7. orca_sdk/_generated_api_client/api/auth/delete_api_key_auth_api_key_name_or_id_delete.py +156 -0
  8. orca_sdk/_generated_api_client/api/auth/delete_org_auth_org_delete.py +130 -0
  9. orca_sdk/_generated_api_client/api/auth/list_api_keys_auth_api_key_get.py +127 -0
  10. orca_sdk/_generated_api_client/api/classification_model/__init__.py +0 -0
  11. orca_sdk/_generated_api_client/api/classification_model/create_evaluation_classification_model_model_name_or_id_evaluation_post.py +183 -0
  12. orca_sdk/_generated_api_client/api/classification_model/create_model_classification_model_post.py +170 -0
  13. orca_sdk/_generated_api_client/api/classification_model/delete_evaluation_classification_model_model_name_or_id_evaluation_task_id_delete.py +168 -0
  14. orca_sdk/_generated_api_client/api/classification_model/delete_model_classification_model_name_or_id_delete.py +154 -0
  15. orca_sdk/_generated_api_client/api/classification_model/get_evaluation_classification_model_model_name_or_id_evaluation_task_id_get.py +170 -0
  16. orca_sdk/_generated_api_client/api/classification_model/get_model_classification_model_name_or_id_get.py +156 -0
  17. orca_sdk/_generated_api_client/api/classification_model/list_evaluations_classification_model_model_name_or_id_evaluation_get.py +161 -0
  18. orca_sdk/_generated_api_client/api/classification_model/list_models_classification_model_get.py +127 -0
  19. orca_sdk/_generated_api_client/api/classification_model/predict_gpu_classification_model_name_or_id_prediction_post.py +190 -0
  20. orca_sdk/_generated_api_client/api/datasource/__init__.py +0 -0
  21. orca_sdk/_generated_api_client/api/datasource/create_datasource_datasource_post.py +167 -0
  22. orca_sdk/_generated_api_client/api/datasource/delete_datasource_datasource_name_or_id_delete.py +156 -0
  23. orca_sdk/_generated_api_client/api/datasource/get_datasource_datasource_name_or_id_get.py +156 -0
  24. orca_sdk/_generated_api_client/api/datasource/list_datasources_datasource_get.py +127 -0
  25. orca_sdk/_generated_api_client/api/default/__init__.py +0 -0
  26. orca_sdk/_generated_api_client/api/default/healthcheck_get.py +118 -0
  27. orca_sdk/_generated_api_client/api/default/healthcheck_gpu_get.py +118 -0
  28. orca_sdk/_generated_api_client/api/finetuned_embedding_model/__init__.py +0 -0
  29. orca_sdk/_generated_api_client/api/finetuned_embedding_model/create_finetuned_embedding_model_finetuned_embedding_model_post.py +168 -0
  30. orca_sdk/_generated_api_client/api/finetuned_embedding_model/delete_finetuned_embedding_model_finetuned_embedding_model_name_or_id_delete.py +156 -0
  31. orca_sdk/_generated_api_client/api/finetuned_embedding_model/embed_with_finetuned_model_gpu_finetuned_embedding_model_name_or_id_embedding_post.py +189 -0
  32. orca_sdk/_generated_api_client/api/finetuned_embedding_model/get_finetuned_embedding_model_finetuned_embedding_model_name_or_id_get.py +156 -0
  33. orca_sdk/_generated_api_client/api/finetuned_embedding_model/list_finetuned_embedding_models_finetuned_embedding_model_get.py +127 -0
  34. orca_sdk/_generated_api_client/api/memoryset/__init__.py +0 -0
  35. orca_sdk/_generated_api_client/api/memoryset/clone_memoryset_memoryset_name_or_id_clone_post.py +181 -0
  36. orca_sdk/_generated_api_client/api/memoryset/create_analysis_memoryset_name_or_id_analysis_post.py +183 -0
  37. orca_sdk/_generated_api_client/api/memoryset/create_memoryset_memoryset_post.py +168 -0
  38. orca_sdk/_generated_api_client/api/memoryset/delete_memories_memoryset_name_or_id_memories_delete_post.py +181 -0
  39. orca_sdk/_generated_api_client/api/memoryset/delete_memory_memoryset_name_or_id_memory_memory_id_delete.py +167 -0
  40. orca_sdk/_generated_api_client/api/memoryset/delete_memoryset_memoryset_name_or_id_delete.py +156 -0
  41. orca_sdk/_generated_api_client/api/memoryset/get_analysis_memoryset_name_or_id_analysis_analysis_task_id_get.py +169 -0
  42. orca_sdk/_generated_api_client/api/memoryset/get_memories_memoryset_name_or_id_memories_get_post.py +188 -0
  43. orca_sdk/_generated_api_client/api/memoryset/get_memory_memoryset_name_or_id_memory_memory_id_get.py +169 -0
  44. orca_sdk/_generated_api_client/api/memoryset/get_memoryset_memoryset_name_or_id_get.py +156 -0
  45. orca_sdk/_generated_api_client/api/memoryset/insert_memories_gpu_memoryset_name_or_id_memory_post.py +184 -0
  46. orca_sdk/_generated_api_client/api/memoryset/list_analyses_memoryset_name_or_id_analysis_get.py +260 -0
  47. orca_sdk/_generated_api_client/api/memoryset/list_memorysets_memoryset_get.py +127 -0
  48. orca_sdk/_generated_api_client/api/memoryset/memoryset_lookup_gpu_memoryset_name_or_id_lookup_post.py +193 -0
  49. orca_sdk/_generated_api_client/api/memoryset/query_memoryset_memoryset_name_or_id_memories_post.py +188 -0
  50. orca_sdk/_generated_api_client/api/memoryset/update_memories_gpu_memoryset_name_or_id_memories_patch.py +191 -0
  51. orca_sdk/_generated_api_client/api/memoryset/update_memory_gpu_memoryset_name_or_id_memory_patch.py +187 -0
  52. orca_sdk/_generated_api_client/api/pretrained_embedding_model/__init__.py +0 -0
  53. orca_sdk/_generated_api_client/api/pretrained_embedding_model/embed_with_pretrained_model_gpu_pretrained_embedding_model_model_name_embedding_post.py +188 -0
  54. orca_sdk/_generated_api_client/api/pretrained_embedding_model/get_pretrained_embedding_model_pretrained_embedding_model_model_name_get.py +157 -0
  55. orca_sdk/_generated_api_client/api/pretrained_embedding_model/list_pretrained_embedding_models_pretrained_embedding_model_get.py +127 -0
  56. orca_sdk/_generated_api_client/api/task/__init__.py +0 -0
  57. orca_sdk/_generated_api_client/api/task/abort_task_task_task_id_abort_delete.py +154 -0
  58. orca_sdk/_generated_api_client/api/task/get_task_status_task_task_id_status_get.py +156 -0
  59. orca_sdk/_generated_api_client/api/task/list_tasks_task_get.py +243 -0
  60. orca_sdk/_generated_api_client/api/telemetry/__init__.py +0 -0
  61. orca_sdk/_generated_api_client/api/telemetry/drop_feedback_category_with_data_telemetry_feedback_category_name_or_id_delete.py +162 -0
  62. orca_sdk/_generated_api_client/api/telemetry/get_feedback_category_telemetry_feedback_category_name_or_id_get.py +156 -0
  63. orca_sdk/_generated_api_client/api/telemetry/get_prediction_telemetry_prediction_prediction_id_get.py +157 -0
  64. orca_sdk/_generated_api_client/api/telemetry/list_feedback_categories_telemetry_feedback_category_get.py +127 -0
  65. orca_sdk/_generated_api_client/api/telemetry/list_predictions_telemetry_prediction_post.py +175 -0
  66. orca_sdk/_generated_api_client/api/telemetry/record_prediction_feedback_telemetry_prediction_feedback_put.py +171 -0
  67. orca_sdk/_generated_api_client/api/telemetry/update_prediction_telemetry_prediction_prediction_id_patch.py +181 -0
  68. orca_sdk/_generated_api_client/client.py +216 -0
  69. orca_sdk/_generated_api_client/errors.py +38 -0
  70. orca_sdk/_generated_api_client/models/__init__.py +159 -0
  71. orca_sdk/_generated_api_client/models/analyze_neighbor_labels_result.py +84 -0
  72. orca_sdk/_generated_api_client/models/api_key_metadata.py +118 -0
  73. orca_sdk/_generated_api_client/models/base_model.py +55 -0
  74. orca_sdk/_generated_api_client/models/body_create_datasource_datasource_post.py +176 -0
  75. orca_sdk/_generated_api_client/models/classification_evaluation_result.py +114 -0
  76. orca_sdk/_generated_api_client/models/clone_labeled_memoryset_request.py +150 -0
  77. orca_sdk/_generated_api_client/models/column_info.py +114 -0
  78. orca_sdk/_generated_api_client/models/column_type.py +14 -0
  79. orca_sdk/_generated_api_client/models/conflict_error_response.py +80 -0
  80. orca_sdk/_generated_api_client/models/create_api_key_request.py +99 -0
  81. orca_sdk/_generated_api_client/models/create_api_key_response.py +126 -0
  82. orca_sdk/_generated_api_client/models/create_labeled_memoryset_request.py +259 -0
  83. orca_sdk/_generated_api_client/models/create_rac_model_request.py +209 -0
  84. orca_sdk/_generated_api_client/models/datasource_metadata.py +142 -0
  85. orca_sdk/_generated_api_client/models/delete_memories_request.py +70 -0
  86. orca_sdk/_generated_api_client/models/embed_request.py +127 -0
  87. orca_sdk/_generated_api_client/models/embedding_finetuning_method.py +9 -0
  88. orca_sdk/_generated_api_client/models/evaluation_request.py +180 -0
  89. orca_sdk/_generated_api_client/models/evaluation_response.py +140 -0
  90. orca_sdk/_generated_api_client/models/feedback_type.py +9 -0
  91. orca_sdk/_generated_api_client/models/field_validation_error.py +103 -0
  92. orca_sdk/_generated_api_client/models/filter_item.py +231 -0
  93. orca_sdk/_generated_api_client/models/filter_item_field_type_0_item.py +15 -0
  94. orca_sdk/_generated_api_client/models/filter_item_field_type_2_item_type_1.py +16 -0
  95. orca_sdk/_generated_api_client/models/filter_item_op.py +16 -0
  96. orca_sdk/_generated_api_client/models/find_duplicates_analysis_result.py +70 -0
  97. orca_sdk/_generated_api_client/models/finetune_embedding_model_request.py +259 -0
  98. orca_sdk/_generated_api_client/models/finetune_embedding_model_request_training_args.py +66 -0
  99. orca_sdk/_generated_api_client/models/finetuned_embedding_model_metadata.py +166 -0
  100. orca_sdk/_generated_api_client/models/get_memories_request.py +70 -0
  101. orca_sdk/_generated_api_client/models/internal_server_error_response.py +80 -0
  102. orca_sdk/_generated_api_client/models/label_class_metrics.py +108 -0
  103. orca_sdk/_generated_api_client/models/label_prediction_memory_lookup.py +274 -0
  104. orca_sdk/_generated_api_client/models/label_prediction_memory_lookup_metadata.py +68 -0
  105. orca_sdk/_generated_api_client/models/label_prediction_result.py +101 -0
  106. orca_sdk/_generated_api_client/models/label_prediction_with_memories_and_feedback.py +232 -0
  107. orca_sdk/_generated_api_client/models/labeled_memory.py +197 -0
  108. orca_sdk/_generated_api_client/models/labeled_memory_insert.py +108 -0
  109. orca_sdk/_generated_api_client/models/labeled_memory_insert_metadata.py +68 -0
  110. orca_sdk/_generated_api_client/models/labeled_memory_lookup.py +258 -0
  111. orca_sdk/_generated_api_client/models/labeled_memory_lookup_metadata.py +68 -0
  112. orca_sdk/_generated_api_client/models/labeled_memory_metadata.py +68 -0
  113. orca_sdk/_generated_api_client/models/labeled_memory_metrics.py +277 -0
  114. orca_sdk/_generated_api_client/models/labeled_memory_update.py +171 -0
  115. orca_sdk/_generated_api_client/models/labeled_memory_update_metadata_type_0.py +68 -0
  116. orca_sdk/_generated_api_client/models/labeled_memoryset_metadata.py +195 -0
  117. orca_sdk/_generated_api_client/models/list_analyses_memoryset_name_or_id_analysis_get_type_type_0.py +9 -0
  118. orca_sdk/_generated_api_client/models/list_memories_request.py +104 -0
  119. orca_sdk/_generated_api_client/models/list_predictions_request.py +234 -0
  120. orca_sdk/_generated_api_client/models/list_predictions_request_sort_item_item_type_0.py +9 -0
  121. orca_sdk/_generated_api_client/models/list_predictions_request_sort_item_item_type_1.py +9 -0
  122. orca_sdk/_generated_api_client/models/lookup_request.py +81 -0
  123. orca_sdk/_generated_api_client/models/memoryset_analysis_request.py +83 -0
  124. orca_sdk/_generated_api_client/models/memoryset_analysis_request_type.py +9 -0
  125. orca_sdk/_generated_api_client/models/memoryset_analysis_response.py +180 -0
  126. orca_sdk/_generated_api_client/models/memoryset_analysis_response_config.py +66 -0
  127. orca_sdk/_generated_api_client/models/memoryset_analysis_response_type.py +9 -0
  128. orca_sdk/_generated_api_client/models/not_found_error_response.py +100 -0
  129. orca_sdk/_generated_api_client/models/not_found_error_response_resource_type_0.py +20 -0
  130. orca_sdk/_generated_api_client/models/prediction_feedback.py +157 -0
  131. orca_sdk/_generated_api_client/models/prediction_feedback_category.py +115 -0
  132. orca_sdk/_generated_api_client/models/prediction_feedback_request.py +122 -0
  133. orca_sdk/_generated_api_client/models/prediction_feedback_result.py +102 -0
  134. orca_sdk/_generated_api_client/models/prediction_request.py +169 -0
  135. orca_sdk/_generated_api_client/models/pretrained_embedding_model_metadata.py +97 -0
  136. orca_sdk/_generated_api_client/models/pretrained_embedding_model_name.py +11 -0
  137. orca_sdk/_generated_api_client/models/rac_head_type.py +11 -0
  138. orca_sdk/_generated_api_client/models/rac_model_metadata.py +191 -0
  139. orca_sdk/_generated_api_client/models/service_unavailable_error_response.py +80 -0
  140. orca_sdk/_generated_api_client/models/task.py +198 -0
  141. orca_sdk/_generated_api_client/models/task_status.py +14 -0
  142. orca_sdk/_generated_api_client/models/task_status_info.py +133 -0
  143. orca_sdk/_generated_api_client/models/unauthenticated_error_response.py +72 -0
  144. orca_sdk/_generated_api_client/models/unauthorized_error_response.py +80 -0
  145. orca_sdk/_generated_api_client/models/unprocessable_input_error_response.py +94 -0
  146. orca_sdk/_generated_api_client/models/update_prediction_request.py +93 -0
  147. orca_sdk/_generated_api_client/py.typed +1 -0
  148. orca_sdk/_generated_api_client/types.py +56 -0
  149. orca_sdk/_utils/__init__.py +0 -0
  150. orca_sdk/_utils/analysis_ui.py +194 -0
  151. orca_sdk/_utils/analysis_ui_style.css +54 -0
  152. orca_sdk/_utils/auth.py +63 -0
  153. orca_sdk/_utils/auth_test.py +31 -0
  154. orca_sdk/_utils/common.py +37 -0
  155. orca_sdk/_utils/data_parsing.py +99 -0
  156. orca_sdk/_utils/data_parsing_test.py +244 -0
  157. orca_sdk/_utils/prediction_result_ui.css +18 -0
  158. orca_sdk/_utils/prediction_result_ui.py +64 -0
  159. orca_sdk/_utils/task.py +73 -0
  160. orca_sdk/classification_model.py +499 -0
  161. orca_sdk/classification_model_test.py +266 -0
  162. orca_sdk/conftest.py +117 -0
  163. orca_sdk/datasource.py +333 -0
  164. orca_sdk/datasource_test.py +95 -0
  165. orca_sdk/embedding_model.py +336 -0
  166. orca_sdk/embedding_model_test.py +173 -0
  167. orca_sdk/labeled_memoryset.py +1154 -0
  168. orca_sdk/labeled_memoryset_test.py +271 -0
  169. orca_sdk/orca_credentials.py +75 -0
  170. orca_sdk/orca_credentials_test.py +37 -0
  171. orca_sdk/telemetry.py +386 -0
  172. orca_sdk/telemetry_test.py +100 -0
  173. orca_sdk-0.1.0.dist-info/METADATA +39 -0
  174. orca_sdk-0.1.0.dist-info/RECORD +175 -0
  175. orca_sdk-0.1.0.dist-info/WHEEL +4 -0
orca_sdk/telemetry.py ADDED
@@ -0,0 +1,386 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from datetime import datetime
5
+ from typing import TYPE_CHECKING, Any, Iterable, overload
6
+ from uuid import UUID
7
+
8
+ from orca_sdk._utils.common import UNSET
9
+
10
+ from ._generated_api_client.api import (
11
+ drop_feedback_category_with_data,
12
+ get_prediction,
13
+ list_feedback_categories,
14
+ list_predictions,
15
+ record_prediction_feedback,
16
+ update_prediction,
17
+ )
18
+ from ._generated_api_client.models import (
19
+ FeedbackType,
20
+ LabelPredictionWithMemoriesAndFeedback,
21
+ ListPredictionsRequest,
22
+ PredictionFeedbackCategory,
23
+ PredictionFeedbackRequest,
24
+ UpdatePredictionRequest,
25
+ )
26
+ from ._generated_api_client.types import UNSET as CLIENT_UNSET
27
+ from ._utils.prediction_result_ui import inspect_prediction_result
28
+ from .labeled_memoryset import LabeledMemoryLookup, LabeledMemoryset
29
+
30
+ if TYPE_CHECKING:
31
+ from .classification_model import ClassificationModel
32
+
33
+
34
+ def _parse_feedback(feedback: dict[str, Any]) -> PredictionFeedbackRequest:
35
+ category = feedback.get("category", None)
36
+ if category is None:
37
+ raise ValueError("`category` must be specified")
38
+ prediction_id = feedback.get("prediction_id", None)
39
+ if prediction_id is None:
40
+ raise ValueError("`prediction_id` must be specified")
41
+ return PredictionFeedbackRequest(
42
+ prediction_id=prediction_id,
43
+ category_name=category,
44
+ value=feedback.get("value", CLIENT_UNSET),
45
+ comment=feedback.get("comment", CLIENT_UNSET),
46
+ )
47
+
48
+
49
+ class FeedbackCategory:
50
+ """
51
+ A category of feedback for predictions.
52
+
53
+ Categories are created automatically, the first time feedback with a new name is recorded.
54
+ The value type of the category is inferred from the first recorded value. Subsequent feedback
55
+ for the same category must be of the same type. Categories are not model specific.
56
+
57
+ Attributes:
58
+ id: Unique identifier for the category.
59
+ name: Name of the category.
60
+ value_type: Type that values for this category must have.
61
+ created_at: When the category was created.
62
+ """
63
+
64
+ id: str
65
+ name: str
66
+ value_type: type[bool] | type[float]
67
+ created_at: datetime
68
+
69
+ def __init__(self, category: PredictionFeedbackCategory):
70
+ # for internal use only, do not document
71
+ self.id = category.id
72
+ self.name = category.name
73
+ self.value_type = bool if category.type == FeedbackType.BINARY else float
74
+ self.created_at = category.created_at
75
+
76
+ @classmethod
77
+ def all(cls) -> list[FeedbackCategory]:
78
+ """
79
+ Get a list of all existing feedback categories.
80
+
81
+ Returns:
82
+ List with information about all existing feedback categories.
83
+ """
84
+ return [FeedbackCategory(category) for category in list_feedback_categories()]
85
+
86
+ @classmethod
87
+ def drop(cls, name: str) -> None:
88
+ """
89
+ Drop all feedback for this category and drop the category itself, allowing it to be
90
+ recreated with a different value type.
91
+
92
+ Warning:
93
+ This will delete all feedback in this category across all models.
94
+
95
+ Params:
96
+ name: Name of the category to drop.
97
+
98
+ Raises:
99
+ LookupError: If the category is not found.
100
+ """
101
+ drop_feedback_category_with_data(name)
102
+ logging.info(f"Dropped feedback category {name} with all associated feedback")
103
+
104
+ def __repr__(self):
105
+ return "FeedbackCategory({" + f"name: {self.name}, " + f"value_type: {self.value_type}" + "})"
106
+
107
+
108
+ class LabelPrediction:
109
+ """
110
+ A prediction made by a model
111
+
112
+ Attributes:
113
+ prediction_id: Unique identifier for the prediction
114
+ label: Predicted label for the input value
115
+ label_name: Name of the predicted label
116
+ confidence: Confidence of the prediction
117
+ memory_lookups: List of memories used to ground the prediction
118
+ input_value: Input value that this prediction was for
119
+ model: Model that was used to make the prediction
120
+ memoryset: Memoryset that was used to lookup memories to ground the prediction
121
+ expected_label: Optional expected label that was set for the prediction
122
+ tags: tags that were set for the prediction
123
+ feedback: Feedback recorded, mapping from category name to value
124
+ """
125
+
126
+ prediction_id: str
127
+ label: int
128
+ label_name: str | None
129
+ confidence: float
130
+ memoryset: LabeledMemoryset
131
+ model: ClassificationModel
132
+
133
+ def __init__(
134
+ self,
135
+ prediction_id: str,
136
+ *,
137
+ label: int,
138
+ label_name: str | None,
139
+ confidence: float,
140
+ memoryset: LabeledMemoryset | str,
141
+ model: ClassificationModel | str,
142
+ telemetry: LabelPredictionWithMemoriesAndFeedback | None = None,
143
+ ):
144
+ # for internal use only, do not document
145
+ from .classification_model import ClassificationModel
146
+
147
+ self.prediction_id = prediction_id
148
+ self.label = label
149
+ self.label_name = label_name
150
+ self.confidence = confidence
151
+ self.memoryset = LabeledMemoryset.open(memoryset) if isinstance(memoryset, str) else memoryset
152
+ self.model = ClassificationModel.open(model) if isinstance(model, str) else model
153
+ self.__telemetry = telemetry if telemetry else None
154
+
155
+ def __repr__(self):
156
+ return (
157
+ "LabelPrediction({"
158
+ + f"label: <{self.label_name}: {self.label}>, "
159
+ + f"confidence: {self.confidence:.2f}, "
160
+ + f"input_value: '{str(self.input_value)[:100] + '...' if len(str(self.input_value)) > 100 else self.input_value}'"
161
+ + "})"
162
+ )
163
+
164
+ @property
165
+ def _telemetry(self) -> LabelPredictionWithMemoriesAndFeedback:
166
+ # for internal use only, do not document
167
+ if self.__telemetry is None:
168
+ self.__telemetry = get_prediction(prediction_id=UUID(self.prediction_id))
169
+ return self.__telemetry
170
+
171
+ @property
172
+ def memory_lookups(self) -> list[LabeledMemoryLookup]:
173
+ return [LabeledMemoryLookup(self.memoryset.id, lookup) for lookup in self._telemetry.memories]
174
+
175
+ @property
176
+ def input_value(self) -> str | None:
177
+ return self._telemetry.input_value
178
+
179
+ @property
180
+ def feedback(self) -> dict[str, bool | float]:
181
+ return {
182
+ f.category_name: (
183
+ f.value if f.category_type == FeedbackType.CONTINUOUS else True if f.value == 1 else False
184
+ )
185
+ for f in self._telemetry.feedbacks
186
+ }
187
+
188
+ @property
189
+ def expected_label(self) -> int | None:
190
+ return self._telemetry.expected_label
191
+
192
+ @property
193
+ def tags(self) -> set[str]:
194
+ return set(self._telemetry.tags)
195
+
196
+ @overload
197
+ @classmethod
198
+ def get(cls, prediction_id: str) -> LabelPrediction: # type: ignore -- this takes precedence
199
+ pass
200
+
201
+ @overload
202
+ @classmethod
203
+ def get(cls, prediction_id: Iterable[str]) -> list[LabelPrediction]:
204
+ pass
205
+
206
+ @classmethod
207
+ def get(cls, prediction_id: str | Iterable[str]) -> LabelPrediction | list[LabelPrediction]:
208
+ """
209
+ Fetch a prediction or predictions
210
+
211
+ Params:
212
+ prediction_id: Unique identifier of the prediction or predictions to fetch
213
+
214
+ Returns:
215
+ Prediction or list of predictions
216
+
217
+ Raises:
218
+ LookupError: If no prediction with the given id is found
219
+
220
+ Examples:
221
+ Fetch a single prediction:
222
+ >>> LabelPrediction.get("0195019a-5bc7-7afb-b902-5945ee1fb766")
223
+ LabelPrediction({
224
+ label: <positive: 1>,
225
+ confidence: 0.95,
226
+ input_value: "I am happy",
227
+ memoryset: "my_memoryset",
228
+ model: "my_model"
229
+ })
230
+
231
+ Fetch multiple predictions:
232
+ >>> LabelPrediction.get([
233
+ ... "0195019a-5bc7-7afb-b902-5945ee1fb766",
234
+ ... "019501a1-ea08-76b2-9f62-95e4800b4841",
235
+ ... ])
236
+ [
237
+ LabelPrediction({
238
+ label: <positive: 1>,
239
+ confidence: 0.95,
240
+ input_value: "I am happy",
241
+ memoryset: "my_memoryset",
242
+ model: "my_model"
243
+ }),
244
+ LabelPrediction({
245
+ label: <negative: 0>,
246
+ confidence: 0.05,
247
+ input_value: "I am sad",
248
+ memoryset: "my_memoryset", model: "my_model"
249
+ }),
250
+ ]
251
+ """
252
+ if isinstance(prediction_id, str):
253
+ prediction = get_prediction(prediction_id=UUID(prediction_id))
254
+ return cls(
255
+ prediction_id=prediction.prediction_id,
256
+ label=prediction.label,
257
+ label_name=prediction.label_name,
258
+ confidence=prediction.confidence,
259
+ memoryset=prediction.memoryset_id,
260
+ model=prediction.model_id,
261
+ telemetry=prediction,
262
+ )
263
+ else:
264
+ return [
265
+ cls(
266
+ prediction_id=prediction.prediction_id,
267
+ label=prediction.label,
268
+ label_name=prediction.label_name,
269
+ confidence=prediction.confidence,
270
+ memoryset=prediction.memoryset_id,
271
+ model=prediction.model_id,
272
+ telemetry=prediction,
273
+ )
274
+ for prediction in list_predictions(body=ListPredictionsRequest(prediction_ids=list(prediction_id)))
275
+ ]
276
+
277
+ def refresh(self):
278
+ """Refresh the prediction data from the OrcaCloud"""
279
+ self.__dict__.update(LabelPrediction.get(self.prediction_id).__dict__)
280
+
281
+ def inspect(self):
282
+ """Open a UI to inspect the memories used by this prediction"""
283
+ inspect_prediction_result(self)
284
+
285
+ def update(self, *, expected_label: int | None = UNSET, tags: set[str] | None = UNSET) -> None:
286
+ """
287
+ Update editable prediction properties.
288
+
289
+ Params:
290
+ expected_label: Value to set for the expected label, defaults to `[UNSET]` if not provided.
291
+ tags: Value to replace existing tags with, defaults to `[UNSET]` if not provided.
292
+
293
+ Examples:
294
+ Update the expected label:
295
+ >>> prediction.update(expected_label=1)
296
+
297
+ Add a new tag:
298
+ >>> prediction.update(tags=prediction.tags | {"new_tag"})
299
+
300
+ Remove expected label and tags:
301
+ >>> prediction.update(expected_label=None, tags=None)
302
+ """
303
+ update_prediction(
304
+ prediction_id=self.prediction_id,
305
+ body=UpdatePredictionRequest(
306
+ expected_label=expected_label if expected_label is not UNSET else CLIENT_UNSET,
307
+ tags=[] if tags is None else list(tags) if tags is not UNSET else CLIENT_UNSET,
308
+ ),
309
+ )
310
+ self.refresh()
311
+
312
+ def add_tag(self, tag: str) -> None:
313
+ """
314
+ Add a tag to the prediction
315
+
316
+ Params:
317
+ tag: Tag to add to the prediction
318
+ """
319
+ self.update(tags=self.tags | {tag})
320
+
321
+ def remove_tag(self, tag: str) -> None:
322
+ """
323
+ Remove a tag from the prediction
324
+
325
+ Params:
326
+ tag: Tag to remove from the prediction
327
+ """
328
+ self.update(tags=self.tags - {tag})
329
+
330
+ def record_feedback(
331
+ self,
332
+ category: str,
333
+ value: bool | float,
334
+ *,
335
+ comment: str | None = None,
336
+ ):
337
+ """
338
+ Record feedback for the prediction.
339
+
340
+ We support recording feedback in several categories for each prediction. A
341
+ [`FeedbackCategory`][orca_sdk.telemetry.FeedbackCategory] is created automatically,
342
+ the first time feedback with a new name is recorded. Categories are global across models.
343
+ The value type of the category is inferred from the first recorded value. Subsequent
344
+ feedback for the same category must be of the same type.
345
+
346
+ Params:
347
+ category: Name of the category under which to record the feedback.
348
+ value: Feedback value to record, should be `True` for positive feedback and `False` for
349
+ negative feedback or a [`float`][float] between `-1.0` and `+1.0` where negative
350
+ values indicate negative feedback and positive values indicate positive feedback.
351
+ comment: Optional comment to record with the feedback.
352
+
353
+ Examples:
354
+ Record whether a suggestion was accepted or rejected:
355
+ >>> prediction.record_feedback("accepted", True)
356
+
357
+ Record star rating as normalized continuous score between `-1.0` and `+1.0`:
358
+ >>> prediction.record_feedback("rating", -0.5, comment="2 stars")
359
+
360
+ Raises:
361
+ ValueError: If the value does not match previous value types for the category, or is a
362
+ [`float`][float] that is not between `-1.0` and `+1.0`.
363
+ """
364
+ record_prediction_feedback(
365
+ body=[
366
+ _parse_feedback(
367
+ {"prediction_id": self.prediction_id, "category": category, "value": value, "comment": comment}
368
+ )
369
+ ]
370
+ )
371
+ self.refresh()
372
+
373
+ def delete_feedback(self, category: str) -> None:
374
+ """
375
+ Delete prediction feedback for a specific category.
376
+
377
+ Params:
378
+ category: Name of the category of the feedback to delete.
379
+
380
+ Raises:
381
+ ValueError: If the category is not found.
382
+ """
383
+ record_prediction_feedback(
384
+ body=[PredictionFeedbackRequest(prediction_id=self.prediction_id, category_name=category, value=None)]
385
+ )
386
+ self.refresh()
@@ -0,0 +1,100 @@
1
+ import pytest
2
+
3
+ from .classification_model import ClassificationModel
4
+ from .labeled_memoryset import LabeledMemoryLookup
5
+ from .telemetry import FeedbackCategory, LabelPrediction
6
+
7
+
8
+ def test_get_prediction(model: ClassificationModel):
9
+ predictions = model.predict(["Do you love soup?", "Are cats cute?"])
10
+ prediction_with_telemetry = LabelPrediction.get(predictions[0].prediction_id)
11
+ assert prediction_with_telemetry is not None
12
+ assert prediction_with_telemetry.label == 0
13
+ assert prediction_with_telemetry.input_value == "Do you love soup?"
14
+
15
+
16
+ def test_get_predictions(model: ClassificationModel):
17
+ predictions = model.predict(["Do you love soup?", "Are cats cute?"])
18
+ prediction_with_telemetry = LabelPrediction.get([predictions[0].prediction_id, predictions[1].prediction_id])
19
+ assert len(prediction_with_telemetry) == 2
20
+ assert prediction_with_telemetry[0].label == 0
21
+ assert prediction_with_telemetry[0].input_value == "Do you love soup?"
22
+
23
+
24
+ def test_get_prediction_memory_lookups(model: ClassificationModel):
25
+ prediction = model.predict("Do you love soup?")
26
+ assert isinstance(prediction.memory_lookups, list)
27
+ assert len(prediction.memory_lookups) > 0
28
+ assert all(isinstance(lookup, LabeledMemoryLookup) for lookup in prediction.memory_lookups)
29
+
30
+
31
+ def test_record_feedback(model: ClassificationModel):
32
+ prediction = model.predict("Do you love soup?")
33
+ assert "correct" not in prediction.feedback
34
+ prediction.record_feedback(category="correct", value=prediction.label == 0)
35
+ assert prediction.feedback["correct"] is True
36
+
37
+
38
+ def test_record_feedback_with_invalid_value(model: ClassificationModel):
39
+ with pytest.raises(ValueError, match=r"Invalid input.*"):
40
+ model.predict("Do you love soup?").record_feedback(category="correct", value="not a bool") # type: ignore
41
+
42
+
43
+ def test_record_feedback_with_inconsistent_value_for_category(model: ClassificationModel):
44
+ model.predict("Do you love soup?").record_feedback(category="correct", value=True)
45
+ with pytest.raises(ValueError, match=r"Invalid input.*"):
46
+ model.predict("Do you love soup?").record_feedback(category="correct", value=-1.0)
47
+
48
+
49
+ def test_delete_feedback(model: ClassificationModel):
50
+ prediction = model.predict("Do you love soup?")
51
+ prediction.record_feedback(category="test_delete", value=True)
52
+ assert "test_delete" in prediction.feedback
53
+ prediction.delete_feedback("test_delete")
54
+ assert "test_delete" not in prediction.feedback
55
+
56
+
57
+ def test_list_feedback_categories(model: ClassificationModel):
58
+ prediction = model.predict("Do you love soup?")
59
+ prediction.record_feedback(category="correct", value=True)
60
+ prediction.record_feedback(category="confidence", value=0.8)
61
+ categories = FeedbackCategory.all()
62
+ assert len(categories) >= 2
63
+ assert any(c.name == "correct" and c.value_type == bool for c in categories)
64
+ assert any(c.name == "confidence" and c.value_type == float for c in categories)
65
+
66
+
67
+ def test_drop_feedback_category(model: ClassificationModel):
68
+ prediction = model.predict("Do you love soup?")
69
+ prediction.record_feedback(category="test_category", value=True)
70
+ assert any(c.name == "test_category" for c in FeedbackCategory.all())
71
+ FeedbackCategory.drop("test_category")
72
+ assert not any(c.name == "test_category" for c in FeedbackCategory.all())
73
+ prediction.refresh()
74
+ assert "test_category" not in prediction.feedback
75
+
76
+
77
+ def test_update_prediction(model: ClassificationModel):
78
+ prediction = model.predict("Do you love soup?")
79
+ assert prediction.expected_label is None
80
+ assert prediction.tags == set()
81
+ # update expected label
82
+ prediction.update(expected_label=1)
83
+ assert prediction.expected_label == 1
84
+
85
+ # update tags
86
+ prediction.update(tags={"test_tag1", "test_tag2"})
87
+ assert prediction.tags == {"test_tag1", "test_tag2"}
88
+
89
+ # update both
90
+ prediction.update(expected_label=0, tags={"new_tag"})
91
+ assert prediction.expected_label == 0
92
+ assert prediction.tags == {"new_tag"}
93
+
94
+ # remove expected label
95
+ prediction.update(expected_label=None)
96
+ assert prediction.expected_label is None
97
+
98
+ # remove tags
99
+ prediction.update(tags=None)
100
+ assert prediction.tags == set()
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.1
2
+ Name: orca_sdk
3
+ Version: 0.1.0
4
+ Summary: SDK for interacting with Orca Services
5
+ License: Apache-2.0
6
+ Author: Orca DB Inc.
7
+ Author-email: dev-rel@orcadb.ai
8
+ Requires-Python: >=3.10,<3.13
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Dist: attrs (>=22.2.0)
15
+ Requires-Dist: datasets (>=3.1.0,<4.0.0)
16
+ Requires-Dist: gradio (==5.13.0)
17
+ Requires-Dist: httpx (>=0.20.0,<0.29.0)
18
+ Requires-Dist: pandas (>=2.2.3,<3.0.0)
19
+ Requires-Dist: pyarrow (>=18.0.0,<19.0.0)
20
+ Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
21
+ Requires-Dist: torch (>=2.5.1,<3.0.0)
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Orca SDK
25
+
26
+ Orca SDK is a Python library for interacting with Orca RAC.
27
+
28
+ ## Documentation
29
+
30
+ TBD
31
+
32
+ ## Installation
33
+
34
+ TBD
35
+
36
+ ## Support
37
+
38
+ If you have any questions, please reach out to us at support@orcadb.ai.
39
+