opik 1.8.39__py3-none-any.whl → 1.9.71__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.
- opik/__init__.py +19 -3
- opik/anonymizer/__init__.py +5 -0
- opik/anonymizer/anonymizer.py +12 -0
- opik/anonymizer/factory.py +80 -0
- opik/anonymizer/recursive_anonymizer.py +64 -0
- opik/anonymizer/rules.py +56 -0
- opik/anonymizer/rules_anonymizer.py +35 -0
- opik/api_objects/attachment/attachment_context.py +36 -0
- opik/api_objects/attachment/attachments_extractor.py +153 -0
- opik/api_objects/attachment/client.py +1 -0
- opik/api_objects/attachment/converters.py +2 -0
- opik/api_objects/attachment/decoder.py +18 -0
- opik/api_objects/attachment/decoder_base64.py +83 -0
- opik/api_objects/attachment/decoder_helpers.py +137 -0
- opik/api_objects/data_helpers.py +79 -0
- opik/api_objects/dataset/dataset.py +64 -4
- opik/api_objects/dataset/rest_operations.py +11 -2
- opik/api_objects/experiment/experiment.py +57 -57
- opik/api_objects/experiment/experiment_item.py +2 -1
- opik/api_objects/experiment/experiments_client.py +64 -0
- opik/api_objects/experiment/helpers.py +35 -11
- opik/api_objects/experiment/rest_operations.py +65 -5
- opik/api_objects/helpers.py +8 -5
- opik/api_objects/local_recording.py +81 -0
- opik/api_objects/opik_client.py +600 -108
- opik/api_objects/opik_query_language.py +39 -5
- opik/api_objects/prompt/__init__.py +12 -2
- opik/api_objects/prompt/base_prompt.py +69 -0
- opik/api_objects/prompt/base_prompt_template.py +29 -0
- opik/api_objects/prompt/chat/__init__.py +1 -0
- opik/api_objects/prompt/chat/chat_prompt.py +210 -0
- opik/api_objects/prompt/chat/chat_prompt_template.py +350 -0
- opik/api_objects/prompt/chat/content_renderer_registry.py +203 -0
- opik/api_objects/prompt/client.py +189 -47
- opik/api_objects/prompt/text/__init__.py +1 -0
- opik/api_objects/prompt/text/prompt.py +174 -0
- opik/api_objects/prompt/{prompt_template.py → text/prompt_template.py} +10 -6
- opik/api_objects/prompt/types.py +23 -0
- opik/api_objects/search_helpers.py +89 -0
- opik/api_objects/span/span_data.py +35 -25
- opik/api_objects/threads/threads_client.py +39 -5
- opik/api_objects/trace/trace_client.py +52 -2
- opik/api_objects/trace/trace_data.py +15 -24
- opik/api_objects/validation_helpers.py +3 -3
- opik/cli/__init__.py +5 -0
- opik/cli/__main__.py +6 -0
- opik/cli/configure.py +66 -0
- opik/cli/exports/__init__.py +131 -0
- opik/cli/exports/dataset.py +278 -0
- opik/cli/exports/experiment.py +784 -0
- opik/cli/exports/project.py +685 -0
- opik/cli/exports/prompt.py +578 -0
- opik/cli/exports/utils.py +406 -0
- opik/cli/harbor.py +39 -0
- opik/cli/healthcheck.py +21 -0
- opik/cli/imports/__init__.py +439 -0
- opik/cli/imports/dataset.py +143 -0
- opik/cli/imports/experiment.py +1192 -0
- opik/cli/imports/project.py +262 -0
- opik/cli/imports/prompt.py +177 -0
- opik/cli/imports/utils.py +280 -0
- opik/cli/main.py +49 -0
- opik/cli/proxy.py +93 -0
- opik/cli/usage_report/__init__.py +16 -0
- opik/cli/usage_report/charts.py +783 -0
- opik/cli/usage_report/cli.py +274 -0
- opik/cli/usage_report/constants.py +9 -0
- opik/cli/usage_report/extraction.py +749 -0
- opik/cli/usage_report/pdf.py +244 -0
- opik/cli/usage_report/statistics.py +78 -0
- opik/cli/usage_report/utils.py +235 -0
- opik/config.py +13 -7
- opik/configurator/configure.py +17 -0
- opik/datetime_helpers.py +12 -0
- opik/decorator/arguments_helpers.py +9 -1
- opik/decorator/base_track_decorator.py +205 -133
- opik/decorator/context_manager/span_context_manager.py +123 -0
- opik/decorator/context_manager/trace_context_manager.py +84 -0
- opik/decorator/opik_args/__init__.py +13 -0
- opik/decorator/opik_args/api_classes.py +71 -0
- opik/decorator/opik_args/helpers.py +120 -0
- opik/decorator/span_creation_handler.py +25 -6
- opik/dict_utils.py +3 -3
- opik/evaluation/__init__.py +13 -2
- opik/evaluation/engine/engine.py +272 -75
- opik/evaluation/engine/evaluation_tasks_executor.py +6 -3
- opik/evaluation/engine/helpers.py +31 -6
- opik/evaluation/engine/metrics_evaluator.py +237 -0
- opik/evaluation/evaluation_result.py +168 -2
- opik/evaluation/evaluator.py +533 -62
- opik/evaluation/metrics/__init__.py +103 -4
- opik/evaluation/metrics/aggregated_metric.py +35 -6
- opik/evaluation/metrics/base_metric.py +1 -1
- opik/evaluation/metrics/conversation/__init__.py +48 -0
- opik/evaluation/metrics/conversation/conversation_thread_metric.py +56 -2
- opik/evaluation/metrics/conversation/g_eval_wrappers.py +19 -0
- opik/evaluation/metrics/conversation/helpers.py +14 -15
- opik/evaluation/metrics/conversation/heuristics/__init__.py +14 -0
- opik/evaluation/metrics/conversation/heuristics/degeneration/__init__.py +3 -0
- opik/evaluation/metrics/conversation/heuristics/degeneration/metric.py +189 -0
- opik/evaluation/metrics/conversation/heuristics/degeneration/phrases.py +12 -0
- opik/evaluation/metrics/conversation/heuristics/knowledge_retention/__init__.py +3 -0
- opik/evaluation/metrics/conversation/heuristics/knowledge_retention/metric.py +172 -0
- opik/evaluation/metrics/conversation/llm_judges/__init__.py +32 -0
- opik/evaluation/metrics/conversation/{conversational_coherence → llm_judges/conversational_coherence}/metric.py +22 -17
- opik/evaluation/metrics/conversation/{conversational_coherence → llm_judges/conversational_coherence}/templates.py +1 -1
- opik/evaluation/metrics/conversation/llm_judges/g_eval_wrappers.py +442 -0
- opik/evaluation/metrics/conversation/{session_completeness → llm_judges/session_completeness}/metric.py +13 -7
- opik/evaluation/metrics/conversation/{session_completeness → llm_judges/session_completeness}/templates.py +1 -1
- opik/evaluation/metrics/conversation/llm_judges/user_frustration/__init__.py +0 -0
- opik/evaluation/metrics/conversation/{user_frustration → llm_judges/user_frustration}/metric.py +21 -14
- opik/evaluation/metrics/conversation/{user_frustration → llm_judges/user_frustration}/templates.py +1 -1
- opik/evaluation/metrics/conversation/types.py +4 -5
- opik/evaluation/metrics/conversation_types.py +9 -0
- opik/evaluation/metrics/heuristics/bertscore.py +107 -0
- opik/evaluation/metrics/heuristics/bleu.py +35 -15
- opik/evaluation/metrics/heuristics/chrf.py +127 -0
- opik/evaluation/metrics/heuristics/contains.py +47 -11
- opik/evaluation/metrics/heuristics/distribution_metrics.py +331 -0
- opik/evaluation/metrics/heuristics/gleu.py +113 -0
- opik/evaluation/metrics/heuristics/language_adherence.py +123 -0
- opik/evaluation/metrics/heuristics/meteor.py +119 -0
- opik/evaluation/metrics/heuristics/prompt_injection.py +150 -0
- opik/evaluation/metrics/heuristics/readability.py +129 -0
- opik/evaluation/metrics/heuristics/rouge.py +26 -9
- opik/evaluation/metrics/heuristics/spearman.py +88 -0
- opik/evaluation/metrics/heuristics/tone.py +155 -0
- opik/evaluation/metrics/heuristics/vader_sentiment.py +77 -0
- opik/evaluation/metrics/llm_judges/answer_relevance/metric.py +20 -5
- opik/evaluation/metrics/llm_judges/context_precision/metric.py +20 -6
- opik/evaluation/metrics/llm_judges/context_recall/metric.py +20 -6
- opik/evaluation/metrics/llm_judges/g_eval/__init__.py +5 -0
- opik/evaluation/metrics/llm_judges/g_eval/metric.py +219 -68
- opik/evaluation/metrics/llm_judges/g_eval/parser.py +102 -52
- opik/evaluation/metrics/llm_judges/g_eval/presets.py +209 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/__init__.py +36 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/agent_assessment.py +77 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/bias_classifier.py +181 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/compliance_risk.py +41 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/prompt_uncertainty.py +41 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/qa_suite.py +146 -0
- opik/evaluation/metrics/llm_judges/hallucination/metric.py +16 -3
- opik/evaluation/metrics/llm_judges/llm_juries/__init__.py +3 -0
- opik/evaluation/metrics/llm_judges/llm_juries/metric.py +76 -0
- opik/evaluation/metrics/llm_judges/moderation/metric.py +16 -4
- opik/evaluation/metrics/llm_judges/structure_output_compliance/__init__.py +0 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/metric.py +144 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/parser.py +79 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/schema.py +15 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/template.py +50 -0
- opik/evaluation/metrics/llm_judges/syc_eval/__init__.py +0 -0
- opik/evaluation/metrics/llm_judges/syc_eval/metric.py +252 -0
- opik/evaluation/metrics/llm_judges/syc_eval/parser.py +82 -0
- opik/evaluation/metrics/llm_judges/syc_eval/template.py +155 -0
- opik/evaluation/metrics/llm_judges/trajectory_accuracy/metric.py +20 -5
- opik/evaluation/metrics/llm_judges/usefulness/metric.py +16 -4
- opik/evaluation/metrics/ragas_metric.py +43 -23
- opik/evaluation/models/__init__.py +8 -0
- opik/evaluation/models/base_model.py +107 -1
- opik/evaluation/models/langchain/langchain_chat_model.py +15 -7
- opik/evaluation/models/langchain/message_converters.py +97 -15
- opik/evaluation/models/litellm/litellm_chat_model.py +156 -29
- opik/evaluation/models/litellm/util.py +125 -0
- opik/evaluation/models/litellm/warning_filters.py +16 -4
- opik/evaluation/models/model_capabilities.py +187 -0
- opik/evaluation/models/models_factory.py +25 -3
- opik/evaluation/preprocessing.py +92 -0
- opik/evaluation/report.py +70 -12
- opik/evaluation/rest_operations.py +49 -45
- opik/evaluation/samplers/__init__.py +4 -0
- opik/evaluation/samplers/base_dataset_sampler.py +40 -0
- opik/evaluation/samplers/random_dataset_sampler.py +48 -0
- opik/evaluation/score_statistics.py +66 -0
- opik/evaluation/scorers/__init__.py +4 -0
- opik/evaluation/scorers/scorer_function.py +55 -0
- opik/evaluation/scorers/scorer_wrapper_metric.py +130 -0
- opik/evaluation/test_case.py +3 -2
- opik/evaluation/test_result.py +1 -0
- opik/evaluation/threads/evaluator.py +31 -3
- opik/evaluation/threads/helpers.py +3 -2
- opik/evaluation/types.py +9 -1
- opik/exceptions.py +33 -0
- opik/file_upload/file_uploader.py +13 -0
- opik/file_upload/upload_options.py +2 -0
- opik/hooks/__init__.py +23 -0
- opik/hooks/anonymizer_hook.py +36 -0
- opik/hooks/httpx_client_hook.py +112 -0
- opik/httpx_client.py +12 -9
- opik/id_helpers.py +18 -0
- opik/integrations/adk/graph/subgraph_edges_builders.py +1 -2
- opik/integrations/adk/helpers.py +16 -7
- opik/integrations/adk/legacy_opik_tracer.py +7 -4
- opik/integrations/adk/opik_tracer.py +14 -1
- opik/integrations/adk/patchers/adk_otel_tracer/opik_adk_otel_tracer.py +7 -3
- opik/integrations/adk/recursive_callback_injector.py +4 -7
- opik/integrations/bedrock/converse/__init__.py +0 -0
- opik/integrations/bedrock/converse/chunks_aggregator.py +188 -0
- opik/integrations/bedrock/{converse_decorator.py → converse/converse_decorator.py} +4 -3
- opik/integrations/bedrock/invoke_agent_decorator.py +5 -4
- opik/integrations/bedrock/invoke_model/__init__.py +0 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/__init__.py +78 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/api.py +45 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/base.py +23 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/claude.py +121 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/format_detector.py +107 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/llama.py +108 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/mistral.py +118 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/nova.py +99 -0
- opik/integrations/bedrock/invoke_model/invoke_model_decorator.py +178 -0
- opik/integrations/bedrock/invoke_model/response_types.py +34 -0
- opik/integrations/bedrock/invoke_model/stream_wrappers.py +122 -0
- opik/integrations/bedrock/invoke_model/usage_converters.py +87 -0
- opik/integrations/bedrock/invoke_model/usage_extraction.py +108 -0
- opik/integrations/bedrock/opik_tracker.py +42 -4
- opik/integrations/bedrock/types.py +19 -0
- opik/integrations/crewai/crewai_decorator.py +8 -51
- opik/integrations/crewai/opik_tracker.py +31 -10
- opik/integrations/crewai/patchers/__init__.py +5 -0
- opik/integrations/crewai/patchers/flow.py +118 -0
- opik/integrations/crewai/patchers/litellm_completion.py +30 -0
- opik/integrations/crewai/patchers/llm_client.py +207 -0
- opik/integrations/dspy/callback.py +80 -17
- opik/integrations/dspy/parsers.py +168 -0
- opik/integrations/harbor/__init__.py +17 -0
- opik/integrations/harbor/experiment_service.py +269 -0
- opik/integrations/harbor/opik_tracker.py +528 -0
- opik/integrations/haystack/opik_connector.py +2 -2
- opik/integrations/haystack/opik_tracer.py +3 -7
- opik/integrations/langchain/__init__.py +3 -1
- opik/integrations/langchain/helpers.py +96 -0
- opik/integrations/langchain/langgraph_async_context_bridge.py +131 -0
- opik/integrations/langchain/langgraph_tracer_injector.py +88 -0
- opik/integrations/langchain/opik_encoder_extension.py +1 -1
- opik/integrations/langchain/opik_tracer.py +474 -229
- opik/integrations/litellm/__init__.py +5 -0
- opik/integrations/litellm/completion_chunks_aggregator.py +115 -0
- opik/integrations/litellm/litellm_completion_decorator.py +242 -0
- opik/integrations/litellm/opik_tracker.py +43 -0
- opik/integrations/litellm/stream_patchers.py +151 -0
- opik/integrations/llama_index/callback.py +146 -107
- opik/integrations/openai/agents/opik_tracing_processor.py +1 -2
- opik/integrations/openai/openai_chat_completions_decorator.py +2 -16
- opik/integrations/openai/opik_tracker.py +1 -1
- opik/integrations/sagemaker/auth.py +5 -1
- opik/llm_usage/google_usage.py +3 -1
- opik/llm_usage/opik_usage.py +7 -8
- opik/llm_usage/opik_usage_factory.py +4 -2
- opik/logging_messages.py +6 -0
- opik/message_processing/batching/base_batcher.py +14 -21
- opik/message_processing/batching/batch_manager.py +22 -10
- opik/message_processing/batching/batch_manager_constuctors.py +10 -0
- opik/message_processing/batching/batchers.py +59 -27
- opik/message_processing/batching/flushing_thread.py +0 -3
- opik/message_processing/emulation/__init__.py +0 -0
- opik/message_processing/emulation/emulator_message_processor.py +578 -0
- opik/message_processing/emulation/local_emulator_message_processor.py +140 -0
- opik/message_processing/emulation/models.py +162 -0
- opik/message_processing/encoder_helpers.py +79 -0
- opik/message_processing/messages.py +56 -1
- opik/message_processing/preprocessing/__init__.py +0 -0
- opik/message_processing/preprocessing/attachments_preprocessor.py +70 -0
- opik/message_processing/preprocessing/batching_preprocessor.py +53 -0
- opik/message_processing/preprocessing/constants.py +1 -0
- opik/message_processing/preprocessing/file_upload_preprocessor.py +38 -0
- opik/message_processing/preprocessing/preprocessor.py +36 -0
- opik/message_processing/processors/__init__.py +0 -0
- opik/message_processing/processors/attachments_extraction_processor.py +146 -0
- opik/message_processing/processors/message_processors.py +92 -0
- opik/message_processing/processors/message_processors_chain.py +96 -0
- opik/message_processing/{message_processors.py → processors/online_message_processor.py} +85 -29
- opik/message_processing/queue_consumer.py +9 -3
- opik/message_processing/streamer.py +71 -33
- opik/message_processing/streamer_constructors.py +43 -10
- opik/opik_context.py +16 -4
- opik/plugins/pytest/hooks.py +5 -3
- opik/rest_api/__init__.py +346 -15
- opik/rest_api/alerts/__init__.py +7 -0
- opik/rest_api/alerts/client.py +667 -0
- opik/rest_api/alerts/raw_client.py +1015 -0
- opik/rest_api/alerts/types/__init__.py +7 -0
- opik/rest_api/alerts/types/get_webhook_examples_request_alert_type.py +5 -0
- opik/rest_api/annotation_queues/__init__.py +4 -0
- opik/rest_api/annotation_queues/client.py +668 -0
- opik/rest_api/annotation_queues/raw_client.py +1019 -0
- opik/rest_api/automation_rule_evaluators/client.py +34 -2
- opik/rest_api/automation_rule_evaluators/raw_client.py +24 -0
- opik/rest_api/client.py +15 -0
- opik/rest_api/dashboards/__init__.py +4 -0
- opik/rest_api/dashboards/client.py +462 -0
- opik/rest_api/dashboards/raw_client.py +648 -0
- opik/rest_api/datasets/client.py +1310 -44
- opik/rest_api/datasets/raw_client.py +2269 -358
- opik/rest_api/experiments/__init__.py +2 -2
- opik/rest_api/experiments/client.py +191 -5
- opik/rest_api/experiments/raw_client.py +301 -7
- opik/rest_api/experiments/types/__init__.py +4 -1
- opik/rest_api/experiments/types/experiment_update_status.py +5 -0
- opik/rest_api/experiments/types/experiment_update_type.py +5 -0
- opik/rest_api/experiments/types/experiment_write_status.py +5 -0
- opik/rest_api/feedback_definitions/types/find_feedback_definitions_request_type.py +1 -1
- opik/rest_api/llm_provider_key/client.py +20 -0
- opik/rest_api/llm_provider_key/raw_client.py +20 -0
- opik/rest_api/llm_provider_key/types/provider_api_key_write_provider.py +1 -1
- opik/rest_api/manual_evaluation/__init__.py +4 -0
- opik/rest_api/manual_evaluation/client.py +347 -0
- opik/rest_api/manual_evaluation/raw_client.py +543 -0
- opik/rest_api/optimizations/client.py +145 -9
- opik/rest_api/optimizations/raw_client.py +237 -13
- opik/rest_api/optimizations/types/optimization_update_status.py +3 -1
- opik/rest_api/prompts/__init__.py +2 -2
- opik/rest_api/prompts/client.py +227 -6
- opik/rest_api/prompts/raw_client.py +331 -2
- opik/rest_api/prompts/types/__init__.py +3 -1
- opik/rest_api/prompts/types/create_prompt_version_detail_template_structure.py +5 -0
- opik/rest_api/prompts/types/prompt_write_template_structure.py +5 -0
- opik/rest_api/spans/__init__.py +0 -2
- opik/rest_api/spans/client.py +238 -76
- opik/rest_api/spans/raw_client.py +307 -95
- opik/rest_api/spans/types/__init__.py +0 -2
- opik/rest_api/traces/client.py +572 -161
- opik/rest_api/traces/raw_client.py +736 -229
- opik/rest_api/types/__init__.py +352 -17
- opik/rest_api/types/aggregation_data.py +1 -0
- opik/rest_api/types/alert.py +33 -0
- opik/rest_api/types/alert_alert_type.py +5 -0
- opik/rest_api/types/alert_page_public.py +24 -0
- opik/rest_api/types/alert_public.py +33 -0
- opik/rest_api/types/alert_public_alert_type.py +5 -0
- opik/rest_api/types/alert_trigger.py +27 -0
- opik/rest_api/types/alert_trigger_config.py +28 -0
- opik/rest_api/types/alert_trigger_config_public.py +28 -0
- opik/rest_api/types/alert_trigger_config_public_type.py +10 -0
- opik/rest_api/types/alert_trigger_config_type.py +10 -0
- opik/rest_api/types/alert_trigger_config_write.py +22 -0
- opik/rest_api/types/alert_trigger_config_write_type.py +10 -0
- opik/rest_api/types/alert_trigger_event_type.py +19 -0
- opik/rest_api/types/alert_trigger_public.py +27 -0
- opik/rest_api/types/alert_trigger_public_event_type.py +19 -0
- opik/rest_api/types/alert_trigger_write.py +23 -0
- opik/rest_api/types/alert_trigger_write_event_type.py +19 -0
- opik/rest_api/types/alert_write.py +28 -0
- opik/rest_api/types/alert_write_alert_type.py +5 -0
- opik/rest_api/types/annotation_queue.py +42 -0
- opik/rest_api/types/annotation_queue_batch.py +27 -0
- opik/rest_api/types/annotation_queue_item_ids.py +19 -0
- opik/rest_api/types/annotation_queue_page_public.py +28 -0
- opik/rest_api/types/annotation_queue_public.py +38 -0
- opik/rest_api/types/annotation_queue_public_scope.py +5 -0
- opik/rest_api/types/annotation_queue_reviewer.py +20 -0
- opik/rest_api/types/annotation_queue_reviewer_public.py +20 -0
- opik/rest_api/types/annotation_queue_scope.py +5 -0
- opik/rest_api/types/annotation_queue_write.py +31 -0
- opik/rest_api/types/annotation_queue_write_scope.py +5 -0
- opik/rest_api/types/audio_url.py +19 -0
- opik/rest_api/types/audio_url_public.py +19 -0
- opik/rest_api/types/audio_url_write.py +19 -0
- opik/rest_api/types/automation_rule_evaluator.py +62 -2
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_object_object_public.py +155 -0
- opik/rest_api/types/automation_rule_evaluator_page_public.py +3 -2
- opik/rest_api/types/automation_rule_evaluator_public.py +57 -2
- opik/rest_api/types/automation_rule_evaluator_span_llm_as_judge.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_llm_as_judge_public.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_llm_as_judge_write.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python_public.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python_write.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update.py +51 -1
- opik/rest_api/types/automation_rule_evaluator_update_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update_span_llm_as_judge.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_update_span_user_defined_metric_python.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_update_trace_thread_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update_trace_thread_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_write.py +51 -1
- opik/rest_api/types/boolean_feedback_definition.py +25 -0
- opik/rest_api/types/boolean_feedback_definition_create.py +20 -0
- opik/rest_api/types/boolean_feedback_definition_public.py +25 -0
- opik/rest_api/types/boolean_feedback_definition_update.py +20 -0
- opik/rest_api/types/boolean_feedback_detail.py +29 -0
- opik/rest_api/types/boolean_feedback_detail_create.py +29 -0
- opik/rest_api/types/boolean_feedback_detail_public.py +29 -0
- opik/rest_api/types/boolean_feedback_detail_update.py +29 -0
- opik/rest_api/types/dashboard_page_public.py +24 -0
- opik/rest_api/types/dashboard_public.py +30 -0
- opik/rest_api/types/dataset.py +4 -0
- opik/rest_api/types/dataset_expansion.py +42 -0
- opik/rest_api/types/dataset_expansion_response.py +39 -0
- opik/rest_api/types/dataset_item.py +2 -0
- opik/rest_api/types/dataset_item_changes_public.py +5 -0
- opik/rest_api/types/dataset_item_compare.py +2 -0
- opik/rest_api/types/dataset_item_filter.py +27 -0
- opik/rest_api/types/dataset_item_filter_operator.py +21 -0
- opik/rest_api/types/dataset_item_page_compare.py +5 -0
- opik/rest_api/types/dataset_item_page_public.py +5 -0
- opik/rest_api/types/dataset_item_public.py +2 -0
- opik/rest_api/types/dataset_item_update.py +39 -0
- opik/rest_api/types/dataset_item_write.py +1 -0
- opik/rest_api/types/dataset_public.py +4 -0
- opik/rest_api/types/dataset_public_status.py +5 -0
- opik/rest_api/types/dataset_status.py +5 -0
- opik/rest_api/types/dataset_version_diff.py +22 -0
- opik/rest_api/types/dataset_version_diff_stats.py +24 -0
- opik/rest_api/types/dataset_version_page_public.py +23 -0
- opik/rest_api/types/dataset_version_public.py +59 -0
- opik/rest_api/types/dataset_version_summary.py +46 -0
- opik/rest_api/types/dataset_version_summary_public.py +46 -0
- opik/rest_api/types/experiment.py +7 -2
- opik/rest_api/types/experiment_group_response.py +2 -0
- opik/rest_api/types/experiment_public.py +7 -2
- opik/rest_api/types/experiment_public_status.py +5 -0
- opik/rest_api/types/experiment_score.py +20 -0
- opik/rest_api/types/experiment_score_public.py +20 -0
- opik/rest_api/types/experiment_score_write.py +20 -0
- opik/rest_api/types/experiment_status.py +5 -0
- opik/rest_api/types/feedback.py +25 -1
- opik/rest_api/types/feedback_create.py +20 -1
- opik/rest_api/types/feedback_object_public.py +27 -1
- opik/rest_api/types/feedback_public.py +25 -1
- opik/rest_api/types/feedback_score_batch_item.py +2 -1
- opik/rest_api/types/feedback_score_batch_item_thread.py +2 -1
- opik/rest_api/types/feedback_score_public.py +4 -0
- opik/rest_api/types/feedback_update.py +20 -1
- opik/rest_api/types/group_content_with_aggregations.py +1 -0
- opik/rest_api/types/group_detail.py +19 -0
- opik/rest_api/types/group_details.py +20 -0
- opik/rest_api/types/guardrail.py +1 -0
- opik/rest_api/types/guardrail_write.py +1 -0
- opik/rest_api/types/ids_holder.py +19 -0
- opik/rest_api/types/image_url.py +20 -0
- opik/rest_api/types/image_url_public.py +20 -0
- opik/rest_api/types/image_url_write.py +20 -0
- opik/rest_api/types/llm_as_judge_message.py +5 -1
- opik/rest_api/types/llm_as_judge_message_content.py +26 -0
- opik/rest_api/types/llm_as_judge_message_content_public.py +26 -0
- opik/rest_api/types/llm_as_judge_message_content_write.py +26 -0
- opik/rest_api/types/llm_as_judge_message_public.py +5 -1
- opik/rest_api/types/llm_as_judge_message_write.py +5 -1
- opik/rest_api/types/llm_as_judge_model_parameters.py +3 -0
- opik/rest_api/types/llm_as_judge_model_parameters_public.py +3 -0
- opik/rest_api/types/llm_as_judge_model_parameters_write.py +3 -0
- opik/rest_api/types/manual_evaluation_request.py +38 -0
- opik/rest_api/types/manual_evaluation_request_entity_type.py +5 -0
- opik/rest_api/types/manual_evaluation_response.py +27 -0
- opik/rest_api/types/optimization.py +4 -2
- opik/rest_api/types/optimization_public.py +4 -2
- opik/rest_api/types/optimization_public_status.py +3 -1
- opik/rest_api/types/optimization_status.py +3 -1
- opik/rest_api/types/optimization_studio_config.py +27 -0
- opik/rest_api/types/optimization_studio_config_public.py +27 -0
- opik/rest_api/types/optimization_studio_config_write.py +27 -0
- opik/rest_api/types/optimization_studio_log.py +22 -0
- opik/rest_api/types/optimization_write.py +4 -2
- opik/rest_api/types/optimization_write_status.py +3 -1
- opik/rest_api/types/project.py +1 -0
- opik/rest_api/types/project_detailed.py +1 -0
- opik/rest_api/types/project_reference.py +31 -0
- opik/rest_api/types/project_reference_public.py +31 -0
- opik/rest_api/types/project_stats_summary_item.py +1 -0
- opik/rest_api/types/prompt.py +6 -0
- opik/rest_api/types/prompt_detail.py +6 -0
- opik/rest_api/types/prompt_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_public.py +6 -0
- opik/rest_api/types/prompt_public_template_structure.py +5 -0
- opik/rest_api/types/prompt_template_structure.py +5 -0
- opik/rest_api/types/prompt_version.py +3 -0
- opik/rest_api/types/prompt_version_detail.py +3 -0
- opik/rest_api/types/prompt_version_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_link.py +1 -0
- opik/rest_api/types/prompt_version_link_public.py +1 -0
- opik/rest_api/types/prompt_version_page_public.py +5 -0
- opik/rest_api/types/prompt_version_public.py +3 -0
- opik/rest_api/types/prompt_version_public_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_update.py +33 -0
- opik/rest_api/types/provider_api_key.py +9 -0
- opik/rest_api/types/provider_api_key_provider.py +1 -1
- opik/rest_api/types/provider_api_key_public.py +9 -0
- opik/rest_api/types/provider_api_key_public_provider.py +1 -1
- opik/rest_api/types/score_name.py +1 -0
- opik/rest_api/types/service_toggles_config.py +18 -0
- opik/rest_api/types/span.py +1 -2
- opik/rest_api/types/span_enrichment_options.py +31 -0
- opik/rest_api/types/span_experiment_item_bulk_write_view.py +1 -2
- opik/rest_api/types/span_filter.py +23 -0
- opik/rest_api/types/span_filter_operator.py +21 -0
- opik/rest_api/types/span_filter_write.py +23 -0
- opik/rest_api/types/span_filter_write_operator.py +21 -0
- opik/rest_api/types/span_llm_as_judge_code.py +27 -0
- opik/rest_api/types/span_llm_as_judge_code_public.py +27 -0
- opik/rest_api/types/span_llm_as_judge_code_write.py +27 -0
- opik/rest_api/types/span_public.py +1 -2
- opik/rest_api/types/span_update.py +46 -0
- opik/rest_api/types/span_user_defined_metric_python_code.py +20 -0
- opik/rest_api/types/span_user_defined_metric_python_code_public.py +20 -0
- opik/rest_api/types/span_user_defined_metric_python_code_write.py +20 -0
- opik/rest_api/types/span_write.py +1 -2
- opik/rest_api/types/studio_evaluation.py +20 -0
- opik/rest_api/types/studio_evaluation_public.py +20 -0
- opik/rest_api/types/studio_evaluation_write.py +20 -0
- opik/rest_api/types/studio_llm_model.py +21 -0
- opik/rest_api/types/studio_llm_model_public.py +21 -0
- opik/rest_api/types/studio_llm_model_write.py +21 -0
- opik/rest_api/types/studio_message.py +20 -0
- opik/rest_api/types/studio_message_public.py +20 -0
- opik/rest_api/types/studio_message_write.py +20 -0
- opik/rest_api/types/studio_metric.py +21 -0
- opik/rest_api/types/studio_metric_public.py +21 -0
- opik/rest_api/types/studio_metric_write.py +21 -0
- opik/rest_api/types/studio_optimizer.py +21 -0
- opik/rest_api/types/studio_optimizer_public.py +21 -0
- opik/rest_api/types/studio_optimizer_write.py +21 -0
- opik/rest_api/types/studio_prompt.py +20 -0
- opik/rest_api/types/studio_prompt_public.py +20 -0
- opik/rest_api/types/studio_prompt_write.py +20 -0
- opik/rest_api/types/trace.py +11 -2
- opik/rest_api/types/trace_enrichment_options.py +32 -0
- opik/rest_api/types/trace_experiment_item_bulk_write_view.py +1 -2
- opik/rest_api/types/trace_filter.py +23 -0
- opik/rest_api/types/trace_filter_operator.py +21 -0
- opik/rest_api/types/trace_filter_write.py +23 -0
- opik/rest_api/types/trace_filter_write_operator.py +21 -0
- opik/rest_api/types/trace_public.py +11 -2
- opik/rest_api/types/trace_thread_filter_write.py +23 -0
- opik/rest_api/types/trace_thread_filter_write_operator.py +21 -0
- opik/rest_api/types/trace_thread_identifier.py +1 -0
- opik/rest_api/types/trace_update.py +39 -0
- opik/rest_api/types/trace_write.py +1 -2
- opik/rest_api/types/value_entry.py +2 -0
- opik/rest_api/types/value_entry_compare.py +2 -0
- opik/rest_api/types/value_entry_experiment_item_bulk_write_view.py +2 -0
- opik/rest_api/types/value_entry_public.py +2 -0
- opik/rest_api/types/video_url.py +19 -0
- opik/rest_api/types/video_url_public.py +19 -0
- opik/rest_api/types/video_url_write.py +19 -0
- opik/rest_api/types/webhook.py +28 -0
- opik/rest_api/types/webhook_examples.py +19 -0
- opik/rest_api/types/webhook_public.py +28 -0
- opik/rest_api/types/webhook_test_result.py +23 -0
- opik/rest_api/types/webhook_test_result_status.py +5 -0
- opik/rest_api/types/webhook_write.py +23 -0
- opik/rest_api/types/welcome_wizard_tracking.py +22 -0
- opik/rest_api/types/workspace_configuration.py +5 -0
- opik/rest_api/welcome_wizard/__init__.py +4 -0
- opik/rest_api/welcome_wizard/client.py +195 -0
- opik/rest_api/welcome_wizard/raw_client.py +208 -0
- opik/rest_api/workspaces/client.py +14 -2
- opik/rest_api/workspaces/raw_client.py +10 -0
- opik/s3_httpx_client.py +14 -1
- opik/simulation/__init__.py +6 -0
- opik/simulation/simulated_user.py +99 -0
- opik/simulation/simulator.py +108 -0
- opik/synchronization.py +5 -6
- opik/{decorator/tracing_runtime_config.py → tracing_runtime_config.py} +6 -7
- opik/types.py +36 -0
- opik/validation/chat_prompt_messages.py +241 -0
- opik/validation/feedback_score.py +3 -3
- opik/validation/validator.py +28 -0
- opik-1.9.71.dist-info/METADATA +370 -0
- opik-1.9.71.dist-info/RECORD +1110 -0
- opik/api_objects/prompt/prompt.py +0 -112
- opik/cli.py +0 -193
- opik/hooks.py +0 -13
- opik/integrations/bedrock/chunks_aggregator.py +0 -55
- opik/integrations/bedrock/helpers.py +0 -8
- opik/rest_api/types/automation_rule_evaluator_object_public.py +0 -100
- opik/rest_api/types/json_node_experiment_item_bulk_write_view.py +0 -5
- opik-1.8.39.dist-info/METADATA +0 -339
- opik-1.8.39.dist-info/RECORD +0 -790
- /opik/{evaluation/metrics/conversation/conversational_coherence → decorator/context_manager}/__init__.py +0 -0
- /opik/evaluation/metrics/conversation/{session_completeness → llm_judges/conversational_coherence}/__init__.py +0 -0
- /opik/evaluation/metrics/conversation/{conversational_coherence → llm_judges/conversational_coherence}/schema.py +0 -0
- /opik/evaluation/metrics/conversation/{user_frustration → llm_judges/session_completeness}/__init__.py +0 -0
- /opik/evaluation/metrics/conversation/{session_completeness → llm_judges/session_completeness}/schema.py +0 -0
- /opik/evaluation/metrics/conversation/{user_frustration → llm_judges/user_frustration}/schema.py +0 -0
- /opik/integrations/bedrock/{stream_wrappers.py → converse/stream_wrappers.py} +0 -0
- /opik/rest_api/{spans/types → types}/span_update_type.py +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/WHEEL +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/entry_points.txt +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/licenses/LICENSE +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/top_level.txt +0 -0
|
@@ -5,16 +5,15 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
5
5
|
|
|
6
6
|
import opik.api_objects.attachment as attachment
|
|
7
7
|
import opik.datetime_helpers as datetime_helpers
|
|
8
|
-
import opik.dict_utils as dict_utils
|
|
9
8
|
import opik.llm_usage as llm_usage
|
|
10
9
|
from opik.types import (
|
|
10
|
+
DistributedTraceHeadersDict,
|
|
11
11
|
ErrorInfoDict,
|
|
12
12
|
FeedbackScoreDict,
|
|
13
13
|
LLMProvider,
|
|
14
14
|
SpanType,
|
|
15
15
|
)
|
|
16
|
-
|
|
17
|
-
from .. import helpers
|
|
16
|
+
from .. import helpers, data_helpers
|
|
18
17
|
|
|
19
18
|
LOGGER = logging.getLogger(__name__)
|
|
20
19
|
|
|
@@ -97,11 +96,24 @@ class SpanData:
|
|
|
97
96
|
)
|
|
98
97
|
|
|
99
98
|
def update(self, **new_data: Any) -> "SpanData":
|
|
99
|
+
"""
|
|
100
|
+
Updates the attributes of the object with the provided key-value pairs. This method checks if
|
|
101
|
+
an attribute exists before updating it and merges the data appropriately for specific
|
|
102
|
+
keywords like metadata, output, input, attachments, and tags. If a key doesn't correspond
|
|
103
|
+
to an attribute of the object or the provided value is None, the update is skipped.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
**new_data: Key-value pairs of attributes to update. Keys should match existing
|
|
107
|
+
attributes on the object, and values that are None will not update.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
SpanData: The updated object instance.
|
|
111
|
+
"""
|
|
100
112
|
for key, value in new_data.items():
|
|
101
113
|
if value is None:
|
|
102
114
|
continue
|
|
103
115
|
|
|
104
|
-
if key not in self.__dict__:
|
|
116
|
+
if key not in self.__dict__ and key != "prompts":
|
|
105
117
|
LOGGER.debug(
|
|
106
118
|
"An attempt to update span with parameter name it doesn't have: %s",
|
|
107
119
|
key,
|
|
@@ -109,40 +121,32 @@ class SpanData:
|
|
|
109
121
|
continue
|
|
110
122
|
|
|
111
123
|
if key == "metadata":
|
|
112
|
-
self.
|
|
124
|
+
self.metadata = data_helpers.merge_metadata(
|
|
125
|
+
self.metadata, new_metadata=value
|
|
126
|
+
)
|
|
113
127
|
continue
|
|
114
128
|
elif key == "output":
|
|
115
|
-
self.
|
|
129
|
+
self.output = data_helpers.merge_outputs(self.output, new_outputs=value)
|
|
116
130
|
continue
|
|
117
131
|
elif key == "input":
|
|
118
|
-
self.
|
|
132
|
+
self.input = data_helpers.merge_inputs(self.input, new_inputs=value)
|
|
119
133
|
continue
|
|
120
134
|
elif key == "attachments":
|
|
121
135
|
self._update_attachments(value)
|
|
122
136
|
continue
|
|
137
|
+
elif key == "tags":
|
|
138
|
+
self.tags = data_helpers.merge_tags(self.tags, new_tags=value)
|
|
139
|
+
continue
|
|
140
|
+
elif key == "prompts":
|
|
141
|
+
self.metadata = data_helpers.merge_metadata(
|
|
142
|
+
self.metadata, new_metadata=new_data.get("metadata"), prompts=value
|
|
143
|
+
)
|
|
144
|
+
continue
|
|
123
145
|
|
|
124
146
|
self.__dict__[key] = value
|
|
125
147
|
|
|
126
148
|
return self
|
|
127
149
|
|
|
128
|
-
def _update_metadata(self, new_metadata: Dict[str, Any]) -> None:
|
|
129
|
-
if self.metadata is None:
|
|
130
|
-
self.metadata = new_metadata
|
|
131
|
-
else:
|
|
132
|
-
self.metadata = dict_utils.deepmerge(self.metadata, new_metadata)
|
|
133
|
-
|
|
134
|
-
def _update_output(self, new_output: Dict[str, Any]) -> None:
|
|
135
|
-
if self.output is None:
|
|
136
|
-
self.output = new_output
|
|
137
|
-
else:
|
|
138
|
-
self.output = dict_utils.deepmerge(self.output, new_output)
|
|
139
|
-
|
|
140
|
-
def _update_input(self, new_input: Dict[str, Any]) -> None:
|
|
141
|
-
if self.input is None:
|
|
142
|
-
self.input = new_input
|
|
143
|
-
else:
|
|
144
|
-
self.input = dict_utils.deepmerge(self.input, new_input)
|
|
145
|
-
|
|
146
150
|
def init_end_time(self) -> "SpanData":
|
|
147
151
|
self.end_time = datetime_helpers.local_timestamp()
|
|
148
152
|
|
|
@@ -199,3 +203,9 @@ class SpanData:
|
|
|
199
203
|
"total_cost": self.total_cost,
|
|
200
204
|
"attachments": self.attachments,
|
|
201
205
|
}
|
|
206
|
+
|
|
207
|
+
def get_distributed_trace_headers(self) -> DistributedTraceHeadersDict:
|
|
208
|
+
return DistributedTraceHeadersDict(
|
|
209
|
+
opik_trace_id=self.trace_id,
|
|
210
|
+
opik_parent_span_id=self.id,
|
|
211
|
+
)
|
|
@@ -3,7 +3,7 @@ from typing import List, Optional
|
|
|
3
3
|
|
|
4
4
|
import opik
|
|
5
5
|
from opik.rest_api import TraceThread
|
|
6
|
-
from opik.types import
|
|
6
|
+
from opik.types import BatchFeedbackScoreDict
|
|
7
7
|
|
|
8
8
|
from .. import helpers, rest_stream_parser, constants
|
|
9
9
|
from ... import config
|
|
@@ -54,8 +54,41 @@ class ThreadsClient:
|
|
|
54
54
|
The name of the project to search the threads for. If None, the search
|
|
55
55
|
will include threads from all projects.
|
|
56
56
|
filter_string:
|
|
57
|
-
A string
|
|
58
|
-
format
|
|
57
|
+
A filter string to narrow down the search using Opik Query Language (OQL).
|
|
58
|
+
The format is: "<COLUMN> <OPERATOR> <VALUE> [AND <COLUMN> <OPERATOR> <VALUE>]*"
|
|
59
|
+
|
|
60
|
+
Supported columns include:
|
|
61
|
+
- `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: String fields with full operator support
|
|
62
|
+
- `status`: String field (=, contains, not_contains only)
|
|
63
|
+
- `start_time`, `end_time`: DateTime fields (use ISO 8601 format, e.g., "2024-01-01T00:00:00Z")
|
|
64
|
+
- `input`, `output`: String fields for content (=, contains, not_contains only)
|
|
65
|
+
- `metadata`: Dictionary field (use dot notation, e.g., "metadata.model")
|
|
66
|
+
- `feedback_scores`: Numeric field (use dot notation, e.g., "feedback_scores.accuracy")
|
|
67
|
+
- `tags`: List field (use "contains" operator only)
|
|
68
|
+
- `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`: Numeric usage fields
|
|
69
|
+
- `duration`, `number_of_messages`, `total_estimated_cost`: Numeric fields
|
|
70
|
+
|
|
71
|
+
Supported operators by column:
|
|
72
|
+
- `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: =, !=, contains, not_contains, starts_with, ends_with, >, <
|
|
73
|
+
- `status`: =, contains, not_contains
|
|
74
|
+
- `start_time`, `end_time`: =, >, <, >=, <=
|
|
75
|
+
- `input`, `output`: =, contains, not_contains
|
|
76
|
+
- `metadata`: =, contains, >, <
|
|
77
|
+
- `feedback_scores`: =, >, <, >=, <=, is_empty, is_not_empty
|
|
78
|
+
- `tags`: contains (only)
|
|
79
|
+
- `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`, `duration`, `number_of_messages`, `total_estimated_cost`: =, !=, >, <, >=, <=
|
|
80
|
+
|
|
81
|
+
Examples:
|
|
82
|
+
- `status = "inactive"` - Filter by thread status
|
|
83
|
+
- `id = "thread_123"` - Filter by specific thread ID
|
|
84
|
+
- `duration > 300` - Filter by thread duration (seconds)
|
|
85
|
+
- `number_of_messages >= 5` - Filter by message count
|
|
86
|
+
- `feedback_scores.user_frustration > 0.5` - Filter by feedback score
|
|
87
|
+
- `feedback_scores.my_metric is_empty` - Filter threads with empty feedback score
|
|
88
|
+
- `feedback_scores.my_metric is_not_empty` - Filter threads with non-empty feedback score
|
|
89
|
+
- `tags contains "important"` - Filter by tag
|
|
90
|
+
|
|
91
|
+
If not provided, all threads in the project will be returned up to the limit.
|
|
59
92
|
max_results:
|
|
60
93
|
The maximum number of threads to retrieve. The default value is 1000
|
|
61
94
|
if not specified.
|
|
@@ -96,7 +129,7 @@ class ThreadsClient:
|
|
|
96
129
|
return threads
|
|
97
130
|
|
|
98
131
|
def log_threads_feedback_scores(
|
|
99
|
-
self, scores: List[
|
|
132
|
+
self, scores: List[BatchFeedbackScoreDict], project_name: Optional[str] = None
|
|
100
133
|
) -> None:
|
|
101
134
|
"""
|
|
102
135
|
Logs feedback scores for threads in a specific project. This method processes the given
|
|
@@ -107,7 +140,8 @@ class ThreadsClient:
|
|
|
107
140
|
scores: A list of dictionaries containing feedback scores
|
|
108
141
|
for threads to be logged. Specifying a thread id via `id` key for each score is mandatory.
|
|
109
142
|
project_name: The name of the project to associate with the logged
|
|
110
|
-
scores. If not provided, the
|
|
143
|
+
scores. If not provided, the project name configured in the Opik client will be used.
|
|
144
|
+
This parameter is used as a fallback if `project_name` is not specified in the score dictionary.
|
|
111
145
|
"""
|
|
112
146
|
project_name = project_name or self._opik_client.project_name
|
|
113
147
|
|
|
@@ -97,9 +97,10 @@ class Trace:
|
|
|
97
97
|
Returns:
|
|
98
98
|
None
|
|
99
99
|
"""
|
|
100
|
-
|
|
100
|
+
update_trace(
|
|
101
101
|
trace_id=self.id,
|
|
102
102
|
project_name=self._project_name,
|
|
103
|
+
message_streamer=self._streamer,
|
|
103
104
|
end_time=end_time,
|
|
104
105
|
metadata=metadata,
|
|
105
106
|
input=input,
|
|
@@ -108,7 +109,6 @@ class Trace:
|
|
|
108
109
|
error_info=error_info,
|
|
109
110
|
thread_id=thread_id,
|
|
110
111
|
)
|
|
111
|
-
self._streamer.put(update_trace_message)
|
|
112
112
|
|
|
113
113
|
def span(
|
|
114
114
|
self,
|
|
@@ -215,3 +215,53 @@ class Trace:
|
|
|
215
215
|
)
|
|
216
216
|
|
|
217
217
|
self._streamer.put(add_trace_feedback_batch_message)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def update_trace(
|
|
221
|
+
trace_id: str,
|
|
222
|
+
project_name: str,
|
|
223
|
+
message_streamer: streamer.Streamer,
|
|
224
|
+
end_time: Optional[datetime.datetime] = None,
|
|
225
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
226
|
+
input: Optional[Dict[str, Any]] = None,
|
|
227
|
+
output: Optional[Dict[str, Any]] = None,
|
|
228
|
+
tags: Optional[List[Any]] = None,
|
|
229
|
+
error_info: Optional[ErrorInfoDict] = None,
|
|
230
|
+
thread_id: Optional[str] = None,
|
|
231
|
+
) -> None:
|
|
232
|
+
"""
|
|
233
|
+
Update an existing trace with new information.
|
|
234
|
+
This function sends an UpdateTraceMessage to the provided message_streamer,
|
|
235
|
+
allowing you to update various fields of a trace, such as its end time,
|
|
236
|
+
metadata, input, output, tags, error information and thread association.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
trace_id: The unique identifier of the trace to update.
|
|
240
|
+
project_name: The name of the project associated with the trace.
|
|
241
|
+
message_streamer: The message streamer used to send the update.
|
|
242
|
+
end_time: The end time of the trace. Defaults to None.
|
|
243
|
+
metadata: Additional metadata for the trace. Defaults to None.
|
|
244
|
+
input: Input data associated with the trace. Defaults to None.
|
|
245
|
+
output: Output data associated with the trace. Defaults to None.
|
|
246
|
+
tags: List of tags to associate with the trace. Defaults to None.
|
|
247
|
+
error_info: Error information related to the trace. Defaults to None.
|
|
248
|
+
thread_id : The thread ID associated with the trace. Defaults to None.
|
|
249
|
+
Returns:
|
|
250
|
+
None
|
|
251
|
+
Usage Notes:
|
|
252
|
+
- This function does not return a value; it sends an update message to the message streamer.
|
|
253
|
+
- All parameters except trace_id, project_name and message_streamer are optional.
|
|
254
|
+
- Only the fields provided will be updated in the trace.
|
|
255
|
+
"""
|
|
256
|
+
update_trace_message = messages.UpdateTraceMessage(
|
|
257
|
+
trace_id=trace_id,
|
|
258
|
+
project_name=project_name,
|
|
259
|
+
end_time=end_time,
|
|
260
|
+
metadata=metadata,
|
|
261
|
+
input=input,
|
|
262
|
+
output=output,
|
|
263
|
+
tags=tags,
|
|
264
|
+
error_info=error_info,
|
|
265
|
+
thread_id=thread_id,
|
|
266
|
+
)
|
|
267
|
+
message_streamer.put(update_trace_message)
|
|
@@ -3,9 +3,7 @@ import datetime
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Any, Dict, List, Optional, Union
|
|
5
5
|
|
|
6
|
-
import opik.dict_utils as dict_utils
|
|
7
6
|
import opik.api_objects.attachment as attachment
|
|
8
|
-
from .. import span
|
|
9
7
|
import opik.datetime_helpers as datetime_helpers
|
|
10
8
|
import opik.id_helpers as id_helpers
|
|
11
9
|
import opik.llm_usage as llm_usage
|
|
@@ -16,6 +14,7 @@ from opik.types import (
|
|
|
16
14
|
LLMProvider,
|
|
17
15
|
SpanType,
|
|
18
16
|
)
|
|
17
|
+
from .. import span, data_helpers
|
|
19
18
|
|
|
20
19
|
LOGGER = logging.getLogger(__name__)
|
|
21
20
|
|
|
@@ -97,7 +96,7 @@ class TraceData:
|
|
|
97
96
|
if value is None:
|
|
98
97
|
continue
|
|
99
98
|
|
|
100
|
-
if key not in self.__dict__:
|
|
99
|
+
if key not in self.__dict__ and key != "prompts":
|
|
101
100
|
LOGGER.debug(
|
|
102
101
|
"An attempt to update span with parameter name it doesn't have: %s",
|
|
103
102
|
key,
|
|
@@ -105,40 +104,32 @@ class TraceData:
|
|
|
105
104
|
continue
|
|
106
105
|
|
|
107
106
|
if key == "metadata":
|
|
108
|
-
self.
|
|
107
|
+
self.metadata = data_helpers.merge_metadata(
|
|
108
|
+
self.metadata, new_metadata=value
|
|
109
|
+
)
|
|
109
110
|
continue
|
|
110
111
|
elif key == "output":
|
|
111
|
-
self.
|
|
112
|
+
self.output = data_helpers.merge_outputs(self.output, new_outputs=value)
|
|
112
113
|
continue
|
|
113
114
|
elif key == "input":
|
|
114
|
-
self.
|
|
115
|
+
self.input = data_helpers.merge_inputs(self.input, new_inputs=value)
|
|
115
116
|
continue
|
|
116
117
|
elif key == "attachments":
|
|
117
118
|
self._update_attachments(value)
|
|
118
119
|
continue
|
|
120
|
+
elif key == "tags":
|
|
121
|
+
self.tags = data_helpers.merge_tags(self.tags, new_tags=value)
|
|
122
|
+
continue
|
|
123
|
+
elif key == "prompts":
|
|
124
|
+
self.metadata = data_helpers.merge_metadata(
|
|
125
|
+
self.metadata, new_metadata=new_data.get("metadata"), prompts=value
|
|
126
|
+
)
|
|
127
|
+
continue
|
|
119
128
|
|
|
120
129
|
self.__dict__[key] = value
|
|
121
130
|
|
|
122
131
|
return self
|
|
123
132
|
|
|
124
|
-
def _update_metadata(self, new_metadata: Dict[str, Any]) -> None:
|
|
125
|
-
if self.metadata is None:
|
|
126
|
-
self.metadata = new_metadata
|
|
127
|
-
else:
|
|
128
|
-
self.metadata = dict_utils.deepmerge(self.metadata, new_metadata)
|
|
129
|
-
|
|
130
|
-
def _update_output(self, new_output: Dict[str, Any]) -> None:
|
|
131
|
-
if self.output is None:
|
|
132
|
-
self.output = new_output
|
|
133
|
-
else:
|
|
134
|
-
self.output = dict_utils.deepmerge(self.output, new_output)
|
|
135
|
-
|
|
136
|
-
def _update_input(self, new_input: Dict[str, Any]) -> None:
|
|
137
|
-
if self.input is None:
|
|
138
|
-
self.input = new_input
|
|
139
|
-
else:
|
|
140
|
-
self.input = dict_utils.deepmerge(self.input, new_input)
|
|
141
|
-
|
|
142
133
|
def init_end_time(self) -> "TraceData":
|
|
143
134
|
self.end_time = datetime_helpers.local_timestamp()
|
|
144
135
|
return self
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Any, Optional, cast, Union, Dict
|
|
3
3
|
|
|
4
|
-
from ..types import
|
|
4
|
+
from ..types import BatchFeedbackScoreDict
|
|
5
5
|
from ..validation import feedback_score as feedback_score_validator
|
|
6
6
|
from .. import logging_messages, llm_usage
|
|
7
7
|
from opik.types import LLMProvider
|
|
@@ -38,7 +38,7 @@ def validate_and_parse_usage(
|
|
|
38
38
|
|
|
39
39
|
def validate_feedback_score(
|
|
40
40
|
feedback_score: Any, logger: logging.Logger
|
|
41
|
-
) -> Optional[
|
|
41
|
+
) -> Optional[BatchFeedbackScoreDict]:
|
|
42
42
|
feedback_score_validator_ = feedback_score_validator.FeedbackScoreValidator(
|
|
43
43
|
feedback_score
|
|
44
44
|
)
|
|
@@ -51,4 +51,4 @@ def validate_feedback_score(
|
|
|
51
51
|
)
|
|
52
52
|
return None
|
|
53
53
|
|
|
54
|
-
return cast(
|
|
54
|
+
return cast(BatchFeedbackScoreDict, feedback_score)
|
opik/cli/__init__.py
ADDED
opik/cli/__main__.py
ADDED
opik/cli/configure.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Configure command for Opik CLI."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from opik.configurator import configure as opik_configure, interactive_helpers
|
|
8
|
+
|
|
9
|
+
LOGGER = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.command(context_settings={"ignore_unknown_options": True})
|
|
13
|
+
@click.option(
|
|
14
|
+
"--use_local",
|
|
15
|
+
"--use-local",
|
|
16
|
+
is_flag=True,
|
|
17
|
+
default=False,
|
|
18
|
+
help="Flag to configure the Opik Python SDK for local Opik deployments.",
|
|
19
|
+
)
|
|
20
|
+
@click.option(
|
|
21
|
+
"-y",
|
|
22
|
+
"--yes",
|
|
23
|
+
is_flag=True,
|
|
24
|
+
default=False,
|
|
25
|
+
help="Flag to automatically answer `yes` whenever a user approval might be required",
|
|
26
|
+
)
|
|
27
|
+
def configure(use_local: bool, yes: bool) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Create a configuration file for the Opik Python SDK, if a configuration file already exists, it will be overwritten.
|
|
30
|
+
This is also available as a function in the Python SDK.
|
|
31
|
+
"""
|
|
32
|
+
automatic_approvals = yes
|
|
33
|
+
|
|
34
|
+
if use_local:
|
|
35
|
+
opik_configure.configure(
|
|
36
|
+
use_local=True, force=True, automatic_approvals=automatic_approvals
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
deployment_type_choice = interactive_helpers.ask_user_for_deployment_type()
|
|
40
|
+
|
|
41
|
+
if deployment_type_choice == interactive_helpers.DeploymentType.CLOUD:
|
|
42
|
+
configurator = opik_configure.OpikConfigurator(
|
|
43
|
+
url=opik_configure.OPIK_BASE_URL_CLOUD,
|
|
44
|
+
use_local=False,
|
|
45
|
+
force=True,
|
|
46
|
+
self_hosted_comet=False,
|
|
47
|
+
automatic_approvals=automatic_approvals,
|
|
48
|
+
)
|
|
49
|
+
elif deployment_type_choice == interactive_helpers.DeploymentType.SELF_HOSTED:
|
|
50
|
+
configurator = opik_configure.OpikConfigurator(
|
|
51
|
+
use_local=False,
|
|
52
|
+
force=True,
|
|
53
|
+
self_hosted_comet=True,
|
|
54
|
+
automatic_approvals=automatic_approvals,
|
|
55
|
+
)
|
|
56
|
+
elif deployment_type_choice == interactive_helpers.DeploymentType.LOCAL:
|
|
57
|
+
configurator = opik_configure.OpikConfigurator(
|
|
58
|
+
use_local=True,
|
|
59
|
+
force=True,
|
|
60
|
+
self_hosted_comet=False,
|
|
61
|
+
automatic_approvals=automatic_approvals,
|
|
62
|
+
)
|
|
63
|
+
else:
|
|
64
|
+
raise click.ClickException("Unknown deployment type was selected. Exiting.")
|
|
65
|
+
|
|
66
|
+
configurator.configure()
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Download command for Opik CLI."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from .dataset import export_dataset_command
|
|
8
|
+
from .experiment import export_experiment_command
|
|
9
|
+
from .prompt import export_prompt_command
|
|
10
|
+
from .project import export_project_command
|
|
11
|
+
|
|
12
|
+
EXPORT_CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.group(
|
|
16
|
+
name="export", context_settings=EXPORT_CONTEXT_SETTINGS, invoke_without_command=True
|
|
17
|
+
)
|
|
18
|
+
@click.argument("workspace", type=str)
|
|
19
|
+
@click.option(
|
|
20
|
+
"--api-key",
|
|
21
|
+
type=str,
|
|
22
|
+
help="Opik API key. If not provided, will use OPIK_API_KEY environment variable or configuration.",
|
|
23
|
+
)
|
|
24
|
+
@click.pass_context
|
|
25
|
+
def export_group(ctx: click.Context, workspace: str, api_key: Optional[str]) -> None:
|
|
26
|
+
"""Export data from Opik workspace.
|
|
27
|
+
|
|
28
|
+
This command allows you to export specific data from an Opik workspace to local files.
|
|
29
|
+
Supported data types include datasets, projects, experiments, and prompts.
|
|
30
|
+
|
|
31
|
+
\b
|
|
32
|
+
General Usage:
|
|
33
|
+
opik export WORKSPACE ITEM NAME [OPTIONS]
|
|
34
|
+
|
|
35
|
+
\b
|
|
36
|
+
Data Types (ITEM):
|
|
37
|
+
dataset Export a dataset by exact name (exports dataset definition and items)
|
|
38
|
+
project Export a project by name or ID (exports project traces and metadata)
|
|
39
|
+
experiment Export an experiment by name or ID (exports experiment configuration and results)
|
|
40
|
+
prompt Export a prompt by exact name (exports prompt templates and versions)
|
|
41
|
+
|
|
42
|
+
\b
|
|
43
|
+
Common Options:
|
|
44
|
+
--path, -p Directory to save exported data (default: opik_exports)
|
|
45
|
+
--format Export format: json or csv (default: json)
|
|
46
|
+
--max-results Maximum number of items to export (varies by data type)
|
|
47
|
+
--force Re-download items even if they already exist locally
|
|
48
|
+
--debug Show detailed information about the export process
|
|
49
|
+
|
|
50
|
+
\b
|
|
51
|
+
Examples:
|
|
52
|
+
# Export a specific dataset
|
|
53
|
+
opik export my-workspace dataset "my-dataset"
|
|
54
|
+
|
|
55
|
+
# Export a project with OQL filter
|
|
56
|
+
opik export my-workspace project "my-project" --filter "status:completed"
|
|
57
|
+
|
|
58
|
+
# Export an experiment with dataset filter (by name or ID)
|
|
59
|
+
opik export my-workspace experiment "my-experiment" --dataset "my-dataset"
|
|
60
|
+
opik export my-workspace experiment "01234567-89ab-cdef-0123-456789abcdef" --dataset "my-dataset"
|
|
61
|
+
|
|
62
|
+
# Export in CSV format to a specific directory
|
|
63
|
+
opik export my-workspace prompt "my-template" --format csv --path ./custom-exports
|
|
64
|
+
"""
|
|
65
|
+
ctx.ensure_object(dict)
|
|
66
|
+
ctx.obj["workspace"] = workspace
|
|
67
|
+
# Use API key from this command or from parent context
|
|
68
|
+
ctx.obj["api_key"] = api_key or (
|
|
69
|
+
ctx.parent.obj.get("api_key") if ctx.parent and ctx.parent.obj else None
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# If no subcommand was invoked, show helpful error
|
|
73
|
+
if ctx.invoked_subcommand is None:
|
|
74
|
+
available_items = ", ".join(
|
|
75
|
+
sorted(["dataset", "experiment", "prompt", "project"])
|
|
76
|
+
)
|
|
77
|
+
click.echo(
|
|
78
|
+
f"Error: Missing ITEM.\n\n"
|
|
79
|
+
f"Available items: {available_items}\n\n"
|
|
80
|
+
f"Usage: opik export {workspace} ITEM NAME [OPTIONS]\n\n"
|
|
81
|
+
f"Examples:\n"
|
|
82
|
+
f' opik export {workspace} dataset "my-dataset"\n'
|
|
83
|
+
f' opik export {workspace} project "my-project"\n'
|
|
84
|
+
f' opik export {workspace} experiment "my-experiment"\n'
|
|
85
|
+
f' opik export {workspace} prompt "my-template"\n\n'
|
|
86
|
+
f"Run 'opik export {workspace} --help' for more information.",
|
|
87
|
+
err=True,
|
|
88
|
+
)
|
|
89
|
+
ctx.exit(2)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Set subcommand metavar to ITEM instead of COMMAND
|
|
93
|
+
export_group.subcommand_metavar = "ITEM [ARGS]..."
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def format_commands(
|
|
97
|
+
self: click.Group, ctx: click.Context, formatter: click.HelpFormatter
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Override to change 'Commands' heading to 'Items'."""
|
|
100
|
+
commands = []
|
|
101
|
+
for subcommand in self.list_commands(ctx):
|
|
102
|
+
cmd = self.get_command(ctx, subcommand)
|
|
103
|
+
if cmd is None or cmd.hidden:
|
|
104
|
+
continue
|
|
105
|
+
commands.append((subcommand, cmd))
|
|
106
|
+
|
|
107
|
+
if len(commands):
|
|
108
|
+
limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands)
|
|
109
|
+
rows = []
|
|
110
|
+
for subcommand, cmd in commands:
|
|
111
|
+
help = cmd.get_short_help_str(limit)
|
|
112
|
+
rows.append((subcommand, help))
|
|
113
|
+
|
|
114
|
+
if rows:
|
|
115
|
+
with formatter.section("Items"):
|
|
116
|
+
formatter.write_dl(rows)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# Override format_commands method
|
|
120
|
+
setattr(
|
|
121
|
+
export_group,
|
|
122
|
+
"format_commands",
|
|
123
|
+
format_commands.__get__(export_group, type(export_group)),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# Add the subcommands
|
|
128
|
+
export_group.add_command(export_dataset_command)
|
|
129
|
+
export_group.add_command(export_experiment_command)
|
|
130
|
+
export_group.add_command(export_prompt_command)
|
|
131
|
+
export_group.add_command(export_project_command)
|