opik 1.9.41__py3-none-any.whl → 1.9.86__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 (192) hide show
  1. opik/api_objects/attachment/attachment_context.py +36 -0
  2. opik/api_objects/attachment/attachments_extractor.py +153 -0
  3. opik/api_objects/attachment/client.py +1 -0
  4. opik/api_objects/attachment/converters.py +2 -0
  5. opik/api_objects/attachment/decoder.py +18 -0
  6. opik/api_objects/attachment/decoder_base64.py +83 -0
  7. opik/api_objects/attachment/decoder_helpers.py +137 -0
  8. opik/api_objects/constants.py +2 -0
  9. opik/api_objects/dataset/dataset.py +133 -40
  10. opik/api_objects/dataset/rest_operations.py +2 -0
  11. opik/api_objects/experiment/experiment.py +6 -0
  12. opik/api_objects/helpers.py +8 -4
  13. opik/api_objects/local_recording.py +6 -5
  14. opik/api_objects/observation_data.py +101 -0
  15. opik/api_objects/opik_client.py +78 -45
  16. opik/api_objects/opik_query_language.py +9 -3
  17. opik/api_objects/prompt/chat/chat_prompt.py +18 -1
  18. opik/api_objects/prompt/client.py +8 -1
  19. opik/api_objects/span/span_data.py +3 -88
  20. opik/api_objects/threads/threads_client.py +7 -4
  21. opik/api_objects/trace/trace_data.py +3 -74
  22. opik/api_objects/validation_helpers.py +3 -3
  23. opik/cli/exports/__init__.py +131 -0
  24. opik/cli/exports/dataset.py +278 -0
  25. opik/cli/exports/experiment.py +784 -0
  26. opik/cli/exports/project.py +685 -0
  27. opik/cli/exports/prompt.py +578 -0
  28. opik/cli/exports/utils.py +406 -0
  29. opik/cli/harbor.py +39 -0
  30. opik/cli/imports/__init__.py +439 -0
  31. opik/cli/imports/dataset.py +143 -0
  32. opik/cli/imports/experiment.py +1192 -0
  33. opik/cli/imports/project.py +262 -0
  34. opik/cli/imports/prompt.py +177 -0
  35. opik/cli/imports/utils.py +280 -0
  36. opik/cli/main.py +14 -12
  37. opik/config.py +12 -1
  38. opik/datetime_helpers.py +12 -0
  39. opik/decorator/arguments_helpers.py +4 -1
  40. opik/decorator/base_track_decorator.py +111 -37
  41. opik/decorator/context_manager/span_context_manager.py +5 -1
  42. opik/decorator/generator_wrappers.py +5 -4
  43. opik/decorator/span_creation_handler.py +13 -4
  44. opik/evaluation/engine/engine.py +111 -28
  45. opik/evaluation/engine/evaluation_tasks_executor.py +71 -19
  46. opik/evaluation/evaluator.py +12 -0
  47. opik/evaluation/metrics/conversation/llm_judges/conversational_coherence/metric.py +3 -1
  48. opik/evaluation/metrics/conversation/llm_judges/session_completeness/metric.py +3 -1
  49. opik/evaluation/metrics/conversation/llm_judges/user_frustration/metric.py +3 -1
  50. opik/evaluation/metrics/heuristics/equals.py +11 -7
  51. opik/evaluation/metrics/llm_judges/answer_relevance/metric.py +3 -1
  52. opik/evaluation/metrics/llm_judges/context_precision/metric.py +3 -1
  53. opik/evaluation/metrics/llm_judges/context_recall/metric.py +3 -1
  54. opik/evaluation/metrics/llm_judges/factuality/metric.py +1 -1
  55. opik/evaluation/metrics/llm_judges/g_eval/metric.py +3 -1
  56. opik/evaluation/metrics/llm_judges/hallucination/metric.py +3 -1
  57. opik/evaluation/metrics/llm_judges/moderation/metric.py +3 -1
  58. opik/evaluation/metrics/llm_judges/structure_output_compliance/metric.py +3 -1
  59. opik/evaluation/metrics/llm_judges/syc_eval/metric.py +4 -2
  60. opik/evaluation/metrics/llm_judges/trajectory_accuracy/metric.py +3 -1
  61. opik/evaluation/metrics/llm_judges/usefulness/metric.py +3 -1
  62. opik/evaluation/metrics/ragas_metric.py +43 -23
  63. opik/evaluation/models/litellm/litellm_chat_model.py +7 -2
  64. opik/evaluation/models/litellm/util.py +4 -20
  65. opik/evaluation/models/models_factory.py +19 -5
  66. opik/evaluation/rest_operations.py +3 -3
  67. opik/evaluation/threads/helpers.py +3 -2
  68. opik/file_upload/file_uploader.py +13 -0
  69. opik/file_upload/upload_options.py +2 -0
  70. opik/integrations/adk/legacy_opik_tracer.py +9 -11
  71. opik/integrations/adk/opik_tracer.py +2 -2
  72. opik/integrations/adk/patchers/adk_otel_tracer/opik_adk_otel_tracer.py +2 -2
  73. opik/integrations/dspy/callback.py +100 -14
  74. opik/integrations/dspy/parsers.py +168 -0
  75. opik/integrations/harbor/__init__.py +17 -0
  76. opik/integrations/harbor/experiment_service.py +269 -0
  77. opik/integrations/harbor/opik_tracker.py +528 -0
  78. opik/integrations/haystack/opik_tracer.py +2 -2
  79. opik/integrations/langchain/__init__.py +15 -2
  80. opik/integrations/langchain/langgraph_tracer_injector.py +88 -0
  81. opik/integrations/langchain/opik_tracer.py +258 -160
  82. opik/integrations/langchain/provider_usage_extractors/langchain_run_helpers/helpers.py +7 -4
  83. opik/integrations/llama_index/callback.py +43 -6
  84. opik/integrations/openai/agents/opik_tracing_processor.py +8 -10
  85. opik/integrations/openai/opik_tracker.py +99 -4
  86. opik/integrations/openai/videos/__init__.py +9 -0
  87. opik/integrations/openai/videos/binary_response_write_to_file_decorator.py +88 -0
  88. opik/integrations/openai/videos/videos_create_decorator.py +159 -0
  89. opik/integrations/openai/videos/videos_download_decorator.py +110 -0
  90. opik/message_processing/batching/base_batcher.py +14 -21
  91. opik/message_processing/batching/batch_manager.py +22 -10
  92. opik/message_processing/batching/batchers.py +32 -40
  93. opik/message_processing/batching/flushing_thread.py +0 -3
  94. opik/message_processing/emulation/emulator_message_processor.py +36 -1
  95. opik/message_processing/emulation/models.py +21 -0
  96. opik/message_processing/messages.py +9 -0
  97. opik/message_processing/preprocessing/__init__.py +0 -0
  98. opik/message_processing/preprocessing/attachments_preprocessor.py +70 -0
  99. opik/message_processing/preprocessing/batching_preprocessor.py +53 -0
  100. opik/message_processing/preprocessing/constants.py +1 -0
  101. opik/message_processing/preprocessing/file_upload_preprocessor.py +38 -0
  102. opik/message_processing/preprocessing/preprocessor.py +36 -0
  103. opik/message_processing/processors/__init__.py +0 -0
  104. opik/message_processing/processors/attachments_extraction_processor.py +146 -0
  105. opik/message_processing/{message_processors.py → processors/message_processors.py} +15 -1
  106. opik/message_processing/{message_processors_chain.py → processors/message_processors_chain.py} +3 -2
  107. opik/message_processing/{online_message_processor.py → processors/online_message_processor.py} +11 -9
  108. opik/message_processing/queue_consumer.py +4 -2
  109. opik/message_processing/streamer.py +71 -33
  110. opik/message_processing/streamer_constructors.py +36 -8
  111. opik/plugins/pytest/experiment_runner.py +1 -1
  112. opik/plugins/pytest/hooks.py +5 -3
  113. opik/rest_api/__init__.py +38 -0
  114. opik/rest_api/datasets/client.py +249 -148
  115. opik/rest_api/datasets/raw_client.py +356 -217
  116. opik/rest_api/experiments/client.py +26 -0
  117. opik/rest_api/experiments/raw_client.py +26 -0
  118. opik/rest_api/llm_provider_key/client.py +4 -4
  119. opik/rest_api/llm_provider_key/raw_client.py +4 -4
  120. opik/rest_api/llm_provider_key/types/provider_api_key_write_provider.py +2 -1
  121. opik/rest_api/manual_evaluation/client.py +101 -0
  122. opik/rest_api/manual_evaluation/raw_client.py +172 -0
  123. opik/rest_api/optimizations/client.py +0 -166
  124. opik/rest_api/optimizations/raw_client.py +0 -248
  125. opik/rest_api/projects/client.py +9 -0
  126. opik/rest_api/projects/raw_client.py +13 -0
  127. opik/rest_api/projects/types/project_metric_request_public_metric_type.py +4 -0
  128. opik/rest_api/prompts/client.py +130 -2
  129. opik/rest_api/prompts/raw_client.py +175 -0
  130. opik/rest_api/traces/client.py +101 -0
  131. opik/rest_api/traces/raw_client.py +120 -0
  132. opik/rest_api/types/__init__.py +46 -0
  133. opik/rest_api/types/audio_url.py +19 -0
  134. opik/rest_api/types/audio_url_public.py +19 -0
  135. opik/rest_api/types/audio_url_write.py +19 -0
  136. opik/rest_api/types/automation_rule_evaluator.py +38 -2
  137. opik/rest_api/types/automation_rule_evaluator_object_object_public.py +33 -2
  138. opik/rest_api/types/automation_rule_evaluator_public.py +33 -2
  139. opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python.py +22 -0
  140. opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python_public.py +22 -0
  141. opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python_write.py +22 -0
  142. opik/rest_api/types/automation_rule_evaluator_update.py +27 -1
  143. opik/rest_api/types/automation_rule_evaluator_update_span_user_defined_metric_python.py +22 -0
  144. opik/rest_api/types/automation_rule_evaluator_write.py +27 -1
  145. opik/rest_api/types/dataset_item.py +1 -1
  146. opik/rest_api/types/dataset_item_batch.py +4 -0
  147. opik/rest_api/types/dataset_item_changes_public.py +5 -0
  148. opik/rest_api/types/dataset_item_compare.py +1 -1
  149. opik/rest_api/types/dataset_item_filter.py +4 -0
  150. opik/rest_api/types/dataset_item_page_compare.py +0 -1
  151. opik/rest_api/types/dataset_item_page_public.py +0 -1
  152. opik/rest_api/types/dataset_item_public.py +1 -1
  153. opik/rest_api/types/dataset_version_public.py +5 -0
  154. opik/rest_api/types/dataset_version_summary.py +5 -0
  155. opik/rest_api/types/dataset_version_summary_public.py +5 -0
  156. opik/rest_api/types/experiment.py +9 -0
  157. opik/rest_api/types/experiment_public.py +9 -0
  158. opik/rest_api/types/llm_as_judge_message_content.py +2 -0
  159. opik/rest_api/types/llm_as_judge_message_content_public.py +2 -0
  160. opik/rest_api/types/llm_as_judge_message_content_write.py +2 -0
  161. opik/rest_api/types/manual_evaluation_request_entity_type.py +1 -1
  162. opik/rest_api/types/project.py +1 -0
  163. opik/rest_api/types/project_detailed.py +1 -0
  164. opik/rest_api/types/project_metric_response_public_metric_type.py +4 -0
  165. opik/rest_api/types/project_reference.py +31 -0
  166. opik/rest_api/types/project_reference_public.py +31 -0
  167. opik/rest_api/types/project_stats_summary_item.py +1 -0
  168. opik/rest_api/types/prompt_version.py +1 -0
  169. opik/rest_api/types/prompt_version_detail.py +1 -0
  170. opik/rest_api/types/prompt_version_page_public.py +5 -0
  171. opik/rest_api/types/prompt_version_public.py +1 -0
  172. opik/rest_api/types/prompt_version_update.py +33 -0
  173. opik/rest_api/types/provider_api_key.py +5 -1
  174. opik/rest_api/types/provider_api_key_provider.py +2 -1
  175. opik/rest_api/types/provider_api_key_public.py +5 -1
  176. opik/rest_api/types/provider_api_key_public_provider.py +2 -1
  177. opik/rest_api/types/service_toggles_config.py +11 -1
  178. opik/rest_api/types/span_user_defined_metric_python_code.py +20 -0
  179. opik/rest_api/types/span_user_defined_metric_python_code_public.py +20 -0
  180. opik/rest_api/types/span_user_defined_metric_python_code_write.py +20 -0
  181. opik/types.py +36 -0
  182. opik/validation/chat_prompt_messages.py +241 -0
  183. opik/validation/feedback_score.py +3 -3
  184. opik/validation/validator.py +28 -0
  185. {opik-1.9.41.dist-info → opik-1.9.86.dist-info}/METADATA +5 -5
  186. {opik-1.9.41.dist-info → opik-1.9.86.dist-info}/RECORD +190 -141
  187. opik/cli/export.py +0 -791
  188. opik/cli/import_command.py +0 -575
  189. {opik-1.9.41.dist-info → opik-1.9.86.dist-info}/WHEEL +0 -0
  190. {opik-1.9.41.dist-info → opik-1.9.86.dist-info}/entry_points.txt +0 -0
  191. {opik-1.9.41.dist-info → opik-1.9.86.dist-info}/licenses/LICENSE +0 -0
  192. {opik-1.9.41.dist-info → opik-1.9.86.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ import typing
5
5
  from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
6
6
  from ..core.request_options import RequestOptions
7
7
  from ..types.dataset_expansion_response import DatasetExpansionResponse
8
+ from ..types.dataset_item_changes_public import DatasetItemChangesPublic
8
9
  from ..types.dataset_item_filter import DatasetItemFilter
9
10
  from ..types.dataset_item_page_compare import DatasetItemPageCompare
10
11
  from ..types.dataset_item_page_public import DatasetItemPagePublic
@@ -45,12 +46,59 @@ class DatasetsClient:
45
46
  """
46
47
  return self._raw_client
47
48
 
49
+ def apply_dataset_item_changes(
50
+ self,
51
+ id: str,
52
+ *,
53
+ request: DatasetItemChangesPublic,
54
+ override: typing.Optional[bool] = None,
55
+ request_options: typing.Optional[RequestOptions] = None,
56
+ ) -> DatasetVersionPublic:
57
+ """
58
+ Apply delta changes (add, edit, delete) to a dataset version with conflict detection.
59
+
60
+ This endpoint:
61
+ - Creates a new version with the applied changes
62
+ - Validates that baseVersion matches the latest version (unless override=true)
63
+ - Returns 409 Conflict if baseVersion is stale and override is not set
64
+
65
+ Use `override=true` query parameter to force version creation even with stale baseVersion.
66
+
67
+ Parameters
68
+ ----------
69
+ id : str
70
+
71
+ request : DatasetItemChangesPublic
72
+
73
+ override : typing.Optional[bool]
74
+
75
+ request_options : typing.Optional[RequestOptions]
76
+ Request-specific configuration.
77
+
78
+ Returns
79
+ -------
80
+ DatasetVersionPublic
81
+ Version created successfully
82
+
83
+ Examples
84
+ --------
85
+ from Opik import OpikApi
86
+ client = OpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
87
+ client.datasets.apply_dataset_item_changes(id='id', request={'key': 'value'
88
+ }, )
89
+ """
90
+ _response = self._raw_client.apply_dataset_item_changes(
91
+ id, request=request, override=override, request_options=request_options
92
+ )
93
+ return _response.data
94
+
48
95
  def batch_update_dataset_items(
49
96
  self,
50
97
  *,
51
98
  update: DatasetItemUpdate,
52
99
  ids: typing.Optional[typing.Sequence[str]] = OMIT,
53
100
  filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
101
+ dataset_id: typing.Optional[str] = OMIT,
54
102
  merge_tags: typing.Optional[bool] = OMIT,
55
103
  request_options: typing.Optional[RequestOptions] = None,
56
104
  ) -> None:
@@ -66,6 +114,9 @@ class DatasetsClient:
66
114
 
67
115
  filters : typing.Optional[typing.Sequence[DatasetItemFilter]]
68
116
 
117
+ dataset_id : typing.Optional[str]
118
+ Dataset ID. Required when using 'filters', optional when using 'ids'.
119
+
69
120
  merge_tags : typing.Optional[bool]
70
121
  If true, merge tags with existing tags instead of replacing them. Default: false. When using 'filters', this is automatically set to true.
71
122
 
@@ -84,7 +135,12 @@ class DatasetsClient:
84
135
  client.datasets.batch_update_dataset_items(update=DatasetItemUpdate(), )
85
136
  """
86
137
  _response = self._raw_client.batch_update_dataset_items(
87
- update=update, ids=ids, filters=filters, merge_tags=merge_tags, request_options=request_options
138
+ update=update,
139
+ ids=ids,
140
+ filters=filters,
141
+ dataset_id=dataset_id,
142
+ merge_tags=merge_tags,
143
+ request_options=request_options,
88
144
  )
89
145
  return _response.data
90
146
 
@@ -198,6 +254,7 @@ class DatasetsClient:
198
254
  items: typing.Sequence[DatasetItemWrite],
199
255
  dataset_name: typing.Optional[str] = OMIT,
200
256
  dataset_id: typing.Optional[str] = OMIT,
257
+ batch_group_id: typing.Optional[str] = OMIT,
201
258
  request_options: typing.Optional[RequestOptions] = None,
202
259
  ) -> None:
203
260
  """
@@ -213,6 +270,9 @@ class DatasetsClient:
213
270
  dataset_id : typing.Optional[str]
214
271
  If null, dataset_name must be provided
215
272
 
273
+ batch_group_id : typing.Optional[str]
274
+ Optional batch group ID to group multiple batches into a single dataset version. If null, mutates the latest version instead of creating a new one.
275
+
216
276
  request_options : typing.Optional[RequestOptions]
217
277
  Request-specific configuration.
218
278
 
@@ -229,7 +289,11 @@ class DatasetsClient:
229
289
  }, )], )
230
290
  """
231
291
  _response = self._raw_client.create_or_update_dataset_items(
232
- items=items, dataset_name=dataset_name, dataset_id=dataset_id, request_options=request_options
292
+ items=items,
293
+ dataset_name=dataset_name,
294
+ dataset_id=dataset_id,
295
+ batch_group_id=batch_group_id,
296
+ request_options=request_options,
233
297
  )
234
298
  return _response.data
235
299
 
@@ -465,14 +529,34 @@ class DatasetsClient:
465
529
  return _response.data
466
530
 
467
531
  def delete_dataset_items(
468
- self, *, item_ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None
532
+ self,
533
+ *,
534
+ item_ids: typing.Optional[typing.Sequence[str]] = OMIT,
535
+ dataset_id: typing.Optional[str] = OMIT,
536
+ filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
537
+ batch_group_id: typing.Optional[str] = OMIT,
538
+ request_options: typing.Optional[RequestOptions] = None,
469
539
  ) -> None:
470
540
  """
471
- Delete dataset items
541
+ Delete dataset items using one of two modes:
542
+ 1. **Delete by IDs**: Provide 'item_ids' to delete specific items by their IDs
543
+ 2. **Delete by filters**: Provide 'dataset_id' with optional 'filters' to delete items matching criteria
544
+
545
+ When using filters, an empty 'filters' array will delete all items in the specified dataset.
472
546
 
473
547
  Parameters
474
548
  ----------
475
- item_ids : typing.Sequence[str]
549
+ item_ids : typing.Optional[typing.Sequence[str]]
550
+ List of dataset item IDs to delete (max 1000). Use this to delete specific items by their IDs. Mutually exclusive with 'dataset_id' and 'filters'.
551
+
552
+ dataset_id : typing.Optional[str]
553
+ Dataset ID to scope the deletion. Required when using 'filters'. Mutually exclusive with 'item_ids'.
554
+
555
+ filters : typing.Optional[typing.Sequence[DatasetItemFilter]]
556
+ Filters to select dataset items to delete within the specified dataset. Must be used with 'dataset_id'. Mutually exclusive with 'item_ids'. Empty array means 'delete all items in the dataset'.
557
+
558
+ batch_group_id : typing.Optional[str]
559
+ Optional batch group ID to group multiple delete operations into a single dataset version. If null, mutates the latest version instead of creating a new one.
476
560
 
477
561
  request_options : typing.Optional[RequestOptions]
478
562
  Request-specific configuration.
@@ -485,9 +569,15 @@ class DatasetsClient:
485
569
  --------
486
570
  from Opik import OpikApi
487
571
  client = OpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
488
- client.datasets.delete_dataset_items(item_ids=['item_ids'], )
572
+ client.datasets.delete_dataset_items()
489
573
  """
490
- _response = self._raw_client.delete_dataset_items(item_ids=item_ids, request_options=request_options)
574
+ _response = self._raw_client.delete_dataset_items(
575
+ item_ids=item_ids,
576
+ dataset_id=dataset_id,
577
+ filters=filters,
578
+ batch_group_id=batch_group_id,
579
+ request_options=request_options,
580
+ )
491
581
  return _response.data
492
582
 
493
583
  def delete_datasets_batch(
@@ -880,6 +970,7 @@ class DatasetsClient:
880
970
  dataset_name: str,
881
971
  last_retrieved_id: typing.Optional[str] = OMIT,
882
972
  steam_limit: typing.Optional[int] = OMIT,
973
+ dataset_version: typing.Optional[str] = OMIT,
883
974
  request_options: typing.Optional[RequestOptions] = None,
884
975
  ) -> typing.Iterator[bytes]:
885
976
  """
@@ -893,6 +984,8 @@ class DatasetsClient:
893
984
 
894
985
  steam_limit : typing.Optional[int]
895
986
 
987
+ dataset_version : typing.Optional[str]
988
+
896
989
  request_options : typing.Optional[RequestOptions]
897
990
  Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.
898
991
 
@@ -905,6 +998,7 @@ class DatasetsClient:
905
998
  dataset_name=dataset_name,
906
999
  last_retrieved_id=last_retrieved_id,
907
1000
  steam_limit=steam_limit,
1001
+ dataset_version=dataset_version,
908
1002
  request_options=request_options,
909
1003
  ) as r:
910
1004
  yield from r.data
@@ -966,120 +1060,77 @@ class DatasetsClient:
966
1060
  _response = self._raw_client.create_version_tag(version_hash, id, tag=tag, request_options=request_options)
967
1061
  return _response.data
968
1062
 
969
- def list_dataset_versions(
970
- self,
971
- id: str,
972
- *,
973
- page: typing.Optional[int] = None,
974
- size: typing.Optional[int] = None,
975
- request_options: typing.Optional[RequestOptions] = None,
976
- ) -> DatasetVersionPagePublic:
1063
+ def delete_version_tag(
1064
+ self, version_hash: str, tag: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
1065
+ ) -> None:
977
1066
  """
978
- Get paginated list of versions for a dataset, ordered by creation time (newest first)
1067
+ Remove a tag from a dataset version. The version itself is not deleted, only the tag reference.
979
1068
 
980
1069
  Parameters
981
1070
  ----------
982
- id : str
1071
+ version_hash : str
983
1072
 
984
- page : typing.Optional[int]
1073
+ tag : str
985
1074
 
986
- size : typing.Optional[int]
1075
+ id : str
987
1076
 
988
1077
  request_options : typing.Optional[RequestOptions]
989
1078
  Request-specific configuration.
990
1079
 
991
1080
  Returns
992
1081
  -------
993
- DatasetVersionPagePublic
994
- Dataset versions
1082
+ None
995
1083
 
996
1084
  Examples
997
1085
  --------
998
1086
  from Opik import OpikApi
999
1087
  client = OpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
1000
- client.datasets.list_dataset_versions(id='id', )
1088
+ client.datasets.delete_version_tag(version_hash='versionHash', tag='tag', id='id', )
1001
1089
  """
1002
- _response = self._raw_client.list_dataset_versions(id, page=page, size=size, request_options=request_options)
1090
+ _response = self._raw_client.delete_version_tag(version_hash, tag, id, request_options=request_options)
1003
1091
  return _response.data
1004
1092
 
1005
- def create_dataset_version(
1093
+ def list_dataset_versions(
1006
1094
  self,
1007
1095
  id: str,
1008
1096
  *,
1009
- tags: typing.Optional[typing.Sequence[str]] = OMIT,
1010
- change_description: typing.Optional[str] = OMIT,
1011
- metadata: typing.Optional[typing.Dict[str, str]] = OMIT,
1097
+ page: typing.Optional[int] = None,
1098
+ size: typing.Optional[int] = None,
1012
1099
  request_options: typing.Optional[RequestOptions] = None,
1013
- ) -> None:
1100
+ ) -> DatasetVersionPagePublic:
1014
1101
  """
1015
- Create a new immutable version of the dataset by snapshotting the current state
1102
+ Get paginated list of versions for a dataset, ordered by creation time (newest first)
1016
1103
 
1017
1104
  Parameters
1018
1105
  ----------
1019
1106
  id : str
1020
1107
 
1021
- tags : typing.Optional[typing.Sequence[str]]
1022
- Optional list of tags for this version
1023
-
1024
- change_description : typing.Optional[str]
1025
- Optional description of changes in this version
1026
-
1027
- metadata : typing.Optional[typing.Dict[str, str]]
1028
- Optional user-defined metadata
1029
-
1030
- request_options : typing.Optional[RequestOptions]
1031
- Request-specific configuration.
1032
-
1033
- Returns
1034
- -------
1035
- None
1036
-
1037
- Examples
1038
- --------
1039
- from Opik import OpikApi
1040
- client = OpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
1041
- client.datasets.create_dataset_version(id='id', )
1042
- """
1043
- _response = self._raw_client.create_dataset_version(
1044
- id, tags=tags, change_description=change_description, metadata=metadata, request_options=request_options
1045
- )
1046
- return _response.data
1047
-
1048
- def delete_version_tag(
1049
- self, version_hash: str, tag: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
1050
- ) -> None:
1051
- """
1052
- Remove a tag from a dataset version. The version itself is not deleted, only the tag reference.
1053
-
1054
- Parameters
1055
- ----------
1056
- version_hash : str
1057
-
1058
- tag : str
1108
+ page : typing.Optional[int]
1059
1109
 
1060
- id : str
1110
+ size : typing.Optional[int]
1061
1111
 
1062
1112
  request_options : typing.Optional[RequestOptions]
1063
1113
  Request-specific configuration.
1064
1114
 
1065
1115
  Returns
1066
1116
  -------
1067
- None
1117
+ DatasetVersionPagePublic
1118
+ Dataset versions
1068
1119
 
1069
1120
  Examples
1070
1121
  --------
1071
1122
  from Opik import OpikApi
1072
1123
  client = OpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
1073
- client.datasets.delete_version_tag(version_hash='versionHash', tag='tag', id='id', )
1124
+ client.datasets.list_dataset_versions(id='id', )
1074
1125
  """
1075
- _response = self._raw_client.delete_version_tag(version_hash, tag, id, request_options=request_options)
1126
+ _response = self._raw_client.list_dataset_versions(id, page=page, size=size, request_options=request_options)
1076
1127
  return _response.data
1077
1128
 
1078
1129
  def restore_dataset_version(
1079
1130
  self, id: str, *, version_ref: str, request_options: typing.Optional[RequestOptions] = None
1080
1131
  ) -> DatasetVersionPublic:
1081
1132
  """
1082
- Restores the dataset to a previous version state. All draft items are replaced with items from the specified version. If the version is not the latest, a new version snapshot is created. If the version is the latest, only draft items are replaced (revert functionality).
1133
+ Restores the dataset to a previous version state by creating a new version with items copied from the specified version. If the version is already the latest, returns it as-is (no-op).
1083
1134
 
1084
1135
  Parameters
1085
1136
  ----------
@@ -1170,12 +1221,62 @@ class AsyncDatasetsClient:
1170
1221
  """
1171
1222
  return self._raw_client
1172
1223
 
1224
+ async def apply_dataset_item_changes(
1225
+ self,
1226
+ id: str,
1227
+ *,
1228
+ request: DatasetItemChangesPublic,
1229
+ override: typing.Optional[bool] = None,
1230
+ request_options: typing.Optional[RequestOptions] = None,
1231
+ ) -> DatasetVersionPublic:
1232
+ """
1233
+ Apply delta changes (add, edit, delete) to a dataset version with conflict detection.
1234
+
1235
+ This endpoint:
1236
+ - Creates a new version with the applied changes
1237
+ - Validates that baseVersion matches the latest version (unless override=true)
1238
+ - Returns 409 Conflict if baseVersion is stale and override is not set
1239
+
1240
+ Use `override=true` query parameter to force version creation even with stale baseVersion.
1241
+
1242
+ Parameters
1243
+ ----------
1244
+ id : str
1245
+
1246
+ request : DatasetItemChangesPublic
1247
+
1248
+ override : typing.Optional[bool]
1249
+
1250
+ request_options : typing.Optional[RequestOptions]
1251
+ Request-specific configuration.
1252
+
1253
+ Returns
1254
+ -------
1255
+ DatasetVersionPublic
1256
+ Version created successfully
1257
+
1258
+ Examples
1259
+ --------
1260
+ from Opik import AsyncOpikApi
1261
+ import asyncio
1262
+ client = AsyncOpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
1263
+ async def main() -> None:
1264
+ await client.datasets.apply_dataset_item_changes(id='id', request={'key': 'value'
1265
+ }, )
1266
+ asyncio.run(main())
1267
+ """
1268
+ _response = await self._raw_client.apply_dataset_item_changes(
1269
+ id, request=request, override=override, request_options=request_options
1270
+ )
1271
+ return _response.data
1272
+
1173
1273
  async def batch_update_dataset_items(
1174
1274
  self,
1175
1275
  *,
1176
1276
  update: DatasetItemUpdate,
1177
1277
  ids: typing.Optional[typing.Sequence[str]] = OMIT,
1178
1278
  filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
1279
+ dataset_id: typing.Optional[str] = OMIT,
1179
1280
  merge_tags: typing.Optional[bool] = OMIT,
1180
1281
  request_options: typing.Optional[RequestOptions] = None,
1181
1282
  ) -> None:
@@ -1191,6 +1292,9 @@ class AsyncDatasetsClient:
1191
1292
 
1192
1293
  filters : typing.Optional[typing.Sequence[DatasetItemFilter]]
1193
1294
 
1295
+ dataset_id : typing.Optional[str]
1296
+ Dataset ID. Required when using 'filters', optional when using 'ids'.
1297
+
1194
1298
  merge_tags : typing.Optional[bool]
1195
1299
  If true, merge tags with existing tags instead of replacing them. Default: false. When using 'filters', this is automatically set to true.
1196
1300
 
@@ -1212,7 +1316,12 @@ class AsyncDatasetsClient:
1212
1316
  asyncio.run(main())
1213
1317
  """
1214
1318
  _response = await self._raw_client.batch_update_dataset_items(
1215
- update=update, ids=ids, filters=filters, merge_tags=merge_tags, request_options=request_options
1319
+ update=update,
1320
+ ids=ids,
1321
+ filters=filters,
1322
+ dataset_id=dataset_id,
1323
+ merge_tags=merge_tags,
1324
+ request_options=request_options,
1216
1325
  )
1217
1326
  return _response.data
1218
1327
 
@@ -1332,6 +1441,7 @@ class AsyncDatasetsClient:
1332
1441
  items: typing.Sequence[DatasetItemWrite],
1333
1442
  dataset_name: typing.Optional[str] = OMIT,
1334
1443
  dataset_id: typing.Optional[str] = OMIT,
1444
+ batch_group_id: typing.Optional[str] = OMIT,
1335
1445
  request_options: typing.Optional[RequestOptions] = None,
1336
1446
  ) -> None:
1337
1447
  """
@@ -1347,6 +1457,9 @@ class AsyncDatasetsClient:
1347
1457
  dataset_id : typing.Optional[str]
1348
1458
  If null, dataset_name must be provided
1349
1459
 
1460
+ batch_group_id : typing.Optional[str]
1461
+ Optional batch group ID to group multiple batches into a single dataset version. If null, mutates the latest version instead of creating a new one.
1462
+
1350
1463
  request_options : typing.Optional[RequestOptions]
1351
1464
  Request-specific configuration.
1352
1465
 
@@ -1366,7 +1479,11 @@ class AsyncDatasetsClient:
1366
1479
  asyncio.run(main())
1367
1480
  """
1368
1481
  _response = await self._raw_client.create_or_update_dataset_items(
1369
- items=items, dataset_name=dataset_name, dataset_id=dataset_id, request_options=request_options
1482
+ items=items,
1483
+ dataset_name=dataset_name,
1484
+ dataset_id=dataset_id,
1485
+ batch_group_id=batch_group_id,
1486
+ request_options=request_options,
1370
1487
  )
1371
1488
  return _response.data
1372
1489
 
@@ -1627,14 +1744,34 @@ class AsyncDatasetsClient:
1627
1744
  return _response.data
1628
1745
 
1629
1746
  async def delete_dataset_items(
1630
- self, *, item_ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None
1747
+ self,
1748
+ *,
1749
+ item_ids: typing.Optional[typing.Sequence[str]] = OMIT,
1750
+ dataset_id: typing.Optional[str] = OMIT,
1751
+ filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
1752
+ batch_group_id: typing.Optional[str] = OMIT,
1753
+ request_options: typing.Optional[RequestOptions] = None,
1631
1754
  ) -> None:
1632
1755
  """
1633
- Delete dataset items
1756
+ Delete dataset items using one of two modes:
1757
+ 1. **Delete by IDs**: Provide 'item_ids' to delete specific items by their IDs
1758
+ 2. **Delete by filters**: Provide 'dataset_id' with optional 'filters' to delete items matching criteria
1759
+
1760
+ When using filters, an empty 'filters' array will delete all items in the specified dataset.
1634
1761
 
1635
1762
  Parameters
1636
1763
  ----------
1637
- item_ids : typing.Sequence[str]
1764
+ item_ids : typing.Optional[typing.Sequence[str]]
1765
+ List of dataset item IDs to delete (max 1000). Use this to delete specific items by their IDs. Mutually exclusive with 'dataset_id' and 'filters'.
1766
+
1767
+ dataset_id : typing.Optional[str]
1768
+ Dataset ID to scope the deletion. Required when using 'filters'. Mutually exclusive with 'item_ids'.
1769
+
1770
+ filters : typing.Optional[typing.Sequence[DatasetItemFilter]]
1771
+ Filters to select dataset items to delete within the specified dataset. Must be used with 'dataset_id'. Mutually exclusive with 'item_ids'. Empty array means 'delete all items in the dataset'.
1772
+
1773
+ batch_group_id : typing.Optional[str]
1774
+ Optional batch group ID to group multiple delete operations into a single dataset version. If null, mutates the latest version instead of creating a new one.
1638
1775
 
1639
1776
  request_options : typing.Optional[RequestOptions]
1640
1777
  Request-specific configuration.
@@ -1649,10 +1786,16 @@ class AsyncDatasetsClient:
1649
1786
  import asyncio
1650
1787
  client = AsyncOpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
1651
1788
  async def main() -> None:
1652
- await client.datasets.delete_dataset_items(item_ids=['item_ids'], )
1789
+ await client.datasets.delete_dataset_items()
1653
1790
  asyncio.run(main())
1654
1791
  """
1655
- _response = await self._raw_client.delete_dataset_items(item_ids=item_ids, request_options=request_options)
1792
+ _response = await self._raw_client.delete_dataset_items(
1793
+ item_ids=item_ids,
1794
+ dataset_id=dataset_id,
1795
+ filters=filters,
1796
+ batch_group_id=batch_group_id,
1797
+ request_options=request_options,
1798
+ )
1656
1799
  return _response.data
1657
1800
 
1658
1801
  async def delete_datasets_batch(
@@ -2072,6 +2215,7 @@ class AsyncDatasetsClient:
2072
2215
  dataset_name: str,
2073
2216
  last_retrieved_id: typing.Optional[str] = OMIT,
2074
2217
  steam_limit: typing.Optional[int] = OMIT,
2218
+ dataset_version: typing.Optional[str] = OMIT,
2075
2219
  request_options: typing.Optional[RequestOptions] = None,
2076
2220
  ) -> typing.AsyncIterator[bytes]:
2077
2221
  """
@@ -2085,6 +2229,8 @@ class AsyncDatasetsClient:
2085
2229
 
2086
2230
  steam_limit : typing.Optional[int]
2087
2231
 
2232
+ dataset_version : typing.Optional[str]
2233
+
2088
2234
  request_options : typing.Optional[RequestOptions]
2089
2235
  Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.
2090
2236
 
@@ -2097,6 +2243,7 @@ class AsyncDatasetsClient:
2097
2243
  dataset_name=dataset_name,
2098
2244
  last_retrieved_id=last_retrieved_id,
2099
2245
  steam_limit=steam_limit,
2246
+ dataset_version=dataset_version,
2100
2247
  request_options=request_options,
2101
2248
  ) as r:
2102
2249
  async for data in r.data:
@@ -2167,32 +2314,26 @@ class AsyncDatasetsClient:
2167
2314
  )
2168
2315
  return _response.data
2169
2316
 
2170
- async def list_dataset_versions(
2171
- self,
2172
- id: str,
2173
- *,
2174
- page: typing.Optional[int] = None,
2175
- size: typing.Optional[int] = None,
2176
- request_options: typing.Optional[RequestOptions] = None,
2177
- ) -> DatasetVersionPagePublic:
2317
+ async def delete_version_tag(
2318
+ self, version_hash: str, tag: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
2319
+ ) -> None:
2178
2320
  """
2179
- Get paginated list of versions for a dataset, ordered by creation time (newest first)
2321
+ Remove a tag from a dataset version. The version itself is not deleted, only the tag reference.
2180
2322
 
2181
2323
  Parameters
2182
2324
  ----------
2183
- id : str
2325
+ version_hash : str
2184
2326
 
2185
- page : typing.Optional[int]
2327
+ tag : str
2186
2328
 
2187
- size : typing.Optional[int]
2329
+ id : str
2188
2330
 
2189
2331
  request_options : typing.Optional[RequestOptions]
2190
2332
  Request-specific configuration.
2191
2333
 
2192
2334
  Returns
2193
2335
  -------
2194
- DatasetVersionPagePublic
2195
- Dataset versions
2336
+ None
2196
2337
 
2197
2338
  Examples
2198
2339
  --------
@@ -2200,45 +2341,38 @@ class AsyncDatasetsClient:
2200
2341
  import asyncio
2201
2342
  client = AsyncOpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
2202
2343
  async def main() -> None:
2203
- await client.datasets.list_dataset_versions(id='id', )
2344
+ await client.datasets.delete_version_tag(version_hash='versionHash', tag='tag', id='id', )
2204
2345
  asyncio.run(main())
2205
2346
  """
2206
- _response = await self._raw_client.list_dataset_versions(
2207
- id, page=page, size=size, request_options=request_options
2208
- )
2347
+ _response = await self._raw_client.delete_version_tag(version_hash, tag, id, request_options=request_options)
2209
2348
  return _response.data
2210
2349
 
2211
- async def create_dataset_version(
2350
+ async def list_dataset_versions(
2212
2351
  self,
2213
2352
  id: str,
2214
2353
  *,
2215
- tags: typing.Optional[typing.Sequence[str]] = OMIT,
2216
- change_description: typing.Optional[str] = OMIT,
2217
- metadata: typing.Optional[typing.Dict[str, str]] = OMIT,
2354
+ page: typing.Optional[int] = None,
2355
+ size: typing.Optional[int] = None,
2218
2356
  request_options: typing.Optional[RequestOptions] = None,
2219
- ) -> None:
2357
+ ) -> DatasetVersionPagePublic:
2220
2358
  """
2221
- Create a new immutable version of the dataset by snapshotting the current state
2359
+ Get paginated list of versions for a dataset, ordered by creation time (newest first)
2222
2360
 
2223
2361
  Parameters
2224
2362
  ----------
2225
2363
  id : str
2226
2364
 
2227
- tags : typing.Optional[typing.Sequence[str]]
2228
- Optional list of tags for this version
2229
-
2230
- change_description : typing.Optional[str]
2231
- Optional description of changes in this version
2365
+ page : typing.Optional[int]
2232
2366
 
2233
- metadata : typing.Optional[typing.Dict[str, str]]
2234
- Optional user-defined metadata
2367
+ size : typing.Optional[int]
2235
2368
 
2236
2369
  request_options : typing.Optional[RequestOptions]
2237
2370
  Request-specific configuration.
2238
2371
 
2239
2372
  Returns
2240
2373
  -------
2241
- None
2374
+ DatasetVersionPagePublic
2375
+ Dataset versions
2242
2376
 
2243
2377
  Examples
2244
2378
  --------
@@ -2246,52 +2380,19 @@ class AsyncDatasetsClient:
2246
2380
  import asyncio
2247
2381
  client = AsyncOpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
2248
2382
  async def main() -> None:
2249
- await client.datasets.create_dataset_version(id='id', )
2383
+ await client.datasets.list_dataset_versions(id='id', )
2250
2384
  asyncio.run(main())
2251
2385
  """
2252
- _response = await self._raw_client.create_dataset_version(
2253
- id, tags=tags, change_description=change_description, metadata=metadata, request_options=request_options
2386
+ _response = await self._raw_client.list_dataset_versions(
2387
+ id, page=page, size=size, request_options=request_options
2254
2388
  )
2255
2389
  return _response.data
2256
2390
 
2257
- async def delete_version_tag(
2258
- self, version_hash: str, tag: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
2259
- ) -> None:
2260
- """
2261
- Remove a tag from a dataset version. The version itself is not deleted, only the tag reference.
2262
-
2263
- Parameters
2264
- ----------
2265
- version_hash : str
2266
-
2267
- tag : str
2268
-
2269
- id : str
2270
-
2271
- request_options : typing.Optional[RequestOptions]
2272
- Request-specific configuration.
2273
-
2274
- Returns
2275
- -------
2276
- None
2277
-
2278
- Examples
2279
- --------
2280
- from Opik import AsyncOpikApi
2281
- import asyncio
2282
- client = AsyncOpikApi(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME", )
2283
- async def main() -> None:
2284
- await client.datasets.delete_version_tag(version_hash='versionHash', tag='tag', id='id', )
2285
- asyncio.run(main())
2286
- """
2287
- _response = await self._raw_client.delete_version_tag(version_hash, tag, id, request_options=request_options)
2288
- return _response.data
2289
-
2290
2391
  async def restore_dataset_version(
2291
2392
  self, id: str, *, version_ref: str, request_options: typing.Optional[RequestOptions] = None
2292
2393
  ) -> DatasetVersionPublic:
2293
2394
  """
2294
- Restores the dataset to a previous version state. All draft items are replaced with items from the specified version. If the version is not the latest, a new version snapshot is created. If the version is the latest, only draft items are replaced (revert functionality).
2395
+ Restores the dataset to a previous version state by creating a new version with items copied from the specified version. If the version is already the latest, returns it as-is (no-op).
2295
2396
 
2296
2397
  Parameters
2297
2398
  ----------