orca-sdk 0.0.96__py3-none-any.whl → 0.0.97__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 (91) hide show
  1. orca_sdk/__init__.py +1 -5
  2. orca_sdk/_generated_api_client/api/__init__.py +28 -8
  3. orca_sdk/_generated_api_client/api/{datasource/create_datasource_datasource_post.py → auth/create_org_plan_auth_org_plan_post.py} +32 -31
  4. orca_sdk/_generated_api_client/api/auth/get_org_plan_auth_org_plan_get.py +122 -0
  5. orca_sdk/_generated_api_client/api/auth/update_org_plan_auth_org_plan_put.py +168 -0
  6. orca_sdk/_generated_api_client/api/classification_model/{create_classification_model_gpu_classification_model_post.py → create_classification_model_classification_model_post.py} +1 -1
  7. orca_sdk/_generated_api_client/api/datasource/create_datasource_from_content_datasource_post.py +224 -0
  8. orca_sdk/_generated_api_client/api/datasource/create_datasource_from_files_datasource_upload_post.py +229 -0
  9. orca_sdk/_generated_api_client/api/regression_model/{create_regression_model_gpu_regression_model_post.py → create_regression_model_regression_model_post.py} +1 -1
  10. orca_sdk/_generated_api_client/api/task/list_tasks_task_get.py +21 -26
  11. orca_sdk/_generated_api_client/api/telemetry/generate_memory_suggestions_telemetry_prediction_prediction_id_memory_suggestions_post.py +239 -0
  12. orca_sdk/_generated_api_client/api/telemetry/get_action_recommendation_telemetry_prediction_prediction_id_action_get.py +192 -0
  13. orca_sdk/_generated_api_client/models/__init__.py +54 -4
  14. orca_sdk/_generated_api_client/models/action_recommendation.py +82 -0
  15. orca_sdk/_generated_api_client/models/action_recommendation_action.py +11 -0
  16. orca_sdk/_generated_api_client/models/add_memory_recommendations.py +85 -0
  17. orca_sdk/_generated_api_client/models/add_memory_suggestion.py +79 -0
  18. orca_sdk/_generated_api_client/models/body_create_datasource_from_files_datasource_upload_post.py +145 -0
  19. orca_sdk/_generated_api_client/models/class_representatives.py +92 -0
  20. orca_sdk/_generated_api_client/models/classification_model_metadata.py +14 -0
  21. orca_sdk/_generated_api_client/models/clone_memoryset_request.py +40 -0
  22. orca_sdk/_generated_api_client/models/constraint_violation_error_response.py +8 -7
  23. orca_sdk/_generated_api_client/models/constraint_violation_error_response_status_code.py +8 -0
  24. orca_sdk/_generated_api_client/models/create_classification_model_request.py +40 -0
  25. orca_sdk/_generated_api_client/models/create_datasource_from_content_request.py +101 -0
  26. orca_sdk/_generated_api_client/models/create_memoryset_request.py +40 -0
  27. orca_sdk/_generated_api_client/models/create_org_plan_request.py +73 -0
  28. orca_sdk/_generated_api_client/models/create_org_plan_request_tier.py +11 -0
  29. orca_sdk/_generated_api_client/models/create_regression_model_request.py +20 -0
  30. orca_sdk/_generated_api_client/models/embed_request.py +20 -0
  31. orca_sdk/_generated_api_client/models/embedding_evaluation_payload.py +28 -10
  32. orca_sdk/_generated_api_client/models/embedding_evaluation_request.py +28 -10
  33. orca_sdk/_generated_api_client/models/embedding_model_result.py +9 -0
  34. orca_sdk/_generated_api_client/models/filter_item.py +31 -23
  35. orca_sdk/_generated_api_client/models/filter_item_field_type_1_item_type_0.py +8 -0
  36. orca_sdk/_generated_api_client/models/filter_item_field_type_2_item_type_0.py +8 -0
  37. orca_sdk/_generated_api_client/models/filter_item_field_type_2_item_type_1.py +2 -0
  38. orca_sdk/_generated_api_client/models/internal_server_error_response.py +8 -7
  39. orca_sdk/_generated_api_client/models/internal_server_error_response_status_code.py +8 -0
  40. orca_sdk/_generated_api_client/models/labeled_memory.py +5 -5
  41. orca_sdk/_generated_api_client/models/labeled_memory_update.py +16 -16
  42. orca_sdk/_generated_api_client/models/labeled_memory_with_feedback_metrics.py +5 -5
  43. orca_sdk/_generated_api_client/models/lookup_request.py +20 -0
  44. orca_sdk/_generated_api_client/models/memory_metrics.py +98 -0
  45. orca_sdk/_generated_api_client/models/memoryset_analysis_configs.py +33 -0
  46. orca_sdk/_generated_api_client/models/memoryset_class_patterns_analysis_config.py +79 -0
  47. orca_sdk/_generated_api_client/models/memoryset_class_patterns_metrics.py +138 -0
  48. orca_sdk/_generated_api_client/models/memoryset_metadata.py +42 -0
  49. orca_sdk/_generated_api_client/models/memoryset_metrics.py +33 -0
  50. orca_sdk/_generated_api_client/models/memoryset_update.py +20 -0
  51. orca_sdk/_generated_api_client/models/not_found_error_response.py +6 -7
  52. orca_sdk/_generated_api_client/models/not_found_error_response_resource_type_0.py +1 -0
  53. orca_sdk/_generated_api_client/models/not_found_error_response_status_code.py +8 -0
  54. orca_sdk/_generated_api_client/models/org_plan.py +99 -0
  55. orca_sdk/_generated_api_client/models/org_plan_tier.py +11 -0
  56. orca_sdk/_generated_api_client/models/paginated_task.py +108 -0
  57. orca_sdk/_generated_api_client/models/predictive_model_update.py +20 -0
  58. orca_sdk/_generated_api_client/models/pretrained_embedding_model_metadata.py +8 -0
  59. orca_sdk/_generated_api_client/models/regression_model_metadata.py +14 -0
  60. orca_sdk/_generated_api_client/models/scored_memory_update.py +9 -9
  61. orca_sdk/_generated_api_client/models/service_unavailable_error_response.py +8 -7
  62. orca_sdk/_generated_api_client/models/service_unavailable_error_response_status_code.py +8 -0
  63. orca_sdk/_generated_api_client/models/telemetry_field_type_0_item_type_0.py +8 -0
  64. orca_sdk/_generated_api_client/models/telemetry_field_type_1_item_type_0.py +8 -0
  65. orca_sdk/_generated_api_client/models/telemetry_field_type_1_item_type_1.py +8 -0
  66. orca_sdk/_generated_api_client/models/telemetry_filter_item.py +42 -30
  67. orca_sdk/_generated_api_client/models/telemetry_sort_options.py +42 -30
  68. orca_sdk/_generated_api_client/models/unauthenticated_error_response.py +8 -7
  69. orca_sdk/_generated_api_client/models/unauthenticated_error_response_status_code.py +8 -0
  70. orca_sdk/_generated_api_client/models/unauthorized_error_response.py +8 -7
  71. orca_sdk/_generated_api_client/models/unauthorized_error_response_status_code.py +8 -0
  72. orca_sdk/_generated_api_client/models/update_org_plan_request.py +73 -0
  73. orca_sdk/_generated_api_client/models/update_org_plan_request_tier.py +11 -0
  74. orca_sdk/_shared/metrics.py +1 -1
  75. orca_sdk/classification_model.py +2 -2
  76. orca_sdk/classification_model_test.py +53 -0
  77. orca_sdk/credentials.py +15 -1
  78. orca_sdk/datasource.py +180 -41
  79. orca_sdk/datasource_test.py +194 -0
  80. orca_sdk/embedding_model.py +51 -13
  81. orca_sdk/embedding_model_test.py +27 -0
  82. orca_sdk/job.py +15 -14
  83. orca_sdk/job_test.py +34 -0
  84. orca_sdk/memoryset.py +47 -7
  85. orca_sdk/regression_model.py +2 -2
  86. orca_sdk/telemetry.py +94 -3
  87. {orca_sdk-0.0.96.dist-info → orca_sdk-0.0.97.dist-info}/METADATA +18 -1
  88. {orca_sdk-0.0.96.dist-info → orca_sdk-0.0.97.dist-info}/RECORD +89 -58
  89. orca_sdk/_generated_api_client/models/body_create_datasource_datasource_post.py +0 -207
  90. orca_sdk/_generated_api_client/models/labeled_memory_metrics.py +0 -246
  91. {orca_sdk-0.0.96.dist-info → orca_sdk-0.0.97.dist-info}/WHEEL +0 -0
@@ -179,3 +179,30 @@ def test_drop_finetuned_model_not_found():
179
179
  def test_drop_finetuned_model_unauthorized(unauthorized, finetuned_model: FinetunedEmbeddingModel):
180
180
  with pytest.raises(LookupError):
181
181
  FinetunedEmbeddingModel.drop(finetuned_model.id)
182
+
183
+
184
+ def test_default_instruction_with_memoryset_creation():
185
+ """Test that embedding models work correctly with instruction support."""
186
+ # Test with an instruction-supporting model
187
+ model = PretrainedEmbeddingModel.open("E5_LARGE")
188
+
189
+ # Verify the model properties
190
+ assert model.supports_instructions
191
+
192
+ # Test that prompt parameter is passed through correctly (orcalib handles the default)
193
+ embeddings_explicit_instruction = model.embed("Hello world", prompt="Represent this sentence for retrieval:")
194
+ embeddings_no_instruction = model.embed("Hello world")
195
+
196
+ # These should be different since one uses a prompt and the other doesn't
197
+ assert embeddings_explicit_instruction != embeddings_no_instruction
198
+
199
+
200
+ def test_default_instruction_error_cases():
201
+ """Test basic embedding model functionality."""
202
+ # Test that model opens correctly and has instruction support information
203
+ model = PretrainedEmbeddingModel.open("GTE_BASE")
204
+ assert not model.supports_instructions
205
+
206
+ # Test instruction-supporting model
207
+ instruction_model = PretrainedEmbeddingModel.open("E5_LARGE")
208
+ assert instruction_model.supports_instructions
orca_sdk/job.py CHANGED
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import time
4
4
  from datetime import datetime, timedelta
5
5
  from enum import Enum
6
- from typing import Callable, Generic, TypedDict, TypeVar, cast
6
+ from typing import Any, Callable, Generic, TypedDict, TypeVar, cast
7
7
 
8
8
  from tqdm.auto import tqdm
9
9
 
@@ -117,7 +117,7 @@ class Job(Generic[TResult]):
117
117
  cls,
118
118
  status: Status | list[Status] | None = None,
119
119
  type: str | list[str] | None = None,
120
- limit: int | None = None,
120
+ limit: int = 100,
121
121
  offset: int = 0,
122
122
  start: datetime | None = None,
123
123
  end: datetime | None = None,
@@ -136,7 +136,7 @@ class Job(Generic[TResult]):
136
136
  Returns:
137
137
  List of jobs matching the given filters
138
138
  """
139
- tasks = list_tasks(
139
+ paginated_tasks = list_tasks(
140
140
  status=(
141
141
  [TaskStatus(s.value) for s in status]
142
142
  if isinstance(status, list)
@@ -167,7 +167,7 @@ class Job(Generic[TResult]):
167
167
  obj,
168
168
  )[-1]
169
169
  )(t)
170
- for t in tasks
170
+ for t in paginated_tasks.items
171
171
  ]
172
172
 
173
173
  def __init__(self, id: str, get_value: Callable[[], TResult | None] | None = None):
@@ -316,14 +316,15 @@ class Job(Generic[TResult]):
316
316
  assert self.value is not None
317
317
  return self.value
318
318
 
319
- def abort(self, show_progress: bool = False, refresh_interval: int = 1, max_wait: int = 20) -> None:
320
- """
321
- Abort the job
322
319
 
323
- Params:
324
- show_progress: Optionally show a progress bar while waiting for the job to abort
325
- refresh_interval: Polling interval in seconds while waiting for the job to abort
326
- max_wait: Maximum time to wait for the job to abort in seconds
327
- """
328
- abort_task(self.id)
329
- self.wait(show_progress, refresh_interval, max_wait)
320
+ def abort(self, show_progress: bool = False, refresh_interval: int = 1, max_wait: int = 20) -> None:
321
+ """
322
+ Abort the job
323
+
324
+ Params:
325
+ show_progress: Optionally show a progress bar while waiting for the job to abort
326
+ refresh_interval: Polling interval in seconds while waiting for the job to abort
327
+ max_wait: Maximum time to wait for the job to abort in seconds
328
+ """
329
+ abort_task(self.id)
330
+ self.wait(show_progress, refresh_interval, max_wait)
orca_sdk/job_test.py CHANGED
@@ -46,3 +46,37 @@ def test_job_refresh(classification_model: ClassificationModel, datasource: Data
46
46
  # calling refresh() should immediately refresh the job
47
47
  job.refresh()
48
48
  assert job.refreshed_at > last_refreshed_at
49
+
50
+
51
+ def test_job_query_pagination(classification_model: ClassificationModel, datasource: Datasource):
52
+ """Test pagination with Job.query() method"""
53
+ # Create multiple jobs to test pagination
54
+ jobs_created = []
55
+ for i in range(3):
56
+ job = classification_model.evaluate(datasource, background=True)
57
+ jobs_created.append(job.id)
58
+
59
+ # Test basic pagination with limit
60
+ jobs_page1 = Job.query(type="EVALUATE_MODEL", limit=2)
61
+ assert len(jobs_page1) == 2
62
+
63
+ # Test pagination with offset
64
+ jobs_page2 = Job.query(type="EVALUATE_MODEL", limit=2, offset=1)
65
+ assert len(jobs_page2) == 2
66
+
67
+ # Verify different pages contain different jobs (allowing for some overlap due to timing)
68
+ page1_ids = {job.id for job in jobs_page1}
69
+ page2_ids = {job.id for job in jobs_page2}
70
+
71
+ # At least one job should be different between pages
72
+ assert len(page1_ids.symmetric_difference(page2_ids)) > 0
73
+
74
+ # Test filtering by status
75
+ jobs_by_status = Job.query(status=Status.PROCESSING, limit=10)
76
+ for job in jobs_by_status:
77
+ assert job.status == Status.PROCESSING
78
+
79
+ # Test filtering by multiple statuses
80
+ multi_status_jobs = Job.query(status=[Status.PROCESSING, Status.COMPLETED], limit=10)
81
+ for job in multi_status_jobs:
82
+ assert job.status in [Status.PROCESSING, Status.COMPLETED]
orca_sdk/memoryset.py CHANGED
@@ -73,7 +73,10 @@ from ._generated_api_client.models import (
73
73
  PretrainedEmbeddingModelName,
74
74
  )
75
75
  from ._generated_api_client.models import ScoredMemory as ScoredMemoryResponse
76
- from ._generated_api_client.models import ScoredMemoryInsert, ScoredMemoryInsertMetadata
76
+ from ._generated_api_client.models import (
77
+ ScoredMemoryInsert,
78
+ ScoredMemoryInsertMetadata,
79
+ )
77
80
  from ._generated_api_client.models import (
78
81
  ScoredMemoryLookup as ScoredMemoryLookupResponse,
79
82
  )
@@ -719,6 +722,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
719
722
  description: str | None = None,
720
723
  label_names: list[str] | None = None,
721
724
  max_seq_length_override: int | None = None,
725
+ prompt: str | None = None,
722
726
  remove_duplicates: bool = True,
723
727
  index_type: IndexType = "FLAT",
724
728
  index_params: dict[str, Any] = {},
@@ -742,6 +746,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
742
746
  description: str | None = None,
743
747
  label_names: list[str] | None = None,
744
748
  max_seq_length_override: int | None = None,
749
+ prompt: str | None = None,
745
750
  remove_duplicates: bool = True,
746
751
  index_type: IndexType = "FLAT",
747
752
  index_params: dict[str, Any] = {},
@@ -764,6 +769,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
764
769
  description: str | None = None,
765
770
  label_names: list[str] | None = None,
766
771
  max_seq_length_override: int | None = None,
772
+ prompt: str | None = None,
767
773
  remove_duplicates: bool = True,
768
774
  index_type: IndexType = "FLAT",
769
775
  index_params: dict[str, Any] = {},
@@ -797,6 +803,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
797
803
  max_seq_length_override: Maximum sequence length of values in the memoryset, if the
798
804
  value is longer than this it will be truncated, will default to the model's max
799
805
  sequence length if not provided
806
+ prompt: Optional prompt to use when embedding documents/memories for storage
800
807
  remove_duplicates: Whether to remove duplicates from the datasource before inserting
801
808
  into the memoryset
802
809
  index_type: Type of vector index to use for the memoryset, defaults to `"FLAT"`. Valid
@@ -849,6 +856,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
849
856
  remove_duplicates=remove_duplicates,
850
857
  index_type=CreateMemorysetRequestIndexType[index_type],
851
858
  index_params=CreateMemorysetRequestIndexParams.from_dict(index_params),
859
+ prompt=prompt,
852
860
  ),
853
861
  )
854
862
  job = Job(response.insertion_task_id, lambda: cls.open(response.id))
@@ -1351,6 +1359,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1351
1359
  *,
1352
1360
  embedding_model: PretrainedEmbeddingModel | FinetunedEmbeddingModel | None = None,
1353
1361
  max_seq_length_override: int | None = None,
1362
+ prompt: str | None = None,
1354
1363
  if_exists: CreateMode = "error",
1355
1364
  background: Literal[True],
1356
1365
  ) -> Job[Self]:
@@ -1363,6 +1372,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1363
1372
  *,
1364
1373
  embedding_model: PretrainedEmbeddingModel | FinetunedEmbeddingModel | None = None,
1365
1374
  max_seq_length_override: int | None = None,
1375
+ prompt: str | None = None,
1366
1376
  if_exists: CreateMode = "error",
1367
1377
  background: Literal[False] = False,
1368
1378
  ) -> Self:
@@ -1374,6 +1384,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1374
1384
  *,
1375
1385
  embedding_model: PretrainedEmbeddingModel | FinetunedEmbeddingModel | None = None,
1376
1386
  max_seq_length_override: int | None = None,
1387
+ prompt: str | None = None,
1377
1388
  if_exists: CreateMode = "error",
1378
1389
  background: bool = False,
1379
1390
  ) -> Self | Job[Self]:
@@ -1385,6 +1396,10 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1385
1396
  embedding_model: Optional new embedding model to use for re-embedding the memory values
1386
1397
  value is longer than this it will be truncated, will default to the model's max
1387
1398
  sequence length if not provided
1399
+ document_prompt_override: Optional custom document prompt to use for the cloned memoryset.
1400
+ If not provided, will use the source memoryset's document prompt.
1401
+ query_prompt_override: Optional custom query prompt to use for the cloned memoryset.
1402
+ If not provided, will use the source memoryset's query prompt.
1388
1403
  if_exists: What to do if a memoryset with the same name already exists, defaults to
1389
1404
  `"error"`. Other option is `"open"` to open the existing memoryset.
1390
1405
 
@@ -1399,6 +1414,13 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1399
1414
  >>> new_memoryset = memoryset.clone(
1400
1415
  ... "my_memoryset_finetuned", embedding_model=finetuned_embedding_model,
1401
1416
  ... )
1417
+
1418
+ >>> # Clone with custom prompts
1419
+ >>> new_memoryset = memoryset.clone(
1420
+ ... "my_memoryset_with_prompts",
1421
+ ... document_prompt_override="Represent this document for retrieval:",
1422
+ ... query_prompt_override="Represent this query for retrieval:",
1423
+ ... )
1402
1424
  """
1403
1425
  if self.exists(name):
1404
1426
  if if_exists == "error":
@@ -1421,6 +1443,7 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1421
1443
  embedding_model.id if isinstance(embedding_model, FinetunedEmbeddingModel) else None
1422
1444
  ),
1423
1445
  max_seq_length_override=max_seq_length_override,
1446
+ prompt=prompt,
1424
1447
  ),
1425
1448
  )
1426
1449
  job = Job(
@@ -1503,20 +1526,24 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1503
1526
  raise ValueError(f"Invalid index type: {type(index)}")
1504
1527
 
1505
1528
  @overload
1506
- def search(self, query: str, *, count: int = 1) -> list[MemoryLookupT]:
1529
+ def search(self, query: str, *, count: int = 1, prompt: str | None = None) -> list[MemoryLookupT]:
1507
1530
  pass
1508
1531
 
1509
1532
  @overload
1510
- def search(self, query: list[str], *, count: int = 1) -> list[list[MemoryLookupT]]:
1533
+ def search(self, query: list[str], *, count: int = 1, prompt: str | None = None) -> list[list[MemoryLookupT]]:
1511
1534
  pass
1512
1535
 
1513
- def search(self, query: str | list[str], *, count: int = 1) -> list[MemoryLookupT] | list[list[MemoryLookupT]]:
1536
+ def search(
1537
+ self, query: str | list[str], *, count: int = 1, prompt: str | None = None
1538
+ ) -> list[MemoryLookupT] | list[list[MemoryLookupT]]:
1514
1539
  """
1515
1540
  Search for memories that are semantically similar to the query
1516
1541
 
1517
1542
  Params:
1518
1543
  query: Query to lookup memories in the memoryset, can be a single query or a list
1519
1544
  count: Number of memories to return for each query
1545
+ prompt: Optional prompt for query embedding during search.
1546
+ If not provided, the memoryset's default query prompt will be used if available.
1520
1547
 
1521
1548
  Returns:
1522
1549
  List of memories from the memoryset that match the query. If a single query is provided,
@@ -1531,6 +1558,13 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1531
1558
  LabeledMemoryLookup({ label: <positive: 1>, value: 'I am content' }),
1532
1559
  ]
1533
1560
 
1561
+ Search with custom query prompt for instruction-following models:
1562
+ >>> memoryset.search("I am happy", count=2, query_prompt="Represent this query for sentiment retrieval:")
1563
+ [
1564
+ LabeledMemoryLookup({ label: <positive: 1>, value: 'I am happy' }),
1565
+ LabeledMemoryLookup({ label: <positive: 1>, value: 'I am content' }),
1566
+ ]
1567
+
1534
1568
  Search for similar memories for multiple queries:
1535
1569
  >>> memoryset.search(["I am happy", "I am sad"], count=1)
1536
1570
  [
@@ -1544,7 +1578,11 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
1544
1578
  """
1545
1579
  response = memoryset_lookup_gpu(
1546
1580
  name_or_id=self.id,
1547
- body=LookupRequest(query=query if isinstance(query, list) else [query], count=count),
1581
+ body=LookupRequest(
1582
+ query=query if isinstance(query, list) else [query],
1583
+ count=count,
1584
+ prompt=prompt,
1585
+ ),
1548
1586
  )
1549
1587
  lookups = [
1550
1588
  [
@@ -2062,9 +2100,11 @@ class _Memoryset(Generic[MemoryT, MemoryLookupT], ABC):
2062
2100
  """
2063
2101
 
2064
2102
  if embedding_models is not None:
2065
- embedding_model_enums = [PretrainedEmbeddingModelName(model) for model in embedding_models]
2103
+ embedding_model_enums: list[PretrainedEmbeddingModelName | str] | None = [
2104
+ PretrainedEmbeddingModelName(model) for model in embedding_models
2105
+ ]
2066
2106
  else:
2067
- embedding_model_enums = None
2107
+ embedding_model_enums: list[PretrainedEmbeddingModelName | str] | None = None
2068
2108
 
2069
2109
  request = EmbeddingEvaluationRequest(
2070
2110
  value_column=value_column,
@@ -11,7 +11,7 @@ import numpy as np
11
11
  from datasets import Dataset
12
12
 
13
13
  from ._generated_api_client.api import (
14
- create_regression_model_gpu,
14
+ create_regression_model,
15
15
  delete_regression_model,
16
16
  evaluate_regression_model,
17
17
  get_regression_model,
@@ -178,7 +178,7 @@ class RegressionModel:
178
178
 
179
179
  return existing
180
180
 
181
- metadata = create_regression_model_gpu(
181
+ metadata = create_regression_model(
182
182
  body=CreateRegressionModelRequest(
183
183
  name=name,
184
184
  memoryset_id=memoryset.id,
orca_sdk/telemetry.py CHANGED
@@ -1,9 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from abc import ABC
4
+ from abc import ABC, abstractmethod
5
5
  from datetime import datetime
6
- from typing import TYPE_CHECKING, Any, Generator, Iterable, Self, overload
6
+ from typing import (
7
+ TYPE_CHECKING,
8
+ Any,
9
+ Generator,
10
+ Iterable,
11
+ Literal,
12
+ Self,
13
+ cast,
14
+ overload,
15
+ )
7
16
  from uuid import UUID
8
17
 
9
18
  from orca_sdk._utils.common import UNSET
@@ -16,6 +25,12 @@ from ._generated_api_client.api import (
16
25
  record_prediction_feedback,
17
26
  update_prediction,
18
27
  )
28
+ from ._generated_api_client.api.telemetry.generate_memory_suggestions_telemetry_prediction_prediction_id_memory_suggestions_post import (
29
+ sync as generate_memory_suggestions,
30
+ )
31
+ from ._generated_api_client.api.telemetry.get_action_recommendation_telemetry_prediction_prediction_id_action_get import (
32
+ sync as get_action_recommendation,
33
+ )
19
34
  from ._generated_api_client.client import get_client
20
35
  from ._generated_api_client.errors import get_error_for_response
21
36
  from ._generated_api_client.models import (
@@ -77,7 +92,6 @@ class FeedbackCategory:
77
92
  created_at: datetime
78
93
 
79
94
  def __init__(self, category: PredictionFeedbackCategory):
80
- # for internal use only, do not document
81
95
  self.id = category.id
82
96
  self.name = category.name
83
97
  self.value_type = bool if category.type == FeedbackType.BINARY else float
@@ -499,6 +513,83 @@ class ClassificationPrediction(_Prediction):
499
513
  """
500
514
  self._update(tags=tags, expected_label=expected_label)
501
515
 
516
+ def recommend_action(self, *, refresh: bool = False) -> tuple[str, str]:
517
+ """
518
+ Get an action recommendation for improving this prediction.
519
+
520
+ Analyzes the prediction and suggests the most effective action to improve model
521
+ performance, such as adding memories, detecting mislabels, removing duplicates,
522
+ or finetuning.
523
+
524
+ Params:
525
+ refresh: Force the action recommendation agent to re-run even if a recommendation already exists
526
+
527
+ Returns:
528
+ Tuple of (action, rationale) where:
529
+ - action: The recommended action ("add_memories", "detect_mislabels", "remove_duplicates", or "finetuning") that would resolve the mislabeling
530
+ - rationale: Explanation for why this action was recommended
531
+
532
+ Raises:
533
+ ValueError: If the prediction has no prediction ID
534
+ RuntimeError: If the lighthouse API key is not configured
535
+
536
+ Examples:
537
+ Get action recommendation for an incorrect prediction:
538
+ >>> action, rationale = prediction.recommend_action()
539
+ >>> print(f"Recommended action: {action}")
540
+ >>> print(f"Rationale: {rationale}")
541
+ """
542
+ if self.prediction_id is None:
543
+ raise ValueError("Cannot get action recommendation with no prediction ID")
544
+
545
+ api_recommendation = get_action_recommendation(
546
+ prediction_id=UUID(self.prediction_id),
547
+ refresh=refresh,
548
+ )
549
+ return (api_recommendation.action.value, api_recommendation.rationale)
550
+
551
+ def generate_memory_suggestions(self, *, num_memories: int = 3) -> list[dict[str, str | int]]:
552
+ """
553
+ Generate synthetic memory suggestions to improve this prediction.
554
+
555
+ Creates new example memories that are similar to the input but have clearer
556
+ signals for the expected label. These can be added to the memoryset to improve
557
+ model performance on similar inputs.
558
+
559
+ Params:
560
+ num_memories: Number of memory suggestions to generate (default: 3)
561
+
562
+ Returns:
563
+ List of dictionaries that can be directly passed to memoryset.insert().
564
+ Each dictionary contains:
565
+ - "value": The suggested memory text
566
+ - "label": The suggested label as an integer
567
+
568
+ Raises:
569
+ ValueError: If the prediction has no prediction ID
570
+ RuntimeError: If the lighthouse API key is not configured
571
+
572
+ Examples:
573
+ Generate memory suggestions for an incorrect prediction:
574
+ >>> suggestions = prediction.generate_memory_suggestions(num_memories=3)
575
+ >>> for suggestion in suggestions:
576
+ ... print(f"Value: {suggestion['value']}, Label: {suggestion['label']}")
577
+ >>>
578
+ >>> # Add suggestions directly to memoryset
579
+ >>> model.memoryset.insert(suggestions)
580
+ """
581
+ if self.prediction_id is None:
582
+ raise ValueError("Cannot generate memory suggestions with no prediction ID")
583
+
584
+ api_recommendations = generate_memory_suggestions(
585
+ prediction_id=UUID(self.prediction_id),
586
+ num_memories=num_memories,
587
+ )
588
+
589
+ return [
590
+ {"value": suggestion.value, "label": int(suggestion.label)} for suggestion in api_recommendations.memories
591
+ ]
592
+
502
593
 
503
594
  class RegressionPrediction(_Prediction):
504
595
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: orca_sdk
3
- Version: 0.0.96
3
+ Version: 0.0.97
4
4
  Summary: SDK for interacting with Orca Services
5
5
  License: Apache-2.0
6
6
  Author: Orca DB Inc.
@@ -71,6 +71,23 @@ model = ClassificationModel("my_model", memoryset)
71
71
 
72
72
  # Make predictions
73
73
  prediction = model.predict("my input")
74
+
75
+ # Get Action Recommendation
76
+ action, rationale = prediction.recommend_action()
77
+ print(f"Recommended action: {action}")
78
+ print(f"Rationale: {rationale}")
79
+
80
+ # Generate and add synthetic memory suggestions
81
+ if action == "add_memories":
82
+ suggestions = prediction.generate_memory_suggestions(num_memories=3)
83
+
84
+ # Review suggestions
85
+ for suggestion in suggestions:
86
+ print(f"Suggested: '{suggestion['value']}' -> {suggestion['label']}")
87
+
88
+ # Add suggestions to memoryset
89
+ model.memoryset.insert(suggestions)
90
+ print(f"Added {len(suggestions)} new memories to improve model performance!")
74
91
  ```
75
92
 
76
93
  For a more detailed walkthrough, check out our [Quick Start Guide](https://docs.orcadb.ai/quickstart-sdk/).